Skip to content

Commit

Permalink
Merge pull request #820 from kernelkit/ospf-container
Browse files Browse the repository at this point in the history
Ospf container
  • Loading branch information
mattiaswal authored Nov 25, 2024
2 parents 260d961 + de50179 commit 68c86c8
Show file tree
Hide file tree
Showing 28 changed files with 2,512 additions and 101 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
/test/.venv
/test/.log
/local.mk
/test/spec/Readme.adoc
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ it maintenance-free. Configuration and data, e.g, containers, is stored
on separate partitions to ensure complete separation from system files
and allow for seamless backup, restore, and provisioning.

In itself Infix is perfectly suited for dedicated networking tasks and
native support for Docker containers provides a versatile platform that
can easily be adapted to any customer need. Be it legacy applications,
network protocols, process monitoring, or edge data analysis, it can run
close to end equipment. Either directly connected on dedicated Ethernet
ports or indirectly using virtual network cables to exist on the same
LAN as other connected equipment.
In itself, Infix is perfectly suited for dedicated networking tasks, and
with native support for Docker containers, the operating system provides
a versatile platform that can easily be adapted to any customer need.
Be it legacy applications, network protocols, process monitoring, or
edge data analysis, it can run close to end equipment. Either directly
connected on dedicated Ethernet ports or indirectly using virtual
network cables to exist on the same LAN as other connected equipment.

