root/drivers/net/ethernet/intel/ice/ice_parser.h
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2024 Intel Corporation */

#ifndef _ICE_PARSER_H_
#define _ICE_PARSER_H_

#define ICE_SEC_DATA_OFFSET                             4
#define ICE_SID_RXPARSER_IMEM_ENTRY_SIZE                48
#define ICE_SID_RXPARSER_METADATA_INIT_ENTRY_SIZE       24
#define ICE_SID_RXPARSER_CAM_ENTRY_SIZE                 16
#define ICE_SID_RXPARSER_PG_SPILL_ENTRY_SIZE            17
#define ICE_SID_RXPARSER_NOMATCH_CAM_ENTRY_SIZE         12
#define ICE_SID_RXPARSER_NOMATCH_SPILL_ENTRY_SIZE       13
#define ICE_SID_RXPARSER_BOOST_TCAM_ENTRY_SIZE          88
#define ICE_SID_RXPARSER_MARKER_TYPE_ENTRY_SIZE         24
#define ICE_SID_RXPARSER_MARKER_GRP_ENTRY_SIZE          8
#define ICE_SID_RXPARSER_PROTO_GRP_ENTRY_SIZE           24
#define ICE_SID_RXPARSER_FLAG_REDIR_ENTRY_SIZE          1

#define ICE_SEC_LBL_DATA_OFFSET                         2
#define ICE_SID_LBL_ENTRY_SIZE                          66

/*** ICE_SID_RXPARSER_IMEM section ***/
#define ICE_IMEM_TABLE_SIZE             192

/* TCAM boost Master; if bit is set, and TCAM hit, TCAM output overrides iMEM
 * output.
 */
struct ice_bst_main {
        bool alu0;
        bool alu1;
        bool alu2;
        bool pg;
};

struct ice_bst_keybuilder {
        u8 prio;        /* 0-3: PG precedence within ALUs (3 highest) */
        bool tsr_ctrl;  /* TCAM Search Register control */
};

/* Next protocol Key builder */
struct ice_np_keybuilder {
        u8 opc;
        u8 start_reg0;
        u8 len_reg1;
};

enum ice_np_keybuilder_opcode {
        ICE_NPKB_OPC_EXTRACT    = 0,
        ICE_NPKB_OPC_BUILD      = 1,
        ICE_NPKB_OPC_BYPASS     = 2,
};

/* Parse Graph Key builder */
struct ice_pg_keybuilder {
        bool flag0_ena;
        bool flag1_ena;
        bool flag2_ena;
        bool flag3_ena;
        u8 flag0_idx;
        u8 flag1_idx;
        u8 flag2_idx;
        u8 flag3_idx;
        u8 alu_reg_idx;
};

enum ice_alu_idx {
        ICE_ALU0_IDX    = 0,
        ICE_ALU1_IDX    = 1,
        ICE_ALU2_IDX    = 2,
};

enum ice_alu_opcode {
        ICE_ALU_PARK    = 0,
        ICE_ALU_MOV_ADD = 1,
        ICE_ALU_ADD     = 2,
        ICE_ALU_MOV_AND = 4,
        ICE_ALU_AND     = 5,
        ICE_ALU_AND_IMM = 6,
        ICE_ALU_MOV_OR  = 7,
        ICE_ALU_OR      = 8,
        ICE_ALU_MOV_XOR = 9,
        ICE_ALU_XOR     = 10,
        ICE_ALU_NOP     = 11,
        ICE_ALU_BR      = 12,
        ICE_ALU_BREQ    = 13,
        ICE_ALU_BRNEQ   = 14,
        ICE_ALU_BRGT    = 15,
        ICE_ALU_BRLT    = 16,
        ICE_ALU_BRGEQ   = 17,
        ICE_ALU_BRLEG   = 18,
        ICE_ALU_SETEQ   = 19,
        ICE_ALU_ANDEQ   = 20,
        ICE_ALU_OREQ    = 21,
        ICE_ALU_SETNEQ  = 22,
        ICE_ALU_ANDNEQ  = 23,
        ICE_ALU_ORNEQ   = 24,
        ICE_ALU_SETGT   = 25,
        ICE_ALU_ANDGT   = 26,
        ICE_ALU_ORGT    = 27,
        ICE_ALU_SETLT   = 28,
        ICE_ALU_ANDLT   = 29,
        ICE_ALU_ORLT    = 30,
        ICE_ALU_MOV_SUB = 31,
        ICE_ALU_SUB     = 32,
        ICE_ALU_INVALID = 64,
};

