]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #8455 from achernavin22/ospf_nssa_after_redist2
authorRuss White <russ@riw.us>
Tue, 20 Apr 2021 14:28:49 +0000 (10:28 -0400)
committerGitHub <noreply@github.com>
Tue, 20 Apr 2021 14:28:49 +0000 (10:28 -0400)
ospfd: install Type-7 when NSSA area is configured after redistribution

179 files changed:
.travis.yml [new file with mode: 0644]
alpine/APKBUILD.in
babeld/.gitignore
babeld/babeld.conf.sample [deleted file]
babeld/subdir.am
bfdd/bfdd.conf.sample [deleted file]
bfdd/bfdd_cli.c
bfdd/subdir.am
bgpd/bgp_evpn_mh.c
bgpd/bgp_fsm.c
bgpd/bgp_fsm.h
bgpd/bgp_io.c
bgpd/bgp_network.c
bgpd/bgp_nht.c
bgpd/bgp_nht.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_updgrp_adv.c
bgpd/bgp_vpn.c
bgpd/bgp_vty.c
bgpd/bgpd.conf.sample [deleted file]
bgpd/bgpd.conf.vnc.sample [deleted file]
bgpd/subdir.am
debian/frr.dirs
debian/frr.install
debian/rules
doc/developer/building-docker.rst
doc/developer/building-frr-for-alpine.rst
doc/manpages/vtysh.rst
doc/user/babeld.rst
doc/user/basic.rst
doc/user/bgp.rst
doc/user/eigrpd.rst
doc/user/fabricd.rst
doc/user/filter.rst
doc/user/ldpd.rst
doc/user/nhrpd.rst
doc/user/ospf6d.rst
doc/user/ospfd.rst
doc/user/pathd.rst
doc/user/pbr.rst
doc/user/pim.rst
doc/user/ripd.rst
doc/user/ripngd.rst
doc/user/routemap.rst
docker/alpine/Dockerfile
docker/ubuntu18-ci/Dockerfile [new file with mode: 0644]
docker/ubuntu18-ci/README.md [new file with mode: 0644]
docker/ubuntu18-ci/docker-start [new file with mode: 0755]
docker/ubuntu20-ci/Dockerfile [new file with mode: 0644]
docker/ubuntu20-ci/README.md [new file with mode: 0644]
docker/ubuntu20-ci/docker-start [new file with mode: 0755]
eigrpd/eigrpd.conf.sample [deleted file]
eigrpd/subdir.am
isisd/fabricd.conf.sample [deleted file]
isisd/isisd.conf.sample [deleted file]
isisd/subdir.am
ldpd/ldpd.conf.sample [deleted file]
ldpd/subdir.am
lib/bfd.c
lib/command.c
lib/filter.c
lib/filter.h
lib/filter_cli.c
lib/filter_nb.c
lib/if.c
lib/lib_errors.c
lib/lib_errors.h
lib/log.c
lib/log_vty.c
lib/plist.c
lib/routemap.c
lib/routemap.h
lib/routemap_cli.c
lib/routemap_northbound.c
lib/sigevent.c
lib/subdir.am
lib/thread.c
lib/thread.h
lib/vty.c
lib/xref.h
lib/zclient.c
lib/zclient.h
lib/zlog.c
nhrpd/linux.c
nhrpd/netlink.h
nhrpd/netlink_arp.c
nhrpd/nhrp_interface.c
nhrpd/nhrp_multicast.c [new file with mode: 0644]
nhrpd/nhrp_peer.c
nhrpd/nhrp_route.c
nhrpd/nhrp_vty.c
nhrpd/nhrpd.h
nhrpd/os.h
nhrpd/subdir.am
nhrpd/vici.c
nhrpd/zbuf.c
ospf6d/ospf6_top.c
ospf6d/ospf6d.conf.sample [deleted file]
ospf6d/subdir.am
ospfd/ospf_dump.c
ospfd/ospf_interface.c
ospfd/ospf_interface.h
ospfd/ospf_lsa.c
ospfd/ospf_packet.c
ospfd/ospf_spf.c
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.conf.sample [deleted file]
ospfd/subdir.am
pathd/pathd.conf.sample [deleted file]
pathd/subdir.am
pbrd/pbrd.conf.sample [deleted file]
pbrd/subdir.am
pimd/pimd.conf.sample [deleted file]
pimd/subdir.am
python/vtysh-cmd-check.py [new file with mode: 0644]
redhat/frr.spec.in
ripd/ripd.conf.sample [deleted file]
ripd/subdir.am
ripngd/ripngd.conf.sample [deleted file]
ripngd/subdir.am
sharpd/sharpd.conf.sample [deleted file]
sharpd/subdir.am
staticd/staticd.conf.sample [deleted file]
staticd/subdir.am
tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post4.1.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post5.0.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post6.1.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv6-post4.1.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_post6.1.ref
tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post4.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post6.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post4.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post6.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post4.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post6.1.ref
tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
tests/topotests/lib/bgp.py
tests/topotests/nhrp-topo/r1/nhrp4_cache.json [new file with mode: 0644]
tests/topotests/nhrp-topo/r1/nhrp_route4.json [new file with mode: 0644]
tests/topotests/nhrp-topo/r1/nhrpd.conf [new file with mode: 0644]
tests/topotests/nhrp-topo/r1/zebra.conf [new file with mode: 0644]
tests/topotests/nhrp-topo/r2/nhrp4_cache.json [new file with mode: 0644]
tests/topotests/nhrp-topo/r2/nhrp_route4.json [new file with mode: 0644]
tests/topotests/nhrp-topo/r2/nhrpd.conf [new file with mode: 0644]
tests/topotests/nhrp-topo/r2/zebra.conf [new file with mode: 0644]
tests/topotests/nhrp-topo/r3/zebra.conf [new file with mode: 0644]
tests/topotests/nhrp-topo/test_nhrp_topo.dot [new file with mode: 0644]
tests/topotests/nhrp-topo/test_nhrp_topo.py [new file with mode: 0644]
tools/etc/frr/frr.conf
vrrpd/subdir.am
vtysh/extract.pl.in
vtysh/subdir.am
vtysh/vtysh.c
vtysh/vtysh.conf.sample [deleted file]
vtysh/vtysh_config.c
vtysh/vtysh_main.c
yang/frr-route-map.yang
zebra/if_netlink.c
zebra/interface.c
zebra/kernel_netlink.c
zebra/rt.h
zebra/rt_netlink.c
zebra/rt_socket.c
zebra/subdir.am
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zebra.conf.sample [deleted file]
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_nhg.c
zebra/zebra_rib.c
zebra/zserv.c
zebra/zserv.h

diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..d8e450a
--- /dev/null
@@ -0,0 +1,40 @@
+dist: focal
+os: linux
+language: c
+services:
+  - docker
+jobs:
+  include:
+   - script:
+       - docker/centos-7/build.sh
+       - docker images
+     name: centos7
+   - script:
+       - docker/centos-8/build.sh
+       - docker images
+     name: centos8
+   - script:
+       - sudo apt install -y linux-modules-extra-$(uname -r)
+       - docker build -t frr-ubuntu18:latest -f docker/ubuntu18-ci/Dockerfile .
+       - docker images
+       - uname -a
+       - docker run -d --privileged --name frr-ubuntu18 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu18:latest
+       - docker ps
+       - docker exec frr-ubuntu18 bash -c 'cd ~/frr ; make check'
+       - docker exec frr-ubuntu18 bash -c 'ps agxu ; lsmod | grep mpls || true'
+       - docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+       - docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/bgp_l3vpn_to_bgp_vrf ; sudo pytest test_bgp_l3vpn_to_bgp_vrf.py'
+     name: ubuntu18+minimalCI
+   - script:
+       - sudo apt install -y linux-modules-extra-$(uname -r)
+       - docker build -t frr-ubuntu20:latest -f docker/ubuntu20-ci/Dockerfile .
+       - docker images
+       - uname -a
+       - docker run -d --privileged --name frr-ubuntu20 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu20:latest
+       - docker ps
+       - docker exec frr-ubuntu20 bash -c 'cd ~/frr ; make check'
+       - docker exec frr-ubuntu20 bash -c 'ps agxu ; lsmod | grep mpls || true'
+       - docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+       - docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/bgp_l3vpn_to_bgp_vrf ; sudo pytest test_bgp_l3vpn_to_bgp_vrf.py'
+     name: ubuntu20+minimalCI
+
index d6c6c5f0afb3ec018ee019d73183428625cfa942..dfedf0b52b27763c60d09832f52be6e91df32a3d 100644 (file)
@@ -18,7 +18,7 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
     ncurses-libs ncurses-terminfo ncurses-terminfo-base patch pax-utils pcre
     perl pkgconf python3 python3-dev readline readline-dev sqlite-libs
     squashfs-tools sudo tar texinfo xorriso xz-libs py-pip rtrlib rtrlib-dev
-    py3-sphinx"
+    py3-sphinx elfutils elfutils-dev"
 checkdepends="pytest py-setuptools"
 install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall"
 subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
index fbdb90f67785c7f994afeb2a7b0c726d49eaaab8..71ef6786c79203192c3052ac5ca911507ad41995 100644 (file)
@@ -4,5 +4,4 @@
 !LICENCE
 !Makefile
 !subdir.am
-!babeld.conf.sample
 !.gitignore
diff --git a/babeld/babeld.conf.sample b/babeld/babeld.conf.sample
deleted file mode 100644 (file)
index a77453a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-debug babel common
-!debug babel kernel
-!debug babel filter
-!debug babel timeout
-!debug babel interface
-!debug babel route
-!debug babel all
-
-router babel
-! network wlan0
-! network eth0
-! redistribute ipv4 kernel
-! no redistribute ipv6 static
-
-! The defaults are fine for a wireless interface
-
-!interface wlan0
-
-! A few optimisation tweaks are optional but recommended on a wired interface
-! Disable link quality estimation, enable split horizon processing, and
-! increase the hello and update intervals.
-
-!interface eth0
-! babel wired
-! babel split-horizon
-! babel hello-interval 12000
-! babel update-interval 36000
-
-! log file /var/log/quagga/babeld.log
-log stdout
index 8e5b46350d2d2979a0cca4c2b9faf817e0661c98..c9b6959fcaf0fe00c9941914da01ac47db07ddbe 100644 (file)
@@ -5,7 +5,6 @@
 if BABELD
 noinst_LIBRARIES += babeld/libbabel.a
 sbin_PROGRAMS += babeld/babeld
-dist_examples_DATA += babeld/babeld.conf.sample
 vtysh_scan += \
        babeld/babel_interface.c \
        babeld/babel_zebra.c \
