Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to test dplane_fpm_nl.c file #15369

Merged
merged 8 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,8 @@ AC_ARG_ENABLE([mgmtd_local_validations],
AS_HELP_STRING([--enable-mgmtd-local-validations], [dev: unimplemented local validation]))
AC_ARG_ENABLE([mgmtd_test_be_client],
AS_HELP_STRING([--enable-mgmtd-test-be-client], [build test backend client]))
AC_ARG_ENABLE([fpm_listener],
AS_HELP_STRING([--enable-fpm-listener], [build fpm listener test program]))
AC_ARG_ENABLE([ripd],
AS_HELP_STRING([--disable-ripd], [do not build ripd]))
AC_ARG_ENABLE([ripngd],
Expand Down Expand Up @@ -1811,6 +1813,10 @@ AS_IF([test "$enable_mgmtd_test_be_client" = "yes"], [
AC_DEFINE([HAVE_MGMTD_TESTC], [1], [mgmtd_testc])
])

AS_IF([test "$enable_fpm_listener" = "yes"], [
AC_DEFINE([HAVE_FPM_LISTENER], [1], [fpm_listener])
])

AS_IF([test "$enable_ripd" != "no"], [
AC_DEFINE([HAVE_RIPD], [1], [ripd])
])
Expand Down Expand Up @@ -2773,6 +2779,7 @@ AM_CONDITIONAL([ZEBRA], [test "$enable_zebra" != "no"])
AM_CONDITIONAL([BGPD], [test "$enable_bgpd" != "no"])
AM_CONDITIONAL([MGMTD], [test "$enable_mgmtd" != "no"])
AM_CONDITIONAL([MGMTD_TESTC], [test "$enable_mgmtd_test_be_client" = "yes"])
AM_CONDITIONAL([FPM_LISTENER], [test "enable_fpm_listener" = "yes"])
AM_CONDITIONAL([RIPD], [test "$enable_ripd" != "no"])
AM_CONDITIONAL([OSPFD], [test "$enable_ospfd" != "no"])
AM_CONDITIONAL([LDPD], [test "$enable_ldpd" != "no"])
Expand Down
8 changes: 8 additions & 0 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ Description: FRRouting suite - BGP RPKI support (rtrlib)
number.
Build-Profiles: <!pkg.frr.nortrlib>

Package: frr-test-tools
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't be good for RPM too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent 2 seconds looking at it and decided I have no idea how to do this in rpm land. If someone needs this as part of the rpm stuff, then they can add it. I feel it is ok for this approach because of the low usage of rpms

Architecture: linux-any
Depends: frr (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends}
Description: FRRouting suite - Testing Tools
Adds FRR test tools, used in testing FRR.

Package: frr-doc
Section: doc
Architecture: all
Expand Down
1 change: 1 addition & 0 deletions debian/frr-test-tools.install
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
usr/lib/frr/fpm_listener
9 changes: 0 additions & 9 deletions doc/developer/checkpatch.rst
Original file line number Diff line number Diff line change
Expand Up @@ -761,15 +761,6 @@ Indentation and Line Breaks
Macros, Attributes and Symbols
------------------------------

**ARRAY_SIZE**
The ARRAY_SIZE(foo) macro should be preferred over
sizeof(foo)/sizeof(foo[0]) for finding number of elements in an
array.

The macro is defined in include/linux/kernel.h::

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

**AVOID_EXTERNS**
Function prototypes don't need to be declared extern in .h
files. It's assumed by the compiler and is unnecessary.
Expand Down
4 changes: 4 additions & 0 deletions doc/user/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ options from the list below.

Build with FPM module support.

.. option:: --enable-fpm-listener

Build a small fpm listener for testing.

.. option:: --with-service-timeout=X

Set timeout value for FRR service. The time of restarting or reloading FRR
Expand Down
3 changes: 3 additions & 0 deletions doc/user/zebra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,9 @@ FPM Commands
User FPM configurations: 1
User FPM disable requests: 0

.. clicmd:: show fpm status [json]

Show the FPM status.

.. clicmd:: clear fpm counters

Expand Down
1 change: 1 addition & 0 deletions redhat/frr.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ fi
%{_sbindir}/mgmtd_testc
%endif
%exclude %{_sbindir}/ssd
%exclude %{_sbindir}/fpm_listener
%if %{with_watchfrr}
%{_sbindir}/watchfrr
%endif
Expand Down
8 changes: 8 additions & 0 deletions tests/topotests/fpm_testing_topo1/r1/fpm_counters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"connected":true,
"useNHG":true,
"useRouteReplace":true,
"disabled":false,
"address":"127.0.0.1",
"port":2620
}
Empty file.
27 changes: 27 additions & 0 deletions tests/topotests/fpm_testing_topo1/r1/routes_summ.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"routes":[
{
"fib":1,
"rib":1,
"fibOffLoaded":0,
"fibTrapped":0,
"type":"connected"
},
{
"fib":1,
"rib":1,
"fibOffLoaded":0,
"fibTrapped":0,
"type":"local"
},
{
"fib":10000,
"rib":10000,
"fibOffLoaded":0,
"fibTrapped":0,
"type":"sharp"
}
],
"routesTotal":10002,
"routesTotalFib":10002
}
20 changes: 20 additions & 0 deletions tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"routes":[
{
"fib":1,
"rib":1,
"fibOffLoaded":0,
"fibTrapped":0,
"type":"connected"
},
{
"fib":1,
"rib":1,
"fibOffLoaded":0,
"fibTrapped":0,
"type":"local"
}
],
"routesTotal":2,
"routesTotalFib":2
}
Empty file.
5 changes: 5 additions & 0 deletions tests/topotests/fpm_testing_topo1/r1/zebra.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fpm address 127.0.0.1