enum ice_proto_off_opcode {
        ICE_PO_OFF_REMAIN       = 0,
        ICE_PO_OFF_HDR_ADD      = 1,
        ICE_PO_OFF_HDR_SUB      = 2,
};

struct ice_alu {
        enum ice_alu_opcode opc;
        u8 src_start;
        u8 src_len;
        bool shift_xlate_sel;
        u8 shift_xlate_key;
        u8 src_reg_id;
        u8 dst_reg_id;
        bool inc0;
        bool inc1;
        u8 proto_offset_opc;
        u8 proto_offset;
        u8 branch_addr;
        u16 imm;
        bool dedicate_flags_ena;
        u8 dst_start;
        u8 dst_len;
        bool flags_extr_imm;
        u8 flags_start_imm;
};

/* Parser program code (iMEM) */
struct ice_imem_item {
        u16 idx;
        struct ice_bst_main b_m;
        struct ice_bst_keybuilder b_kb;
        u8 pg_prio;
        struct ice_np_keybuilder np_kb;
        struct ice_pg_keybuilder pg_kb;
        struct ice_alu alu0;
        struct ice_alu alu1;
        struct ice_alu alu2;
};

/*** ICE_SID_RXPARSER_METADATA_INIT section ***/
#define ICE_METAINIT_TABLE_SIZE         16

/* Metadata Initialization item  */
struct ice_metainit_item {
        u16 idx;

        u8 tsr;         /* TCAM Search key Register */
        u16 ho;         /* Header Offset register */
        u16 pc;         /* Program Counter register */
        u16 pg_rn;      /* Parse Graph Root Node */
        u8 cd;          /* Control Domain ID */

        /* General Purpose Registers */
        bool gpr_a_ctrl;
        u8 gpr_a_data_mdid;
        u8 gpr_a_data_start;
        u8 gpr_a_data_len;
        u8 gpr_a_id;

        bool gpr_b_ctrl;
        u8 gpr_b_data_mdid;
        u8 gpr_b_data_start;
        u8 gpr_b_data_len;
        u8 gpr_b_id;

        bool gpr_c_ctrl;
        u8 gpr_c_data_mdid;
        u8 gpr_c_data_start;
        u8 gpr_c_data_len;
        u8 gpr_c_id;

        bool gpr_d_ctrl;
        u8 gpr_d_data_mdid;
        u8 gpr_d_data_start;
        u8 gpr_d_data_len;
        u8 gpr_d_id;

        u64 flags; /* Initial value for all flags */
};

/*** ICE_SID_RXPARSER_CAM, ICE_SID_RXPARSER_PG_SPILL,
 *    ICE_SID_RXPARSER_NOMATCH_CAM and ICE_SID_RXPARSER_NOMATCH_CAM
 *    sections ***/
#define ICE_PG_CAM_TABLE_SIZE           2048
#define ICE_PG_SP_CAM_TABLE_SIZE        128
#define ICE_PG_NM_CAM_TABLE_SIZE        1024
#define ICE_PG_NM_SP_CAM_TABLE_SIZE     64

struct ice_pg_cam_key {
        bool valid;
        struct_group_attr(val, __packed,
                u16 node_id;    /* Node ID of protocol in parse graph */
                bool flag0;
                bool flag1;
                bool flag2;
                bool flag3;
                u8 boost_idx;   /* Boost TCAM match index */
                u16 alu_reg;
                u32 next_proto; /* next Protocol value (must be last) */
        );
};

struct ice_pg_nm_cam_key {
        bool valid;
        struct_group_attr(val, __packed,
                u16 node_id;
                bool flag0;
                bool flag1;
                bool flag2;
                bool flag3;
                u8 boost_idx;
                u16 alu_reg;
        );
};

struct ice_pg_cam_action {
        u16 next_node;  /* Parser Node ID for the next round */
        u8 next_pc;     /* next Program Counter */
        bool is_pg;     /* is protocol group */
        u8 proto_id;    /* protocol ID or proto group ID */
        bool is_mg;     /* is marker group */
        u8 marker_id;   /* marker ID or marker group ID */
        bool is_last_round;
        bool ho_polarity; /* header offset polarity */
        u16 ho_inc;
};

/* Parse Graph item */
struct ice_pg_cam_item {
        u16 idx;
        struct ice_pg_cam_key key;
        struct ice_pg_cam_action action;
};

