mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-06 07:33:01 +02:00
test: add some basic ptp tests
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
include::ieee1588.adoc[]
|
||||
|
||||
<<<
|
||||
|
||||
include::ieee802dot1as.adoc[]
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
=== PTP basic (IEEE 1588)
|
||||
|
||||
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/ptp/basic]
|
||||
|
||||
==== Description
|
||||
|
||||
Verify basic PTP operation end-to-end: clock configuration, port state
|
||||
transitions, and clock servo convergence.
|
||||
|
||||
Two Ordinary Clocks are connected back-to-back. The grandmaster is
|
||||
configured with `priority1=1` so it always wins the BTCA election; the
|
||||
time receiver is configured with `time-receiver-only` so it never
|
||||
attempts to become grandmaster. The test is run once per supported
|
||||
profile, covering both IEEE 1588-2019 (UDP/IPv4, E2E) and IEEE 802.1AS
|
||||
(Layer 2, P2P).
|
||||
|
||||
==== Topology
|
||||
|
||||
image::topology.svg[PTP basic (IEEE 1588) topology, align=center, scaledwidth=75%]
|
||||
|
||||
==== Sequence
|
||||
|
||||
. Set up topology and attach to DUTs
|
||||
. Configure grandmaster (OC, ieee1588, priority1=1) and time receiver (ieee1588, priority1=128, client-only)
|
||||
. Wait for grandmaster and time receiver ports to reach active states
|
||||
. Wait for time receiver offset to converge
|
||||
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
test.py
|
||||
@@ -0,0 +1,28 @@
|
||||
=== PTP basic (IEEE 802.1AS)
|
||||
|
||||
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/ptp/basic]
|
||||
|
||||
==== Description
|
||||
|
||||
Verify basic PTP operation end-to-end: clock configuration, port state
|
||||
transitions, and clock servo convergence.
|
||||
|
||||
Two Ordinary Clocks are connected back-to-back. The grandmaster is
|
||||
configured with `priority1=1` so it always wins the BTCA election; the
|
||||
time receiver is configured with `time-receiver-only` so it never
|
||||
attempts to become grandmaster. The test is run once per supported
|
||||
profile, covering both IEEE 1588-2019 (UDP/IPv4, E2E) and IEEE 802.1AS
|
||||
(Layer 2, P2P).
|
||||
|
||||
==== Topology
|
||||
|
||||
image::topology.svg[PTP basic (IEEE 802.1AS) topology, align=center, scaledwidth=75%]
|
||||
|
||||
==== Sequence
|
||||
|
||||
. Set up topology and attach to DUTs
|
||||
. Configure grandmaster (OC, ieee802-dot1as, priority1=1) and time receiver (ieee802-dot1as, priority1=128, client-only)
|
||||
. Wait for grandmaster and time receiver ports to reach active states
|
||||
. Wait for time receiver offset to converge
|
||||
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
test.py
|
||||
@@ -0,0 +1,29 @@
|
||||
=== PTP basic
|
||||
|
||||
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/ptp/basic]
|
||||
|
||||
==== Description
|
||||
|
||||
Verify basic PTP operation end-to-end: clock configuration, port state
|
||||
transitions, and clock servo convergence.
|
||||
|
||||
Two Ordinary Clocks are connected back-to-back. The grandmaster is
|
||||
configured with `priority1=1` so it always wins the BTCA election; the
|
||||
time receiver is configured with `time-receiver-only` so it never
|
||||
attempts to become grandmaster. Software timestamping is used, making
|
||||
the test suitable for virtual machines as well as real hardware.
|
||||
|
||||
This is the smoke test: if it passes, the full PTP stack is working.
|
||||
|
||||
==== Topology
|
||||
|
||||
image::topology.svg[PTP basic topology, align=center, scaledwidth=75%]
|
||||
|
||||
==== Sequence
|
||||
|
||||
. Set up topology and attach to DUTs
|
||||
. Configure grandmaster (priority1=1) and time receiver (priority1=128, client-only)
|
||||
. Wait for grandmaster and time receiver ports to reach active states
|
||||
. Wait for time receiver offset to converge
|
||||
|
||||
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
"""PTP basic
|
||||
|
||||
Verify basic PTP operation end-to-end: clock configuration, port state
|
||||
transitions, and clock servo convergence.
|
||||
|
||||
Two Ordinary Clocks are connected back-to-back. The grandmaster is
|
||||
configured with `priority1=1` so it always wins the BTCA election; the
|
||||
time receiver is configured with `time-receiver-only` so it never
|
||||
attempts to become grandmaster. The test is run once per supported
|
||||
profile, covering both IEEE 1588-2019 (UDP/IPv4, E2E) and IEEE 802.1AS
|
||||
(Layer 2, P2P).
|
||||
"""
|
||||
|
||||
import infamy
|
||||
import infamy.ptp as ptp
|
||||
from infamy import until
|
||||
from infamy.util import parallel
|
||||
|
||||
|
||||
class ArgumentParser(infamy.ArgumentParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.args.add_argument("--profile", default="ieee1588",
|
||||
choices=["ieee1588", "ieee802-dot1as"])
|
||||
self.args.add_argument("--threshold-ns", type=int, default=None)
|
||||
|
||||
|
||||
def configure_oc(iface, priority1, client_only, profile, ip=None):
|
||||
config = {
|
||||
"ieee1588-ptp-tt": {
|
||||
"ptp": {
|
||||
"instances": {
|
||||
"instance": [{
|
||||
"instance-index": 0,
|
||||
"default-ds": {
|
||||
"instance-type": "oc",
|
||||
"domain-number": 0,
|
||||
"priority1": priority1,
|
||||
"priority2": 128,
|
||||
"infix-ptp:profile": profile,
|
||||
"time-receiver-only": client_only,
|
||||
},
|
||||
"ports": {
|
||||
"port": [{
|
||||
"port-index": 1,
|
||||
"underlying-interface": iface,
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Always enable the underlying interface — ptp4l needs it up regardless
|
||||
# of profile. IEEE 1588 also needs an IPv4 address for UDP transport.
|
||||
iface_cfg = {"name": iface, "enabled": True}
|
||||
if profile == "ieee1588":
|
||||
iface_cfg["ipv4"] = {"address": [{"ip": ip, "prefix-length": 30}]}
|
||||
config["ietf-interfaces"] = {
|
||||
"interfaces": {"interface": [iface_cfg]}
|
||||
}
|
||||
|
||||
# Fast timers: 250 ms announce/sync intervals speed up port state transitions
|
||||
# and convergence compared to the 1 s defaults.
|
||||
port_ds = {
|
||||
"log-announce-interval": -2,
|
||||
"announce-receipt-timeout": 2,
|
||||
"log-sync-interval": -2,
|
||||
}
|
||||
if profile == "ieee1588":
|
||||
port_ds["delay-mechanism"] = "e2e"
|
||||
config["ieee1588-ptp-tt"]["ptp"]["instances"]["instance"][0] \
|
||||
["ports"]["port"][0]["port-ds"] = port_ds
|
||||
|
||||
return config
|
||||
|
||||
|
||||
with infamy.Test() as test:
|
||||
with test.step("Set up topology and attach to DUTs"):
|
||||
arg = ArgumentParser()
|
||||
env = infamy.Env(args=arg)
|
||||
profile = env.args.profile
|
||||
gm = env.attach("gm", "mgmt")
|
||||
receiver = env.attach("receiver", "mgmt")
|
||||
|
||||
_, gm_iface = env.ltop.xlate("gm", "data")
|
||||
_, receiver_iface = env.ltop.xlate("receiver", "data")
|
||||
threshold_ns = env.args.threshold_ns or ptp.default_threshold(env, "receiver")
|
||||
|
||||
with test.step(f"Configure grandmaster (OC, {profile}, priority1=1) and time receiver ({profile}, priority1=128, client-only)"):
|
||||
gm.put_config_dicts(configure_oc(gm_iface, priority1=1,
|
||||
client_only=False, profile=profile,
|
||||
ip="192.168.100.1"))
|
||||
receiver.put_config_dicts(configure_oc(receiver_iface, priority1=128,
|
||||
client_only=True, profile=profile,
|
||||
ip="192.168.100.2"))
|
||||
|
||||
with test.step("Wait for grandmaster and time receiver ports to reach active states"):
|
||||
parallel(lambda: until(lambda: ptp.is_time_transmitter(gm), attempts=60),
|
||||
lambda: until(lambda: ptp.is_time_receiver(receiver), attempts=60))
|
||||
|
||||
with test.step("Wait for time receiver offset to converge"):
|
||||
until(lambda: ptp.has_converged(receiver, threshold_ns), attempts=120)
|
||||
|
||||
test.succeed()
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- settings:
|
||||
test-spec: <case>.adoc
|
||||
|
||||
- name: PTP basic (IEEE 1588)
|
||||
case: ieee1588.py
|
||||
opts: ["--profile", "ieee1588"]
|
||||
|
||||
- name: PTP basic (IEEE 802.1AS)
|
||||
case: ieee802dot1as.py
|
||||
opts: ["--profile", "ieee802-dot1as"]
|
||||
@@ -0,0 +1,33 @@
|
||||
graph "ptp-basic" {
|
||||
layout="neato";
|
||||
overlap="false";
|
||||
esep="+22";
|
||||
|
||||
node [shape=record, fontname="DejaVu Sans Mono, Book"];
|
||||
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
|
||||
|
||||
host [
|
||||
label="{ <mgmt1> mgmt1 | <host> \n\nhost\n\n\n | <mgmt2> mgmt2 }",
|
||||
pos="0,15!",
|
||||
requires="controller",
|
||||
];
|
||||
|
||||
gm [
|
||||
label="{ <mgmt> mgmt | <data> data } | { gm\npriority1=1 }",
|
||||
pos="2,15.25!",
|
||||
fontsize=12,
|
||||
requires="infix",
|
||||
];
|
||||
|
||||
receiver [
|
||||
label="{ <data> data | <mgmt> mgmt } | { receiver\npriority1=128 }",
|
||||
pos="2,14.75!",
|
||||
fontsize=12,
|
||||
requires="infix",
|
||||
];
|
||||
|
||||
host:mgmt1 -- gm:mgmt [requires="mgmt", color="lightgray"]
|
||||
host:mgmt2 -- receiver:mgmt [requires="mgmt", color="lightgray"]
|
||||
|
||||
gm:data -- receiver:data [label="\n\n192.168.100.0/30 ", dir="both"]
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<!-- Title: ptp-basic Pages: 1 -->
|
||||
<svg width="510pt" height="149pt"
|
||||
viewBox="0.00 0.00 509.54 149.01" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 145.01)">
|
||||
<title>ptp-basic</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-145.01 505.54,-145.01 505.54,4 -4,4"/>
|
||||
<!-- host -->
|
||||
<g id="node1" class="node">
|
||||
<title>host</title>
|
||||
<polygon fill="none" stroke="black" points="0,-4 0,-137 58,-137 58,-4 0,-4"/>
|
||||
<text text-anchor="middle" x="29" y="-121.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt1</text>
|
||||
<polyline fill="none" stroke="black" points="0,-114 58,-114 "/>
|
||||
<text text-anchor="middle" x="29" y="-66.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">host</text>
|
||||
<polyline fill="none" stroke="black" points="0,-27 58,-27 "/>
|
||||
<text text-anchor="middle" x="29" y="-11.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt2</text>
|
||||
</g>
|
||||
<!-- gm -->
|
||||
<g id="node2" class="node">
|
||||
<title>gm</title>
|
||||
<polygon fill="none" stroke="black" points="348.04,-98.51 348.04,-140.51 494.04,-140.51 494.04,-98.51 348.04,-98.51"/>
|
||||
<text text-anchor="middle" x="371.54" y="-126.91" font-family="DejaVu Sans Mono, Book" font-size="12.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="348.04,-119.51 395.04,-119.51 "/>
|
||||
<text text-anchor="middle" x="371.54" y="-105.91" font-family="DejaVu Sans Mono, Book" font-size="12.00">data</text>
|
||||
<polyline fill="none" stroke="black" points="395.04,-98.51 395.04,-140.51 "/>
|
||||
<text text-anchor="middle" x="444.54" y="-122.91" font-family="DejaVu Sans Mono, Book" font-size="12.00">gm</text>
|
||||
<text text-anchor="middle" x="444.54" y="-109.91" font-family="DejaVu Sans Mono, Book" font-size="12.00">priority1=1</text>
|
||||
</g>
|
||||
<!-- host--gm -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>host:mgmt1--gm:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M58,-125.5C58,-125.5 348.04,-130.51 348.04,-130.51"/>
|
||||
</g>
|
||||
<!-- receiver -->
|
||||
<g id="node3" class="node">
|
||||
<title>receiver</title>
|
||||
<polygon fill="none" stroke="black" points="340.54,-0.5 340.54,-42.5 501.54,-42.5 501.54,-0.5 340.54,-0.5"/>
|
||||
<text text-anchor="middle" x="364.04" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">data</text>
|
||||
<polyline fill="none" stroke="black" points="340.54,-21.5 387.54,-21.5 "/>
|
||||
<text text-anchor="middle" x="364.04" y="-7.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">mgmt</text>
|
||||
<polyline fill="none" stroke="black" points="387.54,-0.5 387.54,-42.5 "/>
|
||||
<text text-anchor="middle" x="444.54" y="-24.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">receiver</text>
|
||||
<text text-anchor="middle" x="444.54" y="-11.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">priority1=128</text>
|
||||
</g>
|
||||
<!-- host--receiver -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>host:mgmt2--receiver:mgmt</title>
|
||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M58,-15.5C58,-15.5 340.04,-10.5 340.04,-10.5"/>
|
||||
</g>
|
||||
<!-- gm--receiver -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>gm:data--receiver:data</title>
|
||||
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M369.79,-88.5C368.51,-78.3 366.55,-62.59 365.28,-52.43"/>
|
||||
<polygon fill="cornflowerblue" stroke="cornflowerblue" stroke-width="2" points="366.33,-89.02 371.04,-98.51 373.27,-88.15 366.33,-89.02"/>
|
||||
<polygon fill="cornflowerblue" stroke="cornflowerblue" stroke-width="2" points="368.75,-51.99 364.04,-42.5 361.81,-52.86 368.75,-51.99"/>
|
||||
<text text-anchor="middle" x="299.53" y="-74.26" font-family="DejaVu Serif, Book" font-size="14.00">192.168.100.0/30  </text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
Reference in New Issue
Block a user