diff --git a/providers/base/bin/get_virtual_ptp_path.sh b/providers/base/bin/get_virtual_ptp_path.sh new file mode 100755 index 0000000000..63b0f57ad1 --- /dev/null +++ b/providers/base/bin/get_virtual_ptp_path.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Check if udevadm is available +if ! command -v udevadm &> /dev/null; then + echo "udevadm command not found. Please ensure it is installed." + exit 1 +fi + +# Run udevadm info to get information about /dev/ptp* devices +udevadm_output=$(udevadm info /dev/ptp*) + +# Use awk to extract sections that contain the desired pattern +awk_output=$(echo "$udevadm_output" | awk '/P: \/devices\/virtual\/ptp\/ptp[0-9]+/' RS="\n\n" ORS="\n\n") + +# Use grep to extract the device names +device_names=$(echo "$awk_output" | grep -Po 'DEVNAME=\K[^[:space:]]+') + +# Print the device names +if [ -n "$device_names" ]; then + echo "$device_names" +fi diff --git a/providers/base/bin/tgpio.py b/providers/base/bin/tgpio.py new file mode 100755 index 0000000000..a61b370268 --- /dev/null +++ b/providers/base/bin/tgpio.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +import argparse +import subprocess +import shlex + + +def parse_args(): + parser = argparse.ArgumentParser( + prog="TGPIO Testing Tool", + description="This is a tool to help you perform the TGPIO testing", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "-r", + "--run", + type=str, + choices=["server", "receive"], + help="The ptp device node to test", + required=True, + ) + parser.add_argument( + "-d", + "--device", + type=str, + help="The ptp device node to test", + required=True, + ) + parser.add_argument( + "-p", + "--pin", + type=str, + help="The pin number to test", + required=True, + ) + parser.add_argument( + "-t", + "--timeout", + type=int, + help="The timeout in seconds", + default=10, + ) + return parser.parse_args() + + +def server_mode(device: str, pin: str): + cmd = "testptp -d {} -i {} -L {},2 -p 1000000000".format(device, pin, pin) + subprocess.check_call(shlex.split(cmd)) + + +def receive_timestamp(device: str, pin: str, timeout: int = 10): + cmd = "testptp -d {} -i {} -L {},1 -e 100 -o {} -E".format( + device, pin, pin, timeout + ) + try: + output = subprocess.check_output(shlex.split(cmd)) + except subprocess.CalledProcessError as e: + raise SystemExit( + "[ERROR] Failed to receive timestamps: {}".format(str(e)) + ) + + event_times = [ + int(line.split(":")[-1].split(",")[0].strip()) + for line in output.splitlines() + if "Event time time" in line + ] + cnt = len(event_times) + deltas = [ + y - x for (x, y) in zip(iter(event_times), iter(event_times[1:])) + ] + if any(delta != 1 for delta in deltas): + raise SystemExit( + "[ERROR] Some events didn't take exactly 1 second\n" + "Timestamps: {}\n" + "Deltas:{}".format(str(event_times), str(deltas)) + ) + if cnt < timeout - 1 or timeout + 1 < cnt: + raise SystemExit("[ERROR] The number for Event time time is incorrect") + print("[PASS] Time Delta is 1") + + +def main(): + args = parse_args() + if args.run == "server": + server_mode(args.device, args.pin) + elif args.run == "receive": + receive_timestamp(args.device, args.pin, args.timeout) + else: + raise SystemExit("[ERROR] Invalid run type") + + +if __name__ == "__main__": + main() diff --git a/providers/base/units/tgpio/README.md b/providers/base/units/tgpio/README.md new file mode 100644 index 0000000000..4cdace3c04 --- /dev/null +++ b/providers/base/units/tgpio/README.md @@ -0,0 +1,44 @@ +# TGPIO Testing Guide + +## Introduction + +TGPIO stands for Time-aware General-Purpose Input/Output. It is like GPIO but is used to transmit timestamps for synchronizing time. + +## Prerequisites + +### Hardware + +To perform the TGPIO test, we need two machines. We recommend testing with two identical machines to ensure consistent results. +One machine will act as the server to send timestamps, and the other as the DUT (Device Under Test) to receive timestamps. +Alternatively, you can test both send and receive on one machine. + +**Connect the corresponding TGPIO pins on these two machines.** + +### Software + +#### On the Server + +To start sending timestamps, we need to run the server script. + +1. Check your PTP device node by referring the job `ptp-device-node-info`. +2. Determine the PTP device pin number. The number of TGPIO pins on the machine will affect this. +3. Run the server script in server mode: + + 1. Enter the checkbox environment: `sudo checkbox.shell` + 2. Run the script: `python3 /snap/checkbox22/current/providers/checkbox-provider-base/bin/tgpio.py -r server -d {PTP_DEVICE_NODE} -p {PTP_DEVICE_PIN}` + +#### On the DUT + +Set up how many TGPIO pins you have. + +1. `sudo checkbox.configure TGPIO_PIN_COUNT={NUMBER}` + +For example, if you have 2 TGPIO pins, you should run + +```terminal +sudo checkbox.configure TGPIO_PIN_COUNT=2 +``` + +## Start the test + +Until now, we are ready to perform the TGPIO tests. diff --git a/providers/base/units/tgpio/category.pxu b/providers/base/units/tgpio/category.pxu new file mode 100644 index 0000000000..8bb63eb0e3 --- /dev/null +++ b/providers/base/units/tgpio/category.pxu @@ -0,0 +1,3 @@ +unit: category +id: tgpio +_name: TGPIO (Timed-Aware GPIO) Tests diff --git a/providers/base/units/tgpio/jobs.pxu b/providers/base/units/tgpio/jobs.pxu new file mode 100644 index 0000000000..f0e138d91e --- /dev/null +++ b/providers/base/units/tgpio/jobs.pxu @@ -0,0 +1,63 @@ +unit: job +category_id: tgpio +id: tgpio/ptp-virtual-device-node-detect +plugin: shell +imports: from com.canonical.plainbox import manifest +requires: + manifest.has_tgpio == 'True' +_summary: Check if there's at least one virtual ptp device node +_description: + This test is to check if there's at least one virtual ptp device node +user: root +command: + get_virtual_ptp_path.sh + +unit: job +category_id: tgpio +id: tgpio/intc-driver-loaded +plugin: shell +_summary: Verify if all the Intel Controller(INTC) for TGPIO is loaded +_description: + This test is to enumerate the loaded TGPIO driver. It's hardcoded, so it should + always be INTC1021, INTC1022, INTC1023, INTC1024. +imports: from com.canonical.plainbox import manifest +requires: + manifest.has_tgpio == 'True' +user: root +depends: tgpio/ptp-virtual-device-node-detect +command: + expected_modules='INTC1021 INTC1022 INTC1023 INTC1024' + EXIT=0 + output=$(modinfo ptp-intel-pmc-tgpio | grep alias) + for m in ${expected_modules} + do + echo "Checking module: ${m}" + if echo "${output}" | grep -q "${m}"; then + echo "PASS: ${m} is loaded." + else + echo "FAIL: ${m} is not loaded." + EXIT=1 + fi + done + exit $EXIT + +unit: template +template-resource: ptp-device-node-info +template-unit: job +template-id: tgpio/ptp-time-check-tests +category_id: tgpio +id: tgpio/ptp-time-check-{ptp_device_node}-{ptp_device_pin} +plugin: shell +_summary: Check PTP device node function on {ptp_device_node} pin {ptp_device_pin} +_description: + This test is to check if the ptp device can receive time stamp on {ptp_device_node} pin {ptp_device_pin}. +imports: from com.canonical.plainbox import manifest +requires: + manifest.has_tgpio == 'True' + manifest.has_tgpio_server == 'True' +user: root +depends: tgpio/ptp-virtual-device-node-detect +environ: + TGPIO_RECEIVE_TESTING_TIME +command: + tgpio.py --run receive --device {ptp_device_node} --pin {ptp_device_pin} --timeout ${{TGPIO_RECEIVE_TESTING_TIME:-10}} diff --git a/providers/base/units/tgpio/manifest.pxu b/providers/base/units/tgpio/manifest.pxu new file mode 100644 index 0000000000..b7a36e827b --- /dev/null +++ b/providers/base/units/tgpio/manifest.pxu @@ -0,0 +1,9 @@ +unit: manifest entry +id: has_tgpio_server +_name: Device connected to a TGPIO server which sends timestamps +value-type: bool + +unit: manifest entry +id: has_tgpio +_name: TGPIO support (at least 1 pin) +value-type: bool diff --git a/providers/base/units/tgpio/resource.pxu b/providers/base/units/tgpio/resource.pxu new file mode 100644 index 0000000000..5e64c4299c --- /dev/null +++ b/providers/base/units/tgpio/resource.pxu @@ -0,0 +1,20 @@ +unit: job +id: ptp-device-node-info +plugin: resource +_summary: Get the PTP device node +_description: Get the PTP device node, TGPIO will be used such as /devices/virtual/ptp/ptp*. +user: root +environ: + TGPIO_PIN_COUNT +command: + nodes=$(get_virtual_ptp_path.sh) + for node in ${nodes} + do + for ((i = 0; i < TGPIO_PIN_COUNT; i++)); do + echo "ptp_device_node: ${node}" + echo "ptp_device_pin: ${i}" + echo "" + done + done +estimated_duration: 1s +flags: preserve-locale diff --git a/providers/base/units/tgpio/test-plan.pxu b/providers/base/units/tgpio/test-plan.pxu new file mode 100644 index 0000000000..3e1bfd3999 --- /dev/null +++ b/providers/base/units/tgpio/test-plan.pxu @@ -0,0 +1,23 @@ +id: tgpio-full +_name: TGPIO Tests (Full) +unit: test plan +include: +nested_part: + tgpio-manual + tgpio-automated + +id: tgpio-manual +_name: TGPIO Tests (Manual) +unit: test plan +include: +bootstrap_include: + +id: tgpio-automated +_name: TGPIO Tests (Automated) +unit: test plan +include: + tgpio/ptp-virtual-device-node-detect + tgpio/intc-driver-loaded + tgpio/ptp-time-check-tests +bootstrap_include: + ptp-device-node-info