interface r1-eth0
ip address 192.168.44.1/24
!
134 changes: 134 additions & 0 deletions tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env python
# SPDX-License-Identifier: ISC

#
# test_route_scale1.py
#
# Copyright (c) 2024 by
# Nvidia, Inc.
# Donald Sharp
#

"""
test_fpm_topo1.py: Testing FPM module

"""
import os
import re
import sys
import pytest
import json
from functools import partial

# 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


pytestmark = [pytest.mark.fpm, pytest.mark.sharpd]


def build_topo(tgen):
"Build function"

# Populate routers
tgen.add_router("r1")

switch = tgen.add_switch("sw1")
switch.add_link(tgen.gears["r1"])


def setup_module(module):
"Setup topology"

# fpm_stub = os.system("which fpm-stub")
# if fpm-stub:
# pytest.skip("")

tgen = Topogen(build_topo, module.__name__)
tgen.start_topology()

router_list = tgen.routers()
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA,
os.path.join(CWD, "{}/zebra.conf".format(rname)),
"-M dplane_fpm_nl",
)
router.load_config(
TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
)
router.load_config(
TopoRouter.RD_FPM_LISTENER, os.path.join(CWD, "{}/fpm_stub.conf".format(rname))
)

tgen.start_router()


def teardown_module(_mod):
"Teardown the pytest environment"

tgen = get_topogen()

# This function tears down the whole topology.
tgen.stop_topology()


def test_fpm_connection_made():
"Test that the fpm starts up and a connection is made"

tgen = get_topogen()
router = tgen.gears["r1"]

fpm_counters = "{}/r1/fpm_counters.json".format(CWD)
expected = json.loads(open(fpm_counters).read())

test_func = partial(
topotest.router_json_cmp, router, "show fpm status json", expected
)

success, result = topotest.run_and_expect(test_func, None, 30, 1)
assert success, "Unable to connect to the fpm:\n{}".format(result)


def test_fpm_install_routes():
"Test that simple routes installed appears to work"

tgen = get_topogen()
router = tgen.gears["r1"]

# Let's install 10000 routes
router.vtysh_cmd("sharp install routes 10.0.0.0 nexthop 192.168.44.33 10000")
routes_file = "{}/r1/routes_summ.json".format(CWD)
expected = json.loads(open(routes_file).read())

test_func = partial(
topotest.router_json_cmp, router, "show ip route summ json", expected
)

success, result = topotest.run_and_expect(test_func, None, 60, 1)
assert success, "Unable to successfully install 10000 routes: {}".format(result)

# Let's remove 10000 routes
router.vtysh_cmd("sharp remove routes 10.0.0.0 10000")

routes_file_removed = "{}/r1/routes_summ_removed.json".format(CWD)
expected = json.loads(open(routes_file_removed).read())

test_func = partial(
topotest.router_json_cmp, router, "show ip route summ json", expected
)

success, result = topotest.run_and_expect(test_func, None, 60, 1)
assert success, "Unable to remove 10000 routes: {}".format(result)


if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
14 changes: 11 additions & 3 deletions tests/topotests/lib/topogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ class TopoRouter(TopoGear):
RD_PIM6 = 19
RD_MGMTD = 20
RD_TRAP = 21
RD_FPM_LISTENER = 22
RD = {
RD_FRR: "frr",
RD_ZEBRA: "zebra",
Expand All @@ -771,6 +772,7 @@ class TopoRouter(TopoGear):
RD_SNMP: "snmpd",
RD_MGMTD: "mgmtd",
RD_TRAP: "snmptrapd",
RD_FPM_LISTENER: "fpm_listener",
}

def __init__(self, tgen, cls, name, **params):
Expand Down Expand Up @@ -847,7 +849,8 @@ def load_config(self, daemon, source=None, param=None):
TopoRouter.RD_RIPNG, TopoRouter.RD_OSPF, TopoRouter.RD_OSPF6,
TopoRouter.RD_ISIS, TopoRouter.RD_BGP, TopoRouter.RD_LDP,
TopoRouter.RD_PIM, TopoRouter.RD_PIM6, TopoRouter.RD_PBR,
TopoRouter.RD_SNMP, TopoRouter.RD_MGMTD, TopoRouter.RD_TRAP.
TopoRouter.RD_SNMP, TopoRouter.RD_MGMTD, TopoRouter.RD_TRAP,
TopoRouter.RD_FPM_LISTENER.

Possible `source` values are `None` for an empty config file, a path name which is
used directly, or a file name with no path components which is first looked for
Expand Down Expand Up @@ -885,7 +888,12 @@ def start(self):
# Enable all daemon command logging, logging files
# and set them to the start dir.
for daemon, enabled in nrouter.daemons.items():
if enabled and daemon != "snmpd" and daemon != "snmptrapd":
if (
enabled
and daemon != "snmpd"
and daemon != "snmptrapd"
and daemon != "fpm_listener"
):
self.vtysh_cmd(
"\n".join(
[
Expand Down Expand Up @@ -935,7 +943,7 @@ def startDaemons(self, daemons):
# and set them to the start dir.
for daemon in daemons:
enabled = nrouter.daemons[daemon]
if enabled and daemon != "snmpd":
if enabled and daemon != "snmpd" and daemon != "fpm_listener":
self.vtysh_cmd(
"\n".join(
[
Expand Down
Loading
Loading