/* Parse Graph No Match item */
struct ice_pg_nm_cam_item {
        u16 idx;
        struct ice_pg_nm_cam_key key;
        struct ice_pg_cam_action action;
};

struct ice_pg_cam_item *ice_pg_cam_match(struct ice_pg_cam_item *table,
                                         int size, struct ice_pg_cam_key *key);
struct ice_pg_nm_cam_item *
ice_pg_nm_cam_match(struct ice_pg_nm_cam_item *table, int size,
                    struct ice_pg_cam_key *key);

/*** ICE_SID_RXPARSER_BOOST_TCAM and ICE_SID_LBL_RXPARSER_TMEM sections ***/
#define ICE_BST_TCAM_TABLE_SIZE         256
#define ICE_BST_TCAM_KEY_SIZE           20

/* Boost TCAM item */
struct ice_bst_tcam_item {
        u16 addr;
        u8 key[ICE_BST_TCAM_KEY_SIZE];
        u8 key_inv[ICE_BST_TCAM_KEY_SIZE];
        u8 hit_idx_grp;
        u8 pg_prio;
        struct ice_np_keybuilder np_kb;
        struct ice_pg_keybuilder pg_kb;
        struct ice_alu alu0;
        struct ice_alu alu1;
        struct ice_alu alu2;
};

#define ICE_LBL_LEN                     64
#define ICE_LBL_BST_DVM                 "BOOST_MAC_VLAN_DVM"
#define ICE_LBL_BST_SVM                 "BOOST_MAC_VLAN_SVM"
#define ICE_LBL_TNL_VXLAN               "TNL_VXLAN"
#define ICE_LBL_TNL_GENEVE              "TNL_GENEVE"
#define ICE_LBL_TNL_UDP_ECPRI           "TNL_UDP_ECPRI"

enum ice_lbl_type {
        ICE_LBL_BST_TYPE_UNKNOWN,
        ICE_LBL_BST_TYPE_DVM,
        ICE_LBL_BST_TYPE_SVM,
        ICE_LBL_BST_TYPE_VXLAN,
        ICE_LBL_BST_TYPE_GENEVE,
        ICE_LBL_BST_TYPE_UDP_ECPRI,
};

struct ice_lbl_item {
        u16 idx;
        char label[ICE_LBL_LEN];

        /* must be at the end, not part of the DDP section */
        enum ice_lbl_type type;
};

struct ice_bst_tcam_item *
ice_bst_tcam_match(struct ice_bst_tcam_item *tcam_table, u8 *pat);
struct ice_bst_tcam_item *
ice_bst_tcam_search(struct ice_bst_tcam_item *tcam_table,
                    struct ice_lbl_item *lbl_table,
                    enum ice_lbl_type type, u16 *start);

/*** ICE_SID_RXPARSER_MARKER_PTYPE section ***/
#define ICE_PTYPE_MK_TCAM_TABLE_SIZE    1024
#define ICE_PTYPE_MK_TCAM_KEY_SIZE      10

struct ice_ptype_mk_tcam_item {
        u16 address;
        u16 ptype;
        u8 key[ICE_PTYPE_MK_TCAM_KEY_SIZE];
        u8 key_inv[ICE_PTYPE_MK_TCAM_KEY_SIZE];
} __packed;

struct ice_ptype_mk_tcam_item *
ice_ptype_mk_tcam_match(struct ice_ptype_mk_tcam_item *table,
                        u8 *pat, int len);
/*** ICE_SID_RXPARSER_MARKER_GRP section ***/
#define ICE_MK_GRP_TABLE_SIZE           128
#define ICE_MK_COUNT_PER_GRP            8

/*  Marker Group item */
struct ice_mk_grp_item {
        int idx;
        u8 markers[ICE_MK_COUNT_PER_GRP];
};

/*** ICE_SID_RXPARSER_PROTO_GRP section ***/
#define ICE_PROTO_COUNT_PER_GRP         8
#define ICE_PROTO_GRP_TABLE_SIZE        192
#define ICE_PROTO_GRP_ITEM_SIZE         22
struct ice_proto_off {
        bool polarity;  /* true: positive, false: negative */
        u8 proto_id;
        u16 offset;     /* 10 bit protocol offset */
};

/*  Protocol Group item */
struct ice_proto_grp_item {
        u16 idx;
        struct ice_proto_off po[ICE_PROTO_COUNT_PER_GRP];
};