diff --git a/bfdd/bfdd.conf.sample b/bfdd/bfdd.conf.sample
deleted file mode 100644 (file)
index 9981e26..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-password zebra
-!
-log stdout
-!
-line vty
index 42ed587f20efc5a14ee9746e372f43bfd2ef0e62..6ec724d80cdd981caeb47c1f0117d9bc1df50162 100644 (file)
@@ -273,11 +273,8 @@ DEFPY_YANG(
 void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
                           bool show_defaults)
 {
-       if (show_defaults)
-               vty_out(vty, "  no shutdown\n");
-       else
-               vty_out(vty, "  %sshutdown\n",
-                       yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
+       vty_out(vty, "  %sshutdown\n",
+               yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
 }
 
 DEFPY_YANG(
@@ -294,11 +291,8 @@ DEFPY_YANG(
 void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode,
                          bool show_defaults)
 {
-       if (show_defaults)
-               vty_out(vty, "  no passive-mode\n");
-       else
-               vty_out(vty, "  %spassive-mode\n",
-                       yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
+       vty_out(vty, "  %spassive-mode\n",
+               yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
 }
 
 DEFPY_YANG(
@@ -335,11 +329,7 @@ DEFPY_YANG(
 void bfd_cli_show_minimum_ttl(struct vty *vty, struct lyd_node *dnode,
                              bool show_defaults)
 {
-       if (show_defaults)
-               vty_out(vty, "  minimum-ttl 254\n");
-       else
-               vty_out(vty, "  minimum-ttl %s\n",
-                       yang_dnode_get_string(dnode, NULL));
+       vty_out(vty, "  minimum-ttl %s\n", yang_dnode_get_string(dnode, NULL));
 }
 
 DEFPY_YANG(
@@ -356,12 +346,8 @@ DEFPY_YANG(
 void bfd_cli_show_mult(struct vty *vty, struct lyd_node *dnode,
                       bool show_defaults)
 {
-       if (show_defaults)
-               vty_out(vty, "  detect-multiplier %d\n",
-                       BFD_DEFDETECTMULT);
-       else
-               vty_out(vty, "  detect-multiplier %s\n",
-                       yang_dnode_get_string(dnode, NULL));
+       vty_out(vty, "  detect-multiplier %s\n",
+               yang_dnode_get_string(dnode, NULL));
 }
 
 DEFPY_YANG(
@@ -382,15 +368,9 @@ DEFPY_YANG(
 void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode,
                     bool show_defaults)
 {
-       uint32_t value;
+       uint32_t value = yang_dnode_get_uint32(dnode, NULL);
 
-       if (show_defaults)
-               vty_out(vty, "  receive-interval %d\n",
-                       BFD_DEFREQUIREDMINRX);
-       else {
-               value = yang_dnode_get_uint32(dnode, NULL);
-               vty_out(vty, "  receive-interval %u\n", value / 1000);
-       }
+       vty_out(vty, "  receive-interval %u\n", value / 1000);
 }
 
 DEFPY_YANG(
@@ -411,15 +391,9 @@ DEFPY_YANG(
 void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode,
                     bool show_defaults)
 {
-       uint32_t value;
+       uint32_t value = yang_dnode_get_uint32(dnode, NULL);
 
-       if (show_defaults)
-               vty_out(vty, "  transmit-interval %d\n",
-                       BFD_DEFDESIREDMINTX);
-       else {
-               value = yang_dnode_get_uint32(dnode, NULL);
-               vty_out(vty, "  transmit-interval %u\n", value / 1000);
-       }
+       vty_out(vty, "  transmit-interval %u\n", value / 1000);
 }
 
 DEFPY_YANG(
@@ -445,11 +419,8 @@ DEFPY_YANG(
 void bfd_cli_show_echo(struct vty *vty, struct lyd_node *dnode,
                           bool show_defaults)
 {
-       if (show_defaults)
-               vty_out(vty, "  no echo-mode\n");
-       else
-               vty_out(vty, "  %secho-mode\n",
-                       yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
+       vty_out(vty, "  %secho-mode\n",
+               yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
 }
 
 DEFPY_YANG(
@@ -498,15 +469,9 @@ DEFPY_YANG(
 void bfd_cli_show_desired_echo_transmission_interval(struct vty *vty,
        struct lyd_node *dnode, bool show_defaults)
 {
-       uint32_t value;
+       uint32_t value = yang_dnode_get_uint32(dnode, NULL);
 
-       if (show_defaults)
-               vty_out(vty, "  echo transmit-interval %d\n",
-                       BFD_DEF_DES_MIN_ECHO_TX);
-       else {
-               value = yang_dnode_get_uint32(dnode, NULL);
-               vty_out(vty, "  echo transmit-interval %u\n", value / 1000);
-       }
+       vty_out(vty, "  echo transmit-interval %u\n", value / 1000);
 }
 
 DEFPY_YANG(
@@ -538,19 +503,12 @@ DEFPY_YANG(
 void bfd_cli_show_required_echo_receive_interval(struct vty *vty,
        struct lyd_node *dnode, bool show_defaults)
 {
-       uint32_t value;
-
-       if (show_defaults)
-               vty_out(vty, "  echo receive-interval %d\n",
-                       BFD_DEF_REQ_MIN_ECHO_RX);
-       else {
-               value = yang_dnode_get_uint32(dnode, NULL);
-               if (value)
-                       vty_out(vty, "  echo receive-interval %u\n",
-                               value / 1000);
-               else
-                       vty_out(vty, "  echo receive-interval disabled\n");
-       }
+       uint32_t value = yang_dnode_get_uint32(dnode, NULL);
+
+       if (value)
+               vty_out(vty, "  echo receive-interval %u\n", value / 1000);
+       else
+               vty_out(vty, "  echo receive-interval disabled\n");
 }
 
 /*
index e572d4a3c0b2b862f922a8e97e431e3694427d68..8d35b933d789bf399d823de460c752b7dd5d57f3 100644 (file)
@@ -5,7 +5,6 @@
 if BFDD
 noinst_LIBRARIES += bfdd/libbfd.a
 sbin_PROGRAMS += bfdd/bfdd
-dist_examples_DATA += bfdd/bfdd.conf.sample
 vtysh_scan += bfdd/bfdd_vty.c
 vtysh_scan += bfdd/bfdd_cli.c
 vtysh_daemons += bfdd
index 868238ebddd46e26e51cd4560b108f0bcf53ad30..6467ff8a283c97c1af0f9ac2bd1c152308a2adef 100644 (file)
@@ -2493,6 +2493,10 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf,
                if (!CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
                        continue;
 
+               /* Don't overrun the zapi buffer. */
+               if (api_nhg.nexthop_num == MULTIPATH_NUM)
+                       break;
+
                /* overwrite the gw */
                if (v4_nhg)
                        nh.gate.ipv4 = es_vtep->vtep_ip;
@@ -2514,9 +2518,6 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf,
        if (!api_nhg.nexthop_num)
                return;
 
-       if (api_nhg.nexthop_num > MULTIPATH_NUM)
-               return;
-
        zclient_nhg_send(zclient, ZEBRA_NHG_ADD, &api_nhg);
 }
 
index 45a856a4591fc5f0f7a834fe88acd7eaf7a73c2b..88c44fc984d898222aa006f3fe62f847fc653b85 100644 (file)
@@ -101,7 +101,7 @@ static int bgp_delayopen_timer(struct thread *);
 static int bgp_start(struct peer *);
 
 /* Register peer with NHT */
-static int bgp_peer_reg_with_nht(struct peer *peer)
+int bgp_peer_reg_with_nht(struct peer *peer)
 {
        int connected = 0;
 
@@ -340,6 +340,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
         * needed, even on a passive connection.
         */
        bgp_peer_reg_with_nht(peer);
+       if (from_peer)
+               bgp_replace_nexthop_by_peer(from_peer, peer);
 
        bgp_reads_on(peer);
        bgp_writes_on(peer);
index bcf697e153fb4275d3d777d4c4c54c6b820fc555..12cbad3eb83b0e164a70888fa92268ff5b0fb606 100644 (file)
@@ -179,4 +179,5 @@ const char *print_peer_gr_mode(enum peer_mode pr_mode);
 const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd);
 const char *print_global_gr_mode(enum global_mode gl_mode);
 const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd);
+int bgp_peer_reg_with_nht(struct peer *peer);
 #endif /* _QUAGGA_BGP_FSM_H */
index a696d956977aba5b4fc05bd52c5af5d9e88d668f..c2d8cae580d241b252e1524b1e01798a58370369 100644 (file)
@@ -180,8 +180,8 @@ static int bgp_process_reads(struct thread *thread)
        bool more = true;               // whether we got more data
        bool fatal = false;             // whether fatal error occurred
        bool added_pkt = false;         // whether we pushed onto ->ibuf
+       int code = 0;                   // FSM code if error occurred
        /* clang-format on */
-       int code;
 
        peer = THREAD_ARG(thread);
 
@@ -455,6 +455,9 @@ done : {
 /*
  * Reads a chunk of data from peer->fd into peer->ibuf_work.
  *
+ * code_p
+ *    Pointer to location to store FSM event code in case of fatal error.
+ *
  * @return status flag (see top-of-file)
  */
 static uint16_t bgp_read(struct peer *peer, int *code_p)
index 4821ce8ddbf4000fe04bebba50a86c152e683a5a..8d9024e07c512e7d1a0c3efe8615260806e7cc5f 100644 (file)
@@ -569,6 +569,7 @@ static int bgp_accept(struct thread *thread)
        peer1->doppelganger = peer;
        peer->fd = bgp_sock;
        vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
+       bgp_peer_reg_with_nht(peer);
        bgp_fsm_change_status(peer, Active);
        BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
 
index 9c8d7878c513ac2bca0105b44f0672873d13a7c4..7ccfae4ba4c288e513f137ee5ff8c3b2b0e43036 100644 (file)
@@ -98,6 +98,31 @@ void bgp_unlink_nexthop(struct bgp_path_info *path)
        bgp_unlink_nexthop_check(bnc);
 }
 
+void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to)
+{
+       struct prefix pp;
+       struct prefix pt;
+       struct bgp_nexthop_cache *bncp, *bnct;
+       afi_t afi;
+
+       if (!sockunion2hostprefix(&from->su, &pp))
+               return;
+
+       afi = family2afi(pp.family);
+       bncp = bnc_find(&from->bgp->nexthop_cache_table[afi], &pp, 0);
+
+       if (!sockunion2hostprefix(&to->su, &pt))
+               return;
+
+       bnct = bnc_find(&to->bgp->nexthop_cache_table[afi], &pt, 0);
+
+       if (bnct != bncp)
+               return;
+
+       if (bnct)
+               bnct->nht_info = to;
+}
+
 void bgp_unlink_nexthop_by_peer(struct peer *peer)
 {
        struct prefix p;
@@ -273,8 +298,16 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                        (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
                else if (pi->extra)
                        pi->extra->igpmetric = 0;
-       } else if (peer)
-               bnc->nht_info = (void *)peer; /* NHT peer reference */
+       } else if (peer) {
+               /*
+                * Let's not accidently save the peer data for a peer
+                * we are going to throw away in a second or so.
+                * When we come back around we'll fix up this
+                * data properly in replace_nexthop_by_peer
+                */
+               if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+                       bnc->nht_info = (void *)peer; /* NHT peer reference */
+       }
 
        /*
         * We are cheating here.  Views have no associated underlying
index a1683e15114edb8a7da51da2157d5549e26c2e3a..9268b225ca02888cb3eb95c9aa0bbd21883685b0 100644 (file)
@@ -51,7 +51,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp_route,
  */
 extern void bgp_unlink_nexthop(struct bgp_path_info *p);
 void bgp_unlink_nexthop_by_peer(struct peer *peer);
-
+void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to);
 /**
  * bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
  * nexthop entry. If no paths reference the nexthop, it will be unregistered
index 35a93162216884a061bd58564892b4eb480d5cd2..49b94e6d7c85954ab066dbd4481ed86d7cd909d5 100644 (file)
@@ -8223,8 +8223,8 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
 }
 
 /* Static function to display route. */
-static void route_vty_out_route(const struct prefix *p, struct vty *vty,
-                               json_object *json, bool wide)
+static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
+                               struct vty *vty, json_object *json, bool wide)
 {
        int len = 0;
        char buf[BUFSIZ];
@@ -8241,6 +8241,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty,
                        json_object_int_add(json, "prefixLen", p->prefixlen);
                        prefix2str(p, buf2, PREFIX_STRLEN);
                        json_object_string_add(json, "network", buf2);
+                       json_object_int_add(json, "version", dest->version);
                }
        } else if (p->family == AF_ETHERNET) {
                len = vty_out(vty, "%pFX", p);
@@ -8265,6 +8266,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty,
                        json_object_int_add(json, "prefixLen", p->prefixlen);
                        prefix2str(p, buf2, PREFIX_STRLEN);
                        json_object_string_add(json, "network", buf2);
+                       json_object_int_add(json, "version", dest->version);
                }
        }
 
@@ -8340,8 +8342,11 @@ bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
 /* Print the short form route status for a bgp_path_info */
 static void route_vty_short_status_out(struct vty *vty,
                                       struct bgp_path_info *path,
+                                      const struct prefix *p,
                                       json_object *json_path)
 {
+       enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
+
        if (json_path) {
 
                /* Route status display. */
@@ -8387,6 +8392,17 @@ static void route_vty_short_status_out(struct vty *vty,
                return;
        }
 
+       /* RPKI validation state */
+       rpki_state =
+               hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
+
+       if (rpki_state == RPKI_VALID)
+               vty_out(vty, "V");
+       else if (rpki_state == RPKI_INVALID)
+               vty_out(vty, "I");
+       else if (rpki_state == RPKI_NOTFOUND)
+               vty_out(vty, "N");
+
        /* Route status display. */
        if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
                vty_out(vty, "R");
@@ -8455,16 +8471,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
                json_path = json_object_new_object();
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json_path);
+       route_vty_short_status_out(vty, path, p, json_path);
 
        if (!json_paths) {
                /* print prefix and mask */
                if (!display)
-                       route_vty_out_route(p, vty, json_path, wide);
+                       route_vty_out_route(path->net, p, vty, json_path, wide);
                else
                        vty_out(vty, "%*s", (wide ? 45 : 17), " ");
        } else {
-               route_vty_out_route(p, vty, json_path, wide);
+               route_vty_out_route(path->net, p, vty, json_path, wide);
        }
 
        /*
@@ -8924,9 +8940,9 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
 }
 
 /* called from terminal list command */
-void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
-                      struct attr *attr, safi_t safi, bool use_json,
-                      json_object *json_ar, bool wide)
+void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
+                      const struct prefix *p, struct attr *attr, safi_t safi,
+                      bool use_json, json_object *json_ar, bool wide)
 {
        json_object *json_status = NULL;
        json_object *json_net = NULL;
@@ -8958,7 +8974,7 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
                        json_object_string_add(json_net, "network", buff);
                }
        } else
-               route_vty_out_route(p, vty, NULL, wide);
+               route_vty_out_route(dest, p, vty, NULL, wide);
 
        /* Print attribute */
        if (attr) {
@@ -9101,12 +9117,12 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
                json_out = json_object_new_object();
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json_out);
+       route_vty_short_status_out(vty, path, p, json_out);
 
        /* print prefix and mask */
        if (json == NULL) {
                if (!display)
-                       route_vty_out_route(p, vty, NULL, false);
+                       route_vty_out_route(path->net, p, vty, NULL, false);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -9204,11 +9220,11 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
        }
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json_path);
+       route_vty_short_status_out(vty, path, p, json_path);
 
        /* print prefix and mask */
        if (!display)
-               route_vty_out_route(p, vty, json_path, false);
+               route_vty_out_route(path->net, p, vty, json_path, false);
        else
                vty_out(vty, "%*s", 17, " ");
 
@@ -9308,12 +9324,12 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
        char timebuf[BGP_UPTIME_LEN];
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json);
+       route_vty_short_status_out(vty, path, p, json);
 
        /* print prefix and mask */
        if (!use_json) {
                if (!display)
-                       route_vty_out_route(p, vty, NULL, false);
+                       route_vty_out_route(path->net, p, vty, NULL, false);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -9379,12 +9395,12 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
        bdi = path->extra->damp_info;
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json);
+       route_vty_short_status_out(vty, path, p, json);
 
        /* print prefix and mask */
        if (!use_json) {
                if (!display)
-                       route_vty_out_route(p, vty, NULL, false);
+                       route_vty_out_route(path->net, p, vty, NULL, false);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -10121,6 +10137,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
                        vty_out(vty, ", valid");
        }
 
+       if (json_paths)
+               json_object_int_add(json_path, "version", bn->version);
+
        if (path->peer != bgp->peer_self) {
                if (path->peer->as == path->peer->local_as) {
                        if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
@@ -10241,7 +10260,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
                vty_out(vty, "\n");
 
        /* Line 4 display Community */
-       if (attr->community) {
+       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
                if (json_paths) {
                        if (!attr->community->json)
                                community_str(attr->community, true);
@@ -10616,6 +10635,13 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                for (; pi; pi = pi->next) {
                        total_count++;
 
+                       if (type == bgp_show_type_prefix_version) {
+                               uint32_t version =
+                                       strtoul(output_arg, NULL, 10);
+                               if (dest->version < version)
+                                       continue;
+                       }
+
                        if (type == bgp_show_type_rpki) {
                                if (dest_p->family == AF_INET
                                    || dest_p->family == AF_INET6)
@@ -10791,6 +10817,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                                vty_out(vty, BGP_SHOW_SCODE_HEADER);
                                vty_out(vty, BGP_SHOW_NCODE_HEADER);
                                vty_out(vty, BGP_SHOW_OCODE_HEADER);
+                               vty_out(vty, BGP_SHOW_RPKI_HEADER);
                                if (type == bgp_show_type_dampend_paths
                                    || type == bgp_show_type_damp_neighbor)
                                        vty_out(vty, BGP_SHOW_DAMP_HEADER);
@@ -10818,9 +10845,17 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                                flap_route_vty_out(vty, dest_p, pi, display,
                                                   AFI_IP, safi, use_json,
                                                   json_paths);
-                       else
-                               route_vty_out(vty, dest_p, pi, display, safi,
-                                             json_paths, wide);
+                       else {
+                               if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
+                                       route_vty_out_detail(
+                                               vty, bgp, dest, pi,
+                                               family2afi(dest_p->family),
+                                               safi, RPKI_NOT_BEING_USED,
+                                               json_paths);
+                               else
+                                       route_vty_out(vty, dest_p, pi, display,
+                                                     safi, json_paths, wide);
+                       }
                        display++;
                }
 
@@ -11086,16 +11121,22 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                }
        } else {
                if (!json) {
-                       vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
+                       vty_out(vty,
+                               "BGP routing table entry for %s%s%pFX, version %" PRIu64
+                               "\n",
                                ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
                                         ? prefix_rd2str(prd, buf1,
                                                         sizeof(buf1))
                                         : ""),
-                               safi == SAFI_MPLS_VPN ? ":" : "", p);
+                               safi == SAFI_MPLS_VPN ? ":" : "", p,
+                               dest->version);
 
-               } else
+               } else {
                        json_object_string_add(json, "prefix",
                                prefix2str(p, prefix_str, sizeof(prefix_str)));
+                       json_object_int_add(json, "version", dest->version);
+
+               }
        }
 
        if (has_valid_label) {
@@ -11579,13 +11620,13 @@ DEFUN (show_ip_bgp_large_community_list,
        struct bgp *bgp = NULL;
        bool uj = use_json(argc, argv);
 
-        if (uj)
-                argc--;
+       if (uj)
+               argc--;
 
-        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                            &bgp, uj);
-        if (!idx)
-                return CMD_WARNING;
+       bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+                                           &bgp, uj);
+       if (!idx)
+               return CMD_WARNING;
 
        argv_find(argv, argc, "large-community-list", &idx);
 
@@ -11886,7 +11927,8 @@ DEFPY (show_ip_bgp_json,
                      |route-filter-v4|route-filter-translated-v6\
                      |route-filter-translated-v4] [exact-match]\
           |rpki <invalid|valid|notfound>\
-          ] [json$uj | wide$wide]",
+          |version (1-4294967295)\
+          ] [json$uj [detail$detail] | wide$wide]",
        SHOW_STR
        IP_STR
        BGP_STR
@@ -11919,7 +11961,10 @@ DEFPY (show_ip_bgp_json,
        "A valid path as determined by rpki\n"
        "A invalid path as determined by rpki\n"
        "A path that has no rpki data\n"
+       "Display prefixes with matching version numbers\n"
+       "Version number and above\n"
        JSON_STR
+       "Display detailed version of JSON output\n"
        "Increase table width for longer prefixes\n")
 {
        afi_t afi = AFI_IP6;
@@ -11929,6 +11974,7 @@ DEFPY (show_ip_bgp_json,
        int idx = 0;
        int exact_match = 0;
        char *community = NULL;
+       char *prefix_version = NULL;
        bool first = true;
        uint8_t show_flags = 0;
        enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
@@ -11938,6 +11984,9 @@ DEFPY (show_ip_bgp_json,
                SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
        }
 
+       if (detail)
+               SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
+
        /* [<ipv4|ipv6> [all]] */
        if (all) {
                SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
@@ -11996,12 +12045,22 @@ DEFPY (show_ip_bgp_json,
                        rpki_target_state = RPKI_INVALID;
        }
 
+       /* Display prefixes with matching version numbers */
+       if (argv_find(argv, argc, "version", &idx)) {
+               sh_type = bgp_show_type_prefix_version;
+               prefix_version = argv[idx + 1]->arg;
+       }
+
        if (!all) {
                /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
                if (community)
                        return bgp_show_community(vty, bgp, community,
                                                  exact_match, afi, safi,
                                                  show_flags);
+               else if (prefix_version)
+                       return bgp_show(vty, bgp, afi, safi, sh_type,
+                                       prefix_version, show_flags,
+                                       rpki_target_state);
                else
                        return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
                                        show_flags, rpki_target_state);
@@ -12039,6 +12098,11 @@ DEFPY (show_ip_bgp_json,
                                        bgp_show_community(vty, bgp, community,
                                                           exact_match, afi,
                                                           safi, show_flags);
+                               else if (prefix_version)
+                                       return bgp_show(vty, bgp, afi, safi,
+                                                       sh_type, prefix_version,
+                                                       show_flags,
+                                                       rpki_target_state);
                                else
                                        bgp_show(vty, bgp, afi, safi, sh_type,
                                                 NULL, show_flags,
@@ -12071,6 +12135,11 @@ DEFPY (show_ip_bgp_json,
                                        bgp_show_community(vty, bgp, community,
                                                           exact_match, afi,
                                                           safi, show_flags);
+                               else if (prefix_version)
+                                       return bgp_show(vty, bgp, afi, safi,
+                                                       sh_type, prefix_version,
+                                                       show_flags,
+                                                       rpki_target_state);
                                else
                                        bgp_show(vty, bgp, afi, safi, sh_type,
                                                 NULL, show_flags,
@@ -13137,6 +13206,7 @@ static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
                        vty_out(vty, BGP_SHOW_SCODE_HEADER);
                        vty_out(vty, BGP_SHOW_NCODE_HEADER);
                        vty_out(vty, BGP_SHOW_OCODE_HEADER);
+                       vty_out(vty, BGP_SHOW_RPKI_HEADER);
                }
                *header1 = 0;
        }
@@ -13223,6 +13293,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                        vty_out(vty, BGP_SHOW_SCODE_HEADER);
                        vty_out(vty, BGP_SHOW_NCODE_HEADER);
                        vty_out(vty, BGP_SHOW_OCODE_HEADER);
+                       vty_out(vty, BGP_SHOW_RPKI_HEADER);
 
                        vty_out(vty, "Originating default network %s\n\n",
                                (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
@@ -13283,7 +13354,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                                    && (route_filtered || ret == RMAP_DENY))
                                        (*filtered_count)++;
 
-                               route_vty_out_tmp(vty, rn_p, &attr, safi,
+                               route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
                                                  use_json, json_ar, wide);
                                bgp_attr_undup(&attr, ain->attr);
                                (*output_count)++;
@@ -13325,8 +13396,8 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                                                        }
                                                }
                                                route_vty_out_tmp(
-                                                       vty, rn_p, &attr, safi,
-                                                       use_json, json_ar,
+                                                       vty, dest, rn_p, &attr,
+                                                       safi, use_json, json_ar,
                                                        wide);
                                                (*output_count)++;
                                        } else {
@@ -13350,7 +13421,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                                if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
                                        continue;
 
-                               route_vty_out_tmp(vty,
+                               route_vty_out_tmp(vty, dest,
                                                  bgp_dest_get_prefix(dest),
                                                  pi->attr, safi, use_json,
                                                  json_ar, wide);
index 0a4fd026e4a9a700ad6944859647bc70cd1c1fc0..e58213a6881b812121db1243ba6ae10d9187781d 100644 (file)
@@ -58,6 +58,7 @@ enum bgp_show_type {
        bgp_show_type_damp_neighbor,
        bgp_show_type_detail,
        bgp_show_type_rpki,
+       bgp_show_type_prefix_version,
 };
 
 enum bgp_show_adj_route_type {
@@ -72,8 +73,11 @@ enum bgp_show_adj_route_type {
        "Status codes:  s suppressed, d damped, "                              \
        "h history, * valid, > best, = multipath,\n"                           \
        "               i internal, r RIB-failure, S Stale, R Removed\n"
-#define BGP_SHOW_OCODE_HEADER "Origin codes:  i - IGP, e - EGP, ? - incomplete\n\n"
+#define BGP_SHOW_OCODE_HEADER                                                  \
+       "Origin codes:  i - IGP, e - EGP, ? - incomplete\n"
 #define BGP_SHOW_NCODE_HEADER "Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self\n"
+#define BGP_SHOW_RPKI_HEADER                                                   \
+       "RPKI validation codes: V valid, I invalid, N Not found\n\n"
 #define BGP_SHOW_HEADER "   Network          Next Hop            Metric LocPrf Weight Path\n"
 #define BGP_SHOW_HEADER_WIDE "   Network                                      Next Hop                                  Metric LocPrf Weight Path\n"
 
@@ -585,6 +589,7 @@ DECLARE_HOOK(bgp_process,
 #define BGP_SHOW_OPT_AFI_IP6 (1 << 4)
 #define BGP_SHOW_OPT_ESTABLISHED (1 << 5)
 #define BGP_SHOW_OPT_FAILED (1 << 6)
+#define BGP_SHOW_OPT_DETAIL (1 << 7)
 
 /* Prototypes. */
 extern void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
@@ -714,9 +719,10 @@ extern void route_vty_out(struct vty *vty, const struct prefix *p,
 extern void route_vty_out_tag(struct vty *vty, const struct prefix *p,
                              struct bgp_path_info *path, int display,
                              safi_t safi, json_object *json);
-extern void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
-                             struct attr *attr, safi_t safi, bool use_json,
-                             json_object *json_ar, bool wide);
+extern void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
+                             const struct prefix *p, struct attr *attr,
+                             safi_t safi, bool use_json, json_object *json_ar,
+                             bool wide);
 extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
                                  struct bgp_path_info *path, int display,
                                  json_object *json);
index fb64f010f94e6d2ab524037dd89df976bcad9415..bb0c95e32feda647ffab3fcf2e05d47830f9e6a6 100644 (file)
@@ -267,7 +267,7 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
                                }
                                if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv
                                    && adj->adv->baa) {
-                                       route_vty_out_tmp(vty, dest_p,
+                                       route_vty_out_tmp(vty, dest, dest_p,
                                                          adj->adv->baa->attr,
                                                          SUBGRP_SAFI(subgrp),
                                                          0, NULL, false);
@@ -275,7 +275,7 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
                                }
                                if ((flags & UPDWALK_FLAGS_ADVERTISED)
                                    && adj->attr) {
-                                       route_vty_out_tmp(vty, dest_p,
+                                       route_vty_out_tmp(vty, dest, dest_p,
                                                          adj->attr,
                                                          SUBGRP_SAFI(subgrp),
                                                          0, NULL, false);
index cb459ae13cca3a0825eaf745e9cd0da89cd831c9..8d2cffbb471d7211276841baae678b6131e630a3 100644 (file)
@@ -229,8 +229,9 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
                                }
                                rd_header = 0;
                        }
-                       route_vty_out_tmp(vty, bgp_dest_get_prefix(rm), attr,
-                                         safi, use_json, json_routes, false);
+                       route_vty_out_tmp(vty, rm, bgp_dest_get_prefix(rm),
+                                         attr, safi, use_json, json_routes,
+                                         false);
                        output_count++;
                }
 
index 9ecf02aae035481f2e215f11e02739b747c38e82..1e465d2620f91f1dc20795db56c541843b6cd341 100644 (file)
@@ -1390,7 +1390,6 @@ DEFUN_YANG_NOSH(router_bgp,
                                              NB_OP_MODIFY, "true");
                }
 
-               nb_cli_pending_commit_check(vty);
                ret = nb_cli_apply_changes(vty, base_xpath);
                if (ret == CMD_SUCCESS) {
                        VTY_PUSH_XPATH(BGP_NODE, base_xpath);
@@ -1399,6 +1398,7 @@ DEFUN_YANG_NOSH(router_bgp,
                         * For backward compatibility with old commands we still
                         * need to use the qobj infrastructure.
                         */
+                       nb_cli_pending_commit_check(vty);
                        bgp = bgp_lookup(as, name);
                        if (bgp)
                                VTY_PUSH_CONTEXT(BGP_NODE, bgp);
diff --git a/bgpd/bgpd.conf.sample b/bgpd/bgpd.conf.sample
deleted file mode 100644 (file)
index 1fb4f16..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-! -*- bgp -*-
-!
-! BGPd sample configuration file
-!
-! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
-!
-hostname bgpd
-password zebra
-!enable password please-set-at-here
-!
-!
-router bgp 7675
-! bgp router-id 10.0.0.1
-! network 10.0.0.0/8
-! neighbor 10.0.0.2 remote-as 7675
-! neighbor 10.0.0.2 ebgp-multihop
-!
-! address-family ipv4 unicast
-!  neighbor 10.0.0.2 route-map set-nexthop out
-!  neighbor 10.0.0.2 next-hop-self
-! exit-address-family
-!
-! access-list all permit any
-!
-!route-map set-nexthop permit 10
-! match ip address all
-! set ip next-hop 10.0.0.1
-!
-!log file bgpd.log
-!
-log stdout
diff --git a/bgpd/bgpd.conf.vnc.sample b/bgpd/bgpd.conf.vnc.sample
deleted file mode 100644 (file)
index a8a2dc5..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-hostname H192.1.1.1
-password zebra
-#enable password zebra
-log stdout notifications
-log monitor notifications
-#debug bgp
-
-line vty
-exec-timeout 1000
-exit
-
-
-router bgp 64512
-
-    # Must set a router-id if no zebra (default 0.0.0.0)
-    bgp router-id 192.1.1.1
-
-    neighbor 192.1.1.2 remote-as 64512
-    neighbor 192.1.1.2 description H192.1.1.2
-    neighbor 192.1.1.2 update-source 192.1.1.1
-    neighbor 192.1.1.2 advertisement-interval 1
-
-    neighbor 192.1.1.3 remote-as 64512
-    neighbor 192.1.1.3 description H192.1.1.3
-    neighbor 192.1.1.3 update-source 192.1.1.1
-    neighbor 192.1.1.3 advertisement-interval 1
-
-    address-family ipv4 unicast
-        no neighbor 192.1.1.2 activate
-        no neighbor 192.1.1.3 activate
-
-    address-family vpnv4
-        neighbor 192.1.1.2 activate
-        neighbor 192.1.1.3 activate
-        exit-address-family
-
-    address-family vpnv6
-        neighbor 192.1.1.2 activate
-        neighbor 192.1.1.3 activate
-        exit-address-family
-
-    vnc defaults
-       rd auto:vn:5226
-       response-lifetime 45
-       rt both 1000:1 1000:2
-       exit-vnc
-
-    vnc nve-group group1
-       prefix vn 172.16.0.0/16
-       exit-vnc
-
-    vnc nve-group red
-       prefix vn 10.0.0.0/8
-       rd auto:vn:10
-       rt both 1000:10
-       exit-vnc
-
-    vnc nve-group blue
-       prefix vn 20.0.0.0/8
-       rd auto:vn:20
-       rt both 1000:20
-       exit-vnc
-
-    vnc nve-group green
-       prefix vn 30.0.0.0/8
-       rd auto:vn:20
-       rt both 1000:30
-       exit-vnc
-
-    vnc nve-group rfc4291v6c
-       prefix vn ::ac10:0/112
-       rd auto:vn:5227
-       rt both 2000:1
-       exit-vnc
-
-    vnc nve-group rfc4291v6m
-       prefix vn ::ffff:ac10:0/112
-       rd auto:vn:5528
-       rt both 3000:1
-       exit-vnc
-
-    vnc nve-group rfc6052v6
-       prefix vn 64:ff9b::ac10:0/112
-       rd auto:vn:5529
-       rt both 4000:1
-       exit-vnc
-
-exit
-
-
-
index 583d1cd20727c565d17a85f57db70a5edd2678ae..07e71ba601207c3af03e3ccc5949a5ab20935231 100644 (file)
@@ -6,11 +6,6 @@ if BGPD
 noinst_LIBRARIES += bgpd/libbgp.a
 sbin_PROGRAMS += bgpd/bgpd
 noinst_PROGRAMS += bgpd/bgp_btoa
-dist_examples_DATA += \
-       bgpd/bgpd.conf.sample \
-       bgpd/bgpd.conf.sample2 \
-       bgpd/bgpd.conf.vnc.sample \
-       # end
 vtysh_scan += \
        bgpd/bgp_bfd.c \
        bgpd/bgp_debug.c \
index 9e592e370c67183072c3bd7a8c9922b6816d42fa..e3832d10a17693e8e8cd244eec0d50d947fcbe85 100644 (file)
@@ -2,7 +2,6 @@ etc/frr/
 etc/iproute2/rt_protos.d/
 etc/logrotate.d/
 usr/share/doc/frr/
-usr/share/doc/frr/examples/
 usr/share/lintian/overrides/
 usr/share/yang/
 var/log/frr/
index 9972b579f0f4152f576a7c07e62a232c4ae160a6..48263222f82b958e19f1d7a6e181edca45fbfafb 100644 (file)
@@ -1,5 +1,6 @@
 debian/frr.conf usr/lib/tmpfiles.d
 etc/
+tools/etc/frr/frr.conf etc/frr/
 tools/frr-reload usr/lib/frr/
 usr/bin/mtracebis
 usr/bin/vtysh
@@ -16,6 +17,5 @@ usr/lib/frr/*.sh
 usr/lib/frr/*d
 usr/lib/frr/watchfrr
 usr/lib/frr/zebra
-usr/share/doc/frr/examples
 usr/share/man/
 usr/share/yang/
index 25ae04261d3d1d400066d5749831eb152d9f154e..93d0cdb2a09b3fbd9510006163a46e5b87122197 100755 (executable)
@@ -43,7 +43,6 @@ export PYTHON=python3
 override_dh_auto_configure:
        $(shell dpkg-buildflags --export=sh); \
        dh_auto_configure -- \
-               --enable-exampledir=/usr/share/doc/frr/examples/ \
                --localstatedir=/var/run/frr \
                --sbindir=/usr/lib/frr \
                --sysconfdir=/etc/frr \
@@ -92,8 +91,6 @@ endif
        cp -r tools/etc/* debian/tmp/etc/
        -rm debian/tmp/etc/frr/daemons.conf
 
-       sed -e 's#^!log file #!log file /var/log/frr/#' -i debian/tmp/usr/share/doc/frr/examples/*sample*
-
 # drop dev-only files
        find debian/tmp -name '*.la' -o -name '*.a' -o -name 'lib*.so' | xargs rm -f
        rm -rf debian/tmp/usr/include
index 852a295fd0d069fdacbb9062db13c5ba0e0a2acd..35b51cd9c04361e2173f3be97c3b713e4f7f65d7 100644 (file)
@@ -12,6 +12,13 @@ source-built FRR on the following base platforms:
 * Centos 7
 * Centos 8
 
+The following platform images are used to support Travis CI and can also
+be used to reproduce topotest failures when the docker host is Ubuntu
+(tested on 18.04 and 20.04):
+
+* Ubuntu 18.04
+* Ubuntu 20.04
+
 The following platform images may also be built, but these simply install a
 binary package from an existing repository and do not perform source builds:
 
@@ -99,3 +106,60 @@ No script::
 No script, multi-arch (ex. amd64, arm64)::
 
    docker buildx build --platform linux/amd64,linux/arm64 -f docker/centos-8/Dockerfile -t frr-centos8:latest .
+
+
+
+Building Ubuntu 18.04 Image
+---------------------------
+
+Build image (from project root directory)::
+
+   docker build -t frr-ubuntu18:latest  -f docker/ubuntu18-ci/Dockerfile .
+
+Start the container::
+
+   docker run -d --privileged --name frr-ubuntu18 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu18:latest
+
+Running a topotest (when the docker host is Ubuntu)::
+
+   docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+
+Starting an interactive bash session::
+
+   docker exec -it frr-ubuntu18 bash
+
+Stopping an removing a container::
+
+   docker stop frr-ubuntu18 ; docker rm frr-ubuntu18
+
+Removing the built image::
+
+   docker rmi frr-ubuntu18:latest
+
+
+Building Ubuntu 20.04 Image
+---------------------------
+
+Build image (from project root directory)::
+
+   docker build -t frr-ubuntu20:latest  -f docker/ubuntu20-ci/Dockerfile .
+
+Start the container::
+
+   docker run -d --privileged --name frr-ubuntu20 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu20:latest
+
+Running a topotest (when the docker host is Ubuntu)::
+
+   docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+
+Starting an interactive bash session::
+
+   docker exec -it frr-ubuntu20 bash
+
+Stopping an removing a container::
+
+   docker stop frr-ubuntu20 ; docker rm frr-ubuntu20
+
+Removing the built image::
+
+   docker rmi frr-ubuntu20:latest
index f88fc7bfdc007646ac21244473a9e0395c999236..68e58c9d76dcef6e932cd99e7a3518d6c6e997e8 100644 (file)
@@ -85,8 +85,6 @@ startup.  To configure by hand:
 
    docker exec -it frr /bin/sh
    vi /etc/frr/daemons
-   cp /etc/frr/zebra.conf.sample /etc/frr/zebra.conf
-   vi /etc/frr/zebra.conf
    /etc/init.d/frr start
 
 Or, to configure the daemons using /etc/frr from a host volume, put the
index 3e496956c23d63f143987d6ab53c8c1b3db16ee7..b930cb915de147f7ead770330060401a3f5e35e1 100644 (file)
@@ -53,6 +53,10 @@ OPTIONS available for the vtysh command:
 
    When executing cli that does not invoke a vtysh shell, if an error ocurrs ignore it for purposes of return codes from vtysh.
 
+.. option:: -H, --histfile
+
+   Override the history file for vtysh commands. You can set ``vtysh -H /dev/null`` to turn logging of at all.
+
 .. option:: -u, --user
 
    Restrict access to configuration commands by preventing use of the "enable" command. This option provides the same limited "security" as password-protected telnet access. *This security should not be relied on in production environments.*
@@ -68,6 +72,10 @@ ENVIRONMENT VARIABLES
 VTYSH_PAGER
    This should be the name of the pager to use. Default is more.
 
+VTYSH_HISTFILE
+   Override the history file for vtysh commands. Logging can be turned off using ``VTYSH_HISTFILE=/dev/null vtysh``.
+   Environment is prefered way to override the history file path over command line argument (-H/--histfile).
+
 FILES
 =====
 |INSTALL_PREFIX_SBIN|/vtysh
index e6d4aa5c97ba6bc00c5fb3e26e9ab4291fcc8ad4..c8015bb7e553820fd58ab23e6f608f8e76cb9845 100644 (file)
@@ -233,3 +233,41 @@ Babel debugging commands
 .. note::
    If you have compiled with the ``NO_DEBUG`` flag, then these commands aren't
    available.
+
+
+Babel sample configuration file
+===============================
+
+.. code-block:: frr
+
+   debug babel common
+   !debug babel kernel
+   !debug babel filter
+   !debug babel timeout
+   !debug babel interface
+   !debug babel route
+   !debug babel all
+
+   router babel
+   ! network wlan0
+   ! network eth0
+   ! redistribute ipv4 kernel
+   ! no redistribute ipv6 static
+
+   ! The defaults are fine for a wireless interface
+
+   !interface wlan0
+
+   ! A few optimisation tweaks are optional but recommended on a wired interface
+   ! Disable link quality estimation, enable split horizon processing, and
+   ! increase the hello and update intervals.
+
+   !interface eth0
+   ! babel wired
+   ! babel split-horizon
+   ! babel hello-interval 12000
+   ! babel update-interval 36000
+
+   ! log file /var/log/quagga/babeld.log
+   log stdout
+
index d78eb9b177325b471dd1d53f7f69797cae1e5c1b..519f30d5e669a9d0a171eaab8f5e41d39af18120 100644 (file)
@@ -514,32 +514,43 @@ Terminal Mode Commands
    Send a message to all logging destinations that are enabled for messages of
    the given severity.
 
-.. clicmd:: find COMMAND...
+.. clicmd:: find REGEX...
 
-   This command performs a simple substring search across all defined commands
-   in all modes. As an example, suppose you're in enable mode and can't
-   remember where the command to turn OSPF segment routing on is:
+   This command performs a regex search across all defined commands in all
+   modes. As an example, suppose you're in enable mode and can't remember where
+   the command to turn OSPF segment routing on is:
 
    ::
 
       frr# find segment-routing on
         (ospf)  segment-routing on
+        (isis)  segment-routing on
+
 
    The CLI mode is displayed next to each command. In this example,
    :clicmd:`segment-routing on` is under the `router ospf` mode.
 
-   Similarly, suppose you want a listing of all commands that contain "l2vpn":
+   Similarly, suppose you want a listing of all commands that contain "l2vpn"
+   and "neighbor":
 
    ::
 
-      frr# find l2vpn
-        (view)  show [ip] bgp l2vpn evpn [json]
-        (view)  show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]
-        (view)  show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]
-        (view)  show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]
-        (view)  show [ip] bgp l2vpn evpn all overlay
+      frr# find l2vpn.*neighbor
+        (view)  show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]
+        (view)  show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]
+        (view)  show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]
+        (view)  show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]
         ...
 
+
+   Note that when entering spaces as part of a regex specification, repeated
+   spaces will be compressed into a single space for matching purposes. This is
+   a consequence of spaces being used to delimit CLI tokens. If you need to
+   match more than one space, use the ``\s`` escape.
+
+   POSIX Extended Regular Expressions are supported.
+
+
 .. _common-show-commands:
 
 .. clicmd:: show thread cpu [r|w|t|e|x]
index 7d8d84d6a0f013adec79e850f6280fded07102f0..1da9e3ba73613495bc9fff72eb71996a04c8c49d 100644 (file)
@@ -2849,6 +2849,7 @@ When default route is present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/3
                   i internal, r RIB-failure, S Stale, R Removed
    Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
    Origin codes:  i - IGP, e - EGP, ? - incomplete
+   RPKI validation codes: V valid, I invalid, N Not found
 
       Network          Next Hop            Metric LocPrf Weight Path
    *> 0.0.0.0/0        10.10.10.1               0             0 1 i
@@ -2878,6 +2879,7 @@ When default route is present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/3
                i internal, r RIB-failure, S Stale, R Removed
    Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
    Origin codes:  i - IGP, e - EGP, ? - incomplete
+   RPKI validation codes: V valid, I invalid, N Not found
 
       Network          Next Hop            Metric LocPrf Weight Path
    *> 0.0.0.0/0        0.0.0.0                                0 1 i
@@ -2896,6 +2898,7 @@ When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2
                   i internal, r RIB-failure, S Stale, R Removed
    Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
    Origin codes:  i - IGP, e - EGP, ? - incomplete
+   RPKI validation codes: V valid, I invalid, N Not found
 
       Network          Next Hop            Metric LocPrf Weight Path
    *> 10.139.224.0/20  10.10.10.1               0             0 1 ?
@@ -2925,6 +2928,7 @@ When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2
                   i internal, r RIB-failure, S Stale, R Removed
    Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
    Origin codes:  i - IGP, e - EGP, ? - incomplete
+   RPKI validation codes: V valid, I invalid, N Not found
 
       Network          Next Hop            Metric LocPrf Weight Path
    *> 10.139.224.0/20  0.0.0.0                                0 1 ?
@@ -3115,11 +3119,11 @@ daemon project, while :clicmd:`show bgp` command is the new format. The choice
 has been done to keep old format with IPv4 routing table, while new format
 displays IPv6 routing table.
 
-.. clicmd:: show ip bgp [all] [wide|json]
+.. clicmd:: show ip bgp [all] [wide|json [detail]]
 
 .. clicmd:: show ip bgp A.B.C.D [json]
 
-.. clicmd:: show bgp [all] [wide|json]
+.. clicmd:: show bgp [all] [wide|json [detail]]
 
 .. clicmd:: show bgp X:X::X:X [json]
 
@@ -3148,6 +3152,9 @@ displays IPv6 routing table.
 
    If ``json`` option is specified, output is displayed in JSON format.
 
+   If ``detail`` option is specified after ``json``, more verbose JSON output
+   will be displayed.
+
 Some other commands provide additional options for filtering the output.
 
 .. clicmd:: show [ip] bgp regexp LINE
@@ -3234,6 +3241,26 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
 
    Display flap statistics of routes of the selected afi and safi selected.
 
+.. clicmd:: show bgp [afi] [safi] [all] version (1-4294967295) [wide|json]
+
+   Display prefixes with matching version numbers. The version number and
+   above having prefixes will be listed here.
+
+   It helps to identify which prefixes were installed at some point.
+
+   Here is an example of how to check what prefixes were installed starting
+   with an arbitrary version::
+
+   .. code-block:: frr
+
+      ~# vtysh -c 'show bgp ipv4 unicast json' | jq '.tableVersion'
+      9
+      ~# vtysh -c 'show ip bgp version 9 json' | jq -r '.routes | keys[]'
+      192.168.3.0/24
+      ~# vtysh -c 'show ip bgp version 8 json' | jq -r '.routes | keys[]'
+      192.168.2.0/24
+      192.168.3.0/24
+
 .. clicmd:: show bgp [afi] [safi] statistics
 
    Display statistics of routes of the selected afi and safi.
index 88d289d27ecf270a808ec4d3bd36753ebe3e3ac2..573e2ca2e4a41cc7b0d4011627b5d1f2e9a00a1c 100644 (file)
@@ -183,3 +183,18 @@ Debug for EIGRP protocol.
    ``show debugging eigrp`` will show all information currently set for eigrpd
    debug.
 
+
+Sample configuration
+====================
+
+.. code-block:: frr
+
+   hostname eigrpd
+   password zebra
+   enable password please-set-at-here
+   !
+   router eigrp 4453
+     network 192.168.1.0/24
+   !
+   log stdout
+
index 611bc1caaa004b93056787624e0f8cb9413df99e..48d264f30e7b4214ab52d2cffd5ee33967489623 100644 (file)
@@ -60,7 +60,6 @@ in the configuration:
      
 .. clicmd:: set-overload-bit
 
-
    Set overload bit to avoid any transit traffic.
 
 .. clicmd:: purge-originator
@@ -256,9 +255,8 @@ Debugging OpenFabric
 
    Print which OpenFabric debug levels are active.
 
-
-OpenFabric configuration example
-================================
+Sample configuration
+====================
 
 A simple example:
 
@@ -281,3 +279,26 @@ A simple example:
    !
    router openfabric 1
     net 49.0000.0000.0001.00
+
+
+Alternative example:
+
+.. code-block:: frr
+
+   hostname fabricd
+
+   router openfabric DEAD
+     net 47.0023.0000.0003.0300.0100.0102.0304.0506.00
+     lsp-lifetime 65535
+
+     hostname isisd-router
+     domain-password foobar
+
+   interface eth0
+    ip router openfabric DEAD
+    openfabric hello-interval 5
+    openfabric lsp-interval 1000
+
+   ! -- optional
+   openfabric retransmit-interval 10
+   openfabric retransmit-throttle-interval
index 78043e779baa2467a645aca8e982908fa5bf1e1a..1fb9beccdc1794f3a527fe65183c93d8ca732e3e 100644 (file)
@@ -106,17 +106,6 @@ ip prefix-list description
    description to the prefix list.
 
 
-.. _ip-prefix-list-sequential-number-control:
-
-ip prefix-list sequential number control
-----------------------------------------
-
-.. clicmd:: ip prefix-list sequence-number
-
-   With this command, the IP prefix list sequential number is displayed.
-   This is the default behavior.
-
-
 .. _showing-ip-prefix-list:
 
 Showing ip prefix-list
index 3e662b14d836855a4a1d76005188df0e8dcea045..a6b3d9d97fb181e2d68ffde009a10a68bfd97487 100644 (file)
@@ -242,8 +242,9 @@ LDP debugging commands
    - ``messages``
    - ``zebra``
 
-LDP Example Configuration
-=========================
+
+Sample configuration
+====================
 
 Below configuration gives a typical MPLS configuration of a device located in a
 MPLS backbone. LDP is enabled on two interfaces and will attempt to peer with
@@ -306,3 +307,45 @@ that traffic to that destination will be applied.
    O>* 10.200.0.0/24 [110/210] via 10.115.0.1, eth2, label 17, 00:00:15
    north-vm#
 
+
+Additional example demonstrating use of some miscellaneous config options:
+
+.. code-block:: frr
+
+   interface eth0
+   !
+   interface eth1
+   !
+   interface lo
+   !
+   mpls ldp
+    dual-stack cisco-interop
+    neighbor 10.0.1.5 password opensourcerouting
+    neighbor 172.16.0.1 password opensourcerouting
+    !
+    address-family ipv4
+     discovery transport-address 10.0.1.1
+     label local advertise explicit-null
+     !
+     interface eth0
+     !
+     interface eth1
+     !
+    !
+    address-family ipv6
+     discovery transport-address 2001:db8::1
+     !
+     interface eth1
+     !
+    !
+   !
+   l2vpn ENG type vpls
+    bridge br0
+    member interface eth2
+    !
+    member pseudowire mpw0
+     neighbor lsr-id 1.1.1.1
+     pw-id 100
+    !
+   !
+
index b02e761accb0c9624d903db7322ef5fdb861dcb4..cbbc2dc10a5d56ecf5c724cd552bcfd11928bd51 100644 (file)
@@ -180,6 +180,37 @@ https://git-old.alpinelinux.org/user/tteras/strongswan/
 Actively maintained patches are also available at:
 https://gitlab.alpinelinux.org/alpine/aports/-/tree/master/main/strongswan
 
+.. _multicast-functionality:
+
+Multicast Functionality
+=======================
+
+nhrpd can be configured to forward multicast packets, allowing routing
+protocols that use multicast (such as OSPF) to be supported in the DMVPN
+network.
+
+This support requires an iptables NFLOG rule to allow nhrpd to intercept
+multicast packets. A second iptables rule is also usually used to drop the
+original multicast packet.
+
+ .. code-block:: shell
+
+   iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j NFLOG --nflog-group 2
+   iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j DROP
+
+.. index::  nhrp multicast-nflog-group (1-65535)
+.. clicmd:: nhrp multicast-nflog-group (1-65535)
+
+   Sets the nflog group that nhrpd will listen on for multicast packets. This
+   value must match the nflog-group value set in the iptables rule.
+
+.. index::  ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
+.. clicmd:: ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
+
+   Sends multicast packets to the specified NBMA address. If dynamic is
+   specified then destination NBMA address (or addresses) are learnt
+   dynamically.
+
 .. _nhrp-events:
 
 NHRP Events
index 17251e11accf13c12bd56154c507f67f636da859..43c0f62ea35fa363b6c171b603a1b568bc023944 100644 (file)
@@ -243,8 +243,9 @@ Showing OSPF6 information
    JSON object, with each router having "cost", "isLeafNode" and "children" as
    arguments.
 
-OSPF6 Configuration Examples
-============================
+
+Sample configuration
+====================
 
 Example of ospf6d configured on one interface and area:
 
@@ -258,3 +259,53 @@ Example of ospf6d configured on one interface and area:
     area 0.0.0.0 range 2001:770:105:2::/64
     interface eth0 area 0.0.0.0
    !
+
+
+Larger example with policy and various options set:
+
+
+.. code-block:: frr
+
+   debug ospf6 neighbor state
+   !
+   interface fxp0
+    ipv6 ospf6 cost 1
+    ipv6 ospf6 hello-interval 10
+    ipv6 ospf6 dead-interval 40
+    ipv6 ospf6 retransmit-interval 5
+    ipv6 ospf6 priority 0
+    ipv6 ospf6 transmit-delay 1
+    ipv6 ospf6 instance-id 0
+   !
+   interface lo0
+    ipv6 ospf6 cost 1
+    ipv6 ospf6 hello-interval 10
+    ipv6 ospf6 dead-interval 40
+    ipv6 ospf6 retransmit-interval 5
+    ipv6 ospf6 priority 1
+    ipv6 ospf6 transmit-delay 1
+    ipv6 ospf6 instance-id 0
+   !
+   router ospf6
+    router-id 255.1.1.1
+    redistribute static route-map static-ospf6
+    interface fxp0 area 0.0.0.0
+   !
+   access-list access4 permit 127.0.0.1/32
+   !
+   ipv6 access-list access6 permit 3ffe:501::/32
+   ipv6 access-list access6 permit 2001:200::/48
+   ipv6 access-list access6 permit ::1/128
+   !
+   ipv6 prefix-list test-prefix seq 1000 deny any
+   !
+   route-map static-ospf6 permit 10
+    match ipv6 address prefix-list test-prefix
+    set metric-type type-2
+    set metric 2000
+   !
+   line vty
+    access-class access4
+    ipv6 access-class access6
+    exec-timeout 0 0
+   !
index 85b6007f367e4220667aaf717072929509848d01..ba9917f72f178594890eb5454dc61fd93b922292 100644 (file)
@@ -280,7 +280,7 @@ To start OSPF process you have to specify the OSPF router.
 
    This command enables or disables sending ARP requests to update neighbor
    table entries. It speeds up convergence for /32 networks on a P2P
-   connection. 
+   connection.
 
    This feature is enabled by default.
 
@@ -299,15 +299,11 @@ To start OSPF process you have to specify the OSPF router.
    command can be used when the neighbor state get stuck at some state and
    this can be used to recover it from that state.
 
-.. index:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
-.. clicmd:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
+.. clicmd:: maximum-paths (1-64)
 
-.. index:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
-.. clicmd:: no maximum-paths
-
-   CLI to control maximum number of equal cost paths to reach a specific
-   destination.(ECMP)
-   Reset CLI, resets the maximum supported multi path to the default value.
+   Use this command to control the maximum number of equal cost paths to reach
+   a specific destination. The upper limit may differ if you change the value
+   of MULTIPATH_NUM during compilation. The default is MULTIPATH_NUM (64).
 
 .. _ospf-area:
 
@@ -587,7 +583,7 @@ Interfaces
    :clicmd:`ip ospf dead-interval minimal hello-multiplier (2-20)` is also
    specified for the interface.
 
-.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)
+.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn])
 
    When configuring a point-to-point network on an interface and the interface
    has a /32 address associated with then OSPF will treat the interface
@@ -595,6 +591,9 @@ Interfaces
    net.ipv4.conf.<interface name>.rp_filter value to 0.  In order for
    the ospf multicast packets to be delivered by the kernel.
 
+   When used in a DMVPN network at a spoke, this OSPF will be configured in
+   point-to-point, but the HUB will be a point-to-multipoint. To make this
+   topology work, specify the optional 'dmvpn' parameter at the spoke.
 
    Set explicitly network type for specified interface.
 
@@ -1089,8 +1088,9 @@ Debugging OSPF
 
    Debug commnd to enable/disable external route summarisation specific debugs.
 
-OSPF Configuration Examples
-===========================
+
+Sample Configuration
+====================
 
 A simple example, with MD5 authentication enabled:
 
index fe50a5e7ebb560a30bc1bb56e3ac52b39c35d169..5fc3837839d40335a776ca20fe371f73d3bd4eea 100644 (file)
@@ -395,3 +395,52 @@ learned through BGP using route-maps:
   !
 
 In this case, the SR Policy with color `1` and endpoint `1.1.1.1` is selected.
+
+
+Sample configuration
+====================
+
+.. code-block:: frr
+
+   ! Default pathd configuration sample
+   !
+   password frr
+   log stdout
+
+   segment-routing
+    traffic-eng
+     segment-list test1
+      index 10 mpls label 123
+      index 20 mpls label 456
+     !
+     segment-list test2
+      index 10 mpls label 321
+      index 20 mpls label 654
+     !
+     policy color 1 endpoint 1.1.1.1
+      name one
+      binding-sid 100
+      candidate-path preference 100 name test1 explicit segment-list test1
+      candidate-path preference 200 name test2 explicit segment-list test2
+     !
+     policy color 2 endpoint 2.2.2.2
+      name two
+      binding-sid 101
+      candidate-path preference 100 name def explicit segment-list test2
+      candidate-path preference 200 name dyn dynamic
+       bandwidth 12345
+       metric bound abc 16 required
+       metric te 10
+      !
+     !
+     pcep
+      pcc-peer PCE1
+       address ip 127.0.0.1
+       sr-draft07
+      !
+      pcc
+       peer PCE1
+      !
+    !
+   !
+
index 14a05a69d78d6005689fc2542dfe3c34b2238a13..77134a77042a550a91f56ab165dbbf326c955293 100644 (file)
@@ -290,3 +290,22 @@ kernel that points to a table to use for forwarding once the rule matches.
 The creation of a nexthop or nexthop-group is translated to a default route in a
 table with the nexthops specified as the nexthops for the default route.
 
+
+Sample configuration
+====================
+
+.. code-block:: frr
+
+   nexthop-group TEST
+     nexthop 4.5.6.7
+     nexthop 5.6.7.8
+   !
+   pbr-map BLUE seq 100
+     match dst-ip 9.9.9.0/24
+     match src-ip 10.10.10.0/24
+     set nexthop-group TEST
+   !
+   int swp1
+     pbr-policy BLUE
+
+
index 86716b49a497febc2a95ca5088a7cde03ab89f02..6b7cae2c5dad4c4b4248f811925833bc0376007f 100644 (file)
@@ -656,3 +656,34 @@ setup. This is existing PIM configuration:
 - Enable pim on the underlay L3 interface via the "ip pim" command.
 - Configure RPs for the BUM multicast group range.
 - Ensure the PIM is enabled on the lo of the VTEPs and the RP.
+
+
+Sample configuration
+====================
+
+.. code-block:: frr
+
+   debug igmp
+   debug pim
+   debug pim zebra
+
+   ! You may want to enable ssmpingd for troubleshooting
+   ! See http://www.venaas.no/multicast/ssmping/
+   !
+   ip ssmpingd 1.1.1.1
+   ip ssmpingd 2.2.2.2
+
+   ! HINTS:
+   !  - Enable "ip pim ssm" on the interface directly attached to the
+   !    multicast source host (if this is the first-hop router)
+   !  - Enable "ip pim ssm" on pim-routers-facing interfaces
+   !  - Enable "ip igmp" on IGMPv3-hosts-facing interfaces
+   !  - In order to inject IGMPv3 local membership information in the
+   !    PIM protocol state, enable both "ip pim ssm" and "ip igmp" on
+   !    the same interface; otherwise PIM won't advertise
+   !    IGMPv3-learned membership to other PIM routers
+
+   interface eth0
+    ip pim ssm
+    ip igmp
+
index cba93e0d84f52d246464b7b8e12d13bba23f1180..83c8c93b1c93da1d2982411756865706e5ee8677 100644 (file)
@@ -539,3 +539,21 @@ Debug for RIP protocol.
 
    Shows all information currently set for ripd debug.
 
+
+Sample configuration
+====================
+
+.. code-block:: frr
+
+
+   debug rip events
+   debug rip packet
+
+   router rip
+    network 11.0.0.0/8
+    network eth0
+    route 10.0.0.0/8
+    distribute-list private-only in eth0
+
+   access-list private-only permit 10.0.0.0/8
+   access-list private-only deny any
index 0387e363052654cb0186047149926d6193ca2b18..b273eb3bfa0c28ecb9bccb9945c3be36338371c7 100644 (file)
@@ -71,3 +71,19 @@ ripngd Filtering Commands
 
       distribute-list local-only out sit1
 
+
+Sample configuration
+====================
+
+.. code-block:: frr
+
+   debug ripng events
+   debug ripng packet
+
+   router ripng
+    network sit1
+    route 3ffe:506::0/32
+    distribute-list local-only out sit1
+
+   ipv6 access-list local-only permit 3ffe:506::0/32
+   ipv6 access-list local-only deny any
index 7f357b09252c8e69ad0eaac987d69fbc68703dd5..3cb83cc6524caf6124c6a328258b61eaff0f8237 100644 (file)
@@ -333,10 +333,10 @@ Route Map Exit Action Command
 Route Map Optimization Command
 ==============================
 
-.. clicmd:: route-map optimization
+.. clicmd:: route-map ROUTE-MAP-NAME optimization
 
-   Enable route-map processing optimization. The optimization is
-   enabled by default.
+   Enable route-map processing optimization for `route-map-name`.
+   The optimization is enabled by default.
    Instead of sequentially passing through all the route-map indexes
    until a match is found, the search for the best-match index will be
    based on a look-up in a prefix-tree. A per-route-map prefix-tree
index 126710f8c267464fef3a6c61df4de518f601b052..56ac1c0d007c73f636ddeb1ca3c4ae1a98e59414 100644 (file)
@@ -1,5 +1,5 @@
 # This stage builds a dist tarball from the source
-FROM alpine:latest as source-builder
+FROM alpine:3.13 as source-builder
 
 RUN mkdir -p /src/alpine
 COPY alpine/APKBUILD.in /src/alpine
@@ -21,7 +21,7 @@ RUN cd /src \
        && make dist
 
 # This stage builds an apk from the dist tarball
-FROM alpine:latest as alpine-builder
+FROM alpine:3.13 as alpine-builder
 # Don't use nocache here so that abuild can use the cache
 RUN apk add \
                --update-cache \
@@ -44,7 +44,7 @@ RUN cd /dist \
        && abuild -r -P /pkgs/apk
 
 # This stage installs frr from the apk
-FROM alpine:latest
+FROM alpine:3.13
 RUN mkdir -p /pkgs/apk
 COPY --from=alpine-builder /pkgs/apk/ /pkgs/apk/
 RUN apk add \
diff --git a/docker/ubuntu18-ci/Dockerfile b/docker/ubuntu18-ci/Dockerfile
new file mode 100644 (file)
index 0000000..ac745c6
--- /dev/null
@@ -0,0 +1,71 @@
+FROM ubuntu:18.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
+# Update Ubuntu Software repository
+RUN apt update && \
+    apt-get install -y \
+      git autoconf automake libtool make libreadline-dev texinfo \
+      pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
+      libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
+      install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev \
+      libelf-dev \
+      sudo gdb iputils-ping time \
+      mininet python-pip iproute2 iperf && \
+      pip install ipaddr && \
+      pip install "pytest<5" && \
+      pip install "scapy>=2.4.2" && \
+      pip install exabgp==3.4.17
+
+RUN groupadd -r -g 92 frr && \
+      groupadd -r -g 85 frrvty && \
+      adduser --system --ingroup frr --home /home/frr \
+              --gecos "FRR suite" --shell /bin/bash frr && \
+      usermod -a -G frrvty frr && \
+      useradd -d /var/run/exabgp/ -s /bin/false exabgp && \
+      echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \
+      mkdir -p /home/frr && chown frr.frr /home/frr
+
+#for libyang 1
+RUN apt-get install -y cmake libpcre3-dev
+
+USER frr:frr
+
+# build and install libyang1
+RUN cd && pwd && ls -al && \
+    git clone https://github.com/CESNET/libyang.git && \
+    cd libyang && \
+    git checkout v1.0.225 && \
+    mkdir build; cd build && \
+    cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+          -D CMAKE_BUILD_TYPE:String="Release" .. && \
+    make -j $(nproc) && \
+    sudo make install
+
+COPY --chown=frr:frr . /home/frr/frr/
+
+RUN cd && ls -al && ls -al frr
+
+RUN cd ~/frr && \
+    ./bootstrap.sh  && \
+    ./configure \
+       --prefix=/usr \
+       --localstatedir=/var/run/frr \
+       --sbindir=/usr/lib/frr \
+       --sysconfdir=/etc/frr \
+       --enable-vtysh \
+       --enable-pimd \
+       --enable-sharpd \
+       --enable-multipath=64 \
+       --enable-user=frr \
+       --enable-group=frr \
+       --enable-vty-group=frrvty \
+       --enable-snmp=agentx \
+       --with-pkg-extra-version=-my-manual-build && \
+    make -j $(nproc) && \
+    sudo make install
+
+RUN cd ~/frr && make check || true
+
+COPY docker/ubuntu18-ci/docker-start /usr/sbin/docker-start
+ENTRYPOINT ["/usr/sbin/docker-start"]
diff --git a/docker/ubuntu18-ci/README.md b/docker/ubuntu18-ci/README.md
new file mode 100644 (file)
index 0000000..4e8ab89
--- /dev/null
@@ -0,0 +1,44 @@
+# Ubuntu 18.04
+
+This builds an ubuntu 18.04 container for dev / test
+
+# Build
+
+```
+docker build -t frr-ubuntu18:latest  -f docker/ubuntu18-ci/Dockerfile .
+```
+
+# Running
+
+```
+docker run -d --privileged --name frr-ubuntu18 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu18:latest
+```
+
+# make check
+
+```
+docker exec frr-ubuntu18 bash -c 'cd ~/frr ; make check'
+```
+
+# interactive bash
+```
+docker exec -it frr-ubuntu18 bash
+```
+
+# topotest -- when Host O/S is Ubuntu only
+
+```
+docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+```
+
+# stop & remove container
+
+```
+docker stop frr-ubuntu18 ; docker rm frr-ubuntu18
+```
+
+# remove image
+
+```
+docker rmi frr-ubuntu18:latest
+```
diff --git a/docker/ubuntu18-ci/docker-start b/docker/ubuntu18-ci/docker-start
new file mode 100755 (executable)
index 0000000..9a45c72
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+if [ $(uname -a | grep -ci Ubuntu) -ge 1 ]; then
+    #for topotests under ubuntu host
+    sudo modprobe mpls-router mpls-iptunnel
+    sudo /etc/init.d/openvswitch-switch start
+fi
+while true ; do sleep 365d ; done
diff --git a/docker/ubuntu20-ci/Dockerfile b/docker/ubuntu20-ci/Dockerfile
new file mode 100644 (file)
index 0000000..5665778
--- /dev/null
@@ -0,0 +1,74 @@
+FROM ubuntu:20.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
+# Update Ubuntu Software repository
+RUN apt update && \
+    apt-get install -y \
+      git autoconf automake libtool make libreadline-dev texinfo \
+      pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
+      libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
+      install-info build-essential libsystemd-dev libsnmp-dev perl \
+      libcap-dev python2 libelf-dev \
+      sudo gdb curl iputils-ping time \
+      mininet iproute2 iperf && \
+      curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output /tmp/get-pip.py && \
+      python2 /tmp/get-pip.py && \
+      rm -f  /tmp/get-pip.py && \
+      pip2 install ipaddr && \
+      pip2 install "pytest<5" && \
+      pip2 install "scapy>=2.4.2" && \
+      pip2 install exabgp==3.4.17
+
+RUN groupadd -r -g 92 frr && \
+      groupadd -r -g 85 frrvty && \
+      adduser --system --ingroup frr --home /home/frr \
+              --gecos "FRR suite" --shell /bin/bash frr && \
+      usermod -a -G frrvty frr && \
+      useradd -d /var/run/exabgp/ -s /bin/false exabgp && \
+      echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \
+      mkdir -p /home/frr && chown frr.frr /home/frr
+
+#for libyang 1
+RUN apt-get install -y cmake libpcre3-dev
+
+USER frr:frr
+
+# build and install libyang1
+RUN cd && pwd && ls -al && \
+    git clone https://github.com/CESNET/libyang.git && \
+    cd libyang && \
+    git checkout v1.0.225 && \
+    mkdir build; cd build && \
+    cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+          -D CMAKE_BUILD_TYPE:String="Release" .. && \
+    make -j $(nproc) && \
+    sudo make install
+
+COPY --chown=frr:frr . /home/frr/frr/
+
+RUN cd && ls -al && ls -al frr
+
+RUN cd ~/frr && \
+    ./bootstrap.sh  && \
+    ./configure \
+       --prefix=/usr \
+       --localstatedir=/var/run/frr \
+       --sbindir=/usr/lib/frr \
+       --sysconfdir=/etc/frr \
+       --enable-vtysh \
+       --enable-pimd \
+       --enable-sharpd \
+       --enable-multipath=64 \
+       --enable-user=frr \
+       --enable-group=frr \
+       --enable-vty-group=frrvty \
+       --enable-snmp=agentx \
+       --with-pkg-extra-version=-my-manual-build && \
+    make -j $(nproc) && \
+    sudo make install
+
+RUN cd ~/frr && make check || true
+
+COPY docker/ubuntu20-ci/docker-start /usr/sbin/docker-start
+ENTRYPOINT ["/usr/sbin/docker-start"]
diff --git a/docker/ubuntu20-ci/README.md b/docker/ubuntu20-ci/README.md
new file mode 100644 (file)
index 0000000..11138c6
--- /dev/null
@@ -0,0 +1,45 @@
+# Ubuntu 20.04
+
+This builds an ubuntu 20.04 container for dev / test
+
+# Build
+
+```
+docker build -t frr-ubuntu20:latest  -f docker/ubuntu20-ci/Dockerfile .
+```
+
+# Running
+
+```
+docker run -d --privileged --name frr-ubuntu20 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu20:latest
+```
+
+# make check
+
+```
+docker exec frr-ubuntu20 bash -c 'cd ~/frr ; make check'
+```
+
+# interactive bash
+
+```
+docker exec -it frr-ubuntu20 bash
+```
+
+# topotest -- when Host O/S is Ubuntu only
+
+```
+docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+```
+
+# stop & remove container
+
+```
+docker stop frr-ubuntu20 ; docker rm frr-ubuntu18
+```
+
+# remove image
+
+```
+docker rmi frr-ubuntu20:latest
+```
diff --git a/docker/ubuntu20-ci/docker-start b/docker/ubuntu20-ci/docker-start
new file mode 100755 (executable)
index 0000000..9a45c72
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+if [ $(uname -a | grep -ci Ubuntu) -ge 1 ]; then
+    #for topotests under ubuntu host
+    sudo modprobe mpls-router mpls-iptunnel
+    sudo /etc/init.d/openvswitch-switch start
+fi
+while true ; do sleep 365d ; done
diff --git a/eigrpd/eigrpd.conf.sample b/eigrpd/eigrpd.conf.sample
deleted file mode 100644 (file)
index 662e667..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-! -*- eigrpd -*-
-!
-! EIGRPDd sample configuration file
-!
-!
-hostname eigrpd
-password zebra
-!enable password please-set-at-here
-!
-!router eigrp 4453
-!  network 192.168.1.0/24
-!
-log stdout
index ba9445acb9958f981b4c931104d214d48b6232c2..82873a4960c1793f52ad318268eb2881a84c42f9 100644 (file)
@@ -5,7 +5,6 @@
 if EIGRPD
 noinst_LIBRARIES += eigrpd/libeigrp.a
 sbin_PROGRAMS += eigrpd/eigrpd
-dist_examples_DATA += eigrpd/eigrpd.conf.sample
 vtysh_scan += \
        eigrpd/eigrp_cli.c \
        eigrpd/eigrp_dump.c \
diff --git a/isisd/fabricd.conf.sample b/isisd/fabricd.conf.sample
deleted file mode 100644 (file)
index be9e33b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-! -*- openfabric -*-
-!
-! fabricd sample configuration file
-!
-hostname fabricd
-password foo
-enable password foo
-log stdout
-!log file /tmp/fabricd.log
-!
-!
-router openfabric DEAD
-  net 47.0023.0000.0003.0300.0100.0102.0304.0506.00
-!  lsp-lifetime 65535
-
-!  hostname isisd-router
-!  domain-password foobar
-
-interface eth0
- ip router openfabric DEAD
-! openfabric hello-interval 5
-! openfabric lsp-interval 1000
-
-! -- optional
-! openfabric retransmit-interval 10
-! openfabric retransmit-throttle-interval
-!
diff --git a/isisd/isisd.conf.sample b/isisd/isisd.conf.sample
deleted file mode 100644 (file)
index 47b1595..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-! -*- isis -*-
-!
-! ISISd sample configuration file
-!
-hostname isisd 
-password foo
-enable password foo
-log stdout 
-!log file /tmp/isisd.log
-! 
-! 
-router isis DEAD
-  net 47.0023.0000.0003.0300.0100.0102.0304.0506.00
-!  is-type level-1
-
-!  -- set the lifetime either for level-1, level-2 or both
-!  lsp-lifetime level-1 65535
-!  lsp-lifetime level-2 65535
-!  lsp-lifetime 65535
-
-!  hostname isisd-router
-!  area-password foobar
-!  domain-password foobar
-
-interface eth0
- ip router isis DEAD
-! isis hello-interval 5
-! isis lsp-interval 1000
-
-! -- optional
-! isis circuit-type level-1
-! isis password lallaa level-1 
-! isis metric 1 level-1
-! isis csnp-interval 5 level-1
-! isis retransmit-interval 10
-! isis retransmit-throttle-interval
-! isis hello-multiplier 2 level-1
-! isis priority 64
-! 
index 4cefe6e10b9a3f38571d2a4bed608da9c0955e79..11bae416577d3ddc33c8bb86db10c2460857ca04 100644 (file)
@@ -5,7 +5,6 @@
 if ISISD
 noinst_LIBRARIES += isisd/libisis.a
 sbin_PROGRAMS += isisd/isisd
-dist_examples_DATA += isisd/isisd.conf.sample
 vtysh_scan += \
        isisd/isis_cli.c \
        isisd/isis_ldp_sync.c \
@@ -26,7 +25,6 @@ endif
 if FABRICD
 noinst_LIBRARIES += isisd/libfabric.a
 sbin_PROGRAMS += isisd/fabricd
-dist_examples_DATA += isisd/fabricd.conf.sample
 if !ISISD
 vtysh_scan += \
        isisd/isis_cli.c \
diff --git a/ldpd/ldpd.conf.sample b/ldpd/ldpd.conf.sample
deleted file mode 100644 (file)
index 49da35c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-! -*- ldp -*-
-!
-! LDPd sample configuration file
-!
-hostname ldpd
-password zebra
-log stdout
-!
-interface eth0
-!
-interface eth1
-!
-interface lo
-!
-mpls ldp
- dual-stack cisco-interop
- neighbor 10.0.1.5 password opensourcerouting
- neighbor 172.16.0.1 password opensourcerouting
- !
- address-family ipv4
-  discovery transport-address 10.0.1.1
-  label local advertise explicit-null
-  !
-  interface eth0
-  !
-  interface eth1
-  !
- !
- address-family ipv6
-  discovery transport-address 2001:db8::1
-  !
-  interface eth1
-  !
- !
-!
-l2vpn ENG type vpls
- bridge br0
- member interface eth2
- !
- member pseudowire mpw0
-  neighbor lsr-id 1.1.1.1
-  pw-id 100
- !
-!
-line vty
-!
index aa9b751bcc9c9e85060e13672c3a687ca29cf979..5fc3847c6d8cf53de2680c372b59fc389beea6c7 100644 (file)
@@ -5,7 +5,6 @@
 if LDPD
 noinst_LIBRARIES += ldpd/libldp.a
 sbin_PROGRAMS += ldpd/ldpd
-dist_examples_DATA += ldpd/ldpd.conf.sample
 vtysh_scan += ldpd/ldp_vty_cmds.c
 vtysh_daemons += ldpd
 man8 += $(MANBUILD)/frr-ldpd.8
index 276d6c685e64c0cd1eebca1e7c07a487dfbcb1ad..d22a9150d19fc80967b8b66f897c6797ab8547cf 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -237,7 +237,7 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
        memset(sp, 0, sizeof(*sp));
 
        /* Get interface index. */
-       ifindex = stream_getl(s);
+       STREAM_GETL(s, ifindex);
 
        /* Lookup index. */
        if (ifindex != 0) {
@@ -252,25 +252,28 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
        }
 
        /* Fetch destination address. */
-       dp->family = stream_getc(s);
+       STREAM_GETC(s, dp->family);
 
        plen = prefix_blen(dp);
-       stream_get(&dp->u.prefix, s, plen);
-       dp->prefixlen = stream_getc(s);
+       STREAM_GET(&dp->u.prefix, s, plen);
+       STREAM_GETC(s, dp->prefixlen);
 
        /* Get BFD status. */
-       *status = stream_getl(s);
+       STREAM_GETL(s, (*status));
 
-       sp->family = stream_getc(s);
+       STREAM_GETC(s, sp->family);
 
        plen = prefix_blen(sp);
-       stream_get(&sp->u.prefix, s, plen);
-       sp->prefixlen = stream_getc(s);
+       STREAM_GET(&sp->u.prefix, s, plen);
+       STREAM_GETC(s, sp->prefixlen);
 
-       local_remote_cbit = stream_getc(s);
+       STREAM_GETC(s, local_remote_cbit);
        if (remote_cbit)
                *remote_cbit = local_remote_cbit;
        return ifp;
+
+stream_failure:
+       return NULL;
 }
 
 /*
@@ -1094,6 +1097,13 @@ static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
 
        ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &state, &remote_cbit,
                                vrf_id);
+       /*
+        * When interface lookup fails or an invalid stream is read, we must
+        * not proceed otherwise it will trigger an assertion while checking
+        * family type below.
+        */
+       if (dp.family == 0 || sp.family == 0)
+               return 0;
 
        if (bsglobal.debugging) {
                ifstr[0] = 0;
index 770e2fc5ace68d625fcea2ba2e6dca79af2cbdf6..d2798b500227de6cc7cad288d106d1d71e3808fc 100644 (file)
@@ -2226,18 +2226,19 @@ DEFUN (no_banner_motd,
 
 DEFUN(find,
       find_cmd,
-      "find REGEX",
+      "find REGEX...",
       "Find CLI command matching a regular expression\n"
       "Search pattern (POSIX regex)\n")
 {
-       char *pattern = argv[1]->arg;
        const struct cmd_node *node;
        const struct cmd_element *cli;
        vector clis;
 
        regex_t exp = {};
 
+       char *pattern = argv_concat(argv, argc, 1);
        int cr = regcomp(&exp, pattern, REG_NOSUB | REG_EXTENDED);
+       XFREE(MTYPE_TMP, pattern);
 
        if (cr != 0) {
                switch (cr) {
index 83423ba321922255865e7613a147a3d865488d88..ba8a3086af60be1663c0897e77326bb00a405a17 100644 (file)
@@ -181,6 +181,11 @@ void access_list_delete(struct access_list *access)
        else
                list->head = access->next;
 
+       route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED);
+
+       if (master->delete_hook)
+               master->delete_hook(access);
+
        XFREE(MTYPE_ACCESS_LIST_STR, access->name);
 
        XFREE(MTYPE_TMP, access->remark);
@@ -469,59 +474,6 @@ void access_list_filter_add(struct access_list *access,
   host                 A single host address
 */
 
-struct filter *filter_lookup_cisco(struct access_list *access,
-                                  struct filter *mnew)
-{
-       struct filter *mfilter;
-       struct filter_cisco *filter;
-       struct filter_cisco *new;
-
-       new = &mnew->u.cfilter;
-
-       for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
-               filter = &mfilter->u.cfilter;
-
-               if (filter->extended) {
-                       if (mfilter->type == mnew->type
-                           && filter->addr.s_addr == new->addr.s_addr
-                           && filter->addr_mask.s_addr == new->addr_mask.s_addr
-                           && filter->mask.s_addr == new->mask.s_addr
-                           && filter->mask_mask.s_addr
-                                      == new->mask_mask.s_addr)
-                               return mfilter;
-               } else {
-                       if (mfilter->type == mnew->type
-                           && filter->addr.s_addr == new->addr.s_addr
-                           && filter->addr_mask.s_addr
-                                      == new->addr_mask.s_addr)
-                               return mfilter;
-               }
-       }
-
-       return NULL;
-}
-
-struct filter *filter_lookup_zebra(struct access_list *access,
-                                  struct filter *mnew)
-{
-       struct filter *mfilter;
-       struct filter_zebra *filter;
-       struct filter_zebra *new;
-
-       new = &mnew->u.zfilter;
-
-       for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
-               filter = &mfilter->u.zfilter;
-
-               if (filter->exact == new->exact
-                   && mfilter->type == mnew->type) {
-                       if (prefix_same(&filter->prefix, &new->prefix))
-                               return mfilter;
-               }
-       }
-       return NULL;
-}
-
 static void config_write_access_zebra(struct vty *, struct filter *);
 static void config_write_access_cisco(struct vty *, struct filter *);
 
index 28f52020221b25fb5fd832c1cbe4c044a3861f75..ade68a4567c31b6562003c209573723e91cf55d6 100644 (file)
@@ -151,10 +151,6 @@ void access_list_filter_add(struct access_list *access,
 void access_list_filter_delete(struct access_list *access,
                               struct filter *filter);
 int64_t filter_new_seq_get(struct access_list *access);
-struct filter *filter_lookup_cisco(struct access_list *access,
-                                  struct filter *mnew);
-struct filter *filter_lookup_zebra(struct access_list *access,
-                                  struct filter *mnew);
 
 extern const struct frr_yang_module_info frr_filter_info;
 
@@ -194,6 +190,9 @@ struct acl_dup_args {
        /** Duplicated entry found in list? */
        bool ada_found;
 
+       /** Sequence number of the found entry */
+       int64_t ada_seq;
+
        /** (Optional) Already existing `dnode`. */
        const struct lyd_node *ada_entry_dnode;
 };
@@ -224,6 +223,9 @@ struct plist_dup_args {
        /** Duplicated entry found in list? */
        bool pda_found;
 
+       /** Sequence number of the found entry */
+       int64_t pda_seq;
+
        /** (Optional) Already existing `dnode`. */
        const struct lyd_node *pda_entry_dnode;
 };
index 96444ac970f916db284b81e477adbc5ee0390735..e147ed56390f71c87f3b1c4f67d72645cb7721b0 100644 (file)
 
 #define PREFIX_LIST_NAME_STR "Prefix list entry name\n"
 
-/*
- * Helper function to locate filter data structures for Cisco-style ACLs.
- */
-static int64_t acl_cisco_get_seq(struct access_list *acl, const char *action,
-                                const char *src, const char *src_mask,
-                                const char *dst, const char *dst_mask)
-{
-       struct filter_cisco *fc;
-       struct filter f, *fn;
-
-       memset(&f, 0, sizeof(f));
-       f.cisco = 1;
-       if (strcmp(action, "permit") == 0)
-               f.type = FILTER_PERMIT;
-       else
-               f.type = FILTER_DENY;
-
-       fc = &f.u.cfilter;
-       inet_pton(AF_INET, src, &fc->addr);
-       inet_pton(AF_INET, src_mask, &fc->addr_mask);
-       fc->addr.s_addr &= ~fc->addr_mask.s_addr;
-       if (dst != NULL) {
-               fc->extended = 1;
-               inet_pton(AF_INET, dst, &fc->mask);
-               inet_pton(AF_INET, dst_mask, &fc->mask_mask);
-               fc->mask.s_addr &= ~fc->mask_mask.s_addr;
-       }
-
-       fn = filter_lookup_cisco(acl, &f);
-       if (fn == NULL)
-               return -1;
-
-       return fn->seq;
-}
-
-/*
- * Helper function to locate filter data structures for zebra-style ACLs.
- */
-static int64_t acl_zebra_get_seq(struct access_list *acl, const char *action,
-                                const struct prefix *p, bool exact)
-{
-       struct filter_zebra *fz;
-       struct filter f, *fn;
-
-       memset(&f, 0, sizeof(f));
-       memset(&fz, 0, sizeof(fz));
-       if (strcmp(action, "permit") == 0)
-               f.type = FILTER_PERMIT;
-       else
-               f.type = FILTER_DENY;
-
-       fz = &f.u.zfilter;
-       if (p->family)
-               prefix_copy(&fz->prefix, p);
-       fz->exact = exact;
-
-       fn = filter_lookup_zebra(acl, &f);
-       if (fn == NULL)
-               return -1;
-
-       return fn->seq;
-}
-
 /*
  * Helper function to generate a sequence number for legacy commands.
  */
@@ -146,6 +83,53 @@ static long acl_get_seq(struct vty *vty, const char *xpath)
        return seq + 5;
 }
 
+static int acl_remove_if_empty(struct vty *vty, const char *iptype,
+                              const char *name)
+{
+       char xpath[XPATH_MAXLEN];
+
+       snprintf(xpath, sizeof(xpath),
+                "/frr-filter:lib/access-list[type='%s'][name='%s']/remark",
+                iptype, name);
+       /* List is not empty if there is a remark, check that: */
+       if (yang_dnode_exists(vty->candidate_config->dnode, xpath))
+               return CMD_SUCCESS;
+
+       /* Check if we have any entries: */
+       snprintf(xpath, sizeof(xpath),
+                "/frr-filter:lib/access-list[type='%s'][name='%s']", iptype,
+                name);
+       /*
+        * NOTE: if the list is empty it will return the first sequence
+        * number: 5.
+        */
+       if (acl_get_seq(vty, xpath) != 5)
+               return CMD_SUCCESS;
+
+       /* Nobody is using this list, lets remove it. */
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+static int acl_remove(struct vty *vty, const char *iptype, const char *name,
+                     int64_t sseq)
+{
+       char xpath[XPATH_MAXLEN];
+       int rv;
+
+       snprintfrr(
+               xpath, sizeof(xpath),
+               "/frr-filter:lib/access-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']",
+               iptype, name, sseq);
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, iptype, name);
+
+       return rv;
+}
+
 /*
  * Cisco (legacy) access lists.
  */
@@ -184,7 +168,7 @@ DEFPY_YANG(
                        ada.ada_value[1] = mask_str;
                } else {
                        ada.ada_xpath[0] = "./source-any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -238,44 +222,36 @@ DEFPY_YANG(
        "Address to match\n"
        "Wildcard bits\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv4", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv4";
+       ada.ada_name = name;
+       ada.ada_action = action;
+       if (host_str && mask_str == NULL) {
+               ada.ada_xpath[0] = "./host";
+               ada.ada_value[0] = host_str;
+       } else if (host_str && mask_str) {
+               ada.ada_xpath[0] = "./network/address";
+               ada.ada_value[0] = host_str;
+               ada.ada_xpath[1] = "./network/mask";
+               ada.ada_value[1] = mask_str;
+       } else {
+               ada.ada_xpath[0] = "./source-any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       sseq = acl_cisco_get_seq(acl, action, host_str,
-                                mask_str ? mask_str : CISCO_HOST_WILDCARD_MASK,
-                                NULL, NULL);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv4", name, sseq);
 }
 
 DEFPY_YANG(
@@ -324,7 +300,7 @@ DEFPY_YANG(
                        idx++;
                } else {
                        ada.ada_xpath[idx] = "./source-any";
-                       ada.ada_value[idx] = "true";
+                       ada.ada_value[idx] = "";
                        idx++;
                }
 
@@ -341,7 +317,7 @@ DEFPY_YANG(
                        idx++;
                } else {
                        ada.ada_xpath[idx] = "./destination-any";
-                       ada.ada_value[idx] = "true";
+                       ada.ada_value[idx] = "";
                        idx++;
                }
 
@@ -416,68 +392,58 @@ DEFPY_YANG(
        "Destination address to match\n"
        "Any destination host\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
+       int idx = 0;
        int64_t sseq;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintfrr(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv4", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv4";
+       ada.ada_name = name;
+       ada.ada_action = action;
+       if (src_str && src_mask_str == NULL) {
+               ada.ada_xpath[idx] = "./host";
+               ada.ada_value[idx] = src_str;
+               idx++;
+       } else if (src_str && src_mask_str) {
+               ada.ada_xpath[idx] = "./network/address";
+               ada.ada_value[idx] = src_str;
+               idx++;
+               ada.ada_xpath[idx] = "./network/mask";
+               ada.ada_value[idx] = src_mask_str;
+               idx++;
+       } else {
+               ada.ada_xpath[idx] = "./source-any";
+               ada.ada_value[idx] = "";
+               idx++;
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (src_str != NULL) {
-               if (dst_str != NULL)
-                       sseq = acl_cisco_get_seq(
-                               acl, action, src_str,
-                               src_mask_str ? src_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK,
-                               dst_str,
-                               dst_mask_str ? dst_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK);
-               else
-                       sseq = acl_cisco_get_seq(
-                               acl, action, src_str,
-                               src_mask_str ? src_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK,
-                               "0.0.0.0", CISCO_ANY_WILDCARD_MASK);
+       if (dst_str && dst_mask_str == NULL) {
+               ada.ada_xpath[idx] = "./destination-host";
+               ada.ada_value[idx] = dst_str;
+               idx++;
+       } else if (dst_str && dst_mask_str) {
+               ada.ada_xpath[idx] = "./destination-network/address";
+               ada.ada_value[idx] = dst_str;
+               idx++;
+               ada.ada_xpath[idx] = "./destination-network/mask";
+               ada.ada_value[idx] = dst_mask_str;
+               idx++;
        } else {
-               if (dst_str != NULL)
-                       sseq = acl_cisco_get_seq(
-                               acl, action, "0.0.0.0", CISCO_ANY_WILDCARD_MASK,
-                               dst_str,
-                               dst_mask_str ? dst_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK);
-               else
-                       sseq = acl_cisco_get_seq(
-                               acl, action, "0.0.0.0", CISCO_ANY_WILDCARD_MASK,
-                               "0.0.0.0", CISCO_ANY_WILDCARD_MASK);
+               ada.ada_xpath[idx] = "./destination-any";
+               ada.ada_value[idx] = "";
+               idx++;
        }
-       if (sseq == -1)
-               return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
+               return CMD_WARNING_CONFIG_FAILED;
 
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv4", name, sseq);
 }
 
 /*
@@ -517,7 +483,7 @@ DEFPY_YANG(
                        }
                } else {
                        ada.ada_xpath[0] = "./any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -568,49 +534,36 @@ DEFPY_YANG(
        "Exact match of the prefixes\n"
        "Match any IPv4\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       struct prefix pany;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv4", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv4";
+       ada.ada_name = name;
+       ada.ada_action = action;
+
+       if (prefix_str) {
+               ada.ada_xpath[0] = "./ipv4-prefix";
+               ada.ada_value[0] = prefix_str;
+               if (exact) {
+                       ada.ada_xpath[1] = "./ipv4-exact-match";
+                       ada.ada_value[1] = "true";
+               }
+       } else {
+               ada.ada_xpath[0] = "./any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (prefix_str == NULL) {
-               memset(&pany, 0, sizeof(pany));
-               pany.family = AF_INET;
-               sseq = acl_zebra_get_seq(acl, action, &pany, exact);
-       } else
-               sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
-                                        exact);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv4", name, sseq);
 }
 
 DEFPY_YANG(
@@ -662,13 +615,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/access-list[type='ipv4'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, "ipv4", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -715,7 +673,7 @@ DEFPY_YANG(
                        }
                } else {
                        ada.ada_xpath[0] = "./any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -767,49 +725,36 @@ DEFPY_YANG(
        "Exact match of the prefixes\n"
        "Match any IPv6\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       struct prefix pany;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv6'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv6", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv6";
+       ada.ada_name = name;
+       ada.ada_action = action;
+
+       if (prefix_str) {
+               ada.ada_xpath[0] = "./ipv6-prefix";
+               ada.ada_value[0] = prefix_str;
+               if (exact) {
+                       ada.ada_xpath[1] = "./ipv6-exact-match";
+                       ada.ada_value[1] = "true";
+               }
+       } else {
+               ada.ada_xpath[0] = "./any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (prefix == NULL) {
-               memset(&pany, 0, sizeof(pany));
-               pany.family = AF_INET6;
-               sseq = acl_zebra_get_seq(acl, action, &pany, exact);
-       } else
-               sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
-                                        exact);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv6", name, sseq);
 }
 
 DEFPY_YANG(
@@ -864,13 +809,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/access-list[type='ipv6'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, "ipv6", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -913,7 +863,7 @@ DEFPY_YANG(
                        ada.ada_value[0] = mac_str;
                } else {
                        ada.ada_xpath[0] = "./any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -951,7 +901,7 @@ DEFPY_YANG(
 
 DEFPY_YANG(
        no_mac_access_list, no_mac_access_list_cmd,
-       "no mac access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X:X:X:X:X$prefix|any>",
+       "no mac access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X:X:X:X:X$mac|any>",
        NO_STR
        MAC_STR
        ACCESS_LIST_STR
@@ -961,49 +911,32 @@ DEFPY_YANG(
        "MAC address\n"
        "Match any MAC address\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       struct prefix pany;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='mac'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "mac", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='mac'][name='%s']", name);
+       ada.ada_type = "mac";
+       ada.ada_name = name;
+       ada.ada_action = action;
 
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       if (mac_str) {
+               ada.ada_xpath[0] = "./mac";
+               ada.ada_value[0] = mac_str;
+       } else {
+               ada.ada_xpath[0] = "./any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (prefix == NULL) {
-               memset(&pany, 0, sizeof(pany));
-               pany.family = AF_ETHERNET;
-               sseq = acl_zebra_get_seq(acl, action, &pany, false);
-       } else
-               sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
-                                        false);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "mac", name, sseq);
 }
 
 DEFPY_YANG(
@@ -1058,13 +991,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/access-list[type='mac'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, "mac", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -1257,13 +1195,13 @@ static int plist_remove_if_empty(struct vty *vty, const char *iptype,
 }
 
 static int plist_remove(struct vty *vty, const char *iptype, const char *name,
-                       const char *seq, const char *action, struct prefix *p,
-                       long ge, long le)
+                       const char *seq, const char *action,
+                       const char *prefix_str, const char *ge_str,
+                       const char *le_str)
 {
-       struct prefix_list_entry *pentry;
-       enum prefix_list_type plt;
-       struct prefix_list *pl;
-       struct lyd_node *dnode;
+       int64_t sseq;
+       int arg_idx = 0;
+       struct plist_dup_args pda = {};
        char xpath[XPATH_MAXLEN];
        char xpath_entry[XPATH_MAXLEN + 32];
        int rv;
@@ -1284,29 +1222,57 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name,
        }
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/prefix-list[type='%s'][name='%s']", iptype,
-                name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       pda.pda_type = iptype;
+       pda.pda_name = name;
+       pda.pda_action = action;
+       if (prefix_str) {
+               if (strmatch(iptype, "ipv4")) {
+                       pda.pda_xpath[arg_idx] = "./ipv4-prefix";
+                       pda.pda_value[arg_idx] = prefix_str;
+                       arg_idx++;
+                       if (ge_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv4-prefix-length-greater-or-equal";
+                               pda.pda_value[arg_idx] = ge_str;
+                               arg_idx++;
+                       }
+                       if (le_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv4-prefix-length-lesser-or-equal";
+                               pda.pda_value[arg_idx] = le_str;
+                               arg_idx++;
+                       }
+               } else {
+                       pda.pda_xpath[arg_idx] = "./ipv6-prefix";
+                       pda.pda_value[arg_idx] = prefix_str;
+                       arg_idx++;
+                       if (ge_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv6-prefix-length-greater-or-equal";
+                               pda.pda_value[arg_idx] = ge_str;
+                               arg_idx++;
+                       }
+                       if (le_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv6-prefix-length-lesser-or-equal";
+                               pda.pda_value[arg_idx] = le_str;
+                               arg_idx++;
+                       }
+               }
+       } else {
+               pda.pda_xpath[0] = "./any";
+               pda.pda_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       assert(action != NULL);
-       if (strcmp(action, "permit") == 0)
-               plt = PREFIX_PERMIT;
+       if (plist_is_dup(vty->candidate_config->dnode, &pda))
+               sseq = pda.pda_seq;
        else
-               plt = PREFIX_DENY;
-
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       pl = nb_running_get_entry(dnode, NULL, true);
-       pentry = prefix_list_entry_lookup(pl, p, plt, -1, le, ge);
-       if (pentry == NULL)
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq);
+       snprintfrr(
+               xpath_entry, sizeof(xpath_entry),
+               "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']",
+               iptype, name, sseq);
        nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
 
        rv = nb_cli_apply_changes(vty, NULL);
@@ -1425,8 +1391,8 @@ DEFPY_YANG(
        "Maximum prefix length to be matched\n"
        "Maximum prefix length\n")
 {
-       return plist_remove(vty, "ipv4", name, seq_str, action,
-                           (struct prefix *)prefix, ge, le);
+       return plist_remove(vty, "ipv4", name, seq_str, action, prefix_str,
+                           ge_str, le_str);
 }
 
 DEFPY_YANG(
@@ -1438,7 +1404,7 @@ DEFPY_YANG(
        PREFIX_LIST_NAME_STR
        ACCESS_LIST_SEQ_STR)
 {
-       return plist_remove(vty, "ipv4", name, seq_str, NULL, NULL, 0, 0);
+       return plist_remove(vty, "ipv4", name, seq_str, NULL, NULL, NULL, NULL);
 }
 
 DEFPY_YANG(
@@ -1493,13 +1459,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return plist_remove_if_empty(vty, "ipv4", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -1621,8 +1592,8 @@ DEFPY_YANG(
        "Minimum prefix length to be matched\n"
        "Minimum prefix length\n")
 {
-       return plist_remove(vty, "ipv6", name, seq_str, action,
-                           (struct prefix *)prefix, ge, le);
+       return plist_remove(vty, "ipv6", name, seq_str, action, prefix_str,
+                           ge_str, le_str);
 }
 
 DEFPY_YANG(
@@ -1634,7 +1605,7 @@ DEFPY_YANG(
        PREFIX_LIST_NAME_STR
        ACCESS_LIST_SEQ_STR)
 {
-       return plist_remove(vty, "ipv6", name, seq_str, NULL, NULL, 0, 0);
+       return plist_remove(vty, "ipv6", name, seq_str, NULL, NULL, NULL, NULL);
 }
 
 DEFPY_YANG(
@@ -1689,13 +1660,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return plist_remove_if_empty(vty, "ipv6", name);
+
+       return rv;
 }
 
 ALIAS(
index 3aa362ad63060b897b50b93175b3ab57148ddf31..85805ffa47c190436e9e39b633e2d9a5e6baa3b6 100644 (file)
@@ -279,6 +279,7 @@ static int _acl_is_dup(const struct lyd_node *dnode, void *arg)
        }
 
        ada->ada_found = true;
+       ada->ada_seq = yang_dnode_get_uint32(dnode, "sequence");
 
        return YANG_ITER_STOP;
 }
@@ -416,6 +417,7 @@ static int _plist_is_dup(const struct lyd_node *dnode, void *arg)
        }
 
        pda->pda_found = true;
+       pda->pda_seq = yang_dnode_get_uint32(dnode, "sequence");
 
        return YANG_ITER_STOP;
 }
@@ -506,17 +508,12 @@ static int lib_access_list_create(struct nb_cb_create_args *args)
 
 static int lib_access_list_destroy(struct nb_cb_destroy_args *args)
 {
-       struct access_master *am;
        struct access_list *acl;
 
        if (args->event != NB_EV_APPLY)
                return NB_OK;
 
        acl = nb_running_unset_entry(args->dnode);
-       am = acl->master;
-       if (am->delete_hook)
-               am->delete_hook(acl);
-
        access_list_delete(acl);
 
        return NB_OK;
index 629ef4e70878b3e401392304cf31eb5d6fb6eddc..f8a693d8f3053d7ab5037d3b4571185da9fda1bf 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -1056,15 +1056,30 @@ struct connected *connected_get_linklocal(struct interface *ifp)
 void if_terminate(struct vrf *vrf)
 {
        struct interface *ifp;
+       bool delete;
+
+       /*
+        * If the default VRF is being terminated or has
+        * already been terminated it means that
+        * the program is shutting down and we need to
+        * delete all the interfaces. Otherwise, we only
+        * need to move VRF's interfaces to the default VRF.
+        */
+       delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT
+                || !vrf_lookup_by_id(VRF_DEFAULT);
 
        while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
                ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name);
 
-               if (ifp->node) {
-                       ifp->node->info = NULL;
-                       route_unlock_node(ifp->node);
+               if (delete) {
+                       if (ifp->node) {
+                               ifp->node->info = NULL;
+                               route_unlock_node(ifp->node);
+                       }
+                       if_delete(&ifp);
+               } else {
+                       if_update_to_new_vrf(ifp, VRF_DEFAULT);
                }
-               if_delete(&ifp);
        }
 }
 
index 6e5088142a10c3985d09c4048d9671ff2afc959e..17695e6607c8049d150f054957df8cbb9de30dfd 100644 (file)
@@ -45,9 +45,15 @@ static struct log_ref ferr_lib_warn[] = {
                .suggestion = "Gather log data and open an Issue. restart FRR",
        },
        {
-               .code = EC_LIB_SLOW_THREAD,
-               .title = "The Event subsystem has detected a slow process",
-               .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner.  This can be either a misconfiguration, bug, or some combination therof.",
+               .code = EC_LIB_SLOW_THREAD_CPU,
+               .title = "The Event subsystem has detected a slow cpu time process",
+               .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner.  This can be either a misconfiguration, bug, or some combination therof.  In this case total CPU time was over 5 seconds.  Which indicates that FRR is very busy doing some work and should be addressed",
+               .suggestion = "Gather log data and open an Issue",
+       },
+       {
+               .code = EC_LIB_SLOW_THREAD_WALL,
+               .title = "The Event subsystem has detected a slow wall time process",
+               .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner.  This can be either a misconfiguration, bug or some combination therof.  In this case total WALL time was over 5 seconds.  Which indicates that FRR might be having trouble being scheduled or some system call is delaying",
                .suggestion = "Gather log data and open an Issue",
        },
        {
index 4730b6aa330721ee5c4fc469c097e72d855d9c92..9f0f58d20b1842a11fc83edc27952c99922cfd3e 100644 (file)
@@ -44,7 +44,8 @@ enum lib_log_refs {
        EC_LIB_SNMP,
        EC_LIB_STREAM,
        EC_LIB_LINUX_NS,
-       EC_LIB_SLOW_THREAD,
+       EC_LIB_SLOW_THREAD_CPU,
+       EC_LIB_SLOW_THREAD_WALL,
        EC_LIB_NO_THREAD,
        EC_LIB_RMAP_RECURSION_LIMIT,
        EC_LIB_BACKUP_CONFIG,
index e078d8e2a7a35c67ee987b9ebd4a6ed371dc4afb..ca2f50168602638a34cb600eb32be1f4db72bb41 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -464,7 +464,15 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST),
        DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY),
        DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_ADD),
-       DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL)};
+       DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL),
+       DESC_ENTRY(ZEBRA_NHRP_NEIGH_ADDED),
+       DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED),
+       DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET),
+       DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER),
+       DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER),
+       DESC_ENTRY(ZEBRA_NEIGH_IP_ADD),
+       DESC_ENTRY(ZEBRA_NEIGH_IP_DEL),
+       DESC_ENTRY(ZEBRA_CONFIGURE_ARP)};
 #undef DESC_ENTRY
 
 static const struct zebra_desc_table unknown = {0, "unknown", '?'};
index c26621ae99d1e3e1aac6e98ed6e8ff574160dce4..c6788dd35aaf9b33c500c9fc207d8b48a2dade1a 100644 (file)
@@ -146,11 +146,11 @@ void log_show_syslog(struct vty *vty)
                        zlog_progname);
 }
 
-DEFUN (show_logging,
-       show_logging_cmd,
-       "show logging",
-       SHOW_STR
-       "Show current logging configuration\n")
+DEFUN_NOSH (show_logging,
+           show_logging_cmd,
+           "show logging",
+           SHOW_STR
+           "Show current logging configuration\n")
 {
        log_show_syslog(vty);
 
index 92c8b8ee557115cce21f88a5d895389644a6f23d..0663ac5aecd1376f7549ae9a3445f63ea52b6bdf 100644 (file)
@@ -72,9 +72,6 @@ struct prefix_master {
        /* List of prefix_list which name is string. */
        struct prefix_list_list str;
 
-       /* Whether sequential number is used. */
-       bool seqnum;
-
        /* The latest update. */
        struct prefix_list *recent;
 
@@ -90,22 +87,22 @@ struct prefix_master {
 
 /* Static structure of IPv4 prefix_list's master. */
 static struct prefix_master prefix_master_ipv4 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
+       {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4,
 };
 
 /* Static structure of IPv6 prefix-list's master. */
 static struct prefix_master prefix_master_ipv6 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
+       {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6,
 };
 
 /* Static structure of BGP ORF prefix_list's master. */
 static struct prefix_master prefix_master_orf_v4 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
+       {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4,
 };
 
 /* Static structure of BGP ORF prefix_list's master. */
 static struct prefix_master prefix_master_orf_v6 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
+       {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6,
 };
 
 static struct prefix_master *prefix_master_get(afi_t afi, int orf)
@@ -1003,8 +1000,7 @@ static void vty_show_prefix_entry(struct vty *vty, afi_t afi,
 
                        vty_out(vty, "   ");
 
-                       if (master->seqnum)
-                               vty_out(vty, "seq %" PRId64 " ", pentry->seq);
+                       vty_out(vty, "seq %" PRId64 " ", pentry->seq);
 
                        vty_out(vty, "%s ", prefix_list_type_str(pentry));
 
@@ -1192,19 +1188,6 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
 #include "lib/plist_clippy.c"
 #endif
 
-DEFPY (ip_prefix_list_sequence_number,
-       ip_prefix_list_sequence_number_cmd,
-       "[no] ip prefix-list sequence-number",
-       NO_STR
-       IP_STR
-       PREFIX_LIST_STR
-       "Include/exclude sequence numbers in NVGEN\n")
-{
-       prefix_master_ipv4.seqnum = no ? false : true;
-       return CMD_SUCCESS;
-}
-
-
 DEFPY (show_ip_prefix_list,
        show_ip_prefix_list_cmd,
        "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
@@ -1281,18 +1264,6 @@ DEFPY (clear_ip_prefix_list,
        return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str);
 }
 
-DEFPY (ipv6_prefix_list_sequence_number,
-       ipv6_prefix_list_sequence_number_cmd,
-       "[no] ipv6 prefix-list sequence-number",
-       NO_STR
-       IPV6_STR
-       PREFIX_LIST_STR
-       "Include/exclude sequence numbers in NVGEN\n")
-{
-       prefix_master_ipv6.seqnum = no ? false : true;
-       return CMD_SUCCESS;
-}
-
 DEFPY (show_ipv6_prefix_list,
        show_ipv6_prefix_list_cmd,
        "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
@@ -1553,7 +1524,6 @@ static void prefix_list_reset_afi(afi_t afi, int orf)
        assert(master->str.head == NULL);
        assert(master->str.tail == NULL);
 
-       master->seqnum = true;
        master->recent = NULL;
 }
 
@@ -1597,8 +1567,6 @@ static void prefix_list_init_ipv4(void)
 {
        install_node(&prefix_node);
 
-       install_element(CONFIG_NODE, &ip_prefix_list_sequence_number_cmd);
-
        install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
        install_element(VIEW_NODE, &show_ip_prefix_list_prefix_cmd);
        install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
@@ -1618,8 +1586,6 @@ static void prefix_list_init_ipv6(void)
 {
        install_node(&prefix_ipv6_node);
 
-       install_element(CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd);
-
        install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
        install_element(VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd);
        install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
index 33c65ac33337587bb9f9ae6d501a7435b1e1ec00..b2cb299fd3403cd1b269529cc53966a137fae7bd 100644 (file)
@@ -2906,29 +2906,6 @@ void route_map_notify_dependencies(const char *affected_name,
 }
 
 /* VTY related functions. */
-DEFUN(no_routemap_optimization, no_routemap_optimization_cmd,
-      "no route-map optimization",
-      NO_STR
-      "route-map\n"
-      "optimization\n")
-{
-       VTY_DECLVAR_CONTEXT(route_map_index, index);
-
-       index->map->optimization_disabled = true;
-       return CMD_SUCCESS;
-}
-
-DEFUN(routemap_optimization, routemap_optimization_cmd,
-      "route-map optimization",
-      "route-map\n"
-      "optimization\n")
-{
-       VTY_DECLVAR_CONTEXT(route_map_index, index);
-
-       index->map->optimization_disabled = false;
-       return CMD_SUCCESS;
-}
-
 static void clear_route_map_helper(struct route_map *map)
 {
        struct route_map_index *index;
@@ -3241,8 +3218,5 @@ void route_map_init(void)
        install_element(ENABLE_NODE, &debug_rmap_cmd);
        install_element(ENABLE_NODE, &no_debug_rmap_cmd);
 
-       install_element(RMAP_NODE, &routemap_optimization_cmd);
-       install_element(RMAP_NODE, &no_routemap_optimization_cmd);
-
        install_element(ENABLE_NODE, &show_route_map_pfx_tbl_cmd);
 }
index 6385193bbf88854a7d2df944bcf7d238d1bb9e24..5b6b64eaebba560c8f0f84204e17922424a1c995 100644 (file)
@@ -902,6 +902,9 @@ extern void route_map_call_show(struct vty *vty, struct lyd_node *dnode,
 extern void route_map_description_show(struct vty *vty,
                                       struct lyd_node *dnode,
                                       bool show_defaults);
+extern void route_map_optimization_disabled_show(struct vty *vty,
+                                                struct lyd_node *dnode,
+                                                bool show_defaults);
 extern void route_map_cli_init(void);
 
 #ifdef __cplusplus
index 9a53c11a4cf8e3374da94f2b30702882b8ad41e7..e11b9eea7416cc5d8d45ad55e34220fb35fa88ca 100644 (file)
@@ -1396,6 +1396,74 @@ void route_map_description_show(struct vty *vty, struct lyd_node *dnode,
        vty_out(vty, " description %s\n", yang_dnode_get_string(dnode, NULL));
 }
 
+DEFPY_YANG(
+       route_map_optimization, route_map_optimization_cmd,
+       "[no] route-map WORD$name optimization",
+       NO_STR
+       ROUTE_MAP_CMD_STR
+       "Configure route-map optimization\n")
+{
+       char xpath[XPATH_MAXLEN];
+
+       snprintf(xpath, sizeof(xpath),
+                "/frr-route-map:lib/route-map[name='%s']", name);
+       nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+       snprintf(
+               xpath, sizeof(xpath),
+               "/frr-route-map:lib/route-map[name='%s']/optimization-disabled",
+               name);
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, no ? "true" : "false");
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+void route_map_optimization_disabled_show(struct vty *vty,
+                                         struct lyd_node *dnode,
+                                         bool show_defaults)
+{
+       const char *name = yang_dnode_get_string(dnode, "../name");
+       const bool disabled = yang_dnode_get_bool(dnode, NULL);
+
+       vty_out(vty, "%sroute-map %s optimization\n", disabled ? "no " : "",
+               name);
+}
+
+#if CONFDATE > 20220409
+CPP_NOTICE("Time to remove old route-map optimization command")
+#endif
+
+DEFPY_HIDDEN(
+       routemap_optimization, routemap_optimization_cmd,
+       "[no] route-map optimization",
+       NO_STR
+       "route-map\n"
+       "optimization\n")
+{
+       const struct lyd_node *rmi_dnode;
+       const char *rm_name;
+       char xpath[XPATH_MAXLEN];
+
+       vty_out(vty,
+               "%% This command is deprecated. Please, use `route-map NAME optimization` from the config node.\n");
+
+       rmi_dnode =
+               yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+       if (!rmi_dnode) {
+               vty_out(vty, "%% Failed to get RMI dnode in candidate DB\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       rm_name = yang_dnode_get_string(rmi_dnode, "../name");
+
+       snprintf(
+               xpath, sizeof(xpath),
+               "/frr-route-map:lib/route-map[name='%s']/optimization-disabled",
+               rm_name);
+       nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, no ? "true" : "false");
+       return nb_cli_apply_changes(vty, NULL);
+}
+
 static int route_map_config_write(struct vty *vty)
 {
        struct lyd_node *dnode;
@@ -1447,6 +1515,7 @@ void route_map_cli_init(void)
        install_element(CONFIG_NODE, &route_map_cmd);
        install_element(CONFIG_NODE, &no_route_map_cmd);
        install_element(CONFIG_NODE, &no_route_map_all_cmd);
+       install_element(CONFIG_NODE, &route_map_optimization_cmd);
 
        /* Install the on-match stuff */
        install_element(RMAP_NODE, &rmap_onmatch_next_cmd);
@@ -1513,4 +1582,6 @@ void route_map_cli_init(void)
 
        install_element(RMAP_NODE, &set_srte_color_cmd);
        install_element(RMAP_NODE, &no_set_srte_color_cmd);
+
+       install_element(RMAP_NODE, &routemap_optimization_cmd);
 }
index 410eb51f5e1712b6be6400a1cb747eb33590453b..db06e9caac75653dc80b1810ff808f1d09da408e 100644 (file)
@@ -140,6 +140,30 @@ static int lib_route_map_destroy(struct nb_cb_destroy_args *args)
        return NB_OK;
 }
 
+/*
+ * XPath: /frr-route-map:lib/route-map/optimization-disabled
+ */
+static int
+lib_route_map_optimization_disabled_modify(struct nb_cb_modify_args *args)
+{
+       struct route_map *rm;
+       bool disabled = yang_dnode_get_bool(args->dnode, NULL);
+
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+       case NB_EV_PREPARE:
+       case NB_EV_ABORT:
+               /* NOTHING */
+               break;
+       case NB_EV_APPLY:
+               rm = nb_running_get_entry(args->dnode, NULL, true);
+               rm->optimization_disabled = disabled;
+               break;
+       }
+
+       return NB_OK;
+}
+
 /*
  * XPath: /frr-route-map:lib/route-map/entry
  */
@@ -1197,6 +1221,13 @@ const struct frr_yang_module_info frr_route_map_info = {
                                .destroy = lib_route_map_destroy,
                        }
                },
+               {
+                       .xpath = "/frr-route-map:lib/route-map/optimization-disabled",
+                       .cbs = {
+                               .modify = lib_route_map_optimization_disabled_modify,
+                               .cli_show = route_map_optimization_disabled_show,
+                       }
+               },
                {
                        .xpath = "/frr-route-map:lib/route-map/entry",
                        .cbs = {
index 64cec1385de54513f069433f89f4c35d9d504a81..be7297f26441d57d3f13b7fdab2b1dcb0614ab4f 100644 (file)
@@ -237,9 +237,12 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
        /* make sure we don't hang in here.  default for SIGALRM is terminate.
         * - if we're in backtrace for more than a second, abort. */
        struct sigaction sa_default = {.sa_handler = SIG_DFL};
+
        sigaction(SIGALRM, &sa_default, NULL);
+       sigaction(signo, &sa_default, NULL);
 
        sigset_t sigset;
+
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGALRM);
        sigprocmask(SIG_UNBLOCK, &sigset, NULL);
@@ -252,7 +255,16 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
        log_memstats(stderr, "core_handler");
 
        zlog_tls_buffer_fini();
-       abort();
+
+       /* give the kernel a chance to generate a coredump */
+       sigaddset(&sigset, signo);
+       sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+       raise(signo);
+
+       /* only chance to end up here is if the default action for signo is
+        * something other than kill or coredump the process
+        */
+       _exit(128 + signo);
 }
 
 static void trap_default_signals(void)
index 0853d4bb2bb01705a24c3108376d281bf9333a32..b7efec488296a6e1f5552cc1c119274284a14372 100644 (file)
@@ -141,10 +141,14 @@ vtysh_scan += \
        lib/if_rmap.c \
        lib/keychain.c \
        lib/lib_vty.c \
+       lib/log_vty.c \
        lib/nexthop_group.c \
        lib/plist.c \
+       lib/resolver.c \
        lib/routemap.c \
        lib/routemap_cli.c \
+       lib/spf_backoff.c \
+       lib/thread.c \
        lib/vrf.c \
        lib/vty.c \
        # end
index 866090341e29071456631174e995424bbe5e82b4..3d8b54467821f05229a47a7525ed4435512ac90e 100644 (file)
@@ -124,11 +124,12 @@ static void cpu_record_hash_free(void *a)
 static void vty_out_cpu_thread_history(struct vty *vty,
                                       struct cpu_thread_history *a)
 {
-       vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu",
+       vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu %9zu %9zu",
                a->total_active, a->cpu.total / 1000, a->cpu.total % 1000,
-               a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max,
-               (a->real.total / a->total_calls), a->real.max);
-       vty_out(vty, " %c%c%c%c%c  %s\n",
+               a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max,
+               (a->real.total / a->total_calls), a->real.max,
+               a->total_cpu_warn, a->total_wall_warn);
+       vty_out(vty, "  %c%c%c%c%c  %s\n",
                a->types & (1 << THREAD_READ) ? 'R' : ' ',
                a->types & (1 << THREAD_WRITE) ? 'W' : ' ',
                a->types & (1 << THREAD_TIMER) ? 'T' : ' ',
@@ -149,6 +150,10 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
                atomic_load_explicit(&a->total_active, memory_order_seq_cst);
        copy.total_calls =
                atomic_load_explicit(&a->total_calls, memory_order_seq_cst);
+       copy.total_cpu_warn =
+               atomic_load_explicit(&a->total_cpu_warn, memory_order_seq_cst);
+       copy.total_wall_warn =
+               atomic_load_explicit(&a->total_wall_warn, memory_order_seq_cst);
        copy.cpu.total =
                atomic_load_explicit(&a->cpu.total, memory_order_seq_cst);
        copy.cpu.max = atomic_load_explicit(&a->cpu.max, memory_order_seq_cst);
@@ -165,6 +170,8 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
        vty_out_cpu_thread_history(vty, &copy);
        totals->total_active += copy.total_active;
        totals->total_calls += copy.total_calls;
+       totals->total_cpu_warn += copy.total_cpu_warn;
+       totals->total_wall_warn += copy.total_wall_warn;
        totals->real.total += copy.real.total;
        if (totals->real.max < copy.real.max)
                totals->real.max = copy.real.max;
@@ -202,7 +209,7 @@ static void cpu_record_print(struct vty *vty, uint8_t filter)
                        vty_out(vty,
                                "Active   Runtime(ms)   Invoked Avg uSec Max uSecs");
                        vty_out(vty, " Avg uSec Max uSecs");
-                       vty_out(vty, "  Type  Thread\n");
+                       vty_out(vty, "  CPU_Warn Wall_Warn  Type   Thread\n");
 
                        if (m->cpu_record->count)
                                hash_iterate(
@@ -223,7 +230,7 @@ static void cpu_record_print(struct vty *vty, uint8_t filter)
        vty_out(vty, "%30s %18s %18s\n", "",
                "CPU (user+system):", "Real (wall-clock):");
        vty_out(vty, "Active   Runtime(ms)   Invoked Avg uSec Max uSecs");
-       vty_out(vty, " Avg uSec Max uSecs");
+       vty_out(vty, " Avg uSec Max uSecs  CPU_Warn Wall_Warn");
        vty_out(vty, "  Type  Thread\n");
 
        if (tmp.total_calls > 0)
@@ -300,13 +307,13 @@ static uint8_t parse_filter(const char *filterstr)
 }
 
 #ifndef EXCLUDE_CPU_TIME
-DEFUN (show_thread_cpu,
-       show_thread_cpu_cmd,
-       "show thread cpu [FILTER]",
-       SHOW_STR
-       "Thread information\n"
-       "Thread CPU usage\n"
-       "Display filter (rwtex)\n")
+DEFUN_NOSH (show_thread_cpu,
+           show_thread_cpu_cmd,
+           "show thread cpu [FILTER]",
+           SHOW_STR
+           "Thread information\n"
+           "Thread CPU usage\n"
+           "Display filter (rwtex)\n")
 {
        uint8_t filter = (uint8_t)-1U;
        int idx = 0;
@@ -367,12 +374,12 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
        }
 }
 
-DEFUN (show_thread_poll,
-       show_thread_poll_cmd,
-       "show thread poll",
-       SHOW_STR
-       "Thread information\n"
-       "Show poll FD's and information\n")
+DEFUN_NOSH (show_thread_poll,
+           show_thread_poll_cmd,
+           "show thread poll",
+           SHOW_STR
+           "Thread information\n"
+           "Show poll FD's and information\n")
 {
        struct listnode *node;
        struct thread_master *m;
@@ -1850,15 +1857,33 @@ void thread_call(struct thread *thread)
                                 memory_order_seq_cst);
 
 #ifdef CONSUMED_TIME_CHECK
-       if (realtime > CONSUMED_TIME_CHECK) {
+       if (cputime > CONSUMED_TIME_CHECK) {
                /*
-                * We have a CPU Hog on our hands.
+                * We have a CPU Hog on our hands.  The time FRR
+                * has spent doing actual work ( not sleeping )
+                * is greater than 5 seconds.
                 * Whinge about it now, so we're aware this is yet another task
                 * to fix.
                 */
+               atomic_fetch_add_explicit(&thread->hist->total_cpu_warn,
+                                         1, memory_order_seq_cst);
+               flog_warn(
+                       EC_LIB_SLOW_THREAD_CPU,
+                       "CPU HOG: task %s (%lx) ran for %lums (cpu time %lums)",
+                       thread->xref->funcname, (unsigned long)thread->func,
+                       realtime / 1000, cputime / 1000);
+       } else if (realtime > CONSUMED_TIME_CHECK) {
+               /*
+                * The runtime for a task is greater than 5 seconds, but
+                * the cpu time is under 5 seconds.  Let's whine
+                * about this because this could imply some sort of
+                * scheduling issue.
+                */
+               atomic_fetch_add_explicit(&thread->hist->total_wall_warn,
+                                         1, memory_order_seq_cst);
                flog_warn(
-                       EC_LIB_SLOW_THREAD,
-                       "SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
+                       EC_LIB_SLOW_THREAD_WALL,
+                       "STARVATION: task %s (%lx) ran for %lums (cpu time %lums)",
                        thread->xref->funcname, (unsigned long)thread->func,
                        realtime / 1000, cputime / 1000);
        }
index af6833113100b15442234585f886a9650eeba2e0..fee728dbf9416478cdf857620d2edc480b38fb8f 100644 (file)
@@ -119,6 +119,8 @@ struct thread {
 
 struct cpu_thread_history {
        int (*func)(struct thread *);
+       atomic_size_t total_cpu_warn;
+       atomic_size_t total_wall_warn;
        atomic_size_t total_calls;
        atomic_size_t total_active;
        struct time_stats {
index 96cfef1c0af46bb583e135ca206c8e346ad7672b..f92c912084e51bc3d9dc9f57daa2202c3344ba17 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -515,13 +515,19 @@ static int vty_command(struct vty *vty, char *buf)
 
 #ifdef CONSUMED_TIME_CHECK
                GETRUSAGE(&after);
-               if ((realtime = thread_consumed_time(&after, &before, &cputime))
-                   > CONSUMED_TIME_CHECK)
+               realtime = thread_consumed_time(&after, &before, &cputime);
+               if (cputime > CONSUMED_TIME_CHECK) {
                        /* Warn about CPU hog that must be fixed. */
                        flog_warn(
-                               EC_LIB_SLOW_THREAD,
-                               "SLOW COMMAND: command took %lums (cpu time %lums): %s",
+                               EC_LIB_SLOW_THREAD_CPU,
+                               "CPU HOG: command took %lums (cpu time %lums): %s",
                                realtime / 1000, cputime / 1000, buf);
+               } else if (realtime > CONSUMED_TIME_CHECK) {
+                       flog_warn(
+                               EC_LIB_SLOW_THREAD_WALL,
+                               "STARVATION: command took %lums (cpu time %lums): %s",
+                               realtime / 1000, cputime / 1000, buf);
+               }
        }
 #endif /* CONSUMED_TIME_CHECK */
 
index b1cb172b410d3e260a535a70ce9b03c43b7b0549..63166b069a3811502363a1dd869197003fa9dec3 100644 (file)
@@ -137,6 +137,19 @@ extern void xref_gcc_workaround(const struct xref *xref);
 extern const struct xref * const __start_xref_array[1] DSO_LOCAL;
 extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
 
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+/* no redzone around each of the xref_p please, we're building an array out
+ * of variables here.  kinda breaks things if there's redzones between each
+ * array item.
+ */
+#define xref_array_attr used, section("xref_array"), no_sanitize("address")
+#endif
+#endif
+#ifndef xref_array_attr
+#define xref_array_attr used, section("xref_array")
+#endif
+
 /* this macro is invoked once for each standalone DSO through
  *   FRR_MODULE_SETUP  \
  *                      }-> FRR_COREMOD_SETUP -> XREF_SETUP
@@ -151,8 +164,7 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
                        /* .func = */ "dummy",                                 \
        };                                                                     \
        static const struct xref * const _dummy_xref_p                         \
-                       __attribute__((used, section("xref_array")))           \
-                       = &_dummy_xref;                                        \
+                       __attribute__((xref_array_attr)) = &_dummy_xref;       \
        static void __attribute__((used, _CONSTRUCTOR(1100)))                  \
                        _xref_init(void) {                                     \
                static struct xref_block _xref_block = {                       \
@@ -225,7 +237,7 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
 #if defined(__clang__) || !defined(__cplusplus)
 #define XREF_LINK(dst)                                                         \
        static const struct xref * const NAMECTR(xref_p_)                      \
-                       __attribute__((used, section("xref_array")))           \
+                       __attribute__((xref_array_attr))                       \
                = &(dst)                                                       \
        /* end */
 
index c78937c1ec3b3cd141d0f065fe205df27e0cd13b..d613906d829d1de5ff345cbaa3a87f3e44e5f135 100644 (file)
@@ -3916,6 +3916,21 @@ static int zclient_read(struct thread *thread)
                        (*zclient->zebra_client_close_notify)(command, zclient,
                                                              length, vrf_id);
                break;
+       case ZEBRA_NHRP_NEIGH_ADDED:
+               if (zclient->neighbor_added)
+                       (*zclient->neighbor_added)(command, zclient, length,
+                                                  vrf_id);
+               break;
+       case ZEBRA_NHRP_NEIGH_REMOVED:
+               if (zclient->neighbor_removed)
+                       (*zclient->neighbor_removed)(command, zclient, length,
+                                                    vrf_id);
+               break;
+       case ZEBRA_NHRP_NEIGH_GET:
+               if (zclient->neighbor_get)
+                       (*zclient->neighbor_get)(command, zclient, length,
+                                                vrf_id);
+               break;
        default:
                break;
        }
@@ -4181,3 +4196,59 @@ char *zclient_evpn_dump_macip_flags(uint8_t flags, char *buf, size_t len)
 
        return buf;
 }
+
+static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add)
+{
+       uint8_t family;
+
+       STREAM_GETC(s, family);
+       if (family != AF_INET && family != AF_INET6)
+               return -1;
+
+       STREAM_GET(&add->ip.addr, s, family2addrsize(family));
+       add->ipa_type = family;
+       return 0;
+ stream_failure:
+       return -1;
+}
+
+int zclient_neigh_ip_encode(struct stream *s,
+                           uint16_t cmd,
+                           union sockunion *in,
+                           union sockunion *out,
+                           struct interface *ifp)
+{
+       int ret = 0;
+
+       zclient_create_header(s, cmd, ifp->vrf_id);
+       stream_putc(s, sockunion_family(in));
+       stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in));
+       if (out && sockunion_family(out) != AF_UNSPEC) {
+               stream_putc(s, sockunion_family(out));
+               stream_write(s, sockunion_get_addr(out),
+                            sockunion_get_addrlen(out));
+       } else
+               stream_putc(s, AF_UNSPEC);
+       stream_putl(s, ifp->ifindex);
+       if (out)
+               stream_putl(s, ZEBRA_NEIGH_STATE_REACHABLE);
+       else
+               stream_putl(s, ZEBRA_NEIGH_STATE_FAILED);
+       return ret;
+}
+
+int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api)
+{
+       int ret;
+
+       ret = zclient_neigh_ip_read_entry(s, &api->ip_in);
+       if (ret < 0)
+               return -1;
+       zclient_neigh_ip_read_entry(s, &api->ip_out);
+
+       STREAM_GETL(s, api->index);
+       STREAM_GETL(s, api->ndm_state);
+       return 0;
+ stream_failure:
+       return -1;
+}
index bd952ea1e66d9c6b22a0532a1bf9208e45b29613..90240e40b2f78eccf305fb5184c7d1623633435e 100644 (file)
@@ -23,6 +23,7 @@
 
 /* For struct zapi_route. */
 #include "prefix.h"
+#include "ipaddr.h"
 
 /* For struct interface and struct connected. */
 #include "if.h"
@@ -223,6 +224,14 @@ typedef enum {
        ZEBRA_NEIGH_DISCOVER,
        ZEBRA_ROUTE_NOTIFY_REQUEST,
        ZEBRA_CLIENT_CLOSE_NOTIFY,
+       ZEBRA_NHRP_NEIGH_ADDED,
+       ZEBRA_NHRP_NEIGH_REMOVED,
+       ZEBRA_NHRP_NEIGH_GET,
+       ZEBRA_NHRP_NEIGH_REGISTER,
+       ZEBRA_NHRP_NEIGH_UNREGISTER,
+       ZEBRA_NEIGH_IP_ADD,
+       ZEBRA_NEIGH_IP_DEL,
+       ZEBRA_CONFIGURE_ARP,
 } zebra_message_types_t;
 
 enum zebra_error_types {
@@ -381,6 +390,9 @@ struct zclient {
        int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS);
        int (*sr_policy_notify_status)(ZAPI_CALLBACK_ARGS);
        int (*zebra_client_close_notify)(ZAPI_CALLBACK_ARGS);
+       void (*neighbor_added)(ZAPI_CALLBACK_ARGS);
+       void (*neighbor_removed)(ZAPI_CALLBACK_ARGS);
+       void (*neighbor_get)(ZAPI_CALLBACK_ARGS);
 };
 
 /* Zebra API message flag. */
@@ -794,6 +806,27 @@ struct zclient_options {
 
 extern struct zclient_options zclient_options_default;
 
+/* link layer representation for GRE like interfaces
+ * ip_in is the underlay IP, ip_out is the tunnel dest
+ * index stands for the index of the interface
+ * ndm state stands for the NDM value in netlink
+ */
+#define ZEBRA_NEIGH_STATE_REACHABLE (0x02)
+#define ZEBRA_NEIGH_STATE_FAILED    (0x20)
+struct zapi_neigh_ip {
+       int cmd;
+       struct ipaddr ip_in;
+       struct ipaddr ip_out;
+       ifindex_t index;
+       uint32_t ndm_state;
+};
+int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api);
+int zclient_neigh_ip_encode(struct stream *s,
+                           uint16_t cmd,
+                           union sockunion *in,
+                           union sockunion *out,
+                           struct interface *ifp);
+
 /*
  * We reserve the top 4 bits for l2-NHG, everything else
  * is for zebra/proto l3-NHG.
index f54670932830b8f90202e1a7b06ae532051bc205..24800c6e64edad30087e3d4e709e32e39db230c4 100644 (file)
@@ -142,6 +142,7 @@ struct zlog_msg {
 struct zlog_tls {
        char *mmbuf;
        size_t bufpos;
+       bool do_unlink;
 
        size_t nmsgs;
        struct zlog_msg msgs[TLS_LOG_MAXMSG];
@@ -266,13 +267,14 @@ void zlog_tls_buffer_init(void)
                         mmpath, strerror(errno));
                goto out_anon_unlink;
        }
+       zlog_tls->do_unlink = true;
 
        close(mmfd);
        zlog_tls_set(zlog_tls);
        return;
 
 out_anon_unlink:
-       unlink(mmpath);
+       unlinkat(zlog_tmpdirfd, mmpath, 0);
        close(mmfd);
 out_anon:
 
@@ -296,14 +298,16 @@ out_anon:
 void zlog_tls_buffer_fini(void)
 {
        char mmpath[MAXPATHLEN];
+       struct zlog_tls *zlog_tls = zlog_tls_get();
+       bool do_unlink = zlog_tls ? zlog_tls->do_unlink : false;
 
        zlog_tls_buffer_flush();
 
-       zlog_tls_free(zlog_tls_get());
+       zlog_tls_free(zlog_tls);
        zlog_tls_set(NULL);
 
        snprintfrr(mmpath, sizeof(mmpath), "logbuf.%ld", zlog_gettid());
-       if (unlinkat(zlog_tmpdirfd, mmpath, 0))
+       if (do_unlink && unlinkat(zlog_tmpdirfd, mmpath, 0))
                zlog_err("unlink logbuf: %s (%d)", strerror(errno), errno);
 }
 
index 59c82b1c554ca8adba51c5c9377c4da4bdaa9a5c..f697311d4955e865235fab61bd768c9d91a860d7 100644 (file)
@@ -15,6 +15,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include "os.h"
 #include "netlink.h"
 
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *__restrict dest,
+              const char *__restrict src, size_t destsize);
+#endif
+
 static int nhrp_socket_fd = -1;
 
 int os_socket(void)
@@ -42,7 +48,7 @@ int os_socket(void)
 }
 
 int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
-              size_t addrlen)
+              size_t addrlen, uint16_t protocol)
 {
        struct sockaddr_ll lladdr;
        struct iovec iov = {
@@ -54,23 +60,27 @@ int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
                .msg_iov = &iov,
                .msg_iovlen = 1,
        };
-       int status;
+       int status, fd;
 
        if (addrlen > sizeof(lladdr.sll_addr))
                return -1;
 
        memset(&lladdr, 0, sizeof(lladdr));
        lladdr.sll_family = AF_PACKET;
-       lladdr.sll_protocol = htons(ETH_P_NHRP);
+       lladdr.sll_protocol = htons(protocol);
        lladdr.sll_ifindex = ifindex;
        lladdr.sll_halen = addrlen;
        memcpy(lladdr.sll_addr, addr, addrlen);
 
-       status = sendmsg(nhrp_socket_fd, &msg, 0);
-       if (status < 0)
+       fd = os_socket();
+       if (fd < 0)
                return -1;
 
-       return 0;
+       status = sendmsg(fd, &msg, 0);
+       if (status < 0)
+               return -errno;
+
+       return status;
 }
 
 int os_recvmsg(uint8_t *buf, size_t *len, int *ifindex, uint8_t *addr,
@@ -111,7 +121,7 @@ static int linux_configure_arp(const char *iface, int on)
 {
        struct ifreq ifr;
 
-       strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
+       strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
        if (ioctl(nhrp_socket_fd, SIOCGIFFLAGS, &ifr))
                return -1;
 
@@ -154,7 +164,6 @@ int os_configure_dmvpn(unsigned int ifindex, const char *ifname, int af)
                break;
        }
        ret |= linux_configure_arp(ifname, 1);
-       ret |= netlink_configure_arp(ifindex, af);
 
        return ret;
 }
index 74cb81daaa644a0bc5f82e8ea11f85ac4422fa97..5e971cabf13a46215d443b41ba0a789e30b44ba4 100644 (file)
@@ -13,6 +13,7 @@ union sockunion;
 struct interface;
 
 extern int netlink_nflog_group;
+extern int netlink_mcast_nflog_group;
 extern int netlink_req_fd;
 
 void netlink_init(void);
index dc4697cda031fafd5d057560dabf996217d3e6d3..ecea0a9ec57bedcda1a7f3c30bbd6de27fe6648b 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/netfilter/nfnetlink_log.h>
 
 #include "thread.h"
+#include "stream.h"
+#include "prefix.h"
 #include "nhrpd.h"
 #include "netlink.h"
 #include "znl.h"
@@ -27,129 +29,11 @@ int netlink_req_fd = -1;
 int netlink_nflog_group;
 static int netlink_log_fd = -1;
 static struct thread *netlink_log_thread;
-static int netlink_listen_fd = -1;
-
-typedef void (*netlink_dispatch_f)(struct nlmsghdr *msg, struct zbuf *zb);
 
 void netlink_update_binding(struct interface *ifp, union sockunion *proto,
                            union sockunion *nbma)
 {
-       struct nlmsghdr *n;
-       struct ndmsg *ndm;
-       struct zbuf *zb = zbuf_alloc(512);
-
-       n = znl_nlmsg_push(zb, nbma ? RTM_NEWNEIGH : RTM_DELNEIGH,
-                          NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
-       ndm = znl_push(zb, sizeof(*ndm));
-       *ndm = (struct ndmsg){
-               .ndm_family = sockunion_family(proto),
-               .ndm_ifindex = ifp->ifindex,
-               .ndm_type = RTN_UNICAST,
-               .ndm_state = nbma ? NUD_REACHABLE : NUD_FAILED,
-       };
-       znl_rta_push(zb, NDA_DST, sockunion_get_addr(proto),
-                    family2addrsize(sockunion_family(proto)));
-       if (nbma)
-               znl_rta_push(zb, NDA_LLADDR, sockunion_get_addr(nbma),
-                            family2addrsize(sockunion_family(nbma)));
-       znl_nlmsg_complete(zb, n);
-       zbuf_send(zb, netlink_req_fd);
-       zbuf_recv(zb, netlink_req_fd);
-       zbuf_free(zb);
-}
-
-static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb)
-{
-       struct ndmsg *ndm;
-       struct rtattr *rta;
-       struct nhrp_cache *c;
-       struct interface *ifp;
-       struct zbuf payload;
-       union sockunion addr, lladdr;
-       size_t len;
-       int state;
-
-       memset(&lladdr, 0, sizeof(lladdr));
-       ndm = znl_pull(zb, sizeof(*ndm));
-       if (!ndm)
-               return;
-
-       sockunion_family(&addr) = AF_UNSPEC;
-       while ((rta = znl_rta_pull(zb, &payload)) != NULL) {
-               len = zbuf_used(&payload);
-               switch (rta->rta_type) {
-               case NDA_DST:
-                       sockunion_set(&addr, ndm->ndm_family,
-                                     zbuf_pulln(&payload, len), len);
-                       break;
-               case NDA_LLADDR:
-                       sockunion_set(&lladdr, ndm->ndm_family,
-                                     zbuf_pulln(&payload, len), len);
-                       break;
-               }
-       }
-
-       ifp = if_lookup_by_index(ndm->ndm_ifindex, VRF_DEFAULT);
-       if (!ifp || sockunion_family(&addr) == AF_UNSPEC)
-               return;
-
-       c = nhrp_cache_get(ifp, &addr, 0);
-       if (!c)
-               return;
-
-       debugf(NHRP_DEBUG_KERNEL,
-              "Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",
-              (msg->nlmsg_type == RTM_GETNEIGH)
-                      ? "who-has"
-                      : (msg->nlmsg_type == RTM_NEWNEIGH) ? "new-neigh"
-                                                          : "del-neigh",
-              &addr, ifp->name, &lladdr, ndm->ndm_state, c->used, c->cur.type);
-
-       if (msg->nlmsg_type == RTM_GETNEIGH) {
-               if (c->cur.type >= NHRP_CACHE_CACHED) {
-                       nhrp_cache_set_used(c, 1);
-                       debugf(NHRP_DEBUG_KERNEL,
-                              "Netlink: update binding for %pSU dev %s from c %pSU peer.vc.nbma %pSU to lladdr %pSU",
-                              &addr, ifp->name, &c->cur.remote_nbma_natoa,
-                              &c->cur.peer->vc->remote.nbma, &lladdr);
-                       /* In case of shortcuts, nbma is given by lladdr, not
-                        * vc->remote.nbma.
-                        */
-                       netlink_update_binding(ifp, &addr, &lladdr);
-               }
-       } else {
-               state = (msg->nlmsg_type == RTM_NEWNEIGH) ? ndm->ndm_state
-                                                         : NUD_FAILED;
-               nhrp_cache_set_used(c, state == NUD_REACHABLE);
-       }
-}
-
-static int netlink_route_recv(struct thread *t)
-{
-       uint8_t buf[ZNL_BUFFER_SIZE];
-       int fd = THREAD_FD(t);
-       struct zbuf payload, zb;
-       struct nlmsghdr *n;
-
-       zbuf_init(&zb, buf, sizeof(buf), 0);
-       while (zbuf_recv(&zb, fd) > 0) {
-               while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
-                       debugf(NHRP_DEBUG_KERNEL,
-                              "Netlink: Received msg_type %u, msg_flags %u",
-                              n->nlmsg_type, n->nlmsg_flags);
-                       switch (n->nlmsg_type) {
-                       case RTM_GETNEIGH:
-                       case RTM_NEWNEIGH:
-                       case RTM_DELNEIGH:
-                               netlink_neigh_msg(n, &payload);
-                               break;
-                       }
-               }
-       }
-
-       thread_add_read(master, netlink_route_recv, 0, fd, NULL);
-
-       return 0;
+       nhrp_send_zebra_nbr(proto, nbma, ifp);
 }
 
 static void netlink_log_register(int fd, int group)
@@ -265,47 +149,64 @@ void netlink_set_nflog_group(int nlgroup)
        }
 }
 
-void netlink_init(void)
+void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
 {
-       netlink_req_fd = znl_open(NETLINK_ROUTE, 0);
-       if (netlink_req_fd < 0)
-               return;
+       union sockunion addr = {}, lladdr = {};
+       struct interface *ifp;
+       int state, ndm_state;
+       struct nhrp_cache *c;
+       struct zapi_neigh_ip api = {};
 
-       netlink_listen_fd = znl_open(NETLINK_ROUTE, RTMGRP_NEIGH);
-       if (netlink_listen_fd < 0)
+       zclient_neigh_ip_decode(zclient->ibuf, &api);
+       if (api.ip_in.ipa_type == AF_UNSPEC)
                return;
+       sockunion_family(&addr) = api.ip_in.ipa_type;
+       memcpy((uint8_t *)sockunion_get_addr(&addr), &api.ip_in.ip.addr,
+              family2addrsize(api.ip_in.ipa_type));
 
-       thread_add_read(master, netlink_route_recv, 0, netlink_listen_fd, NULL);
-}
+       sockunion_family(&lladdr) = api.ip_out.ipa_type;
+       if (api.ip_out.ipa_type != AF_UNSPEC)
+               memcpy((uint8_t *)sockunion_get_addr(&lladdr),
+                      &api.ip_out.ip.addr,
+                      family2addrsize(api.ip_out.ipa_type));
 
-int netlink_configure_arp(unsigned int ifindex, int pf)
-{
-       struct nlmsghdr *n;
-       struct ndtmsg *ndtm;
-       struct rtattr *rta;
-       struct zbuf *zb = zbuf_alloc(512);
-       int r;
-
-       n = znl_nlmsg_push(zb, RTM_SETNEIGHTBL, NLM_F_REQUEST | NLM_F_REPLACE);
-       ndtm = znl_push(zb, sizeof(*ndtm));
-       *ndtm = (struct ndtmsg){
-               .ndtm_family = pf,
-       };
+       ifp = if_lookup_by_index(api.index, vrf_id);
+       ndm_state = api.ndm_state;
 
-       znl_rta_push(zb, NDTA_NAME, pf == AF_INET ? "arp_cache" : "ndisc_cache",
-                    10);
-
-       rta = znl_rta_nested_push(zb, NDTA_PARMS);
-       znl_rta_push_u32(zb, NDTPA_IFINDEX, ifindex);
-       znl_rta_push_u32(zb, NDTPA_APP_PROBES, 1);
-       znl_rta_push_u32(zb, NDTPA_MCAST_PROBES, 0);
-       znl_rta_push_u32(zb, NDTPA_UCAST_PROBES, 0);
-       znl_rta_nested_complete(zb, rta);
-
-       znl_nlmsg_complete(zb, n);
-       r = zbuf_send(zb, netlink_req_fd);
-       zbuf_recv(zb, netlink_req_fd);
-       zbuf_free(zb);
+       if (!ifp)
+               return;
+       c = nhrp_cache_get(ifp, &addr, 0);
+       if (!c)
+               return;
+       debugf(NHRP_DEBUG_KERNEL,
+              "Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",
+              (cmd == ZEBRA_NHRP_NEIGH_GET)
+              ? "who-has"
+              : (cmd == ZEBRA_NHRP_NEIGH_ADDED) ? "new-neigh"
+              : "del-neigh",
+              &addr, ifp->name, &lladdr, ndm_state, c->used, c->cur.type);
+       if (cmd == ZEBRA_NHRP_NEIGH_GET) {
+               if (c->cur.type >= NHRP_CACHE_CACHED) {
+                       nhrp_cache_set_used(c, 1);
+                       debugf(NHRP_DEBUG_KERNEL,
+                              "Netlink: update binding for %pSU dev %s from c %pSU peer.vc.nbma %pSU to lladdr %pSU",
+                              &addr, ifp->name, &c->cur.remote_nbma_natoa,
+                              &c->cur.peer->vc->remote.nbma, &lladdr);
+                       /* In case of shortcuts, nbma is given by lladdr, not
+                        * vc->remote.nbma.
+                        */
+                       netlink_update_binding(ifp, &addr, &lladdr);
+               }
+       } else {
+               state = (cmd == ZEBRA_NHRP_NEIGH_ADDED) ? ndm_state
+                       : ZEBRA_NEIGH_STATE_FAILED;
+               nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE);
+       }
+}
 
