1*a584d3beSAshish Gupta.. SPDX-License-Identifier: BSD-3-Clause 2*a584d3beSAshish Gupta Copyright(c) 2017-2018 Cavium Networks. 3*a584d3beSAshish Gupta 4*a584d3beSAshish GuptaCompression Device Library 5*a584d3beSAshish Gupta=========================== 6*a584d3beSAshish Gupta 7*a584d3beSAshish GuptaThe compression framework provides a generic set of APIs to perform compression services 8*a584d3beSAshish Guptaas well as to query and configure compression devices both physical(hardware) and virtual(software) 9*a584d3beSAshish Guptato perform those services. The framework currently only supports lossless compression schemes: 10*a584d3beSAshish GuptaDeflate and LZS. 11*a584d3beSAshish Gupta 12*a584d3beSAshish GuptaDevice Management 13*a584d3beSAshish Gupta----------------- 14*a584d3beSAshish Gupta 15*a584d3beSAshish GuptaDevice Creation 16*a584d3beSAshish Gupta~~~~~~~~~~~~~~~ 17*a584d3beSAshish Gupta 18*a584d3beSAshish GuptaPhysical compression devices are discovered during the bus probe of the EAL function 19*a584d3beSAshish Guptawhich is executed at DPDK initialization, based on their unique device identifier. 20*a584d3beSAshish GuptaFor eg. PCI devices can be identified using PCI BDF (bus/bridge, device, function). 21*a584d3beSAshish GuptaSpecific physical compression devices, like other physical devices in DPDK can be 22*a584d3beSAshish Guptawhite-listed or black-listed using the EAL command line options. 23*a584d3beSAshish Gupta 24*a584d3beSAshish GuptaVirtual devices can be created by two mechanisms, either using the EAL command 25*a584d3beSAshish Guptaline options or from within the application using an EAL API directly. 26*a584d3beSAshish Gupta 27*a584d3beSAshish GuptaFrom the command line using the --vdev EAL option 28*a584d3beSAshish Gupta 29*a584d3beSAshish Gupta.. code-block:: console 30*a584d3beSAshish Gupta 31*a584d3beSAshish Gupta --vdev '<pmd name>,socket_id=0' 32*a584d3beSAshish Gupta 33*a584d3beSAshish Gupta.. Note:: 34*a584d3beSAshish Gupta 35*a584d3beSAshish Gupta * If DPDK application requires multiple software compression PMD devices then required 36*a584d3beSAshish Gupta number of ``--vdev`` with appropriate libraries are to be added. 37*a584d3beSAshish Gupta 38*a584d3beSAshish Gupta * An Application with multiple compression device instances exposed by the same PMD must 39*a584d3beSAshish Gupta specify a unique name for each device. 40*a584d3beSAshish Gupta 41*a584d3beSAshish Gupta Example: ``--vdev 'pmd0' --vdev 'pmd1'`` 42*a584d3beSAshish Gupta 43*a584d3beSAshish GuptaOr, by using the rte_vdev_init API within the application code. 44*a584d3beSAshish Gupta 45*a584d3beSAshish Gupta.. code-block:: c 46*a584d3beSAshish Gupta 47*a584d3beSAshish Gupta rte_vdev_init("<pmd_name>","socket_id=0") 48*a584d3beSAshish Gupta 49*a584d3beSAshish GuptaAll virtual compression devices support the following initialization parameters: 50*a584d3beSAshish Gupta 51*a584d3beSAshish Gupta* ``socket_id`` - socket on which to allocate the device resources on. 52*a584d3beSAshish Gupta 53*a584d3beSAshish GuptaDevice Identification 54*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~ 55*a584d3beSAshish Gupta 56*a584d3beSAshish GuptaEach device, whether virtual or physical is uniquely designated by two 57*a584d3beSAshish Guptaidentifiers: 58*a584d3beSAshish Gupta 59*a584d3beSAshish Gupta- A unique device index used to designate the compression device in all functions 60*a584d3beSAshish Gupta exported by the compressdev API. 61*a584d3beSAshish Gupta 62*a584d3beSAshish Gupta- A device name used to designate the compression device in console messages, for 63*a584d3beSAshish Gupta administration or debugging purposes. 64*a584d3beSAshish Gupta 65*a584d3beSAshish GuptaDevice Configuration 66*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~ 67*a584d3beSAshish Gupta 68*a584d3beSAshish GuptaThe configuration of each compression device includes the following operations: 69*a584d3beSAshish Gupta 70*a584d3beSAshish Gupta- Allocation of resources, including hardware resources if a physical device. 71*a584d3beSAshish Gupta- Resetting the device into a well-known default state. 72*a584d3beSAshish Gupta- Initialization of statistics counters. 73*a584d3beSAshish Gupta 74*a584d3beSAshish GuptaThe ``rte_compressdev_configure`` API is used to configure a compression device. 75*a584d3beSAshish Gupta 76*a584d3beSAshish GuptaThe ``rte_compressdev_config`` structure is used to pass the configuration 77*a584d3beSAshish Guptaparameters. 78*a584d3beSAshish Gupta 79*a584d3beSAshish GuptaSee *DPDK API Reference* for details. 80*a584d3beSAshish Gupta 81*a584d3beSAshish GuptaConfiguration of Queue Pairs 82*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83*a584d3beSAshish Gupta 84*a584d3beSAshish GuptaEach compression device queue pair is individually configured through the 85*a584d3beSAshish Gupta``rte_compressdev_queue_pair_setup`` API. 86*a584d3beSAshish Gupta 87*a584d3beSAshish GuptaThe ``max_inflight_ops`` is used to pass maximum number of 88*a584d3beSAshish Guptarte_comp_op that could be present in a queue at-a-time. 89*a584d3beSAshish GuptaPMD then can allocate resources accordingly on a specified socket. 90*a584d3beSAshish Gupta 91*a584d3beSAshish GuptaSee *DPDK API Reference* for details. 92*a584d3beSAshish Gupta 93*a584d3beSAshish GuptaLogical Cores, Memory and Queues Pair Relationships 94*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 95*a584d3beSAshish Gupta 96*a584d3beSAshish GuptaLibrary supports NUMA similarly as described in Cryptodev library section. 97*a584d3beSAshish Gupta 98*a584d3beSAshish GuptaA queue pair cannot be shared and should be exclusively used by a single processing 99*a584d3beSAshish Guptacontext for enqueuing operations or dequeuing operations on the same compression device 100*a584d3beSAshish Guptasince sharing would require global locks and hinder performance. It is however possible 101*a584d3beSAshish Guptato use a different logical core to dequeue an operation on a queue pair from the logical 102*a584d3beSAshish Guptacore on which it was enqueued. This means that a compression burst enqueue/dequeue 103*a584d3beSAshish GuptaAPIs are a logical place to transition from one logical core to another in a 104*a584d3beSAshish Guptadata processing pipeline. 105*a584d3beSAshish Gupta 106*a584d3beSAshish GuptaDevice Features and Capabilities 107*a584d3beSAshish Gupta--------------------------------- 108*a584d3beSAshish Gupta 109*a584d3beSAshish GuptaCompression devices define their functionality through two mechanisms, global device 110*a584d3beSAshish Guptafeatures and algorithm features. Global devices features identify device 111*a584d3beSAshish Guptawide level features which are applicable to the whole device such as supported hardware 112*a584d3beSAshish Guptaacceleration and CPU features. List of compression device features can be seen in the 113*a584d3beSAshish GuptaRTE_COMPDEV_FF_XXX macros. 114*a584d3beSAshish Gupta 115*a584d3beSAshish GuptaThe algorithm features lists individual algo feature which device supports per-algorithm, 116*a584d3beSAshish Guptasuch as a stateful compression/decompression, checksums operation etc. List of algorithm 117*a584d3beSAshish Guptafeatures can be seen in the RTE_COMP_FF_XXX macros. 118*a584d3beSAshish Gupta 119*a584d3beSAshish GuptaCapabilities 120*a584d3beSAshish Gupta~~~~~~~~~~~~ 121*a584d3beSAshish GuptaEach PMD has a list of capabilities, including algorithms listed in 122*a584d3beSAshish Guptaenum ``rte_comp_algorithm`` and its associated feature flag and 123*a584d3beSAshish Guptasliding window range in log base 2 value. Sliding window tells 124*a584d3beSAshish Guptathe minimum and maximum size of lookup window that algorithm uses 125*a584d3beSAshish Guptato find duplicates. 126*a584d3beSAshish Gupta 127*a584d3beSAshish GuptaSee *DPDK API Reference* for details. 128*a584d3beSAshish Gupta 129*a584d3beSAshish GuptaEach Compression poll mode driver defines its array of capabilities 130*a584d3beSAshish Guptafor each algorithm it supports. See PMD implementation for capability 131*a584d3beSAshish Guptainitialization. 132*a584d3beSAshish Gupta 133*a584d3beSAshish GuptaCapabilities Discovery 134*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~ 135*a584d3beSAshish Gupta 136*a584d3beSAshish GuptaPMD capability and features are discovered via ``rte_compressdev_info_get`` function. 137*a584d3beSAshish Gupta 138*a584d3beSAshish GuptaThe ``rte_compressdev_info`` structure contains all the relevant information for the device. 139*a584d3beSAshish Gupta 140*a584d3beSAshish GuptaSee *DPDK API Reference* for details. 141*a584d3beSAshish Gupta 142*a584d3beSAshish GuptaCompression Operation 143*a584d3beSAshish Gupta---------------------- 144*a584d3beSAshish Gupta 145*a584d3beSAshish GuptaDPDK compression supports two types of compression methodologies: 146*a584d3beSAshish Gupta 147*a584d3beSAshish Gupta- Stateless, data associated to a compression operation is compressed without any reference 148*a584d3beSAshish Gupta to another compression operation. 149*a584d3beSAshish Gupta 150*a584d3beSAshish Gupta- Stateful, data in each compression operation is compressed with reference to previous compression 151*a584d3beSAshish Gupta operations in the same data stream i.e. history of data is maintained between the operations. 152*a584d3beSAshish Gupta 153*a584d3beSAshish GuptaFor more explanation, please refer RFC https://www.ietf.org/rfc/rfc1951.txt 154*a584d3beSAshish Gupta 155*a584d3beSAshish GuptaOperation Representation 156*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~ 157*a584d3beSAshish Gupta 158*a584d3beSAshish GuptaCompression operation is described via ``struct rte_comp_op``, which contains both input and 159*a584d3beSAshish Guptaoutput data. The operation structure includes the operation type (stateless or stateful), 160*a584d3beSAshish Guptathe operation status and the priv_xform/stream handle, source, destination and checksum buffer 161*a584d3beSAshish Guptapointers. It also contains the source mempool from which the operation is allocated. 162*a584d3beSAshish GuptaPMD updates consumed field with amount of data read from source buffer and produced 163*a584d3beSAshish Guptafield with amount of data of written into destination buffer along with status of 164*a584d3beSAshish Guptaoperation. See section *Produced, Consumed And Operation Status* for more details. 165*a584d3beSAshish Gupta 166*a584d3beSAshish GuptaCompression operations mempool also has an ability to allocate private memory with the 167*a584d3beSAshish Guptaoperation for application's purposes. Application software is responsible for specifying 168*a584d3beSAshish Guptaall the operation specific fields in the ``rte_comp_op`` structure which are then used 169*a584d3beSAshish Guptaby the compression PMD to process the requested operation. 170*a584d3beSAshish Gupta 171*a584d3beSAshish Gupta 172*a584d3beSAshish GuptaOperation Management and Allocation 173*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 174*a584d3beSAshish Gupta 175*a584d3beSAshish GuptaThe compressdev library provides an API set for managing compression operations which 176*a584d3beSAshish Guptautilize the Mempool Library to allocate operation buffers. Therefore, it ensures 177*a584d3beSAshish Guptathat the compression operation is interleaved optimally across the channels and 178*a584d3beSAshish Guptaranks for optimal processing. 179*a584d3beSAshish Gupta 180*a584d3beSAshish GuptaA ``rte_comp_op`` contains a field indicating the pool it originated from. 181*a584d3beSAshish Gupta 182*a584d3beSAshish Gupta``rte_comp_op_alloc()`` and ``rte_comp_op_bulk_alloc()`` are used to allocate 183*a584d3beSAshish Guptacompression operations from a given compression operation mempool. 184*a584d3beSAshish GuptaThe operation gets reset before being returned to a user so that operation 185*a584d3beSAshish Guptais always in a good known state before use by the application. 186*a584d3beSAshish Gupta 187*a584d3beSAshish Gupta``rte_comp_op_free()`` is called by the application to return an operation to 188*a584d3beSAshish Guptaits allocating pool. 189*a584d3beSAshish Gupta 190*a584d3beSAshish GuptaSee *DPDK API Reference* for details. 191*a584d3beSAshish Gupta 192*a584d3beSAshish GuptaPassing source data as mbuf-chain 193*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 194*a584d3beSAshish GuptaIf input data is scattered across several different buffers, then 195*a584d3beSAshish GuptaApplication can either parse through all such buffers and make one 196*a584d3beSAshish Guptambuf-chain and enqueue it for processing or, alternatively, it can 197*a584d3beSAshish Guptamake multiple sequential enqueue_burst() calls for each of them 198*a584d3beSAshish Guptaprocessing them statefully. See *Compression API Stateful Operation* 199*a584d3beSAshish Guptafor stateful processing of ops. 200*a584d3beSAshish Gupta 201*a584d3beSAshish GuptaOperation Status 202*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~ 203*a584d3beSAshish GuptaEach operation carries a status information updated by PMD after it is processed. 204*a584d3beSAshish Guptafollowing are currently supported status: 205*a584d3beSAshish Gupta 206*a584d3beSAshish Gupta- RTE_COMP_OP_STATUS_SUCCESS, 207*a584d3beSAshish Gupta Operation is successfully completed 208*a584d3beSAshish Gupta 209*a584d3beSAshish Gupta- RTE_COMP_OP_STATUS_NOT_PROCESSED, 210*a584d3beSAshish Gupta Operation has not yet been processed by the device 211*a584d3beSAshish Gupta 212*a584d3beSAshish Gupta- RTE_COMP_OP_STATUS_INVALID_ARGS, 213*a584d3beSAshish Gupta Operation failed due to invalid arguments in request 214*a584d3beSAshish Gupta 215*a584d3beSAshish Gupta- RTE_COMP_OP_STATUS_ERROR, 216*a584d3beSAshish Gupta Operation failed because of internal error 217*a584d3beSAshish Gupta 218*a584d3beSAshish Gupta- RTE_COMP_OP_STATUS_INVALID_STATE, 219*a584d3beSAshish Gupta Operation is invoked in invalid state 220*a584d3beSAshish Gupta 221*a584d3beSAshish Gupta- RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED, 222*a584d3beSAshish Gupta Output buffer ran out of space during processing. Error case, 223*a584d3beSAshish Gupta PMD cannot continue from here. 224*a584d3beSAshish Gupta 225*a584d3beSAshish Gupta- RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE, 226*a584d3beSAshish Gupta Output buffer ran out of space before operation completed, but this 227*a584d3beSAshish Gupta is not an error case. Output data up to op.produced can be used and 228*a584d3beSAshish Gupta next op in the stream should continue on from op.consumed+1. 229*a584d3beSAshish Gupta 230*a584d3beSAshish GuptaProduced, Consumed And Operation Status 231*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 232*a584d3beSAshish Gupta 233*a584d3beSAshish Gupta- If status is RTE_COMP_OP_STATUS_SUCCESS, 234*a584d3beSAshish Gupta consumed = amount of data read from input buffer, and 235*a584d3beSAshish Gupta produced = amount of data written in destination buffer 236*a584d3beSAshish Gupta- If status is RTE_COMP_OP_STATUS_FAILURE, 237*a584d3beSAshish Gupta consumed = produced = 0 or undefined 238*a584d3beSAshish Gupta- If status is RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED, 239*a584d3beSAshish Gupta consumed = 0 and 240*a584d3beSAshish Gupta produced = usually 0, but in decompression cases a PMD may return > 0 241*a584d3beSAshish Gupta i.e. amount of data successfully produced until out of space condition 242*a584d3beSAshish Gupta hit. Application can consume output data in this case, if required. 243*a584d3beSAshish Gupta- If status is RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE, 244*a584d3beSAshish Gupta consumed = amount of data read, and 245*a584d3beSAshish Gupta produced = amount of data successfully produced until 246*a584d3beSAshish Gupta out of space condition hit. PMD has ability to recover 247*a584d3beSAshish Gupta from here, so application can submit next op from 248*a584d3beSAshish Gupta consumed+1 and a destination buffer with available space. 249*a584d3beSAshish Gupta 250*a584d3beSAshish GuptaTransforms 251*a584d3beSAshish Gupta---------- 252*a584d3beSAshish Gupta 253*a584d3beSAshish GuptaCompression transforms (``rte_comp_xform``) are the mechanism 254*a584d3beSAshish Guptato specify the details of the compression operation such as algorithm, 255*a584d3beSAshish Guptawindow size and checksum. 256*a584d3beSAshish Gupta 257*a584d3beSAshish GuptaCompression API Hash support 258*a584d3beSAshish Gupta---------------------------- 259*a584d3beSAshish Gupta 260*a584d3beSAshish GuptaCompression API allows application to enable digest calculation 261*a584d3beSAshish Guptaalongside compression and decompression of data. A PMD reflects its 262*a584d3beSAshish Guptasupport for hash algorithms via capability algo feature flags. 263*a584d3beSAshish GuptaIf supported, PMD calculates digest always on plaintext i.e. 264*a584d3beSAshish Guptabefore compression and after decompression. 265*a584d3beSAshish Gupta 266*a584d3beSAshish GuptaCurrently supported list of hash algos are SHA-1 and SHA2 family 267*a584d3beSAshish GuptaSHA256. 268*a584d3beSAshish Gupta 269*a584d3beSAshish GuptaSee *DPDK API Reference* for details. 270*a584d3beSAshish Gupta 271*a584d3beSAshish GuptaIf required, application should set valid hash algo in compress 272*a584d3beSAshish Guptaor decompress xforms during ``rte_compressdev_stream_create()`` 273*a584d3beSAshish Guptaor ``rte_compressdev_private_xform_create()`` and pass a valid 274*a584d3beSAshish Guptaoutput buffer in ``rte_comp_op`` hash field struct to store the 275*a584d3beSAshish Guptaresulting digest. Buffer passed should be contiguous and large 276*a584d3beSAshish Guptaenough to store digest which is 20 bytes for SHA-1 and 277*a584d3beSAshish Gupta32 bytes for SHA2-256. 278*a584d3beSAshish Gupta 279*a584d3beSAshish GuptaCompression API Stateless operation 280*a584d3beSAshish Gupta------------------------------------ 281*a584d3beSAshish Gupta 282*a584d3beSAshish GuptaAn op is processed stateless if it has 283*a584d3beSAshish Gupta- op_type set to RTE_COMP_OP_STATELESS 284*a584d3beSAshish Gupta- flush value set to RTE_FLUSH_FULL or RTE_FLUSH_FINAL 285*a584d3beSAshish Gupta(required only on compression side), 286*a584d3beSAshish Gupta- All required input in source buffer 287*a584d3beSAshish Gupta 288*a584d3beSAshish GuptaWhen all of the above conditions are met, PMD initiates stateless processing 289*a584d3beSAshish Guptaand releases acquired resources after processing of current operation is 290*a584d3beSAshish Guptacomplete. Application can enqueue multiple stateless ops in a single burst 291*a584d3beSAshish Guptaand must attach priv_xform handle to such ops. 292*a584d3beSAshish Gupta 293*a584d3beSAshish Guptapriv_xform in Stateless operation 294*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 295*a584d3beSAshish Gupta 296*a584d3beSAshish Guptapriv_xform is PMD internally managed private data that it maintains to do stateless processing. 297*a584d3beSAshish Guptapriv_xforms are initialized provided a generic xform structure by an application via making call 298*a584d3beSAshish Guptato ``rte_comp_private_xform_create``, at an output PMD returns an opaque priv_xform reference. 299*a584d3beSAshish GuptaIf PMD support SHAREABLE priv_xform indicated via algorithm feature flag, then application can 300*a584d3beSAshish Guptaattach same priv_xform with many stateless ops at-a-time. If not, then application needs to 301*a584d3beSAshish Guptacreate as many priv_xforms as it expects to have stateless operations in-flight. 302*a584d3beSAshish Gupta 303*a584d3beSAshish Gupta.. figure:: img/stateless-op.* 304*a584d3beSAshish Gupta 305*a584d3beSAshish Gupta Stateless Ops using Non-Shareable priv_xform 306*a584d3beSAshish Gupta 307*a584d3beSAshish Gupta 308*a584d3beSAshish Gupta.. figure:: img/stateless-op-shared.* 309*a584d3beSAshish Gupta 310*a584d3beSAshish Gupta Stateless Ops using Shareable priv_xform 311*a584d3beSAshish Gupta 312*a584d3beSAshish Gupta 313*a584d3beSAshish GuptaApplication should call ``rte_compressdev_private_xform_create()`` and attach to stateless op before 314*a584d3beSAshish Guptaenqueuing them for processing and free via ``rte_compressdev_private_xform_free()`` during termination. 315*a584d3beSAshish Gupta 316*a584d3beSAshish GuptaAn example pseudocode to setup and process NUM_OPS stateless ops with each of length OP_LEN 317*a584d3beSAshish Guptausing priv_xform would look like: 318*a584d3beSAshish Gupta 319*a584d3beSAshish Gupta.. code-block:: c 320*a584d3beSAshish Gupta 321*a584d3beSAshish Gupta /* 322*a584d3beSAshish Gupta * pseudocode for stateless compression 323*a584d3beSAshish Gupta */ 324*a584d3beSAshish Gupta 325*a584d3beSAshish Gupta uint8_t cdev_id = rte_compdev_get_dev_id(<pmd name>); 326*a584d3beSAshish Gupta 327*a584d3beSAshish Gupta /* configure the device. */ 328*a584d3beSAshish Gupta if (rte_compressdev_configure(cdev_id, &conf) < 0) 329*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Failed to configure compressdev %u", cdev_id); 330*a584d3beSAshish Gupta 331*a584d3beSAshish Gupta if (rte_compressdev_queue_pair_setup(cdev_id, 0, NUM_MAX_INFLIGHT_OPS, 332*a584d3beSAshish Gupta socket_id()) < 0) 333*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Failed to setup queue pair\n"); 334*a584d3beSAshish Gupta 335*a584d3beSAshish Gupta if (rte_compressdev_start(cdev_id) < 0) 336*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Failed to start device\n"); 337*a584d3beSAshish Gupta 338*a584d3beSAshish Gupta /* setup compress transform */ 339*a584d3beSAshish Gupta struct rte_compress_compress_xform compress_xform = { 340*a584d3beSAshish Gupta .type = RTE_COMP_COMPRESS, 341*a584d3beSAshish Gupta .compress = { 342*a584d3beSAshish Gupta .algo = RTE_COMP_ALGO_DEFLATE, 343*a584d3beSAshish Gupta .deflate = { 344*a584d3beSAshish Gupta .huffman = RTE_COMP_HUFFMAN_DEFAULT 345*a584d3beSAshish Gupta }, 346*a584d3beSAshish Gupta .level = RTE_COMP_LEVEL_PMD_DEFAULT, 347*a584d3beSAshish Gupta .chksum = RTE_COMP_CHECKSUM_NONE, 348*a584d3beSAshish Gupta .window_size = DEFAULT_WINDOW_SIZE, 349*a584d3beSAshish Gupta .hash_algo = RTE_COMP_HASH_ALGO_NONE 350*a584d3beSAshish Gupta } 351*a584d3beSAshish Gupta }; 352*a584d3beSAshish Gupta 353*a584d3beSAshish Gupta /* create priv_xform and initialize it for the compression device. */ 354*a584d3beSAshish Gupta void *priv_xform = NULL; 355*a584d3beSAshish Gupta rte_compressdev_info_get(cdev_id, &dev_info); 356*a584d3beSAshish Gupta if(dev_info.capability->comps_feature_flag & RTE_COMP_FF_SHAREABLE_PRIV_XFORM) { 357*a584d3beSAshish Gupta rte_comp_priv_xform_create(cdev_id, &compress_xform, &priv_xform); 358*a584d3beSAshish Gupta } else { 359*a584d3beSAshish Gupta shareable = 0; 360*a584d3beSAshish Gupta } 361*a584d3beSAshish Gupta 362*a584d3beSAshish Gupta /* create operation pool via call to rte_comp_op_pool_create and alloc ops */ 363*a584d3beSAshish Gupta rte_comp_op_bulk_alloc(op_pool, comp_ops, NUM_OPS); 364*a584d3beSAshish Gupta 365*a584d3beSAshish Gupta /* prepare ops for compression operations */ 366*a584d3beSAshish Gupta for (i = 0; i < NUM_OPS; i++) { 367*a584d3beSAshish Gupta struct rte_comp_op *op = comp_ops[i]; 368*a584d3beSAshish Gupta if (!shareable) 369*a584d3beSAshish Gupta rte_priv_xform_create(cdev_id, &compress_xform, &op->priv_xform) 370*a584d3beSAshish Gupta else 371*a584d3beSAshish Gupta op->priv_xform = priv_xform; 372*a584d3beSAshish Gupta op->type = RTE_COMP_OP_STATELESS; 373*a584d3beSAshish Gupta op->flush = RTE_COMP_FLUSH_FINAL; 374*a584d3beSAshish Gupta 375*a584d3beSAshish Gupta op->src.offset = 0; 376*a584d3beSAshish Gupta op->dst.offset = 0; 377*a584d3beSAshish Gupta op->src.length = OP_LEN; 378*a584d3beSAshish Gupta op->input_chksum = 0; 379*a584d3beSAshish Gupta setup op->m_src and op->m_dst; 380*a584d3beSAshish Gupta } 381*a584d3beSAshish Gupta num_enqd = rte_compressdev_enqueue_burst(cdev_id, 0, comp_ops, NUM_OPS); 382*a584d3beSAshish Gupta /* wait for this to complete before enqueing next*/ 383*a584d3beSAshish Gupta do { 384*a584d3beSAshish Gupta num_deque = rte_compressdev_dequeue_burst(cdev_id, 0 , &processed_ops, NUM_OPS); 385*a584d3beSAshish Gupta } while (num_dqud < num_enqd); 386*a584d3beSAshish Gupta 387*a584d3beSAshish Gupta 388*a584d3beSAshish GuptaStateless and OUT_OF_SPACE 389*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 390*a584d3beSAshish Gupta 391*a584d3beSAshish GuptaOUT_OF_SPACE is a condition when output buffer runs out of space and where PMD 392*a584d3beSAshish Guptastill has more data to produce. If PMD runs into such condition, then PMD returns 393*a584d3beSAshish GuptaRTE_COMP_OP_OUT_OF_SPACE_TERMINATED error. In such case, PMD resets itself and can set 394*a584d3beSAshish Guptaconsumed=0 and produced=amount of output it could produce before hitting out_of_space. 395*a584d3beSAshish GuptaApplication would need to resubmit the whole input with a larger output buffer, if it 396*a584d3beSAshish Guptawants the operation to be completed. 397*a584d3beSAshish Gupta 398*a584d3beSAshish GuptaHash in Stateless 399*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~ 400*a584d3beSAshish GuptaIf hash is enabled, digest buffer will contain valid data after op is successfully 401*a584d3beSAshish Guptaprocessed i.e. dequeued with status = RTE_COMP_OP_STATUS_SUCCESS. 402*a584d3beSAshish Gupta 403*a584d3beSAshish GuptaChecksum in Stateless 404*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~ 405*a584d3beSAshish GuptaIf checksum is enabled, checksum will only be available after op is successfully 406*a584d3beSAshish Guptaprocessed i.e. dequeued with status = RTE_COMP_OP_STATUS_SUCCESS. 407*a584d3beSAshish Gupta 408*a584d3beSAshish GuptaCompression API Stateful operation 409*a584d3beSAshish Gupta----------------------------------- 410*a584d3beSAshish Gupta 411*a584d3beSAshish GuptaCompression API provide RTE_COMP_FF_STATEFUL_COMPRESSION and 412*a584d3beSAshish GuptaRTE_COMP_FF_STATEFUL_DECOMPRESSION feature flag for PMD to reflect 413*a584d3beSAshish Guptaits support for Stateful operations. 414*a584d3beSAshish Gupta 415*a584d3beSAshish GuptaA Stateful operation in DPDK compression means application invokes enqueue 416*a584d3beSAshish Guptaburst() multiple times to process related chunk of data because 417*a584d3beSAshish Guptaapplication broke data into several ops. 418*a584d3beSAshish Gupta 419*a584d3beSAshish GuptaIn such case 420*a584d3beSAshish Gupta- ops are setup with op_type RTE_COMP_OP_STATEFUL, 421*a584d3beSAshish Gupta- all ops except last set to flush value = RTE_COMP_NO/SYNC_FLUSH 422*a584d3beSAshish Guptaand last set to flush value RTE_COMP_FULL/FINAL_FLUSH. 423*a584d3beSAshish Gupta 424*a584d3beSAshish GuptaIn case of either one or all of the above conditions, PMD initiates 425*a584d3beSAshish Guptastateful processing and releases acquired resources after processing 426*a584d3beSAshish Guptaoperation with flush value = RTE_COMP_FLUSH_FULL/FINAL is complete. 427*a584d3beSAshish GuptaUnlike stateless, application can enqueue only one stateful op from 428*a584d3beSAshish Guptaa particular stream at a time and must attach stream handle 429*a584d3beSAshish Guptato each op. 430*a584d3beSAshish Gupta 431*a584d3beSAshish GuptaStream in Stateful operation 432*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 433*a584d3beSAshish Gupta 434*a584d3beSAshish Gupta`stream` in DPDK compression is a logical entity which identifies related set of ops, say, a one large 435*a584d3beSAshish Guptafile broken into multiple chunks then file is represented by a stream and each chunk of that file is 436*a584d3beSAshish Guptarepresented by compression op `rte_comp_op`. Whenever application wants a stateful processing of such 437*a584d3beSAshish Guptadata, then it must get a stream handle via making call to ``rte_comp_stream_create()`` 438*a584d3beSAshish Guptawith xform, at an output the target PMD will return an opaque stream handle to application which 439*a584d3beSAshish Guptait must attach to all of the ops carrying data of that stream. In stateful processing, every op 440*a584d3beSAshish Guptarequires previous op data for compression/decompression. A PMD allocates and set up resources such 441*a584d3beSAshish Guptaas history, states, etc. within a stream, which are maintained during the processing of the related ops. 442*a584d3beSAshish Gupta 443*a584d3beSAshish GuptaUnlike priv_xforms, stream is always a NON_SHAREABLE entity. One stream handle must be attached to only 444*a584d3beSAshish Guptaone set of related ops and cannot be reused until all of them are processed with status Success or failure. 445*a584d3beSAshish Gupta 446*a584d3beSAshish Gupta.. figure:: img/stateful-op.* 447*a584d3beSAshish Gupta 448*a584d3beSAshish Gupta Stateful Ops 449*a584d3beSAshish Gupta 450*a584d3beSAshish Gupta 451*a584d3beSAshish GuptaApplication should call ``rte_comp_stream_create()`` and attach to op before 452*a584d3beSAshish Guptaenqueuing them for processing and free via ``rte_comp_stream_free()`` during 453*a584d3beSAshish Guptatermination. All ops that are to be processed statefully should carry *same* stream. 454*a584d3beSAshish Gupta 455*a584d3beSAshish GuptaSee *DPDK API Reference* document for details. 456*a584d3beSAshish Gupta 457*a584d3beSAshish GuptaAn example pseudocode to set up and process a stream having NUM_CHUNKS with each chunk size of CHUNK_LEN would look like: 458*a584d3beSAshish Gupta 459*a584d3beSAshish Gupta.. code-block:: c 460*a584d3beSAshish Gupta 461*a584d3beSAshish Gupta /* 462*a584d3beSAshish Gupta * pseudocode for stateful compression 463*a584d3beSAshish Gupta */ 464*a584d3beSAshish Gupta 465*a584d3beSAshish Gupta uint8_t cdev_id = rte_compdev_get_dev_id(<pmd name>); 466*a584d3beSAshish Gupta 467*a584d3beSAshish Gupta /* configure the device. */ 468*a584d3beSAshish Gupta if (rte_compressdev_configure(cdev_id, &conf) < 0) 469*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Failed to configure compressdev %u", cdev_id); 470*a584d3beSAshish Gupta 471*a584d3beSAshish Gupta if (rte_compressdev_queue_pair_setup(cdev_id, 0, NUM_MAX_INFLIGHT_OPS, 472*a584d3beSAshish Gupta socket_id()) < 0) 473*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Failed to setup queue pair\n"); 474*a584d3beSAshish Gupta 475*a584d3beSAshish Gupta if (rte_compressdev_start(cdev_id) < 0) 476*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Failed to start device\n"); 477*a584d3beSAshish Gupta 478*a584d3beSAshish Gupta /* setup compress transform. */ 479*a584d3beSAshish Gupta struct rte_compress_compress_xform compress_xform = { 480*a584d3beSAshish Gupta .type = RTE_COMP_COMPRESS, 481*a584d3beSAshish Gupta .compress = { 482*a584d3beSAshish Gupta .algo = RTE_COMP_ALGO_DEFLATE, 483*a584d3beSAshish Gupta .deflate = { 484*a584d3beSAshish Gupta .huffman = RTE_COMP_HUFFMAN_DEFAULT 485*a584d3beSAshish Gupta }, 486*a584d3beSAshish Gupta .level = RTE_COMP_LEVEL_PMD_DEFAULT, 487*a584d3beSAshish Gupta .chksum = RTE_COMP_CHECKSUM_NONE, 488*a584d3beSAshish Gupta .window_size = DEFAULT_WINDOW_SIZE, 489*a584d3beSAshish Gupta .hash_algo = RTE_COMP_HASH_ALGO_NONE 490*a584d3beSAshish Gupta } 491*a584d3beSAshish Gupta }; 492*a584d3beSAshish Gupta 493*a584d3beSAshish Gupta /* create stream */ 494*a584d3beSAshish Gupta rte_comp_stream_create(cdev_id, &compress_xform, &stream); 495*a584d3beSAshish Gupta 496*a584d3beSAshish Gupta /* create an op pool and allocate ops */ 497*a584d3beSAshish Gupta rte_comp_op_bulk_alloc(op_pool, comp_ops, NUM_CHUNKS); 498*a584d3beSAshish Gupta 499*a584d3beSAshish Gupta /* Prepare source and destination mbufs for compression operations */ 500*a584d3beSAshish Gupta unsigned int i; 501*a584d3beSAshish Gupta for (i = 0; i < NUM_CHUNKS; i++) { 502*a584d3beSAshish Gupta if (rte_pktmbuf_append(mbufs[i], CHUNK_LEN) == NULL) 503*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Not enough room in the mbuf\n"); 504*a584d3beSAshish Gupta comp_ops[i]->m_src = mbufs[i]; 505*a584d3beSAshish Gupta if (rte_pktmbuf_append(dst_mbufs[i], CHUNK_LEN) == NULL) 506*a584d3beSAshish Gupta rte_exit(EXIT_FAILURE, "Not enough room in the mbuf\n"); 507*a584d3beSAshish Gupta comp_ops[i]->m_dst = dst_mbufs[i]; 508*a584d3beSAshish Gupta } 509*a584d3beSAshish Gupta 510*a584d3beSAshish Gupta /* Set up the compress operations. */ 511*a584d3beSAshish Gupta for (i = 0; i < NUM_CHUNKS; i++) { 512*a584d3beSAshish Gupta struct rte_comp_op *op = comp_ops[i]; 513*a584d3beSAshish Gupta op->stream = stream; 514*a584d3beSAshish Gupta op->m_src = src_buf[i]; 515*a584d3beSAshish Gupta op->m_dst = dst_buf[i]; 516*a584d3beSAshish Gupta op->type = RTE_COMP_OP_STATEFUL; 517*a584d3beSAshish Gupta if(i == NUM_CHUNKS-1) { 518*a584d3beSAshish Gupta /* set to final, if last chunk*/ 519*a584d3beSAshish Gupta op->flush = RTE_COMP_FLUSH_FINAL; 520*a584d3beSAshish Gupta } else { 521*a584d3beSAshish Gupta /* set to NONE, for all intermediary ops */ 522*a584d3beSAshish Gupta op->flush = RTE_COMP_FLUSH_NONE; 523*a584d3beSAshish Gupta } 524*a584d3beSAshish Gupta op->src.offset = 0; 525*a584d3beSAshish Gupta op->dst.offset = 0; 526*a584d3beSAshish Gupta op->src.length = CHUNK_LEN; 527*a584d3beSAshish Gupta op->input_chksum = 0; 528*a584d3beSAshish Gupta num_enqd = rte_compressdev_enqueue_burst(cdev_id, 0, &op[i], 1); 529*a584d3beSAshish Gupta /* wait for this to complete before enqueing next*/ 530*a584d3beSAshish Gupta do { 531*a584d3beSAshish Gupta num_deqd = rte_compressdev_dequeue_burst(cdev_id, 0 , &processed_ops, 1); 532*a584d3beSAshish Gupta } while (num_deqd < num_enqd); 533*a584d3beSAshish Gupta /* push next op*/ 534*a584d3beSAshish Gupta } 535*a584d3beSAshish Gupta 536*a584d3beSAshish Gupta 537*a584d3beSAshish GuptaStateful and OUT_OF_SPACE 538*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~ 539*a584d3beSAshish Gupta 540*a584d3beSAshish GuptaIf PMD supports stateful operation, then OUT_OF_SPACE status is not an actual 541*a584d3beSAshish Guptaerror for the PMD. In such case, PMD returns with status 542*a584d3beSAshish GuptaRTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE with consumed = number of input bytes 543*a584d3beSAshish Guptaread and produced = length of complete output buffer. 544*a584d3beSAshish GuptaApplication should enqueue next op with source starting at consumed+1 and an 545*a584d3beSAshish Guptaoutput buffer with available space. 546*a584d3beSAshish Gupta 547*a584d3beSAshish GuptaHash in Stateful 548*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~ 549*a584d3beSAshish GuptaIf enabled, digest buffer will contain valid digest after last op in stream 550*a584d3beSAshish Gupta(having flush = RTE_COMP_OP_FLUSH_FINAL) is successfully processed i.e. dequeued 551*a584d3beSAshish Guptawith status = RTE_COMP_OP_STATUS_SUCCESS. 552*a584d3beSAshish Gupta 553*a584d3beSAshish GuptaChecksum in Stateful 554*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~ 555*a584d3beSAshish GuptaIf enabled, checksum will only be available after last op in stream 556*a584d3beSAshish Gupta(having flush = RTE_COMP_OP_FLUSH_FINAL) is successfully processed i.e. dequeued 557*a584d3beSAshish Guptawith status = RTE_COMP_OP_STATUS_SUCCESS. 558*a584d3beSAshish Gupta 559*a584d3beSAshish GuptaBurst in compression API 560*a584d3beSAshish Gupta------------------------- 561*a584d3beSAshish Gupta 562*a584d3beSAshish GuptaScheduling of compression operations on DPDK's application data path is 563*a584d3beSAshish Guptaperformed using a burst oriented asynchronous API set. A queue pair on a compression 564*a584d3beSAshish Guptadevice accepts a burst of compression operations using enqueue burst API. On physical 565*a584d3beSAshish Guptadevices the enqueue burst API will place the operations to be processed 566*a584d3beSAshish Guptaon the device's hardware input queue, for virtual devices the processing of the 567*a584d3beSAshish Guptaoperations is usually completed during the enqueue call to the compression 568*a584d3beSAshish Guptadevice. The dequeue burst API will retrieve any processed operations available 569*a584d3beSAshish Guptafrom the queue pair on the compression device, from physical devices this is usually 570*a584d3beSAshish Guptadirectly from the devices processed queue, and for virtual device's from a 571*a584d3beSAshish Gupta``rte_ring`` where processed operations are place after being processed on the 572*a584d3beSAshish Guptaenqueue call. 573*a584d3beSAshish Gupta 574*a584d3beSAshish GuptaA burst in DPDK compression can be a combination of stateless and stateful operations with a condition 575*a584d3beSAshish Guptathat for stateful ops only one op at-a-time should be enqueued from a particular stream i.e. no-two ops 576*a584d3beSAshish Guptashould belong to same stream in a single burst. However a burst may contain multiple stateful ops as long 577*a584d3beSAshish Guptaas each op is attached to a different stream i.e. a burst can look like: 578*a584d3beSAshish Gupta 579*a584d3beSAshish Gupta+---------------+--------------+--------------+-----------------+--------------+--------------+ 580*a584d3beSAshish Gupta| enqueue_burst | op1.no_flush | op2.no_flush | op3.flush_final | op4.no_flush | op5.no_flush | 581*a584d3beSAshish Gupta+---------------+--------------+--------------+-----------------+--------------+--------------+ 582*a584d3beSAshish Gupta 583*a584d3beSAshish GuptaWhere, op1 .. op5 all belong to different independent data units. op1, op2, op4, op5 must be stateful 584*a584d3beSAshish Guptaas stateless ops can only use flush full or final and op3 can be of type stateless or stateful. 585*a584d3beSAshish GuptaEvery op with type set to RTE_COMP_OP_TYPE_STATELESS must be attached to priv_xform and 586*a584d3beSAshish GuptaEvery op with type set to RTE_COMP_OP_TYPE_STATEFUL *must* be attached to stream. 587*a584d3beSAshish Gupta 588*a584d3beSAshish GuptaSince each operation in a burst is independent and thus can be completed 589*a584d3beSAshish Guptaout-of-order, applications which need ordering, should setup per-op user data 590*a584d3beSAshish Guptaarea with reordering information so that it can determine enqueue order at 591*a584d3beSAshish Guptadequeue. 592*a584d3beSAshish Gupta 593*a584d3beSAshish GuptaAlso if multiple threads calls enqueue_burst() on same queue pair then it’s 594*a584d3beSAshish Guptaapplication onus to use proper locking mechanism to ensure exclusive enqueuing 595*a584d3beSAshish Guptaof operations. 596*a584d3beSAshish Gupta 597*a584d3beSAshish GuptaEnqueue / Dequeue Burst APIs 598*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 599*a584d3beSAshish Gupta 600*a584d3beSAshish GuptaThe burst enqueue API uses a compression device identifier and a queue pair 601*a584d3beSAshish Guptaidentifier to specify the compression device queue pair to schedule the processing on. 602*a584d3beSAshish GuptaThe ``nb_ops`` parameter is the number of operations to process which are 603*a584d3beSAshish Guptasupplied in the ``ops`` array of ``rte_comp_op`` structures. 604*a584d3beSAshish GuptaThe enqueue function returns the number of operations it actually enqueued for 605*a584d3beSAshish Guptaprocessing, a return value equal to ``nb_ops`` means that all packets have been 606*a584d3beSAshish Guptaenqueued. 607*a584d3beSAshish Gupta 608*a584d3beSAshish GuptaThe dequeue API uses the same format as the enqueue API but 609*a584d3beSAshish Guptathe ``nb_ops`` and ``ops`` parameters are now used to specify the max processed 610*a584d3beSAshish Guptaoperations the user wishes to retrieve and the location in which to store them. 611*a584d3beSAshish GuptaThe API call returns the actual number of processed operations returned, this 612*a584d3beSAshish Guptacan never be larger than ``nb_ops``. 613*a584d3beSAshish Gupta 614*a584d3beSAshish GuptaSample code 615*a584d3beSAshish Gupta----------- 616*a584d3beSAshish Gupta 617*a584d3beSAshish GuptaThere are unit test applications that show how to use the compressdev library inside 618*a584d3beSAshish Guptatest/test/test_compressdev.c 619*a584d3beSAshish Gupta 620*a584d3beSAshish GuptaCompression Device API 621*a584d3beSAshish Gupta~~~~~~~~~~~~~~~~~~~~~~ 622*a584d3beSAshish Gupta 623*a584d3beSAshish GuptaThe compressdev Library API is described in the *DPDK API Reference* document. 624