/*** ICE_SID_RXPARSER_FLAG_REDIR section ***/
#define ICE_FLG_RD_TABLE_SIZE   64
#define ICE_FLG_RDT_SIZE        64

/* Flags Redirection item */
struct ice_flg_rd_item {
        u16 idx;
        bool expose;
        u8 intr_flg_id; /* Internal Flag ID */
};

u64 ice_flg_redirect(struct ice_flg_rd_item *table, u64 psr_flg);

/*** ICE_SID_XLT_KEY_BUILDER_SW, ICE_SID_XLT_KEY_BUILDER_ACL,
 * ICE_SID_XLT_KEY_BUILDER_FD and ICE_SID_XLT_KEY_BUILDER_RSS
 * sections ***/
#define ICE_XLT_KB_FLAG0_14_CNT         15
#define ICE_XLT_KB_TBL_CNT              8
#define ICE_XLT_KB_TBL_ENTRY_SIZE       24

struct ice_xlt_kb_entry {
        u8 xlt1_ad_sel;
        u8 xlt2_ad_sel;
        u16 flg0_14_sel[ICE_XLT_KB_FLAG0_14_CNT];
        u8 xlt1_md_sel;
        u8 xlt2_md_sel;
};

/* XLT Key Builder */
struct ice_xlt_kb {
        u8 xlt1_pm;     /* XLT1 Partition Mode */
        u8 xlt2_pm;     /* XLT2 Partition Mode */
        u8 prof_id_pm;  /* Profile ID Partition Mode */
        u64 flag15;

        struct ice_xlt_kb_entry entries[ICE_XLT_KB_TBL_CNT];
};

u16 ice_xlt_kb_flag_get(struct ice_xlt_kb *kb, u64 pkt_flag);

/*** Parser API ***/
#define ICE_GPR_HV_IDX          64
#define ICE_GPR_HV_SIZE         32
#define ICE_GPR_ERR_IDX         84
#define ICE_GPR_FLG_IDX         104
#define ICE_GPR_FLG_SIZE        16

#define ICE_GPR_TSR_IDX         108     /* TSR: TCAM Search Register */
#define ICE_GPR_NN_IDX          109     /* NN: Next Parsing Cycle Node ID */
#define ICE_GPR_HO_IDX          110     /* HO: Next Parsing Cycle hdr Offset */
#define ICE_GPR_NP_IDX          111     /* NP: Next Parsing Cycle */

#define ICE_PARSER_MAX_PKT_LEN  504
#define ICE_PARSER_PKT_REV      32
#define ICE_PARSER_GPR_NUM      128
#define ICE_PARSER_FLG_NUM      64
#define ICE_PARSER_ERR_NUM      16
#define ICE_MARKER_ID_SIZE      9
#define ICE_MARKER_MAX_SIZE     \
                (ICE_MARKER_ID_SIZE * BITS_PER_BYTE - 1)
#define ICE_MARKER_ID_NUM       8
#define ICE_PO_PAIR_SIZE        256

struct ice_gpr_pu {
        /* array of flags to indicate if GRP needs to be updated */
        bool gpr_val_upd[ICE_PARSER_GPR_NUM];
        u16 gpr_val[ICE_PARSER_GPR_NUM];
        u64 flg_msk;
        u64 flg_val;
        u16 err_msk;
        u16 err_val;
};

enum ice_pg_prio {
        ICE_PG_P0       = 0,
        ICE_PG_P1       = 1,
        ICE_PG_P2       = 2,
        ICE_PG_P3       = 3,
};

struct ice_parser_rt {
        struct ice_parser *psr;
        u16 gpr[ICE_PARSER_GPR_NUM];
        u8 pkt_buf[ICE_PARSER_MAX_PKT_LEN + ICE_PARSER_PKT_REV];
        u16 pkt_len;
        u16 po;
        u8 bst_key[ICE_BST_TCAM_KEY_SIZE];
        struct ice_pg_cam_key pg_key;
        u8 pg_prio;
        struct ice_alu *alu0;
        struct ice_alu *alu1;
        struct ice_alu *alu2;
        struct ice_pg_cam_action *action;
        struct ice_gpr_pu pu;
        u8 markers[ICE_MARKER_ID_SIZE];
        bool protocols[ICE_PO_PAIR_SIZE];
        u16 offsets[ICE_PO_PAIR_SIZE];
};