-       return r;
+void netlink_init(void)
+{
+       netlink_req_fd = znl_open(NETLINK_ROUTE, 0);
+       if (netlink_req_fd < 0)
+               return;
 }
index a6880054fdf141f3aae6e7aceac758d0ad026aaf..402ffe9a24239a3522e1071eb69add6e5307f757 100644 (file)
@@ -42,6 +42,7 @@ static int nhrp_if_new_hook(struct interface *ifp)
                struct nhrp_afi_data *ad = &nifp->afi[afi];
                ad->holdtime = NHRPD_DEFAULT_HOLDTIME;
                list_init(&ad->nhslist_head);
+               list_init(&ad->mcastlist_head);
        }
 
        return 0;
@@ -55,6 +56,7 @@ static int nhrp_if_delete_hook(struct interface *ifp)
 
        nhrp_cache_interface_del(ifp);
        nhrp_nhs_interface_del(ifp);
+       nhrp_multicast_interface_del(ifp);
        nhrp_peer_interface_del(ifp);
 
        if (nifp->ipsec_profile)
@@ -298,6 +300,7 @@ void nhrp_interface_update(struct interface *ifp)
                if (!if_ad->configured) {
                        os_configure_dmvpn(ifp->ifindex, ifp->name,
                                           afi2family(afi));
+                       nhrp_send_zebra_configure_arp(ifp, afi2family(afi));
                        if_ad->configured = 1;
                        nhrp_interface_update_address(ifp, afi, 1);
                }
diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c
new file mode 100644 (file)
index 0000000..b78afda
--- /dev/null
@@ -0,0 +1,305 @@
+/* NHRP Multicast Support
+ * Copyright (c) 2020-2021 4RF Limited
+ *
+ * This file is free software: you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <netinet/if_ether.h>
+#include <linux/netlink.h>
+#include <linux/neighbour.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/if_packet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "thread.h"
+#include "nhrpd.h"
+#include "netlink.h"
+#include "znl.h"
+#include "os.h"
+
+DEFINE_MTYPE_STATIC(NHRPD, NHRP_MULTICAST, "NHRP Multicast");
+
+int netlink_mcast_nflog_group;
+static int netlink_mcast_log_fd = -1;
+static struct thread *netlink_mcast_log_thread;
+
+struct mcast_ctx {
+       struct interface *ifp;
+       struct zbuf *pkt;
+};
+
+static void nhrp_multicast_send(struct nhrp_peer *p, struct zbuf *zb)
+{
+       size_t addrlen;
+       int ret;
+
+       addrlen = sockunion_get_addrlen(&p->vc->remote.nbma);
+       ret = os_sendmsg(zb->head, zbuf_used(zb), p->ifp->ifindex,
+                        sockunion_get_addr(&p->vc->remote.nbma), addrlen,
+                        addrlen == 4 ? ETH_P_IP : ETH_P_IPV6);
+
+       debugf(NHRP_DEBUG_COMMON,
+              "Multicast Packet: %pSU -> %pSU, ret = %d, size = %zu, addrlen = %zu",
+              &p->vc->local.nbma, &p->vc->remote.nbma, ret, zbuf_used(zb),
+              addrlen);
+}
+
+static void nhrp_multicast_forward_nbma(union sockunion *nbma_addr,
+                                       struct interface *ifp, struct zbuf *pkt)
+{
+       struct nhrp_peer *p = nhrp_peer_get(ifp, nbma_addr);
+
+       if (p && p->online) {
+               /* Send packet */
+               nhrp_multicast_send(p, pkt);
+       }
+       nhrp_peer_unref(p);
+}
+
+static void nhrp_multicast_forward_cache(struct nhrp_cache *c, void *pctx)
+{
+       struct mcast_ctx *ctx = (struct mcast_ctx *)pctx;
+
+       if (c->cur.type == NHRP_CACHE_DYNAMIC && c->cur.peer)
+               nhrp_multicast_forward_nbma(&c->cur.peer->vc->remote.nbma,
+                                           ctx->ifp, ctx->pkt);
+}
+
+static void nhrp_multicast_forward(struct nhrp_multicast *mcast, void *pctx)
+{
+       struct mcast_ctx *ctx = (struct mcast_ctx *)pctx;
+       struct nhrp_interface *nifp = ctx->ifp->info;
+
+       if (!nifp->enabled)
+               return;
+
+       /* dynamic */
+       if (sockunion_family(&mcast->nbma_addr) == AF_UNSPEC) {
+               nhrp_cache_foreach(ctx->ifp, nhrp_multicast_forward_cache,
+                                  pctx);
+               return;
+       }
+
+       /* Fixed IP Address */
+       nhrp_multicast_forward_nbma(&mcast->nbma_addr, ctx->ifp, ctx->pkt);
+}
+
+static void netlink_mcast_log_handler(struct nlmsghdr *msg, struct zbuf *zb)
+{
+       struct nfgenmsg *nf;
+       struct rtattr *rta;
+       struct zbuf rtapl;
+       uint32_t *out_ndx = NULL;
+       afi_t afi;
+       struct mcast_ctx ctx;
+
+       nf = znl_pull(zb, sizeof(*nf));
+       if (!nf)
+               return;
+
+       ctx.pkt = NULL;
+       while ((rta = znl_rta_pull(zb, &rtapl)) != NULL) {
+               switch (rta->rta_type) {
+               case NFULA_IFINDEX_OUTDEV:
+                       out_ndx = znl_pull(&rtapl, sizeof(*out_ndx));
+                       break;
+               case NFULA_PAYLOAD:
+                       ctx.pkt = &rtapl;
+                       break;
+                       /* NFULA_HWHDR exists and is supposed to contain source
+                        * hardware address. However, for ip_gre it seems to be
+                        * the nexthop destination address if the packet matches
+                        * route.
+                        */
+               }
+       }
+
+       if (!out_ndx || !ctx.pkt)
+               return;
+
+       ctx.ifp = if_lookup_by_index(htonl(*out_ndx), VRF_DEFAULT);
+       if (!ctx.ifp)
+               return;
+
+       debugf(NHRP_DEBUG_COMMON,
+              "Intercepted multicast packet leaving %s len %zu",
+              ctx.ifp->name, zbuf_used(ctx.pkt));
+
+       for (afi = 0; afi < AFI_MAX; afi++) {
+               nhrp_multicast_foreach(ctx.ifp, afi, nhrp_multicast_forward,
+                                      (void *)&ctx);
+       }
+}
+
+static int netlink_mcast_log_recv(struct thread *t)
+{
+       uint8_t buf[65535]; /* Max OSPF Packet size */
+       int fd = THREAD_FD(t);
+       struct zbuf payload, zb;
+       struct nlmsghdr *n;
+
+       netlink_mcast_log_thread = NULL;
+
+       zbuf_init(&zb, buf, sizeof(buf), 0);
+       while (zbuf_recv(&zb, fd) > 0) {
+               while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
+                       debugf(NHRP_DEBUG_COMMON,
+                              "Netlink-mcast-log: Received msg_type %u, msg_flags %u",
+                              n->nlmsg_type, n->nlmsg_flags);
+                       switch (n->nlmsg_type) {
+                       case (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_PACKET:
+                               netlink_mcast_log_handler(n, &payload);
+                               break;
+                       }
+               }
+       }
+
+       thread_add_read(master, netlink_mcast_log_recv, 0, netlink_mcast_log_fd,
+                       &netlink_mcast_log_thread);
+
+       return 0;
+}
+
+static void netlink_mcast_log_register(int fd, int group)
+{
+       struct nlmsghdr *n;
+       struct nfgenmsg *nf;
+       struct nfulnl_msg_config_cmd cmd;
+       struct zbuf *zb = zbuf_alloc(512);
+
+       n = znl_nlmsg_push(zb, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG,
+                          NLM_F_REQUEST | NLM_F_ACK);
+       nf = znl_push(zb, sizeof(*nf));
+       *nf = (struct nfgenmsg){
+               .nfgen_family = AF_UNSPEC,
+               .version = NFNETLINK_V0,
+               .res_id = htons(group),
+       };
+       cmd.command = NFULNL_CFG_CMD_BIND;
+       znl_rta_push(zb, NFULA_CFG_CMD, &cmd, sizeof(cmd));
+       znl_nlmsg_complete(zb, n);
+
+       zbuf_send(zb, fd);
+       zbuf_free(zb);
+}
+
+void netlink_mcast_set_nflog_group(int nlgroup)
+{
+       if (netlink_mcast_log_fd >= 0) {
+               THREAD_OFF(netlink_mcast_log_thread);
+               close(netlink_mcast_log_fd);
+               netlink_mcast_log_fd = -1;
+               debugf(NHRP_DEBUG_COMMON, "De-register nflog group");
+       }
+       netlink_mcast_nflog_group = nlgroup;
+       if (nlgroup) {
+               netlink_mcast_log_fd = znl_open(NETLINK_NETFILTER, 0);
+               if (netlink_mcast_log_fd < 0)
+                       return;
+
+               netlink_mcast_log_register(netlink_mcast_log_fd, nlgroup);
+               thread_add_read(master, netlink_mcast_log_recv, 0,
+                               netlink_mcast_log_fd,
+                               &netlink_mcast_log_thread);
+               debugf(NHRP_DEBUG_COMMON, "Register nflog group: %d",
+                      netlink_mcast_nflog_group);
+       }
+}
+
+static int nhrp_multicast_free(struct interface *ifp,
+                              struct nhrp_multicast *mcast)
+{
+       list_del(&mcast->list_entry);
+       XFREE(MTYPE_NHRP_MULTICAST, mcast);
+       return 0;
+}
+
+int nhrp_multicast_add(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast;
+
+       list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
+       {
+               if (sockunion_same(&mcast->nbma_addr, nbma_addr))
+                       return NHRP_ERR_ENTRY_EXISTS;
+       }
+
+       mcast = XMALLOC(MTYPE_NHRP_MULTICAST, sizeof(struct nhrp_multicast));
+
+       *mcast = (struct nhrp_multicast){
+               .afi = afi, .ifp = ifp, .nbma_addr = *nbma_addr,
+       };
+       list_add_tail(&mcast->list_entry, &nifp->afi[afi].mcastlist_head);
+
+       debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%pSU)", nbma_addr);
+
+       return NHRP_OK;
+}
+
+int nhrp_multicast_del(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast, *tmp;
+
+       list_for_each_entry_safe(mcast, tmp, &nifp->afi[afi].mcastlist_head,
+                                list_entry)
+       {
+               if (!sockunion_same(&mcast->nbma_addr, nbma_addr))
+                       continue;
+
+               debugf(NHRP_DEBUG_COMMON, "Deleting multicast entry (%pSU)",
+                      nbma_addr);
+
+               nhrp_multicast_free(ifp, mcast);
+
+               return NHRP_OK;
+       }
+
+       return NHRP_ERR_ENTRY_NOT_FOUND;
+}
+
+void nhrp_multicast_interface_del(struct interface *ifp)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast, *tmp;
+       afi_t afi;
+
+       for (afi = 0; afi < AFI_MAX; afi++) {
+               debugf(NHRP_DEBUG_COMMON,
+                      "Cleaning up multicast entries (%d)",
+                      !list_empty(&nifp->afi[afi].mcastlist_head));
+
+               list_for_each_entry_safe(
+                       mcast, tmp, &nifp->afi[afi].mcastlist_head, list_entry)
+               {
+                       nhrp_multicast_free(ifp, mcast);
+               }
+       }
+}
+
+void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
+                           void (*cb)(struct nhrp_multicast *, void *),
+                           void *ctx)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast;
+
+       list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
+       {
+               cb(mcast, ctx);
+       }
+}
index c1f615d0a9b5709278111dbfb4e99c2c85673e68..5a7da703acc7c629fe37621c35ae56bb8401794c 100644 (file)
@@ -192,10 +192,10 @@ static void *nhrp_peer_create(void *data)
        return p;
 }
 
