blob: a680ded4d59b42fcc0dd4a94d9e29a74eb74d79f [file] [log] [blame]
*** Settings ***
Test Setup GPTP Test Setup
*** Variables ***
# The parameters are actually configurable, if the tests that
# use them fail, make sure the test is built with the default
# parameters or set the variables to the updated values
#
# NOTE: Maybe this should be somehow parametrized to take these
# settings from the actual .config file?
${EXPECTED_PTP_PRIORITY1} \xf8
${EXPECTED_PTP_GM_CLOCK_CLASS} \xf8
${EXPECTED_PTP_GM_CLOCK_ACCURACY} \xfe
${EXPECTED_PTP_GM_CLOCK_VARIANCE} \x6a\x43
${EXPECTED_PTP_PRIORITY2} \xf8
${EXPECTED_PTP_TIME_SOURCE} \xa0
${SAM_GMAC_PTP_TIMER_SECONDS_REG} 0x1D0
${ZEPHYR_MASTER_ELF} https://dl.antmicro.com/projects/renode/sam-e70_xplained--gptp-zephyr-gm.elf-s_2087900-49bb30b12c6ca60206c923771cd9cb04c09d5f35
${ZEPHYR_SLAVE_ELF} https://dl.antmicro.com/projects/renode/sam-e70_xplained--gptp-zephyr-nogm.elf-s_2085692-204437fef2ce19260e916a358b657d2691c9df28
*** Keywords ***
GPTP Test Setup
Reset Emulation
Execute Command emulation CreateSwitch "switch"
########################
### PACKET RECEIVERS ###
########################
Wait For Outgoing PTPv2 Packet
# EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTP packets
# The next byte is the type of packet, and the next version (should be 0x02)
${pkt} = Wait For Outgoing Packet With Bytes At Index 88f7__02 12 20 60
${bytes} = Convert To Bytes ${pkt.bytes}
[return] ${bytes} ${pkt.timestamp}
Wait For Outgoing PTPv2 Announce Packet
# EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTPv2 packets
# Announce packet should have 0x1b at the next byte
${pkt} = Wait For Outgoing Packet With Bytes At Index 88f71b 12 20 60
${bytes} = Convert To Bytes ${pkt.bytes}
[return] ${bytes} ${pkt.timestamp}
Wait For Outgoing PTPv2 Sync Packet
# EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTPv2 packets
# Sync packet should have 0x10 at the next byte
${pkt} = Wait For Outgoing Packet With Bytes At Index 88f710 12 20 60
${bytes} = Convert To Bytes ${pkt.bytes}
[return] ${bytes} ${pkt.timestamp}
Wait For Outgoing PTPv2 Sync Follow Up Packet
# EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTPv2 packets
# Sync FUP packet should have 0x18 at the next byte
${pkt} = Wait For Outgoing Packet With Bytes At Index 88f718 12 20 60
${bytes} = Convert To Bytes ${pkt.bytes}
[return] ${bytes} ${pkt.timestamp}
#######################
### GENERIC GETTERS ###
#######################
Get Timestamp From The PTP Packet
[Arguments] ${pktBytes}
${timestamp} = Get Substring ${pktBytes} 48 58
[return] ${timestamp}
Get Clock ID From The PTP Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 34 42
[return] ${value}
#################################
### ANNOUNCE SPECIFIC GETTERS ###
#################################
Get Priority1 From The Announce Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 61 61
[return] ${value}
Get Grand Master Clock Class From The Announce Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 62 62
[return] ${value}
Get Grand Master Clock Accuracy From The Announce Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 63 63
[return] ${value}
Get Grand Master Clock Variance From The Announce Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 64 66
[return] ${value}
Get Priority2 From The Announce Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 66 66
[return] ${value}
Get Grand Master Clock ID From The Announce Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 67 75
[return] ${value}
Get Time Source From The Announce Packet
[Arguments] ${pktBytes}
${value} = Get Substring ${pktBytes} 77 77
[return] ${value}
#############################
### SYNC SPECIFIC GETTERS ###
#############################
Get Sync Messages Reported Period
[Arguments] ${pktBytes}
${b} = Get Substring ${pktBytes} 47 48
${logInterval} = Evaluate ord('${b}')
# This is a Log2 of the interval, so calculate it in milliseconds
# (Renode uses milliseconds for timestamps)
${interval} = Evaluate 2**(${logInterval}) * (10**3)
[return] ${interval}
############################
### ACTUAL TEST KEYWORDS ###
############################
Should Be A PTP Packet
[Arguments] ${pktBytes}
# Verify if EtherType is 0x88f7 (Bytes 12-13)
${etherTypePtp} = Convert To Bytes \x88\xf7
${etherTypePkt} = Get Substring ${pktBytes} 12 14
Should Be Equal As Strings ${etherTypePtp} ${etherTypePkt}
Should Be A PDelay Request Packet
[Arguments] ${pktBytes}
# The byte at ofsset 14 indicates "Transport specific" and "PDelayReq" (value: 0x12)
Should Be A PTP Packet ${pktBytes}
${ptpTypePkt} = Get Substring ${pktBytes} 14 14
${ptpTypePDelayReqList} = Convert To Bytes \x12
${ptpTypePDelayReq} = Get Substring ${ptpTypePDelayReqList} 0 0
Should Be Equal ${ptpTypePDelayReq} ${ptpTypePkt}
PTP Clock ID Should Be Correct
[Arguments] ${pktBytes}
# Correct means generated from the MAC address with 0xfffe in the middle
# Get the Reported MAC first
${reportedMac} = Get Substring ${pktBytes} 6 12
# And then get the reported Clock ID and try to reconstruct the MAC
${reconstructedMacH0} = Get Substring ${pktBytes} 34 37
${middleClockBytes} = Get Substring ${pktBytes} 37 39
${reconstructedMacH1} = Get Substring ${pktBytes} 39 42
${reconstructedMac} = Set Variable ${reconstructedMacH0}${reconstructedMacH1}
Should Be Equal As Strings ${reportedMac} ${reconstructedMac}
${expectedMiddleClockBytes} = Convert To Bytes \xff\xfe
Should Be Equal As Strings ${middleClockBytes} ${expectedMiddleClockBytes}
######################
### ANNOUNCE TESTS ###
######################
Announce Sender Should Be The Grand Master
[Arguments] ${pktBytes}
# in a two-node scenario, the master node should also be the grand master node
# verify that the node clock id and grand master id match
${clockId} = Get Clock ID From The PTP Packet ${pktBytes}
${grandMasterClockId} = Get Grand Master Clock ID From The Announce Packet ${pktBytes}
Should Be Equal As Strings ${clockId} ${grandMasterClockId}
Should Announce Priority1 Equal To
[Arguments] ${pktBytes} ${priority1}
${bytes} = Convert To Bytes ${priority1}
${byte} = Get Substring ${bytes} 0 0
${actualValue} = Get Priority1 From The Announce Packet ${pktBytes}
Should Be Equal ${actualValue} ${byte}
Should Announce GM Clock Class Equal To
[Arguments] ${pktBytes} ${gmClass}
${bytes} = Convert To Bytes ${gmClass}
${byte} = Get Substring ${bytes} 0 0
${actualValue} = Get Grand Master Clock Class From The Announce Packet ${pktBytes}
Should Be Equal ${actualValue} ${byte}
Should Announce GM Clock Accuracy Equal To
[Arguments] ${pktBytes} ${gmAccuracy}
${bytes} = Convert To Bytes ${gmAccuracy}
${byte} = Get Substring ${bytes} 0 0
${actualValue} = Get Grand Master Clock Accuracy From The Announce Packet ${pktBytes}
Should Be Equal ${actualValue} ${byte}
Should Announce GM Clock Variance Equal To
[Arguments] ${pktBytes} ${gmVariance}
${bytes} = Convert To Bytes ${gmVariance}
${actualValue} = Get Grand Master Clock Variance From The Announce Packet ${pktBytes}
Should Be Equal As Strings ${actualValue} ${bytes}
Should Announce Priority2 Equal To
[Arguments] ${pktBytes} ${priority2}
${bytes} = Convert To Bytes ${priority2}
${byte} = Get Substring ${bytes} 0 0
${actualValue} = Get Priority2 From The Announce Packet ${pktBytes}
Should Be Equal ${actualValue} ${byte}
Should Announce Time Source Equal To
[Arguments] ${pktBytes} ${timeSource}
${bytes} = Convert To Bytes ${timeSource}
${byte} = Get Substring ${bytes} 0 0
${actualValue} = Get Time Source From The Announce Packet ${pktBytes}
Should Be Equal ${actualValue} ${byte}
Should Be Equal Within Range
[Arguments] ${value0} ${value1} ${range}
${diff} = Evaluate abs(${value0} - ${value1})
Should Be True ${diff} <= ${range}
Register Values Should Be Equal Within Range
[Arguments] ${regValue0} ${regValue1} ${range}
# Renode returns it as "0xXXXX\n\n" - get the first line to trim the string
${regValue0} = Get Line ${regValue0} 0
${regValue0} = Convert To Integer ${regValue0}
${regValue1} = Get Line ${regValue1} 0
${regValue1} = Convert To Integer ${regValue1}
Should Be Equal Within Range ${regValue0} ${regValue1} ${range}
##################
### SYNC TESTS ###
##################
Sync Packet Timestamp Should Be Empty
[Arguments] ${pktBytes}
${emptyTimestamp} = Convert To Bytes \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
${actualTimestamp} = Get Timestamp From The PTP Packet ${pktBytes}
Should Be Equal As Strings ${emptyTimestamp} ${actualTimestamp}
Sync Packet Timestamp Should Not Be Empty
[Arguments] ${pktBytes}
${emptyTimestamp} = Convert To Bytes \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
${actualTimestamp} = Get Timestamp From The PTP Packet ${pktBytes}
Run Keyword And Expect Error * Should Be Equal As Strings ${emptyTimestamp} ${actualTimestamp}
Should Have Synchronized Clocks
[Arguments] ${mach0} ${mach1}
Execute Command mach set "${mach0}"
${mach0Seconds} = Execute Command gem ReadDoubleWord ${SAM_GMAC_PTP_TIMER_SECONDS_REG}
Execute Command mach set "${mach1}"
${mach1Seconds} = Execute Command gem ReadDoubleWord ${SAM_GMAC_PTP_TIMER_SECONDS_REG}
# Note: this test is not really precise, because of the way we are able to send and
# and receive packets with Renode. Ideally we should also read the nanseconds
# registers, combine them with seconds to get a proper timestamp, and compare
# the values from both nodes with n-nanoseconds precision.
Register Values Should Be Equal Within Range ${mach0Seconds} ${mach1Seconds} 1
Should Have Desynchronized Clocks
[Arguments] ${mach0} ${mach1}
Run Keyword And Expect Error * Should Have Synchronized Clocks ${mach0} ${mach1}
#####################
### SETUP HELPERS ###
#####################
Setup Slave Node
[Arguments] ${name}
Execute Command set bin @${ZEPHYR_SLAVE_ELF}
Execute Command set name "${name}"
Execute Command i @scripts/single-node/sam_e70.resc
Execute Command connector Connect gem switch
Execute Command mach clear
Setup Master Node
[Arguments] ${name}
Execute Command set bin @${ZEPHYR_MASTER_ELF}
Execute Command set name "${name}"
Execute Command i @scripts/single-node/sam_e70.resc
Execute Command connector Connect gem switch
Execute Command mach clear
Setup Single Node Scenario
Setup Master Node master
Setup Multi Node Scenario
Setup Master Node master
Setup Slave Node slave
Execute Command emulation SetGlobalSerialExecution True
*** Test Cases ***
Single Node Should Send A PDelay Request Packet
Setup Single Node Scenario
Create Network Interface Tester sysbus.gem
Start Emulation
${pkt} ${ts} = Wait For Outgoing PTPv2 Packet
Should Be A PDelay Request Packet ${pkt}
Slave Should Call The Phase Dis Callback
Setup Multi Node Scenario
Create Terminal Tester sysbus.usart1 machine=slave
Start Emulation
Wait For Line On Uart net_gptp_sample.gptp_phase_dis_cb
Master Should Send Announce Packets With The Expected Parameters
Setup Multi Node Scenario
Create Network Interface Tester sysbus.gem master
Start Emulation
${pkt} ${ts} = Wait For Outgoing PTPv2 Announce Packet
PTP Clock ID Should Be Correct ${pkt}
Announce Sender Should Be The Grand Master ${pkt}
Should Announce Priority1 Equal To ${pkt} ${EXPECTED_PTP_PRIORITY1}
Should Announce GM Clock Class Equal To ${pkt} ${EXPECTED_PTP_GM_CLOCK_CLASS}
Should Announce GM Clock Accuracy Equal To ${pkt} ${EXPECTED_PTP_GM_CLOCK_ACCURACY}
Should Announce GM Clock Variance Equal To ${pkt} ${EXPECTED_PTP_GM_CLOCK_VARIANCE}
Should Announce Priority2 Equal To ${pkt} ${EXPECTED_PTP_PRIORITY2}
Should Announce Time Source Equal To ${pkt} ${EXPECTED_PTP_TIME_SOURCE}
Master Should Send Sync And Fup Packets With The Expected Parameters
Setup Multi Node Scenario
Create Network Interface Tester sysbus.gem master
Start Emulation
${pkt} ${ts} = Wait For Outgoing PTPv2 Sync Packet
Sync Packet Timestamp Should Be Empty ${pkt}
${pkt} ${ts} = Wait For Outgoing PTPv2 Sync Follow Up Packet
Sync Packet Timestamp Should Not Be Empty ${pkt}
Master Should Send Syncs In Valid Intervals
Setup Multi Node Scenario
Create Network Interface Tester sysbus.gem master
Start Emulation
${pkt} ${ts} = Wait For Outgoing PTPv2 Sync Packet
${range} = Get Sync Messages Reported Period ${pkt}
${pkt} ${ts0} = Wait For Outgoing PTPv2 Sync Packet
${pkt} ${ts1} = Wait For Outgoing PTPv2 Sync Packet
# Assume 100% interval error is alright for renode ;)
${rangeErr} = Evaluate ${range}*1.0
Should Be Equal Within Range ${ts1} - ${ts0} - ${range} 0 ${rangeErr}
Slave Should Sync Its Clock To Master
Setup Multi Node Scenario
Execute Command mach set "slave"
Execute Command cpu IsHalted true
Execute Command emulation RunFor "5"
Execute Command gem Reset
Should Have Desynchronized Clocks slave master
Execute Command mach set "slave"
Execute Command cpu IsHalted false
Execute Command emulation RunFor "5"
Should Have Synchronized Clocks slave master