Files
infix/dev/test-arch/index.html
T

2940 lines
73 KiB
HTML

<!DOCTYPE html><html lang="en" class="no-js"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Infix Documentation">
<link rel="canonical" href="https://kernelkit.github.io/infix/dev/test-arch/">
<link rel="prev" href="../testing/">
<link rel="next" href="../virtual/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.6">
<title>Test System Architecture - User's Guide</title>
<link rel="stylesheet" href="../assets/stylesheets/main.484c7ddc.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.ab4e12ef.min.css">
<link rel="stylesheet" href="../extra.css">
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<link href="../assets/stylesheets/glightbox.min.css" rel="stylesheet"><script src="../assets/javascripts/glightbox.min.js"></script><style id="glightbox-style">
html.glightbox-open { overflow: initial; height: 100%; }
.gslide-title { margin-top: 0px; user-select: text; }
.gslide-desc { color: #666; user-select: text; }
.gslide-image img { background: black; }
.glightbox-clean .gslide-media { -webkit-box-shadow: none; box-shadow: none; }
.gscrollbar-fixer { padding-right: 15px; }
.gdesc-inner { font-size: 0.75rem; }
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color); }
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color); }
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color); }
</style></head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="orange" data-md-color-accent="orange">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#test-system-architecture" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<div data-md-color-scheme="default" data-md-component="outdated" hidden="">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="https://www.kernelkit.org/" title="User's Guide" class="md-header__button md-logo" aria-label="User's Guide" data-md-component="logo">
<img src="../logo-plain.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"></path></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
User's Guide
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Test System Architecture
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="orange" data-md-color-accent="orange" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31"></path></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="orange" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z"></path></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required="">
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"></path></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard="" data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"></path></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix="">
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/kernelkit/infix/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
kernelkit/infix
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="https://www.kernelkit.org/" title="User's Guide" class="md-nav__button md-logo" aria-label="User's Guide" data-md-component="logo">
<img src="../logo-plain.png" alt="logo">
</a>
User's Guide
</label>
<div class="md-nav__source">
<a href="https://github.com/kernelkit/infix/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
kernelkit/infix
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
CLI
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
CLI
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../cli/introduction/" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/configure/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/keybindings/" class="md-nav__link">
<span class="md-ellipsis">
Keybindings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/netcalc/" class="md-nav__link">
<span class="md-ellipsis">
Network Calculator
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/tcpdump/" class="md-nav__link">
<span class="md-ellipsis">
Network Monitoring
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/quick/" class="md-nav__link">
<span class="md-ellipsis">
Quickstart Guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/text-editor/" class="md-nav__link">
<span class="md-ellipsis">
Text Editor
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/upgrade/" class="md-nav__link">
<span class="md-ellipsis">
Upgrading
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../container/" class="md-nav__link">
<span class="md-ellipsis">
Docker Containers
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4">
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Networking
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Networking
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../networking/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../iface/" class="md-nav__link">
<span class="md-ellipsis">
Common Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../bridging/" class="md-nav__link">
<span class="md-ellipsis">
Bridging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../lag/" class="md-nav__link">
<span class="md-ellipsis">
Link Aggregation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ethernet/" class="md-nav__link">
<span class="md-ellipsis">
Ethernet Interfaces
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vlan/" class="md-nav__link">
<span class="md-ellipsis">
VLAN Interfaces
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ip/" class="md-nav__link">
<span class="md-ellipsis">
IP Addressing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../routing/" class="md-nav__link">
<span class="md-ellipsis">
Routing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../firewall/" class="md-nav__link">
<span class="md-ellipsis">
Firewall Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../qos/" class="md-nav__link">
<span class="md-ellipsis">
Quality of Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../eth-counters/" class="md-nav__link">
<span class="md-ellipsis">
RMON Counters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tunnels/" class="md-nav__link">
<span class="md-ellipsis">
Tunneling (L2/L3)
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_13">
<label class="md-nav__link" for="__nav_4_13" id="__nav_4_13_label" tabindex="0">
<span class="md-ellipsis">
VPN Tunnels
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4_13">
<span class="md-nav__icon md-icon"></span>
VPN Tunnels
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../vpn/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vpn-wireguard/" class="md-nav__link">
<span class="md-ellipsis">
WireGuard
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../wifi/" class="md-nav__link">
<span class="md-ellipsis">
Wireless LAN (WiFi)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5">
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Services
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../discovery/" class="md-nav__link">
<span class="md-ellipsis">
Device Discovery
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dhcp/" class="md-nav__link">
<span class="md-ellipsis">
DHCP Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ntp/" class="md-nav__link">
<span class="md-ellipsis">
NTP Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ptp/" class="md-nav__link">
<span class="md-ellipsis">
PTP (IEEE 1588/802.1AS)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6">
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
System
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
System
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../boot/" class="md-nav__link">
<span class="md-ellipsis">
Boot Procedure
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../system/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../nacm/" class="md-nav__link">
<span class="md-ellipsis">
Access Control (NACM)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../hardware/" class="md-nav__link">
<span class="md-ellipsis">
Hardware Info &amp; Status
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../management/" class="md-nav__link">
<span class="md-ellipsis">
Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../keystore/" class="md-nav__link">
<span class="md-ellipsis">
Keystore
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../syslog/" class="md-nav__link">
<span class="md-ellipsis">
Syslog Support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../support/" class="md-nav__link">
<span class="md-ellipsis">
Support Data
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../upgrade/" class="md-nav__link">
<span class="md-ellipsis">
Upgrade
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7">
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Scripting
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Scripting
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../scripting/" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-sysrepocfg/" class="md-nav__link">
<span class="md-ellipsis">
Legacy Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-netconf/" class="md-nav__link">
<span class="md-ellipsis">
NETCONF Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-restconf/" class="md-nav__link">
<span class="md-ellipsis">
RESTCONF Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-prod/" class="md-nav__link">
<span class="md-ellipsis">
Production Testing
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" checked="">
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
<span class="md-ellipsis">
Developer's Corner
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Developer's Corner
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../branding/" class="md-nav__link">
<span class="md-ellipsis">
Branding &amp; Releases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../developers-guide/" class="md-nav__link">
<span class="md-ellipsis">
Developer's Guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../override-package/" class="md-nav__link">
<span class="md-ellipsis">
Developing with Buildroot
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../netboot/" class="md-nav__link">
<span class="md-ellipsis">
Netboot HowTo
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../testing/" class="md-nav__link">
<span class="md-ellipsis">
Regression Testing
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Test System Architecture
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Test System Architecture
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#tenets" class="md-nav__link">
<span class="md-ellipsis">
Tenets
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
<nav class="md-nav" aria-label="Overview">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#test-cases" class="md-nav__link">
<span class="md-ellipsis">
Test Cases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#infamy" class="md-nav__link">
<span class="md-ellipsis">
Infamy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#9pm" class="md-nav__link">
<span class="md-ellipsis">
9PM
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#testenv" class="md-nav__link">
<span class="md-ellipsis">
/test/env
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#physical-and-logical-topologies" class="md-nav__link">
<span class="md-ellipsis">
Physical and Logical Topologies
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#integration-to-infix" class="md-nav__link">
<span class="md-ellipsis">
Integration to Infix
</span>
</a>
<nav class="md-nav" aria-label="Integration to Infix">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#test-mode" class="md-nav__link">
<span class="md-ellipsis">
Test Mode
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-mode-on-virtual-devices" class="md-nav__link">
<span class="md-ellipsis">
Test Mode on Virtual Devices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-mode-on-physical-devices" class="md-nav__link">
<span class="md-ellipsis">
Test Mode on Physical Devices
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../virtual/" class="md-nav__link">
<span class="md-ellipsis">
Virtual Environments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vpd/" class="md-nav__link">
<span class="md-ellipsis">
Vital Product Data (VPD)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../license/" class="md-nav__link">
<span class="md-ellipsis">
Origin &amp; Licensing
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#tenets" class="md-nav__link">
<span class="md-ellipsis">
Tenets
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
<nav class="md-nav" aria-label="Overview">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#test-cases" class="md-nav__link">
<span class="md-ellipsis">
Test Cases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#infamy" class="md-nav__link">
<span class="md-ellipsis">
Infamy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#9pm" class="md-nav__link">
<span class="md-ellipsis">
9PM
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#testenv" class="md-nav__link">
<span class="md-ellipsis">
/test/env
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#physical-and-logical-topologies" class="md-nav__link">
<span class="md-ellipsis">
Physical and Logical Topologies
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#integration-to-infix" class="md-nav__link">
<span class="md-ellipsis">
Integration to Infix
</span>
</a>
<nav class="md-nav" aria-label="Integration to Infix">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#test-mode" class="md-nav__link">
<span class="md-ellipsis">
Test Mode
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-mode-on-virtual-devices" class="md-nav__link">
<span class="md-ellipsis">
Test Mode on Virtual Devices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-mode-on-physical-devices" class="md-nav__link">
<span class="md-ellipsis">
Test Mode on Physical Devices
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<nav class="md-path" aria-label="Navigation">
<ol class="md-path__list">
<li class="md-path__item">
<a href=".." class="md-path__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-path__item">
<a href="../branding/" class="md-path__link">
<span class="md-ellipsis">
Developer's Corner
</span>
</a>
</li>
</ol>
</nav>
<article class="md-content__inner md-typeset">
<h1 id="test-system-architecture">Test System Architecture<a class="headerlink" href="#test-system-architecture" title="Permanent link"></a></h1>
<h2 id="tenets">Tenets<a class="headerlink" href="#tenets" title="Permanent link"></a></h2>
<ul>
<li>
<p><strong>Keep overhead to a minimum</strong>. Tests should be fast to both write
and run. Ideally, the developer should <em>want</em> to add tests early in
the development cycle because they instinctively feel that that is
the quickest route to arrive at a correct and robust implementation.</p>
</li>
<li>
<p><strong>Both physical and virtual hardware matters</strong>. Infix is primarily
deployed on physical hardware, so being able to run the test suite
on real devices is crucial to guarantee a high quality product. At
the same time, there is much value in running the same suite on
virtual hardware, as it makes it easy to catch regressions early.
It is also much more practical and economical to build large virtual
networks than physical ones.</p>
</li>
<li>
<p><strong>Avoid CLI scripting &amp; scraping</strong>. Reliably interacting with a DUT
over a serial line in a robust way is <em>very</em> hard to get right.
Given that we have a proper API (RESTCONF), we should leverage that
when testing. Front-ends can be tested by other means.</p>
</li>
</ul>
<h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link"></a></h2>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/testing-overview.svg" data-desc-position="bottom"><img alt="Infix Testing Architecture" src="../img/testing-overview.svg"></a></p>
<p>The test system is made up of several independent components, which
are typically used in concert to run a full test suite.</p>
<h3 id="test-cases">Test Cases<a class="headerlink" href="#test-cases" title="Permanent link"></a></h3>
<p>A test case is an executable, receiving the physical topology as a
positional argument, which produces <a href="https://testanything.org/">TAP</a> compliant output on its
<code>stdout</code>. I.e., it is executed in the following manner:</p>
<div class="highlight"><pre><span></span><code>test-case [OPTS] &lt;physical-topology&gt;
</code></pre></div>
<p>Test cases are typically written in Python, using the
<a href="#infamy">Infamy</a> library. Ultimately though, it can be implemented
in any language, as long as it matches the calling convention above.</p>
<h3 id="infamy">Infamy<a class="headerlink" href="#infamy" title="Permanent link"></a></h3>
<p>Rather than having each test case come up with its own implementation
of how to map topologies, how to push NETCONF data to a device, etc.,
we provide a library of functions to take care of all that, dubbed
"Infamy". When adding a new test case, ask yourself if any parts of
it might belong in Infamy as a generalized component that can be
reused by other tests.</p>
<p>Some of the core functions provided by Infamy are:</p>
<ul>
<li>Mapping a logical topology to a physical one</li>
<li>Finding and attaching to a device over an Ethernet interface, using
NETCONF</li>
<li>Pushing/pulling NETCONF data to/from a device</li>
<li>Generating TAP compliant output</li>
</ul>
<h3 id="9pm">9PM<a class="headerlink" href="#9pm" title="Permanent link"></a></h3>
<p>To run multiple tests, we employ <a href="https://github.com/rical/9pm">9PM</a>. It let's us define test
suites as simple YAML files. Suites can also be hierarchically
structured, with a suite being made up of other suites, etc.</p>
<p>It also validates the TAP output, making sure to catch early exits
from a case, and produces a nice summary report.</p>
<h3 id="testenv"><code>/test/env</code><a class="headerlink" href="#testenv" title="Permanent link"></a></h3>
<p>A good way to ensure that nobody ever runs the test suite is to make
it <em>really</em> hard to do so. <code>/test/env</code>'s job is instead to make it
very <em>easy</em> to create a reproducible environment in which tests can be
executed.</p>
<p>Several technologies are leveraged to accomplish this:</p>
<ul>
<li>
<p><strong>Containers</strong>: The entire execution is optionally done inside a
standardized <code>docker</code> container environment. This ensures that the
software needed to run the test suite is always available, no matter
which distribution the user is running on their machine.</p>
</li>
<li>
<p><strong>Python Virtual Environments</strong>: To make sure that the expected
versions of all Python packages are available, the execution is
wrapped inside a <code>venv</code>. This is true for containerized executions,
where the container comes with a pre-installed environment, but it
can also be sourced from the host system when running outside of the
container.</p>
</li>
<li>
<p><strong>Virtual Test Topology</strong>: Using <a href="https://github.com/wkz/qeneth">Qeneth</a>, the environment can
optionally be started with a virtual topology of DUTs to run the
tests on.</p>
</li>
</ul>
<blockquote>
<p><code>docker</code> is the only supported container environment when running
tests in the host's network namespace. When running on a virtual
Qeneth topology, <code>podman</code> may also be used by installing the
<code>podman-docker</code> package from your host system's distro.</p>
</blockquote>
<h2 id="physical-and-logical-topologies">Physical and Logical Topologies<a class="headerlink" href="#physical-and-logical-topologies" title="Permanent link"></a></h2>
<p>Imagine that we want to create a test with three DUTs; one acting as a
DHCP server, and the other two as DHCP clients - with all three having
a management connection to the host PC running the test. In other
words, the test requires a <em>logical</em> topology like the one below.</p>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/testing-log.svg" data-desc-position="bottom"><img align="right" alt="Example Logical Topology" src="../img/testing-log.svg" width="360"></a></p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="k">graph</span><span class="w"> </span><span class="nt">"dhcp-client-server"</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="w"> </span><span class="nt">host</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"host | { &lt;c1&gt; c1 | &lt;srv&gt; srv | &lt;c2&gt; c2 }"</span><span class="p">,</span>
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"controller"</span><span class="p">,</span>
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a>
<a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a><span class="w"> </span><span class="nt">server</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"{ &lt;mgmt&gt; mgmt } | server | { &lt;c1&gt; c1 | &lt;c2&gt; c2 }"</span><span class="p">,</span>
<a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"infix"</span><span class="p">,</span>
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a><span class="w"> </span><span class="nt">client1</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"{ &lt;mgmt&gt; mgmt } | client1 | { &lt;srv&gt; srv }"</span><span class="p">,</span>
<a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"infix"</span><span class="p">,</span>
<a id="__codelineno-0-14" name="__codelineno-0-14" href="#__codelineno-0-14"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></a><span class="w"> </span><span class="nt">client2</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-0-16" name="__codelineno-0-16" href="#__codelineno-0-16"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"{ &lt;mgmt&gt; mgmt } | client2 | { &lt;srv&gt; srv }"</span><span class="p">,</span>
<a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"infix"</span><span class="p">,</span>
<a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-0-19" name="__codelineno-0-19" href="#__codelineno-0-19"></a>
<a id="__codelineno-0-20" name="__codelineno-0-20" href="#__codelineno-0-20"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">srv</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">server</span><span class="p">:</span><span class="nt">mgmt</span>
<a id="__codelineno-0-21" name="__codelineno-0-21" href="#__codelineno-0-21"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">c1</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">client1</span><span class="p">:</span><span class="nt">mgmt</span>
<a id="__codelineno-0-22" name="__codelineno-0-22" href="#__codelineno-0-22"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">c2</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">client2</span><span class="p">:</span><span class="nt">mgmt</span>
<a id="__codelineno-0-23" name="__codelineno-0-23" href="#__codelineno-0-23"></a>
<a id="__codelineno-0-24" name="__codelineno-0-24" href="#__codelineno-0-24"></a><span class="w"> </span><span class="nt">server</span><span class="p">:</span><span class="nt">c1</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">client1</span><span class="p">:</span><span class="nt">srv</span><span class="p">;</span>
<a id="__codelineno-0-25" name="__codelineno-0-25" href="#__codelineno-0-25"></a><span class="w"> </span><span class="nt">server</span><span class="p">:</span><span class="nt">c2</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">client2</span><span class="p">:</span><span class="nt">srv</span><span class="p">;</span>
<a id="__codelineno-0-26" name="__codelineno-0-26" href="#__codelineno-0-26"></a><span class="p">}</span>
</code></pre></div>
<p>When running in a virtualized environment, one could simply create a
setup that matches the test's logical topology. But in scenarios when
devices are physical systems, connected by real copper cables, this is
not possible (unless you have some wicked L1 relay matrix thingy).</p>
<p>Instead, the test implementation does not concern itself with the
exact nodes used to run the test, only that the <em>logical</em> topology can
be <em>mapped</em> to some subset of the <em>physical</em> topology. In
mathematical terms, the physical topology must contain a subgraph that
is <em>isomorphic</em> to the logical topology.</p>
<p>Standing on the shoulders of giants (i.e. people with mathematics
degrees), we can deploy well-known algorithms to find such subgraphs.
Continuing our example, let's say we want to run our DHCP test on the
<em>physical</em> topology below.</p>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/testing-phy.svg" data-desc-position="bottom"><img align="right" alt="Example Physical Topology" src="../img/testing-phy.svg" width="360"></a></p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="k">graph</span><span class="w"> </span><span class="nt">"quad-ring"</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="w"> </span><span class="nt">host</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"host | { &lt;d1a&gt; d1a | &lt;d1b&gt; d1b | &lt;d1c&gt; d1c | &lt;d2a&gt; d2a | &lt;d2b&gt; d2b | &lt;d2c&gt; d2c | &lt;d3a&gt; d3a | &lt;d3b&gt; d3b | &lt;d3c&gt; d3c | &lt;d4a&gt; d4a | &lt;d4b&gt; d4b | &lt;d4c&gt; d4c }"</span><span class="p">,</span>
<a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"controller"</span><span class="p">,</span>
<a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a>
<a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a><span class="w"> </span><span class="nt">dut1</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"{ &lt;e1&gt; e1 | &lt;e2&gt; e2 | &lt;e3&gt; e3 } | dut1 | { &lt;e4&gt; e4 | &lt;e5&gt; e5 }"</span><span class="p">,</span>
<a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"infix"</span><span class="p">,</span>
<a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-1-11" name="__codelineno-1-11" href="#__codelineno-1-11"></a><span class="w"> </span><span class="nt">dut2</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-1-12" name="__codelineno-1-12" href="#__codelineno-1-12"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"{ &lt;e1&gt; e1 | &lt;e2&gt; e2 | &lt;e3&gt; e3 } | dut2 | { &lt;e4&gt; e4 | &lt;e5&gt; e5 }"</span><span class="p">,</span>
<a id="__codelineno-1-13" name="__codelineno-1-13" href="#__codelineno-1-13"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"infix"</span><span class="p">,</span>
<a id="__codelineno-1-14" name="__codelineno-1-14" href="#__codelineno-1-14"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-1-15" name="__codelineno-1-15" href="#__codelineno-1-15"></a><span class="w"> </span><span class="nt">dut3</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-1-16" name="__codelineno-1-16" href="#__codelineno-1-16"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"{ &lt;e1&gt; e1 | &lt;e2&gt; e2 | &lt;e3&gt; e3 } | dut3 | { &lt;e4&gt; e4 | &lt;e5&gt; e5 }"</span><span class="p">,</span>
<a id="__codelineno-1-17" name="__codelineno-1-17" href="#__codelineno-1-17"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"infix"</span><span class="p">,</span>
<a id="__codelineno-1-18" name="__codelineno-1-18" href="#__codelineno-1-18"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-1-19" name="__codelineno-1-19" href="#__codelineno-1-19"></a><span class="w"> </span><span class="nt">dut4</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-1-20" name="__codelineno-1-20" href="#__codelineno-1-20"></a><span class="w"> </span><span class="na">label</span><span class="p">=</span><span class="s2">"{ &lt;e1&gt; e1 | &lt;e2&gt; e2 | &lt;e3&gt; e3 } | dut4 | { &lt;e4&gt; e4 | &lt;e5&gt; e5 }"</span><span class="p">,</span>
<a id="__codelineno-1-21" name="__codelineno-1-21" href="#__codelineno-1-21"></a><span class="w"> </span><span class="na">kind</span><span class="p">=</span><span class="s2">"infix"</span><span class="p">,</span>
<a id="__codelineno-1-22" name="__codelineno-1-22" href="#__codelineno-1-22"></a><span class="w"> </span><span class="p">];</span>
<a id="__codelineno-1-23" name="__codelineno-1-23" href="#__codelineno-1-23"></a>
<a id="__codelineno-1-24" name="__codelineno-1-24" href="#__codelineno-1-24"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d1a</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut1</span><span class="p">:</span><span class="nt">e1</span>
<a id="__codelineno-1-25" name="__codelineno-1-25" href="#__codelineno-1-25"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d1b</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut1</span><span class="p">:</span><span class="nt">e2</span>
<a id="__codelineno-1-26" name="__codelineno-1-26" href="#__codelineno-1-26"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d1c</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut1</span><span class="p">:</span><span class="nt">e3</span>
<a id="__codelineno-1-27" name="__codelineno-1-27" href="#__codelineno-1-27"></a>
<a id="__codelineno-1-28" name="__codelineno-1-28" href="#__codelineno-1-28"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d2a</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut2</span><span class="p">:</span><span class="nt">e1</span>
<a id="__codelineno-1-29" name="__codelineno-1-29" href="#__codelineno-1-29"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d2b</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut2</span><span class="p">:</span><span class="nt">e2</span>
<a id="__codelineno-1-30" name="__codelineno-1-30" href="#__codelineno-1-30"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d2c</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut2</span><span class="p">:</span><span class="nt">e3</span>
<a id="__codelineno-1-31" name="__codelineno-1-31" href="#__codelineno-1-31"></a>
<a id="__codelineno-1-32" name="__codelineno-1-32" href="#__codelineno-1-32"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d3a</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut3</span><span class="p">:</span><span class="nt">e1</span>
<a id="__codelineno-1-33" name="__codelineno-1-33" href="#__codelineno-1-33"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d3b</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut3</span><span class="p">:</span><span class="nt">e2</span>
<a id="__codelineno-1-34" name="__codelineno-1-34" href="#__codelineno-1-34"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d3c</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut3</span><span class="p">:</span><span class="nt">e3</span>
<a id="__codelineno-1-35" name="__codelineno-1-35" href="#__codelineno-1-35"></a>
<a id="__codelineno-1-36" name="__codelineno-1-36" href="#__codelineno-1-36"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d4a</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut4</span><span class="p">:</span><span class="nt">e1</span>
<a id="__codelineno-1-37" name="__codelineno-1-37" href="#__codelineno-1-37"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d4b</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut4</span><span class="p">:</span><span class="nt">e2</span>
<a id="__codelineno-1-38" name="__codelineno-1-38" href="#__codelineno-1-38"></a><span class="w"> </span><span class="nt">host</span><span class="p">:</span><span class="nt">d4c</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut4</span><span class="p">:</span><span class="nt">e3</span>
<a id="__codelineno-1-39" name="__codelineno-1-39" href="#__codelineno-1-39"></a>
<a id="__codelineno-1-40" name="__codelineno-1-40" href="#__codelineno-1-40"></a><span class="w"> </span><span class="nt">dut1</span><span class="p">:</span><span class="nt">e5</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut2</span><span class="p">:</span><span class="nt">e4</span>
<a id="__codelineno-1-41" name="__codelineno-1-41" href="#__codelineno-1-41"></a><span class="w"> </span><span class="nt">dut2</span><span class="p">:</span><span class="nt">e5</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut3</span><span class="p">:</span><span class="nt">e4</span>
<a id="__codelineno-1-42" name="__codelineno-1-42" href="#__codelineno-1-42"></a><span class="w"> </span><span class="nt">dut3</span><span class="p">:</span><span class="nt">e5</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut4</span><span class="p">:</span><span class="nt">e4</span>
<a id="__codelineno-1-43" name="__codelineno-1-43" href="#__codelineno-1-43"></a><span class="w"> </span><span class="nt">dut4</span><span class="p">:</span><span class="nt">e5</span><span class="w"> </span><span class="o">--</span><span class="w"> </span><span class="nt">dut1</span><span class="p">:</span><span class="nt">e4</span>
<a id="__codelineno-1-44" name="__codelineno-1-44" href="#__codelineno-1-44"></a><span class="p">}</span>
</code></pre></div>
<p>Our test (in fact, all tests) receives the physical topology as an
input parameter, and then maps the desired logical topology onto it,
producing a mapping from logical nodes and ports to their physical
counterparts.</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="p">{</span>
<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="w"> </span><span class="nt">"client1"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut1"</span><span class="p">,</span>
<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="w"> </span><span class="nt">"client1:mgmt"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut1:e1"</span><span class="p">,</span>
<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a><span class="w"> </span><span class="nt">"client1:srv"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut1:e4"</span><span class="p">,</span>
<a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a><span class="w"> </span><span class="nt">"client2"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut3"</span><span class="p">,</span>
<a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a><span class="w"> </span><span class="nt">"client2:mgmt"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut3:e2"</span><span class="p">,</span>
<a id="__codelineno-2-7" name="__codelineno-2-7" href="#__codelineno-2-7"></a><span class="w"> </span><span class="nt">"client2:srv"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut3:e5"</span><span class="p">,</span>
<a id="__codelineno-2-8" name="__codelineno-2-8" href="#__codelineno-2-8"></a><span class="w"> </span><span class="nt">"host"</span><span class="p">:</span><span class="w"> </span><span class="nt">"host"</span><span class="p">,</span>
<a id="__codelineno-2-9" name="__codelineno-2-9" href="#__codelineno-2-9"></a><span class="w"> </span><span class="nt">"host:c1"</span><span class="p">:</span><span class="w"> </span><span class="nt">"host:d1a"</span><span class="p">,</span>
<a id="__codelineno-2-10" name="__codelineno-2-10" href="#__codelineno-2-10"></a><span class="w"> </span><span class="nt">"host:c2"</span><span class="p">:</span><span class="w"> </span><span class="nt">"host:d3b"</span><span class="p">,</span>
<a id="__codelineno-2-11" name="__codelineno-2-11" href="#__codelineno-2-11"></a><span class="w"> </span><span class="nt">"host:srv"</span><span class="p">:</span><span class="w"> </span><span class="nt">"host:d4c"</span><span class="p">,</span>
<a id="__codelineno-2-12" name="__codelineno-2-12" href="#__codelineno-2-12"></a><span class="w"> </span><span class="nt">"server"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut4"</span><span class="p">,</span>
<a id="__codelineno-2-13" name="__codelineno-2-13" href="#__codelineno-2-13"></a><span class="w"> </span><span class="nt">"server:c1"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut4:e5"</span><span class="p">,</span>
<a id="__codelineno-2-14" name="__codelineno-2-14" href="#__codelineno-2-14"></a><span class="w"> </span><span class="nt">"server:c2"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut4:e4"</span><span class="p">,</span>
<a id="__codelineno-2-15" name="__codelineno-2-15" href="#__codelineno-2-15"></a><span class="w"> </span><span class="nt">"server:mgmt"</span><span class="p">:</span><span class="w"> </span><span class="nt">"dut4:e3"</span>
<a id="__codelineno-2-16" name="__codelineno-2-16" href="#__codelineno-2-16"></a><span class="p">}</span>
</code></pre></div>
<p>With this information, the test knows that, in this particular
environment, the server should be managed via the port called <code>d4c</code> on
the node called <code>host</code>; that the port connected to the server on
<code>client1</code> is <code>e4</code> on <code>dut1</code>, etc. Thereby separating the
implementation of the test from any specific physical setup.</p>
<p>Testcases are not required to use a logical topology; they may choose
to accept whatever physical topology its given, and dynamically
determine the DUTs to use for testing. As an example, an STP test
could accept an arbitrary physical topology, run the STP algorithm on
it offline, enable STP on all DUTs, and then verify that the resulting
spanning tree matches the expected one.</p>
<h2 id="integration-to-infix">Integration to Infix<a class="headerlink" href="#integration-to-infix" title="Permanent link"></a></h2>
<h3 id="test-mode">Test Mode<a class="headerlink" href="#test-mode" title="Permanent link"></a></h3>
<p>Infix supports a <em>test mode</em> that makes devices safe and predictable to
test against. When active, each boot starts from a known-good
<code>test-config</code> (equivalent to the failure/secure config) instead of the
stored startup or factory configuration. This prevents any persistent
configuration from interfering with tests and avoids L2 loops that a
factory config might create. It also enables two extra RPCs used by
Infamy:</p>
<ul>
<li><code>infix-test:test/reset</code> — reload the <code>test-config</code> into the running
datastore (called by <code>env.attach()</code> at the start of each test)</li>
<li><code>infix-test:test/override-startup</code> — boot from the startup datastore
once, instead of the <code>test-config</code> (used by tests that verify
save-and-reboot behaviour)</li>
</ul>
<p>Test mode is activated by the presence of an empty file named
<code>test-mode</code> on the device's <code>aux</code> partition (<code>/mnt/aux/test-mode</code>).</p>
<h3 id="test-mode-on-virtual-devices">Test Mode on Virtual Devices<a class="headerlink" href="#test-mode-on-virtual-devices" title="Permanent link"></a></h3>
<p>When the test environment is started with Qeneth, the <code>inject-test-mode</code>
script (<code>test/inject-test-mode</code>) is run automatically. It copies the
base disk image and writes the <code>test-mode</code> marker into the <code>aux</code>
partition of that copy, which is then used as the Qeneth backing image.</p>
<h3 id="test-mode-on-physical-devices">Test Mode on Physical Devices<a class="headerlink" href="#test-mode-on-physical-devices" title="Permanent link"></a></h3>
<p>For a physical device, log in as <code>root</code> (or <code>admin</code>) and create the
marker file on the <code>aux</code> partition, then reboot:</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a># touch /mnt/aux/test-mode
<a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a># reboot
</code></pre></div>
<p>Alternatively, if you want to prepare the disk image before flashing,
use the <code>inject-test-mode</code> script:</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a>$ test/inject-test-mode -b infix-&lt;board&gt;.img -o infix-&lt;board&gt;-test.img
</code></pre></div>
<p>Flash <code>infix-&lt;board&gt;-test.img</code> to the device instead of the plain
image. The device will boot into test mode on first power-on.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Test mode persists across reboots until the marker file is removed
(<code>rm /mnt/aux/test-mode</code>). A device in test mode always starts from
the <code>test-config</code>, so any configuration changes are lost on reboot
unless <code>startup_override()</code> is called first (or the marker is removed
and a normal startup config is saved).</p>
</div>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright © 2022-2026 The KernelKit Team
</div>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<script id="__config" type="application/json">{"annotate": null, "base": "..", "features": ["toc.follow", "navigation.path", "navigation.instant", "navigation.instant.progress", "navigation.tracking", "navigation.indexes", "search.highlight", "search.share", "content.code.copy", "content.code.annotate", "content.footnote.tooltips"], "search": "../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
<script src="../assets/javascripts/bundle.79ae519e.min.js"></script>
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
document$.subscribe(()=>{ lightbox.reload(); });
</script></body></html>