-static void do_peer_hash_free(struct hash_bucket *hb,
-                             void *arg __attribute__((__unused__)))
+static void do_peer_hash_free(void *hb_data)
 {
-       struct nhrp_peer *p = hb->data;
+       struct nhrp_peer *p = (struct nhrp_peer *)hb_data;
+
        nhrp_peer_check_delete(p);
 }
 
@@ -207,9 +207,10 @@ void nhrp_peer_interface_del(struct interface *ifp)
               nifp->peer_hash ? nifp->peer_hash->count : 0);
 
        if (nifp->peer_hash) {
-               hash_iterate(nifp->peer_hash, do_peer_hash_free, NULL);
+               hash_clean(nifp->peer_hash, do_peer_hash_free);
                assert(nifp->peer_hash->count == 0);
                hash_free(nifp->peer_hash);
+               nifp->peer_hash = NULL;
        }
 }
 
@@ -375,7 +376,7 @@ void nhrp_peer_send(struct nhrp_peer *p, struct zbuf *zb)
 
        os_sendmsg(zb->head, zbuf_used(zb), p->ifp->ifindex,
                   sockunion_get_addr(&p->vc->remote.nbma),
-                  sockunion_get_addrlen(&p->vc->remote.nbma));
+                  sockunion_get_addrlen(&p->vc->remote.nbma), ETH_P_NHRP);
        zbuf_reset(zb);
 }
 
index 7a4c57b5d43fd367e7a1096f31578c77ed6afd5a..23fa0771eff84f6b553f810236a237933b86214d 100644 (file)
@@ -79,6 +79,24 @@ static void nhrp_route_update_zebra(const struct prefix *p,
        }
 }
 
+static void nhrp_zebra_register_neigh(vrf_id_t vrf_id, afi_t afi, bool reg)
+{
+       struct stream *s;
+
+       if (!zclient || zclient->sock < 0)
+               return;
+
+       s = zclient->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, reg ? ZEBRA_NHRP_NEIGH_REGISTER :
+                             ZEBRA_NHRP_NEIGH_UNREGISTER,
+                             vrf_id);
+       stream_putw(s, afi);
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zclient_send_message(zclient);
+}
+
 void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp)
 {
        struct route_node *rn;
@@ -344,6 +362,8 @@ static void nhrp_zebra_connected(struct zclient *zclient)
                                ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
        zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
                                ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
+       nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, true);
+       nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, true);
 }
 
 void nhrp_zebra_init(void)
@@ -357,7 +377,9 @@ void nhrp_zebra_init(void)
        zclient->interface_address_delete = nhrp_interface_address_delete;
        zclient->redistribute_route_add = nhrp_route_read;
        zclient->redistribute_route_del = nhrp_route_read;
-
+       zclient->neighbor_added = nhrp_neighbor_operation;
+       zclient->neighbor_removed = nhrp_neighbor_operation;
+       zclient->neighbor_get = nhrp_neighbor_operation;
        zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);
 }
 
@@ -370,8 +392,47 @@ static void nhrp_table_node_cleanup(struct route_table *table,
        XFREE(MTYPE_NHRP_ROUTE, node->info);
 }
 
+void nhrp_send_zebra_configure_arp(struct interface *ifp, int family)
+{
+       struct stream *s;
+
+       if (!zclient || zclient->sock < 0) {
+               debugf(NHRP_DEBUG_COMMON, "%s() : zclient not ready",
+                      __func__);
+               return;
+       }
+       s = zclient->obuf;
+       stream_reset(s);
+       zclient_create_header(s,
+                             ZEBRA_CONFIGURE_ARP,
+                             ifp->vrf_id);
+       stream_putc(s, family);
+       stream_putl(s, ifp->ifindex);
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zclient_send_message(zclient);
+}
+
+void nhrp_send_zebra_nbr(union sockunion *in,
+                        union sockunion *out,
+                        struct interface *ifp)
+{
+       struct stream *s;
+
+       if (!zclient || zclient->sock < 0)
+               return;
+       s = zclient->obuf;
+       stream_reset(s);
+       zclient_neigh_ip_encode(s, out ? ZEBRA_NEIGH_IP_ADD :
+                               ZEBRA_NEIGH_IP_DEL, in, out,
+                               ifp);
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zclient_send_message(zclient);
+}
+
 void nhrp_zebra_terminate(void)
 {
+       nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false);
+       nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, false);
        zclient_stop(zclient);
        zclient_free(zclient);
 
index 4358605e2b03b14511ec00a34d140ec109e84a90..420ea12ec1e23c9771370a11aaee54af9d216ed0 100644 (file)
@@ -187,6 +187,9 @@ static int nhrp_config_write(struct vty *vty)
        if (netlink_nflog_group) {
                vty_out(vty, "nhrp nflog-group %d\n", netlink_nflog_group);
        }
+       if (netlink_mcast_nflog_group)
+               vty_out(vty, "nhrp multicast-nflog-group %d\n",
+                       netlink_mcast_nflog_group);
 
        return 0;
 }
@@ -257,6 +260,31 @@ DEFUN(no_nhrp_nflog_group, no_nhrp_nflog_group_cmd,
        return CMD_SUCCESS;
 }
 
+DEFUN(nhrp_multicast_nflog_group, nhrp_multicast_nflog_group_cmd,
+       "nhrp multicast-nflog-group (1-65535)",
+       NHRP_STR
+       "Specify NFLOG group number for Multicast Packets\n"
+       "NFLOG group number\n")
+{
+       uint32_t nfgroup;
+
+       nfgroup = strtoul(argv[2]->arg, NULL, 10);
+       netlink_mcast_set_nflog_group(nfgroup);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(no_nhrp_multicast_nflog_group, no_nhrp_multicast_nflog_group_cmd,
+       "no nhrp multicast-nflog-group [(1-65535)]",
+       NO_STR
+       NHRP_STR
+       "Specify NFLOG group number\n"
+       "NFLOG group number\n")
+{
+       netlink_mcast_set_nflog_group(0);
+       return CMD_SUCCESS;
+}
+
 DEFUN(tunnel_protection, tunnel_protection_cmd,
        "tunnel protection vici profile PROFILE [fallback-profile FALLBACK]",
        "NHRP/GRE integration\n"
@@ -570,6 +598,53 @@ DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd,
        return CMD_SUCCESS;
 }
 
+DEFUN(if_nhrp_map_multicast, if_nhrp_map_multicast_cmd,
+       AFI_CMD " nhrp map multicast <A.B.C.D|X:X::X:X|dynamic>",
+       AFI_STR
+       NHRP_STR
+       "Multicast NBMA Configuration\n"
+       "Use this NBMA mapping for multicasts\n"
+       "IPv4 NBMA address\n"
+       "IPv6 NBMA address\n"
+       "Dynamically learn destinations from client registrations on hub\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       afi_t afi = cmd_to_afi(argv[0]);
+       union sockunion nbma_addr;
+       int ret;
+
+       if (str2sockunion(argv[4]->arg, &nbma_addr) < 0)
+               sockunion_family(&nbma_addr) = AF_UNSPEC;
+
+       ret = nhrp_multicast_add(ifp, afi, &nbma_addr);
+
+       return nhrp_vty_return(vty, ret);
+}
+
+DEFUN(if_no_nhrp_map_multicast, if_no_nhrp_map_multicast_cmd,
+       "no " AFI_CMD " nhrp map multicast <A.B.C.D|X:X::X:X|dynamic>",
+       NO_STR
+       AFI_STR
+       NHRP_STR
+       "Multicast NBMA Configuration\n"
+       "Use this NBMA mapping for multicasts\n"
+       "IPv4 NBMA address\n"
+       "IPv6 NBMA address\n"
+       "Dynamically learn destinations from client registrations on hub\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       afi_t afi = cmd_to_afi(argv[1]);
+       union sockunion nbma_addr;
+       int ret;
+
+       if (str2sockunion(argv[5]->arg, &nbma_addr) < 0)
+               sockunion_family(&nbma_addr) = AF_UNSPEC;
+
+       ret = nhrp_multicast_del(ifp, afi, &nbma_addr);
+
+       return nhrp_vty_return(vty, ret);
+}
+
 DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
        AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
        AFI_STR
@@ -732,8 +807,8 @@ static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg,
        ctx->count++;
 
        if (reg && reg->peer)
-               sockunion2str(&reg->peer->vc->remote.nbma,
-                             buf[0], sizeof(buf[0]));
+               sockunion2str(&reg->peer->vc->remote.nbma, buf[0],
+                             sizeof(buf[0]));
        else
                snprintf(buf[0], sizeof(buf[0]), "-");
        sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1],
@@ -1047,19 +1122,20 @@ struct write_map_ctx {
        const char *aficmd;
 };
 
-static void interface_config_write_nhrp_map(struct nhrp_cache_config *c, void *data)
+static void interface_config_write_nhrp_map(struct nhrp_cache_config *c,
+                                           void *data)
 {
        struct write_map_ctx *ctx = data;
        struct vty *vty = ctx->vty;
-       char buf[2][SU_ADDRSTRLEN];
 
        if (sockunion_family(&c->remote_addr) != ctx->family)
                return;
 
-       vty_out(vty, " %s nhrp map %s %s\n", ctx->aficmd,
-               sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])),
-               c->type == NHRP_CACHE_LOCAL
-               ? "local" : sockunion2str(&c->nbma, buf[1], sizeof(buf[1])));
+       vty_out(vty, " %s nhrp map %pSU ", ctx->aficmd, &c->remote_addr);
+       if (c->type == NHRP_CACHE_LOCAL)
+               vty_out(vty, "local\n");
+       else
+               vty_out(vty, "%pSU\n", &c->nbma);
 }
 
 static int interface_config_write(struct vty *vty)
@@ -1069,9 +1145,9 @@ static int interface_config_write(struct vty *vty)
        struct interface *ifp;
        struct nhrp_interface *nifp;
        struct nhrp_nhs *nhs;
+       struct nhrp_multicast *mcast;
        const char *aficmd;
        afi_t afi;
-       char buf[SU_ADDRSTRLEN];
        int i;
 
        FOR_ALL_INTERFACES (vrf, ifp) {
@@ -1122,21 +1198,31 @@ static int interface_config_write(struct vty *vty)
                                .family = afi2family(afi),
                                .aficmd = aficmd,
                        };
-                       nhrp_cache_config_foreach(ifp, interface_config_write_nhrp_map,
-                                                 &mapctx);
+                       nhrp_cache_config_foreach(
+                               ifp, interface_config_write_nhrp_map, &mapctx);
 
                        list_for_each_entry(nhs, &ad->nhslist_head,
                                            nhslist_entry)
                        {
-                               vty_out(vty, " %s nhrp nhs %s nbma %s\n",
-                                       aficmd,
-                                       sockunion_family(&nhs->proto_addr)
-                                                       == AF_UNSPEC
-                                               ? "dynamic"
-                                               : sockunion2str(
-                                                         &nhs->proto_addr, buf,
-                                                         sizeof(buf)),
-                                       nhs->nbma_fqdn);
+                               vty_out(vty, " %s nhrp nhs ", aficmd);
+                               if (sockunion_family(&nhs->proto_addr)
+                                  == AF_UNSPEC)
+                                       vty_out(vty, "dynamic");
+                               else
+                                       vty_out(vty, "%pSU", &nhs->proto_addr);
+                               vty_out(vty, "nbma %s\n", nhs->nbma_fqdn);
+                       }
+
+                       list_for_each_entry(mcast, &ad->mcastlist_head,
+                                           list_entry)
+                       {
+                               vty_out(vty, " %s nhrp map multicast ", aficmd);
+                               if (sockunion_family(&mcast->nbma_addr)
+                                  == AF_UNSPEC)
+                                       vty_out(vty, "dynamic\n");
+                               else
+                                       vty_out(vty, "%pSU\n",
+                                               &mcast->nbma_addr);
                        }
                }
 
@@ -1171,6 +1257,8 @@ void nhrp_config_init(void)
        install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
        install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
        install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
+       install_element(CONFIG_NODE, &nhrp_multicast_nflog_group_cmd);
+       install_element(CONFIG_NODE, &no_nhrp_multicast_nflog_group_cmd);
 
        /* interface specific commands */
        install_node(&nhrp_interface_node);
@@ -1192,6 +1280,8 @@ void nhrp_config_init(void)
        install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
        install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
        install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
+       install_element(INTERFACE_NODE, &if_nhrp_map_multicast_cmd);
+       install_element(INTERFACE_NODE, &if_no_nhrp_map_multicast_cmd);
        install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
        install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
 }
index e4afb22f803f35f07341d1e3d270347cb3881469..730f9b7d13e08e2427076fcd83bb9956456b637a 100644 (file)
@@ -88,7 +88,12 @@ static inline int notifier_active(struct notifier_list *l)
 
 void nhrp_zebra_init(void);
 void nhrp_zebra_terminate(void);
-
+void nhrp_send_zebra_configure_arp(struct interface *ifp, int family);
+void nhrp_send_zebra_nbr(union sockunion *in,
+                        union sockunion *out,
+                        struct interface *ifp);
+void nhrp_send_zebra_configure_arp(struct interface *ifp,
+                                  int family);
 struct zbuf;
 struct nhrp_vc;
 struct nhrp_cache;
@@ -264,6 +269,13 @@ struct nhrp_nhs {
        struct list_head reglist_head;
 };
 
+struct nhrp_multicast {
+       struct interface *ifp;
+       struct list_head list_entry;
+       afi_t afi;
+       union sockunion nbma_addr; /* IP-address */
+};
+
 struct nhrp_registration {
        struct list_head reglist_entry;
        struct thread *t_register;
@@ -309,6 +321,7 @@ struct nhrp_interface {
                unsigned short mtu;
                unsigned int holdtime;
                struct list_head nhslist_head;
+               struct list_head mcastlist_head;
        } afi[AFI_MAX];
 };
 
@@ -326,6 +339,7 @@ int nhrp_interface_up(ZAPI_CALLBACK_ARGS);
 int nhrp_interface_down(ZAPI_CALLBACK_ARGS);
 int nhrp_interface_address_add(ZAPI_CALLBACK_ARGS);
 int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS);
+void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS);
 
 void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,
                               notifier_fn_t fn);
@@ -350,6 +364,16 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi,
                      void *ctx);
 void nhrp_nhs_interface_del(struct interface *ifp);
 
+int nhrp_multicast_add(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr);
+int nhrp_multicast_del(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr);
+void nhrp_multicast_interface_del(struct interface *ifp);
+void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
+                           void (*cb)(struct nhrp_multicast *, void *),
+                           void *ctx);
+void netlink_mcast_set_nflog_group(int nlgroup);
+
 void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp);
 void nhrp_route_announce(int add, enum nhrp_cache_type type,
                         const struct prefix *p, struct interface *ifp,
index dd65d3cbe104e8746bfc88e97846a32cbca368c8..2b9e07fa6ef5655b32939f0881ee45ddcd961f4d 100644 (file)
@@ -1,7 +1,7 @@
 
 int os_socket(void);
 int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
-              size_t addrlen);
+              size_t addrlen, uint16_t protocol);
 int os_recvmsg(uint8_t *buf, size_t *len, int *ifindex, uint8_t *addr,
               size_t *addrlen);
 int os_configure_dmvpn(unsigned int ifindex, const char *ifname, int af);
index 61b1fe31b2f203ba4293ec8d5b942bf29eb774ab..d00aecc1ead75d4600d8b393f9f92bb2b6bea5f6 100644 (file)
@@ -22,6 +22,7 @@ nhrpd_nhrpd_SOURCES = \
        nhrpd/nhrp_nhs.c \
        nhrpd/nhrp_packet.c \
        nhrpd/nhrp_peer.c \
+       nhrpd/nhrp_multicast.c \
        nhrpd/nhrp_route.c \
        nhrpd/nhrp_shortcut.c \
        nhrpd/nhrp_vc.c \
index 9b117ddf0d91bfa1aac01748c5191d43f8b43f80..c21e01601c14e4bb6ed7c8ed9e3945d3fe5a6454 100644 (file)
@@ -470,16 +470,55 @@ static void vici_register_event(struct vici_conn *vici, const char *name)
        vici_submit(vici, obuf);
 }
 
