1*** Settings ***
2Test Setup                                         GPTP Test Setup
3
4*** Variables ***
5
6# The parameters are actually configurable, if the tests that
7# use them fail, make sure the test is built with the default
8# parameters or set the variables to the updated values
9#
10# NOTE: Maybe this should be somehow parametrized to take these
11#       settings from the actual .config file?
12
13${EXPECTED_PTP_PRIORITY1}                          \xf8
14${EXPECTED_PTP_GM_CLOCK_CLASS}                     \xf8
15${EXPECTED_PTP_GM_CLOCK_ACCURACY}                  \xfe
16${EXPECTED_PTP_GM_CLOCK_VARIANCE}                  \x6a\x43
17${EXPECTED_PTP_PRIORITY2}                          \xf8
18${EXPECTED_PTP_TIME_SOURCE}                        \xa0
19
20${SAM_GMAC_PTP_TIMER_SECONDS_REG}                  0x1D0
21
22${ZEPHYR_MASTER_ELF}                               https://dl.antmicro.com/projects/renode/sam-e70_xplained--gptp-zephyr-gm.elf-s_2087900-49bb30b12c6ca60206c923771cd9cb04c09d5f35
23${ZEPHYR_SLAVE_ELF}                                https://dl.antmicro.com/projects/renode/sam-e70_xplained--gptp-zephyr-nogm.elf-s_2085692-204437fef2ce19260e916a358b657d2691c9df28
24
25*** Keywords ***
26
27GPTP Test Setup
28    Reset Emulation
29    Execute Command                                emulation CreateSwitch "switch"
30
31########################
32### PACKET RECEIVERS ###
33########################
34
35Wait For Outgoing PTPv2 Packet
36    # EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTP packets
37    # The next byte is the type of packet, and the next version (should be 0x02)
38
39    ${pkt} =                                       Wait For Outgoing Packet With Bytes At Index  88f7__02  12  20  60
40    ${bytes} =                                     Convert To Bytes  ${pkt.bytes}
41
42    RETURN                                         ${bytes}  ${pkt.timestamp}
43
44Wait For Outgoing PTPv2 Announce Packet
45    # EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTPv2 packets
46    # Announce packet should have 0x1b at the next byte
47
48    ${pkt} =                                       Wait For Outgoing Packet With Bytes At Index  88f71b  12  20  60
49    ${bytes} =                                     Convert To Bytes  ${pkt.bytes}
50
51    RETURN                                         ${bytes}  ${pkt.timestamp}
52
53Wait For Outgoing PTPv2 Sync Packet
54    # EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTPv2 packets
55    # Sync packet should have 0x10 at the next byte
56
57    ${pkt} =                                       Wait For Outgoing Packet With Bytes At Index  88f710  12  20  60
58    ${bytes} =                                     Convert To Bytes  ${pkt.bytes}
59
60    RETURN                                         ${bytes}  ${pkt.timestamp}
61
62Wait For Outgoing PTPv2 Sync Follow Up Packet
63    # EtherType are Bytes 13-14 and should be equal to 0x88f7 for PTPv2 packets
64    # Sync FUP packet should have 0x18 at the next byte
65
66    ${pkt} =                                       Wait For Outgoing Packet With Bytes At Index  88f718  12  20  60
67    ${bytes} =                                     Convert To Bytes  ${pkt.bytes}
68
69    RETURN                                         ${bytes}  ${pkt.timestamp}
70
71#######################
72### GENERIC GETTERS ###
73#######################
74
75Get Timestamp From The PTP Packet
76    [Arguments]   ${pktBytes}
77
78    ${timestamp} =                                 Get Substring  ${pktBytes}  48  58
79
80    RETURN                                         ${timestamp}
81
82Get Clock ID From The PTP Packet
83    [Arguments]   ${pktBytes}
84
85    ${value} =                                     Get Substring  ${pktBytes}  34  42
86
87    RETURN                                         ${value}
88
89#################################
90### ANNOUNCE SPECIFIC GETTERS ###
91#################################
92
93Get Priority1 From The Announce Packet
94    [Arguments]   ${pktBytes}
95
96    ${value} =                                     Get Substring  ${pktBytes}  61  61
97
98    RETURN                                         ${value}
99
100Get Grand Master Clock Class From The Announce Packet
101    [Arguments]   ${pktBytes}
102
103    ${value} =                                     Get Substring  ${pktBytes}  62  62
104
105    RETURN                                         ${value}
106
107Get Grand Master Clock Accuracy From The Announce Packet
108    [Arguments]   ${pktBytes}
109
110    ${value} =                                     Get Substring  ${pktBytes}  63  63
111
112    RETURN                                         ${value}
113
114Get Grand Master Clock Variance From The Announce Packet
115    [Arguments]   ${pktBytes}
116
117    ${value} =                                     Get Substring  ${pktBytes}  64  66
118
119    RETURN                                         ${value}
120
121Get Priority2 From The Announce Packet
122    [Arguments]   ${pktBytes}
123
124    ${value} =                                     Get Substring  ${pktBytes}  66  66
125
126    RETURN                                         ${value}
127
128Get Grand Master Clock ID From The Announce Packet
129    [Arguments]   ${pktBytes}
130
131    ${value} =                                     Get Substring  ${pktBytes}  67  75
132
133    RETURN                                         ${value}
134
135Get Time Source From The Announce Packet
136    [Arguments]   ${pktBytes}
137
138    ${value} =                                     Get Substring  ${pktBytes}  77  77
139
140    RETURN                                         ${value}
141
142#############################
143### SYNC SPECIFIC GETTERS ###
144#############################
145
146Get Sync Messages Reported Period
147    [Arguments]   ${pktBytes}
148
149    ${b} =                                         Get Substring  ${pktBytes}  47  48
150    ${logInterval} =                               Evaluate  ord('${b}')
151
152    # This is a Log2 of the interval, so calculate it in milliseconds
153    # (Renode uses milliseconds for timestamps)
154    ${interval} =                                  Evaluate  2**(${logInterval}) * (10**3)
155
156    RETURN                                         ${interval}
157
158############################
159### ACTUAL TEST KEYWORDS ###
160############################
161
162Should Be A PTP Packet
163    [Arguments]    ${pktBytes}
164
165    # Verify if EtherType is 0x88f7 (Bytes 12-13)
166
167    ${etherTypePtp} =                              Convert To Bytes  \x88\xf7
168    ${etherTypePkt} =                              Get Substring  ${pktBytes}  12   14
169
170    Should Be Equal As Strings                     ${etherTypePtp}  ${etherTypePkt}
171
172Should Be A PDelay Request Packet
173    [Arguments]    ${pktBytes}
174
175    # The byte at ofsset 14 indicates "Transport specific" and "PDelayReq" (value: 0x12)
176
177    Should Be A PTP Packet                         ${pktBytes}
178
179    ${ptpTypePkt} =                                Get Substring  ${pktBytes}  14   14
180    ${ptpTypePDelayReqList} =                      Convert To Bytes  \x12
181    ${ptpTypePDelayReq} =                          Get Substring  ${ptpTypePDelayReqList}  0    0
182    Should Be Equal                                ${ptpTypePDelayReq}  ${ptpTypePkt}
183
184PTP Clock ID Should Be Correct
185    [Arguments]   ${pktBytes}
186
187    # Correct means generated from the MAC address with 0xfffe in the middle
188
189    # Get the Reported MAC first
190    ${reportedMac} =                               Get Substring  ${pktBytes}  6    12
191
192    # And then get the reported Clock ID and try to reconstruct the MAC
193    ${reconstructedMacH0} =                        Get Substring  ${pktBytes}  34   37
194    ${middleClockBytes} =                          Get Substring  ${pktBytes}  37   39
195    ${reconstructedMacH1} =                        Get Substring  ${pktBytes}  39   42
196
197    ${reconstructedMac} =                          Set Variable  ${reconstructedMacH0}${reconstructedMacH1}
198    Should Be Equal As Strings                     ${reportedMac}  ${reconstructedMac}
199
200    ${expectedMiddleClockBytes} =                  Convert To Bytes  \xff\xfe
201    Should Be Equal As Strings                     ${middleClockBytes}  ${expectedMiddleClockBytes}
202
203######################
204### ANNOUNCE TESTS ###
205######################
206
207Announce Sender Should Be The Grand Master
208    [Arguments]   ${pktBytes}
209
210    # in a two-node scenario, the master node should also be the grand master node
211    # verify that the node clock id and grand master id match
212
213    ${clockId} =                                   Get Clock ID From The PTP Packet  ${pktBytes}
214    ${grandMasterClockId} =                        Get Grand Master Clock ID From The Announce Packet  ${pktBytes}
215
216    Should Be Equal As Strings                     ${clockId}  ${grandMasterClockId}
217
218Should Announce Priority1 Equal To
219    [Arguments]   ${pktBytes}  ${priority1}
220
221    ${bytes} =                                     Convert To Bytes  ${priority1}
222    ${byte} =                                      Get Substring  ${bytes}  0  0
223
224    ${actualValue} =                               Get Priority1 From The Announce Packet  ${pktBytes}
225
226    Should Be Equal                                ${actualValue}  ${byte}
227
228Should Announce GM Clock Class Equal To
229    [Arguments]   ${pktBytes}  ${gmClass}
230
231    ${bytes} =                                     Convert To Bytes  ${gmClass}
232    ${byte} =                                      Get Substring  ${bytes}  0  0
233
234    ${actualValue} =                               Get Grand Master Clock Class From The Announce Packet  ${pktBytes}
235    Should Be Equal                                ${actualValue}  ${byte}
236
237Should Announce GM Clock Accuracy Equal To
238    [Arguments]   ${pktBytes}  ${gmAccuracy}
239
240    ${bytes} =                                     Convert To Bytes  ${gmAccuracy}
241    ${byte} =                                      Get Substring  ${bytes}  0  0
242
243    ${actualValue} =                               Get Grand Master Clock Accuracy From The Announce Packet  ${pktBytes}
244    Should Be Equal                                ${actualValue}  ${byte}
245
246Should Announce GM Clock Variance Equal To
247    [Arguments]   ${pktBytes}  ${gmVariance}
248
249    ${bytes} =                                     Convert To Bytes  ${gmVariance}
250
251    ${actualValue} =                               Get Grand Master Clock Variance From The Announce Packet  ${pktBytes}
252    Should Be Equal As Strings                     ${actualValue}  ${bytes}
253
254Should Announce Priority2 Equal To
255    [Arguments]   ${pktBytes}  ${priority2}
256
257    ${bytes} =                                     Convert To Bytes  ${priority2}
258    ${byte} =                                      Get Substring  ${bytes}  0  0
259
260    ${actualValue} =                               Get Priority2 From The Announce Packet  ${pktBytes}
261    Should Be Equal                                ${actualValue}  ${byte}
262
263Should Announce Time Source Equal To
264    [Arguments]   ${pktBytes}  ${timeSource}
265
266    ${bytes} =                                     Convert To Bytes  ${timeSource}
267    ${byte} =                                      Get Substring  ${bytes}  0  0
268
269    ${actualValue} =                               Get Time Source From The Announce Packet  ${pktBytes}
270    Should Be Equal                                ${actualValue}  ${byte}
271
272Should Be Equal Within Range
273    [Arguments]   ${value0}  ${value1}  ${range}
274
275    ${diff} =                                      Evaluate  abs(${value0} - ${value1})
276
277    Should Be True                                 ${diff} <= ${range}
278
279Register Values Should Be Equal Within Range
280    [Arguments]   ${regValue0}  ${regValue1}  ${range}
281
282    # Renode returns it as "0xXXXX\n\n" - get the first line to trim the string
283    ${regValue0} =                                 Get Line  ${regValue0}  0
284    ${regValue0} =                                 Convert To Integer  ${regValue0}
285
286    ${regValue1} =                                 Get Line  ${regValue1}  0
287    ${regValue1} =                                 Convert To Integer  ${regValue1}
288
289    Should Be Equal Within Range                   ${regValue0}  ${regValue1}  ${range}
290
291##################
292### SYNC TESTS ###
293##################
294
295Sync Packet Timestamp Should Be Empty
296    [Arguments]   ${pktBytes}
297
298    ${emptyTimestamp} =                            Convert To Bytes  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
299    ${actualTimestamp} =                           Get Timestamp From The PTP Packet  ${pktBytes}
300
301    Should Be Equal As Strings                     ${emptyTimestamp}  ${actualTimestamp}
302
303Sync Packet Timestamp Should Not Be Empty
304    [Arguments]   ${pktBytes}
305
306    ${emptyTimestamp} =                            Convert To Bytes  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
307    ${actualTimestamp} =                           Get Timestamp From The PTP Packet  ${pktBytes}
308
309    Run Keyword And Expect Error                   *  Should Be Equal As Strings  ${emptyTimestamp}  ${actualTimestamp}
310
311Should Have Synchronized Clocks
312    [Arguments]   ${mach0}   ${mach1}
313
314    Execute Command                                mach set "${mach0}"
315    ${mach0Seconds} =                              Execute Command  gem ReadDoubleWord ${SAM_GMAC_PTP_TIMER_SECONDS_REG}
316
317    Execute Command                                mach set "${mach1}"
318    ${mach1Seconds} =                              Execute Command  gem ReadDoubleWord ${SAM_GMAC_PTP_TIMER_SECONDS_REG}
319
320    # Note: this test is not really precise, because of the way we are able to send and
321    #       and receive packets with Renode. Ideally we should also read the nanseconds
322    #       registers, combine them with seconds to get a proper timestamp, and compare
323    #       the values from both nodes with n-nanoseconds precision.
324
325    Register Values Should Be Equal Within Range   ${mach0Seconds}  ${mach1Seconds}  1
326
327Should Have Desynchronized Clocks
328    [Arguments]   ${mach0}   ${mach1}
329
330    Run Keyword And Expect Error                   *  Should Have Synchronized Clocks  ${mach0}  ${mach1}
331
332#####################
333### SETUP HELPERS ###
334#####################
335
336Setup Slave Node
337    [Arguments]   ${name}
338
339    Execute Command                                set bin @${ZEPHYR_SLAVE_ELF}
340    Execute Command                                set name "${name}"
341    Execute Command                                i @scripts/single-node/sam_e70.resc
342    Execute Command                                connector Connect gem switch
343    Execute Command                                mach clear
344
345Setup Master Node
346    [Arguments]   ${name}
347
348    Execute Command                                set bin @${ZEPHYR_MASTER_ELF}
349    Execute Command                                set name "${name}"
350    Execute Command                                i @scripts/single-node/sam_e70.resc
351    Execute Command                                connector Connect gem switch
352    Execute Command                                mach clear
353
354Setup Single Node Scenario
355    Setup Master Node                              master
356
357Setup Multi Node Scenario
358    Setup Master Node                              master
359    Setup Slave Node                               slave
360
361    Execute Command                                emulation SetGlobalSerialExecution True
362
363*** Test Cases ***
364
365Single Node Should Send A PDelay Request Packet
366    Setup Single Node Scenario
367    Create Network Interface Tester                sysbus.gem
368    Start Emulation
369
370    ${pkt}  ${ts} =                                Wait For Outgoing PTPv2 Packet
371
372    Should Be A PDelay Request Packet              ${pkt}
373
374Slave Should Call The Phase Dis Callback
375    Setup Multi Node Scenario
376    Create Terminal Tester                         sysbus.usart1  machine=slave
377    Start Emulation
378
379    Wait For Line On Uart                          net_gptp_sample.gptp_phase_dis_cb
380
381Master Should Send Announce Packets With The Expected Parameters
382    Setup Multi Node Scenario
383    Create Network Interface Tester                sysbus.gem  master
384    Start Emulation
385
386    ${pkt}  ${ts} =                                Wait For Outgoing PTPv2 Announce Packet
387
388    PTP Clock ID Should Be Correct                 ${pkt}
389    Announce Sender Should Be The Grand Master     ${pkt}
390
391    Should Announce Priority1 Equal To             ${pkt}  ${EXPECTED_PTP_PRIORITY1}
392    Should Announce GM Clock Class Equal To        ${pkt}  ${EXPECTED_PTP_GM_CLOCK_CLASS}
393    Should Announce GM Clock Accuracy Equal To     ${pkt}  ${EXPECTED_PTP_GM_CLOCK_ACCURACY}
394    Should Announce GM Clock Variance Equal To     ${pkt}  ${EXPECTED_PTP_GM_CLOCK_VARIANCE}
395    Should Announce Priority2 Equal To             ${pkt}  ${EXPECTED_PTP_PRIORITY2}
396    Should Announce Time Source Equal To           ${pkt}  ${EXPECTED_PTP_TIME_SOURCE}
397
398Master Should Send Sync And Fup Packets With The Expected Parameters
399    Setup Multi Node Scenario
400    Create Network Interface Tester                sysbus.gem  master
401    Start Emulation
402
403    ${pkt}  ${ts} =                                Wait For Outgoing PTPv2 Sync Packet
404    Sync Packet Timestamp Should Be Empty          ${pkt}
405
406    ${pkt}  ${ts} =                                Wait For Outgoing PTPv2 Sync Follow Up Packet
407    Sync Packet Timestamp Should Not Be Empty      ${pkt}
408
409Master Should Send Syncs In Valid Intervals
410    Setup Multi Node Scenario
411    Create Network Interface Tester                sysbus.gem  master
412
413    Start Emulation
414
415    ${pkt}  ${ts} =                                Wait For Outgoing PTPv2 Sync Packet
416
417    ${range} =                                     Get Sync Messages Reported Period  ${pkt}
418
419    ${pkt}  ${ts0} =                               Wait For Outgoing PTPv2 Sync Packet
420    ${pkt}  ${ts1} =                               Wait For Outgoing PTPv2 Sync Packet
421
422    # Assume 100% interval error is alright for renode ;)
423    ${rangeErr} =                                  Evaluate  ${range}*1.0
424
425    Should Be Equal Within Range                   ${ts1} - ${ts0} - ${range}  0  ${rangeErr}
426
427Slave Should Sync Its Clock To Master
428    Setup Multi Node Scenario
429    Execute Command                                mach set "slave"
430    Execute Command                                cpu IsHalted true
431    Execute Command                                emulation RunFor "5"
432    Execute Command                                gem Reset
433
434    Should Have Desynchronized Clocks              slave  master
435
436    Execute Command                                mach set "slave"
437    Execute Command                                cpu IsHalted false
438    Execute Command                                emulation RunFor "5"
439
440    Should Have Synchronized Clocks                slave  master
441