struct ice_parser_proto_off {
        u8 proto_id;    /* hardware protocol ID */
        u16 offset;     /* offset from the start of the protocol header */
};

#define ICE_PARSER_PROTO_OFF_PAIR_SIZE  16
#define ICE_PARSER_FLAG_PSR_SIZE        8
#define ICE_PARSER_FV_SIZE              48
#define ICE_PARSER_FV_MAX               24
#define ICE_BT_TUN_PORT_OFF_H           16
#define ICE_BT_TUN_PORT_OFF_L           15
#define ICE_BT_VM_OFF                   0
#define ICE_UDP_PORT_OFF_H              1
#define ICE_UDP_PORT_OFF_L              0

struct ice_parser_result {
        u16 ptype;      /* 16 bits hardware PTYPE */
        /* array of protocol and header offset pairs */
        struct ice_parser_proto_off po[ICE_PARSER_PROTO_OFF_PAIR_SIZE];
        int po_num;     /* # of protocol-offset pairs must <= 16 */
        u64 flags_psr;  /* parser flags */
        u64 flags_pkt;  /* packet flags */
        u16 flags_sw;   /* key builder flags for SW */
        u16 flags_acl;  /* key builder flags for ACL */
        u16 flags_fd;   /* key builder flags for FD */
        u16 flags_rss;  /* key builder flags for RSS */
};

void ice_parser_rt_reset(struct ice_parser_rt *rt);
void ice_parser_rt_pktbuf_set(struct ice_parser_rt *rt, const u8 *pkt_buf,
                              int pkt_len);
int ice_parser_rt_execute(struct ice_parser_rt *rt,
                          struct ice_parser_result *rslt);

struct ice_parser {
        struct ice_hw *hw; /* pointer to the hardware structure */

        struct ice_imem_item *imem_table;
        struct ice_metainit_item *mi_table;

        struct ice_pg_cam_item *pg_cam_table;
        struct ice_pg_cam_item *pg_sp_cam_table;
        struct ice_pg_nm_cam_item *pg_nm_cam_table;
        struct ice_pg_nm_cam_item *pg_nm_sp_cam_table;

        struct ice_bst_tcam_item *bst_tcam_table;
        struct ice_lbl_item *bst_lbl_table;
        struct ice_ptype_mk_tcam_item *ptype_mk_tcam_table;
        struct ice_mk_grp_item *mk_grp_table;
        struct ice_proto_grp_item *proto_grp_table;
        struct ice_flg_rd_item *flg_rd_table;

        struct ice_xlt_kb *xlt_kb_sw;
        struct ice_xlt_kb *xlt_kb_acl;
        struct ice_xlt_kb *xlt_kb_fd;
        struct ice_xlt_kb *xlt_kb_rss;

        struct ice_parser_rt rt;
};

struct ice_parser *ice_parser_create(struct ice_hw *hw);
void ice_parser_destroy(struct ice_parser *psr);
void ice_parser_dvm_set(struct ice_parser *psr, bool on);
int ice_parser_vxlan_tunnel_set(struct ice_parser *psr, u16 udp_port, bool on);
int ice_parser_geneve_tunnel_set(struct ice_parser *psr, u16 udp_port, bool on);
int ice_parser_ecpri_tunnel_set(struct ice_parser *psr, u16 udp_port, bool on);
int ice_parser_run(struct ice_parser *psr, const u8 *pkt_buf,
                   int pkt_len, struct ice_parser_result *rslt);
void ice_parser_result_dump(struct ice_hw *hw, struct ice_parser_result *rslt);

struct ice_parser_fv {
        u8 proto_id;    /* hardware protocol ID */
        u16 offset;     /* offset from the start of the protocol header */
        u16 spec;       /* pattern to match */
        u16 msk;        /* pattern mask */
};

struct ice_parser_profile {
        /* array of field vectors */
        struct ice_parser_fv fv[ICE_PARSER_FV_SIZE];
        int fv_num;             /* # of field vectors must <= 48 */
        u16 flags;              /* key builder flags */
        u16 flags_msk;          /* key builder flag mask */

        DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX); /* PTYPE bitmap */
};

int ice_parser_profile_init(struct ice_parser_result *rslt,
                            const u8 *pkt_buf, const u8 *msk_buf,
                            int buf_len, enum ice_block blk,
                            struct ice_parser_profile *prof);
void ice_parser_profile_dump(struct ice_hw *hw,
                             struct ice_parser_profile *prof);
#endif /* _ICE_PARSER_H_ */