+static bool vici_charon_filepath_done;
+static bool vici_charon_not_found;
+
+static char *vici_get_charon_filepath(void)
+{
+       static char buff[1200];
+       FILE *fp;
+       char *ptr;
+       char line[1024];
+
+       if (vici_charon_filepath_done)
+               return (char *)buff;
+       fp = popen("ipsec --piddir", "r");
+       if (!fp) {
+               if (!vici_charon_not_found) {
+                       flog_err(EC_NHRP_SWAN,
+                                "VICI: Failed to retrieve charon file path");
+                       vici_charon_not_found = true;
+               }
+               return NULL;
+       }
+       /* last line of output is used to get vici path */
+       while (fgets(line, sizeof(line), fp) != NULL) {
+               ptr = strchr(line, '\n');
+               if (ptr)
+                       *ptr = '\0';
+               snprintf(buff, sizeof(buff), "%s/charon.vici", line);
+       }
+       pclose(fp);
+       vici_charon_filepath_done = true;
+       return buff;
+}
+
 static int vici_reconnect(struct thread *t)
 {
        struct vici_conn *vici = THREAD_ARG(t);
        int fd;
+       char *file_path;
 
        vici->t_reconnect = NULL;
        if (vici->fd >= 0)
                return 0;
 
        fd = sock_open_unix(VICI_SOCKET);
+       if (fd < 0) {
+               file_path = vici_get_charon_filepath();
+               if (file_path)
+                       fd = sock_open_unix(file_path);
+       }
        if (fd < 0) {
                debugf(NHRP_DEBUG_VICI,
                       "%s: failure connecting VICI socket: %s", __func__,
index a23526af484ebaad4031404f660e36ffe0d93482..43ce974817986c52656bdff848e943264f98a6e6 100644 (file)
@@ -27,7 +27,7 @@ struct zbuf *zbuf_alloc(size_t size)
 {
        struct zbuf *zb;
 
-       zb = XMALLOC(MTYPE_ZBUF_DATA, sizeof(*zb) + size);
+       zb = XCALLOC(MTYPE_ZBUF_DATA, sizeof(*zb) + size);
 
        zbuf_init(zb, zb + 1, size, 0);
        zb->allocated = 1;
index e2cd5c259de9cf04305a9fa3aa8796a9ee3fa4ef..52e40dc1ad0fbd50cae433f8b93029e8949a583d 100644 (file)
@@ -814,7 +814,7 @@ DEFUN (no_ospf6_interface_area,
        /* Verify Area */
        if (oi->area == NULL) {
                vty_out(vty, "%s not attached to area %s\n",
-                       oi->interface->name, oi->area->name);
+                       oi->interface->name, argv[idx_ipv4]->arg);
                return CMD_SUCCESS;
        }
 
diff --git a/ospf6d/ospf6d.conf.sample b/ospf6d/ospf6d.conf.sample
deleted file mode 100644 (file)
index 0a6ddb7..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-!
-! Zebra configuration saved from vty
-!   2003/11/28 00:49:49
-!
-hostname ospf6d@plant
-password zebra
-log stdout
-service advanced-vty
-!
-debug ospf6 neighbor state
-!
-interface fxp0
- ipv6 ospf6 cost 1
- ipv6 ospf6 hello-interval 10
- ipv6 ospf6 dead-interval 40
- ipv6 ospf6 retransmit-interval 5
- ipv6 ospf6 priority 0
- ipv6 ospf6 transmit-delay 1
- ipv6 ospf6 instance-id 0
-!
-interface lo0
- ipv6 ospf6 cost 1
- ipv6 ospf6 hello-interval 10
- ipv6 ospf6 dead-interval 40
- ipv6 ospf6 retransmit-interval 5
- ipv6 ospf6 priority 1
- ipv6 ospf6 transmit-delay 1
- ipv6 ospf6 instance-id 0
-!
-router ospf6
- router-id 255.1.1.1
- redistribute static route-map static-ospf6
- interface fxp0 area 0.0.0.0
-!
-access-list access4 permit 127.0.0.1/32
-!
-ipv6 access-list access6 permit 3ffe:501::/32
-ipv6 access-list access6 permit 2001:200::/48
-ipv6 access-list access6 permit ::1/128
-!
-ipv6 prefix-list test-prefix seq 1000 deny any
-!
-route-map static-ospf6 permit 10
- match ipv6 address prefix-list test-prefix
- set metric-type type-2
- set metric 2000
-!
-line vty
- access-class access4
- ipv6 access-class access6
- exec-timeout 0 0
-!
index 788b532a9015c57dc061eb7f371d51b2b01f55c6..5ccae5b27901fcbc2e3a9dbabbb8d7368f23690f 100644 (file)
@@ -5,7 +5,6 @@
 if OSPF6D
 noinst_LIBRARIES += ospf6d/libospf6.a
 sbin_PROGRAMS += ospf6d/ospf6d
-dist_examples_DATA += ospf6d/ospf6d.conf.sample
 vtysh_scan += \
        ospf6d/ospf6_abr.c \
        ospf6d/ospf6_asbr.c \
index 2442f2e781c73030e00d47f3bd37e1490caea057..8f31f90346effa1f9b0654406f4abb1247b917e8 100644 (file)
@@ -169,8 +169,7 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
 /* Making formatted timer strings. */
 #define MINUTE_IN_SECONDS      60
 #define HOUR_IN_SECONDS                (60*MINUTE_IN_SECONDS)
-#define DAY_IN_SECONDS         (24*HOUR_IN_SECONDS)
-#define WEEK_IN_SECONDS                (7*DAY_IN_SECONDS)
+
        unsigned long w, d, h, m, ms, us;
 
        if (!t)
@@ -191,14 +190,14 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
                ms %= 1000;
        }
 
-       if (t->tv_sec > WEEK_IN_SECONDS) {
-               w = t->tv_sec / WEEK_IN_SECONDS;
-               t->tv_sec -= w * WEEK_IN_SECONDS;
+       if (t->tv_sec > ONE_WEEK_SECOND) {
+               w = t->tv_sec / ONE_WEEK_SECOND;
+               t->tv_sec -= w * ONE_WEEK_SECOND;
        }
 
-       if (t->tv_sec > DAY_IN_SECONDS) {
-               d = t->tv_sec / DAY_IN_SECONDS;
-               t->tv_sec -= d * DAY_IN_SECONDS;
+       if (t->tv_sec > ONE_DAY_SECOND) {
+               d = t->tv_sec / ONE_DAY_SECOND;
+               t->tv_sec -= d * ONE_DAY_SECOND;
        }
 
        if (t->tv_sec >= HOUR_IN_SECONDS) {
@@ -221,7 +220,7 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
                snprintf(buf, size, "%luh%02lum%02lds", h, m, (long)t->tv_sec);
        else if (m)
                snprintf(buf, size, "%lum%02lds", m, (long)t->tv_sec);
-       else if (ms)
+       else if (t->tv_sec > 0 || ms > 0)
                snprintf(buf, size, "%ld.%03lus", (long)t->tv_sec, ms);
        else
                snprintf(buf, size, "%ld usecs", (long)t->tv_usec);
index 6e4bc7abf1e092ddbc7a28e2ed42f9312dd53bdb..334ed33ee0ed587916d82e127840b901c2998072 100644 (file)
@@ -543,6 +543,8 @@ static struct ospf_if_params *ospf_new_if_params(void)
        oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
        oip->is_v_wait_set = false;
 
+       oip->ptp_dmvpn = 0;
+
        return oip;
 }
 
index e2d732738169a2032330419532011c19c7be13f6..4a211472468a256d16b5c70515fbe209556228e8 100644 (file)
@@ -118,6 +118,9 @@ struct ospf_if_params {
 
        /* MPLS LDP-IGP Sync configuration */
        struct ldp_sync_info *ldp_sync_info;
+
+       /* point-to-point DMVPN configuration */
+       uint8_t ptp_dmvpn;
 };
 
 enum { MEMBER_ALLROUTERS = 0,
@@ -180,6 +183,9 @@ struct ospf_interface {
        /* OSPF Network Type. */
        uint8_t type;
 
+       /* point-to-point DMVPN configuration */
+       uint8_t ptp_dmvpn;
+
        /* State of Interface State Machine. */
        uint8_t state;
 
index cb1c565d3770f73469ad626e03936985375b3969..6e9df77fb879db8fb5099cfcdac9cc930a901a69 100644 (file)
@@ -469,6 +469,12 @@ char link_info_set(struct stream **s, struct in_addr id, struct in_addr data,
 }
 
 /* Describe Point-to-Point link (Section 12.4.1.1). */
+
+/* Note: If the interface is configured as point-to-point dmvpn then the other
+ * end of link is dmvpn hub with point-to-multipoint ospf network type. The
+ * hub then expects this router to populate the stub network and also Link Data
+ * Field set to IP Address and not MIB-II ifIndex
+ */
 static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
 {
        int links = 0;
@@ -482,7 +488,8 @@ static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
        if ((nbr = ospf_nbr_lookup_ptop(oi)))
                if (nbr->state == NSM_Full) {
                        if (CHECK_FLAG(oi->connected->flags,
-                                      ZEBRA_IFA_UNNUMBERED)) {
+                                      ZEBRA_IFA_UNNUMBERED)
+                           && !oi->ptp_dmvpn) {
                                /* For unnumbered point-to-point networks, the
                                   Link Data field
                                   should specify the interface's MIB-II ifIndex
@@ -500,7 +507,8 @@ static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
                }
 
        /* no need for a stub link for unnumbered interfaces */
-       if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
+       if (oi->ptp_dmvpn
+           || !CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
                /* Regardless of the state of the neighboring router, we must
                   add a Type 3 link (stub network).
                   N.B. Options 1 & 2 share basically the same logic. */
index 0fd4803c7993efe57e25136834b2168dc25c3d46..aa98d7dd285f51b884bbce74384e3fd05f85630e 100644 (file)
@@ -799,7 +799,13 @@ static int ospf_write(struct thread *thread)
                                &iph.ip_dst, iph.ip_id, iph.ip_off,
                                iph.ip_len, oi->ifp->name, oi->ifp->mtu);
 
-               if (ret < 0)
+               /* sendmsg will return EPERM if firewall is blocking sending.
+                * This is a normal situation when 'ip nhrp map multicast xxx'
+                * is being used to send multicast packets to DMVPN peers. In
+                * that case the original message is blocked with iptables rule
+                * causing the EPERM result
+                */
+               if (ret < 0 && errno != EPERM)
                        flog_err(
                                EC_LIB_SOCKET,
                                "*** sendmsg in ospf_write failed to %pI4, id %d, off %d, len %d, interface %s, mtu %u: %s",
@@ -907,8 +913,11 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh,
 
        /* Compare network mask. */
        /* Checking is ignored for Point-to-Point and Virtual link. */
+       /* Checking is also ignored for Point-to-Multipoint with /32 prefix */
        if (oi->type != OSPF_IFTYPE_POINTOPOINT
-           && oi->type != OSPF_IFTYPE_VIRTUALLINK)
+           && oi->type != OSPF_IFTYPE_VIRTUALLINK
+           && !(oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
+                && oi->address->prefixlen == IPV4_MAX_BITLEN))
                if (oi->address->prefixlen != p.prefixlen) {
                        flog_warn(
                                EC_OSPF_PACKET,
@@ -2427,6 +2436,11 @@ static int ospf_check_network_mask(struct ospf_interface *oi,
            || oi->type == OSPF_IFTYPE_VIRTUALLINK)
                return 1;
 
+       /* Ignore mask check for max prefix length (32) */
+       if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
+           && oi->address->prefixlen == IPV4_MAX_BITLEN)
+               return 1;
+
        masklen2ip(oi->address->prefixlen, &mask);
 
        me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
index 95553dacdfdf064785b4e610e01ce1bf7a4dfe80..0164bfac678dc490520e1e7544825f1c301c9c46 100644 (file)
@@ -905,7 +905,9 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
                                 * somehow.
                                 */
                                if (area->ospf->ti_lfa_enabled
-                                   || (oi && oi->type == OSPF_IFTYPE_POINTOPOINT)) {
+                                   || (oi && oi->type == OSPF_IFTYPE_POINTOPOINT)
+                                   || (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
+                                          && oi->address->prefixlen == IPV4_MAX_BITLEN)) {
                                        struct ospf_neighbor *nbr_w = NULL;
 
                                        /* Calculating node is root node, link
index 8d6176fd37ae70c61daa32536ff3ce3d97343918..69a3e45878ba5b3c0aff779231c2a56affec1179 100644 (file)
@@ -8392,6 +8392,7 @@ DEFUN (no_ip_ospf_hello_interval,
                        continue;
 
                oi->type = IF_DEF_PARAMS(ifp)->type;
+               oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
 
                if (oi->state > ISM_Down) {
                        OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
@@ -8419,20 +8420,21 @@ DEFUN_HIDDEN (no_ospf_hello_interval,
        return no_ip_ospf_hello_interval(self, vty, argc, argv);
 }
 
-DEFUN (ip_ospf_network,
-       ip_ospf_network_cmd,
-       "ip ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point>",
-       "IP Information\n"
-       "OSPF interface commands\n"
-       "Network type\n"
-       "Specify OSPF broadcast multi-access network\n"
-       "Specify OSPF NBMA network\n"
-       "Specify OSPF point-to-multipoint network\n"
-       "Specify OSPF point-to-point network\n")
+DEFUN(ip_ospf_network, ip_ospf_network_cmd,
+      "ip ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn]>",
+      "IP Information\n"
+      "OSPF interface commands\n"
+      "Network type\n"
+      "Specify OSPF broadcast multi-access network\n"
+      "Specify OSPF NBMA network\n"
+      "Specify OSPF point-to-multipoint network\n"
+      "Specify OSPF point-to-point network\n"
+      "Specify OSPF point-to-point DMVPN network\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx = 0;
        int old_type = IF_DEF_PARAMS(ifp)->type;
+       uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
        struct route_node *rn;
 
        if (old_type == OSPF_IFTYPE_LOOPBACK) {
@@ -8441,16 +8443,22 @@ DEFUN (ip_ospf_network,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
+       IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
+
        if (argv_find(argv, argc, "broadcast", &idx))
                IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST;
        else if (argv_find(argv, argc, "non-broadcast", &idx))
                IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
        else if (argv_find(argv, argc, "point-to-multipoint", &idx))
                IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
-       else if (argv_find(argv, argc, "point-to-point", &idx))
+       else if (argv_find(argv, argc, "point-to-point", &idx)) {
                IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
+               if (argv_find(argv, argc, "dmvpn", &idx))
+                       IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
+       }
 
-       if (IF_DEF_PARAMS(ifp)->type == old_type)
+       if (IF_DEF_PARAMS(ifp)->type == old_type
+           && IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn)
                return CMD_SUCCESS;
 
        SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
@@ -8502,6 +8510,7 @@ DEFUN (no_ip_ospf_network,
        struct route_node *rn;
 
        IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
+       IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
 
        if (IF_DEF_PARAMS(ifp)->type == old_type)
                return CMD_SUCCESS;
@@ -11644,6 +11653,10 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
                                        vty_out(vty, " ip ospf network %s",
                                                ospf_int_type_str
                                                        [params->type]);
+                                       if (params->type
+                                                   == OSPF_IFTYPE_POINTOPOINT
+                                           && params->ptp_dmvpn)
+                                               vty_out(vty, " dmvpn");
                                        if (params != IF_DEF_PARAMS(ifp) && rn)
                                                vty_out(vty, " %pI4",
                                                        &rn->p.u.prefix4);
@@ -11711,6 +11724,7 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
 
                        /* Router Dead Interval print. */
                        if (OSPF_IF_PARAM_CONFIGURED(params, v_wait)
+                           && params->is_v_wait_set
                            && params->v_wait
                                       != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT) {
                                vty_out(vty, " ip ospf dead-interval ");
index b455d0b411f72196733b5e030dd9c4f024ffa91c..faec868b2aeeca08fb178111fdf74b05eb456b59 100644 (file)
@@ -1077,6 +1077,7 @@ struct ospf_interface *add_ospf_interface(struct connected *co,
        /* If network type is specified previously,
           skip network type setting. */
        oi->type = IF_DEF_PARAMS(co->ifp)->type;
+       oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
 
        /* Add pseudo neighbor. */
        ospf_nbr_self_reset(oi, oi->ospf->router_id);
diff --git a/ospfd/ospfd.conf.sample b/ospfd/ospfd.conf.sample
deleted file mode 100644 (file)
index 0e8ac67..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-! -*- ospf -*-
-!
-! OSPFd sample configuration file
-!
-!
-hostname ospfd
-password zebra
-!enable password please-set-at-here
-!
-!router ospf
-!  network 192.168.1.0/24 area 0
-!
-log stdout
index 63610e38d8d980bd3e5fb4713596b90e681ed52e..f592a9eec8d659a04c6db0a3bef9dc1a095cf1c5 100644 (file)
@@ -5,7 +5,6 @@
 if OSPFD
 noinst_LIBRARIES += ospfd/libfrrospf.a
 sbin_PROGRAMS += ospfd/ospfd
-dist_examples_DATA += ospfd/ospfd.conf.sample
 vtysh_scan += \
        ospfd/ospf_bfd.c \
        ospfd/ospf_dump.c \
diff --git a/pathd/pathd.conf.sample b/pathd/pathd.conf.sample
deleted file mode 100644 (file)
index 9fe7d2d..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-! Default pathd configuration sample
-!
-password frr
-log stdout
-
-segment-routing
- traffic-eng
-  segment-list test1
-   index 10 mpls label 123
-   index 20 mpls label 456
-  !
-  segment-list test2
-   index 10 mpls label 321
-   index 20 mpls label 654
-  !
-  policy color 1 endpoint 1.1.1.1
-   name one
-   binding-sid 100
-   candidate-path preference 100 name test1 explicit segment-list test1
-   candidate-path preference 200 name test2 explicit segment-list test2
-  !
-  policy color 2 endpoint 2.2.2.2
-   name two
-   binding-sid 101
-   candidate-path preference 100 name def explicit segment-list test2
-   candidate-path preference 200 name dyn dynamic
-    bandwidth 12345
-    metric bound abc 16 required
-    metric te 10
-   !
-  !
-  pcep
-   pcc-peer PCE1
-    address ip 127.0.0.1
-    sr-draft07
-   !
-   pcc
-    peer PCE1
-   !
- !
-!
index fdc08e9e97fab7246808f24b8a39fe44f80e311a..4eabdd2ac54fd8bc2a3da7d404a7497474a04b59 100644 (file)
@@ -5,14 +5,13 @@
 if PATHD
 noinst_LIBRARIES += pathd/libpath.a
 sbin_PROGRAMS += pathd/pathd
-dist_examples_DATA += pathd/pathd.conf.sample
-vtysh_scan += $(top_srcdir)/pathd/path_cli.c
+vtysh_scan += pathd/path_cli.c
 vtysh_daemons += pathd
 # TODO add man page
 #man8 += $(MANBUILD)/pathd.8
 
 if PATHD_PCEP
-vtysh_scan += $(top_srcdir)/pathd/path_pcep_cli.c
+vtysh_scan += pathd/path_pcep_cli.c
 module_LTLIBRARIES += pathd/pathd_pcep.la
 endif
 
diff --git a/pbrd/pbrd.conf.sample b/pbrd/pbrd.conf.sample
deleted file mode 100644 (file)
index c9e7dce..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-! Sample pbrd configuration file
-!
-! A quick example of what a pbr configuration might look like
-!
-!
-log stdout
-!
-! nexthop-group TEST
-!   nexthop 4.5.6.7
-!   nexthop 5.6.7.8
-! !
-! pbr-map BLUE seq 100
-!   match dst-ip 9.9.9.0/24
-!   match src-ip 10.10.10.0/24
-!   set nexthop-group TEST
-! !
-! int swp1
-!   pbr-policy BLUE
-!
index 7ad071af3b659b3b8ef824ec74d7b18384aee39d..bbe3f2ab71dffcf45191db0f53b44e825c4b3b7d 100644 (file)
@@ -5,7 +5,6 @@
 if PBRD
 noinst_LIBRARIES += pbrd/libpbr.a
 sbin_PROGRAMS += pbrd/pbrd
-dist_examples_DATA += pbrd/pbrd.conf.sample
 vtysh_scan += \
        pbrd/pbr_vty.c \
        pbrd/pbr_debug.c \
diff --git a/pimd/pimd.conf.sample b/pimd/pimd.conf.sample
deleted file mode 100644 (file)
index de1da6b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-!
-! pimd sample configuration file
-!
-hostname quagga-pimd-router
-password zebra
-!enable password zebra
-!
-!log file pimd.log
-log stdout
-!
-line vty
- exec-timeout 60
-!
-!debug igmp
-!debug pim
-!debug pim zebra
-!
-ip multicast-routing
-!
-! ! You may want to enable ssmpingd for troubleshooting
-! ! See http://www.venaas.no/multicast/ssmping/
-! !
-! ip ssmpingd 1.1.1.1
-! ip ssmpingd 2.2.2.2
-!
-! ! HINTS:
-! !  - Enable "ip pim ssm" on the interface directly attached to the
-! !    multicast source host (if this is the first-hop router)
-! !  - Enable "ip pim ssm" on pim-routers-facing interfaces
-! !  - Enable "ip igmp" on IGMPv3-hosts-facing interfaces
-! !  - In order to inject IGMPv3 local membership information in the
-! !    PIM protocol state, enable both "ip pim ssm" and "ip igmp" on
-! !    the same interface; otherwise PIM won't advertise
-! !    IGMPv3-learned membership to other PIM routers
-!
-interface eth0
- ip pim ssm
- ip igmp
-
-! -x-
index 717f4782f8bc3ca40454050d4445a0f0eae89410..9910642ffa40a97c8eecbf23a5d6854b9a4c0f23 100644 (file)
@@ -7,7 +7,6 @@ noinst_LIBRARIES += pimd/libpim.a
 sbin_PROGRAMS += pimd/pimd
 bin_PROGRAMS += pimd/mtracebis
 noinst_PROGRAMS += pimd/test_igmpv3_join
-dist_examples_DATA += pimd/pimd.conf.sample
 vtysh_scan += pimd/pim_cmd.c
 vtysh_daemons += pimd
 man8 += $(MANBUILD)/frr-pimd.8
diff --git a/python/vtysh-cmd-check.py b/python/vtysh-cmd-check.py
new file mode 100644 (file)
index 0000000..ef9eea4
--- /dev/null
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+#
+# Quick demo program that checks whether files define commands that aren't
+# in vtysh.  Execute after building.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# For more information, please refer to <http://unlicense.org/>
+
+import os
+import json
+import subprocess
+
+os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+with open("frr.xref", "r") as fd:
+    data = json.load(fd)
+
+vtysh_scan, _ = subprocess.Popen(
+    ["make", "var-vtysh_scan"], stdout=subprocess.PIPE
+).communicate()
+vtysh_scan = set(vtysh_scan.decode("US-ASCII").split())
+
+check = set()
+vtysh = {}
+
+for cmd, defs in data["cli"].items():
+    for binary, clidef in defs.items():
+        if clidef["defun"]["file"].startswith("vtysh/"):
+            vtysh[clidef["string"]] = clidef
+
+for cmd, defs in data["cli"].items():
+    for binary, clidef in defs.items():
+        if clidef["defun"]["file"].startswith("vtysh/"):
+            continue
+
+        if clidef["defun"]["file"] not in vtysh_scan:
+            vtysh_def = vtysh.get(clidef["string"])
+            if vtysh_def is not None:
+                print(
+                    "\033[33m%s defines %s, has a custom define in vtysh %s\033[m"
+                    % (clidef["defun"]["file"], cmd, vtysh_def["defun"]["file"])
+                )
+            else:
+                print(
+                    "\033[31m%s defines %s, not in vtysh_scan\033[m"
+                    % (clidef["defun"]["file"], cmd)
+                )
+                check.add(clidef["defun"]["file"])
+
+print("\nfiles to check:\n\t" + " ".join(sorted(check)))
index b6d7ab2416adf399e7c0a4fd7e92f8708b42cc8e..47c6ad41afb71fbcc939c449144e47aa7f2dfa8b 100644 (file)
@@ -456,6 +456,7 @@ ln -s %{_sbindir}/frrinit.sh %{buildroot}%{_initddir}/frr
 %endif
 
 install %{zeb_src}/tools/etc/frr/daemons %{buildroot}%{_sysconfdir}/frr
+install %{zeb_src}/tools/etc/frr/frr.conf %{buildroot}%{_sysconfdir}/frr
 install -m644 %{zeb_rh_src}/frr.pam %{buildroot}%{_sysconfdir}/pam.d/frr
 install -m644 %{zeb_rh_src}/frr.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/frr
 install -d -m750 %{buildroot}%{rundir}
@@ -641,7 +642,7 @@ fi
 
 
 %files
-%doc */*.sample* COPYING
+%doc COPYING
 %doc doc/mpls
 %doc README.md
 /usr/share/yang/*.yang
@@ -654,9 +655,6 @@ fi
     %dir %attr(750,root,root) %{_localstatedir}/log/frr
     %dir %attr(750,root,root) %{rundir}
 %endif
-%if 0%{?vty_group:1}
-    %attr(750,%{frr_user},%{vty_group}) %{configdir}/vtysh.conf.sample
-%endif
 %{_infodir}/frr.info.gz
 %{_mandir}/man*/*
 %{_sbindir}/zebra
diff --git a/ripd/ripd.conf.sample b/ripd/ripd.conf.sample
deleted file mode 100644 (file)
index e11bf0b..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-! -*- rip -*-
-!
-! RIPd sample configuration file
-!
-hostname ripd
-password zebra
-!
-! debug rip events
-! debug rip packet
-!
-router rip
-! network 11.0.0.0/8
-! network eth0
-! route 10.0.0.0/8
-! distribute-list private-only in eth0
-!
-!access-list private-only permit 10.0.0.0/8
-!access-list private-only deny any
-! 
-!log file ripd.log
-!
-log stdout
index 09d5590329e00aa82db7dea72055180dab66ce6e..99979bff0dd2d1d6eec75a4aa8d6b44e8bbc2190 100644 (file)
@@ -5,7 +5,6 @@
 if RIPD
 noinst_LIBRARIES += ripd/librip.a
 sbin_PROGRAMS += ripd/ripd
-dist_examples_DATA += ripd/ripd.conf.sample
 vtysh_scan += \
        ripd/rip_cli.c \
        ripd/rip_debug.c \
diff --git a/ripngd/ripngd.conf.sample b/ripngd/ripngd.conf.sample
deleted file mode 100644 (file)
index 28f08c3..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-! -*- rip -*-
-!
-! RIPngd sample configuration file
-!
-hostname ripngd
-password zebra
-!
-! debug ripng events
-! debug ripng packet
-!
-!
-router ripng
-! network sit1
-! route 3ffe:506::0/32
-! distribute-list local-only out sit1
-!
-!ipv6 access-list local-only permit 3ffe:506::0/32
-!ipv6 access-list local-only deny any
-!
-log stdout
index 8d370f1b5d5440201f59d2ae071d294074f2cfa5..9d8d27d4ccbc890ea0c660828757ad3ed3781a03 100644 (file)
@@ -50,5 +50,3 @@ ripngd_ripngd_SOURCES = \
 nodist_ripngd_ripngd_SOURCES = \
        yang/frr-ripngd.yang.c \
        # end
-
-dist_examples_DATA += ripngd/ripngd.conf.sample
diff --git a/sharpd/sharpd.conf.sample b/sharpd/sharpd.conf.sample
deleted file mode 100644 (file)
index d1cc19a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-! Default sharpd configuration sample
-!
-! There are no `default` configuration commands for sharpd
-! all commands are at the view or enable level.
-!
-log stdout
index d161eb6327a4e391b0e6c24c7b5a21dcfdea902b..acf4fe5d0079f269823155b5af8909f035e24bfd 100644 (file)
@@ -5,7 +5,6 @@
 if SHARPD
 noinst_LIBRARIES += sharpd/libsharp.a
 sbin_PROGRAMS += sharpd/sharpd
-dist_examples_DATA += sharpd/sharpd.conf.sample
 vtysh_scan += sharpd/sharp_vty.c
 vtysh_daemons += sharpd
 man8 += $(MANBUILD)/frr-sharpd.8
diff --git a/staticd/staticd.conf.sample b/staticd/staticd.conf.sample
deleted file mode 100644 (file)
index 3b64eb9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-! Default staticd configuration sample
-!
-log stdout
-!
-! ip route 4.5.6.7/32 10.10.10.10
index a0ae2569cbf65e30ba4dca30e239306d78a0615c..62969a0a2a7c766756f0e6a0c1084afb53fb713b 100644 (file)
@@ -5,7 +5,6 @@
 if STATICD
 noinst_LIBRARIES += staticd/libstatic.a
 sbin_PROGRAMS += staticd/staticd
-dist_examples_DATA += staticd/staticd.conf.sample
 vtysh_scan += staticd/static_vty.c
 vtysh_daemons += staticd
 man8 += $(MANBUILD)/frr-staticd.8
index 6cc23a465c8bdb9ff8b0d5fc7f47e82efa46587f..b38701a53d94a2029b4e066795249940f87cf35b 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *> 192.168.0.0      0.0.0.0                  0         32768 i
index 2f348a7b77cc8610b337cfed670a4b26080211e1..82b64c0d98d8fa51c26502d8e136927a927025ed 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *> 192.168.0.0/24   0.0.0.0                  0         32768 i
index d36d04539790bfe8a2ad5e38127f8a6747973aba..fd333b3084cc96a102c00e1504c20505b5f2aa90 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *> 192.168.0.0/24   0.0.0.0                  0         32768 i
index 8bb5da72be11b811aadab92145f67718887302c6..20034b7408826a4632868e0dbdf93a681f2c6573 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *> fc00::/64        ::                       0         32768 i
index de91b247d86b31c99221b199a44a4334bd852cdc..5b5f8596cfa1f39a01a0b934f1830068232248e1 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *> fc00::/64        ::                       0         32768 i
index b70626fcce250ea83843dda768fc0621039e49fb..524da05875c13fed6cd82d6cd4a2ab23ef32506e 100644 (file)
@@ -287,272 +287,6 @@ def next_hop_per_address_family(
     return next_hop
 
 
-def test_BGP_GR_TC_46_p1(request):
-    """
-    Test Objective : transition from Peer-level helper to Global Restarting
-    Global Mode : GR Restarting
-    PerPeer Mode :  GR Helper
-    GR Mode effective : GR Helper
-
-    """
-
-    tgen = get_topogen()
-    tc_name = request.node.name
-    write_test_header(tc_name)
-
-    # Check router status
-    check_router_status(tgen)
-
-    # Don't run this test if we have any failure.
-    if tgen.routers_have_failure():
-        pytest.skip(tgen.errors)
-
-    # Creating configuration from JSON
-    reset_config_on_routers(tgen)
-
-    step(
-        "Configure R1 and R2 as GR restarting node in global"
-        " and helper in per-Peer-level"
-    )
-
-    input_dict = {
-        "r1": {
-            "bgp": {
-                "graceful-restart": {
-                    "graceful-restart": True,
-                },
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                },
-            }
-        },
-        "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
-    }
-
-    configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
-    step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    step("Kill BGP on R2")
-
-    kill_router_daemons(tgen, "r2", ["bgpd"])
-
-    step(
-        "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using"
-    )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    step(
-        "Bring up BGP on R1 and remove Peer-level GR config"
-        " from R1 following by a session reset"
-    )
-
-    start_router_daemons(tgen, "r2", ["bgpd"])
-
-    input_dict = {
-        "r1": {
-            "bgp": {
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": False}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": False}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                }
-            }
-        }
-    }
-
-    result = create_router_bgp(tgen, topo, input_dict)
-    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
-    step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
-    input_dict = {
-        "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
-        "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
-    }
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    step("Kill BGP on R1")
-
-    kill_router_daemons(tgen, "r1", ["bgpd"])
-
-    step(
-        "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB"
-    )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    step("Start BGP on R1")
-
-    start_router_daemons(tgen, "r1", ["bgpd"])
-
-    write_test_footer(tc_name)
-
-
 def BGP_GR_TC_50_p1(request):
     """
     Test Objective : Transition from Peer-level helper to Global inherit helper
@@ -1979,198 +1713,6 @@ def test_BGP_GR_TC_8_p1(request):
     write_test_footer(tc_name)
 
 
-def test_BGP_GR_TC_17_p1(request):
-    """
-    Test Objective : Verify that only GR helper routers keep the stale
-     route entries, not any GR disabled router.
-    """
-
-    tgen = get_topogen()
-    tc_name = request.node.name
-    write_test_header(tc_name)
-
-    # Check router status
-    check_router_status(tgen)
-
-    # Don't run this test if we have any failure.
-    if tgen.routers_have_failure():
-        pytest.skip(tgen.errors)
-
-    # Creating configuration from JSON
-    reset_config_on_routers(tgen)
-
-    logger.info("[Phase 1] : Test Setup [Disable]R1-----R2[Restart] initialized  ")
-
-    # Configure graceful-restart
-    input_dict = {
-        "r1": {
-            "bgp": {
-                "graceful-restart": {
-                    "graceful-restart": True,
-                    "preserve-fw-state": True,
-                },
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-disable": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-disable": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                },
-            }
-        },
-        "r2": {
-            "bgp": {
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r1": {
-                                    "dest_link": {
-                                        "r2-link1": {"graceful-restart": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r1": {
-                                    "dest_link": {
-                                        "r2-link1": {"graceful-restart": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                }
-            }
-        },
-    }
-
-    configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        # Verifying BGP RIB routes
-        dut = "r1"
-        peer = "r2"
-        next_hop = next_hop_per_address_family(
-            tgen, dut, peer, addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {key: topo["routers"][key] for key in ["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        # Verifying RIB routes
-        protocol = "bgp"
-        result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    logger.info("[Phase 2] : R2 goes for reload  ")
-
-    kill_router_daemons(tgen, "r2", ["bgpd"])
-
-    logger.info(
-        "[Phase 3] : R2 is still down, restart time 120 sec."
-        " So time verify the routes are present in BGP RIB and ZEBRA  "
-    )
-
-    for addr_type in ADDR_TYPES:
-        # Verifying BGP RIB routes
-        next_hop = next_hop_per_address_family(
-            tgen, dut, peer, addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {key: topo["routers"][key] for key in ["r2"]}
-        result = verify_bgp_rib(
-            tgen, addr_type, dut, input_topo, next_hop, expected=False
-        )
-        assert result is not True, (
-            "Testcase {} : Failed \n "
-            "r1: routes are still present in BGP RIB\n Error: {}".format(
-                tc_name, result
-            )
-        )
-        logger.info(" Expected behavior: {}".format(result))
-
-        # Verifying RIB routes
-        result = verify_rib(
-            tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
-        )
-        assert result is not True, (
-            "Testcase {} : Failed \n "
-            "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
-        )
-        logger.info(" Expected behavior: {}".format(result))
-
-    logger.info("[Phase 5] : R2 is about to come up now  ")
-    start_router_daemons(tgen, "r2", ["bgpd"])
-
-    logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats  ")
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_r_bit(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
-        )
-        assert (
-            result is not True
-        ), "Testcase {} : Failed \n " "r1: R-bit is set to True\n Error: {}".format(
-            tc_name, result
-        )
-
-        # Verifying BGP RIB routes
-        next_hop = next_hop_per_address_family(
-            tgen, dut, peer, addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {key: topo["routers"][key] for key in ["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        # Verifying RIB routes
-        result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    write_test_footer(tc_name)
-
-
 def test_BGP_GR_TC_19_p1(request):
     """
     Test Objective : Verify that GR helper routers keeps all the routes received
index cd845be29641256958eb92e92f176577c751997d..0df2c9cb5a31b0f769b224416f96832c6bfacc4f 100644 (file)
@@ -112,7 +112,7 @@ def test_protocols_convergence():
         test_func = partial(
             topotest.router_json_cmp,
             router,
-            "show ip route json".format(router.name),
+            "show ip route json",
             expected,
         )
         _, result = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
@@ -131,7 +131,7 @@ def test_protocols_convergence():
         test_func = partial(
             topotest.router_json_cmp,
             router,
-            "show ipv6 route json".format(router.name),
+            "show ipv6 route json",
             expected,
         )
         _, result = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
index 5ecaee2ecebb67b5fb8cab4e208a2590550b6a7c..1b62d986bd3b40ab2665f2e25c6e4e6d8c58d5a9 100644 (file)
@@ -2677,14 +2677,12 @@ def test_route_map_within_vrf_to_alter_bgp_attribute_nexthop_p0(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because"
-        " nexthop-self config is deleted \n Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because nexthop-self config is deleted \n Error {}".format(tc_name, result)
 
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because"
-        " nexthop-self config is deleted \n Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because nexthop-self config is deleted \n Error {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
@@ -4958,8 +4956,7 @@ def test_prefix_list_to_permit_deny_prefixes_p0(request):
 
         result = verify_rib(tgen, addr_type, dut, denied_routes, expected=False)
         assert result is not True, "Testcase {} : Failed \n"
-        "Expected behaviour: Routes are denied by prefix-list \n"
-        "Error {}".format(tc_name, result)
+        "{}:Expected behaviour: Routes are denied by prefix-list \nError {}".format(tc_name, result)
 
     step(
         "On router R1, configure prefix-lists to permit 2 "
@@ -5169,9 +5166,7 @@ def test_prefix_list_to_permit_deny_prefixes_p0(request):
         )
 
         result = verify_rib(tgen, addr_type, dut, denied_routes, expected=False)
-        assert result is not True, "Testcase {} : Failed \n"
-        "Expected behaviour: Routes are denied by prefix-list \n"
-        "Error {}".format(tc_name, result)
+        assert result is not True, "Testcase {} : Failed \nExpected behaviour: Routes are denied by prefix-list \nError {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
@@ -5449,8 +5444,7 @@ def test_route_map_set_and_match_tag_p0(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \n"
-        "Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \nError {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
@@ -5853,8 +5847,7 @@ def test_route_map_set_and_match_metric_p0(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \n"
-        "Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \nError {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
index c8d13301225aecf82a9613567da1fbb723c4f070..90356ec173be15cb9815935b114917bf8b7c1dd9 100644 (file)
@@ -1571,9 +1571,7 @@ def test_shut_noshut_p1(request):
         sleep(HOLDDOWNTIMER + 1)
 
         result = verify_bgp_convergence(tgen, topo, expected=False)
-        assert result is not True, "Testcase {} : Failed \n "
-        "Expected Behaviour: BGP will not be converged \n "
-        "Error {}".format(tc_name, result)
+        assert result is not True, "Testcase {} : Failed \nExpected Behaviour: BGP will not be converged \nError {}".format(tc_name, result)
 
         for addr_type in ADDR_TYPES:
             dut = "r2"
@@ -1616,14 +1614,10 @@ def test_shut_noshut_p1(request):
             }
 
             result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
-            assert result is not True, "Testcase {} : Failed \n "
-            " Expected Behaviour: Routes are flushed out \n "
-            "Error {}".format(tc_name, result)
+            assert result is not True, "Testcase {} : Failed \nExpected Behaviour: Routes are flushed out \nError {}".format(tc_name, result)
 
             result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
-            assert result is not True, "Testcase {} : Failed \n "
-            " Expected Behaviour: Routes are flushed out \n "
-            "Error {}".format(tc_name, result)
+            assert result is not True, "Testcase {} : Failed \nExpected Behaviour: Routes are flushed out \nError {}".format(tc_name, result)
 
         step("Bring up connecting interface between R1<<>>R2 on R1.")
         for intf in interfaces:
@@ -1862,8 +1856,7 @@ def test_vrf_vlan_routing_table_p1(request):
             result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
             assert (
                 result is not True
-            ), "Testcase {} : Failed \n Expected Behaviour: Routes are"
-            " cleaned \n Error {}".format(tc_name, result)
+            ), "Testcase {} : Failed \n Expected Behaviour: Routes are cleaned \n Error {}".format(tc_name, result)
 
         step("Add/reconfigure the same VRF instance again")
 
@@ -2180,7 +2173,7 @@ def test_restart_bgpd_daemon_p1(request):
     assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
 
     result = verify_bgp_convergence(tgen, topo)
-    assert result is True, "Testcase () :Failed\n Error {}".format(tc_name, result)
+    assert result is True, "Testcase {} :Failed\n Error {}".format(tc_name, result)
 
     step("Kill BGPd daemon on R1.")
     kill_router_daemons(tgen, "r1", ["bgpd"])
@@ -3392,14 +3385,12 @@ def test_vrf_name_significance_p1(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
         assert (
             result is not True
-        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-        " present \n Error {}".format(tc_name, result)
+        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
 
         result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
         assert (
             result is not True
-        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-        " present \n Error {}".format(tc_name, result)
+        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
 
     for addr_type in ADDR_TYPES:
         dut = "blue2"
@@ -3417,14 +3408,12 @@ def test_vrf_name_significance_p1(request):
 
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert result is not True, (
-            "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-            " present \n Error {}".format(tc_name, result)
+            "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
         )
 
         result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert result is not True, (
-            "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-            " present \n Error {}".format(tc_name, result)
+            "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
         )
 
     step("Create 2 new VRFs PINK_A and GREY_A IN R3")
index 9e30bf2ef09203c7e056b18c1a1cfe89d6df5beb..6b20e1df5a3401badf2810f60f57c9264a48b1e3 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *  10.0.1.0/24      172.16.1.5                             0 65005 i
index 2cf87487abdc6a6bfe44f79913885b6e804dde02..5469eaa1cc070ae4f21ba58bb80ca6c9833215ac 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *  10.0.1.0/24      172.16.1.5                             0 65005 i
index 39eb3134bed4e95e1cd32096d049c224659ee6f0..a64927c92d7f4a7944928a7a105d7a88e3e38dbe 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *  10.0.1.0/24      172.16.1.4                             0 65004 i
index 9d1b948b5cf04eac60b4635bbbad8bab361850d4..8d4a843b843d44935d4a9d0112b1cb621eb3b505 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *  10.0.1.0/24      172.16.1.4                             0 65004 i
index fa53d79e8814c44063ec55f34c9fd03db50def77..a3b9ef0888998b4eb50455bf9a55acf636f90a4e 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *  10.0.1.0/24      172.16.1.8                             0 65008 i
index 8b66fa67ec32c35b7381d7735bd5ed9a00af5448..117e48847ae5ed92f72c9c1926f7103156bf3472 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                i internal, r RIB-failure, S Stale, R Removed
 Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
 Origin codes:  i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
 
    Network          Next Hop            Metric LocPrf Weight Path
 *  10.0.1.0/24      172.16.1.8                             0 65008 i
index 291a6e7c3a9f2d64eeabba71f0fd8771236d3d53..83682fb36d37460117be33cec49bea9b49dac16a 100644 (file)
@@ -224,6 +224,7 @@ def disable_route_map_to_prefer_global_next_hop(tgen, topo):
 
     """
 
+    tc_name = request.node.name
     logger.info("Remove prefer-global rmap applied on neighbors")
     input_dict = {
         "r1": {
index d2212d180756f36aafc3f0fe58b226cf3946c145..50cb586acdfef0642c7b70c8a4a61bf0b58534b1 100644 (file)
@@ -1309,7 +1309,6 @@ def verify_bgp_community(
 
     command = "show bgp"
 
-    sleep(5)
     for net in network:
         if vrf:
             cmd = "{} vrf {} {} {} json".format(command, vrf, addr_type, net)
diff --git a/tests/topotests/nhrp-topo/r1/nhrp4_cache.json b/tests/topotests/nhrp-topo/r1/nhrp4_cache.json
new file mode 100644 (file)
index 0000000..6426a93
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "attr":{
+    "entriesCount":2
+  },
+  "table":[
+    {
+      "interface":"r1-gre0",
+      "type":"nhs",
+      "protocol":"10.255.255.2",
+      "nbma":"10.2.1.2",
+      "claimed_nbma":"10.2.1.2",
+      "used":false,
+      "timeout":true,
+      "auth":false,
+      "identity":""
+    },
+    {
+      "interface":"r1-gre0",
+      "type":"local",
+      "protocol":"10.255.255.1",
+      "nbma":"10.1.1.1",
+      "claimed_nbma":"10.1.1.1",
+      "used":false,
+      "timeout":false,
+      "auth":false,
+      "identity":"-"
+    }
+  ]
+}
diff --git a/tests/topotests/nhrp-topo/r1/nhrp_route4.json b/tests/topotests/nhrp-topo/r1/nhrp_route4.json
new file mode 100644 (file)
index 0000000..68b5a6e
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "10.255.255.2\/32":[
+    {
+      "prefix":"10.255.255.2\/32",
+      "protocol":"nhrp",
+      "vrfId":0,
+      "vrfName":"default",
+      "selected":true,
+      "destSelected":true,
+      "distance":10,
+      "metric":0,
+      "installed":true,
+      "internalNextHopNum":1,
+      "internalNextHopActiveNum":1,
+      "nexthops":[
+        {
+          "fib":true,
+          "directlyConnected":true,
+          "interfaceName":"r1-gre0",
+          "active":true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/nhrp-topo/r1/nhrpd.conf b/tests/topotests/nhrp-topo/r1/nhrpd.conf
new file mode 100644 (file)
index 0000000..04114bd
--- /dev/null
@@ -0,0 +1,10 @@
+log stdout debugging
+debug nhrp all
+interface r1-gre0
+ ip nhrp holdtime 500
+ ip nhrp shortcut
+ ip nhrp network-id 42
+ ip nhrp nhs dynamic nbma 10.2.1.2
+ ip nhrp registration no-unique
+ tunnel source r1-eth0
+exit
diff --git a/tests/topotests/nhrp-topo/r1/zebra.conf b/tests/topotests/nhrp-topo/r1/zebra.conf
new file mode 100644 (file)
index 0000000..b45670f
--- /dev/null
@@ -0,0 +1,12 @@
+interface r1-eth0
+ ip address 10.1.1.1/24
+!
+ip route 10.2.1.0/24 10.1.1.3
+interface r1-gre0
+ ip address 10.255.255.1/32
+ no link-detect
+ ipv6 nd suppress-ra
+exit
+interface r1-eth1
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/nhrp-topo/r2/nhrp4_cache.json b/tests/topotests/nhrp-topo/r2/nhrp4_cache.json
new file mode 100644 (file)
index 0000000..34558e0
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  "attr":{
+    "entriesCount":2
+  },
+  "table":[
+    {
+      "interface":"r2-gre0",
+      "type":"local",
+      "protocol":"10.255.255.2",
+      "nbma":"10.2.1.2",
+      "claimed_nbma":"10.2.1.2",
+      "used":false,
+      "timeout":false,
+      "auth":false,
+      "identity":"-"
+    },
+    {
+      "interface":"r2-gre0",
+      "type":"dynamic",
+      "protocol":"10.255.255.1",
+      "nbma":"10.1.1.1",
+      "claimed_nbma":"10.1.1.1",
+      "used":false,
+      "timeout":true,
+      "auth":false,
+      "identity":""
+    }
+  ]
+}
diff --git a/tests/topotests/nhrp-topo/r2/nhrp_route4.json b/tests/topotests/nhrp-topo/r2/nhrp_route4.json
new file mode 100644 (file)
index 0000000..7393cba
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "10.255.255.1\/32":[
+    {
+      "prefix":"10.255.255.1\/32",
+      "protocol":"nhrp",
+      "vrfId":0,
+      "vrfName":"default",
+      "selected":true,
+      "destSelected":true,
+      "distance":10,
+      "metric":0,
+      "installed":true,
+      "internalNextHopNum":1,
+      "internalNextHopActiveNum":1,
+      "nexthops":[
+        {
+          "fib":true,
+          "directlyConnected":true,
+          "interfaceName":"r2-gre0",
+          "active":true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/nhrp-topo/r2/nhrpd.conf b/tests/topotests/nhrp-topo/r2/nhrpd.conf
new file mode 100644 (file)
index 0000000..e4f6fb7
--- /dev/null
@@ -0,0 +1,10 @@
+debug nhrp all
+log stdout debugging
+nhrp nflog-group 1
+interface r2-gre0
+ ip nhrp holdtime 500
+ ip nhrp redirect
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ tunnel source r2-eth0
+exit
diff --git a/tests/topotests/nhrp-topo/r2/zebra.conf b/tests/topotests/nhrp-topo/r2/zebra.conf
new file mode 100644 (file)
index 0000000..9f40d4d
--- /dev/null
@@ -0,0 +1,12 @@
+interface r2-eth0
+ ip address 10.2.1.2/24
+!
+ip route 10.1.1.0/24 10.2.1.3
+interface r2-gre0
+ ip address 10.255.255.2/32
+ no link-detect
+ ipv6 nd suppress-ra
+!
+interface r2-eth1
+ ip address 192.168.2.2/24
+!
diff --git a/tests/topotests/nhrp-topo/r3/zebra.conf b/tests/topotests/nhrp-topo/r3/zebra.conf
new file mode 100644 (file)
index 0000000..6d3d267
--- /dev/null
@@ -0,0 +1,11 @@
+debug zebra kernel
+debug zebra rib
+debug zebra events
+debug zebra packet
+ip forwarding
+interface r3-eth0
+ ip address 10.1.1.3/24
+!
+interface r3-eth1
+ ip address 10.2.1.3/24
+exit
diff --git a/tests/topotests/nhrp-topo/test_nhrp_topo.dot b/tests/topotests/nhrp-topo/test_nhrp_topo.dot
new file mode 100644 (file)
index 0000000..6b68fb3
--- /dev/null
@@ -0,0 +1,73 @@
+## Color coding:
+#########################
+##  Main FRR: #f08080  red
+##  Switches: #d0e0d0  gray
+##  RIP:      #19e3d9  Cyan
+##  RIPng:    #fcb314  dark yellow
+##  OSPFv2:   #32b835  Green
+##  OSPFv3:   #19e3d9  Cyan
+##  ISIS IPv4 #fcb314  dark yellow
+##  ISIS IPv6 #9a81ec  purple
+##  BGP IPv4  #eee3d3  beige
+##  BGP IPv6  #fdff00  yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+  label="bfd-topo2";
+
+  # Routers
+  r1 [
+    shape=doubleoctagon,
+    label="r1",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r2 [
+    shape=doubleoctagon
+    label="r2",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r3 [
+    shape=doubleoctagon
+    label="r3",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r4 [
+    shape=doubleoctagon
+    label="r4",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+
+  # Switches
+  sw1 [
+    shape=oval,
+    label="sw1\n2001:db8:1::/64",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw2 [
+    shape=oval,
+    label="sw2\n10.0.3.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw3 [
+    shape=oval,
+    label="sw3\n2001:db8:4::/64",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+
+  # Connections
+  r1 -- sw1 [label="eth0"];
+  r2 -- sw1 [label="eth0"];
+
+  r2 -- sw2 [label="eth1"];
+  r3 -- sw2 [label="eth0"];
+
+  r2 -- sw3 [label="eth2"];
+  r4 -- sw3 [label="eth0"];
+}
diff --git a/tests/topotests/nhrp-topo/test_nhrp_topo.py b/tests/topotests/nhrp-topo/test_nhrp_topo.py
new file mode 100644 (file)
index 0000000..1687961
--- /dev/null
@@ -0,0 +1,221 @@
+#!/usr/bin/env python
+
+#
+# test_nhrp_topo.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# 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.
+#
+
+"""
+test_nhrp_topo.py: Test the FRR/Quagga NHRP daemon
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class NHRPTopo(Topo):
+    "Test topology builder"
+    def build(self, *_args, **_opts):
+        "Build function"
+        tgen = get_topogen(self)
+
+        # Create 3 routers.
+        for routern in range(1, 4):
+            tgen.add_router('r{}'.format(routern))
+
+        switch = tgen.add_switch('s1')
+        switch.add_link(tgen.gears['r1'])
+        switch.add_link(tgen.gears['r3'])
+        switch = tgen.add_switch('s2')
+        switch.add_link(tgen.gears['r2'])
+        switch.add_link(tgen.gears['r3'])
+        switch = tgen.add_switch('s3')
+        switch.add_link(tgen.gears['r2'])
+        switch = tgen.add_switch('s4')
+        switch.add_link(tgen.gears['r1'])
+
+
+def _populate_iface():
+    tgen = get_topogen()
+    cmds_tot_hub = ['ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 10.2.1.{1} remote 0.0.0.0',
+                    'ip link set dev {0}-gre0 up',
+                    'echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu',
+                    'echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6',
+                    'echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6']
+
+    cmds_tot = ['ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 10.1.1.{1} remote 0.0.0.0',
+                'ip link set dev {0}-gre0 up',
+                'echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu',
+                'echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6',
+                'echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6']
+
+    for cmd in cmds_tot_hub:
+        input = cmd.format('r2', '2')
+        logger.info('input: '+cmd)
+        output = tgen.net['r2'].cmd(cmd.format('r2', '2'))
+        logger.info('output: '+output);
+
+    for cmd in cmds_tot:
+        input = cmd.format('r1', '1')
+        logger.info('input: '+cmd)
+        output = tgen.net['r1'].cmd(cmd.format('r1', '1'))
+        logger.info('output: '+output);
+
+
+def setup_module(mod):
+    "Sets up the pytest environment"
+    tgen = Topogen(NHRPTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+    _populate_iface()
+        
+    for rname, router in router_list.iteritems():
+        router.load_config(
+            TopoRouter.RD_ZEBRA,
+            os.path.join(CWD, '{}/zebra.conf'.format(rname)),
+        )
+        if rname in ('r1', 'r2'):
+            router.load_config(
+                TopoRouter.RD_NHRP,
+                os.path.join(CWD, '{}/nhrpd.conf'.format(rname))
+            )
+
+    # Initialize all routers.
+    logger.info('Launching BGP, NHRP')
+    for name in router_list:
+        router = tgen.gears[name]
+        router.start()
+
+
+def teardown_module(_mod):
+    "Teardown the pytest environment"
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+def test_protocols_convergence():
+    """
+    Assert that all protocols have converged before checking for the NHRP
+    statuses as they depend on it.
+    """
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # Check IPv4 routing tables.
+    logger.info("Checking NHRP cache and IPv4 routes for convergence")
+    router_list = tgen.routers()
+
+    for rname, router in router_list.iteritems():
+        if rname == 'r3':
+            continue
+
+        json_file = '{}/{}/nhrp4_cache.json'.format(CWD, router.name)
+        if not os.path.isfile(json_file):
+            logger.info('skipping file {}'.format(json_file))
+            continue
+
+        expected = json.loads(open(json_file).read())
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show ip nhrp cache json', expected)
+        _, result = topotest.run_and_expect(test_func, None, count=40,
+                                            wait=0.5)
+
+        output = router.vtysh_cmd('show ip nhrp cache')
+        logger.info(output)
+
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert result is None, assertmsg
+
+    for rname, router in router_list.iteritems():
+        if rname == 'r3':
+            continue
+
+        json_file = '{}/{}/nhrp_route4.json'.format(CWD, router.name)
+        if not os.path.isfile(json_file):
+            logger.info('skipping file {}'.format(json_file))
+            continue
+
+        expected = json.loads(open(json_file).read())
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show ip route nhrp json', expected)
+        _, result = topotest.run_and_expect(test_func, None, count=40,
+                                            wait=0.5)
+
+        output = router.vtysh_cmd('show ip route nhrp')
+        logger.info(output)
+
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert result is None, assertmsg
+
+    for rname, router in router_list.iteritems():
+        if rname == 'r3':
+            continue
+        logger.info('Dump neighbor information on {}-gre0'.format(rname))
+        output = router.run('ip neigh show')
+        logger.info(output)
+
+
+def test_nhrp_connection():
+    "Assert that the NHRP peers can find themselves."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    pingrouter = tgen.gears['r1']
+    logger.info('Check Ping IPv4 from  R1 to R2 = 10.255.255.2)')
+    output = pingrouter.run('ping 10.255.255.2 -f -c 1000')
+    logger.info(output)
+    if '1000 packets transmitted, 1000 received' not in output:
+        assertmsg = 'expected ping IPv4 from R1 to R2 should be ok'
+        assert 0, assertmsg
+    else:
+        logger.info('Check Ping IPv4 from R1 to R2 OK')
+
+
+def test_memory_leak():
+    "Run the memory leak test and report results."
+    tgen = get_topogen()
+    if not tgen.is_memleak_enabled():
+        pytest.skip('Memory leak test/report is disabled')
+
+    tgen.report_memory_leaks()
+
+
+if __name__ == '__main__':
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
index 61f7a656203472734accf21f693be6dd0231f496..5ee6d15c915c1403c8b7664e47ff7a8fef2fcd94 100644 (file)
@@ -1,3 +1,10 @@
-# default to using syslog. /etc/rsyslog.d/45-frr.conf places the log
-# in /var/log/frr/frr.log
+# default to using syslog. /etc/rsyslog.d/45-frr.conf places the log in
+# /var/log/frr/frr.log
+#
+# Note:
+# FRR's configuration shell, vtysh, dynamically edits the live, in-memory
+# configuration while FRR is running. When instructed, vtysh will persist the
+# live configuration to this file, overwriting its contents. If you want to
+# avoid this, you can edit this file manually before starting FRR, or instruct
+# vtysh to write configuration to a different file.
 log syslog informational
index 96ae5308941743e7090ea0ca8d94c4cc566a5488..dfa9b261c3ffd26f2a55e7d84367e55e5297f8c1 100644 (file)
@@ -5,7 +5,6 @@
 if VRRPD
 noinst_LIBRARIES += vrrpd/libvrrp.a
 sbin_PROGRAMS += vrrpd/vrrpd
-# dist_examples_DATA += staticd/staticd.conf.sample
 vtysh_scan += vrrpd/vrrp_vty.c
 vtysh_daemons += vrrpd
 man8 += $(MANBUILD)/frr-vrrpd.8
index 4855c23f4b15ab837b37614c9b2278bb1a981c5a..af974771cc25da6fdf2b43dc10401d70d33d0fe7 100755 (executable)
@@ -103,7 +103,7 @@ sub scan_file {
         elsif ($file =~ /lib\/(filter|filter_cli)\.c$/) {
             $protocol = "VTYSH_ACL";
         }
-        elsif ($file =~ /lib\/lib_vty\.c$/) {
+        elsif ($file =~ /lib\/(lib|log)_vty\.c$/) {
             $protocol = "VTYSH_ALL";
         }
        elsif ($file =~ /lib\/agentx\.c$/) {
@@ -133,7 +133,13 @@ sub scan_file {
                 $protocol = "VTYSH_RIPD";
             }
         }
-        elsif ($file =~ /lib\/vty\.c$/) {
+       elsif ($file =~ /lib\/resolver\.c$/) {
+           $protocol = "VTYSH_NHRPD|VTYSH_BGPD";
+       }
+       elsif ($file =~ /lib\/spf_backoff\.c$/) {
+           $protocol = "VTYSH_ISISD";
+       }
+        elsif ($file =~ /lib\/(vty|thread)\.c$/) {
            $protocol = "VTYSH_ALL";
         }
         elsif ($file =~ /librfp\/.*\.c$/ || $file =~ /rfapi\/.*\.c$/) {
@@ -269,7 +275,7 @@ EOF
 foreach (sort keys %odefun) {
     my ($node, $str) = (split (/,/));
     $cmd = $ocmd{$_};
-    $cmd =~ s/_cmd/_cmd_vtysh/;
+    $cmd =~ s/_cmd$/_cmd_vtysh/;
     printf "  install_element ($node, &$cmd);\n";
 }
 
index 86861b0390ed9ca7af49cb9141ca92a90bc4447e..5f7d85494844920858c71470bbaa17016a76e999 100644 (file)
@@ -4,7 +4,6 @@
 
 if VTYSH
 bin_PROGRAMS += vtysh/vtysh
-dist_examples_DATA += vtysh/vtysh.conf.sample
 man1 += $(MANBUILD)/vtysh.1
 endif
 
index 931eb91593d6a18bb025c5633ba3b5bf729bb672..a1417430ec47621b055d8ad156b8387316a8ea59 100644 (file)
@@ -2964,136 +2964,6 @@ DEFUN (vtysh_show_logging,
                               "Logging configuration for %s:\n");
 }
 
-DEFUNSH(VTYSH_ALL, vtysh_log_stdout, vtysh_log_stdout_cmd, "log stdout",
-       "Logging control\n"
-       "Set stdout logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_stdout_level, vtysh_log_stdout_level_cmd,
-       "log stdout <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>",
-       "Logging control\n"
-       "Set stdout logging level\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_stdout, no_vtysh_log_stdout_cmd,
-       "no log stdout [LEVEL]", NO_STR
-       "Logging control\n"
-       "Cancel logging to stdout\n"
-       "Logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_file, vtysh_log_file_cmd, "log file FILENAME",
-       "Logging control\n"
-       "Logging to file\n"
-       "Logging filename\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_file_level, vtysh_log_file_level_cmd,
-       "log file FILENAME <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>",
-       "Logging control\n"
-       "Logging to file\n"
-       "Logging filename\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_file, no_vtysh_log_file_cmd,
-       "no log file [FILENAME [LEVEL]]", NO_STR
-       "Logging control\n"
-       "Cancel logging to file\n"
-       "Logging file name\n"
-       "Logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_monitor, vtysh_log_monitor_cmd,
-       "log monitor [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
-       "Logging control\n"
-       "Set terminal line (monitor) logging level\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_monitor, no_vtysh_log_monitor_cmd,
-       "no log monitor [LEVEL]", NO_STR
-       "Logging control\n"
-       "Disable terminal line (monitor) logging\n"
-       "Logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_syslog, vtysh_log_syslog_cmd,
-       "log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
-       "Logging control\n"
-       "Set syslog logging level\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_syslog, no_vtysh_log_syslog_cmd,
-       "no log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
-       NO_STR
-       "Logging control\n"
-       "Cancel logging to syslog\n"
-       LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_facility, vtysh_log_facility_cmd,
-       "log facility <kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>",
-       "Logging control\n"
-       "Facility parameter for syslog messages\n" LOG_FACILITY_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd,
-       "no log facility [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>]",
-       NO_STR
-       "Logging control\n"
-       "Reset syslog facility to default (daemon)\n"
-       LOG_FACILITY_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_record_priority, vtysh_log_record_priority_cmd,
-       "log record-priority",
-       "Logging control\n"
-       "Log the priority of the message within the message\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_record_priority,
-       no_vtysh_log_record_priority_cmd, "no log record-priority", NO_STR
-       "Logging control\n"
-       "Do not log the priority of the message within the message\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_timestamp_precision,
-       vtysh_log_timestamp_precision_cmd, "log timestamp precision (0-6)",
-       "Logging control\n"
-       "Timestamp configuration\n"
-       "Set the timestamp precision\n"
-       "Number of subsecond digits\n")
-{
-       return CMD_SUCCESS;
-}
-
 DEFUNSH(VTYSH_ALL, vtysh_debug_memstats,
        vtysh_debug_memstats_cmd, "[no] debug memstats-at-exit",
        NO_STR
@@ -3103,16 +2973,6 @@ DEFUNSH(VTYSH_ALL, vtysh_debug_memstats,
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_ALL, no_vtysh_log_timestamp_precision,
-       no_vtysh_log_timestamp_precision_cmd, "no log timestamp precision",
-       NO_STR
-       "Logging control\n"
-       "Timestamp configuration\n"
-       "Reset the timestamp precision to the default value of 0\n")
-{
-       return CMD_SUCCESS;
-}
-
 DEFUNSH(VTYSH_ALL, vtysh_service_password_encrypt,
        vtysh_service_password_encrypt_cmd, "service password-encryption",
        "Set up miscellaneous service\n"
@@ -3724,19 +3584,19 @@ DEFUN (no_vtysh_output_file,
 
 DEFUN(find,
       find_cmd,
-      "find REGEX",
+      "find REGEX...",
       "Find CLI command matching a regular expression\n"
       "Search pattern (POSIX regex)\n")
 {
-       char *pattern = argv[1]->arg;
        const struct cmd_node *node;
        const struct cmd_element *cli;
        vector clis;
-
        regex_t exp = {};
-
+       char *pattern = argv_concat(argv, argc, 1);
        int cr = regcomp(&exp, pattern, REG_NOSUB | REG_EXTENDED);
 
+       XFREE(MTYPE_TMP, pattern);
+
        if (cr != 0) {
                switch (cr) {
                case REG_BADBR:
@@ -4605,22 +4465,6 @@ void vtysh_init_vty(void)
 
        /* Logging */
        install_element(VIEW_NODE, &vtysh_show_logging_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_stdout_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_stdout_level_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_stdout_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_file_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_file_level_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_file_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_monitor_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_monitor_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_syslog_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_syslog_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_facility_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_facility_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_record_priority_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_record_priority_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_timestamp_precision_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_timestamp_precision_cmd);
 
        install_element(CONFIG_NODE, &vtysh_service_password_encrypt_cmd);
        install_element(CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd);
diff --git a/vtysh/vtysh.conf.sample b/vtysh/vtysh.conf.sample
deleted file mode 100644 (file)
index 4e0a2be..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-!
-! Sample configuration file for vtysh.
-!
-!service integrated-vtysh-config
-!hostname quagga-router
-!username root nopassword
-!
index 498d3e5f67328be753cf874f6abb2e3952b9f438..3414c764ce39783c5902e8663db87ef2e96c6487 100644 (file)
@@ -342,6 +342,9 @@ void vtysh_config_parse_line(void *arg, const char *line)
                        config = config_get(OPENFABRIC_NODE, line);
                else if (strncmp(line, "route-map", strlen("route-map")) == 0)
                        config = config_get(RMAP_NODE, line);
+               else if (strncmp(line, "no route-map", strlen("no route-map"))
+                        == 0)
+                       config = config_get(RMAP_NODE, line);
                else if (strncmp(line, "pbr-map", strlen("pbr-map")) == 0)
                        config = config_get(PBRMAP_NODE, line);
                else if (strncmp(line, "access-list", strlen("access-list"))
index db7cc312d684ed4d022cc5ef9e2180a460a347bd..fe33bed7f65da19367acb0049410dd3af5b35dfa 100644 (file)
@@ -153,8 +153,10 @@ static void usage(int status)
                        progname);
        else
                printf("Usage : %s [OPTION...]\n\n"
-                      "Integrated shell for FRR (version " FRR_VERSION "). \n"
-                      "Configured with:\n    " FRR_CONFIG_ARGS "\n\n"
+                      "Integrated shell for FRR (version " FRR_VERSION
+                      "). \n"
+                      "Configured with:\n    " FRR_CONFIG_ARGS
+                      "\n\n"
                       "-b, --boot               Execute boot startup configuration\n"
                       "-c, --command            Execute argument as command\n"
                       "-d, --daemon             Connect only to the specified daemon\n"
@@ -167,6 +169,7 @@ static void usage(int status)
                       "-N  --pathspace          Insert prefix into config & socket paths\n"
                       "-u  --user               Run as an unprivileged user\n"
                       "-w, --writeconfig        Write integrated config (frr.conf) and exit\n"
+                      "-H, --histfile           Override history file\n"
                       "-h, --help               Display this help and exit\n\n"
                       "Note that multiple commands may be executed from the command\n"
                       "line by passing multiple -c args, or by embedding linefeed\n"
@@ -189,6 +192,7 @@ struct option longopts[] = {
        {"vty_socket", required_argument, NULL, OPTION_VTYSOCK},
        {"config_dir", required_argument, NULL, OPTION_CONFDIR},
        {"inputfile", required_argument, NULL, 'f'},
+       {"histfile", required_argument, NULL, 'H'},
        {"echo", no_argument, NULL, 'E'},
        {"dryrun", no_argument, NULL, 'C'},
        {"help", no_argument, NULL, 'h'},
@@ -321,6 +325,7 @@ int main(int argc, char **argv, char **env)
        char sysconfdir[MAXPATHLEN];
        const char *pathspace_arg = NULL;
        char pathspace[MAXPATHLEN] = "";
+       const char *histfile = NULL;
 
        /* SUID: drop down to calling user & go back up when needed */
        elevuid = geteuid();
@@ -341,8 +346,8 @@ int main(int argc, char **argv, char **env)
 
        /* Option handling. */
        while (1) {
-               opt = getopt_long(argc, argv, "be:c:d:nf:mEhCwN:u",
-                                 longopts, 0);
+               opt = getopt_long(argc, argv, "be:c:d:nf:H:mEhCwN:u", longopts,
+                                 0);
 
                if (opt == EOF)
                        break;
@@ -409,6 +414,9 @@ int main(int argc, char **argv, char **env)
                case 'h':
                        usage(0);
                        break;
+               case 'H':
+                       histfile = optarg;
+                       break;
                default:
                        usage(1);
                        break;
@@ -569,12 +577,24 @@ int main(int argc, char **argv, char **env)
        /*
         * Setup history file for use by both -c and regular input
         * If we can't find the home directory, then don't store
-        * the history information
+        * the history information.
+        * VTYSH_HISTFILE is prefered over command line
+        * argument (-H/--histfile).
         */
-       homedir = vtysh_get_home();
-       if (homedir) {
-               snprintf(history_file, sizeof(history_file), "%s/.history_frr",
-                        homedir);
+       if (getenv("VTYSH_HISTFILE")) {
+               const char *file = getenv("VTYSH_HISTFILE");
+
+               strlcpy(history_file, file, sizeof(history_file));
+       } else if (histfile) {
+               strlcpy(history_file, histfile, sizeof(history_file));
+       } else {
+               homedir = vtysh_get_home();
+               if (homedir)
+                       snprintf(history_file, sizeof(history_file),
+                                "%s/.history_frr", homedir);
+       }
+
+       if (strlen(history_file) > 0) {
                if (read_history(history_file) != 0) {
                        int fp;
 
index 6ed3dadaae5addc4b4c3a92397e11c8043b922c1..c4eb78608b85fa3e1d3bcbbbadfbfd602733e2a9 100644 (file)
@@ -364,6 +364,11 @@ module frr-route-map {
         description
           "Route map instance name";
       }
+      leaf optimization-disabled {
+        type boolean;
+        default false;
+        description "Disables or enables the optimization";
+      }
 
       list entry {
         key "sequence";
index af2c2516071d7e60874381f0fb6ff552d74200c8..6aaf9d94f3664a9f37aa415953c2b89658548abc 100644 (file)
@@ -1661,8 +1661,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                else if (IS_ZEBRA_IF_VXLAN(ifp))
                        zebra_l2_vxlanif_del(ifp);
 
-               if (!IS_ZEBRA_IF_VRF(ifp))
-                       if_delete_update(ifp);
+               if_delete_update(ifp);
        }
 
        return 0;
index 3eeed9ac90e27cbbcf62d0ceb4f8f6d0ecad8a7b..4b708496a1dbc0eedaf1bb6dac618c1c3a18dbd2 100644 (file)
@@ -898,7 +898,8 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
         * Remove and re-add any existing neighbor entry for this address,
         * since Netlink doesn't currently offer update message types.
         */
-       kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
+       kernel_neigh_update(0, ifp->ifindex, (void *)&ipv4_ll.s_addr, mac, 6,
+                           ns_id, AF_INET, true);
 
        /* Add new neighbor entry.
         *
@@ -910,8 +911,8 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
         * they'll be useless to us.
         */
        if (add)
-               kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6,
-                                   ns_id);
+               kernel_neigh_update(add, ifp->ifindex, (void *)&ipv4_ll.s_addr,
+                                   mac, 6, ns_id, AF_INET, true);
 
        memcpy(&zif->neigh_mac[0], &mac[0], 6);
 
index e71e6624589d42acff66b861f3c0205f3ef287a5..adb61023c1f11b0b564baeee4f0dabe42c71b0f9 100644 (file)
@@ -1335,6 +1335,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
+       case DPLANE_OP_NEIGH_TABLE_UPDATE:
                return netlink_put_neigh_update_msg(bth, ctx);
 
        case DPLANE_OP_RULE_ADD:
index 48f1df28685ef419d6980282f87a0b4473d79846..daaa926a7dc2834617fcacb4be45d1584c35477d 100644 (file)
@@ -68,8 +68,11 @@ kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx);
 
 #endif /* !HAVE_NETLINK */
 
-extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
-                              int llalen, ns_id_t ns_id);
+extern int kernel_neigh_update(int cmd, int ifindex, void *addr, char *lla,
+                              int llalen, ns_id_t ns_id, uint8_t family,
+                              bool permanent);
+extern int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client,
+                                bool reg);
 extern int kernel_interface_set_master(struct interface *master,
                                       struct interface *slave);
 
@@ -78,6 +81,9 @@ extern int mpls_kernel_init(void);
 extern uint32_t kernel_get_speed(struct interface *ifp, int *error);
 extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
 
+extern int kernel_configure_if_link(struct interface *ifp,
+                                   struct interface *link_ifp, ns_id_t ns_id);
+
 /*
  * Southbound Initialization routines to get initial starting
  * state.
index 55e0775a8c49dffe30f87564a4b55d4d9bf08b0f..d2ec7da57cc13df091bfa51523eca862f256147f 100644 (file)
@@ -185,6 +185,10 @@ static uint16_t neigh_state_to_netlink(uint16_t dplane_state)
                state |= NUD_PROBE;
        if (dplane_state & DPLANE_NUD_INCOMPLETE)
                state |= NUD_INCOMPLETE;
+       if (dplane_state & DPLANE_NUD_PERMANENT)
+               state |= NUD_PERMANENT;
+       if (dplane_state & DPLANE_NUD_FAILED)
+               state |= NUD_FAILED;
 
        return state;
 }
@@ -1537,10 +1541,10 @@ static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
                           routedesc, nl_msg_type_to_str(cmd), label);
 }
 
-static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
-                               int llalen, ns_id_t ns_id)
+static int netlink_neigh_update(int cmd, int ifindex, void *addr, char *lla,
+                               int llalen, ns_id_t ns_id, uint8_t family,
+                               bool permanent, uint8_t protocol)
 {
-       uint8_t protocol = RTPROT_ZEBRA;
        struct {
                struct nlmsghdr n;
                struct ndmsg ndm;
@@ -1556,15 +1560,24 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
        req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
        req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
 
-       req.ndm.ndm_family = AF_INET;
-       req.ndm.ndm_state = NUD_PERMANENT;
+       req.ndm.ndm_family = family;
        req.ndm.ndm_ifindex = ifindex;
        req.ndm.ndm_type = RTN_UNICAST;
+       if (cmd == RTM_NEWNEIGH) {
+               if (!permanent)
+                       req.ndm.ndm_state = NUD_REACHABLE;
+               else
+                       req.ndm.ndm_state = NUD_PERMANENT;
+       } else
+               req.ndm.ndm_state = NUD_FAILED;
 
        nl_attr_put(&req.n, sizeof(req), NDA_PROTOCOL, &protocol,
                    sizeof(protocol));
-       nl_attr_put32(&req.n, sizeof(req), NDA_DST, addr);
-       nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
+       req.ndm.ndm_type = RTN_UNICAST;
+       nl_attr_put(&req.n, sizeof(req), NDA_DST, addr,
+                   family2addrsize(family));
+       if (lla)
+               nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
 
        return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
                            0);
@@ -2679,11 +2692,12 @@ int netlink_nexthop_read(struct zebra_ns *zns)
 }
 
 
-int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
-                       int llalen, ns_id_t ns_id)
+int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen,
+                       ns_id_t ns_id, uint8_t family, bool permanent)
 {
        return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
-                                   addr, lla, llalen, ns_id);
+                                   addr, lla, llalen, ns_id, family, permanent,
+                                   RTPROT_ZEBRA);
 }
 
 /**
@@ -2694,7 +2708,9 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
  * entry.
  * @ctx:               Dataplane context
  * @cmd:               Netlink command (RTM_NEWNEIGH or RTM_DELNEIGH)
- * @mac:               A neighbor cache link layer address
+ * @lla:               A pointer to neighbor cache link layer address
+ * @llalen:            Length of the pointer to neighbor cache link layer
+ * address
  * @ip:                A neighbor cache n/w layer destination address
  *                     In the case of bridge FDB, this represnts the remote
  *                     VTEP IP.
@@ -2706,18 +2722,18 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
  * @state:             NUD_* states
  * @data:              data buffer pointer
  * @datalen:           total amount of data buffer space
+ * @protocol:          protocol information
  *
  * Return:             0 when the msg doesn't fit entirely in the buffer
  *                             otherwise the number of bytes written to buf.
  */
 static ssize_t netlink_neigh_update_msg_encode(
-       const struct zebra_dplane_ctx *ctx, int cmd, const struct ethaddr *mac,
-       const struct ipaddr *ip, bool replace_obj, uint8_t family, uint8_t type,
-       uint8_t flags, uint16_t state, uint32_t nhg_id, bool nfy,
+       const struct zebra_dplane_ctx *ctx, int cmd, const void *lla,
+       int llalen, const struct ipaddr *ip, bool replace_obj, uint8_t family,
+       uint8_t type, uint8_t flags, uint16_t state, uint32_t nhg_id, bool nfy,
        uint8_t nfy_flags, bool ext, uint32_t ext_flags, void *data,
-       size_t datalen)
+       size_t datalen, uint8_t protocol)
 {
-       uint8_t protocol = RTPROT_ZEBRA;
        struct {
                struct nlmsghdr n;
                struct ndmsg ndm;
@@ -2749,8 +2765,8 @@ static ssize_t netlink_neigh_update_msg_encode(
                         sizeof(protocol)))
                return 0;
 
-       if (mac) {
-               if (!nl_attr_put(&req->n, datalen, NDA_LLADDR, mac, 6))
+       if (lla) {
+               if (!nl_attr_put(&req->n, datalen, NDA_LLADDR, lla, llalen))
                        return 0;
        }
 
@@ -2814,12 +2830,17 @@ netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx, int cmd,
                               void *buf, size_t buflen)
 {
        struct ethaddr dst_mac = {.octet = {0}};
+       int proto = RTPROT_ZEBRA;
+
+       if (dplane_ctx_get_type(ctx) != 0)
+               proto = zebra2proto(dplane_ctx_get_type(ctx));
 
        return netlink_neigh_update_msg_encode(
-               ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false,
-               PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT), 0 /*nhg*/,
-               false /*nfy*/, 0 /*nfy_flags*/, false /*ext*/, 0 /*ext_flags*/,
-               buf, buflen);
+               ctx, cmd, (const void *)&dst_mac, ETH_ALEN,
+               dplane_ctx_neigh_get_ipaddr(ctx), false, PF_BRIDGE, 0, NTF_SELF,
+               (NUD_NOARP | NUD_PERMANENT), 0 /*nhg*/, false /*nfy*/,
+               0 /*nfy_flags*/, false /*ext*/, 0 /*ext_flags*/, buf, buflen,
+               proto);
 }
 
 #ifndef NDA_RTA
@@ -3185,6 +3206,10 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
        uint32_t update_flags;
        bool nfy = false;
        uint8_t nfy_flags = 0;
+       int proto = RTPROT_ZEBRA;
+
+       if (dplane_ctx_get_type(ctx) != 0)
+               proto = zebra2proto(dplane_ctx_get_type(ctx));
 
        cmd = dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL
                          ? RTM_NEWNEIGH : RTM_DELNEIGH;
@@ -3251,9 +3276,10 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
        }
 
        total = netlink_neigh_update_msg_encode(
-               ctx, cmd, dplane_ctx_mac_get_addr(ctx), &vtep_ip, true,
-               AF_BRIDGE, 0, flags, state, nhg_id, nfy, nfy_flags,
-               false /*ext*/, 0 /*ext_flags*/, data, datalen);
+               ctx, cmd, (const void *)dplane_ctx_mac_get_addr(ctx), ETH_ALEN,
+               &vtep_ip, true, AF_BRIDGE, 0, flags, state, nhg_id, nfy,
+               nfy_flags, false /*ext*/, 0 /*ext_flags*/, data, datalen,
+               proto);
 
        return total;
 }
@@ -3307,6 +3333,8 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
        bool local_inactive;
        uint32_t ext_flags = 0;
        bool dp_static = false;
+       int l2_len = 0;
+       int cmd;
 
        ndm = NLMSG_DATA(h);
 
@@ -3348,6 +3376,43 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
        if (h->nlmsg_type == RTM_NEWNEIGH && !(ndm->ndm_state & NUD_VALID))
                netlink_handle_5549(ndm, zif, ifp, &ip, true);
 
+       /* we send link layer information to client:
+        * - nlmsg_type = RTM_DELNEIGH|NEWNEIGH|GETNEIGH
+        * - struct ipaddr ( for DEL and GET)
+        * - struct ethaddr mac; (for NEW)
+        */
+       if (h->nlmsg_type == RTM_NEWNEIGH)
+               cmd = ZEBRA_NHRP_NEIGH_ADDED;
+       else if (h->nlmsg_type == RTM_GETNEIGH)
+               cmd = ZEBRA_NHRP_NEIGH_GET;
+       else if (h->nlmsg_type == RTM_DELNEIGH)
+               cmd = ZEBRA_NHRP_NEIGH_REMOVED;
+       else {
+               zlog_debug("%s(): unknown nlmsg type %u", __func__,
+                          h->nlmsg_type);
+               return 0;
+       }
+       if (tb[NDA_LLADDR]) {
+               /* copy LLADDR information */
+               l2_len = RTA_PAYLOAD(tb[NDA_LLADDR]);
+               memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), l2_len);
+       }
+       if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0) {
+               union sockunion link_layer_ipv4;
+
+               if (l2_len) {
+                       sockunion_family(&link_layer_ipv4) = AF_INET;
+                       memcpy((void *)sockunion_get_addr(&link_layer_ipv4),
+                              &mac, l2_len);
+               } else
+                       sockunion_family(&link_layer_ipv4) = AF_UNSPEC;
+               zsend_nhrp_neighbor_notify(cmd, ifp, &ip, ndm->ndm_state,
+                                          &link_layer_ipv4);
+       }
+
+       if (h->nlmsg_type == RTM_GETNEIGH)
+               return 0;
+
        /* The neighbor is present on an SVI. From this, we locate the
         * underlying
         * bridge because we're only interested in neighbors on a VxLAN bridge.
@@ -3615,7 +3680,8 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
        int len;
        struct ndmsg *ndm;
 
-       if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
+       if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH
+             || h->nlmsg_type == RTM_GETNEIGH))
                return 0;
 
        /* Length validity. */
@@ -3656,19 +3722,42 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
                                        int cmd, void *buf, size_t buflen)
 {
        const struct ipaddr *ip;
-       const struct ethaddr *mac;
+       const struct ethaddr *mac = NULL;
+       const struct ipaddr *link_ip = NULL;
+       const void *link_ptr = NULL;
+       char buf2[ETHER_ADDR_STRLEN];
+
+       int llalen;
        uint8_t flags;
        uint16_t state;
        uint8_t family;
        uint32_t update_flags;
        uint32_t ext_flags = 0;
        bool ext = false;
+       int proto = RTPROT_ZEBRA;
+
+       if (dplane_ctx_get_type(ctx) != 0)
+               proto = zebra2proto(dplane_ctx_get_type(ctx));
 
        ip = dplane_ctx_neigh_get_ipaddr(ctx);
-       mac = dplane_ctx_neigh_get_mac(ctx);
-       if (is_zero_mac(mac))
-               mac = NULL;
 
+       if (dplane_ctx_get_op(ctx) == DPLANE_OP_NEIGH_IP_INSTALL
+           || dplane_ctx_get_op(ctx) == DPLANE_OP_NEIGH_IP_DELETE) {
+               link_ip = dplane_ctx_neigh_get_link_ip(ctx);
+               llalen = IPADDRSZ(link_ip);
+               link_ptr = (const void *)&(link_ip->ip.addr);
+               ipaddr2str(link_ip, buf2, sizeof(buf2));
+       } else {
+               mac = dplane_ctx_neigh_get_mac(ctx);
+               llalen = ETH_ALEN;
+               link_ptr = (const void *)mac;
+               if (is_zero_mac(mac))
+                       mac = NULL;
+               if (mac)
+                       prefix_mac2str(mac, buf2, sizeof(buf2));
+               else
+                       snprintf(buf2, sizeof(buf2), "null");
+       }
        update_flags = dplane_ctx_neigh_get_update_flags(ctx);
        flags = neigh_flags_to_netlink(dplane_ctx_neigh_get_flags(ctx));
        state = neigh_state_to_netlink(dplane_ctx_neigh_get_state(ctx));
@@ -3682,7 +3771,7 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
                 */
                if (update_flags & DPLANE_NEIGH_WAS_STATIC)
                        ext = true;
-       } else {
+       } else if (!(update_flags & DPLANE_NEIGH_NO_EXTENSION)) {
                ext = true;
                /* local neigh */
                if (update_flags & DPLANE_NEIGH_SET_STATIC)
@@ -3690,15 +3779,63 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
        }
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_debug(
-                       "Tx %s family %s IF %s(%u) Neigh %pIA MAC %pEA flags 0x%x state 0x%x %sext_flags 0x%x",
+                       "Tx %s family %s IF %s(%u) Neigh %pIA %s %s flags 0x%x state 0x%x %sext_flags 0x%x",
                        nl_msg_type_to_str(cmd), nl_family_to_str(family),
                        dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx),
-                       ip, mac, flags, state, ext ? "ext " : "", ext_flags);
+                       ip, link_ip ? "Link " : "MAC ", buf2, flags, state,
+                       ext ? "ext " : "", ext_flags);
 
        return netlink_neigh_update_msg_encode(
-               ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags, state,
-               0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, ext, ext_flags, buf,
-               buflen);
+               ctx, cmd, link_ptr, llalen, ip, true, family, RTN_UNICAST,
+               flags, state, 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, ext,
+               ext_flags, buf, buflen, proto);
+}
+
+static int netlink_neigh_table_update_ctx(const struct zebra_dplane_ctx *ctx,
+                                         void *data, size_t datalen)
+{
+       struct {
+               struct nlmsghdr n;
+               struct ndtmsg ndtm;
+               char buf[];
+       } *req = data;
+       struct rtattr *nest;
+       uint8_t family;
+       ifindex_t idx;
+       uint32_t val;
+
+       if (datalen < sizeof(*req))
+               return 0;
+       memset(req, 0, sizeof(*req));
+       family = dplane_ctx_neightable_get_family(ctx);
+       idx = dplane_ctx_get_ifindex(ctx);
+
+       req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndtmsg));
+       req->n.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE;
+       req->n.nlmsg_type = RTM_SETNEIGHTBL;
+       req->ndtm.ndtm_family = family;
+
+       nl_attr_put(&req->n, datalen, NDTA_NAME,
+                   family == AF_INET ? "arp_cache" : "ndisc_cache", 10);
+       nest = nl_attr_nest(&req->n, datalen, NDTA_PARMS);
+       if (nest == NULL)
+               return 0;
+       if (!nl_attr_put(&req->n, datalen, NDTPA_IFINDEX, &idx, sizeof(idx)))
+               return 0;
+       val = dplane_ctx_neightable_get_app_probes(ctx);
+       if (!nl_attr_put(&req->n, datalen, NDTPA_APP_PROBES, &val, sizeof(val)))
+               return 0;
+       val = dplane_ctx_neightable_get_mcast_probes(ctx);
+       if (!nl_attr_put(&req->n, datalen, NDTPA_MCAST_PROBES, &val,
+                        sizeof(val)))
+               return 0;
+       val = dplane_ctx_neightable_get_ucast_probes(ctx);
+       if (!nl_attr_put(&req->n, datalen, NDTPA_UCAST_PROBES, &val,
+                        sizeof(val)))
+               return 0;
+       nl_attr_nest_end(&req->n, nest);
+
+       return NLMSG_ALIGN(req->n.nlmsg_len);
 }
 
 static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
@@ -3710,9 +3847,11 @@ static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
        case DPLANE_OP_NEIGH_INSTALL:
        case DPLANE_OP_NEIGH_UPDATE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
                ret = netlink_neigh_update_ctx(ctx, RTM_NEWNEIGH, buf, buflen);
                break;
        case DPLANE_OP_NEIGH_DELETE:
+       case DPLANE_OP_NEIGH_IP_DELETE:
                ret = netlink_neigh_update_ctx(ctx, RTM_DELNEIGH, buf, buflen);
                break;
        case DPLANE_OP_VTEP_ADD:
@@ -3723,6 +3862,9 @@ static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
                ret = netlink_vxlan_flood_update_ctx(ctx, RTM_DELNEIGH, buf,
                                                     buflen);
                break;
+       case DPLANE_OP_NEIGH_TABLE_UPDATE:
+               ret = netlink_neigh_table_update_ctx(ctx, buf, buflen);
+               break;
        default:
                ret = -1;
        }
index a0f401c33469fb4b66f503e1fcbc7a83c3bc12b2..ada828d01688879aa0c2bb8b4adb6639cc81996d 100644 (file)
@@ -362,8 +362,14 @@ enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx)
        return ZEBRA_DPLANE_REQUEST_SUCCESS;
 }
 
-int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
-                       int llalen, ns_id_t ns_id)
+int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, bool reg)
+{
+       /* TODO */
+       return 0;
+}
+
+int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen,
+                       ns_id_t ns_id, uint8_t family, bool permanent)
 {
        /* TODO */
        return 0;
@@ -388,6 +394,12 @@ enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
        return ZEBRA_DPLANE_REQUEST_SUCCESS;
 }
 
+int kernel_configure_if_link(struct interface *ifp, struct interface *link_ifp,
+                            ns_id_t ns_id)
+{
+       return 0;
+}
+
 extern int kernel_interface_set_master(struct interface *master,
                                       struct interface *slave)
 {
index 6a582f69015b501a18ec2af225b74cf709463235..f0d1c5844f32b16bba8b672a8f1ad6c254f29693 100644 (file)
@@ -4,7 +4,6 @@
 
 if ZEBRA
 sbin_PROGRAMS += zebra/zebra
-dist_examples_DATA += zebra/zebra.conf.sample
 vtysh_scan += \
        zebra/debug.c \
        zebra/interface.c \
@@ -233,7 +232,7 @@ zebra_dplane_fpm_nl_la_SOURCES = zebra/dplane_fpm_nl.c
 zebra_dplane_fpm_nl_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 zebra_dplane_fpm_nl_la_LIBADD  =
 
-vtysh_scan += $(top_srcdir)/zebra/dplane_fpm_nl.c
+vtysh_scan += zebra/dplane_fpm_nl.c
 endif
 
 if NETLINK_DEBUG
index b482914418f9b1c5b6d053a129f1149cc39556ea..e854d7ff3a406ec18baa49f8ca434673eca8e5ff 100644 (file)
@@ -974,6 +974,37 @@ void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
        zserv_send_message(client, s);
 }
 
+void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
+                               struct ipaddr *ipaddr, int ndm_state,
+                               union sockunion *link_layer_ipv4)
+{
+       struct stream *s;
+       struct listnode *node, *nnode;
+       struct zserv *client;
+       afi_t afi;
+       union sockunion ip;
+
+       if (IS_ZEBRA_DEBUG_PACKET)
+               zlog_debug("%s: Notifying Neighbor entry (%u)",
+                          __PRETTY_FUNCTION__, cmd);
+
+       sockunion_family(&ip) = ipaddr_family(ipaddr);
+       afi = family2afi(sockunion_family(&ip));
+       memcpy((char *)sockunion_get_addr(&ip), &ipaddr->ip.addr,
+              family2addrsize(sockunion_family(&ip)));
+
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
+               if (!vrf_bitmap_check(client->nhrp_neighinfo[afi], ifp->vrf_id))
+                       continue;
+
+               s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+               zclient_neigh_ip_encode(s, cmd, &ip, link_layer_ipv4, ifp);
+               stream_putw_at(s, 0, stream_get_endp(s));
+               zserv_send_message(client, s);
+       }
+}
+
+
 /* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */
 int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,
                           vrf_id_t vrf_id)
@@ -2277,6 +2308,7 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
                        vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
                vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
                vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
+               vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
        }
 }
 
@@ -3167,6 +3199,97 @@ stream_failure:
        return;
 }
 
