15630257fSFerruh Yigit.. SPDX-License-Identifier: BSD-3-Clause 25630257fSFerruh Yigit Copyright(c) 2015 Intel Corporation. 32d123257SDaniel Mrzyglod 42d123257SDaniel MrzyglodPTP Client Sample Application 52d123257SDaniel Mrzyglod============================= 62d123257SDaniel Mrzyglod 72d123257SDaniel MrzyglodThe PTP (Precision Time Protocol) client sample application is a simple 8b8d1d60fSStephen Hemmingerexample of using the DPDK IEEE1588 API to communicate with a PTP time transmitter 92d123257SDaniel Mrzyglodto synchronize the time on the NIC and, optionally, on the Linux system. 102d123257SDaniel Mrzyglod 112d123257SDaniel MrzyglodNote, PTP is a time syncing protocol and cannot be used within DPDK as a 122d123257SDaniel Mrzyglodtime-stamping mechanism. See the following for an explanation of the protocol: 132d123257SDaniel Mrzyglod`Precision Time Protocol 142d123257SDaniel Mrzyglod<https://en.wikipedia.org/wiki/Precision_Time_Protocol>`_. 152d123257SDaniel Mrzyglod 162d123257SDaniel Mrzyglod 172d123257SDaniel MrzyglodLimitations 182d123257SDaniel Mrzyglod----------- 192d123257SDaniel Mrzyglod 202d123257SDaniel MrzyglodThe PTP sample application is intended as a simple reference implementation of 212d123257SDaniel Mrzygloda PTP client using the DPDK IEEE1588 API. 222d123257SDaniel MrzyglodIn order to keep the application simple the following assumptions are made: 232d123257SDaniel Mrzyglod 24b8d1d60fSStephen Hemminger* The first discovered time transmitter is the main for the session. 252d123257SDaniel Mrzyglod* Only L2 PTP packets are supported. 262d123257SDaniel Mrzyglod* Only the PTP v2 protocol is supported. 27b8d1d60fSStephen Hemminger* Only the time receiver clock is implemented. 282d123257SDaniel Mrzyglod 292d123257SDaniel Mrzyglod 302d123257SDaniel MrzyglodHow the Application Works 312d123257SDaniel Mrzyglod------------------------- 322d123257SDaniel Mrzyglod 332d123257SDaniel Mrzyglod.. _figure_ptpclient_highlevel: 342d123257SDaniel Mrzyglod 352d123257SDaniel Mrzyglod.. figure:: img/ptpclient.* 362d123257SDaniel Mrzyglod 372d123257SDaniel Mrzyglod PTP Synchronization Protocol 382d123257SDaniel Mrzyglod 392d123257SDaniel MrzyglodThe PTP synchronization in the sample application works as follows: 402d123257SDaniel Mrzyglod 41b8d1d60fSStephen Hemminger* Time transmitter sends *Sync* message - the time receiver saves it as T2. 42b8d1d60fSStephen Hemminger* Time transmitter sends *Follow Up* message and sends time of T1. 43b8d1d60fSStephen Hemminger* Time receiver sends *Delay Request* frame to PTP time transmitter and stores T3. 44b8d1d60fSStephen Hemminger* Time transmitter sends *Delay Response* T4 time which is time of received T3. 452d123257SDaniel Mrzyglod 46b8d1d60fSStephen HemmingerThe adjustment for time receiver can be represented as: 472d123257SDaniel Mrzyglod 482d123257SDaniel Mrzyglod adj = -[(T2-T1)-(T4 - T3)]/2 492d123257SDaniel Mrzyglod 502d123257SDaniel MrzyglodIf the command line parameter ``-T 1`` is used the application also 512d123257SDaniel Mrzyglodsynchronizes the PTP PHC clock with the Linux kernel clock. 522d123257SDaniel Mrzyglod 532d123257SDaniel MrzyglodCompiling the Application 542d123257SDaniel Mrzyglod------------------------- 552d123257SDaniel Mrzyglod 567cacb056SHerakliusz LipiecTo compile the sample application see :doc:`compiling`. 577cacb056SHerakliusz Lipiec 587cacb056SHerakliusz LipiecThe application is located in the ``ptpclient`` sub-directory. 597cacb056SHerakliusz Lipiec 602d123257SDaniel Mrzyglod 612d123257SDaniel MrzyglodRunning the Application 622d123257SDaniel Mrzyglod----------------------- 632d123257SDaniel Mrzyglod 64218c4e68SBruce RichardsonTo run the example in a ``linux`` environment: 652d123257SDaniel Mrzyglod 662d123257SDaniel Mrzyglod.. code-block:: console 672d123257SDaniel Mrzyglod 68*5357e228SMingjin Ye ./<build_dir>/examples/dpdk-ptpclient -l 1 -n 4 -- -p 0x1 -T 0 692d123257SDaniel Mrzyglod 702d123257SDaniel MrzyglodRefer to *DPDK Getting Started Guide* for general information on running 712d123257SDaniel Mrzyglodapplications and the Environment Abstraction Layer (EAL) options. 722d123257SDaniel Mrzyglod 732d123257SDaniel Mrzyglod* ``-p portmask``: Hexadecimal portmask. 74b8d1d60fSStephen Hemminger* ``-T 0``: Update only the PTP time receiver clock. 75b8d1d60fSStephen Hemminger* ``-T 1``: Update the PTP time receiver clock and synchronize the Linux Kernel to the PTP clock. 762d123257SDaniel Mrzyglod 772d123257SDaniel Mrzyglod 782d123257SDaniel MrzyglodCode Explanation 792d123257SDaniel Mrzyglod---------------- 802d123257SDaniel Mrzyglod 812d123257SDaniel MrzyglodThe following sections provide an explanation of the main components of the 822d123257SDaniel Mrzyglodcode. 832d123257SDaniel Mrzyglod 842d123257SDaniel MrzyglodAll DPDK library functions used in the sample code are prefixed with ``rte_`` 852d123257SDaniel Mrzyglodand are explained in detail in the *DPDK API Documentation*. 862d123257SDaniel Mrzyglod 872d123257SDaniel Mrzyglod 882d123257SDaniel MrzyglodThe Main Function 892d123257SDaniel Mrzyglod~~~~~~~~~~~~~~~~~ 902d123257SDaniel Mrzyglod 912d123257SDaniel MrzyglodThe ``main()`` function performs the initialization and calls the execution 922d123257SDaniel Mrzyglodthreads for each lcore. 932d123257SDaniel Mrzyglod 942d123257SDaniel MrzyglodThe first task is to initialize the Environment Abstraction Layer (EAL). The 952d123257SDaniel Mrzyglod``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()`` 962d123257SDaniel Mrzyglodfunction. The value returned is the number of parsed arguments: 972d123257SDaniel Mrzyglod 989a212dc0SConor Fogarty.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 999a212dc0SConor Fogarty :language: c 1009a212dc0SConor Fogarty :start-after: Initialize the Environment Abstraction Layer (EAL). 8< 1019a212dc0SConor Fogarty :end-before: >8 End of initialization of EAL. 1029a212dc0SConor Fogarty :dedent: 1 1032d123257SDaniel Mrzyglod 1042d123257SDaniel MrzyglodAnd than we parse application specific arguments 1052d123257SDaniel Mrzyglod 1069a212dc0SConor Fogarty.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 1079a212dc0SConor Fogarty :language: c 1089a212dc0SConor Fogarty :start-after: Parse specific arguments. 8< 1099a212dc0SConor Fogarty :end-before: >8 End of parsing specific arguments. 1109a212dc0SConor Fogarty :dedent: 1 1112d123257SDaniel Mrzyglod 1122d123257SDaniel MrzyglodThe ``main()`` also allocates a mempool to hold the mbufs (Message Buffers) 1132d123257SDaniel Mrzyglodused by the application: 1142d123257SDaniel Mrzyglod 1159a212dc0SConor Fogarty.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 1169a212dc0SConor Fogarty :language: c 1179a212dc0SConor Fogarty :start-after: Creates a new mempool in memory to hold the mbufs. 8< 1189a212dc0SConor Fogarty :end-before: >8 End of a new mempool in memory to hold the mbufs. 1199a212dc0SConor Fogarty :dedent: 1 1202d123257SDaniel Mrzyglod 1212d123257SDaniel MrzyglodMbufs are the packet buffer structure used by DPDK. They are explained in 1222d123257SDaniel Mrzygloddetail in the "Mbuf Library" section of the *DPDK Programmer's Guide*. 1232d123257SDaniel Mrzyglod 1242d123257SDaniel MrzyglodThe ``main()`` function also initializes all the ports using the user defined 1252d123257SDaniel Mrzyglod``port_init()`` function with portmask provided by user: 1262d123257SDaniel Mrzyglod 1279a212dc0SConor Fogarty.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 1289a212dc0SConor Fogarty :language: c 1299a212dc0SConor Fogarty :start-after: Initialize all ports. 8< 1309a212dc0SConor Fogarty :end-before: >8 End of initialization of all ports. 1319a212dc0SConor Fogarty :dedent: 1 1322d123257SDaniel Mrzyglod 1332d123257SDaniel Mrzyglod 1342d123257SDaniel MrzyglodOnce the initialization is complete, the application is ready to launch a 1352d123257SDaniel Mrzyglodfunction on an lcore. In this example ``lcore_main()`` is called on a single 1362d123257SDaniel Mrzyglodlcore. 1372d123257SDaniel Mrzyglod 1382d123257SDaniel Mrzyglod.. code-block:: c 1392d123257SDaniel Mrzyglod 1402d123257SDaniel Mrzyglod lcore_main(); 1412d123257SDaniel Mrzyglod 1422d123257SDaniel MrzyglodThe ``lcore_main()`` function is explained below. 1432d123257SDaniel Mrzyglod 1442d123257SDaniel Mrzyglod 1452d123257SDaniel MrzyglodThe Lcores Main 1462d123257SDaniel Mrzyglod~~~~~~~~~~~~~~~ 1472d123257SDaniel Mrzyglod 1482d123257SDaniel MrzyglodAs we saw above the ``main()`` function calls an application function on the 1492d123257SDaniel Mrzyglodavailable lcores. 1502d123257SDaniel Mrzyglod 1512d123257SDaniel MrzyglodThe main work of the application is done within the loop: 1522d123257SDaniel Mrzyglod 1539a212dc0SConor Fogarty.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 1549a212dc0SConor Fogarty :language: c 1559a212dc0SConor Fogarty :start-after: Read packet from RX queues. 8< 1569a212dc0SConor Fogarty :end-before: >8 End of read packets from RX queues. 1579a212dc0SConor Fogarty :dedent: 2 1582d123257SDaniel Mrzyglod 1592d123257SDaniel MrzyglodPackets are received one by one on the RX ports and, if required, PTP response 1602d123257SDaniel Mrzyglodpackets are transmitted on the TX ports. 1612d123257SDaniel Mrzyglod 1622d123257SDaniel MrzyglodIf the offload flags in the mbuf indicate that the packet is a PTP packet then 1632d123257SDaniel Mrzyglodthe packet is parsed to determine which type: 1642d123257SDaniel Mrzyglod 1659a212dc0SConor Fogarty.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 1669a212dc0SConor Fogarty :language: c 1679a212dc0SConor Fogarty :start-after: Packet is parsed to determine which type. 8< 1689a212dc0SConor Fogarty :end-before: >8 End of packet is parsed to determine which type. 1699a212dc0SConor Fogarty :dedent: 3 1702d123257SDaniel Mrzyglod 1712d123257SDaniel Mrzyglod 1722d123257SDaniel MrzyglodAll packets are freed explicitly using ``rte_pktmbuf_free()``. 1732d123257SDaniel Mrzyglod 1742d123257SDaniel MrzyglodThe forwarding loop can be interrupted and the application closed using 1752d123257SDaniel Mrzyglod``Ctrl-C``. 1762d123257SDaniel Mrzyglod 1772d123257SDaniel Mrzyglod 1782d123257SDaniel MrzyglodPTP parsing 1792d123257SDaniel Mrzyglod~~~~~~~~~~~ 1802d123257SDaniel Mrzyglod 181b8d1d60fSStephen HemmingerThe ``parse_ptp_frames()`` function processes PTP packets, implementing time receiver 1822d123257SDaniel MrzyglodPTP IEEE1588 L2 functionality. 1832d123257SDaniel Mrzyglod 1849a212dc0SConor Fogarty.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 1859a212dc0SConor Fogarty :language: c 1869a212dc0SConor Fogarty :start-after: Parse ptp frames. 8< 1879a212dc0SConor Fogarty :end-before: >8 End of function processes PTP packets. 1882d123257SDaniel Mrzyglod 1892d123257SDaniel MrzyglodThere are 3 types of packets on the RX path which we must parse to create a minimal 190b8d1d60fSStephen Hemmingerimplementation of the PTP time receiver client: 1912d123257SDaniel Mrzyglod 1922d123257SDaniel Mrzyglod* SYNC packet. 1932d123257SDaniel Mrzyglod* FOLLOW UP packet 1942d123257SDaniel Mrzyglod* DELAY RESPONSE packet. 1952d123257SDaniel Mrzyglod 1962d123257SDaniel MrzyglodWhen we parse the *FOLLOW UP* packet we also create and send a *DELAY_REQUEST* packet. 197b8d1d60fSStephen HemmingerAlso when we parse the *DELAY RESPONSE* packet, and all conditions are met 198b8d1d60fSStephen Hemmingerwe adjust the PTP time receiver clock. 199