1.. SPDX-License-Identifier: BSD-3-Clause 2 Copyright(c) 2015 Intel Corporation. 3 4PTP Client Sample Application 5============================= 6 7The PTP (Precision Time Protocol) client sample application is a simple 8example of using the DPDK IEEE1588 API to communicate with a PTP time transmitter 9to synchronize the time on the NIC and, optionally, on the Linux system. 10 11Note, PTP is a time syncing protocol and cannot be used within DPDK as a 12time-stamping mechanism. See the following for an explanation of the protocol: 13`Precision Time Protocol 14<https://en.wikipedia.org/wiki/Precision_Time_Protocol>`_. 15 16 17Limitations 18----------- 19 20The PTP sample application is intended as a simple reference implementation of 21a PTP client using the DPDK IEEE1588 API. 22In order to keep the application simple the following assumptions are made: 23 24* The first discovered time transmitter is the main for the session. 25* Only L2 PTP packets are supported. 26* Only the PTP v2 protocol is supported. 27* Only the time receiver clock is implemented. 28 29 30How the Application Works 31------------------------- 32 33.. _figure_ptpclient_highlevel: 34 35.. figure:: img/ptpclient.* 36 37 PTP Synchronization Protocol 38 39The PTP synchronization in the sample application works as follows: 40 41* Time transmitter sends *Sync* message - the time receiver saves it as T2. 42* Time transmitter sends *Follow Up* message and sends time of T1. 43* Time receiver sends *Delay Request* frame to PTP time transmitter and stores T3. 44* Time transmitter sends *Delay Response* T4 time which is time of received T3. 45 46The adjustment for time receiver can be represented as: 47 48 adj = -[(T2-T1)-(T4 - T3)]/2 49 50If the command line parameter ``-T 1`` is used the application also 51synchronizes the PTP PHC clock with the Linux kernel clock. 52 53If the command line parameter ``-c 1`` is used, 54the application will also use the servo of the local clock. 55Only one type of servo is currently implemented, the PI controller. 56Default 0 (not used). 57 58 59Compiling the Application 60------------------------- 61 62To compile the sample application see :doc:`compiling`. 63 64The application is located in the ``ptpclient`` sub-directory. 65 66 67Running the Application 68----------------------- 69 70To run the example in a ``linux`` environment: 71 72.. code-block:: console 73 74 ./<build_dir>/examples/dpdk-ptpclient -l 1 -n 4 -- -p 0x1 -T 0 -c 1 75 76Refer to *DPDK Getting Started Guide* for general information on running 77applications and the Environment Abstraction Layer (EAL) options. 78 79* ``-p portmask``: Hexadecimal portmask. 80* ``-T 0``: Update only the PTP time receiver clock. 81* ``-T 1``: Update the PTP time receiver clock and synchronize the Linux Kernel to the PTP clock. 82* ``-c 0``: Not used clock servo controller. 83* ``-c 1``: The clock servo PI controller is used and the log will print information 84 about time transmitter offset. 85 Note that the PMD needs to support the ``rte_eth_timesync_adjust_freq()`` API 86 to enable the servo controller. 87 88Also, by adding ``-T 1`` and ``-c 1``, the time transmitter offset value printed in the log 89will slowly converge and eventually stabilise at the nanosecond level. 90The synchronisation accuracy is much higher compared to not using a servo controller. 91 92 93Code Explanation 94---------------- 95 96The following sections provide an explanation of the main components of the 97code. 98 99All DPDK library functions used in the sample code are prefixed with ``rte_`` 100and are explained in detail in the *DPDK API Documentation*. 101 102 103The Main Function 104~~~~~~~~~~~~~~~~~ 105 106The ``main()`` function performs the initialization and calls the execution 107threads for each lcore. 108 109The first task is to initialize the Environment Abstraction Layer (EAL). The 110``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()`` 111function. The value returned is the number of parsed arguments: 112 113.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 114 :language: c 115 :start-after: Initialize the Environment Abstraction Layer (EAL). 8< 116 :end-before: >8 End of initialization of EAL. 117 :dedent: 1 118 119And than we parse application specific arguments 120 121.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 122 :language: c 123 :start-after: Parse specific arguments. 8< 124 :end-before: >8 End of parsing specific arguments. 125 :dedent: 1 126 127The ``main()`` also allocates a mempool to hold the mbufs (Message Buffers) 128used by the application: 129 130.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 131 :language: c 132 :start-after: Creates a new mempool in memory to hold the mbufs. 8< 133 :end-before: >8 End of a new mempool in memory to hold the mbufs. 134 :dedent: 1 135 136Mbufs are the packet buffer structure used by DPDK. They are explained in 137detail in the "Mbuf Library" section of the *DPDK Programmer's Guide*. 138 139The ``main()`` function also initializes all the ports using the user defined 140``port_init()`` function with portmask provided by user: 141 142.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 143 :language: c 144 :start-after: Initialize all ports. 8< 145 :end-before: >8 End of initialization of all ports. 146 :dedent: 1 147 148 149Once the initialization is complete, the application is ready to launch a 150function on an lcore. In this example ``lcore_main()`` is called on a single 151lcore. 152 153.. code-block:: c 154 155 lcore_main(); 156 157The ``lcore_main()`` function is explained below. 158 159 160The Lcores Main 161~~~~~~~~~~~~~~~ 162 163As we saw above the ``main()`` function calls an application function on the 164available lcores. 165 166The main work of the application is done within the loop: 167 168.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 169 :language: c 170 :start-after: Read packet from RX queues. 8< 171 :end-before: >8 End of read packets from RX queues. 172 :dedent: 2 173 174Packets are received one by one on the RX ports and, if required, PTP response 175packets are transmitted on the TX ports. 176 177If the offload flags in the mbuf indicate that the packet is a PTP packet then 178the packet is parsed to determine which type: 179 180.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 181 :language: c 182 :start-after: Packet is parsed to determine which type. 8< 183 :end-before: >8 End of packet is parsed to determine which type. 184 :dedent: 3 185 186 187All packets are freed explicitly using ``rte_pktmbuf_free()``. 188 189The forwarding loop can be interrupted and the application closed using 190``Ctrl-C``. 191 192 193PTP parsing 194~~~~~~~~~~~ 195 196The ``parse_ptp_frames()`` function processes PTP packets, implementing time receiver 197PTP IEEE1588 L2 functionality. 198 199.. literalinclude:: ../../../examples/ptpclient/ptpclient.c 200 :language: c 201 :start-after: Parse ptp frames. 8< 202 :end-before: >8 End of function processes PTP packets. 203 204There are 3 types of packets on the RX path which we must parse to create a minimal 205implementation of the PTP time receiver client: 206 207* SYNC packet. 208* FOLLOW UP packet 209* DELAY RESPONSE packet. 210 211When we parse the *FOLLOW UP* packet we also create and send a *DELAY_REQUEST* packet. 212Also when we parse the *DELAY RESPONSE* packet, and all conditions are met 213we adjust the PTP time receiver clock. 214