net/bnxt: support PTP for Thor
authorKalesh AP <kalesh-anakkur.purayil@broadcom.com>
Wed, 2 Oct 2019 01:23:35 +0000 (18:23 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 8 Oct 2019 10:14:30 +0000 (12:14 +0200)
On Thor, direct access to PTP registers (via GRC) is not supported.
Driver must use HWRM to access the timestamp information.

Vectorized Rx/Tx cannot be enabled if RTE_LIBRTE_IEEE1588=y.
Remove the PTP flags handling code from the vector Rx path.

Add support to read tx timestamp value and the time from the
timesync clock.

On Thor, Rx timestamps are provided directly in the Rx completion
records to the driver. Only 32 bits of the timestamp is present in
the completion. Driver needs to read the current 48 bit free running
timer using the HWRM_PORT_TS_QUERY command and combine the upper
16 bits from the HWRM response with the lower 32 bits in the
Rx completion to produce the 48 bit timestamp for the Rx packet.

Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
drivers/net/bnxt/bnxt.h
drivers/net/bnxt/bnxt_ethdev.c
drivers/net/bnxt/bnxt_hwrm.c
drivers/net/bnxt/bnxt_hwrm.h
drivers/net/bnxt/bnxt_rxr.c
drivers/net/bnxt/bnxt_txr.c
drivers/net/bnxt/hsi_struct_def_dpdk.h

index 310b730..818a49f 100644 (file)
@@ -189,6 +189,10 @@ struct rte_flow {
        struct bnxt_vnic_info   *vnic;
 };
 
+#define BNXT_PTP_FLAGS_PATH_TX         0x0
+#define BNXT_PTP_FLAGS_PATH_RX         0x1
+#define BNXT_PTP_FLAGS_CURRENT_TIME    0x2
+
 struct bnxt_ptp_cfg {
 #define BNXT_GRCPF_REG_WINDOW_BASE_OUT  0x400
 #define BNXT_GRCPF_REG_SYNC_TIME        0x480
@@ -234,6 +238,9 @@ struct bnxt_ptp_cfg {
        uint32_t                        rx_mapped_regs[BNXT_PTP_RX_REGS];
        uint32_t                        tx_regs[BNXT_PTP_TX_REGS];
        uint32_t                        tx_mapped_regs[BNXT_PTP_TX_REGS];
+
+       /* On Thor, the Rx timestamp is present in the Rx completion record */
+       uint64_t                        rx_timestamp;
 };
 
 struct bnxt_coal {
@@ -428,6 +435,7 @@ struct bnxt {
 #define BNXT_FLAG_EXT_STATS_SUPPORTED          BIT(22)
 #define BNXT_FLAG_NEW_RM                       BIT(23)
 #define BNXT_FLAG_INIT_DONE                    BIT(24)
+#define BNXT_FLAG_FW_CAP_ONE_STEP_TX_TS                BIT(25)
 #define BNXT_PF(bp)            (!((bp)->flags & BNXT_FLAG_VF))
 #define BNXT_VF(bp)            ((bp)->flags & BNXT_FLAG_VF)
 #define BNXT_NPAR(bp)          ((bp)->port_partition_type)
index 7c3ef93..0083ba6 100644 (file)
@@ -740,6 +740,7 @@ static eth_rx_burst_t
 bnxt_receive_function(__rte_unused struct rte_eth_dev *eth_dev)
 {
 #ifdef RTE_ARCH_X86
+#ifndef RTE_LIBRTE_IEEE1588
        /*
         * Vector mode receive can be enabled only if scatter rx is not
         * in use and rx offloads are limited to VLAN stripping and
@@ -766,6 +767,7 @@ bnxt_receive_function(__rte_unused struct rte_eth_dev *eth_dev)
                    eth_dev->data->port_id,
                    eth_dev->data->scattered_rx,
                    eth_dev->data->dev_conf.rxmode.offloads);
+#endif
 #endif
        return bnxt_recv_pkts;
 }
@@ -774,6 +776,7 @@ static eth_tx_burst_t
 bnxt_transmit_function(__rte_unused struct rte_eth_dev *eth_dev)
 {
 #ifdef RTE_ARCH_X86
+#ifndef RTE_LIBRTE_IEEE1588
        /*
         * Vector mode transmit can be enabled only if not using scatter rx
         * or tx offloads.
@@ -791,6 +794,7 @@ bnxt_transmit_function(__rte_unused struct rte_eth_dev *eth_dev)
                    eth_dev->data->port_id,
                    eth_dev->data->scattered_rx,
                    eth_dev->data->dev_conf.txmode.offloads);
+#endif
 #endif
        return bnxt_xmit_pkts;
 }
@@ -3223,18 +3227,24 @@ bnxt_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
 static int
 bnxt_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
 {
-       uint64_t ns, systime_cycles;
        struct bnxt *bp = dev->data->dev_private;
        struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+       uint64_t ns, systime_cycles = 0;
+       int rc = 0;
 
        if (!ptp)
                return 0;
 
-       systime_cycles = bnxt_cc_read(bp);
+       if (BNXT_CHIP_THOR(bp))
+               rc = bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_CURRENT_TIME,
+                                            &systime_cycles);
+       else
+               systime_cycles = bnxt_cc_read(bp);
+
        ns = rte_timecounter_update(&ptp->tc, systime_cycles);
        *ts = rte_ns_to_timespec(ns);
 
-       return 0;
+       return rc;
 }
 static int
 bnxt_timesync_enable(struct rte_eth_dev *dev)
@@ -3242,6 +3252,7 @@ bnxt_timesync_enable(struct rte_eth_dev *dev)
        struct bnxt *bp = dev->data->dev_private;
        struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
        uint32_t shift = 0;
+       int rc;
 
        if (!ptp)
                return 0;
@@ -3250,8 +3261,9 @@ bnxt_timesync_enable(struct rte_eth_dev *dev)
        ptp->tx_tstamp_en = 1;
        ptp->rxctl = BNXT_PTP_MSG_EVENTS;
 
-       if (!bnxt_hwrm_ptp_cfg(bp))
-               bnxt_map_ptp_regs(bp);
+       rc = bnxt_hwrm_ptp_cfg(bp);
+       if (rc)
+               return rc;
 
        memset(&ptp->tc, 0, sizeof(struct rte_timecounter));
        memset(&ptp->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
@@ -3269,6 +3281,9 @@ bnxt_timesync_enable(struct rte_eth_dev *dev)
        ptp->tx_tstamp_tc.cc_shift = shift;
        ptp->tx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
 
+       if (!BNXT_CHIP_THOR(bp))
+               bnxt_map_ptp_regs(bp);
+
        return 0;
 }
 
@@ -3287,7 +3302,8 @@ bnxt_timesync_disable(struct rte_eth_dev *dev)
 
        bnxt_hwrm_ptp_cfg(bp);
 
-       bnxt_unmap_ptp_regs(bp);
+       if (!BNXT_CHIP_THOR(bp))
+               bnxt_unmap_ptp_regs(bp);
 
        return 0;
 }
@@ -3305,7 +3321,11 @@ bnxt_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
        if (!ptp)
                return 0;
 
-       bnxt_get_rx_ts(bp, &rx_tstamp_cycles);
+       if (BNXT_CHIP_THOR(bp))
+               rx_tstamp_cycles = ptp->rx_timestamp;
+       else
+               bnxt_get_rx_ts(bp, &rx_tstamp_cycles);
+
        ns = rte_timecounter_update(&ptp->rx_tstamp_tc, rx_tstamp_cycles);
        *timestamp = rte_ns_to_timespec(ns);
        return  0;
@@ -3319,15 +3339,21 @@ bnxt_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
        struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
        uint64_t tx_tstamp_cycles = 0;
        uint64_t ns;
+       int rc = 0;
 
        if (!ptp)
                return 0;
 
-       bnxt_get_tx_ts(bp, &tx_tstamp_cycles);
+       if (BNXT_CHIP_THOR(bp))
+               rc = bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_PATH_TX,
+                                            &tx_tstamp_cycles);
+       else
+               rc = bnxt_get_tx_ts(bp, &tx_tstamp_cycles);
+
        ns = rte_timecounter_update(&ptp->tx_tstamp_tc, tx_tstamp_cycles);
        *timestamp = rte_ns_to_timespec(ns);
 
-       return 0;
+       return rc;
 }
 
 static int
@@ -4574,6 +4600,8 @@ bnxt_uninit_resources(struct bnxt *bp, bool reconfig_dev)
                }
        }
 
+       rte_free(bp->ptp_cfg);
+       bp->ptp_cfg = NULL;
        return rc;
 }
 
index 7304cbf..174dc75 100644 (file)
@@ -506,31 +506,37 @@ static int bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
 
        HWRM_CHECK_RESULT();
 
-       if (!(resp->flags & HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_DIRECT_ACCESS))
+       if (!BNXT_CHIP_THOR(bp) &&
+           !(resp->flags & HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_DIRECT_ACCESS))
                return 0;
 
+       if (resp->flags & HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_ONE_STEP_TX_TS)
+               bp->flags |= BNXT_FLAG_FW_CAP_ONE_STEP_TX_TS;
+
        ptp = rte_zmalloc("ptp_cfg", sizeof(*ptp), 0);
        if (!ptp)
                return -ENOMEM;
 
-       ptp->rx_regs[BNXT_PTP_RX_TS_L] =
-               rte_le_to_cpu_32(resp->rx_ts_reg_off_lower);
-       ptp->rx_regs[BNXT_PTP_RX_TS_H] =
-               rte_le_to_cpu_32(resp->rx_ts_reg_off_upper);
-       ptp->rx_regs[BNXT_PTP_RX_SEQ] =
-               rte_le_to_cpu_32(resp->rx_ts_reg_off_seq_id);
-       ptp->rx_regs[BNXT_PTP_RX_FIFO] =
-               rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo);
-       ptp->rx_regs[BNXT_PTP_RX_FIFO_ADV] =
-               rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo_adv);
-       ptp->tx_regs[BNXT_PTP_TX_TS_L] =
-               rte_le_to_cpu_32(resp->tx_ts_reg_off_lower);
-       ptp->tx_regs[BNXT_PTP_TX_TS_H] =
-               rte_le_to_cpu_32(resp->tx_ts_reg_off_upper);
-       ptp->tx_regs[BNXT_PTP_TX_SEQ] =
-               rte_le_to_cpu_32(resp->tx_ts_reg_off_seq_id);
-       ptp->tx_regs[BNXT_PTP_TX_FIFO] =
-               rte_le_to_cpu_32(resp->tx_ts_reg_off_fifo);
+       if (!BNXT_CHIP_THOR(bp)) {
+               ptp->rx_regs[BNXT_PTP_RX_TS_L] =
+                       rte_le_to_cpu_32(resp->rx_ts_reg_off_lower);
+               ptp->rx_regs[BNXT_PTP_RX_TS_H] =
+                       rte_le_to_cpu_32(resp->rx_ts_reg_off_upper);
+               ptp->rx_regs[BNXT_PTP_RX_SEQ] =
+                       rte_le_to_cpu_32(resp->rx_ts_reg_off_seq_id);
+               ptp->rx_regs[BNXT_PTP_RX_FIFO] =
+                       rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo);
+               ptp->rx_regs[BNXT_PTP_RX_FIFO_ADV] =
+                       rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo_adv);
+               ptp->tx_regs[BNXT_PTP_TX_TS_L] =
+                       rte_le_to_cpu_32(resp->tx_ts_reg_off_lower);
+               ptp->tx_regs[BNXT_PTP_TX_TS_H] =
+                       rte_le_to_cpu_32(resp->tx_ts_reg_off_upper);
+               ptp->tx_regs[BNXT_PTP_TX_SEQ] =
+                       rte_le_to_cpu_32(resp->tx_ts_reg_off_seq_id);
+               ptp->tx_regs[BNXT_PTP_TX_FIFO] =
+                       rte_le_to_cpu_32(resp->tx_ts_reg_off_fifo);
+       }
 
        ptp->bp = bp;
        bp->ptp_cfg = ptp;
@@ -4834,3 +4840,45 @@ int bnxt_hwrm_fw_reset(struct bnxt *bp)
 
        return rc;
 }
+
+int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path, uint64_t *timestamp)
+{
+       struct hwrm_port_ts_query_output *resp = bp->hwrm_cmd_resp_addr;
+       struct hwrm_port_ts_query_input req = {0};
+       struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+       uint32_t flags = 0;
+       int rc;
+
+       if (!ptp)
+               return 0;
+
+       HWRM_PREP(req, PORT_TS_QUERY, BNXT_USE_CHIMP_MB);
+
+       switch (path) {
+       case BNXT_PTP_FLAGS_PATH_TX:
+               flags |= HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_TX;
+               break;
+       case BNXT_PTP_FLAGS_PATH_RX:
+               flags |= HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX;
+               break;
+       case BNXT_PTP_FLAGS_CURRENT_TIME:
+               flags |= HWRM_PORT_TS_QUERY_INPUT_FLAGS_CURRENT_TIME;
+               break;
+       }
+
+       req.flags = rte_cpu_to_le_32(flags);
+       req.port_id = rte_cpu_to_le_16(bp->pf.port_id);
+
+       rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
+
+       HWRM_CHECK_RESULT();
+
+       if (timestamp) {
+               *timestamp = rte_le_to_cpu_32(resp->ptp_msg_ts[0]);
+               *timestamp |=
+                       (uint64_t)(rte_le_to_cpu_32(resp->ptp_msg_ts[1])) << 32;
+       }
+       HWRM_UNLOCK();
+
+       return rc;
+}
index db25ad5..0d38695 100644 (file)
@@ -206,4 +206,6 @@ int bnxt_hwrm_set_mac(struct bnxt *bp);
 int bnxt_hwrm_if_change(struct bnxt *bp, bool state);
 int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp);
 int bnxt_hwrm_fw_reset(struct bnxt *bp);
+int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path,
+                           uint64_t *timestamp);
 #endif
index 12313dd..28487fb 100644 (file)
@@ -17,6 +17,9 @@
 #include "bnxt_rxr.h"
 #include "bnxt_rxq.h"
 #include "hsi_struct_def_dpdk.h"
+#ifdef RTE_LIBRTE_IEEE1588
+#include "bnxt_hwrm.h"
+#endif
 
 /*
  * RX Ring handling
@@ -348,6 +351,30 @@ bnxt_parse_pkt_type(struct rx_pkt_cmpl *rxcmp, struct rx_pkt_cmpl_hi *rxcmp1)
        return pkt_type;
 }
 
+#ifdef RTE_LIBRTE_IEEE1588
+static void
+bnxt_get_rx_ts_thor(struct bnxt *bp, uint32_t rx_ts_cmpl)
+{
+       uint64_t systime_cycles = 0;
+
+       if (!BNXT_CHIP_THOR(bp))
+               return;
+
+       /* On Thor, Rx timestamps are provided directly in the
+        * Rx completion records to the driver. Only 32 bits of
+        * the timestamp is present in the completion. Driver needs
+        * to read the current 48 bit free running timer using the
+        * HWRM_PORT_TS_QUERY command and combine the upper 16 bits
+        * from the HWRM response with the lower 32 bits in the
+        * Rx completion to produce the 48 bit timestamp for the Rx packet
+        */
+       bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_CURRENT_TIME,
+                               &systime_cycles);
+       bp->ptp_cfg->rx_timestamp = (systime_cycles & 0xFFFF00000000);
+       bp->ptp_cfg->rx_timestamp |= rx_ts_cmpl;
+}
+#endif
+
 static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
                            struct bnxt_rx_queue *rxq, uint32_t *raw_cons)
 {
@@ -363,6 +390,7 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
        uint8_t agg_buf = 0;
        uint16_t cmp_type;
        uint32_t flags2_f = 0;
+       uint16_t flags_type;
 
        rxcmp = (struct rx_pkt_cmpl *)
            &cpr->cp_desc_ring[cp_cons];
@@ -418,18 +446,22 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
        mbuf->data_len = mbuf->pkt_len;
        mbuf->port = rxq->port_id;
        mbuf->ol_flags = 0;
-       if (rxcmp->flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) {
+
+       flags_type = rte_le_to_cpu_16(rxcmp->flags_type);
+       if (flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) {
                mbuf->hash.rss = rxcmp->rss_hash;
                mbuf->ol_flags |= PKT_RX_RSS_HASH;
        } else {
                mbuf->hash.fdir.id = rxcmp1->cfa_code;
                mbuf->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
        }
-
-       if ((rxcmp->flags_type & rte_cpu_to_le_16(RX_PKT_CMPL_FLAGS_MASK)) ==
-            RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP)
+#ifdef RTE_LIBRTE_IEEE1588
+       if (unlikely((flags_type & RX_PKT_CMPL_FLAGS_MASK) ==
+                    RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP)) {
                mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST;
-
+               bnxt_get_rx_ts_thor(rxq->bp, rxcmp1->reorder);
+       }
+#endif
        if (agg_buf)
                bnxt_rx_pages(rxq, mbuf, &tmp_raw_cons, agg_buf);
 
index 35e7166..172b480 100644 (file)
@@ -155,7 +155,7 @@ static uint16_t bnxt_start_xmit(struct rte_mbuf *tx_pkt,
                                PKT_TX_UDP_CKSUM | PKT_TX_IP_CKSUM |
                                PKT_TX_VLAN_PKT | PKT_TX_OUTER_IP_CKSUM |
                                PKT_TX_TUNNEL_GRE | PKT_TX_TUNNEL_VXLAN |
-                               PKT_TX_TUNNEL_GENEVE))
+                               PKT_TX_TUNNEL_GENEVE | PKT_TX_IEEE1588_TMST))
                long_bd = true;
 
        nr_bds = long_bd + tx_pkt->nb_segs;
@@ -324,6 +324,11 @@ static uint16_t bnxt_start_xmit(struct rte_mbuf *tx_pkt,
                        /* IP CSO */
                        txbd1->lflags |= TX_BD_LONG_LFLAGS_T_IP_CHKSUM;
                        txbd1->mss = 0;
+               } else if ((tx_pkt->ol_flags & PKT_TX_IEEE1588_TMST) ==
+                          PKT_TX_IEEE1588_TMST) {
+                       /* PTP */
+                       txbd1->lflags |= TX_BD_LONG_LFLAGS_STAMP;
+                       txbd1->mss = 0;
                }
        } else {
                txbd->flags_type |= TX_BD_SHORT_TYPE_TX_BD_SHORT;
index bd04fe4..26d12cf 100644 (file)
@@ -33777,4 +33777,90 @@ struct hwrm_fw_reset_output {
        uint8_t valid;
 } __attribute__((packed));
 
+/**********************
+ * hwrm_port_ts_query *
+ ***********************/
+
+
+/* hwrm_port_ts_query_input (size:192b/24B) */
+struct hwrm_port_ts_query_input {
+       /* The HWRM command request type. */
+       uint16_t        req_type;
+       /*
+        * The completion ring to send the completion event on. This should
+        * be the NQ ID returned from the `nq_alloc` HWRM command.
+        */
+       uint16_t        cmpl_ring;
+       /*
+        * The sequence ID is used by the driver for tracking multiple
+        * commands. This ID is treated as opaque data by the firmware and
+        * the value is returned in the `hwrm_resp_hdr` upon completion.
+        */
+       uint16_t        seq_id;
+       /*
+        * The target ID of the command:
+        * * 0x0-0xFFF8 - The function ID
+        * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors
+        * * 0xFFFD - Reserved for user-space HWRM interface
+        * * 0xFFFF - HWRM
+        */
+       uint16_t        target_id;
+       /*
+        * A physical address pointer pointing to a host buffer that the
+        * command's response data will be written. This can be either a host
+        * physical address (HPA) or a guest physical address (GPA) and must
+        * point to a physically contiguous block of memory.
+        */
+       uint64_t        resp_addr;
+       uint32_t        flags;
+       /*
+        * Enumeration denoting the RX, TX type of the resource.
+        * This enumeration is used for resources that are similar for both
+        * TX and RX paths of the chip.
+        */
+       #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH             0x1UL
+       /* tx path */
+       #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_TX          0x0UL
+       /* rx path */
+       #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX          0x1UL
+       #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_LAST        \
+               HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX
+       /*
+        * If set, the response includes the current value of the free
+        * running timer.
+        */
+       #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_CURRENT_TIME     0x2UL
+       /* Port ID of port that is being queried. */
+       uint16_t        port_id;
+       uint8_t         unused_0[2];
+} __attribute__((packed));
+
+/* hwrm_port_ts_query_output (size:192b/24B) */
+struct hwrm_port_ts_query_output {
+       /* The specific error status for the command. */
+       uint16_t        error_code;
+       /* The HWRM command request type. */
+       uint16_t        req_type;
+       /* The sequence ID from the original command. */
+       uint16_t        seq_id;
+       /* The length of the response data in number of bytes. */
+       uint16_t        resp_len;
+       /*
+        * Timestamp value of PTP message captured, or current value of
+        * free running timer.
+        */
+       uint32_t        ptp_msg_ts[2];
+       /* Sequence ID of the PTP message captured. */
+       uint16_t        ptp_msg_seqid;
+       uint8_t         unused_0[5];
+       /*
+        * This field is used in Output records to indicate that the output
+        * is completely written to RAM.  This field should be read as '1'
+        * to indicate that the output has been completely written.
+        * When writing a command completion or response to an internal processor,
+        * the order of writes has to be such that this field is written last.
+        */
+       uint8_t         valid;
+} __attribute__((packed));
+
 #endif /* _HSI_STRUCT_DEF_DPDK_H_ */