The simple design of Infix provides complete control over both system
and data, minimal cognitive burden, and makes it incredibly easy to get
Expand Down
3 changes: 2 additions & 1 deletion board/x86_64/linux_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ CONFIG_KALLSYMS_ALL=y
CONFIG_PROFILING=y
CONFIG_SMP=y
CONFIG_EFI=y
CONFIG_KPROBES=y
# CONFIG_GCC_PLUGINS is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
Expand Down Expand Up @@ -264,5 +265,5 @@ CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=20
CONFIG_DETECT_HUNG_TASK=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
# CONFIG_FTRACE is not set
CONFIG_FUNCTION_TRACER=y
CONFIG_UNWINDER_FRAME_POINTER=y
6 changes: 6 additions & 0 deletions src/confd/src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,14 @@ int core_post_hook(sr_session_ctx_t *session, uint32_t sub_id, const char *modul
num_changes = 0;
return SR_ERR_OK;
case SR_EV_DONE:
if (num_changes <= 0) {
ERROR("BUG in core_post_hook(): callback tracking out of sync");
abort();
}

if (--num_changes == 0)
break;

return SR_ERR_OK;
default:
ERROR("core_post_hook() should not be called with event %s", ev2str(event));
Expand Down
6 changes: 4 additions & 2 deletions src/statd/python/yanger/yanger.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,12 @@ def add_ospf(control_protocols):
neighbor = {}
neighbor["neighbor-router-id"] = neigh["neighborIp"]
neighbor["address"] = neigh["ifaceAddress"]
neighbor["dr-router-id"] = neigh["routerDesignatedId"]
neighbor["bdr-router-id"] = neigh["routerDesignatedBackupId"]
neighbor["dead-timer"] = neigh["routerDeadIntervalTimerDueMsec"]
neighbor["state"] = frr_to_ietf_neighbor_state(neigh["nbrState"])
if neigh.get("routerDesignatedId"):
neighbor["dr-router-id"] = neigh["routerDesignatedId"]
if neigh.get("routerDesignatedBackupId"):
neighbor["bdr-router-id"] = neigh["routerDesignatedBackupId"]
neighbors.append(neighbor)

interface["ietf-ospf:neighbors"] = {}
Expand Down
3 changes: 3 additions & 0 deletions test/case/all.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@

- name: infix-services
suite: infix_services/infix_services.yaml

- name: use-cases
suite: use_case/use_case.yml
28 changes: 2 additions & 26 deletions test/case/ietf_system/upgrade/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@
Verify it is possible to upgrade.
"""
import concurrent.futures
import functools
import http.server
import os
import socket
import time

import netifaces

import infamy
import infamy.file_server as srv

SRVPORT = 8008

Expand All @@ -27,25 +22,6 @@
"package"
)

class FileServer(http.server.HTTPServer):
class RequestHandler(http.server.SimpleHTTPRequestHandler):
def log_message(*args, **kwargs):
pass

address_family = socket.AF_INET6

def __init__(self, server_address, directory):
rh = functools.partial(FileServer.RequestHandler, directory=directory)
self.__tp = concurrent.futures.ThreadPoolExecutor(max_workers=1)
super().__init__(server_address, rh)

def __enter__(self):
self.__tp.submit(self.serve_forever)

def __exit__(self, _, __, ___):
self.shutdown()
self.__tp.shutdown()

with infamy.Test() as test:
with test.step("Set up topology and attach to target DUT"):
env = infamy.Env()
Expand All @@ -66,7 +42,7 @@ def __exit__(self, _, __, ___):
hip = netifaces.ifaddresses(hport)[netifaces.AF_INET6][0]["addr"]
hip = hip.replace(f"%{hport}", f"%{tport}")

with FileServer(("::", SRVPORT), BUNDLEDIR):
with srv.FileServer(("::", SRVPORT), BUNDLEDIR):

with test.step("Start installation of selected package"):
print(f"Installing {os.path.basename(env.args.package)}")
Expand Down
8 changes: 8 additions & 0 deletions test/case/use_case/Readme.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
:testgroup:

== Use case tests
Contains test of multiple parts of Infix together.

<<<

include::ospf_container/Readme.adoc[]
98 changes: 98 additions & 0 deletions test/case/use_case/ospf_container/Readme.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
=== OSPF Container
==== Description
This use-case test verifies connectivity in an OSPF network to services
running as hosted containers inside each router.

NOTE: The _Controller_, _ABR_, and `data` connections are simulated by
the test PC. The `ringN` ports are connected to other DUTs via the test
PC, which can act as a link breaker.

.Use-case overview.
[#img-overview]
ifdef::topdoc[]
image::../../test/case/use_case/ospf_container/overview.svg[]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::ospf_container/overview.svg[]
endif::testgroup[]
ifndef::testgroup[]
image::overview.svg[]
endif::testgroup[]
endif::topdoc[]

The DUTs are connected in a routed topology inside their own OSPF area.
A single area border router (ABR) is used to access the controller
network in OSPF area 0. Each router also has "test point" connections
where the controller can attach other than its connection in area 0.

- The ringN ports are intended to be connected to neighboring DUTs, but
may at each end of the bus be used as test points
- The data ports are intended to be test points for verifying
connectivity with container B via br1
- The uplink ports are for connecting to the ABR, at least one of the
DUTs should not have a connection to the ABR, this to verify routing
via another DUT
- Area 1 is 10.1.Rn.0/16, and each router is assigned a /24

Each DUT hosts one application container and one system container, all
have the same setup, with only different subnets assigned. A third
container is used to manipulate the firewall of each DUT, providing port
forwarding and masquerading.

Devices attached to the first bridge, `br0`, are supposed to be easily
accesible using IPv4, so internally they use IPv4 too, and to avoid any
risk of clashing with external IP subnets, IPv4 link-local addresses are
employed: `br0` request 169.254.1.1, so the second container (B) always
can reach it, the first container (A) reqquest 169.254.1.2 and the
second (B) request 169.254.1.3. The network for devices attached to the
second bridge, `br1`, only use IPv6 link-local addresses.

.Internal network setup, here router R1 on subnet 10.1.1.1/24.
[#img-setup]
ifdef::topdoc[]
image::../../test/case/use_case/ospf_container/internal-network.svg[Internal networks]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::ospf_container/internal-network.svg[Internal networks]
endif::testgroup[]
ifndef::testgroup[]
image::internal-network.svg[Internal networks]
endif::testgroup[]
endif::topdoc[]

- *Container A* runs a very basic web server, it runs on port 80 inside
the container, and `br0`, but is accessible outside on port 8080.
The controller connects to each of these servers from OSPF area 0.
For the controller to be able to distinguish between the servers,
they all serve slightly different content
- *Container B* runs a complete system with an SSH server. During the
test, the controller connects to this container using the `data` port
to ensure the container can access all other parts of the network.
To distinguish between the different container B's, each container
will have a unique hostname derived from the chassis MAC address

==== Topology
ifdef::topdoc[]
image::../../test/case/use_case/ospf_container/topology.svg[OSPF Container topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::ospf_container/topology.svg[OSPF Container topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[OSPF Container topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUTs
. Configure DUTs
. Wait for all routers to peer
. Verify ABR:data can access container A on R1 (10.1.1.101)
. Verify ABR:data can access container A on R2 (10.1.2.101)
. Verify ABR:data can access container A on R3 (10.1.3.101)


<<<

4 changes: 4 additions & 0 deletions test/case/use_case/ospf_container/internal-network.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 68c86c8

Please sign in to comment.