.. Copyright (c) 2019-2022 Intel .. .. Licensed under the Apache License, Version 2.0 (the "License"); .. you may not use this file except in compliance with the License. .. You may obtain a copy of the License at .. .. http://www.apache.org/licenses/LICENSE-2.0 .. .. Unless required by applicable law or agreed to in writing, software .. distributed under the License is distributed on an "AS IS" BASIS, .. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. .. See the License for the specific language governing permissions and .. limitations under the License. eCPRI DDP Profile for Columbiaville (Experimental Feature) ========================================================== .. _introduction-3: Introduction ============ The Intel® Ethernet 800 Series is the next generation of Intel® Ethernet Controllers and Network Adapters. The Intel® Ethernet 800 Series is designed with an enhanced programmable pipeline, allowing deeper and more diverse protocol header processing. This on-chip capability is called Dynamic Device Personalization (DDP). In the Intel® Ethernet 800 Series, a DDP profile is loaded dynamically on driver load per device. A general-purpose DDP package is automatically installed with all supported Intel® Ethernet 800 Series drivers on Windows*, ESX*, FreeBSD*, and Linux\* operating systems, including those provided by the Data Plane Development Kit (DPDK). This general-purpose DDP package is known as the OS-default package. For more information on DDP technology in the Intel® Ethernet 800 Series products and the OS-default package, refer to the Intel® Ethernet Controller E810 Dynamic Device Personalization (DDP) Technology Guide, published here: https://cdrdv2.intel.com/v1/dl/getContent/617015. This document describes an optional DDP package targeted towards the needs of Wireless and Edge (Wireless Edge) customers. This Wireless Edge DDP package (v1.3.22.101) adds support for eCPRI protocols in addition to the protocols in the OS-default package. The Wireless Edge DDP package is supported by DPDK. Starting from DPDK 21.02 drivers and in the future will also be supported by the Intel® Ethernet 800 Series ice driver. on Linux operating systems. The Wireless DDP Package can be loaded on all Intel® Ethernet 800 Series devices, or different packages can be selected via serial number per device. Software/Firmware Requirements ============================== The specific DDP package requires certain firmware and DPDK versions and Intel® Ethernet 800 Series firmware/NVM versions. Support for eCPRI DDP profile included starting from Columbiaville (CVL)release 2.4 or later. This section is for general information purposes as the binaries provided for this FlexRan release in github.com are built with DPDK 20.11.3 and the mix and match of binaries is not supported. The required DPDK version contains the support of loading the specific Wireless Edge DDP package. - Intel® Ethernet 800 Series Linux Driver (ice) — 1.4.0 (or later) - Wireless Edge DDP Package version (ice_wireless_edge) — 1.3.22.101 - Intel® Ethernet 800 Series firmware version — 1.5.4.2 (or later) - Intel® Ethernet 800 Series NVM version — 2.4 (or later) - DPDK version— 21.02 (or later) - For FlexRAN release oran_f_release_v1.0, corresponding support of CVL 2.4 driver pack and DPDK 21.02 is “experimental” and subject to additional testing and potential changes. DDP Package Setup ================= The Intel® Ethernet 800 Series Comms DDP package supports only Linux-based operating systems currently. Currently, the eCPRI is fully supported only by DPDK 21.02. It can be loaded either by DPDK or the Intel® Ethernet 800 Series Linux base driver. Wireless Edge DDP Package ========================= For details on how to set up DPDK, refer to Intel® Ethernet Controller E810 Data Plane Development Kit (DPDK) Configuration Guide (Doc ID: 633514). There are two methods where DDP package can be loaded and used under DPDK (see Section C.3.2 and Section C.3.2 ). For both methods, the user must obtain the ice_wireless_edge-1.3.22.101.pkg or later from Intel (please contact your Intel representative for more information) Option 1: *ice* Linux Base Driver ================================= The first option is to have the ice Linux base driver load the package. The *ice* Linux base driver looks for the symbolic link *intel/ice/ddp/ice.pkg* under the default firmware search path, checking the following folders in order: - */lib/firmware/updates/* - */lib/firmware/* To install the Comms package, copy the extracted .pkg file and its symbolic link to */lib/firmware/updates/intel/ice/ddp* as follows, and reload the ice driver:: # cp /usr/tmp/ice_wireless_edge-1.3.22.101.pkg /lib/firmware/updates/intel/ice/ddp/ # ln -sf /lib/firmware/updates/intel/ice/ddp/ice_wireless_edge-1.3.22.101.pkg /lib/firmware/updates/intel/ice/ddp/ice.pkg # modprobe -r irdma # modprobe -r ice # modprobe ice The kernel message log (*dmesg*) indicates status of package loading in the system. If the driver successfully finds and loads the DDP package, *dmesg* indicates that the DDP package successfully loaded. If not, the driver transitions to safe mode. Once the driver loads the package, the user can unbind the *ice* driver from a desired port on the device so that DPDK can utilize the port. The following example unbinds Port 0 and Port 1 of device on Bus 6, Device 0. Then, the port is bound to either igb_uio or vfio-pci. :: # ifdown # dpdk-devbind -u 06:00.0 # dpdk-devbind -u 06:00.1 # dpdk-devbind -b igb_uio 06:00.0 06:00.1 Option 2: DPDK Driver Only ========================== The second method is if the system does not have the *ice* driver installed. In this case, the user can download the DDP package from the Intel download center and extract the zip file to obtain the package (*.pkg*) file. Similar to the Linux base driver, the DPDK driver looks for the *intel/ddp/ice.pkg* symbolic link in the kernel default firmware search path */lib/firmware/updates and /lib/firmware/*. Copy the extracted DDP *.pkg* file and its symbolic link to */lib/firmware/intel/ice/ddp*, as follows. :: # cp /usr/tmp/ice_wireless_edge-1.3.22.101 /lib/firmware/intel/ice/ddp/ # cp /usr/tmp/ice.pkg /lib/firmware/intel/ice/ddp/ When DPDK driver loads, it looks for *ice.pkg* to load. If the file exists, the driver downloads it into the device. If not, the driver transitions into safe mode. Loading DDP Package to a Specific Intel® Ethernet 800 Series Device =================================================================== On a host system running with multiple Intel® Ethernet 800 Series devices, there is sometimes a need to load a specific DDP package on a selected device while loading a different package on the remaining devices. The Intel® Ethernet 800 Series Linux base driver and DPDK driver can both load a specific DDP package to a selected adapter based on the device's serial number. The driver does this by looking for a specific symbolic link package filename containing the selected device's serial number. The following example illustrates how a user can load a specific package (e.g., *ice_wireless_edge-1.3.22.101*) on the device of Bus 6. 1. Find device serial number. .. To view bus, device, and function of all Intel® Ethernet 800 Series Network Adapters in the system::: # lspci | grep -i Ethernet | grep -i Intel 06:00.0 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 01) 06:00.1 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 01) 82:00.0 Ethernet controller: Intel Corporation Ethernet Controller E810-C for SFP (rev 01) 82:00.1 Ethernet controller: Intel Corporation Ethernet Controller E810-C for SFP (rev 01) 82:00.2 Ethernet controller: Intel Corporation Ethernet Controller E810-C for SFP (rev 01) 82:00.3 Ethernet controller: Intel Corporation Ethernet Controller E810-C for SFP (rev 01) Use the **lspci** command to obtain the selected device serial number:: # lspci -vv -s 06:00.0 \| grep -i Serial Capabilities: [150 v1] Device Serial Number 35-11-a0-ff-ff-ca-05-68 Or, fully parsed without punctuation:: # lspci -vv -s 06:00.0 \|grep Serial \|awk '{print $7}'|sed s/-//g 3511a0ffffca0568 2. Rename the package file with the device serial number in the name. .. Copy the specific package over to /lib/firmware/updates/intel/ice/ddp (or /lib/firmware/intel/ice/ ddp) and create a symbolic link with the serial number linking to the package, as shown. The specific symbolic link filename starts with “ice-” followed by the device serial in lower case without dash ('-'). :: # ln -s /lib/firmware/updates/intel/ice/ddp/ice_wireless_edge-1.3.22.101.pkg /lib/firmware/updates/intel/ice/ddp/ice-3511a0ffffca0568.pkg 3. If using Linux kernel driver (*ice*), reload the base driver (not required if using only DPDK driver). :: # rmmod ice # modprobe ice The driver loads the specific package to the selected device and the OS-default package to the remaining Intel® Ethernet 800 Series devices in the system. 4. Verify. For kernel driver: ================== Example of output of successful load of Wireless Edge Package to all devices:: # dmesg | grep -i "ddp \| safe" [606960.921404] ice 0000:18:00.0: The DDP package was successfully loaded: ICE Wireless Edge Package version 1.3.22.101 [606961.672999] ice 0000:18:00.1: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606962.439067] ice 0000:18:00.2: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606963.198305] ice 0000:18:00.3: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606964.252076] ice 0000:51:00.0: The DDP package was successfully loaded: ICE Wireless Edge Package version 1.3.22.101 [606965.017082] ice 0000:51:00.1: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606965.802115] ice 0000:51:00.2: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606966.576517] ice 0000:51:00.3: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606960.921404] ice 0000:18:00.0: The DDP package was successfully loaded: ICE Wireless Edge Package version 1.3.22.101 [606961.672999] ice 0000:18:00.1: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606962.439067] ice 0000:18:00.2: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606963.198305] ice 0000:18:00.3: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606964.252076] ice 0000:51:00.0: The DDP package was successfully loaded: ICE Wireless Edge Package version 1.3.22.101 [606965.017082] ice 0000:51:00.1: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606965.802115] ice 0000:51:00.2: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 [606966.576517] ice 0000:51:00.3: DDP package already present on device: ICE Wireless Edge Package version 1.3.22.101 If using only DPDK driver: ========================== Verify using DPDK's **testpmd** application to indicate the status and version of the loaded DDP package. Example of eCPRI config with dpdk-testpmd ----------------------------------------- 16 O-RAN eCPRI IQ streams mapped to 16 independent HW queues each.:: #./dpdk-testpmd -l 22-25 -n 4 -a 0000:af:01.0 -- -i --rxq=16 --txq=16 --cmdline-file=/home/flexran_xran/ddp.txt cat /home/flexran_xran/ddp.txt port stop 0 port config mtu 0 9600 port config 0 rx_offload vlan_strip on port start 0 flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0000 / end actions queue index 0 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0001 / end actions queue index 1 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0002 / end actions queue index 2 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0003 / end actions queue index 3 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0004 / end actions queue index 4 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0005 / end actions queue index 5 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0006 / end actions queue index 6 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0007 / end actions queue index 7 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0008 / end actions queue index 8 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x0009 / end actions queue index 9 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x000a / end actions queue index 10 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x000b / end actions queue index 11 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x000c / end actions queue index 12 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x000d / end actions queue index 13 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x000e / end actions queue index 14 / mark / end flow create 0 ingress pattern eth / ecpri common type iq_data pc_id is 0x000f / end actions queue index 15 / mark / end set fwd rxonly start show fwd stats all O-RAN Front haul eCPRI ====================== Intel® Ethernet 800 Series DDP capabilities support several functionalities important for the O-RAN FH. - RSS for packet steering based on ecpriMessage - RSS for packet steering based on ecpriRtcid/ecpriPcid - Queue mapping based on ecpriRtcid/ecpriPcid - Queue mapping based on ecpriMessage .. image:: images/O-RAN-FH-VNF.jpg :width: 400 :alt: Figure . O-RAN FH VNF Figure 30. O-RAN FH VNF Table 13. Patterns & Input Sets for Flow Director and RSS (DPDK 21.02) ============================= ======================================== Pattern Input Set ============================= ======================================== ETH / VLAN / eCPRI ecpriMessage \| ecpriRtcid/ecpriPcid ETH / VLAN /IPv4(6)/UDP/eCPRI ecpriMessage \| ecpriRtcid/ecpriPcid (*) ============================= ======================================== *Note:* \* IP/UDP is not used with FlexRAN Limitations =========== DPDK 21.02 allows up to 1024 queues per VF and RSS across up to 64 receive queues. RTE Flow API ============ The DPDK Generic flow API (rte_flow) will be used to the configure the Intel® Ethernet 800 Series to match specific ingress traffic and forward it to specified queues. For further information, please refer to section 11 of the DPDK Programmers guide . The specific ingress traffic is identified by a matching pattern which is composed of one or more Pattern items (represented by struct rte_flow_item). Once a match has been determined one or more associated Actions (represented by struct rte_flow_action) will be performed. A number of flow rules can be combined such that one rule directs traffic to a queue group based on *ecpriMessage/ ecpriRtcid/ecpriPcid* etc. and a second rule distributes matching packets within that queue group using RSS. The following subset of the RTE Flow API functions can be used to validate, create and destroy RTE Flow rules. RTE Flow Rule Validation ======================== A RTE Flow rule is created via a call to the function *rte_flow_validate*. This can be used to check the rule for correctness and whether it would be accepted by the device given sufficient resources.:: int rte_flow_validate(uint16_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], const struct rte_flow_action *actions[] struct rte_flow_error *error); port_id : port identifier of Ethernet device attr : flow rule attributes(ingress/egress) pattern : pattern specification (list terminated by the END pattern item). action : associated actions (list terminated by the END action). error : perform verbose error reporting if not NULL. 0 is returned upon success, negative errno otherwise. RTE Flow Rule Creation ====================== A RTE Flow rule is created via a call to the function *rte_flow_create*.:: struct rte_flow * rte_flow_create(uint16_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], const struct rte_flow_action *actions[] struct rte_flow_error *error); port_id : port identifier of Ethernet device attr : flow rule attributes(ingress/egress) pattern : pattern specification (list terminated by the END pattern item). action : associated actions (list terminated by the END action). error : perform verbose error reporting if not NULL. A valid handle is returned upon success, NULL otherwise. RTE Flow Rule Destruction ========================= A RTE Flow rule is destroyed via a call to the function *rte_flow_destroy*.:: int rte_flow_destroy(uint16_t port_id, struct rte_flow \*flow, struct rte_flow_error \*error); port_id : port identifier of Ethernet device flow : flow rule handle to destroy. error : perform verbose error reporting if not NULL. 0 is returned upon success, negative errno otherwise. RTE Flow Flush ============== All flow rule handles associated with a port can be released using *rte_flow_flush*. They are released as with successive calls to function *rte_flow_destroy*.:: int rte_flow_flush(uint16_t port_id, struct rte_flow_error \*error); port_id : port identifier of Ethernet device error : perform verbose error reporting if not NULL. 0 is returned upon success, negative errno otherwise. RTE Flow Query ============== A RTE Flow rule is queried via a call to the function *rte_flow_query*.:: int rte_flow_query(uint16_t port_id, struct rte_flow *flow, const struct rte_flow_action *action, void *data, struct rte_flow_error *error); port_id : port identifier of Ethernet device flow : flow rule handle to query action : action to query, this must match prototype from flow rule. data : pointer to storage for the associated query data type error : perform verbose error reporting if not NULL. 0 is returned upon success, negative errno otherwise. RTE Flow Rules ============== A flow rule is the combination of attributes with a matching pattern and a list of actions. Each flow rules consists of: - **Attributes (represented by struct rte_flow_attr):** properties of a flow rule such as its direction (ingress or egress) and priority. - **Pattern Items (represented by struct rte_flow_item):** is part of a matching pattern that either matches specific packet data or traffic properties. - **Matching pattern:** traffic properties to look for, a combination of any number of items. - **Actions (represented by struct rte_flow_action):** operations to perform whenever a packet is matched by a pattern. Attributes ========== Flow rule patterns apply to inbound and/or outbound traffic. For the purposes described in later sections the rules apply to ingress only. For further information, please refer to section 11 of the DPDK Programmers guide .:: *struct*\ rte_flow_attr \ *{* *uint32_t*\ group \ *;* *uint32_t*\ priority \ *;* *uint32_t*\ ingress \ *:1;* *uint32_t*\ egress \ *:1;* *uint32_t*\ transfer \ *:1;* *uint32_t*\ reserved \ *:29;* *};* Pattern items ============= For the purposes described in later sections Pattern items are primarily for matching protocol headers and packet data, usually associated with a specification structure. These must be stacked in the same order as the protocol layers to match inside packets, starting from the lowest. Item specification structures are used to match specific values among protocol fields (or item properties). Up to three structures of the same type can be set for a given item: - **spec:** values to match (e.g. a given IPv4 address). - **last:** upper bound for an inclusive range with corresponding fields in spec. - **mask:** bit-mask applied to both spec and last whose purpose is to distinguish the values to take into account and/or partially mask them out (e.g. in order to match an IPv4 address prefix). Table 14. Example RTE FLOW Item Types +-------------+---------------------------------------+-------------------------+ | Item Type\* | Description | Specification Structure | +=============+=======================================+=========================+ | END | End marker for item lists | None | +-------------+---------------------------------------+-------------------------+ | VOID | Used as a placeholder for convenience | None | +-------------+---------------------------------------+-------------------------+ | ETH | Matches an Ethernet header | rte_flow_item_eth | +-------------+---------------------------------------+-------------------------+ | VLAN | Matches an 802.1Q/ad VLAN tag. | rte_flow_item_vlan | +-------------+---------------------------------------+-------------------------+ | IPV4 | Matches an IPv4 header | rte_flow_item_ipv4 | +-------------+---------------------------------------+-------------------------+ | IPV6 | Matches an IPv6 header | rte_flow_item_ipv6 | +-------------+---------------------------------------+-------------------------+ | ICMP | Matches an ICMP header. | rte_flow_item_icmp | +-------------+---------------------------------------+-------------------------+ | UDP | Matches an UDP header. | rte_flow_item_udp | +-------------+---------------------------------------+-------------------------+ | TCP | Matches a TCP header. | rte_flow_item_tcp | +-------------+---------------------------------------+-------------------------+ | SCTP | Matches a SCTP header. | rte_flow_item_sctp | +-------------+---------------------------------------+-------------------------+ | VXLAN | Matches a VXLAN header. | rte_flow_item_vxlan | +-------------+---------------------------------------+-------------------------+ | NVGRE | Matches a NVGRE header. | rte_flow_item_nvgre | +-------------+---------------------------------------+-------------------------+ | ECPRI | Matches ECPRI Header | rte_flow_item_ecpri | +-------------+---------------------------------------+-------------------------+ :: RTE_FLOW_ITEM_TYPE_ETH struct rte_flow_item_eth { struct rte_ether_addr dst; /**< Destination MAC. */ struct rte_ether_addr src; /**< Source MAC. > */ rte_be16_t type; /**< EtherType or TPID.> */ }; struct rte_ether_addr { uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order */ } :: RTE_FLOW_ITEM_TYPE_IPV4 struct rte_flow_item_ipv4 { struct rte_ipv4_hdr hdr; /**< IPv4 header definition. */ }; struct rte_ipv4_hdr { uint8_t version_ihl; /**< version and header length */ uint8_t type_of_service; /**< type of service */ rte_be16_t total_length; /**< length of packet */ rte_be16_t packet_id; /**< packet ID */ rte_be16_t fragment_offset; /**< fragmentation offset */ uint8_t time_to_live; /**< time to live */ uint8_t next_proto_id; /**< protocol ID */ rte_be16_t hdr_checksum; /**< header checksum */ rte_be32_t src_addr; /**< source address */ rte_be32_t dst_addr; /**< destination address */ } RTE_FLOW_ITEM_TYPE_UDP struct rte_flow_item_udp { struct rte_udp_hdr hdr; /**< UDP header definition. */ }; struct rte_udp_hdr { rte_be16_t src_port; /**< UDP source port. */ rte_be16_t dst_port; /**< UDP destination port. */ rte_be16_t dgram_len; /**< UDP datagram length */ rte_be16_t dgram_cksum; /**< UDP datagram checksum */ } RTE_FLOW_ITEM_TYPE_ECPRI struct rte_flow_item_ecpri { struct rte_ecpri_combined_msg_hdr hdr; }; struct rte_ecpri_combined_msg_hdr { struct rte_ecpri_common_hdr common; union { struct rte_ecpri_msg_iq_data type0; struct rte_ecpri_msg_bit_seq type1; struct rte_ecpri_msg_rtc_ctrl type2; struct rte_ecpri_msg_bit_seq type3; struct rte_ecpri_msg_rm_access type4; struct rte_ecpri_msg_delay_measure type5; struct rte_ecpri_msg_remote_reset type6; struct rte_ecpri_msg_event_ind type7; rte_be32_t dummy[3]; }; }; struct rte_ecpri_common_hdr { union { rte_be32_t u32; /**< 4B common header in BE */ struct { #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN uint32_t size:16; /**< Payload Size */ uint32_t type:8; /**< Message Type */ uint32_t c:1; /**< Concatenation Indicator */ uint32_t res:3; /**< Reserved */ uint32_t revision:4; /**< Protocol Revision */ #elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN uint32_t revision:4; /**< Protocol Revision */ uint32_t res:3; /**< Reserved */ uint32_t c:1; /**< Concatenation Indicator */ uint32_t type:8; /**< Message Type */ uint32_t size:16; /**< Payload Size */ #endif }; }; }; /** * eCPRI Message Header of Type #0: IQ Data */ struct rte_ecpri_msg_iq_data { rte_be16_t pc_id; /**< Physical channel ID */ rte_be16_t seq_id; /**< Sequence ID */ }; /** * eCPRI Message Header of Type #1: Bit Sequence */ struct rte_ecpri_msg_bit_seq { rte_be16_t pc_id; /**< Physical channel ID */ rte_be16_t seq_id; /**< Sequence ID */ }; /** * eCPRI Message Header of Type #2: Real-Time Control Data */ struct rte_ecpri_msg_rtc_ctrl { rte_be16_t rtc_id; /**< Real-Time Control Data ID */ rte_be16_t seq_id; /**< Sequence ID */ }; /** * eCPRI Message Header of Type #3: Generic Data Transfer */ struct rte_ecpri_msg_gen_data { rte_be32_t pc_id; /**< Physical channel ID */ rte_be32_t seq_id; /**< Sequence ID */ }; /** * eCPRI Message Header of Type #4: Remote Memory Access */ RTE_STD_C11 struct rte_ecpri_msg_rm_access { #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN uint32_t ele_id:16; /**< Element ID */ uint32_t rr:4; /**< Req/Resp */ uint32_t rw:4; /**< Read/Write */ uint32_t rma_id:8; /**< Remote Memory Access ID */ #elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN uint32_t rma_id:8; /**< Remote Memory Access ID */ uint32_t rw:4; /**< Read/Write */ uint32_t rr:4; /**< Req/Resp */ uint32_t ele_id:16; /**< Element ID */ #endif uint8_t addr[6]; /**< 48-bits address */ rte_be16_t length; /**< number of bytes */ }; /** * eCPRI Message Header of Type #5: One-Way Delay Measurement */ struct rte_ecpri_msg_delay_measure { uint8_t msr_id; /**< Measurement ID */ uint8_t act_type; /**< Action Type */ }; /** * eCPRI Message Header of Type #6: Remote Reset */ struct rte_ecpri_msg_remote_reset { rte_be16_t rst_id; /**< Reset ID */ uint8_t rst_op; /**< Reset Code Op */ }; /** * eCPRI Message Header of Type #7: Event Indication */ struct rte_ecpri_msg_event_ind { uint8_t evt_id; /**< Event ID */ uint8_t evt_type; /**< Event Type */ uint8_t seq; /**< Sequence Number */ uint8_t number; /**< Number of Faults/Notif */ }; Matching Patterns ================= A matching pattern is formed by stacking items starting from the lowest protocol layer to match. Patterns are terminated by END pattern item. Actions ------- Each possible action is represented by a type. An action can have an associated configuration object. Actions are terminated by the END action. Table 15. RTE FLOW Actions +----------+----------------------------+-------------------------+ | Action\* | Description | Configuration Structure | +==========+============================+=========================+ | END || End marker for action | none | | || lists | | +----------+----------------------------+-------------------------+ | VOID || Used as a placeholder for | none | | || convenience | | +----------+----------------------------+-------------------------+ | PASSTHRU || Leaves traffic up for | none | | || additional processing by | | | || subsequent flow rules; | | | || makes a flow rule | | | || non-terminating. | | +----------+----------------------------+-------------------------+ | MARK || Attaches an integer value | rte_flow_action_mark | | || to packets and sets | | | || PKT_RX_FDIR and | | | || PKT_RX_FDIR_ID mbuf flags | | +----------+----------------------------+-------------------------+ | QUEUE || Assigns packets to a given| rte_flow_action_queue | | || queue index | | +----------+----------------------------+-------------------------+ | DROP || Drops packets | none | +----------+----------------------------+-------------------------+ | COUNT || Enables Counters for this | rte_flow_action_count | | || flow rule | | +----------+----------------------------+-------------------------+ | RSS || Similar to QUEUE, except | rte_flow_action_rss | | || RSS is additionally | | | || performed on packets to | | | || spread them among several | | | || queues according to the | | | || provided parameters. | | +----------+----------------------------+-------------------------+ | VF || Directs matching traffic | rte_flow_action_vf | | || to a given virtual | | | || function of the current | | | || device | | +----------+----------------------------+-------------------------+ Route to specific Queue id based on ecpriRtcid/ecpriPcid ======================================================== An RTE Flow Rule will be created to match an eCPRI packet with a specific pc_id value and route it to specified queues. .. _pattern-items-1: Pattern Items ------------- Table 16. Pattern Items to match eCPRI packet with a Specific Physical Channel ID (pc_id) +-------+----------+-----------------------+-----------------------+ | Index | Item | Spec | Mask | +=======+==========+=======================+=======================+ | 0 | Ethernet | 0 | 0 | +-------+----------+-----------------------+-----------------------+ | 1 | eCPRI || hdr.common.type = || hdr.common.type = | | | || RTE_EC || 0xff; | | | || PRI_MSG_TYPE_IQ_DATA;| | | | | || hdr.type0.pc_id = | | | || hdr.type0.pc_id = || 0xffff; | | | || pc_id; | | +-------+----------+-----------------------+-----------------------+ | 2 | END | 0 | 0 | +-------+----------+-----------------------+-----------------------+ The following code sets up the *RTE_FLOW_ITEM_TYPE_ETH* and *RTE_FLOW_ITEM_TYPE_ECPRI* Pattern Items. The *RTE_FLOW_ITEM_TYPE_ECPRI* Pattern is configured to match on the pc_id value (in this case 8 converted to Big Endian byte order). +--------------------------------------------------------------------------+ | uint8_t pc_id_be = 0x0800; | | | | #define MAX_PATTERN_NUM 3 | | | | struct rte_flow_item pattern[MAX_PATTERN_NUM]; | | | | struct rte_flow_action action[MAX_ACTION_NUM]; | | | | struct rte_flow_item_ecpri ecpri_spec; | | | | struct rte_flow_item_ecpri ecpri_mask; | | | | /\* Ethernet \*/ | | | | patterns[0].type = RTE_FLOW_ITEM_TYPE_ETH; | | | | patterns[0].spec = 0; | | | | patterns[0].mask = 0; | | | | /\* ECPRI \*/ | | | | ecpri_spec.hdr.common.type = RTE_ECPRI_MSG_TYPE_IQ_DATA; | | | | ecpri_spec.hdr.type0.pc_id = pc_id_be; | | | | ecpri_mask.hdr.common.type = 0xff; | | | | ecpri_mask.hdr.type0.pc_id = 0xffff; | | | | ecpri_spec.hdr.common.u32 = rte_cpu_to_be_32(ecpri_spec.hdr.common.u32); | | | | pattern[1].type = RTE_FLOW_ITEM_TYPE_ECPRI; | | | | pattern[1].spec = &ecpri_spec; | | | | pattern[1].mask = &ecpri_mask; | | | | /\* END the pattern array \*/ | | | | patterns[2].type = RTE_FLOW_ITEM_TYPE_END | +--------------------------------------------------------------------------+ Action ------ Table 17. QUEUE action for given queue id ===== ====== ====== ==================== ==================== Index Action Fields Description Value ===== ====== ====== ==================== ==================== 0 QUEUE index queue indices to use Must be 0,1,2,3, etc 1 END ===== ====== ====== ==================== ==================== The following code sets up the action *RTE_FLOW_ACTION_TYPE_QUEUE* and calls the *rte_flow_create* function to create the RTE Flow rule. +----------------------------------------------------------------------+ | *#define MAX_ACTION_NUM 2* | | | | *uint16_t rx_q = 4;* | | | | *struct rte_flow_action_queue queue = { .index = rx_q };* | | | | *struct rte_flow \*handle;* | | | | *struct rte_flow_error err;* | | | | *struct rte_flow_action actions[MAX_ACTION_NUM];* | | | | *struct rte_flow_attr attributes = {.ingress = 1 };* | | | | *action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;* | | | | *action[0].conf = &queue;* | | | | *action[1].type = RTE_FLOW_ACTION_TYPE_END;* | | | | *handle = rte_flow_create (port_id, &attributes, patterns, actions, | | &err);* | +----------------------------------------------------------------------+