+
+static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS)
+{
+       afi_t afi;
+
+       STREAM_GETW(msg, afi);
+       if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
+               zlog_warn(
+                       "Invalid AFI %u while registering for neighbors notifications",
+                       afi);
+               goto stream_failure;
+       }
+       vrf_bitmap_set(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
+stream_failure:
+       return;
+}
+
+static inline void zebra_neigh_unregister(ZAPI_HANDLER_ARGS)
+{
+       afi_t afi;
+
+       STREAM_GETW(msg, afi);
+       if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
+               zlog_warn(
+                       "Invalid AFI %u while unregistering from neighbor notifications",
+                       afi);
+               goto stream_failure;
+       }
+       vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
+stream_failure:
+       return;
+}
+
+static inline void zebra_configure_arp(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       uint8_t fam;
+       ifindex_t idx;
+       struct interface *ifp;
+
+       s = msg;
+       STREAM_GETC(s, fam);
+       if (fam != AF_INET && fam != AF_INET6)
+               return;
+       STREAM_GETL(s, idx);
+       ifp = if_lookup_by_index_per_ns(zvrf->zns, idx);
+       if (!ifp)
+               return;
+       dplane_neigh_table_update(ifp, fam, 1, 0, 0);
+stream_failure:
+       return;
+}
+
+static inline void zebra_neigh_ip_add(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       struct zapi_neigh_ip api = {};
+       int ret;
+       const struct interface *ifp;
+
+       s = msg;
+       ret = zclient_neigh_ip_decode(s, &api);
+       if (ret < 0)
+               return;
+       ifp = if_lookup_by_index(api.index, zvrf_id(zvrf));
+       if (!ifp)
+               return;
+       dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_INSTALL, ifp, &api.ip_out,
+                              &api.ip_in, api.ndm_state, client->proto);
+}
+
+
+static inline void zebra_neigh_ip_del(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       struct zapi_neigh_ip api = {};
+       int ret;
+       struct interface *ifp;
+
+       s = msg;
+       ret = zclient_neigh_ip_decode(s, &api);
+       if (ret < 0)
+               return;
+       ifp = if_lookup_by_index(api.index, zvrf_id(zvrf));
+       if (!ifp)
+               return;
+       dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_DELETE, ifp, &api.ip_out,
+                              &api.ip_in, api.ndm_state, client->proto);
+}
+
+
 static inline void zread_iptable(ZAPI_HANDLER_ARGS)
 {
        struct zebra_pbr_iptable *zpi =
@@ -3352,6 +3475,11 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
        [ZEBRA_EVPN_REMOTE_NH_ADD] = zebra_evpn_proc_remote_nh,
        [ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh,
+       [ZEBRA_NEIGH_IP_ADD] = zebra_neigh_ip_add,
+       [ZEBRA_NEIGH_IP_DEL] = zebra_neigh_ip_del,
+       [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register,
+       [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister,
+       [ZEBRA_CONFIGURE_ARP] = zebra_configure_arp,
 };
 
 /*
index ca471f8d989bd1148c4a381805c15396739f38f1..0beb3cc100d8da6b4b9e2cea2f09d6aa8b902609 100644 (file)
@@ -104,6 +104,9 @@ extern int zsend_label_manager_connect_response(struct zserv *client,
 extern int zsend_sr_policy_notify_status(uint32_t color,
                                         struct ipaddr *endpoint, char *name,
                                         int status);
+extern void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
+                                      struct ipaddr *ipaddr, int ndm_state,
+                                      union sockunion *link_layer_ipv4);
 
 extern int zsend_client_close_notify(struct zserv *client,
                                     struct zserv *closed_client);
diff --git a/zebra/zebra.conf.sample b/zebra/zebra.conf.sample
deleted file mode 100644 (file)
index 03042eb..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-! -*- zebra -*-
-!
-! zebra sample configuration file
-!
-hostname Router
-password zebra
-enable password zebra
-!
-! Interface's description. 
-!
-!interface lo
-! description test of desc.
-!
-!interface sit0
-! multicast
-
-!
-! Static default route sample.
-!
-!ip route 0.0.0.0/0 203.181.89.241
-!
-
-!log file zebra.log
index 18fe0a7e853a597ae56964607f39df2cd019eedb..c8ee8f9051223ddce792441f1291209229c2d8f1 100644 (file)
@@ -220,12 +220,25 @@ struct dplane_mac_info {
  */
 struct dplane_neigh_info {
        struct ipaddr ip_addr;
-       struct ethaddr mac;
+       union {
+               struct ethaddr mac;
+               struct ipaddr ip_addr;
+       } link;
        uint32_t flags;
        uint16_t state;
        uint32_t update_flags;
 };
 
+/*
+ * Neighbor Table
+ */
+struct dplane_neigh_table {
+       uint8_t family;
+       uint32_t app_probes;
+       uint32_t ucast_probes;
+       uint32_t mcast_probes;
+};
+
 /*
  * Policy based routing rule info for the dataplane
  */
@@ -313,6 +326,7 @@ struct zebra_dplane_ctx {
                        struct zebra_pbr_ipset_entry entry;
                        struct zebra_pbr_ipset_info info;
                } ipset_entry;
+               struct dplane_neigh_table neightable;
        } u;
 
        /* Namespace info, used especially for netlink kernel communication */
@@ -452,6 +466,9 @@ static struct zebra_dplane_globals {
        _Atomic uint32_t dg_ipset_entry_in;
        _Atomic uint32_t dg_ipset_entry_errors;
 
+       _Atomic uint32_t dg_neightable_in;
+       _Atomic uint32_t dg_neightable_errors;
+
        /* Dataplane pthread */
        struct frr_pthread *dg_pthread;
 
@@ -496,12 +513,11 @@ static enum zebra_dplane_result mac_update_common(
        vlanid_t vid, const struct ethaddr *mac,
        struct in_addr vtep_ip, bool sticky, uint32_t nhg_id,
        uint32_t update_flags);
-static enum zebra_dplane_result neigh_update_internal(
-       enum dplane_op_e op,
-       const struct interface *ifp,
-       const struct ethaddr *mac,
-       const struct ipaddr *ip,
-       uint32_t flags, uint16_t state, uint32_t update_flags);
+static enum zebra_dplane_result
+neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
+                     const void *link, int link_family,
+                     const struct ipaddr *ip, uint32_t flags, uint16_t state,
+                     uint32_t update_flags, int protocol);
 
 /*
  * Public APIs
@@ -669,6 +685,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_RULE_UPDATE:
        case DPLANE_OP_NEIGH_DISCOVER:
        case DPLANE_OP_BR_PORT_UPDATE:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
        case DPLANE_OP_NONE:
        case DPLANE_OP_IPSET_ADD:
        case DPLANE_OP_IPSET_DELETE:
@@ -677,6 +695,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_IPSET_ENTRY_ADD:
        case DPLANE_OP_IPSET_ENTRY_DELETE:
                break;
+       case DPLANE_OP_NEIGH_TABLE_UPDATE:
+               break;
        case DPLANE_OP_IPTABLE_ADD:
        case DPLANE_OP_IPTABLE_DELETE:
                if (ctx->u.iptable.interface_name_list) {
@@ -950,6 +970,15 @@ const char *dplane_op2str(enum dplane_op_e op)
        case DPLANE_OP_IPSET_ENTRY_DELETE:
                ret = "IPSET_ENTRY_DELETE";
                break;
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+               ret = "NEIGH_IP_INSTALL";
+               break;
+       case DPLANE_OP_NEIGH_IP_DELETE:
+               ret = "NEIGH_IP_DELETE";
+               break;
+       case DPLANE_OP_NEIGH_TABLE_UPDATE:
+               ret = "NEIGH_TABLE_UPDATE";
+               break;
        }
 
        return ret;
@@ -1711,11 +1740,18 @@ const struct ipaddr *dplane_ctx_neigh_get_ipaddr(
        return &(ctx->u.neigh.ip_addr);
 }
 
+const struct ipaddr *
+dplane_ctx_neigh_get_link_ip(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+       return &(ctx->u.neigh.link.ip_addr);
+}
+
 const struct ethaddr *dplane_ctx_neigh_get_mac(
        const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
-       return &(ctx->u.neigh.mac);
+       return &(ctx->u.neigh.link.mac);
 }
 
 uint32_t dplane_ctx_neigh_get_flags(const struct zebra_dplane_ctx *ctx)
@@ -1978,6 +2014,37 @@ uint32_t dplane_intf_extra_get_status(const struct dplane_intf_extra *ptr)
        return ptr->status;
 }
 
+uint8_t dplane_ctx_neightable_get_family(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.neightable.family;
+}
+
+uint32_t
+dplane_ctx_neightable_get_app_probes(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.neightable.app_probes;
+}
+
+uint32_t
+dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.neightable.ucast_probes;
+}
+
+uint32_t
+dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.neightable.mcast_probes;
+}
+
 /*
  * End of interface extra info accessors
  */
@@ -3435,6 +3502,41 @@ enum zebra_dplane_result dplane_rem_mac_del(const struct interface *ifp,
        return result;
 }
 
+/*
+ * API to configure link local with either MAC address or IP information
+ */
+enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op,
+                                               const struct interface *ifp,
+                                               struct ipaddr *link_ip,
+                                               struct ipaddr *ip,
+                                               uint32_t ndm_state, int protocol)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       uint16_t state = 0;
+       uint32_t update_flags;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               char buf1[PREFIX_STRLEN], buf2[PREFIX_STRLEN];
+
+               ipaddr2str(link_ip, buf1, sizeof(buf1));
+               ipaddr2str(ip, buf2, sizeof(buf2));
+               zlog_debug("init link ctx %s: ifp %s, ip %s link %s",
+                          dplane_op2str(op), ifp->name, buf1, buf2);
+       }
+       if (ndm_state == ZEBRA_NEIGH_STATE_REACHABLE)
+               state = DPLANE_NUD_REACHABLE;
+       else if (ndm_state == ZEBRA_NEIGH_STATE_FAILED)
+               state = DPLANE_NUD_FAILED;
+
+       update_flags = DPLANE_NEIGH_NO_EXTENSION;
+
+       result = neigh_update_internal(op, ifp, (const void *)link_ip,
+                                      ipaddr_family(link_ip), ip, 0, state,
+                                      update_flags, protocol);
+
+       return result;
+}
+
 /*
  * Enqueue local mac add (or update).
  */
@@ -3584,9 +3686,9 @@ enum zebra_dplane_result dplane_rem_neigh_add(const struct interface *ifp,
        if (was_static)
                update_flags |= DPLANE_NEIGH_WAS_STATIC;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL,
-                                      ifp, mac, ip, flags, DPLANE_NUD_NOARP,
-                                      update_flags);
+       result = neigh_update_internal(
+               DPLANE_OP_NEIGH_INSTALL, ifp, (const void *)mac, AF_ETHERNET,
+               ip, flags, DPLANE_NUD_NOARP, update_flags, 0);
 
        return result;
 }
@@ -3618,9 +3720,9 @@ enum zebra_dplane_result dplane_local_neigh_add(const struct interface *ifp,
        if (set_router)
                ntf |= DPLANE_NTF_ROUTER;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL,
-                                      ifp, mac, ip, ntf,
-                                      state, update_flags);
+       result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL, ifp,
+                                      (const void *)mac, AF_ETHERNET, ip, ntf,
+                                      state, update_flags, 0);
 
        return result;
 }
@@ -3636,8 +3738,8 @@ enum zebra_dplane_result dplane_rem_neigh_delete(const struct interface *ifp,
 
        update_flags |= DPLANE_NEIGH_REMOTE;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_DELETE,
-                                      ifp, NULL, ip, 0, 0, update_flags);
+       result = neigh_update_internal(DPLANE_OP_NEIGH_DELETE, ifp, NULL,
+                                      AF_ETHERNET, ip, 0, 0, update_flags, 0);
 
        return result;
 }
@@ -3660,8 +3762,8 @@ enum zebra_dplane_result dplane_vtep_add(const struct interface *ifp,
        SET_IPADDR_V4(&addr);
        addr.ipaddr_v4 = *ip;
 
-       result = neigh_update_internal(DPLANE_OP_VTEP_ADD,
-                                      ifp, &mac, &addr, 0, 0, 0);
+       result = neigh_update_internal(DPLANE_OP_VTEP_ADD, ifp, &mac,
+                                      AF_ETHERNET, &addr, 0, 0, 0, 0);
 
        return result;
 }
@@ -3685,8 +3787,9 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
        SET_IPADDR_V4(&addr);
        addr.ipaddr_v4 = *ip;
 
-       result = neigh_update_internal(DPLANE_OP_VTEP_DELETE,
-                                      ifp, &mac, &addr, 0, 0, 0);
+       result = neigh_update_internal(DPLANE_OP_VTEP_DELETE, ifp,
+                                      (const void *)&mac, AF_ETHERNET, &addr,
+                                      0, 0, 0, 0);
 
        return result;
 }
@@ -3696,8 +3799,65 @@ enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
 {
        enum zebra_dplane_result result;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_DISCOVER, ifp, NULL, ip,
-                                      DPLANE_NTF_USE, DPLANE_NUD_INCOMPLETE, 0);
+       result = neigh_update_internal(DPLANE_OP_NEIGH_DISCOVER, ifp, NULL,
+                                      AF_ETHERNET, ip, DPLANE_NTF_USE,
+                                      DPLANE_NUD_INCOMPLETE, 0, 0);
+
+       return result;
+}
+
+enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
+                                                  const uint8_t family,
+                                                  const uint32_t app_probes,
+                                                  const uint32_t ucast_probes,
+                                                  const uint32_t mcast_probes)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       int ret;
+       struct zebra_dplane_ctx *ctx = NULL;
+       struct zebra_ns *zns;
+       enum dplane_op_e op = DPLANE_OP_NEIGH_TABLE_UPDATE;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               zlog_debug("set neigh ctx %s: ifp %s, family %s",
+                          dplane_op2str(op), ifp->name, family2str(family));
+       }
+
+       ctx = dplane_ctx_alloc();
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+       ctx->zd_vrf_id = ifp->vrf_id;
+
+       zns = zebra_ns_lookup(ifp->vrf_id);
+       dplane_ctx_ns_init(ctx, zns, false);
+
+       strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+       ctx->zd_ifindex = ifp->ifindex;
+
+       /* Init the neighbor-specific data area */
+       memset(&ctx->u.neightable, 0, sizeof(ctx->u.neightable));
+
+       ctx->u.neightable.family = family;
+       ctx->u.neightable.app_probes = app_probes;
+       ctx->u.neightable.ucast_probes = ucast_probes;
+       ctx->u.neightable.mcast_probes = mcast_probes;
+
+       /* Enqueue for processing on the dplane pthread */
+       ret = dplane_update_enqueue(ctx);
+
+       /* Increment counter */
+       atomic_fetch_add_explicit(&zdplane_info.dg_neightable_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               /* Error counter */
+               atomic_fetch_add_explicit(&zdplane_info.dg_neightable_errors, 1,
+                                         memory_order_relaxed);
+               dplane_ctx_free(&ctx);
+       }
 
        return result;
 }
@@ -3706,27 +3866,43 @@ enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
  * Common helper api for neighbor updates
  */
 static enum zebra_dplane_result
-neigh_update_internal(enum dplane_op_e op,
-                     const struct interface *ifp,
-                     const struct ethaddr *mac,
-                     const struct ipaddr *ip,
-                     uint32_t flags, uint16_t state,
-                         uint32_t update_flags)
+neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
+                     const void *link, const int link_family,
+                     const struct ipaddr *ip, uint32_t flags, uint16_t state,
+                     uint32_t update_flags, int protocol)
 {
        enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
        int ret;
        struct zebra_dplane_ctx *ctx = NULL;
        struct zebra_ns *zns;
+       const struct ethaddr *mac = NULL;
+       const struct ipaddr *link_ip = NULL;
 
-       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
-               zlog_debug("init neigh ctx %s: ifp %s, mac %pEA, ip %pIA",
-                          dplane_op2str(op), ifp->name, mac, ip);
+       if (link_family == AF_ETHERNET)
+               mac = (const struct ethaddr *)link;
+       else
+               link_ip = (const struct ipaddr *)link;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               char buf1[PREFIX_STRLEN];
+
+               buf1[0] = '\0';
+               if (link_family == AF_ETHERNET)
+                       prefix_mac2str(mac, buf1, sizeof(buf1));
+               else
+                       ipaddr2str(link_ip, buf1, sizeof(buf1));
+               zlog_debug("init neigh ctx %s: ifp %s, %s %s, ip %pIA",
+                          dplane_op2str(op), ifp->name,
+                          link_family == AF_ETHERNET ? "mac " : "link ",
+                          buf1, ip);
+       }
 
        ctx = dplane_ctx_alloc();
 
        ctx->zd_op = op;
        ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
        ctx->zd_vrf_id = ifp->vrf_id;
+       dplane_ctx_set_type(ctx, protocol);
 
        zns = zebra_ns_lookup(ifp->vrf_id);
        dplane_ctx_ns_init(ctx, zns, false);
@@ -3739,7 +3915,10 @@ neigh_update_internal(enum dplane_op_e op,
 
        ctx->u.neigh.ip_addr = *ip;
        if (mac)
-               ctx->u.neigh.mac = *mac;
+               ctx->u.neigh.link.mac = *mac;
+       else if (link_ip)
+               ctx->u.neigh.link.ip_addr = *link_ip;
+
        ctx->u.neigh.flags = flags;
        ctx->u.neigh.state = state;
        ctx->u.neigh.update_flags = update_flags;
@@ -4048,6 +4227,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)
                                    memory_order_relaxed);
        vty_out(vty, "IPset entry updates:             %" PRIu64 "\n", incoming);
        vty_out(vty, "IPset entry errors:              %" PRIu64 "\n", errs);
+
+       incoming = atomic_load_explicit(&zdplane_info.dg_neightable_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_neightable_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "Neighbor Table updates:       %"PRIu64"\n", incoming);
+       vty_out(vty, "Neighbor Table errors:        %"PRIu64"\n", errs);
        return CMD_SUCCESS;
 }
 
@@ -4433,6 +4619,8 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
                ipaddr2str(dplane_ctx_neigh_get_ipaddr(ctx), buf,
                           sizeof(buf));
 
@@ -4485,6 +4673,13 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
                                   dplane_op2str(dplane_ctx_get_op(ctx)),
                                   ipent.unique, ctx);
        } break;
+
+       case DPLANE_OP_NEIGH_TABLE_UPDATE:
+               zlog_debug("Dplane neigh table op %s, ifp %s, family %s",
+                          dplane_op2str(dplane_ctx_get_op(ctx)),
+                          dplane_ctx_get_ifname(ctx),
+                          family2str(dplane_ctx_neightable_get_family(ctx)));
+               break;
        }
 }
 
@@ -4568,6 +4763,8 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
                if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
                        atomic_fetch_add_explicit(&zdplane_info.dg_neigh_errors,
                                                  1, memory_order_relaxed);
@@ -4604,6 +4801,13 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
                                memory_order_relaxed);
                break;
 
+       case DPLANE_OP_NEIGH_TABLE_UPDATE:
+               if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+                       atomic_fetch_add_explicit(
+                               &zdplane_info.dg_neightable_errors, 1,
+                               memory_order_relaxed);
+               break;
+
        /* Ignore 'notifications' - no-op */
        case DPLANE_OP_SYS_ROUTE_ADD:
        case DPLANE_OP_SYS_ROUTE_DELETE:
index 4913ca251f83b548d3c4bdb5592b35fe03fad8af..8d51d93cd4bfcd8ac4ad0e1b6aee61ecf47f5eba 100644 (file)
@@ -165,6 +165,12 @@ enum dplane_op_e {
        DPLANE_OP_IPSET_DELETE,
        DPLANE_OP_IPSET_ENTRY_ADD,
        DPLANE_OP_IPSET_ENTRY_DELETE,
+
+       /* LINK LAYER IP address update */
+       DPLANE_OP_NEIGH_IP_INSTALL,
+       DPLANE_OP_NEIGH_IP_DELETE,
+
+       DPLANE_OP_NEIGH_TABLE_UPDATE,
 };
 
 /*
@@ -184,6 +190,8 @@ enum dplane_op_e {
 #define DPLANE_NUD_NOARP          0x04
 #define DPLANE_NUD_PROBE          0x08
 #define DPLANE_NUD_INCOMPLETE     0x10
+#define DPLANE_NUD_PERMANENT      0x20
+#define DPLANE_NUD_FAILED         0x40
 
 /* MAC update flags - dplane_mac_info.update_flags */
 #define DPLANE_MAC_REMOTE       (1 << 0)
@@ -196,6 +204,7 @@ enum dplane_op_e {
 #define DPLANE_NEIGH_WAS_STATIC   (1 << 1)
 #define DPLANE_NEIGH_SET_STATIC   (1 << 2)
 #define DPLANE_NEIGH_SET_INACTIVE (1 << 3)
+#define DPLANE_NEIGH_NO_EXTENSION (1 << 4)
 
 #define DPLANE_BR_PORT_NON_DF (1 << 0)
 
@@ -458,6 +467,8 @@ const struct ipaddr *dplane_ctx_neigh_get_ipaddr(
        const struct zebra_dplane_ctx *ctx);
 const struct ethaddr *dplane_ctx_neigh_get_mac(
        const struct zebra_dplane_ctx *ctx);
+const struct ipaddr *
+dplane_ctx_neigh_get_link_ip(const struct zebra_dplane_ctx *ctx);
 uint32_t dplane_ctx_neigh_get_flags(const struct zebra_dplane_ctx *ctx);
 uint16_t dplane_ctx_neigh_get_state(const struct zebra_dplane_ctx *ctx);
 uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx);
@@ -507,6 +518,15 @@ dplane_ctx_get_br_port_sph_filters(const struct zebra_dplane_ctx *ctx);
 uint32_t
 dplane_ctx_get_br_port_backup_nhg_id(const struct zebra_dplane_ctx *ctx);
 
+/* Accessors for neighbor table information */
+uint8_t dplane_ctx_neightable_get_family(const struct zebra_dplane_ctx *ctx);
+uint32_t
+dplane_ctx_neightable_get_app_probes(const struct zebra_dplane_ctx *ctx);
+uint32_t
+dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx);
+uint32_t
+dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx);
+
 /* Namespace info - esp. for netlink communication */
 const struct zebra_dplane_info *dplane_ctx_get_ns(
        const struct zebra_dplane_ctx *ctx);
@@ -584,6 +604,16 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp,
 enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
                                                const struct connected *ifc);
 
+/*
+ * Link layer operations for the dataplane.
+ */
+enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op,
+                                               const struct interface *ifp,
+                                               struct ipaddr *link_ip,
+                                               struct ipaddr *ip,
+                                               uint32_t ndm_state,
+                                               int protocol);
+
 /*
  * Enqueue evpn mac operations for the dataplane.
  */
@@ -656,6 +686,15 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
 enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
                                               const struct ipaddr *ip);
 
+/*
+ * Enqueue a neighbor table parameter set
+ */
+enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
+                                                  const uint8_t family,
+                                                  const uint32_t app_probes,
+                                                  const uint32_t ucast_probes,
+                                                  const uint32_t mcast_probes);
+
 /* Forward ref of zebra_pbr_rule */
 struct zebra_pbr_rule;
 
index 12ed024a661ea3986dc027b700b907157bcbe8dc..7edf022892839a8e0afde5e88286be16a60f9001 100644 (file)
@@ -2898,6 +2898,8 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_NEIGH_INSTALL:
        case DPLANE_OP_NEIGH_UPDATE:
        case DPLANE_OP_NEIGH_DELETE:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_RULE_ADD:
@@ -2912,6 +2914,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_IPSET_DELETE:
        case DPLANE_OP_IPSET_ENTRY_ADD:
        case DPLANE_OP_IPSET_ENTRY_DELETE:
+       case DPLANE_OP_NEIGH_TABLE_UPDATE:
                break;
        }
 
index ffe4be8557fd9d37bffeffeb8abb2ac730533d76..82a0e6d015701e1f74352d5fa98b2c55d86a25b1 100644 (file)
@@ -3924,10 +3924,13 @@ static int rib_process_dplane_results(struct thread *thread)
                        case DPLANE_OP_NEIGH_INSTALL:
                        case DPLANE_OP_NEIGH_UPDATE:
                        case DPLANE_OP_NEIGH_DELETE:
+                       case DPLANE_OP_NEIGH_IP_INSTALL:
+                       case DPLANE_OP_NEIGH_IP_DELETE:
                        case DPLANE_OP_VTEP_ADD:
                        case DPLANE_OP_VTEP_DELETE:
                        case DPLANE_OP_NEIGH_DISCOVER:
                        case DPLANE_OP_BR_PORT_UPDATE:
+                       case DPLANE_OP_NEIGH_TABLE_UPDATE:
                        case DPLANE_OP_NONE:
                                /* Don't expect this: just return the struct? */
                                dplane_ctx_fini(&ctx);
index 6c5eebe6fe696477b8a4983848586405db8dbc12..f89b6fe478313ebca5439705b35b3dace1a0af59 100644 (file)
@@ -638,6 +638,7 @@ static void zserv_client_free(struct zserv *client)
 
                vrf_bitmap_free(client->redist_default[afi]);
                vrf_bitmap_free(client->ridinfo[afi]);
+               vrf_bitmap_free(client->nhrp_neighinfo[afi]);
        }
 
        /*
@@ -760,6 +761,7 @@ static struct zserv *zserv_client_create(int sock)
                        client->redist[afi][i] = vrf_bitmap_init();
                client->redist_default[afi] = vrf_bitmap_init();
                client->ridinfo[afi] = vrf_bitmap_init();
+               client->nhrp_neighinfo[afi] = vrf_bitmap_init();
        }
 
        /* Add this client to linked list. */
index c60799b8ba8dff2f11632d1aa6c0fba85b36765f..203670ac1dd5186f33c376c1424aa62004cbb83c 100644 (file)
@@ -137,6 +137,9 @@ struct zserv {
        /* Router-id information. */
        vrf_bitmap_t ridinfo[AFI_MAX];
 
+       /* Router-id information. */
+       vrf_bitmap_t nhrp_neighinfo[AFI_MAX];
+
        bool notify_owner;
 
        /* Indicates if client is synchronous. */