diff --git a/LingYaoSNIC/.DS_Store b/LingYaoSNIC/.DS_Store deleted file mode 100644 index 6689871..0000000 Binary files a/LingYaoSNIC/.DS_Store and /dev/null differ diff --git a/LingYaoSNIC/HW/README.md b/LingYaoSNIC/HW/README.md new file mode 100644 index 0000000..a76685a --- /dev/null +++ b/LingYaoSNIC/HW/README.md @@ -0,0 +1 @@ +适配对接中移网络云华为虚拟层版本 \ No newline at end of file diff --git a/LingYaoSNIC/HW/config/p4_info.json b/LingYaoSNIC/HW/config/p4_info.json new file mode 100644 index 0000000..0ff5e11 --- /dev/null +++ b/LingYaoSNIC/HW/config/p4_info.json @@ -0,0 +1,32569 @@ +{ + "pkg_info" : { + }, + "record_info" : { + "key_template_table" : [ + { + "g_key_tmpl_id" : 0, + "template_id" : 0, + "dir" : 0, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 1, + "template_id" : 0, + "dir" : 0, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 2, + "template_id" : 0, + "dir" : 0, + "pipe_no" : 1, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 3, + "template_id" : 0, + "dir" : 0, + "pipe_no" : 1, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 4, + "template_id" : 0, + "dir" : 0, + "pipe_no" : 2, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 5, + "template_id" : 0, + "dir" : 0, + "pipe_no" : 2, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 6, + "template_id" : 1, + "dir" : 0, + "pipe_no" : 0, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 1, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "it_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 505 + }, + { + "udf_en" : 1, + "udf_sel" : 1396 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 4294967295, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 4294967295, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 7, + "template_id" : 1, + "dir" : 0, + "pipe_no" : 1, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 1, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "it_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 505 + }, + { + "udf_en" : 1, + "udf_sel" : 1396 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 4294967295, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 4294967295, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 8, + "template_id" : 1, + "dir" : 0, + "pipe_no" : 2, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 1, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "it_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 9, + "template_id" : 2, + "dir" : 0, + "pipe_no" : 2, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "ot_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 499 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 0, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 10, + "template_id" : 3, + "dir" : 0, + "pipe_no" : 2, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "ot_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 499 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 0, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 11, + "template_id" : 1, + "dir" : 0, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 12, + "template_id" : 2, + "dir" : 0, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 13, + "template_id" : 3, + "dir" : 0, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 14, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 15, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 16, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 1, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 17, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 1, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 18, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 2, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 19, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 2, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 20, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 3, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 21, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 3, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 22, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 4, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 23, + "template_id" : 0, + "dir" : 1, + "pipe_no" : 4, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 24, + "template_id" : 1, + "dir" : 1, + "pipe_no" : 0, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "ot_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 499 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 0, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 25, + "template_id" : 1, + "dir" : 1, + "pipe_no" : 1, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "ot_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 499 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 0, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 26, + "template_id" : 1, + "dir" : 1, + "pipe_no" : 2, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "ot_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 27, + "template_id" : 1, + "dir" : 1, + "pipe_no" : 2, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "ot_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 28, + "template_id" : 1, + "dir" : 1, + "pipe_no" : 3, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 1, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "it_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 505 + }, + { + "udf_en" : 1, + "udf_sel" : 1396 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 4294967295, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 4294967295, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 29, + "template_id" : 1, + "dir" : 1, + "pipe_no" : 4, + "mask_is_set" : 1, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 1, + "key_profile_id_en" : 1, + "meta_data_en" : 1, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 1, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 1, + "l2_smac_en" : 1, + "l2_ovlan_tpid" : 1, + "l2_ovlan_pri" : 1, + "l2_ovlan_de" : 1, + "l2_ovlan_vid" : 1, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 1 + }, + "it_l3" : { + "l3_dip_v4_en" : 1, + "l3_dip_v6_en" : 1, + "l3_sip_v4_en" : 1, + "l3_sip_v6_en" : 1, + "l3_protocol_en" : 1, + "l3_ttl_en" : 0, + "l3_tos_en" : 1, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 1, + "udf_sel" : 505 + }, + { + "udf_en" : 1, + "udf_sel" : 1396 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 0, + "vnic_id" : 16383, + "profile_id" : 2047, + "mac_port_en" : 0, + "metadata" : 65011712, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 4294967295, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_smac" : [255, 255, 255, 255, 255, 255, 0, 0], + "l2_ovlan" : 65535, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 255, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + }, + "tun" : { + "tunnel_type" : 0, + "tunnel_id" : 0, + "tunnel_flags" : 0 + }, + "nsh" : { + "flags" : 0, + "ttl" : 0, + "length" : 0, + "md_type" : 0, + "next_proto" : 0, + "spi" : 0, + "si" : 0 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_smac" : [0, 0, 0, 0, 0, 0, 0, 0], + "l2_ovlan" : 0, + "l2_ivlan" : 0 + }, + "l3" : { + "l3_dip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_sip" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "l3_type" : 0, + "l3_proto" : 0, + "l3_ttl" : 0, + "l3_ipv6_flow" : 0, + "l3_tos" : 0, + "l3_frag_offset" : 0, + "l3_extend_header" : 0, + "is_dipv4" : 0, + "is_sipv4" : 0 + }, + "l4" : { + "l4_sport" : 0, + "l4_dport" : 0, + "l4_flags" : 0, + "is_icmp" : 0 + } + }, + "udf" : [4294967295, 4294967295, 0, 0, 0, 0, 0, 0], + "udf_key_len" : 0, + "udf_key" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "rangecheck_type0" : 0, + "rangecheck_type1" : 0, + "udf0_l16" : 0, + "udf1_l16" : 0 + }, + "key_template_masks" : [33554431, 4261920768, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "g_key_tmpl_id" : 30, + "template_id" : 2, + "dir" : 1, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 31, + "template_id" : 3, + "dir" : 1, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 32, + "template_id" : 4, + "dir" : 1, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + }, + { + "g_key_tmpl_id" : 4294967295, + "template_id" : 1, + "dir" : 1, + "pipe_no" : 0, + "mask_is_set" : 0, + "key_template" : { + "grp_id_en" : 0, + "vnic_id_en" : 0, + "key_profile_id_en" : 1, + "meta_data_en" : 0, + "mac_port_en" : 0, + "ot_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "ot_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "ot_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "ot_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "it_l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "it_l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "it_l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "it_tun" : { + "tun_type_en" : 0, + "tun_vni_en" : 0, + "tun_flags_en" : 0 + }, + "l2" : { + "l2_dmac_en" : 0, + "l2_smac_en" : 0, + "l2_ovlan_tpid" : 0, + "l2_ovlan_pri" : 0, + "l2_ovlan_de" : 0, + "l2_ovlan_vid" : 0, + "l2_ivlan_tpid" : 0, + "l2_ivlan_pri" : 0, + "l2_ivlan_de" : 0, + "l2_ivlan_vid" : 0, + "l3_type_en" : 0 + }, + "l3" : { + "l3_dip_v4_en" : 0, + "l3_dip_v6_en" : 0, + "l3_sip_v4_en" : 0, + "l3_sip_v6_en" : 0, + "l3_protocol_en" : 0, + "l3_ttl_en" : 0, + "l3_tos_en" : 0, + "l3_flow_id_en" : 0, + "l3_fragment_en" : 0, + "l3_ext_head_vld_en" : 0 + }, + "l4" : { + "l4_sport_en" : 0, + "l4_icmp_code_en" : 0, + "l4_icmp_type_en" : 0, + "l4_dport_en" : 0, + "l4_icmp_identifier_en" : 0, + "l4_tcp_flags_en" : 0 + }, + "udf" : [ + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + }, + { + "udf_en" : 0, + "udf_sel" : 0 + } + ], + "range_check_type0" : 0, + "range_check_type1" : 0 + }, + "key_mask" : { + "grp_id" : 255, + "vnic_id" : 65535, + "profile_id" : 65535, + "mac_port_en" : 255, + "metadata" : 4294967295, + "outer_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "inner_tunnel" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + }, + "tun" : { + "tunnel_type" : 4294967295, + "tunnel_id" : 4294967295, + "tunnel_flags" : 4294967295 + }, + "nsh" : { + "flags" : 255, + "ttl" : 255, + "length" : 255, + "md_type" : 255, + "next_proto" : 255, + "spi" : 4294967295, + "si" : 255 + } + }, + "pkt" : { + "l2" : { + "l2_dmac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_smac" : [255, 255, 255, 255, 255, 255, 255, 255], + "l2_ovlan" : 65535, + "l2_ivlan" : 65535 + }, + "l3" : { + "l3_dip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_sip" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "l3_type" : 65535, + "l3_proto" : 255, + "l3_ttl" : 255, + "l3_ipv6_flow" : 4294967295, + "l3_tos" : 255, + "l3_frag_offset" : 255, + "l3_extend_header" : 255, + "is_dipv4" : 1, + "is_sipv4" : 1 + }, + "l4" : { + "l4_sport" : 65535, + "l4_dport" : 65535, + "l4_flags" : 4294967295, + "is_icmp" : 255 + } + }, + "udf" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], + "udf_key_len" : 255, + "udf_key" : [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], + "rangecheck_type0" : 255, + "rangecheck_type1" : 255, + "udf0_l16" : 65535, + "udf1_l16" : 65535 + }, + "key_template_masks" : [4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295] + } + ], + "em_table" : [ + { + "table_name" : "ingress_pre_control.meter_profile_ops", + "p4_table_size" : 256, + "table_id" : 0, + "p4_table_id" : 5, + "total_len" : 1888, + "table_type" : 0, + "key_template_id" : 11, + "dir" : 0, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 4294967295, + "id" : 1073741829, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 0, + "n_actions" : 3, + "keys" : [], + "actions" : [ + { + "act_name" : "add_meter_profile", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 5, + "p4_action_type" : 1074069504, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 276, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_profile_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_profile_entry", + "p_id" : 0, + "p_len" : 260, + "p_offset" : 16, + "endian" : 1 + } + ] + }, + { + "act_name" : "delete_meter_profile", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 5, + "p4_action_type" : 1074069505, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 12, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 1, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_profile_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_meter_profile", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 5, + "p4_action_type" : 1074069506, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 276, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_profile_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_profile_entry", + "p_id" : 0, + "p_len" : 260, + "p_offset" : 16, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "ingress_pre_control.meter_policer_ops", + "p4_table_size" : 256, + "table_id" : 0, + "p4_table_id" : 6, + "total_len" : 1888, + "table_type" : 0, + "key_template_id" : 12, + "dir" : 0, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 4294967295, + "id" : 1073741830, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 0, + "n_actions" : 3, + "keys" : [], + "actions" : [ + { + "act_name" : "add_meter_policer", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 6, + "p4_action_type" : 1074135040, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 40, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_policer_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_policer_entry", + "p_id" : 0, + "p_len" : 24, + "p_offset" : 16, + "endian" : 1 + } + ] + }, + { + "act_name" : "delete_meter_policer", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 6, + "p4_action_type" : 1074135041, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 12, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 1, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_policer_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_meter_policer", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 6, + "p4_action_type" : 1074135042, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 40, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_policer_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_policer_entry", + "p_id" : 0, + "p_len" : 24, + "p_offset" : 16, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "ingress_pre_control.meter_instance_ops", + "p4_table_size" : 4096, + "table_id" : 0, + "p4_table_id" : 7, + "total_len" : 1888, + "table_type" : 0, + "key_template_id" : 13, + "dir" : 0, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 4294967295, + "id" : 1073741831, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 0, + "n_actions" : 3, + "keys" : [], + "actions" : [ + { + "act_name" : "add_meter_instance", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 7, + "p4_action_type" : 1074200576, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 61, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_instance_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_inst_entry", + "p_id" : 0, + "p_len" : 45, + "p_offset" : 16, + "endian" : 1 + } + ] + }, + { + "act_name" : "delete_meter_instance", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 7, + "p4_action_type" : 1074200577, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 12, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 1, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_instance_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_meter_instance", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 7, + "p4_action_type" : 1074200578, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 61, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_instance_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_inst_entry", + "p_id" : 0, + "p_len" : 45, + "p_offset" : 16, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_control.egress_fwd.em_table", + "p4_table_size" : 1048576, + "table_id" : 3, + "p4_table_id" : 11, + "total_len" : 28154, + "table_type" : 0, + "key_template_id" : 27, + "dir" : 1, + "pipe_no" : 2, + "index" : 0, + "group_id" : 0, + "profile_id" : 43, + "id" : 1073741835, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 1, + "n_keys" : 11, + "n_actions" : 16, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.dst_addr", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 148, + "p4_pattern_type" : 1073807616, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.tpid", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 150, + "p4_pattern_type" : 1073807617, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.priority", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 151, + "p4_pattern_type" : 1073807617, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.cfi", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 152, + "p4_pattern_type" : 1073807617, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.vlan_id", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 153, + "p4_pattern_type" : 1073807617, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.type", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 158, + "p4_pattern_type" : 1073807616, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.dst_addr", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 160, + "p4_pattern_type" : 1073808130, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.dst_addr", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 160, + "p4_pattern_type" : 1073808128, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.dst_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 162, + "p4_pattern_type" : 1073808132, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.dst_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 11, + "key_type" : 162, + "p4_pattern_type" : 1073808131, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "dec_ttl", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462720, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 4194304, + "n_sub_acts" : 1, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 342, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 64, 0] + } + ], + "param" : [] + }, + { + "act_name" : "drop", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462721, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 3, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 700, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "ecmp", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462722, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 16, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [28], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "recirc_id", + "p_id" : 0, + "p_len" : 8, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "member_num", + "p_id" : 0, + "p_len" : 8, + "p_offset" : 8, + "endian" : 0 + } + ] + }, + { + "act_name" : "encap_vxlan", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462723, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 482, + "n_sub_acts" : 2, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 482, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 432, + "offset_in_param" : 8, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 638, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "flag", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 1, + "offset_in_param" : 0, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "flag", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "vxlan", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 8, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462724, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 24, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [42, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [12, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 13, + "type" : 0, + "target_offset" : 16, + "target_bits" : 16, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 32, + "target_bits" : 2, + "offset_in_param" : 32, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 15, + "type" : 0, + "target_offset" : 34, + "target_bits" : 3, + "offset_in_param" : 34, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 40, + "target_bits" : 2, + "offset_in_param" : 40, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 17, + "type" : 0, + "target_offset" : 42, + "target_bits" : 1, + "offset_in_param" : 42, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 43, + "target_bits" : 1, + "offset_in_param" : 43, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 19, + "type" : 0, + "target_offset" : 44, + "target_bits" : 2, + "offset_in_param" : 44, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 20, + "type" : 0, + "target_offset" : 48, + "target_bits" : 22, + "offset_in_param" : 48, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 690, + "data" : [], + "s_name" : "nvgre_hdr", + "s_id" : 21, + "type" : 0, + "target_offset" : 72, + "target_bits" : 336, + "offset_in_param" : 72, + "length_in_param" : 696, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "nvgre_hdr.eth", + "s_id" : 22, + "type" : 0, + "target_offset" : 80, + "target_bits" : 112, + "offset_in_param" : 80, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "nvgre_hdr.ipv4", + "s_id" : 23, + "type" : 0, + "target_offset" : 224, + "target_bits" : 160, + "offset_in_param" : 224, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 374, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "nvgre_hdr.nvgre", + "s_id" : 24, + "type" : 0, + "target_offset" : 704, + "target_bits" : 64, + "offset_in_param" : 704, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462725, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 25, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [50, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [13, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 11, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 12, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 13, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 15, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 17, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 18, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan_hdr", + "s_id" : 19, + "type" : 0, + "target_offset" : 96, + "target_bits" : 400, + "offset_in_param" : 96, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "vxlan_hdr.eth", + "s_id" : 20, + "type" : 0, + "target_offset" : 104, + "target_bits" : 112, + "offset_in_param" : 104, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "vxlan_hdr.ipv4", + "s_id" : 21, + "type" : 0, + "target_offset" : 248, + "target_bits" : 160, + "offset_in_param" : 248, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 432, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.udp", + "s_id" : 22, + "type" : 0, + "target_offset" : 728, + "target_bits" : 64, + "offset_in_param" : 728, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 372, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.vxlan", + "s_id" : 23, + "type" : 0, + "target_offset" : 792, + "target_bits" : 64, + "offset_in_param" : 792, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 24, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 26, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462726, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 13, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 4, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 5, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 6, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 7, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 8, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 9, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 10, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 11, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "pop_vlan", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462727, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 1, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 338, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "push_vlan", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462728, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 341, + "n_sub_acts" : 4, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 4, + "data" : [], + "s_name" : "type", + "s_id" : 2, + "type" : 0, + "target_offset" : 19, + "target_bits" : 2, + "offset_in_param" : 0, + "length_in_param" : 4, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "mask", + "s_id" : 3, + "type" : 0, + "target_offset" : 16, + "target_bits" : 3, + "offset_in_param" : 8, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "tpid", + "s_id" : 4, + "type" : 0, + "target_offset" : 21, + "target_bits" : 3, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "value", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 32, + "length_in_param" : 16, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "type", + "p_id" : 0, + "p_len" : 4, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "mask", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "tpid", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "value", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 32, + "endian" : 1 + } + ] + }, + { + "act_name" : "send_port", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462729, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 2, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 310, + "n_sub_acts" : 4, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 308, + "need_param" : 0, + "s_len" : 1, + "data" : [1], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 309, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 72, 0] + }, + { + "s_type" : 310, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "id", + "s_id" : 5, + "type" : 0, + "target_offset" : 6, + "target_bits" : 2, + "offset_in_param" : 0, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_counter", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462730, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 686, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_dmac", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462731, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 349, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 349, + "need_param" : 1, + "s_len" : 48, + "data" : [], + "s_name" : "mac", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 48, + "offset_in_param" : 0, + "length_in_param" : 48, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "set_smac", + "action_id" : 12, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462732, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 350, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 350, + "need_param" : 1, + "s_len" : 48, + "data" : [], + "s_name" : "mac", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 48, + "offset_in_param" : 0, + "length_in_param" : 48, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "send_to_vf", + "action_id" : 13, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462733, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 13, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 310, + "n_sub_acts" : 4, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 308, + "need_param" : 0, + "s_len" : 1, + "data" : [1], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 309, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 0, + "s_len" : 4, + "data" : [64, 18, 64, 0] + }, + { + "s_type" : 310, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "vfid", + "s_id" : 5, + "type" : 0, + "target_offset" : 6, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "vfid", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "tx_upcall", + "action_id" : 14, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462734, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [29], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "snat", + "action_id" : 15, + "table_id" : 0, + "p4_table_id" : 11, + "p4_action_type" : 1074462735, + "rte_flow_type" : 0, + "priority" : 2, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 353, + "need_param" : 1, + "s_len" : 32, + "data" : [], + "s_name" : "src_addr", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 32, + "offset_in_param" : 0, + "length_in_param" : 32, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_control.egress_fwd.ecmp_table", + "p4_table_size" : 128, + "table_id" : 1, + "p4_table_id" : 14, + "total_len" : 12548, + "table_type" : 0, + "key_template_id" : 4294967295, + "dir" : 1, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 49, + "id" : 1073741838, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 2, + "n_actions" : 12, + "keys" : [ + { + "key_name" : "meta.dp_hash", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 14, + "key_type" : 672, + "p4_pattern_type" : 1610612761, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 32, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "meta.recirc_id", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 14, + "key_type" : 673, + "p4_pattern_type" : 1610612762, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 8, + "total_len_in_param" : 8, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "dec_ttl", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659328, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 342, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [52], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "drop", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659329, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 700, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [53], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "encap_vxlan", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659330, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 482, + "n_sub_acts" : 3, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [54], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "flag", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "vxlan", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 8, + "endian" : 1 + } + ] + }, + { + "act_name" : "push_vlan", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659331, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 341, + "n_sub_acts" : 3, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [55], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "type", + "p_id" : 0, + "p_len" : 4, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "mask", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "tpid", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "value", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 32, + "endian" : 1 + } + ] + }, + { + "act_name" : "pop_vlan", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659332, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 338, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [56], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "send_port", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659333, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 2, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [57], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "send_to_vf", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659334, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 13, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [58], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "vfid", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659335, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 3, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [59], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_dmac", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659336, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 349, + "n_sub_acts" : 3, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [60], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "set_smac", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659337, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 350, + "n_sub_acts" : 3, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [61], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "tx_upcall", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659338, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [62], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "snat", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 14, + "p4_action_type" : 1074659339, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 3, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [63], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_pre_control.meter_profile_ops", + "p4_table_size" : 256, + "table_id" : 1, + "p4_table_id" : 15, + "total_len" : 1888, + "table_type" : 0, + "key_template_id" : 30, + "dir" : 1, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 4294967295, + "id" : 1073741839, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 0, + "n_actions" : 3, + "keys" : [], + "actions" : [ + { + "act_name" : "add_meter_profile", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 15, + "p4_action_type" : 1074724864, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 276, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_profile_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_profile_entry", + "p_id" : 0, + "p_len" : 260, + "p_offset" : 16, + "endian" : 1 + } + ] + }, + { + "act_name" : "delete_meter_profile", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 15, + "p4_action_type" : 1074724865, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 12, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 1, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_profile_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_meter_profile", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 15, + "p4_action_type" : 1074724866, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 276, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_profile_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_profile_entry", + "p_id" : 0, + "p_len" : 260, + "p_offset" : 16, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_pre_control.meter_policer_ops", + "p4_table_size" : 256, + "table_id" : 1, + "p4_table_id" : 16, + "total_len" : 1888, + "table_type" : 0, + "key_template_id" : 31, + "dir" : 1, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 4294967295, + "id" : 1073741840, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 0, + "n_actions" : 3, + "keys" : [], + "actions" : [ + { + "act_name" : "add_meter_policer", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 16, + "p4_action_type" : 1074790400, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 40, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_policer_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_policer_entry", + "p_id" : 0, + "p_len" : 24, + "p_offset" : 16, + "endian" : 1 + } + ] + }, + { + "act_name" : "delete_meter_policer", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 16, + "p4_action_type" : 1074790401, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 12, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 1, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_policer_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_meter_policer", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 16, + "p4_action_type" : 1074790402, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 40, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_policer_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_policer_entry", + "p_id" : 0, + "p_len" : 24, + "p_offset" : 16, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_pre_control.meter_instance_ops", + "p4_table_size" : 4096, + "table_id" : 1, + "p4_table_id" : 17, + "total_len" : 1888, + "table_type" : 0, + "key_template_id" : 32, + "dir" : 1, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 4294967295, + "id" : 1073741841, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 0, + "n_actions" : 3, + "keys" : [], + "actions" : [ + { + "act_name" : "add_meter_instance", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 17, + "p4_action_type" : 1074855936, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 61, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_instance_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_inst_entry", + "p_id" : 0, + "p_len" : 45, + "p_offset" : 16, + "endian" : 1 + } + ] + }, + { + "act_name" : "delete_meter_instance", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 17, + "p4_action_type" : 1074855937, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 12, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 1, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_instance_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_meter_instance", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 17, + "p4_action_type" : 1074855938, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 0, + "total_len_in_param" : 61, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 2, + "sub_actions" : [], + "param" : [ + { + "p_name" : "meter_instance_id", + "p_id" : 0, + "p_len" : 12, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "meter_inst_entry", + "p_id" : 0, + "p_len" : 45, + "p_offset" : 16, + "endian" : 1 + } + ] + } + ] + } + ], + "wc_table" : [ + { + "table_name" : "ingress_control.ingress_acl_group1.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 0, + "total_len" : 25521, + "table_type" : 1, + "key_template_id" : 6, + "dir" : 0, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 5, + "id" : 1073741824, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 33, + "n_actions" : 9, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.vni", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 177, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 32, + "length_in_param" : 32, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.dst_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 186, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.src_addr", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 187, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.tpid", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 188, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.priority", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 189, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.cfi", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 190, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.vlan_id", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 191, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.type", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 196, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 197, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 197, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 199, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.src_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 199, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 198, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 198, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.dst_addr", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 200, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.dst_addr", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 200, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.protocol", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 201, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.protocol", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 201, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.next_hdr", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 201, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.next_hdr", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 201, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.diffserv", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 203, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.diffserv", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 203, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.traffic_class", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 204, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.traffic_class", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 204, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.dst_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.dst_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.dst_port", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.src_port", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.src_port", + "key_id" : 30, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.src_port", + "key_id" : 31, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 32, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.reserved0", + "key_id" : 33, + "table_id" : 0, + "p4_table_id" : 0, + "key_type" : 253, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 24, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 24, + "total_len_in_param" : 64, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741824, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 24, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [42, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 13, + "type" : 0, + "target_offset" : 16, + "target_bits" : 16, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 32, + "target_bits" : 2, + "offset_in_param" : 32, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 15, + "type" : 0, + "target_offset" : 34, + "target_bits" : 3, + "offset_in_param" : 34, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 40, + "target_bits" : 2, + "offset_in_param" : 40, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 17, + "type" : 0, + "target_offset" : 42, + "target_bits" : 1, + "offset_in_param" : 42, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 43, + "target_bits" : 1, + "offset_in_param" : 43, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 19, + "type" : 0, + "target_offset" : 44, + "target_bits" : 2, + "offset_in_param" : 44, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 20, + "type" : 0, + "target_offset" : 48, + "target_bits" : 22, + "offset_in_param" : 48, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 690, + "data" : [], + "s_name" : "nvgre_hdr", + "s_id" : 21, + "type" : 0, + "target_offset" : 72, + "target_bits" : 336, + "offset_in_param" : 72, + "length_in_param" : 696, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "nvgre_hdr.eth", + "s_id" : 22, + "type" : 0, + "target_offset" : 80, + "target_bits" : 112, + "offset_in_param" : 80, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "nvgre_hdr.ipv4", + "s_id" : 23, + "type" : 0, + "target_offset" : 224, + "target_bits" : 160, + "offset_in_param" : 224, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 374, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "nvgre_hdr.nvgre", + "s_id" : 24, + "type" : 0, + "target_offset" : 704, + "target_bits" : 64, + "offset_in_param" : 704, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741825, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 25, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [50, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 11, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 12, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 13, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 15, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 17, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 18, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan_hdr", + "s_id" : 19, + "type" : 0, + "target_offset" : 96, + "target_bits" : 400, + "offset_in_param" : 96, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "vxlan_hdr.eth", + "s_id" : 20, + "type" : 0, + "target_offset" : 104, + "target_bits" : 112, + "offset_in_param" : 104, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "vxlan_hdr.ipv4", + "s_id" : 21, + "type" : 0, + "target_offset" : 248, + "target_bits" : 160, + "offset_in_param" : 248, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 432, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.udp", + "s_id" : 22, + "type" : 0, + "target_offset" : 728, + "target_bits" : 64, + "offset_in_param" : 728, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 372, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.vxlan", + "s_id" : 23, + "type" : 0, + "target_offset" : 792, + "target_bits" : 64, + "offset_in_param" : 792, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 24, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 26, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741826, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 13, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 4, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 5, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 6, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 7, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 8, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 9, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 10, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 11, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741827, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "rx_upcall", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741828, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741829, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 686, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741830, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 1, + "s_len" : 5, + "data" : [], + "s_name" : "tag", + "s_id" : 3, + "type" : 0, + "target_offset" : 21, + "target_bits" : 5, + "offset_in_param" : 0, + "length_in_param" : 5, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741831, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 687, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 0, + "p4_action_type" : 1073741832, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 15, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 353, + "need_param" : 1, + "s_len" : 32, + "data" : [], + "s_name" : "src_addr", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 32, + "offset_in_param" : 0, + "length_in_param" : 32, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "ingress_control.ingress_acl_group2.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 1, + "total_len" : 25521, + "table_type" : 1, + "key_template_id" : 7, + "dir" : 0, + "pipe_no" : 1, + "index" : 0, + "group_id" : 0, + "profile_id" : 23, + "id" : 1073741825, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 33, + "n_actions" : 9, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.vni", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 177, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 32, + "length_in_param" : 32, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.dst_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 186, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.src_addr", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 187, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.tpid", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 188, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.priority", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 189, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.cfi", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 190, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.vlan_id", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 191, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.type", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 196, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 197, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 197, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 199, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.src_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 199, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 198, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 198, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.dst_addr", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 200, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.dst_addr", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 200, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.protocol", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 201, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.protocol", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 201, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.next_hdr", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 201, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.next_hdr", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 201, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.diffserv", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 203, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.diffserv", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 203, + "p4_pattern_type" : 1073873664, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.traffic_class", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 204, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.traffic_class", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 204, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.dst_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.dst_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.dst_port", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.src_port", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.src_port", + "key_id" : 30, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.src_port", + "key_id" : 31, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 32, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.reserved0", + "key_id" : 33, + "table_id" : 0, + "p4_table_id" : 1, + "key_type" : 253, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 24, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 24, + "total_len_in_param" : 64, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807360, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 24, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [42, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 13, + "type" : 0, + "target_offset" : 16, + "target_bits" : 16, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 32, + "target_bits" : 2, + "offset_in_param" : 32, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 15, + "type" : 0, + "target_offset" : 34, + "target_bits" : 3, + "offset_in_param" : 34, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 40, + "target_bits" : 2, + "offset_in_param" : 40, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 17, + "type" : 0, + "target_offset" : 42, + "target_bits" : 1, + "offset_in_param" : 42, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 43, + "target_bits" : 1, + "offset_in_param" : 43, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 19, + "type" : 0, + "target_offset" : 44, + "target_bits" : 2, + "offset_in_param" : 44, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 20, + "type" : 0, + "target_offset" : 48, + "target_bits" : 22, + "offset_in_param" : 48, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 690, + "data" : [], + "s_name" : "nvgre_hdr", + "s_id" : 21, + "type" : 0, + "target_offset" : 72, + "target_bits" : 336, + "offset_in_param" : 72, + "length_in_param" : 696, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "nvgre_hdr.eth", + "s_id" : 22, + "type" : 0, + "target_offset" : 80, + "target_bits" : 112, + "offset_in_param" : 80, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "nvgre_hdr.ipv4", + "s_id" : 23, + "type" : 0, + "target_offset" : 224, + "target_bits" : 160, + "offset_in_param" : 224, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 374, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "nvgre_hdr.nvgre", + "s_id" : 24, + "type" : 0, + "target_offset" : 704, + "target_bits" : 64, + "offset_in_param" : 704, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807361, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 25, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [50, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [3, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 11, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 12, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 13, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 15, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 17, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 18, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan_hdr", + "s_id" : 19, + "type" : 0, + "target_offset" : 96, + "target_bits" : 400, + "offset_in_param" : 96, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "vxlan_hdr.eth", + "s_id" : 20, + "type" : 0, + "target_offset" : 104, + "target_bits" : 112, + "offset_in_param" : 104, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "vxlan_hdr.ipv4", + "s_id" : 21, + "type" : 0, + "target_offset" : 248, + "target_bits" : 160, + "offset_in_param" : 248, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 432, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.udp", + "s_id" : 22, + "type" : 0, + "target_offset" : 728, + "target_bits" : 64, + "offset_in_param" : 728, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 372, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.vxlan", + "s_id" : 23, + "type" : 0, + "target_offset" : 792, + "target_bits" : 64, + "offset_in_param" : 792, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 24, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 26, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807362, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 13, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 4, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 5, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 6, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 7, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 8, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 9, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 10, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 11, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807363, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "rx_upcall", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807364, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [9, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [1], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807365, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 686, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807366, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 1, + "s_len" : 5, + "data" : [], + "s_name" : "tag", + "s_id" : 3, + "type" : 0, + "target_offset" : 21, + "target_bits" : 5, + "offset_in_param" : 0, + "length_in_param" : 5, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807367, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 687, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 1, + "p4_action_type" : 1073807368, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 17, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 353, + "need_param" : 1, + "s_len" : 32, + "data" : [], + "s_name" : "src_addr", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 32, + "offset_in_param" : 0, + "length_in_param" : 32, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "ingress_control.ingress_fwd.em_table", + "p4_table_size" : 1048576, + "table_id" : 0, + "p4_table_id" : 2, + "total_len" : 37142, + "table_type" : 1, + "key_template_id" : 8, + "dir" : 0, + "pipe_no" : 2, + "index" : 0, + "group_id" : 0, + "profile_id" : 25, + "id" : 1073741826, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 12, + "n_actions" : 15, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.vni", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 177, + "p4_pattern_type" : 1073808897, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 32, + "length_in_param" : 32, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.dst_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 186, + "p4_pattern_type" : 1073873152, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.tpid", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 188, + "p4_pattern_type" : 1073873153, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.priority", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 189, + "p4_pattern_type" : 1073873153, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.cfi", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 190, + "p4_pattern_type" : 1073873153, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.vlan_id", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 191, + "p4_pattern_type" : 1073873153, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.type", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 196, + "p4_pattern_type" : 1073873152, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.dst_addr", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 198, + "p4_pattern_type" : 1073873666, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4_frag.dst_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 198, + "p4_pattern_type" : 1073873664, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.dst_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 200, + "p4_pattern_type" : 1073873668, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.dst_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 2, + "key_type" : 200, + "p4_pattern_type" : 1073873667, + "match_type" : 1, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "dec_ttl", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872896, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 4194304, + "n_sub_acts" : 5, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 342, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 64, 0] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [6, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "decap_tunnel", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872897, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 1, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 65847, + "n_sub_acts" : 6, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 311, + "need_param" : 0, + "s_len" : 4, + "data" : [6, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 1, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 637, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "flag", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 1, + "offset_in_param" : 0, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "flag", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "drop", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872898, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 3, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 700, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872899, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 28, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [42, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 15, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 16, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 17, + "type" : 0, + "target_offset" : 16, + "target_bits" : 16, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 32, + "target_bits" : 2, + "offset_in_param" : 32, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 19, + "type" : 0, + "target_offset" : 34, + "target_bits" : 3, + "offset_in_param" : 34, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 20, + "type" : 0, + "target_offset" : 40, + "target_bits" : 2, + "offset_in_param" : 40, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 21, + "type" : 0, + "target_offset" : 42, + "target_bits" : 1, + "offset_in_param" : 42, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 22, + "type" : 0, + "target_offset" : 43, + "target_bits" : 1, + "offset_in_param" : 43, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 23, + "type" : 0, + "target_offset" : 44, + "target_bits" : 2, + "offset_in_param" : 44, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 24, + "type" : 0, + "target_offset" : 48, + "target_bits" : 22, + "offset_in_param" : 48, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 690, + "data" : [], + "s_name" : "nvgre_hdr", + "s_id" : 25, + "type" : 0, + "target_offset" : 72, + "target_bits" : 336, + "offset_in_param" : 72, + "length_in_param" : 696, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "nvgre_hdr.eth", + "s_id" : 26, + "type" : 0, + "target_offset" : 80, + "target_bits" : 112, + "offset_in_param" : 80, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "nvgre_hdr.ipv4", + "s_id" : 27, + "type" : 0, + "target_offset" : 224, + "target_bits" : 160, + "offset_in_param" : 224, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 374, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "nvgre_hdr.nvgre", + "s_id" : 28, + "type" : 0, + "target_offset" : 704, + "target_bits" : 64, + "offset_in_param" : 704, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 29, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872900, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 29, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [50, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [5, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 15, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 17, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 19, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 20, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 21, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 22, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan_hdr", + "s_id" : 23, + "type" : 0, + "target_offset" : 96, + "target_bits" : 400, + "offset_in_param" : 96, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "vxlan_hdr.eth", + "s_id" : 24, + "type" : 0, + "target_offset" : 104, + "target_bits" : 112, + "offset_in_param" : 104, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "vxlan_hdr.ipv4", + "s_id" : 25, + "type" : 0, + "target_offset" : 248, + "target_bits" : 160, + "offset_in_param" : 248, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 432, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.udp", + "s_id" : 26, + "type" : 0, + "target_offset" : 728, + "target_bits" : 64, + "offset_in_param" : 728, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 372, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.vxlan", + "s_id" : 27, + "type" : 0, + "target_offset" : 792, + "target_bits" : 64, + "offset_in_param" : 792, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 28, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 29, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 30, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872901, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 17, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 8, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 9, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 10, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 11, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 12, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 13, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 14, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 15, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 16, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 17, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 18, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "pop_vlan", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872902, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 5, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 338, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "push_vlan", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872903, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 341, + "n_sub_acts" : 8, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 4, + "data" : [], + "s_name" : "type", + "s_id" : 6, + "type" : 0, + "target_offset" : 19, + "target_bits" : 2, + "offset_in_param" : 0, + "length_in_param" : 4, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "mask", + "s_id" : 7, + "type" : 0, + "target_offset" : 16, + "target_bits" : 3, + "offset_in_param" : 8, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "tpid", + "s_id" : 8, + "type" : 0, + "target_offset" : 21, + "target_bits" : 3, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "value", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 32, + "length_in_param" : 16, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "type", + "p_id" : 0, + "p_len" : 4, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "mask", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "tpid", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "value", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 32, + "endian" : 1 + } + ] + }, + { + "act_name" : "rx_upcall", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872904, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [2], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "send_to_vf", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872905, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 13, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 310, + "n_sub_acts" : 8, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 308, + "need_param" : 0, + "s_len" : 1, + "data" : [1], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 309, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 0, + "s_len" : 4, + "data" : [64, 18, 64, 0] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "vfid", + "s_id" : 9, + "type" : 0, + "target_offset" : 6, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "vfid", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_counter", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872906, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 5, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 686, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_dmac", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872907, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 349, + "n_sub_acts" : 5, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 349, + "need_param" : 1, + "s_len" : 48, + "data" : [], + "s_name" : "mac", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 48, + "offset_in_param" : 0, + "length_in_param" : 48, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "set_smac", + "action_id" : 12, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872908, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 350, + "n_sub_acts" : 5, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 350, + "need_param" : 1, + "s_len" : 48, + "data" : [], + "s_name" : "mac", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 48, + "offset_in_param" : 0, + "length_in_param" : 48, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "send_port", + "action_id" : 13, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872909, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 2, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 310, + "n_sub_acts" : 8, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 308, + "need_param" : 0, + "s_len" : 1, + "data" : [1], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 309, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 72, 0] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "id", + "s_id" : 9, + "type" : 0, + "target_offset" : 6, + "target_bits" : 2, + "offset_in_param" : 0, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 14, + "table_id" : 0, + "p4_table_id" : 2, + "p4_action_type" : 1073872910, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 5, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 678, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 353, + "need_param" : 1, + "s_len" : 32, + "data" : [], + "s_name" : "src_addr", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 32, + "offset_in_param" : 0, + "length_in_param" : 32, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "ingress_control.ingress_acl_group3.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 3, + "total_len" : 18135, + "table_type" : 1, + "key_template_id" : 9, + "dir" : 0, + "pipe_no" : 3, + "index" : 0, + "group_id" : 0, + "profile_id" : 27, + "id" : 1073741827, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 31, + "n_actions" : 12, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.dst_addr", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 148, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.src_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 149, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.tpid", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 150, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.priority", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 151, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.cfi", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 152, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.vlan_id", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 153, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.type", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 158, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.src_addr", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 159, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 159, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 161, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 161, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.dst_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 160, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 160, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 162, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.dst_addr", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 162, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.protocol", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 163, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.protocol", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 163, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.next_hdr", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 163, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.next_hdr", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 163, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.diffserv", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 165, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.diffserv", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 165, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.traffic_class", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 166, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.traffic_class", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 166, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.src_port", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.src_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.src_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.dst_port", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.dst_port", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.dst_port", + "key_id" : 30, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 31, + "table_id" : 0, + "p4_table_id" : 3, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938432, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [3], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938433, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [4], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938434, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [5], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938435, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "rx_upcall", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938436, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [6], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938437, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [7], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938438, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [8], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938439, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [9], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv4_dscp", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938440, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [10], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv6_dscp", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938441, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [11], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_vxlan_rsv0", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938442, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 11, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [12], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "rsv0", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 3, + "p4_action_type" : 1073938443, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [13], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "ingress_control.ingress_acl_group4.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 4, + "total_len" : 18135, + "table_type" : 1, + "key_template_id" : 10, + "dir" : 0, + "pipe_no" : 4, + "index" : 0, + "group_id" : 0, + "profile_id" : 28, + "id" : 1073741828, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 31, + "n_actions" : 12, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.dst_addr", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 148, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.src_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 149, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.tpid", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 150, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.priority", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 151, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.cfi", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 152, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.vlan_id", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 153, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.type", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 158, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.src_addr", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 159, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 159, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 161, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 161, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.dst_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 160, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 160, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 162, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.dst_addr", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 162, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.protocol", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 163, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.protocol", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 163, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.next_hdr", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 163, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.next_hdr", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 163, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.diffserv", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 165, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.diffserv", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 165, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.traffic_class", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 166, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.traffic_class", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 166, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.src_port", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.src_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.src_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.dst_port", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.dst_port", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.dst_port", + "key_id" : 30, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 31, + "table_id" : 0, + "p4_table_id" : 4, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003968, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [14], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003969, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [15], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003970, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [16], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003971, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "rx_upcall", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003972, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [17], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003973, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [18], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003974, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [19], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003975, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [20], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv4_dscp", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003976, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [21], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv6_dscp", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003977, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [22], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_vxlan_rsv0", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003978, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 11, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [23], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "rsv0", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 4, + "p4_action_type" : 1074003979, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [24], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_control.egress_acl_group1.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 8, + "total_len" : 25153, + "table_type" : 1, + "key_template_id" : 24, + "dir" : 1, + "pipe_no" : 0, + "index" : 0, + "group_id" : 0, + "profile_id" : 32, + "id" : 1073741832, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 31, + "n_actions" : 9, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.dst_addr", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 148, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.src_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 149, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.tpid", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 150, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.priority", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 151, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.cfi", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 152, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.vlan_id", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 153, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.type", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 158, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.src_addr", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 159, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 159, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 161, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 161, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.dst_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 160, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 160, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 162, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.dst_addr", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 162, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.protocol", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 163, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.protocol", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 163, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.next_hdr", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 163, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.next_hdr", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 163, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.diffserv", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 165, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.diffserv", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 165, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.traffic_class", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 166, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.traffic_class", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 166, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.src_port", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.src_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.src_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.dst_port", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.dst_port", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.dst_port", + "key_id" : 30, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 31, + "table_id" : 0, + "p4_table_id" : 8, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266112, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 24, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [42, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [6, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 13, + "type" : 0, + "target_offset" : 16, + "target_bits" : 16, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 32, + "target_bits" : 2, + "offset_in_param" : 32, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 15, + "type" : 0, + "target_offset" : 34, + "target_bits" : 3, + "offset_in_param" : 34, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 40, + "target_bits" : 2, + "offset_in_param" : 40, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 17, + "type" : 0, + "target_offset" : 42, + "target_bits" : 1, + "offset_in_param" : 42, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 43, + "target_bits" : 1, + "offset_in_param" : 43, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 19, + "type" : 0, + "target_offset" : 44, + "target_bits" : 2, + "offset_in_param" : 44, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 20, + "type" : 0, + "target_offset" : 48, + "target_bits" : 22, + "offset_in_param" : 48, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 690, + "data" : [], + "s_name" : "nvgre_hdr", + "s_id" : 21, + "type" : 0, + "target_offset" : 72, + "target_bits" : 336, + "offset_in_param" : 72, + "length_in_param" : 696, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "nvgre_hdr.eth", + "s_id" : 22, + "type" : 0, + "target_offset" : 80, + "target_bits" : 112, + "offset_in_param" : 80, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "nvgre_hdr.ipv4", + "s_id" : 23, + "type" : 0, + "target_offset" : 224, + "target_bits" : 160, + "offset_in_param" : 224, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 374, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "nvgre_hdr.nvgre", + "s_id" : 24, + "type" : 0, + "target_offset" : 704, + "target_bits" : 64, + "offset_in_param" : 704, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266113, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 25, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [50, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [7, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 11, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 12, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 13, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 15, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 17, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 18, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan_hdr", + "s_id" : 19, + "type" : 0, + "target_offset" : 96, + "target_bits" : 400, + "offset_in_param" : 96, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "vxlan_hdr.eth", + "s_id" : 20, + "type" : 0, + "target_offset" : 104, + "target_bits" : 112, + "offset_in_param" : 104, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "vxlan_hdr.ipv4", + "s_id" : 21, + "type" : 0, + "target_offset" : 248, + "target_bits" : 160, + "offset_in_param" : 248, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 432, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.udp", + "s_id" : 22, + "type" : 0, + "target_offset" : 728, + "target_bits" : 64, + "offset_in_param" : 728, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 372, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.vxlan", + "s_id" : 23, + "type" : 0, + "target_offset" : 792, + "target_bits" : 64, + "offset_in_param" : 792, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 24, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 26, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266114, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 13, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 4, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 5, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 6, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 7, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 8, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 9, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 10, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 11, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266115, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266116, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 686, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266117, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 1, + "s_len" : 5, + "data" : [], + "s_name" : "tag", + "s_id" : 3, + "type" : 0, + "target_offset" : 21, + "target_bits" : 5, + "offset_in_param" : 0, + "length_in_param" : 5, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "tx_upcall", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266118, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [25], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266119, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 687, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 8, + "p4_action_type" : 1074266120, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 6, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 353, + "need_param" : 1, + "s_len" : 32, + "data" : [], + "s_name" : "src_addr", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 32, + "offset_in_param" : 0, + "length_in_param" : 32, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_control.egress_acl_group2.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 9, + "total_len" : 25153, + "table_type" : 1, + "key_template_id" : 25, + "dir" : 1, + "pipe_no" : 1, + "index" : 0, + "group_id" : 0, + "profile_id" : 41, + "id" : 1073741833, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 31, + "n_actions" : 9, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.dst_addr", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 148, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.src_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 149, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.tpid", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 150, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.priority", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 151, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.cfi", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 152, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.vlan_id", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 153, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.type", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 158, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.src_addr", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 159, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 159, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 161, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 161, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.dst_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 160, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 160, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 162, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.dst_addr", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 162, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.protocol", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 163, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.protocol", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 163, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.next_hdr", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 163, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.next_hdr", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 163, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.diffserv", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 165, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.diffserv", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 165, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.traffic_class", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 166, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.traffic_class", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 166, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.src_port", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.src_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.src_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.sctp.dst_port", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 252, + "p4_pattern_type" : 1073808645, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.tcp.dst_port", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 252, + "p4_pattern_type" : 1073808642, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outertransport.udp.dst_port", + "key_id" : 30, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 252, + "p4_pattern_type" : 1073808643, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 31, + "table_id" : 0, + "p4_table_id" : 9, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331648, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 24, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [42, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 13, + "type" : 0, + "target_offset" : 16, + "target_bits" : 16, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 32, + "target_bits" : 2, + "offset_in_param" : 32, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 15, + "type" : 0, + "target_offset" : 34, + "target_bits" : 3, + "offset_in_param" : 34, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 40, + "target_bits" : 2, + "offset_in_param" : 40, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 17, + "type" : 0, + "target_offset" : 42, + "target_bits" : 1, + "offset_in_param" : 42, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 43, + "target_bits" : 1, + "offset_in_param" : 43, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 19, + "type" : 0, + "target_offset" : 44, + "target_bits" : 2, + "offset_in_param" : 44, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 20, + "type" : 0, + "target_offset" : 48, + "target_bits" : 22, + "offset_in_param" : 48, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 690, + "data" : [], + "s_name" : "nvgre_hdr", + "s_id" : 21, + "type" : 0, + "target_offset" : 72, + "target_bits" : 336, + "offset_in_param" : 72, + "length_in_param" : 696, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "nvgre_hdr.eth", + "s_id" : 22, + "type" : 0, + "target_offset" : 80, + "target_bits" : 112, + "offset_in_param" : 80, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "nvgre_hdr.ipv4", + "s_id" : 23, + "type" : 0, + "target_offset" : 224, + "target_bits" : 160, + "offset_in_param" : 224, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 374, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "nvgre_hdr.nvgre", + "s_id" : 24, + "type" : 0, + "target_offset" : 704, + "target_bits" : 64, + "offset_in_param" : 704, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331649, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 25, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [50, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [9, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 11, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 12, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 13, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 15, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 17, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 18, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan_hdr", + "s_id" : 19, + "type" : 0, + "target_offset" : 96, + "target_bits" : 400, + "offset_in_param" : 96, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "vxlan_hdr.eth", + "s_id" : 20, + "type" : 0, + "target_offset" : 104, + "target_bits" : 112, + "offset_in_param" : 104, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "vxlan_hdr.ipv4", + "s_id" : 21, + "type" : 0, + "target_offset" : 248, + "target_bits" : 160, + "offset_in_param" : 248, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 432, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.udp", + "s_id" : 22, + "type" : 0, + "target_offset" : 728, + "target_bits" : 64, + "offset_in_param" : 728, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 372, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.vxlan", + "s_id" : 23, + "type" : 0, + "target_offset" : 792, + "target_bits" : 64, + "offset_in_param" : 792, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 24, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 26, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331650, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 13, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 4, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 5, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 6, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 7, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 8, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 9, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 10, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 11, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331651, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331652, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 686, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331653, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 337, + "need_param" : 1, + "s_len" : 5, + "data" : [], + "s_name" : "tag", + "s_id" : 3, + "type" : 0, + "target_offset" : 21, + "target_bits" : 5, + "offset_in_param" : 0, + "length_in_param" : 5, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "tx_upcall", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331654, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [9, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [26], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331655, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 687, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 9, + "p4_action_type" : 1074331656, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 8, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 353, + "need_param" : 1, + "s_len" : 32, + "data" : [], + "s_name" : "src_addr", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 32, + "offset_in_param" : 0, + "length_in_param" : 32, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_control.egress_fwd.wc_table", + "p4_table_size" : 512, + "table_id" : 0, + "p4_table_id" : 10, + "total_len" : 27141, + "table_type" : 1, + "key_template_id" : 26, + "dir" : 1, + "pipe_no" : 2, + "index" : 0, + "group_id" : 0, + "profile_id" : 43, + "id" : 1073741834, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 10, + "n_actions" : 15, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.tpid", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 150, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.priority", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 151, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.cfi", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 152, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_vlan.vlan_id", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 153, + "p4_pattern_type" : 1073807617, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.outer_ethernet.type", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 158, + "p4_pattern_type" : 1073807616, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4.dst_addr", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 160, + "p4_pattern_type" : 1073808130, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv4_frag.dst_addr", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 160, + "p4_pattern_type" : 1073808128, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6.dst_addr", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 162, + "p4_pattern_type" : 1073808132, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.outerip.ipv6_frag.dst_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 10, + "key_type" : 162, + "p4_pattern_type" : 1073808131, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "dec_ttl", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397184, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 4194304, + "n_sub_acts" : 1, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 342, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 64, 0] + } + ], + "param" : [] + }, + { + "act_name" : "drop", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397185, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 3, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 700, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "ecmp", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397186, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 1, + "key_build_profile_id" : 0, + "total_len_in_param" : 16, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 3, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 337, + "need_param" : 0, + "s_len" : 8, + "data" : [0, 0, 0, 0, 0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [27], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "recirc_id", + "p_id" : 0, + "p_len" : 8, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "member_num", + "p_id" : 0, + "p_len" : 8, + "p_offset" : 8, + "endian" : 0 + } + ] + }, + { + "act_name" : "encap_vxlan", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397187, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 482, + "n_sub_acts" : 2, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 482, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 432, + "offset_in_param" : 8, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 638, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "flag", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 1, + "offset_in_param" : 0, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "flag", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "vxlan", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 8, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397188, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 24, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [42, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 11, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 13, + "type" : 0, + "target_offset" : 16, + "target_bits" : 16, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 32, + "target_bits" : 2, + "offset_in_param" : 32, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 15, + "type" : 0, + "target_offset" : 34, + "target_bits" : 3, + "offset_in_param" : 34, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 40, + "target_bits" : 2, + "offset_in_param" : 40, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 17, + "type" : 0, + "target_offset" : 42, + "target_bits" : 1, + "offset_in_param" : 42, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 18, + "type" : 0, + "target_offset" : 43, + "target_bits" : 1, + "offset_in_param" : 43, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 19, + "type" : 0, + "target_offset" : 44, + "target_bits" : 2, + "offset_in_param" : 44, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 20, + "type" : 0, + "target_offset" : 48, + "target_bits" : 22, + "offset_in_param" : 48, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 690, + "data" : [], + "s_name" : "nvgre_hdr", + "s_id" : 21, + "type" : 0, + "target_offset" : 72, + "target_bits" : 336, + "offset_in_param" : 72, + "length_in_param" : 696, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "nvgre_hdr.eth", + "s_id" : 22, + "type" : 0, + "target_offset" : 80, + "target_bits" : 112, + "offset_in_param" : 80, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "nvgre_hdr.ipv4", + "s_id" : 23, + "type" : 0, + "target_offset" : 224, + "target_bits" : 160, + "offset_in_param" : 224, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 374, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "nvgre_hdr.nvgre", + "s_id" : 24, + "type" : 0, + "target_offset" : 704, + "target_bits" : 64, + "offset_in_param" : 704, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397189, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 25, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [50, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 416, + "need_param" : 0, + "s_len" : 4, + "data" : [11, 0, 0, 0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 417, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 4, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 418, + "need_param" : 0, + "s_len" : 4, + "data" : [8, 0, 0, 0], + "s_name" : "", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 419, + "need_param" : 0, + "s_len" : 4, + "data" : [4, 0, 0, 0], + "s_name" : "", + "s_id" : 6, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 420, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 7, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 421, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 8, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 422, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 9, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 10, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 11, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 12, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 13, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 14, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 15, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 16, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 17, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 18, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 430, + "need_param" : 1, + "s_len" : 754, + "data" : [], + "s_name" : "vxlan_hdr", + "s_id" : 19, + "type" : 0, + "target_offset" : 96, + "target_bits" : 400, + "offset_in_param" : 96, + "length_in_param" : 760, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 431, + "need_param" : 1, + "s_len" : 112, + "data" : [], + "s_name" : "vxlan_hdr.eth", + "s_id" : 20, + "type" : 0, + "target_offset" : 104, + "target_bits" : 112, + "offset_in_param" : 104, + "length_in_param" : 112, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 433, + "need_param" : 1, + "s_len" : 160, + "data" : [], + "s_name" : "vxlan_hdr.ipv4", + "s_id" : 21, + "type" : 0, + "target_offset" : 248, + "target_bits" : 160, + "offset_in_param" : 248, + "length_in_param" : 160, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 432, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.udp", + "s_id" : 22, + "type" : 0, + "target_offset" : 728, + "target_bits" : 64, + "offset_in_param" : 728, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 372, + "need_param" : 1, + "s_len" : 64, + "data" : [], + "s_name" : "vxlan_hdr.vxlan", + "s_id" : 23, + "type" : 0, + "target_offset" : 792, + "target_bits" : 64, + "offset_in_param" : 792, + "length_in_param" : 64, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 24, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 25, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 26, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397190, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 13, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 441, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 411, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "sample.sample_config", + "s_id" : 4, + "type" : 0, + "target_offset" : 40, + "target_bits" : 16, + "offset_in_param" : 40, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 410, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "sample.sample_mode", + "s_id" : 5, + "type" : 0, + "target_offset" : 56, + "target_bits" : 2, + "offset_in_param" : 56, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 412, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "sample.time_mode", + "s_id" : 6, + "type" : 0, + "target_offset" : 58, + "target_bits" : 3, + "offset_in_param" : 58, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 406, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.mode", + "s_id" : 7, + "type" : 0, + "target_offset" : 64, + "target_bits" : 2, + "offset_in_param" : 64, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 407, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.ignore_drop", + "s_id" : 8, + "type" : 0, + "target_offset" : 66, + "target_bits" : 1, + "offset_in_param" : 66, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 414, + "need_param" : 1, + "s_len" : 1, + "data" : [], + "s_name" : "conf.int_encap_mode", + "s_id" : 9, + "type" : 0, + "target_offset" : 67, + "target_bits" : 1, + "offset_in_param" : 67, + "length_in_param" : 1, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 408, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "conf.trunc", + "s_id" : 10, + "type" : 0, + "target_offset" : 68, + "target_bits" : 2, + "offset_in_param" : 68, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 326, + "need_param" : 1, + "s_len" : 22, + "data" : [], + "s_name" : "dest", + "s_id" : 11, + "type" : 0, + "target_offset" : 72, + "target_bits" : 22, + "offset_in_param" : 72, + "length_in_param" : 22, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 41, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "pri", + "s_id" : 12, + "type" : 0, + "target_offset" : 0, + "target_bits" : 2, + "offset_in_param" : 16, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 43, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "mirror_index", + "s_id" : 13, + "type" : 0, + "target_offset" : 0, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 42, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "meter_id", + "s_id" : 14, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 24, + "length_in_param" : 16, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "pop_vlan", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397191, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 1, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 338, + "need_param" : 0, + "s_len" : 4, + "data" : [1, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "push_vlan", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397192, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 341, + "n_sub_acts" : 4, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 4, + "data" : [], + "s_name" : "type", + "s_id" : 2, + "type" : 0, + "target_offset" : 19, + "target_bits" : 2, + "offset_in_param" : 0, + "length_in_param" : 4, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 3, + "data" : [], + "s_name" : "mask", + "s_id" : 3, + "type" : 0, + "target_offset" : 16, + "target_bits" : 3, + "offset_in_param" : 8, + "length_in_param" : 3, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "tpid", + "s_id" : 4, + "type" : 0, + "target_offset" : 21, + "target_bits" : 3, + "offset_in_param" : 16, + "length_in_param" : 16, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 341, + "need_param" : 1, + "s_len" : 16, + "data" : [], + "s_name" : "value", + "s_id" : 5, + "type" : 0, + "target_offset" : 0, + "target_bits" : 16, + "offset_in_param" : 32, + "length_in_param" : 16, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "type", + "p_id" : 0, + "p_len" : 4, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "mask", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "tpid", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "value", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 32, + "endian" : 1 + } + ] + }, + { + "act_name" : "send_port", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397193, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 2, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 310, + "n_sub_acts" : 4, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 308, + "need_param" : 0, + "s_len" : 1, + "data" : [1], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 309, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 0, + "s_len" : 4, + "data" : [0, 0, 72, 0] + }, + { + "s_type" : 310, + "need_param" : 1, + "s_len" : 2, + "data" : [], + "s_name" : "id", + "s_id" : 5, + "type" : 0, + "target_offset" : 6, + "target_bits" : 2, + "offset_in_param" : 0, + "length_in_param" : 2, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "send_to_vf", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397194, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 13, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 310, + "n_sub_acts" : 4, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 308, + "need_param" : 0, + "s_len" : 1, + "data" : [1], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 309, + "need_param" : 0, + "s_len" : 1, + "data" : [0], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 310, + "need_param" : 0, + "s_len" : 4, + "data" : [64, 18, 64, 0] + }, + { + "s_type" : 310, + "need_param" : 1, + "s_len" : 13, + "data" : [], + "s_name" : "vfid", + "s_id" : 5, + "type" : 0, + "target_offset" : 6, + "target_bits" : 13, + "offset_in_param" : 0, + "length_in_param" : 13, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "vfid", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_counter", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397195, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 686, + "need_param" : 1, + "s_len" : 14, + "data" : [], + "s_name" : "id", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 14, + "offset_in_param" : 0, + "length_in_param" : 14, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_dmac", + "action_id" : 12, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397196, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 349, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 349, + "need_param" : 1, + "s_len" : 48, + "data" : [], + "s_name" : "mac", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 48, + "offset_in_param" : 0, + "length_in_param" : 48, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "set_smac", + "action_id" : 13, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397197, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 48, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 350, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 350, + "need_param" : 1, + "s_len" : 48, + "data" : [], + "s_name" : "mac", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 48, + "offset_in_param" : 0, + "length_in_param" : 48, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mac", + "p_id" : 0, + "p_len" : 48, + "p_offset" : 0, + "endian" : 1 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 14, + "table_id" : 0, + "p4_table_id" : 10, + "p4_action_type" : 1074397198, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 5, + "key_build_profile_id" : 10, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 1, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 353, + "need_param" : 1, + "s_len" : 32, + "data" : [], + "s_name" : "src_addr", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 32, + "offset_in_param" : 0, + "length_in_param" : 32, + "endian" : 1, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_control.egress_acl_group3.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 12, + "total_len" : 17767, + "table_type" : 1, + "key_template_id" : 28, + "dir" : 1, + "pipe_no" : 3, + "index" : 0, + "group_id" : 0, + "profile_id" : 45, + "id" : 1073741836, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 29, + "n_actions" : 12, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.vni", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 177, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 32, + "length_in_param" : 32, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.dst_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 186, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.src_addr", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 187, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.tpid", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 188, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.priority", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 189, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.cfi", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 190, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.vlan_id", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 191, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.type", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 196, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 197, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 199, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 199, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.dst_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 198, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 200, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 200, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.protocol", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 201, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.next_hdr", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 201, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.next_hdr", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 201, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.diffserv", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 203, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.traffic_class", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 204, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.traffic_class", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 204, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.dst_port", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.dst_port", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.dst_port", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.src_port", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.src_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.src_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.reserved0", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 12, + "key_type" : 253, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 24, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 24, + "total_len_in_param" : 64, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528256, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [30], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528257, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [31], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528258, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [32], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528259, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528260, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [33], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528261, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [34], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "tx_upcall", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528262, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [35], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528263, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [36], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv4_dscp", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528264, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [37], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv6_dscp", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528265, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [38], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_vxlan_rsv0", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528266, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 11, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [39], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "rsv0", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 12, + "p4_action_type" : 1074528267, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [10, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [40], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + }, + { + "table_name" : "egress_control.egress_acl_group4.wc_table", + "p4_table_size" : 16, + "table_id" : 0, + "p4_table_id" : 13, + "total_len" : 17767, + "table_type" : 1, + "key_template_id" : 29, + "dir" : 1, + "pipe_no" : 4, + "index" : 0, + "group_id" : 0, + "profile_id" : 47, + "id" : 1073741837, + "wc_priority" : 0, + "priority" : 0, + "is_ct" : 0, + "flags" : 0, + "n_keys" : 29, + "n_actions" : 12, + "keys" : [ + { + "key_name" : "meta.tx_port", + "key_id" : 1, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 144, + "p4_pattern_type" : 1610612739, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 14, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 14, + "total_len_in_param" : 14, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.vni", + "key_id" : 2, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 177, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 32, + "length_in_param" : 32, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.dst_addr", + "key_id" : 3, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 186, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.src_addr", + "key_id" : 4, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 187, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 48, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 48, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.tpid", + "key_id" : 5, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 188, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.priority", + "key_id" : 6, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 189, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 3, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 3, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.cfi", + "key_id" : 7, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 190, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 1, + "data_len" : 0, + "offset_in_param" : 3, + "length_in_param" : 1, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_vlan.vlan_id", + "key_id" : 8, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 191, + "p4_pattern_type" : 1073873153, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 12, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 12, + "total_len_in_param" : 32, + "data" : [] + }, + { + "key_name" : "hdr.inner_ethernet.type", + "key_id" : 9, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 196, + "p4_pattern_type" : 1073873152, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 16, + "total_len_in_param" : 112, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.src_addr", + "key_id" : 10, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 197, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 96, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.src_addr", + "key_id" : 11, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 199, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.src_addr", + "key_id" : 12, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 199, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 64, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.dst_addr", + "key_id" : 13, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 198, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 32, + "data_len" : 0, + "offset_in_param" : 128, + "length_in_param" : 32, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.dst_addr", + "key_id" : 14, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 200, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.dst_addr", + "key_id" : 15, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 200, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 128, + "data_len" : 0, + "offset_in_param" : 192, + "length_in_param" : 128, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.protocol", + "key_id" : 16, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 201, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 72, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.next_hdr", + "key_id" : 17, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 201, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.next_hdr", + "key_id" : 18, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 201, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 48, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv4.diffserv", + "key_id" : 19, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 203, + "p4_pattern_type" : 1073873666, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 8, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6.traffic_class", + "key_id" : 20, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 204, + "p4_pattern_type" : 1073873668, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innerip.ipv6_frag.traffic_class", + "key_id" : 21, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 204, + "p4_pattern_type" : 1073873667, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 8, + "data_len" : 0, + "offset_in_param" : 4, + "length_in_param" : 8, + "total_len_in_param" : 320, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.dst_port", + "key_id" : 22, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.dst_port", + "key_id" : 23, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.dst_port", + "key_id" : 24, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 16, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.sctp.src_port", + "key_id" : 25, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 252, + "p4_pattern_type" : 1073874181, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 96, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.tcp.src_port", + "key_id" : 26, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 252, + "p4_pattern_type" : 1073874178, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 160, + "data" : [] + }, + { + "key_name" : "hdr.innertransport.udp.src_port", + "key_id" : 27, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 252, + "p4_pattern_type" : 1073874179, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 16, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 16, + "total_len_in_param" : 64, + "data" : [] + }, + { + "key_name" : "umeta.tag", + "key_id" : 28, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 146, + "p4_pattern_type" : 1342177281, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 5, + "data_len" : 0, + "offset_in_param" : 0, + "length_in_param" : 5, + "total_len_in_param" : 5, + "data" : [] + }, + { + "key_name" : "hdr.outer_vxlan.reserved0", + "key_id" : 29, + "table_id" : 0, + "p4_table_id" : 13, + "key_type" : 253, + "p4_pattern_type" : 1073808897, + "match_type" : 2, + "udf_flag" : 0, + "key_bit_len" : 24, + "data_len" : 0, + "offset_in_param" : 8, + "length_in_param" : 24, + "total_len_in_param" : 64, + "data" : [] + } + ], + "actions" : [ + { + "act_name" : "mirror_encap_nvgre", + "action_id" : 0, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593792, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 768, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 5, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [41], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 16, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 48, + "endian" : 1 + }, + { + "p_name" : "nvgre_hdr", + "p_id" : 0, + "p_len" : 696, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_encap_vxlan", + "action_id" : 1, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593793, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 856, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 7, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [42], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + }, + { + "p_name" : "vxlan_hdr", + "p_id" : 0, + "p_len" : 760, + "p_offset" : 96, + "endian" : 1 + } + ] + }, + { + "act_name" : "mirror_no_tunnel", + "action_id" : 2, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593794, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 94, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 43, + "n_sub_acts" : 2, + "n_params" : 6, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [43], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "mirror_index", + "p_id" : 0, + "p_len" : 13, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "pri", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "meter_id", + "p_id" : 0, + "p_len" : 16, + "p_offset" : 24, + "endian" : 0 + }, + { + "p_name" : "sample", + "p_id" : 0, + "p_len" : 21, + "p_offset" : 40, + "endian" : 1 + }, + { + "p_name" : "conf", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 64, + "endian" : 1 + }, + { + "p_name" : "dest", + "p_id" : 0, + "p_len" : 22, + "p_offset" : 72, + "endian" : 1 + } + ] + }, + { + "act_name" : "NoAction", + "action_id" : 3, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593795, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 0, + "n_params" : 0, + "sub_actions" : [], + "param" : [] + }, + { + "act_name" : "set_counter", + "action_id" : 4, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593796, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 686, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [44], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "set_tag", + "action_id" : 5, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593797, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 5, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 337, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [45], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "tag", + "p_id" : 0, + "p_len" : 5, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "tx_upcall", + "action_id" : 6, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593798, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 0, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 0, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [46], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [] + }, + { + "act_name" : "set_shared_counter", + "action_id" : 7, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593799, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 14, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 687, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [47], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "id", + "p_id" : 0, + "p_len" : 14, + "p_offset" : 0, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv4_dscp", + "action_id" : 8, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593800, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [48], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_ipv6_dscp", + "action_id" : 9, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593801, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 30, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 4, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [49], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "dst_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 8, + "endian" : 0 + }, + { + "p_name" : "src_level", + "p_id" : 0, + "p_len" : 1, + "p_offset" : 16, + "endian" : 0 + }, + { + "p_name" : "dscp", + "p_id" : 0, + "p_len" : 6, + "p_offset" : 24, + "endian" : 0 + } + ] + }, + { + "act_name" : "modify_vxlan_rsv0", + "action_id" : 10, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593802, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 11, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 0, + "n_sub_acts" : 2, + "n_params" : 2, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [50], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "opcode", + "p_id" : 0, + "p_len" : 2, + "p_offset" : 0, + "endian" : 0 + }, + { + "p_name" : "rsv0", + "p_id" : 0, + "p_len" : 3, + "p_offset" : 8, + "endian" : 0 + } + ] + }, + { + "act_name" : "snat", + "action_id" : 11, + "table_id" : 0, + "p4_table_id" : 13, + "p4_action_type" : 1074593803, + "rte_flow_type" : 0, + "priority" : 3, + "opcode" : 2, + "key_build_profile_id" : 0, + "total_len_in_param" : 32, + "is_ct" : 0, + "session_id_offset" : 0, + "session_id_len" : 0, + "dir_offset" : 0, + "dir_len" : 0, + "init_state_offset" : 0, + "init_state_len" : 0, + "attribute" : 353, + "n_sub_acts" : 2, + "n_params" : 1, + "sub_actions" : [ + { + "s_type" : 305, + "need_param" : 0, + "s_len" : 4, + "data" : [2, 0, 0, 0], + "s_name" : "", + "s_id" : 2, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + }, + { + "s_type" : 335, + "need_param" : 0, + "s_len" : 1, + "data" : [51], + "s_name" : "", + "s_id" : 3, + "type" : 0, + "target_offset" : 0, + "target_bits" : 0, + "offset_in_param" : 0, + "length_in_param" : 0, + "endian" : 0, + "decap_tnl_type" : 0, + "param" : [] + } + ], + "param" : [ + { + "p_name" : "src_addr", + "p_id" : 0, + "p_len" : 32, + "p_offset" : 0, + "endian" : 1 + } + ] + } + ] + } + ], + "classify_table" : [ + { + "index" : 0, + "classify_id" : 0, + "priority" : 0, + "valid" : 0, + "rsv" : 0, + "dir" : 0, + "key" : { + "source_port" : 7, + "outer" : { + "tun_type" : 1, + "l5p5_type" : 0, + "vlan_valid" : 0, + "vlan_tpid_sel" : 0 + }, + "inner" : { + "tun_type" : 0, + "l5p5_type" : 0, + "vlan_valid" : 0, + "vlan_tpid_sel" : 0 + }, + "tun_idctx" : 0, + "addr_ext" : 0, + "addr0" : 0, + "addr1" : 0, + "outer_vlan_id" : 0, + "inner_vlan_id" : 0, + "ether_type" : 0, + "pipe_no" : 0, + "err_flag" : 0, + "err_type" : 0, + "pkt_type" : 0 + }, + "mask" : { + "source_port" : 255, + "outer" : { + "tun_type" : 31, + "l5p5_type" : 0, + "vlan_valid" : 0, + "vlan_tpid_sel" : 0 + }, + "inner" : { + "tun_type" : 0, + "l5p5_type" : 0, + "vlan_valid" : 0, + "vlan_tpid_sel" : 0 + }, + "tun_idctx" : 0, + "addr_ext" : 0, + "addr0" : 0, + "addr1" : 0, + "outer_vlan_id" : 0, + "inner_vlan_id" : 0, + "ether_type" : 0, + "pipe_no" : 1, + "err_flag" : 0, + "err_type" : 0, + "pkt_type" : 0 + }, + "value" : { + "opcode" : 2, + "default_action_index" : 0, + "key_build_profil_id" : 12, + "mep_distribution_model" : 0, + "mep_distribution_type" : 0, + "dest_valid" : 0, + "action_type" : 0, + "default_dest" : 0 + } + } + ] + } +} \ No newline at end of file diff --git a/LingYaoSNIC/HW/config/smart_nic_init.cfg b/LingYaoSNIC/HW/config/smart_nic_init.cfg new file mode 100644 index 0000000..fe19f49 --- /dev/null +++ b/LingYaoSNIC/HW/config/smart_nic_init.cfg @@ -0,0 +1,28 @@ +{ + "vswitch_cfg": { + "flow_merge_enable": 1, + "bond_info": { + "bus_name": "pci", + "prefix": "jmnd", + "linux-device": [], + "dpdk-device": "b1:00.0" + }, + "vport_info": { + "bus_name": "vdev", + "prefix": "jmnd_vdpa_net_" + }, + "upcall-queue": { + "vm-queue-total-num": 1020 + }, + "reinject-queue": { + "vm-queue-total-num": 1020 + } + }, + "global_cfg": { + "nic_type": "smart_nic", + "vnic_max_num": 255, + "vnic_queue_num": 2040, + "nic_driver_path": "/usr/lib64/librte_jmnd.so", + "vdpa_status": 2 + } +} diff --git a/LingYaoSNIC/HW/firmware/imu_flash_snic_cqaca_1.7.6.img b/LingYaoSNIC/HW/firmware/imu_flash_snic_cqaca_1.7.6.img new file mode 100644 index 0000000..752f4c2 Binary files /dev/null and b/LingYaoSNIC/HW/firmware/imu_flash_snic_cqaca_1.7.6.img differ diff --git a/LingYaoSNIC/HW/firmware/md5.txt b/LingYaoSNIC/HW/firmware/md5.txt new file mode 100644 index 0000000..9b9a9f0 --- /dev/null +++ b/LingYaoSNIC/HW/firmware/md5.txt @@ -0,0 +1,3 @@ +890073cae9c0fae3edf42938e3dfd010 imu_flash_snic_cqaca.img +3c1d9cbab63b4aae0f406c706a307681 scp_flash_cqaca_n2_2.0g_cmn_1.65g.img + diff --git a/LingYaoSNIC/HW/firmware/scp_flash_cqaca_n2_2.0g_cmn_1.65g_1.7.6.img b/LingYaoSNIC/HW/firmware/scp_flash_cqaca_n2_2.0g_cmn_1.65g_1.7.6.img new file mode 100644 index 0000000..43417f3 Binary files /dev/null and b/LingYaoSNIC/HW/firmware/scp_flash_cqaca_n2_2.0g_cmn_1.65g_1.7.6.img differ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vdpa/Makefile b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vdpa/Makefile new file mode 100644 index 0000000..529d3c2 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vdpa/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-m += vdpa.o + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build/ +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + @\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vdpa/vdpa.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vdpa/vdpa.c new file mode 100644 index 0000000..5c9e370 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vdpa/vdpa.c @@ -0,0 +1,1239 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * vDPA bus. + * + * Copyright (c) 2020, Red Hat. All rights reserved. + * Author: Jason Wang + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(mdev_head); +/* A global mutex that protects vdpa management device and device level operations. */ +static DECLARE_RWSEM(vdpa_dev_lock); +static DEFINE_IDA(vdpa_index_ida); + +void vdpa_set_status(struct vdpa_device *vdev, u8 status) +{ + down_write(&vdev->cf_lock); + vdev->config->set_status(vdev, status); + up_write(&vdev->cf_lock); +} +EXPORT_SYMBOL(vdpa_set_status); + +static struct genl_family vdpa_nl_family; + +static int vdpa_dev_probe(struct device *d) +{ + struct vdpa_device *vdev = dev_to_vdpa(d); + struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver); + const struct vdpa_config_ops *ops = vdev->config; + u32 max_num, min_num = 1; + int ret = 0; + + max_num = ops->get_vq_num_max(vdev); + if (ops->get_vq_num_min) + min_num = ops->get_vq_num_min(vdev); + if (max_num < min_num) + return -EINVAL; + + if (drv && drv->probe) + ret = drv->probe(vdev); + + return ret; +} + +static int vdpa_dev_remove(struct device *d) +{ + struct vdpa_device *vdev = dev_to_vdpa(d); + struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver); + + if (drv && drv->remove) + drv->remove(vdev); + + return 0; +} + +static int vdpa_dev_match(struct device *dev, struct device_driver *drv) +{ + struct vdpa_device *vdev = dev_to_vdpa(dev); + + /* Check override first, and if set, only use the named driver */ + if (vdev->driver_override) + return strcmp(vdev->driver_override, drv->name) == 0; + + /* Currently devices must be supported by all vDPA bus drivers */ + return 1; +} + +static ssize_t driver_override_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct vdpa_device *vdev = dev_to_vdpa(dev); + const char *driver_override, *old; + char *cp; + + /* We need to keep extra room for a newline */ + if (count >= (PAGE_SIZE - 1)) + return -EINVAL; + + driver_override = kstrndup(buf, count, GFP_KERNEL); + if (!driver_override) + return -ENOMEM; + + cp = strchr(driver_override, '\n'); + if (cp) + *cp = '\0'; + + device_lock(dev); + old = vdev->driver_override; + if (strlen(driver_override)) { + vdev->driver_override = driver_override; + } else { + kfree(driver_override); + vdev->driver_override = NULL; + } + device_unlock(dev); + + kfree(old); + + return count; +} + +static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct vdpa_device *vdev = dev_to_vdpa(dev); + ssize_t len; + + device_lock(dev); + len = snprintf(buf, PAGE_SIZE, "%s\n", vdev->driver_override); + device_unlock(dev); + + return len; +} +static DEVICE_ATTR_RW(driver_override); + +static struct attribute *vdpa_dev_attrs[] = { + &dev_attr_driver_override.attr, + NULL, +}; + +static const struct attribute_group vdpa_dev_group = { + .attrs = vdpa_dev_attrs, +}; +__ATTRIBUTE_GROUPS(vdpa_dev); + + +static struct bus_type vdpa_bus = { + .name = "vdpa", + .dev_groups = vdpa_dev_groups, + .match = vdpa_dev_match, + .probe = vdpa_dev_probe, + .remove = vdpa_dev_remove, +}; + +static void vdpa_release_dev(struct device *d) +{ + struct vdpa_device *vdev = dev_to_vdpa(d); + const struct vdpa_config_ops *ops = vdev->config; + + if (ops->free) + ops->free(vdev); + + ida_simple_remove(&vdpa_index_ida, vdev->index); + kfree(vdev->driver_override); + kfree(vdev); +} + +/** + * __vdpa_alloc_device - allocate and initilaize a vDPA device + * This allows driver to some prepartion after device is + * initialized but before registered. + * @parent: the parent device + * @config: the bus operations that is supported by this device + * @ngroups: number of groups supported by this device + * @nas: number of address spaces supported by this device + * @size: size of the parent structure that contains private data + * @name: name of the vdpa device; optional. + * @use_va: indicate whether virtual address must be used by this device + * + * Driver should use vdpa_alloc_device() wrapper macro instead of + * using this directly. + * + * Return: Returns an error when parent/config/dma_dev is not set or fail to get + * ida. + */ +struct vdpa_device *__vdpa_alloc_device(struct device *parent, + const struct vdpa_config_ops *config, + unsigned int ngroups, unsigned int nas, + size_t size, const char *name, + bool use_va) +{ + struct vdpa_device *vdev; + int err = -EINVAL; + + if (!config) + goto err; + + if (!!config->dma_map != !!config->dma_unmap) + goto err; + + /* It should only work for the device that use on-chip IOMMU */ + if (use_va && !(config->dma_map || config->set_map)) + goto err; + + err = -ENOMEM; + vdev = kzalloc(size, GFP_KERNEL); + if (!vdev) + goto err; + + err = ida_alloc(&vdpa_index_ida, GFP_KERNEL); + if (err < 0) + goto err_ida; + + vdev->dev.bus = &vdpa_bus; + vdev->dev.parent = parent; + vdev->dev.release = vdpa_release_dev; + vdev->index = err; + vdev->config = config; + vdev->features_valid = false; + vdev->use_va = use_va; + vdev->ngroups = ngroups; + vdev->nas = nas; + + if (name) + err = dev_set_name(&vdev->dev, "%s", name); + else + err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index); + if (err) + goto err_name; + + init_rwsem(&vdev->cf_lock); + device_initialize(&vdev->dev); + + return vdev; + +err_name: + ida_simple_remove(&vdpa_index_ida, vdev->index); +err_ida: + kfree(vdev); +err: + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(__vdpa_alloc_device); + +static int vdpa_name_match(struct device *dev, const void *data) +{ + struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); + + return (strcmp(dev_name(&vdev->dev), data) == 0); +} + +static int __vdpa_register_device(struct vdpa_device *vdev, u32 nvqs) +{ + struct device *dev; + + vdev->nvqs = nvqs; + + lockdep_assert_held(&vdpa_dev_lock); + dev = bus_find_device(&vdpa_bus, NULL, dev_name(&vdev->dev), vdpa_name_match); + if (dev) { + put_device(dev); + return -EEXIST; + } + return device_add(&vdev->dev); +} + +/** + * _vdpa_register_device - register a vDPA device with vdpa lock held + * Caller must have a succeed call of vdpa_alloc_device() before. + * Caller must invoke this routine in the management device dev_add() + * callback after setting up valid mgmtdev for this vdpa device. + * @vdev: the vdpa device to be registered to vDPA bus + * @nvqs: number of virtqueues supported by this device + * + * Return: Returns an error when fail to add device to vDPA bus + */ +int _vdpa_register_device(struct vdpa_device *vdev, u32 nvqs) +{ + if (!vdev->mdev) + return -EINVAL; + + return __vdpa_register_device(vdev, nvqs); +} +EXPORT_SYMBOL_GPL(_vdpa_register_device); + +/** + * vdpa_register_device - register a vDPA device + * Callers must have a succeed call of vdpa_alloc_device() before. + * @vdev: the vdpa device to be registered to vDPA bus + * @nvqs: number of virtqueues supported by this device + * + * Return: Returns an error when fail to add to vDPA bus + */ +int vdpa_register_device(struct vdpa_device *vdev, u32 nvqs) +{ + int err; + + down_write(&vdpa_dev_lock); + err = __vdpa_register_device(vdev, nvqs); + up_write(&vdpa_dev_lock); + return err; +} +EXPORT_SYMBOL_GPL(vdpa_register_device); + +/** + * _vdpa_unregister_device - unregister a vDPA device + * Caller must invoke this routine as part of management device dev_del() + * callback. + * @vdev: the vdpa device to be unregisted from vDPA bus + */ +void _vdpa_unregister_device(struct vdpa_device *vdev) +{ + lockdep_assert_held(&vdpa_dev_lock); + WARN_ON(!vdev->mdev); + device_unregister(&vdev->dev); +} +EXPORT_SYMBOL_GPL(_vdpa_unregister_device); + +/** + * vdpa_unregister_device - unregister a vDPA device + * @vdev: the vdpa device to be unregisted from vDPA bus + */ +void vdpa_unregister_device(struct vdpa_device *vdev) +{ + down_write(&vdpa_dev_lock); + device_unregister(&vdev->dev); + up_write(&vdpa_dev_lock); +} +EXPORT_SYMBOL_GPL(vdpa_unregister_device); + +/** + * __vdpa_register_driver - register a vDPA device driver + * @drv: the vdpa device driver to be registered + * @owner: module owner of the driver + * + * Return: Returns an err when fail to do the registration + */ +int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner) +{ + drv->driver.bus = &vdpa_bus; + drv->driver.owner = owner; + + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(__vdpa_register_driver); + +/** + * vdpa_unregister_driver - unregister a vDPA device driver + * @drv: the vdpa device driver to be unregistered + */ +void vdpa_unregister_driver(struct vdpa_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(vdpa_unregister_driver); + +/** + * vdpa_mgmtdev_register - register a vdpa management device + * + * @mdev: Pointer to vdpa management device + * vdpa_mgmtdev_register() register a vdpa management device which supports + * vdpa device management. + * Return: Returns 0 on success or failure when required callback ops are not + * initialized. + */ +int vdpa_mgmtdev_register(struct vdpa_mgmt_dev *mdev) +{ + if (!mdev->device || !mdev->ops || !mdev->ops->dev_add || !mdev->ops->dev_del) + return -EINVAL; + + INIT_LIST_HEAD(&mdev->list); + down_write(&vdpa_dev_lock); + list_add_tail(&mdev->list, &mdev_head); + up_write(&vdpa_dev_lock); + return 0; +} +EXPORT_SYMBOL_GPL(vdpa_mgmtdev_register); + +static int vdpa_match_remove(struct device *dev, void *data) +{ + struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); + struct vdpa_mgmt_dev *mdev = vdev->mdev; + + if (mdev == data) + mdev->ops->dev_del(mdev, vdev); + return 0; +} + +void vdpa_mgmtdev_unregister(struct vdpa_mgmt_dev *mdev) +{ + down_write(&vdpa_dev_lock); + + list_del(&mdev->list); + + /* Filter out all the entries belong to this management device and delete it. */ + bus_for_each_dev(&vdpa_bus, NULL, mdev, vdpa_match_remove); + + up_write(&vdpa_dev_lock); +} +EXPORT_SYMBOL_GPL(vdpa_mgmtdev_unregister); + +static void vdpa_get_config_unlocked(struct vdpa_device *vdev, + unsigned int offset, + void *buf, unsigned int len) +{ + const struct vdpa_config_ops *ops = vdev->config; + + /* + * Config accesses aren't supposed to trigger before features are set. + * If it does happen we assume a legacy guest. + */ + if (!vdev->features_valid) + vdpa_set_features_unlocked(vdev, 0); + ops->get_config(vdev, offset, buf, len); +} + +/** + * vdpa_get_config - Get one or more device configuration fields. + * @vdev: vdpa device to operate on + * @offset: starting byte offset of the field + * @buf: buffer pointer to read to + * @len: length of the configuration fields in bytes + */ +void vdpa_get_config(struct vdpa_device *vdev, unsigned int offset, + void *buf, unsigned int len) +{ + down_read(&vdev->cf_lock); + vdpa_get_config_unlocked(vdev, offset, buf, len); + up_read(&vdev->cf_lock); +} +EXPORT_SYMBOL_GPL(vdpa_get_config); + +/** + * vdpa_set_config - Set one or more device configuration fields. + * @vdev: vdpa device to operate on + * @offset: starting byte offset of the field + * @buf: buffer pointer to read from + * @length: length of the configuration fields in bytes + */ +void vdpa_set_config(struct vdpa_device *vdev, unsigned int offset, + const void *buf, unsigned int length) +{ + down_write(&vdev->cf_lock); + vdev->config->set_config(vdev, offset, buf, length); + up_write(&vdev->cf_lock); +} +EXPORT_SYMBOL_GPL(vdpa_set_config); + +static bool mgmtdev_handle_match(const struct vdpa_mgmt_dev *mdev, + const char *busname, const char *devname) +{ + /* Bus name is optional for simulated management device, so ignore the + * device with bus if bus attribute is provided. + */ + if ((busname && !mdev->device->bus) || (!busname && mdev->device->bus)) + return false; + + if (!busname && strcmp(dev_name(mdev->device), devname) == 0) + return true; + + if (busname && (strcmp(mdev->device->bus->name, busname) == 0) && + (strcmp(dev_name(mdev->device), devname) == 0)) + return true; + + return false; +} + +static struct vdpa_mgmt_dev *vdpa_mgmtdev_get_from_attr(struct nlattr **attrs) +{ + struct vdpa_mgmt_dev *mdev; + const char *busname = NULL; + const char *devname; + + if (!attrs[VDPA_ATTR_MGMTDEV_DEV_NAME]) + return ERR_PTR(-EINVAL); + devname = nla_data(attrs[VDPA_ATTR_MGMTDEV_DEV_NAME]); + if (attrs[VDPA_ATTR_MGMTDEV_BUS_NAME]) + busname = nla_data(attrs[VDPA_ATTR_MGMTDEV_BUS_NAME]); + + list_for_each_entry(mdev, &mdev_head, list) { + if (mgmtdev_handle_match(mdev, busname, devname)) + return mdev; + } + return ERR_PTR(-ENODEV); +} + +static int vdpa_nl_mgmtdev_handle_fill(struct sk_buff *msg, const struct vdpa_mgmt_dev *mdev) +{ + if (mdev->device->bus && + nla_put_string(msg, VDPA_ATTR_MGMTDEV_BUS_NAME, mdev->device->bus->name)) + return -EMSGSIZE; + if (nla_put_string(msg, VDPA_ATTR_MGMTDEV_DEV_NAME, dev_name(mdev->device))) + return -EMSGSIZE; + return 0; +} + +static int vdpa_mgmtdev_fill(const struct vdpa_mgmt_dev *mdev, struct sk_buff *msg, + u32 portid, u32 seq, int flags) +{ + u64 supported_classes = 0; + void *hdr; + int i = 0; + int err; + + hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, VDPA_CMD_MGMTDEV_NEW); + if (!hdr) + return -EMSGSIZE; + err = vdpa_nl_mgmtdev_handle_fill(msg, mdev); + if (err) + goto msg_err; + + while (mdev->id_table[i].device) { + if (mdev->id_table[i].device <= 63) + supported_classes |= BIT_ULL(mdev->id_table[i].device); + i++; + } + + if (nla_put_u64_64bit(msg, VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, + supported_classes, VDPA_ATTR_UNSPEC)) { + err = -EMSGSIZE; + goto msg_err; + } + if (nla_put_u32(msg, VDPA_ATTR_DEV_MGMTDEV_MAX_VQS, + mdev->max_supported_vqs)) { + err = -EMSGSIZE; + goto msg_err; + } + if (nla_put_u64_64bit(msg, VDPA_ATTR_DEV_SUPPORTED_FEATURES, + mdev->supported_features, VDPA_ATTR_PAD)) { + err = -EMSGSIZE; + goto msg_err; + } + + genlmsg_end(msg, hdr); + return 0; + +msg_err: + genlmsg_cancel(msg, hdr); + return err; +} + +static int vdpa_nl_cmd_mgmtdev_get_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct vdpa_mgmt_dev *mdev; + struct sk_buff *msg; + int err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + down_read(&vdpa_dev_lock); + mdev = vdpa_mgmtdev_get_from_attr(info->attrs); + if (IS_ERR(mdev)) { + up_read(&vdpa_dev_lock); + NL_SET_ERR_MSG_MOD(info->extack, "Fail to find the specified mgmt device"); + err = PTR_ERR(mdev); + goto out; + } + + err = vdpa_mgmtdev_fill(mdev, msg, info->snd_portid, info->snd_seq, 0); + up_read(&vdpa_dev_lock); + if (err) + goto out; + err = genlmsg_reply(msg, info); + return err; + +out: + nlmsg_free(msg); + return err; +} + +static int +vdpa_nl_cmd_mgmtdev_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb) +{ + struct vdpa_mgmt_dev *mdev; + int start = cb->args[0]; + int idx = 0; + int err; + + down_read(&vdpa_dev_lock); + list_for_each_entry(mdev, &mdev_head, list) { + if (idx < start) { + idx++; + continue; + } + err = vdpa_mgmtdev_fill(mdev, msg, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI); + if (err) + goto out; + idx++; + } +out: + up_read(&vdpa_dev_lock); + cb->args[0] = idx; + return msg->len; +} + +#define VDPA_DEV_NET_ATTRS_MASK (BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR) | \ + BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MTU) | \ + BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP)) + +static int vdpa_nl_cmd_dev_add_set_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct vdpa_dev_set_config config = {}; + struct nlattr **nl_attrs = info->attrs; + struct vdpa_mgmt_dev *mdev; + const u8 *macaddr; + const char *name; + int err = 0; + + if (!info->attrs[VDPA_ATTR_DEV_NAME]) + return -EINVAL; + + name = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); + + if (nl_attrs[VDPA_ATTR_DEV_NET_CFG_MACADDR]) { + macaddr = nla_data(nl_attrs[VDPA_ATTR_DEV_NET_CFG_MACADDR]); + memcpy(config.net.mac, macaddr, sizeof(config.net.mac)); + config.mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR); + } + if (nl_attrs[VDPA_ATTR_DEV_NET_CFG_MTU]) { + config.net.mtu = + nla_get_u16(nl_attrs[VDPA_ATTR_DEV_NET_CFG_MTU]); + config.mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MTU); + } + if (nl_attrs[VDPA_ATTR_DEV_NET_CFG_MAX_VQP]) { + config.net.max_vq_pairs = + nla_get_u16(nl_attrs[VDPA_ATTR_DEV_NET_CFG_MAX_VQP]); + if (!config.net.max_vq_pairs) { + NL_SET_ERR_MSG_MOD(info->extack, + "At least one pair of VQs is required"); + return -EINVAL; + } + config.mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP); + } + + /* Skip checking capability if user didn't prefer to configure any + * device networking attributes. It is likely that user might have used + * a device specific method to configure such attributes or using device + * default attributes. + */ + if ((config.mask & VDPA_DEV_NET_ATTRS_MASK) && + !netlink_capable(skb, CAP_NET_ADMIN)) + return -EPERM; + + down_write(&vdpa_dev_lock); + mdev = vdpa_mgmtdev_get_from_attr(info->attrs); + if (IS_ERR(mdev)) { + NL_SET_ERR_MSG_MOD(info->extack, "Fail to find the specified management device"); + err = PTR_ERR(mdev); + goto err; + } + if ((config.mask & mdev->config_attr_mask) != config.mask) { + NL_SET_ERR_MSG_MOD(info->extack, + "All provided attributes are not supported"); + err = -EOPNOTSUPP; + goto err; + } + + err = mdev->ops->dev_add(mdev, name, &config); +err: + up_write(&vdpa_dev_lock); + return err; +} + +static int vdpa_nl_cmd_dev_del_set_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct vdpa_mgmt_dev *mdev; + struct vdpa_device *vdev; + struct device *dev; + const char *name; + int err = 0; + + if (!info->attrs[VDPA_ATTR_DEV_NAME]) + return -EINVAL; + name = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); + + down_write(&vdpa_dev_lock); + dev = bus_find_device(&vdpa_bus, NULL, name, vdpa_name_match); + if (!dev) { + NL_SET_ERR_MSG_MOD(info->extack, "device not found"); + err = -ENODEV; + goto dev_err; + } + vdev = container_of(dev, struct vdpa_device, dev); + if (!vdev->mdev) { + NL_SET_ERR_MSG_MOD(info->extack, "Only user created device can be deleted by user"); + err = -EINVAL; + goto mdev_err; + } + mdev = vdev->mdev; + mdev->ops->dev_del(mdev, vdev); +mdev_err: + put_device(dev); +dev_err: + up_write(&vdpa_dev_lock); + return err; +} + +static int +vdpa_dev_fill(struct vdpa_device *vdev, struct sk_buff *msg, u32 portid, u32 seq, + int flags, struct netlink_ext_ack *extack) +{ + u16 max_vq_size; + u16 min_vq_size = 1; + u32 device_id; + u32 vendor_id; + void *hdr; + int err; + + hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, VDPA_CMD_DEV_NEW); + if (!hdr) + return -EMSGSIZE; + + err = vdpa_nl_mgmtdev_handle_fill(msg, vdev->mdev); + if (err) + goto msg_err; + + device_id = vdev->config->get_device_id(vdev); + vendor_id = vdev->config->get_vendor_id(vdev); + max_vq_size = vdev->config->get_vq_num_max(vdev); + if (vdev->config->get_vq_num_min) + min_vq_size = vdev->config->get_vq_num_min(vdev); + + err = -EMSGSIZE; + if (nla_put_string(msg, VDPA_ATTR_DEV_NAME, dev_name(&vdev->dev))) + goto msg_err; + if (nla_put_u32(msg, VDPA_ATTR_DEV_ID, device_id)) + goto msg_err; + if (nla_put_u32(msg, VDPA_ATTR_DEV_VENDOR_ID, vendor_id)) + goto msg_err; + if (nla_put_u32(msg, VDPA_ATTR_DEV_MAX_VQS, vdev->nvqs)) + goto msg_err; + if (nla_put_u16(msg, VDPA_ATTR_DEV_MAX_VQ_SIZE, max_vq_size)) + goto msg_err; + if (nla_put_u16(msg, VDPA_ATTR_DEV_MIN_VQ_SIZE, min_vq_size)) + goto msg_err; + + genlmsg_end(msg, hdr); + return 0; + +msg_err: + genlmsg_cancel(msg, hdr); + return err; +} + +static int vdpa_nl_cmd_dev_get_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct vdpa_device *vdev; + struct sk_buff *msg; + const char *devname; + struct device *dev; + int err; + + if (!info->attrs[VDPA_ATTR_DEV_NAME]) + return -EINVAL; + devname = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + down_read(&vdpa_dev_lock); + dev = bus_find_device(&vdpa_bus, NULL, devname, vdpa_name_match); + if (!dev) { + NL_SET_ERR_MSG_MOD(info->extack, "device not found"); + err = -ENODEV; + goto err; + } + vdev = container_of(dev, struct vdpa_device, dev); + if (!vdev->mdev) { + err = -EINVAL; + goto mdev_err; + } + err = vdpa_dev_fill(vdev, msg, info->snd_portid, info->snd_seq, 0, info->extack); + if (err) + goto mdev_err; + + err = genlmsg_reply(msg, info); + put_device(dev); + up_read(&vdpa_dev_lock); + return err; + +mdev_err: + put_device(dev); +err: + up_read(&vdpa_dev_lock); + nlmsg_free(msg); + return err; +} + +struct vdpa_dev_dump_info { + struct sk_buff *msg; + struct netlink_callback *cb; + int start_idx; + int idx; +}; + +static int vdpa_dev_dump(struct device *dev, void *data) +{ + struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); + struct vdpa_dev_dump_info *info = data; + int err; + + if (!vdev->mdev) + return 0; + if (info->idx < info->start_idx) { + info->idx++; + return 0; + } + err = vdpa_dev_fill(vdev, info->msg, NETLINK_CB(info->cb->skb).portid, + info->cb->nlh->nlmsg_seq, NLM_F_MULTI, info->cb->extack); + if (err) + return err; + + info->idx++; + return 0; +} + +static int vdpa_nl_cmd_dev_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb) +{ + struct vdpa_dev_dump_info info; + + info.msg = msg; + info.cb = cb; + info.start_idx = cb->args[0]; + info.idx = 0; + + down_read(&vdpa_dev_lock); + bus_for_each_dev(&vdpa_bus, NULL, &info, vdpa_dev_dump); + up_read(&vdpa_dev_lock); + cb->args[0] = info.idx; + return msg->len; +} + +static int vdpa_dev_net_mq_config_fill(struct vdpa_device *vdev, + struct sk_buff *msg, u64 features, + const struct virtio_net_config *config) +{ + u16 val_u16; + + if ((features & BIT_ULL(VIRTIO_NET_F_MQ)) == 0) + return 0; + + val_u16 = le16_to_cpu(config->max_virtqueue_pairs); + return nla_put_u16(msg, VDPA_ATTR_DEV_NET_CFG_MAX_VQP, val_u16); +} + +static int vdpa_dev_net_config_fill(struct vdpa_device *vdev, struct sk_buff *msg) +{ + struct virtio_net_config config = {}; + u64 features; + u16 val_u16; + + vdpa_get_config_unlocked(vdev, 0, &config, sizeof(config)); + + if (nla_put(msg, VDPA_ATTR_DEV_NET_CFG_MACADDR, sizeof(config.mac), + config.mac)) + return -EMSGSIZE; + + val_u16 = __virtio16_to_cpu(true, config.status); + if (nla_put_u16(msg, VDPA_ATTR_DEV_NET_STATUS, val_u16)) + return -EMSGSIZE; + + val_u16 = __virtio16_to_cpu(true, config.mtu); + if (nla_put_u16(msg, VDPA_ATTR_DEV_NET_CFG_MTU, val_u16)) + return -EMSGSIZE; + + features = vdev->config->get_driver_features(vdev); + if (nla_put_u64_64bit(msg, VDPA_ATTR_DEV_NEGOTIATED_FEATURES, features, + VDPA_ATTR_PAD)) + return -EMSGSIZE; + + return vdpa_dev_net_mq_config_fill(vdev, msg, features, &config); +} + +static int +vdpa_dev_config_fill(struct vdpa_device *vdev, struct sk_buff *msg, u32 portid, u32 seq, + int flags, struct netlink_ext_ack *extack) +{ + u32 device_id; + void *hdr; + int err; + + down_read(&vdev->cf_lock); + hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, + VDPA_CMD_DEV_CONFIG_GET); + if (!hdr) { + err = -EMSGSIZE; + goto out; + } + + if (nla_put_string(msg, VDPA_ATTR_DEV_NAME, dev_name(&vdev->dev))) { + err = -EMSGSIZE; + goto msg_err; + } + + device_id = vdev->config->get_device_id(vdev); + if (nla_put_u32(msg, VDPA_ATTR_DEV_ID, device_id)) { + err = -EMSGSIZE; + goto msg_err; + } + + switch (device_id) { + case VIRTIO_ID_NET: + err = vdpa_dev_net_config_fill(vdev, msg); + break; + default: + err = -EOPNOTSUPP; + break; + } + if (err) + goto msg_err; + + up_read(&vdev->cf_lock); + genlmsg_end(msg, hdr); + return 0; + +msg_err: + genlmsg_cancel(msg, hdr); +out: + up_read(&vdev->cf_lock); + return err; +} + +static int vdpa_fill_stats_rec(struct vdpa_device *vdev, struct sk_buff *msg, + struct genl_info *info, u32 index) +{ + struct virtio_net_config config = {}; + u64 features; + u16 max_vqp; + u8 status; + int err; + + status = vdev->config->get_status(vdev); + if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { + NL_SET_ERR_MSG_MOD(info->extack, "feature negotiation not complete"); + return -EAGAIN; + } + vdpa_get_config_unlocked(vdev, 0, &config, sizeof(config)); + + max_vqp = __virtio16_to_cpu(true, config.max_virtqueue_pairs); + if (nla_put_u16(msg, VDPA_ATTR_DEV_NET_CFG_MAX_VQP, max_vqp)) + return -EMSGSIZE; + + features = vdev->config->get_driver_features(vdev); + if (nla_put_u64_64bit(msg, VDPA_ATTR_DEV_NEGOTIATED_FEATURES, + features, VDPA_ATTR_PAD)) + return -EMSGSIZE; + + if (nla_put_u32(msg, VDPA_ATTR_DEV_QUEUE_INDEX, index)) + return -EMSGSIZE; + + err = vdev->config->get_vendor_vq_stats(vdev, index, msg, info->extack); + if (err) + return err; + + return 0; +} + +static int vendor_stats_fill(struct vdpa_device *vdev, struct sk_buff *msg, + struct genl_info *info, u32 index) +{ + int err; + + down_read(&vdev->cf_lock); + if (!vdev->config->get_vendor_vq_stats) { + err = -EOPNOTSUPP; + goto out; + } + + err = vdpa_fill_stats_rec(vdev, msg, info, index); +out: + up_read(&vdev->cf_lock); + return err; +} + +static int vdpa_dev_vendor_stats_fill(struct vdpa_device *vdev, + struct sk_buff *msg, + struct genl_info *info, u32 index) +{ + u32 device_id; + void *hdr; + int err; + u32 portid = info->snd_portid; + u32 seq = info->snd_seq; + u32 flags = 0; + + hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, + VDPA_CMD_DEV_VSTATS_GET); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_string(msg, VDPA_ATTR_DEV_NAME, dev_name(&vdev->dev))) { + err = -EMSGSIZE; + goto undo_msg; + } + + device_id = vdev->config->get_device_id(vdev); + if (nla_put_u32(msg, VDPA_ATTR_DEV_ID, device_id)) { + err = -EMSGSIZE; + goto undo_msg; + } + + switch (device_id) { + case VIRTIO_ID_NET: + if (index > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX) { + NL_SET_ERR_MSG_MOD(info->extack, "queue index excceeds max value"); + err = -ERANGE; + break; + } + + err = vendor_stats_fill(vdev, msg, info, index); + break; + default: + err = -EOPNOTSUPP; + break; + } + genlmsg_end(msg, hdr); + + return err; + +undo_msg: + genlmsg_cancel(msg, hdr); + return err; +} + +static int vdpa_nl_cmd_dev_config_get_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct vdpa_device *vdev; + struct sk_buff *msg; + const char *devname; + struct device *dev; + int err; + + if (!info->attrs[VDPA_ATTR_DEV_NAME]) + return -EINVAL; + devname = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + down_read(&vdpa_dev_lock); + dev = bus_find_device(&vdpa_bus, NULL, devname, vdpa_name_match); + if (!dev) { + NL_SET_ERR_MSG_MOD(info->extack, "device not found"); + err = -ENODEV; + goto dev_err; + } + vdev = container_of(dev, struct vdpa_device, dev); + if (!vdev->mdev) { + NL_SET_ERR_MSG_MOD(info->extack, "unmanaged vdpa device"); + err = -EINVAL; + goto mdev_err; + } + err = vdpa_dev_config_fill(vdev, msg, info->snd_portid, info->snd_seq, + 0, info->extack); + if (!err) + err = genlmsg_reply(msg, info); + +mdev_err: + put_device(dev); +dev_err: + up_read(&vdpa_dev_lock); + if (err) + nlmsg_free(msg); + return err; +} + +static int vdpa_dev_config_dump(struct device *dev, void *data) +{ + struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); + struct vdpa_dev_dump_info *info = data; + int err; + + if (!vdev->mdev) + return 0; + if (info->idx < info->start_idx) { + info->idx++; + return 0; + } + err = vdpa_dev_config_fill(vdev, info->msg, NETLINK_CB(info->cb->skb).portid, + info->cb->nlh->nlmsg_seq, NLM_F_MULTI, + info->cb->extack); + if (err) + return err; + + info->idx++; + return 0; +} + +static int +vdpa_nl_cmd_dev_config_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb) +{ + struct vdpa_dev_dump_info info; + + info.msg = msg; + info.cb = cb; + info.start_idx = cb->args[0]; + info.idx = 0; + + down_read(&vdpa_dev_lock); + bus_for_each_dev(&vdpa_bus, NULL, &info, vdpa_dev_config_dump); + up_read(&vdpa_dev_lock); + cb->args[0] = info.idx; + return msg->len; +} + +static int vdpa_nl_cmd_dev_stats_get_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct vdpa_device *vdev; + struct sk_buff *msg; + const char *devname; + struct device *dev; + u32 index; + int err; + + if (!info->attrs[VDPA_ATTR_DEV_NAME]) + return -EINVAL; + + if (!info->attrs[VDPA_ATTR_DEV_QUEUE_INDEX]) + return -EINVAL; + + devname = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + index = nla_get_u32(info->attrs[VDPA_ATTR_DEV_QUEUE_INDEX]); + down_read(&vdpa_dev_lock); + dev = bus_find_device(&vdpa_bus, NULL, devname, vdpa_name_match); + if (!dev) { + NL_SET_ERR_MSG_MOD(info->extack, "device not found"); + err = -ENODEV; + goto dev_err; + } + vdev = container_of(dev, struct vdpa_device, dev); + if (!vdev->mdev) { + NL_SET_ERR_MSG_MOD(info->extack, "unmanaged vdpa device"); + err = -EINVAL; + goto mdev_err; + } + err = vdpa_dev_vendor_stats_fill(vdev, msg, info, index); + if (err) + goto mdev_err; + + err = genlmsg_reply(msg, info); + + put_device(dev); + up_read(&vdpa_dev_lock); + + return err; + +mdev_err: + put_device(dev); +dev_err: + nlmsg_free(msg); + up_read(&vdpa_dev_lock); + return err; +} + +static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = { + [VDPA_ATTR_MGMTDEV_BUS_NAME] = { .type = NLA_NUL_STRING }, + [VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING }, + [VDPA_ATTR_DEV_NAME] = { .type = NLA_STRING }, + [VDPA_ATTR_DEV_NET_CFG_MACADDR] = NLA_POLICY_ETH_ADDR, + /* virtio spec 1.1 section 5.1.4.1 for valid MTU range */ + [VDPA_ATTR_DEV_NET_CFG_MTU] = NLA_POLICY_MIN(NLA_U16, 68), +}; + +static const struct genl_ops vdpa_nl_ops[] = { + { + .cmd = VDPA_CMD_MGMTDEV_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = vdpa_nl_cmd_mgmtdev_get_doit, + .dumpit = vdpa_nl_cmd_mgmtdev_get_dumpit, + }, + { + .cmd = VDPA_CMD_DEV_NEW, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = vdpa_nl_cmd_dev_add_set_doit, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = VDPA_CMD_DEV_DEL, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = vdpa_nl_cmd_dev_del_set_doit, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = VDPA_CMD_DEV_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = vdpa_nl_cmd_dev_get_doit, + .dumpit = vdpa_nl_cmd_dev_get_dumpit, + }, + { + .cmd = VDPA_CMD_DEV_CONFIG_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = vdpa_nl_cmd_dev_config_get_doit, + .dumpit = vdpa_nl_cmd_dev_config_get_dumpit, + }, + { + .cmd = VDPA_CMD_DEV_VSTATS_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = vdpa_nl_cmd_dev_stats_get_doit, + .flags = GENL_ADMIN_PERM, + }, +}; + +static struct genl_family vdpa_nl_family __ro_after_init = { + .name = VDPA_GENL_NAME, + .version = VDPA_GENL_VERSION, + .maxattr = VDPA_ATTR_MAX, + .policy = vdpa_nl_policy, + .netnsok = false, + .module = THIS_MODULE, + .ops = vdpa_nl_ops, + .n_ops = ARRAY_SIZE(vdpa_nl_ops), +}; + +static int vdpa_init(void) +{ + int err; + + err = bus_register(&vdpa_bus); + if (err) + return err; + err = genl_register_family(&vdpa_nl_family); + if (err) + goto err; + return 0; + +err: + bus_unregister(&vdpa_bus); + return err; +} + +static void __exit vdpa_exit(void) +{ + genl_unregister_family(&vdpa_nl_family); + bus_unregister(&vdpa_bus); + ida_destroy(&vdpa_index_ida); +} +core_initcall(vdpa_init); +module_exit(vdpa_exit); + +MODULE_AUTHOR("Jason Wang "); +MODULE_LICENSE("GPL v2"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/Makefile b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/Makefile new file mode 100644 index 0000000..a78ffba --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-m += vhost_vdpa.o +vhost_vdpa-y := vdpa.o + +obj-m += vhost.o + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build/ +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers +# # KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers +KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + @\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vdpa.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vdpa.c new file mode 100644 index 0000000..9703480 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vdpa.c @@ -0,0 +1,1769 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2020 Intel Corporation. + * Copyright (C) 2020 Red Hat, Inc. + * + * Author: Tiwei Bie + * Jason Wang + * + * Thanks Michael S. Tsirkin for the valuable comments and + * suggestions. And thanks to Cunming Liang and Zhihong Wang for all + * their supports. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vhost.h" + +enum { + VHOST_VDPA_BACKEND_FEATURES = + (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2) | + (1ULL << VHOST_BACKEND_F_IOTLB_BATCH) | + (1ULL << VHOST_BACKEND_F_IOTLB_ASID), +}; + +#define VHOST_VDPA_DEV_MAX (1U << MINORBITS) + +#define VHOST_VDPA_IOTLB_BUCKETS 16 + +struct vhost_vdpa_as { + struct hlist_node hash_link; + struct vhost_iotlb iotlb; + u32 id; +}; + +struct vhost_vdpa { + struct vhost_dev vdev; + struct iommu_domain *domain; + struct vhost_virtqueue *vqs; + struct completion completion; + struct vdpa_device *vdpa; + struct hlist_head as[VHOST_VDPA_IOTLB_BUCKETS]; + struct vhost_iotlb resv_iotlb; + struct device dev; + struct cdev cdev; + atomic_t opened; + u32 nvqs; + int virtio_id; + int minor; + struct eventfd_ctx *config_ctx; + int in_batch; + struct vdpa_iova_range range; + u32 batch_asid; +}; + +static DEFINE_IDA(vhost_vdpa_ida); + +static dev_t vhost_vdpa_major; + +static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, + struct vhost_iotlb *iotlb, u64 start, + u64 last, u32 asid); + +static inline u32 iotlb_to_asid(struct vhost_iotlb *iotlb) +{ + struct vhost_vdpa_as *as = container_of(iotlb, struct + vhost_vdpa_as, iotlb); + return as->id; +} + +static struct vhost_vdpa_as *asid_to_as(struct vhost_vdpa *v, u32 asid) +{ + struct hlist_head *head = &v->as[asid % VHOST_VDPA_IOTLB_BUCKETS]; + struct vhost_vdpa_as *as; + + hlist_for_each_entry(as, head, hash_link) + if (as->id == asid) + return as; + + return NULL; +} + +static struct vhost_iotlb *asid_to_iotlb(struct vhost_vdpa *v, u32 asid) +{ + struct vhost_vdpa_as *as = asid_to_as(v, asid); + + if (!as) + return NULL; + + return &as->iotlb; +} + +static struct vhost_vdpa_as *vhost_vdpa_alloc_as(struct vhost_vdpa *v, u32 asid) +{ + struct hlist_head *head = &v->as[asid % VHOST_VDPA_IOTLB_BUCKETS]; + struct vhost_vdpa_as *as; + + if (asid_to_as(v, asid)) + return NULL; + + if (asid >= v->vdpa->nas) + return NULL; + + as = kmalloc(sizeof(*as), GFP_KERNEL); + if (!as) + return NULL; + + vhost_iotlb_init(&as->iotlb, 0, 0); + as->id = asid; + hlist_add_head(&as->hash_link, head); + + return as; +} + +static struct vhost_vdpa_as *vhost_vdpa_find_alloc_as(struct vhost_vdpa *v, + u32 asid) +{ + struct vhost_vdpa_as *as = asid_to_as(v, asid); + + if (as) + return as; + + return vhost_vdpa_alloc_as(v, asid); +} + +static int vhost_vdpa_remove_as(struct vhost_vdpa *v, u32 asid) +{ + struct vhost_vdpa_as *as = asid_to_as(v, asid); + + if (!as) + return -EINVAL; + + hlist_del(&as->hash_link); + vhost_vdpa_iotlb_unmap(v, &as->iotlb, 0ULL, 0ULL - 1, asid); + kfree(as); + + return 0; +} + +static void handle_vq_kick(struct vhost_work *work) +{ + struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, + poll.work); + struct vhost_vdpa *v = container_of(vq->dev, struct vhost_vdpa, vdev); + const struct vdpa_config_ops *ops = v->vdpa->config; + + ops->kick_vq(v->vdpa, vq - v->vqs); +} + +static irqreturn_t vhost_vdpa_virtqueue_cb(void *private) +{ + struct vhost_virtqueue *vq = private; + struct eventfd_ctx *call_ctx = vq->call_ctx.ctx; + + if (call_ctx) + eventfd_signal(call_ctx, 1); + + return IRQ_HANDLED; +} + +static irqreturn_t vhost_vdpa_config_cb(void *private) +{ + struct vhost_vdpa *v = private; + struct eventfd_ctx *config_ctx = v->config_ctx; + + if (config_ctx) + eventfd_signal(config_ctx, 1); + + return IRQ_HANDLED; +} + +static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid) +{ + struct vhost_virtqueue *vq = &v->vqs[qid]; + const struct vdpa_config_ops *ops = v->vdpa->config; + struct vdpa_device *vdpa = v->vdpa; + int ret, irq; + + if (!ops->get_vq_irq) + return; + + irq = ops->get_vq_irq(vdpa, qid); + if (irq < 0) + return; + + irq_bypass_unregister_producer(&vq->call_ctx.producer); + if (!vq->call_ctx.ctx) + return; + + vq->call_ctx.producer.token = vq->call_ctx.ctx; + vq->call_ctx.producer.irq = irq; + ret = irq_bypass_register_producer(&vq->call_ctx.producer); + if (unlikely(ret)) + dev_info(&v->dev, "vq %u, irq bypass producer (token %p) registration fails, ret = %d\n", + qid, vq->call_ctx.producer.token, ret); +} + +static void vhost_vdpa_unsetup_vq_irq(struct vhost_vdpa *v, u16 qid) +{ + struct vhost_virtqueue *vq = &v->vqs[qid]; + + irq_bypass_unregister_producer(&vq->call_ctx.producer); +} + +static int vhost_vdpa_reset(struct vhost_vdpa *v, int state) +{ + struct vdpa_device *vdpa = v->vdpa; + + v->in_batch = 0; + + return vdpa_reset(vdpa, state); +} + +static long vhost_vdpa_bind_mm(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (!vdpa->use_va || !ops->bind_mm) + return 0; + + return ops->bind_mm(vdpa, v->vdev.mm); +} + +static void vhost_vdpa_unbind_mm(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (!vdpa->use_va || !ops->unbind_mm) + return; + + ops->unbind_mm(vdpa); +} + +static long vhost_vdpa_get_device_id(struct vhost_vdpa *v, u8 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u32 device_id; + + device_id = ops->get_device_id(vdpa); + + if (copy_to_user(argp, &device_id, sizeof(device_id))) + return -EFAULT; + + return 0; +} + +static long vhost_vdpa_get_status(struct vhost_vdpa *v, u8 __user *statusp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u8 status; + + status = ops->get_status(vdpa); + + if (copy_to_user(statusp, &status, sizeof(status))) + return -EFAULT; + + return 0; +} + +static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u8 status, status_old; + u32 nvqs = v->nvqs; + int ret; + u16 i; + + if (copy_from_user(&status, statusp, sizeof(status))) + return -EFAULT; + + status_old = ops->get_status(vdpa); + + /* + * Userspace shouldn't remove status bits unless reset the + * status to 0. + */ + if (status != 0 && (status_old & ~status) != 0) + return -EINVAL; + + if ((status_old & VIRTIO_CONFIG_S_DRIVER_OK) && !(status & VIRTIO_CONFIG_S_DRIVER_OK)) + for (i = 0; i < nvqs; i++) + vhost_vdpa_unsetup_vq_irq(v, i); + + if (status == 0) { + ret = vdpa_reset(vdpa, VDPA_DEV_RESET_VIRTIO); + if (ret) + return ret; + } else + vdpa_set_status(vdpa, status); + + if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && !(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) + for (i = 0; i < nvqs; i++) + vhost_vdpa_setup_vq_irq(v, i); + + return 0; +} + +static int vhost_vdpa_config_validate(struct vhost_vdpa *v, + struct vhost_vdpa_config *c) +{ + struct vdpa_device *vdpa = v->vdpa; + size_t size = vdpa->config->get_config_size(vdpa); + + if (c->len == 0 || c->off > size) + return -EINVAL; + + if (c->len > size - c->off) + return -E2BIG; + + return 0; +} + +static long vhost_vdpa_get_config(struct vhost_vdpa *v, + struct vhost_vdpa_config __user *c) +{ + struct vdpa_device *vdpa = v->vdpa; + struct vhost_vdpa_config config; + unsigned long size = offsetof(struct vhost_vdpa_config, buf); + u8 *buf; + + if (copy_from_user(&config, c, size)) + return -EFAULT; + if (vhost_vdpa_config_validate(v, &config)) + return -EINVAL; + buf = kvzalloc(config.len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + vdpa_get_config(vdpa, config.off, buf, config.len); + + if (copy_to_user(c->buf, buf, config.len)) { + kvfree(buf); + return -EFAULT; + } + + kvfree(buf); + return 0; +} + +static long vhost_vdpa_set_config(struct vhost_vdpa *v, + struct vhost_vdpa_config __user *c) +{ + struct vdpa_device *vdpa = v->vdpa; + struct vhost_vdpa_config config; + unsigned long size = offsetof(struct vhost_vdpa_config, buf); + u8 *buf; + + if (copy_from_user(&config, c, size)) + return -EFAULT; + if (vhost_vdpa_config_validate(v, &config)) + return -EINVAL; + + buf = vmemdup_user(c->buf, config.len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + vdpa_set_config(vdpa, config.off, buf, config.len); + + kvfree(buf); + return 0; +} + +static bool vhost_vdpa_can_suspend(const struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + return ops->suspend; +} + +static bool vhost_vdpa_can_resume(const struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + return ops->resume; +} + +static long vhost_vdpa_get_features(struct vhost_vdpa *v, u64 __user *featurep) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u64 features; + + features = ops->get_device_features(vdpa); + + if (copy_to_user(featurep, &features, sizeof(features))) + return -EFAULT; + + return 0; +} + +static u64 vhost_vdpa_get_backend_features(const struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (!ops->get_backend_features) + return 0; + else + return ops->get_backend_features(vdpa); +} + +static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_dev *d = &v->vdev; + u64 actual_features; + u64 features; + int i; + + if (copy_from_user(&features, featurep, sizeof(features))) + return -EFAULT; + + actual_features = ops->get_driver_features(vdpa); + + /* + * It's not allowed to change the features after they have + * been negotiated. But log start/end is allowed. + */ + if ((ops->get_status(vdpa) & VIRTIO_CONFIG_S_FEATURES_OK) && + (features & ~(BIT_ULL(VHOST_F_LOG_ALL))) != actual_features) { + dev_info(&v->dev,"vhost vdpa set features error. features 0x%llx actual 0x%llx", + features, actual_features); + return -EBUSY; + } + + if (vdpa_set_features(vdpa, features)) + return -EINVAL; + + /* let the vqs know what has been configured */ + actual_features = ops->get_driver_features(vdpa); + for (i = 0; i < d->nvqs; ++i) { + struct vhost_virtqueue *vq = d->vqs[i]; + + mutex_lock(&vq->mutex); + vq->acked_features = actual_features; + mutex_unlock(&vq->mutex); + } + + return 0; +} + +static long vhost_vdpa_get_vring_num(struct vhost_vdpa *v, u16 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u16 num; + + num = ops->get_vq_num_max(vdpa); + + if (copy_to_user(argp, &num, sizeof(num))) + return -EFAULT; + + return 0; +} + +static void vhost_vdpa_config_put(struct vhost_vdpa *v) +{ + if (v->config_ctx) { + eventfd_ctx_put(v->config_ctx); + v->config_ctx = NULL; + } +} + +static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp) +{ + struct vdpa_callback cb; + int fd; + struct eventfd_ctx *ctx; + + cb.callback = vhost_vdpa_config_cb; + cb.private = v; + if (copy_from_user(&fd, argp, sizeof(fd))) + return -EFAULT; + + ctx = fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(fd); + swap(ctx, v->config_ctx); + + if (!IS_ERR_OR_NULL(ctx)) + eventfd_ctx_put(ctx); + + if (IS_ERR(v->config_ctx)) { + long ret = PTR_ERR(v->config_ctx); + + v->config_ctx = NULL; + return ret; + } + + v->vdpa->config->set_config_cb(v->vdpa, &cb); + + return 0; +} + +static long vhost_vdpa_get_iova_range(struct vhost_vdpa *v, u32 __user *argp) +{ + struct vhost_vdpa_iova_range range = { + .first = v->range.first, + .last = v->range.last, + }; + + if (copy_to_user(argp, &range, sizeof(range))) + return -EFAULT; + return 0; +} + +static long vhost_vdpa_get_config_size(struct vhost_vdpa *v, u32 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u32 size; + + size = ops->get_config_size(vdpa); + + if (copy_to_user(argp, &size, sizeof(size))) + return -EFAULT; + + return 0; +} + +static long vhost_vdpa_get_vqs_count(struct vhost_vdpa *v, u32 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + + if (copy_to_user(argp, &vdpa->nvqs, sizeof(vdpa->nvqs))) + return -EFAULT; + + return 0; +} + +/* After a successful return of ioctl the device must not process more + * virtqueue descriptors. The device can answer to read or writes of config + * fields as if it were not suspended. In particular, writing to "queue_enable" + * with a value of 1 will not make the device start processing buffers. + */ +static long vhost_vdpa_suspend(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (!ops->suspend) + return -EOPNOTSUPP; + + return ops->suspend(vdpa); +} + +/* After a successful return of this ioctl the device resumes processing + * virtqueue descriptors. The device becomes fully operational the same way it + * was before it was suspended. + */ +static long vhost_vdpa_resume(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (!ops->resume) + return -EOPNOTSUPP; + + return ops->resume(vdpa); +} + +static int vhost_vdpa_get_dev_buffer_size(struct vhost_vdpa *v, + uint32_t __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + uint32_t size; + + if (!ops->get_dev_buffer_size) + return -EOPNOTSUPP; + + size = ops->get_dev_buffer_size(vdpa); + + if (copy_to_user(argp, &size, sizeof(size))) + return -EFAULT; + + return 0; +} + +static int vhost_vdpa_get_dev_buffer(struct vhost_vdpa *v, + struct vhost_vdpa_config __user *c) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_vdpa_config config; + int ret; + unsigned long size = offsetof(struct vhost_vdpa_config, buf); + + if (copy_from_user(&config, c, size)) + return -EFAULT; + + if (!ops->get_dev_buffer) + return -EOPNOTSUPP; + + down_read(&vdpa->cf_lock); + ret = ops->get_dev_buffer(vdpa, config.off, c->buf, config.len); + up_read(&vdpa->cf_lock); + + return ret; +} + +static int vhost_vdpa_set_dev_buffer(struct vhost_vdpa *v, + struct vhost_vdpa_config __user *c) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_vdpa_config config; + int ret; + unsigned long size = offsetof(struct vhost_vdpa_config, buf); + + if (copy_from_user(&config, c, size)) + return -EFAULT; + + if (!ops->set_dev_buffer) + return -EOPNOTSUPP; + + down_write(&vdpa->cf_lock); + ret = ops->set_dev_buffer(vdpa, config.off, c->buf, config.len); + up_write(&vdpa->cf_lock); + + return ret; +} + +static int vhost_vdpa_set_mig_state(struct vhost_vdpa *v, u8 __user *c) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u8 state; + + if (!ops->set_mig_state) + return -EOPNOTSUPP; + + if (get_user(state, c)) + return -EFAULT; + + return ops->set_mig_state(vdpa, state); +} + +static long vhost_vdpa_set_log_base(struct vhost_vdpa *v, u64 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u64 log; + + if (!ops->set_log_base) + return -EOPNOTSUPP; + + if (copy_from_user(&log, argp, sizeof(uint64_t))) + return -EFAULT; + + return ops->set_log_base(vdpa, log); +} + +static long vhost_vdpa_set_log_size(struct vhost_vdpa *v, u64 __user *sizep) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u64 log_size; + + if (!ops->set_log_size) + return -EOPNOTSUPP; + + if (copy_from_user(&log_size, sizep, sizeof(log_size))) + return -EFAULT; + + return ops->set_log_size(vdpa, log_size); +} + +static long vhost_vdpa_log_sync(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (!ops->log_sync) + return -EOPNOTSUPP; + + return ops->log_sync(vdpa); +} + +static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, + void __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_vq_state vq_state; + struct vdpa_callback cb; + struct vhost_virtqueue *vq; + struct vhost_vring_state s; + u32 idx; + long r; + + r = get_user(idx, (u32 __user *)argp); + if (r < 0) + return r; + + if (idx >= v->nvqs) + return -ENOBUFS; + + idx = array_index_nospec(idx, v->nvqs); + vq = &v->vqs[idx]; + + switch (cmd) { + case VHOST_VDPA_SET_VRING_ENABLE: + if (copy_from_user(&s, argp, sizeof(s))) + return -EFAULT; + ops->set_vq_ready(vdpa, idx, s.num); + return 0; + case VHOST_VDPA_GET_VRING_GROUP: + if (!ops->get_vq_group) + return -EOPNOTSUPP; + s.index = idx; + s.num = ops->get_vq_group(vdpa, idx); + if (s.num >= vdpa->ngroups) + return -EIO; + else if (copy_to_user(argp, &s, sizeof(s))) + return -EFAULT; + return 0; + case VHOST_VDPA_SET_GROUP_ASID: + if (copy_from_user(&s, argp, sizeof(s))) + return -EFAULT; + if (s.num >= vdpa->nas) + return -EINVAL; + if (!ops->set_group_asid) + return -EOPNOTSUPP; + return ops->set_group_asid(vdpa, idx, s.num); + case VHOST_GET_VRING_BASE: + r = ops->get_vq_state(v->vdpa, idx, &vq_state); + if (r) + return r; + + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) { + vq->last_avail_idx = vq_state.packed.last_avail_idx | + (vq_state.packed.last_avail_counter << 15); + vq->last_used_idx = vq_state.packed.last_used_idx | + (vq_state.packed.last_used_counter << 15); + } else { + vq->last_avail_idx = vq_state.split.avail_index; + } + break; + } + + r = vhost_vring_ioctl(&v->vdev, cmd, argp); + if (r) + return r; + + switch (cmd) { + case VHOST_SET_VRING_ADDR: + if (ops->set_vq_address(vdpa, idx, + (u64)(uintptr_t)vq->desc, + (u64)(uintptr_t)vq->avail, + (u64)(uintptr_t)vq->used)) + r = -EINVAL; + break; + + case VHOST_SET_VRING_BASE: + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) { + vq_state.packed.last_avail_idx = vq->last_avail_idx & 0x7fff; + vq_state.packed.last_avail_counter = !!(vq->last_avail_idx & 0x8000); + vq_state.packed.last_used_idx = vq->last_used_idx & 0x7fff; + vq_state.packed.last_used_counter = !!(vq->last_used_idx & 0x8000); + } else { + vq_state.split.avail_index = vq->last_avail_idx; + } + r = ops->set_vq_state(vdpa, idx, &vq_state); + break; + + case VHOST_SET_VRING_CALL: + if (vq->call_ctx.ctx) { + cb.callback = vhost_vdpa_virtqueue_cb; + cb.private = vq; + } else { + cb.callback = NULL; + cb.private = NULL; + } + ops->set_vq_cb(vdpa, idx, &cb); + vhost_vdpa_setup_vq_irq(v, idx); + break; + + case VHOST_SET_VRING_NUM: + ops->set_vq_num(vdpa, idx, vq->num); + break; + } + + return r; +} + +static long vhost_vdpa_unlocked_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + struct vhost_vdpa *v = filep->private_data; + struct vhost_dev *d = &v->vdev; + void __user *argp = (void __user *)arg; + u64 __user *featurep = argp; + u64 features; + long r = 0; + + if (cmd == VHOST_SET_BACKEND_FEATURES) { + if (copy_from_user(&features, featurep, sizeof(features))) + return -EFAULT; + if (features & ~(VHOST_VDPA_BACKEND_FEATURES | + BIT_ULL(VHOST_BACKEND_F_SUSPEND) | + BIT_ULL(VHOST_BACKEND_F_RESUME) | + BIT_ULL(VHOST_BACKEND_F_BYTEMAPLOG))) + return -EOPNOTSUPP; + if ((features & BIT_ULL(VHOST_BACKEND_F_SUSPEND)) && + !vhost_vdpa_can_suspend(v)) + return -EOPNOTSUPP; + if ((features & BIT_ULL(VHOST_BACKEND_F_RESUME)) && + !vhost_vdpa_can_resume(v)) + return -EOPNOTSUPP; + vhost_set_backend_features(&v->vdev, features); + return 0; + } + + mutex_lock(&d->mutex); + + switch (cmd) { + case VHOST_VDPA_GET_DEVICE_ID: + r = vhost_vdpa_get_device_id(v, argp); + break; + case VHOST_VDPA_GET_STATUS: + r = vhost_vdpa_get_status(v, argp); + break; + case VHOST_VDPA_SET_STATUS: + r = vhost_vdpa_set_status(v, argp); + break; + case VHOST_VDPA_GET_CONFIG: + r = vhost_vdpa_get_config(v, argp); + break; + case VHOST_VDPA_SET_CONFIG: + r = vhost_vdpa_set_config(v, argp); + break; + case VHOST_GET_FEATURES: + r = vhost_vdpa_get_features(v, argp); + break; + case VHOST_SET_FEATURES: + r = vhost_vdpa_set_features(v, argp); + break; + case VHOST_VDPA_GET_VRING_NUM: + r = vhost_vdpa_get_vring_num(v, argp); + break; + case VHOST_VDPA_GET_GROUP_NUM: + if (copy_to_user(argp, &v->vdpa->ngroups, + sizeof(v->vdpa->ngroups))) + r = -EFAULT; + break; + case VHOST_VDPA_GET_AS_NUM: + if (copy_to_user(argp, &v->vdpa->nas, sizeof(v->vdpa->nas))) + r = -EFAULT; + break; + case VHOST_SET_LOG_BASE: + r = vhost_vdpa_set_log_base(v, argp); + break; + case VHOST_SET_LOG_SIZE: + r = vhost_vdpa_set_log_size(v, argp); + break; + case VHOST_LOG_SYNC: + r = vhost_vdpa_log_sync(v); + break; + case VHOST_SET_LOG_FD: + r = -ENOIOCTLCMD; + break; + case VHOST_VDPA_SET_CONFIG_CALL: + r = vhost_vdpa_set_config_call(v, argp); + break; + case VHOST_GET_BACKEND_FEATURES: + features = VHOST_VDPA_BACKEND_FEATURES; + if (vhost_vdpa_can_suspend(v)) + features |= BIT_ULL(VHOST_BACKEND_F_SUSPEND); + if (vhost_vdpa_can_resume(v)) + features |= BIT_ULL(VHOST_BACKEND_F_RESUME); + features |= vhost_vdpa_get_backend_features(v); + if (copy_to_user(featurep, &features, sizeof(features))) + r = -EFAULT; + break; + case VHOST_VDPA_GET_IOVA_RANGE: + r = vhost_vdpa_get_iova_range(v, argp); + break; + case VHOST_VDPA_GET_CONFIG_SIZE: + r = vhost_vdpa_get_config_size(v, argp); + break; + case VHOST_VDPA_GET_VQS_COUNT: + r = vhost_vdpa_get_vqs_count(v, argp); + break; + case VHOST_VDPA_SUSPEND: + r = vhost_vdpa_suspend(v); + break; + case VHOST_VDPA_RESUME: + r = vhost_vdpa_resume(v); + break; + case VHOST_GET_DEV_BUFFER_SIZE: + r = vhost_vdpa_get_dev_buffer_size(v, argp); + break; + case VHOST_GET_DEV_BUFFER: + r = vhost_vdpa_get_dev_buffer(v, argp); + break; + case VHOST_SET_DEV_BUFFER: + r = vhost_vdpa_set_dev_buffer(v, argp); + break; + case VHOST_VDPA_SET_MIG_STATE: + r = vhost_vdpa_set_mig_state(v, argp); + break; + default: + r = vhost_dev_ioctl(&v->vdev, cmd, argp); + if (r == -ENOIOCTLCMD) + r = vhost_vdpa_vring_ioctl(v, cmd, argp); + break; + } + + if (r) + goto out; + + switch (cmd) { + case VHOST_SET_OWNER: + r = vhost_vdpa_bind_mm(v); + if (r) + vhost_dev_reset_owner(d, NULL); + break; + } +out: + mutex_unlock(&d->mutex); + return r; +} +static void vhost_vdpa_general_unmap(struct vhost_vdpa *v, + struct vhost_iotlb_map *map, u32 asid) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + if (ops->dma_map) { + ops->dma_unmap(vdpa, asid, map->start, map->size); + } else if (ops->set_map == NULL) { + iommu_unmap(v->domain, map->start, map->size); + } +} + +static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, struct vhost_iotlb *iotlb, + u64 start, u64 last, u32 asid) +{ + struct vhost_dev *dev = &v->vdev; + struct vhost_iotlb_map *map; + struct page *page; + unsigned long pfn, pinned; + + while ((map = vhost_iotlb_itree_first(iotlb, start, last)) != NULL) { + pinned = PFN_DOWN(map->size); + for (pfn = PFN_DOWN(map->addr); + pinned > 0; pfn++, pinned--) { + page = pfn_to_page(pfn); + if (map->perm & VHOST_ACCESS_WO) + set_page_dirty_lock(page); + unpin_user_page(page); + } + atomic64_sub(PFN_DOWN(map->size), &dev->mm->pinned_vm); + vhost_vdpa_general_unmap(v, map, asid); + vhost_iotlb_map_free(iotlb, map); + } +} + +static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, struct vhost_iotlb *iotlb, + u64 start, u64 last, u32 asid) +{ + struct vhost_iotlb_map *map; + struct vdpa_map_file *map_file; + + while ((map = vhost_iotlb_itree_first(iotlb, start, last)) != NULL) { + map_file = (struct vdpa_map_file *)map->opaque; + fput(map_file->file); + kfree(map_file); + vhost_vdpa_general_unmap(v, map, asid); + vhost_iotlb_map_free(iotlb, map); + } +} + +static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, + struct vhost_iotlb *iotlb, u64 start, + u64 last, u32 asid) +{ + struct vdpa_device *vdpa = v->vdpa; + + if (vdpa->use_va) + return vhost_vdpa_va_unmap(v, iotlb, start, last, asid); + + return vhost_vdpa_pa_unmap(v, iotlb, start, last, asid); +} + +static int perm_to_iommu_flags(u32 perm) +{ + int flags = 0; + + switch (perm) { + case VHOST_ACCESS_WO: + flags |= IOMMU_WRITE; + break; + case VHOST_ACCESS_RO: + flags |= IOMMU_READ; + break; + case VHOST_ACCESS_RW: + flags |= (IOMMU_WRITE | IOMMU_READ); + break; + default: + WARN(1, "invalidate vhost IOTLB permission\n"); + break; + } + + return flags | IOMMU_CACHE; +} + +static int vhost_vdpa_map(struct vhost_vdpa *v, struct vhost_iotlb *iotlb, + u64 iova, u64 size, u64 pa, u32 perm, void *opaque) +{ + struct vhost_dev *dev = &v->vdev; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u32 asid = iotlb_to_asid(iotlb); + int r = 0; + + r = vhost_iotlb_add_range_ctx(iotlb, iova, iova + size - 1, + pa, perm, opaque); + if (r) + return r; + + if (ops->dma_map) { + r = ops->dma_map(vdpa, asid, iova, size, pa, perm, opaque); + } else if (ops->set_map) { + if (!v->in_batch) + r = ops->set_map(vdpa, asid, iotlb); + } else { + r = iommu_map(v->domain, iova, pa, size, + perm_to_iommu_flags(perm)); + } + if (r) { + vhost_iotlb_del_range(iotlb, iova, iova + size - 1); + return r; + } + + if (!vdpa->use_va) + atomic64_add(PFN_DOWN(size), &dev->mm->pinned_vm); + + return 0; +} + +static void vhost_vdpa_unmap(struct vhost_vdpa *v, + struct vhost_iotlb *iotlb, + u64 iova, u64 size) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u32 asid = iotlb_to_asid(iotlb); + + vhost_vdpa_iotlb_unmap(v, iotlb, iova, iova + size - 1, asid); + + if (ops->set_map) { + if (!v->in_batch) + ops->set_map(vdpa, asid, iotlb); + } + +} + +static int vhost_vdpa_va_map(struct vhost_vdpa *v, + struct vhost_iotlb *iotlb, + u64 iova, u64 size, u64 uaddr, u32 perm) +{ + struct vhost_dev *dev = &v->vdev; + u64 offset, map_size, map_iova = iova; + struct vdpa_map_file *map_file; + struct vm_area_struct *vma; + int ret = 0; + + mmap_read_lock(dev->mm); + + while (size) { + vma = find_vma(dev->mm, uaddr); + if (!vma) { + ret = -EINVAL; + break; + } + map_size = min(size, vma->vm_end - uaddr); + if (!(vma->vm_file && (vma->vm_flags & VM_SHARED) && + !(vma->vm_flags & (VM_IO | VM_PFNMAP)))) + goto next; + + map_file = kzalloc(sizeof(*map_file), GFP_KERNEL); + if (!map_file) { + ret = -ENOMEM; + break; + } + offset = (vma->vm_pgoff << PAGE_SHIFT) + uaddr - vma->vm_start; + map_file->offset = offset; + map_file->file = get_file(vma->vm_file); + ret = vhost_vdpa_map(v, iotlb, map_iova, map_size, uaddr, + perm, map_file); + if (ret) { + fput(map_file->file); + kfree(map_file); + break; + } +next: + size -= map_size; + uaddr += map_size; + map_iova += map_size; + } + if (ret) + vhost_vdpa_unmap(v, iotlb, iova, map_iova - iova); + + mmap_read_unlock(dev->mm); + + return ret; +} + +static int vhost_vdpa_pa_map(struct vhost_vdpa *v, + struct vhost_iotlb *iotlb, + u64 iova, u64 size, u64 uaddr, u32 perm) +{ + struct vhost_dev *dev = &v->vdev; + struct page **page_list; + unsigned long list_size = PAGE_SIZE / sizeof(struct page *); + unsigned int gup_flags = FOLL_LONGTERM; + unsigned long npages, cur_base, map_pfn, last_pfn = 0; + unsigned long lock_limit, sz2pin, nchunks, i; + u64 start = iova; + long pinned; + int ret = 0; + + /* Limit the use of memory for bookkeeping */ + page_list = (struct page **) __get_free_page(GFP_KERNEL); + if (!page_list) + return -ENOMEM; + + if (perm & VHOST_ACCESS_WO) + gup_flags |= FOLL_WRITE; + + npages = PFN_UP(size + (iova & ~PAGE_MASK)); + if (!npages) { + ret = -EINVAL; + goto free; + } + + mmap_read_lock(dev->mm); + + lock_limit = PFN_DOWN(rlimit(RLIMIT_MEMLOCK)); + if (npages + atomic64_read(&dev->mm->pinned_vm) > lock_limit) { + ret = -ENOMEM; + goto unlock; + } + + cur_base = uaddr & PAGE_MASK; + iova &= PAGE_MASK; + nchunks = 0; + + while (npages) { + sz2pin = min_t(unsigned long, npages, list_size); + pinned = pin_user_pages(cur_base, sz2pin, + gup_flags, page_list, NULL); + if (sz2pin != pinned) { + if (pinned < 0) { + ret = pinned; + } else { + unpin_user_pages(page_list, pinned); + ret = -ENOMEM; + } + goto out; + } + nchunks++; + + if (!last_pfn) + map_pfn = page_to_pfn(page_list[0]); + + for (i = 0; i < pinned; i++) { + unsigned long this_pfn = page_to_pfn(page_list[i]); + u64 csize; + + if (last_pfn && (this_pfn != last_pfn + 1)) { + /* Pin a contiguous chunk of memory */ + csize = PFN_PHYS(last_pfn - map_pfn + 1); + ret = vhost_vdpa_map(v, iotlb, iova, csize, + PFN_PHYS(map_pfn), + perm, NULL); + if (ret) { + /* + * Unpin the pages that are left unmapped + * from this point on in the current + * page_list. The remaining outstanding + * ones which may stride across several + * chunks will be covered in the common + * error path subsequently. + */ + unpin_user_pages(&page_list[i], + pinned - i); + goto out; + } + + map_pfn = this_pfn; + iova += csize; + nchunks = 0; + } + + last_pfn = this_pfn; + } + + cur_base += PFN_PHYS(pinned); + npages -= pinned; + } + + /* Pin the rest chunk */ + ret = vhost_vdpa_map(v, iotlb, iova, PFN_PHYS(last_pfn - map_pfn + 1), + PFN_PHYS(map_pfn), perm, NULL); +out: + if (ret) { + if (nchunks) { + unsigned long pfn; + + /* + * Unpin the outstanding pages which are yet to be + * mapped but haven't due to vdpa_map() or + * pin_user_pages() failure. + * + * Mapped pages are accounted in vdpa_map(), hence + * the corresponding unpinning will be handled by + * vdpa_unmap(). + */ + WARN_ON(!last_pfn); + for (pfn = map_pfn; pfn <= last_pfn; pfn++) + unpin_user_page(pfn_to_page(pfn)); + } + vhost_vdpa_unmap(v, iotlb, start, size); + } +unlock: + mmap_read_unlock(dev->mm); +free: + free_page((unsigned long)page_list); + return ret; + +} + +static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v, + struct vhost_iotlb *iotlb, + struct vhost_iotlb_msg *msg) +{ + struct vdpa_device *vdpa = v->vdpa; + + if (msg->iova < v->range.first || !msg->size || + msg->iova > U64_MAX - msg->size + 1 || + msg->iova + msg->size - 1 > v->range.last) + return -EINVAL; + + if (vhost_iotlb_itree_first(&v->resv_iotlb, msg->iova, + msg->iova + msg->size - 1)) + return -EINVAL; + + if (vhost_iotlb_itree_first(iotlb, msg->iova, + msg->iova + msg->size - 1)) + return -EEXIST; + + if (vdpa->use_va) + return vhost_vdpa_va_map(v, iotlb, msg->iova, msg->size, + msg->uaddr, msg->perm); + + return vhost_vdpa_pa_map(v, iotlb, msg->iova, msg->size, msg->uaddr, + msg->perm); +} + +static int vhost_vdpa_process_iotlb_msg(struct vhost_dev *dev, u32 asid, + struct vhost_iotlb_msg *msg) +{ + struct vhost_vdpa *v = container_of(dev, struct vhost_vdpa, vdev); + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_iotlb *iotlb = NULL; + struct vhost_vdpa_as *as = NULL; + int r = 0; + + mutex_lock(&dev->mutex); + + r = vhost_dev_check_owner(dev); + if (r) + goto unlock; + + if (msg->type == VHOST_IOTLB_UPDATE || + msg->type == VHOST_IOTLB_BATCH_BEGIN) { + as = vhost_vdpa_find_alloc_as(v, asid); + if (!as) { + dev_err(&v->dev, "can't find and alloc asid %d\n", + asid); + r = -EINVAL; + goto unlock; + } + iotlb = &as->iotlb; + } else + iotlb = asid_to_iotlb(v, asid); + + if ((v->in_batch && v->batch_asid != asid) || !iotlb) { + if (v->in_batch && v->batch_asid != asid) { + dev_info(&v->dev, "batch id %d asid %d\n", + v->batch_asid, asid); + } + if (!iotlb) + dev_err(&v->dev, "no iotlb for asid %d\n", asid); + r = -EINVAL; + goto unlock; + } + + switch (msg->type) { + case VHOST_IOTLB_UPDATE: + r = vhost_vdpa_process_iotlb_update(v, iotlb, msg); + break; + case VHOST_IOTLB_INVALIDATE: + vhost_vdpa_unmap(v, iotlb, msg->iova, msg->size); + break; + case VHOST_IOTLB_BATCH_BEGIN: + v->batch_asid = asid; + v->in_batch = true; + break; + case VHOST_IOTLB_BATCH_END: + if (v->in_batch && ops->set_map) + ops->set_map(vdpa, asid, iotlb); + v->in_batch = false; + break; + default: + r = -EINVAL; + break; + } +unlock: + mutex_unlock(&dev->mutex); + + return r; +} + +static ssize_t vhost_vdpa_chr_write_iter(struct kiocb *iocb, + struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct vhost_vdpa *v = file->private_data; + struct vhost_dev *dev = &v->vdev; + + return vhost_chr_write_iter(dev, from); +} + +static int vhost_vdpa_resv_iommu_region(struct iommu_domain *domain, struct device *dma_dev, + struct vhost_iotlb *resv_iotlb) +{ + struct list_head dev_resv_regions; + phys_addr_t resv_msi_base = 0; + struct iommu_resv_region *region; + int ret = 0; + bool with_sw_msi = false; + bool with_hw_msi = false; + + INIT_LIST_HEAD(&dev_resv_regions); + iommu_get_resv_regions(dma_dev, &dev_resv_regions); + + list_for_each_entry(region, &dev_resv_regions, list) { + ret = vhost_iotlb_add_range_ctx(resv_iotlb, region->start, + region->start + region->length - 1, + 0, 0, NULL); + if (ret) { + vhost_iotlb_reset(resv_iotlb); + break; + } + + if (region->type == IOMMU_RESV_MSI) + with_hw_msi = true; + + if (region->type == IOMMU_RESV_SW_MSI) { + resv_msi_base = region->start; + with_sw_msi = true; + } + + } + + if (!ret && !with_hw_msi && with_sw_msi) + ret = iommu_get_msi_cookie(domain, resv_msi_base); + + iommu_put_resv_regions(dma_dev, &dev_resv_regions); + + return ret; +} + +static int vhost_vdpa_alloc_domain(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct device *dma_dev = vdpa_get_dma_dev(vdpa); + struct bus_type *bus; + int ret; + + /* Device want to do DMA by itself */ + if (ops->set_map || ops->dma_map) + return 0; + + bus = dma_dev->bus; + if (!bus) + return -EFAULT; + + if (!iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY)) + return -ENOTSUPP; + + v->domain = iommu_domain_alloc(bus); + if (!v->domain) + return -EIO; + + ret = iommu_attach_device(v->domain, dma_dev); + if (ret) + goto err_alloc_domain; + + ret = vhost_vdpa_resv_iommu_region(v->domain, dma_dev, &v->resv_iotlb); + if (ret) + goto err_attach_device; + + return 0; +err_attach_device: + iommu_detach_device(v->domain, dma_dev); +err_alloc_domain: + iommu_domain_free(v->domain); + v->domain = NULL; + return ret; +} + +static void vhost_vdpa_free_domain(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + struct device *dma_dev = vdpa_get_dma_dev(vdpa); + + if (v->domain) { + iommu_detach_device(v->domain, dma_dev); + iommu_domain_free(v->domain); + } + + v->domain = NULL; +} + +static void vhost_vdpa_set_iova_range(struct vhost_vdpa *v) +{ + struct vdpa_iova_range *range = &v->range; + struct iommu_domain_geometry geo; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (ops->get_iova_range) { + *range = ops->get_iova_range(vdpa); + } else if (v->domain && + !iommu_domain_get_attr(v->domain, + DOMAIN_ATTR_GEOMETRY, &geo) && + geo.force_aperture) { + range->first = geo.aperture_start; + range->last = geo.aperture_end; + } else { + range->first = 0; + range->last = ULLONG_MAX; + } +} + +static void vhost_vdpa_cleanup(struct vhost_vdpa *v) +{ + struct vhost_vdpa_as *as; + u32 asid; + + for (asid = 0; asid < v->vdpa->nas; asid++) { + as = asid_to_as(v, asid); + if (as) + vhost_vdpa_remove_as(v, asid); + } + + vhost_vdpa_free_domain(v); + vhost_dev_cleanup(&v->vdev); + kfree(v->vdev.vqs); +} + +static int vhost_vdpa_open(struct inode *inode, struct file *filep) +{ + struct vhost_vdpa *v; + struct vhost_dev *dev; + struct vhost_virtqueue **vqs; + int r, opened; + u32 i, nvqs; + + v = container_of(inode->i_cdev, struct vhost_vdpa, cdev); + + opened = atomic_cmpxchg(&v->opened, 0, 1); + if (opened) + return -EBUSY; + r = vhost_vdpa_alloc_domain(v); + if (r) + return r; + + dev_info(&v->dev, "vhost vdpa domain alloced\n"); + nvqs = v->nvqs; + r = vhost_vdpa_reset(v, VDPA_DEV_RESET_OPEN); + if (r) + goto err; + + vqs = kmalloc_array(nvqs, sizeof(*vqs), GFP_KERNEL); + if (!vqs) { + r = -ENOMEM; + goto err; + } + + dev = &v->vdev; + for (i = 0; i < nvqs; i++) { + vqs[i] = &v->vqs[i]; + vqs[i]->handle_kick = handle_vq_kick; + } + vhost_dev_init(dev, vqs, nvqs, 0, 0, 0, false, + vhost_vdpa_process_iotlb_msg); + + vhost_vdpa_set_iova_range(v); + + filep->private_data = v; + + return 0; + +err: + vhost_vdpa_free_domain(v); + atomic_dec(&v->opened); + return r; +} + +static void vhost_vdpa_clean_irq(struct vhost_vdpa *v) +{ + u32 i; + + for (i = 0; i < v->nvqs; i++) + vhost_vdpa_unsetup_vq_irq(v, i); +} + +static int vhost_vdpa_release(struct inode *inode, struct file *filep) +{ + struct vhost_vdpa *v = filep->private_data; + struct vhost_dev *d = &v->vdev; + + mutex_lock(&d->mutex); + filep->private_data = NULL; + vhost_vdpa_clean_irq(v); + vhost_vdpa_reset(v, VDPA_DEV_RESET_CLOSE); + vhost_dev_stop(&v->vdev); + vhost_vdpa_unbind_mm(v); + vhost_vdpa_config_put(v); + vhost_vdpa_cleanup(v); + mutex_unlock(&d->mutex); + + atomic_dec(&v->opened); + complete(&v->completion); + + return 0; +} + +#ifdef CONFIG_MMU +static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) +{ + struct vhost_vdpa *v = vmf->vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + struct vm_area_struct *vma = vmf->vma; + u16 index = vma->vm_pgoff; + + notify = ops->get_vq_notification(vdpa, index); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + if (remap_pfn_range(vma, vmf->address & PAGE_MASK, + PFN_DOWN(notify.addr), PAGE_SIZE, + vma->vm_page_prot)) + return VM_FAULT_SIGBUS; + + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct vhost_vdpa_vm_ops = { + .fault = vhost_vdpa_fault, +}; + +static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct vhost_vdpa *v = vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + unsigned long index = vma->vm_pgoff; + + if (vma->vm_end - vma->vm_start != PAGE_SIZE) + return -EINVAL; + if ((vma->vm_flags & VM_SHARED) == 0) + return -EINVAL; + if (vma->vm_flags & VM_READ) + return -EINVAL; + if (index > 65535) + return -EINVAL; + if (!ops->get_vq_notification) + return -ENOTSUPP; + + /* To be safe and easily modelled by userspace, We only + * support the doorbell which sits on the page boundary and + * does not share the page with other registers. + */ + notify = ops->get_vq_notification(vdpa, index); + if (notify.addr & (PAGE_SIZE - 1)) + return -EINVAL; + if (vma->vm_end - vma->vm_start != notify.size) + return -ENOTSUPP; + + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_ops = &vhost_vdpa_vm_ops; + return 0; +} +#endif /* CONFIG_MMU */ + +static const struct file_operations vhost_vdpa_fops = { + .owner = THIS_MODULE, + .open = vhost_vdpa_open, + .release = vhost_vdpa_release, + .write_iter = vhost_vdpa_chr_write_iter, + .unlocked_ioctl = vhost_vdpa_unlocked_ioctl, +#ifdef CONFIG_MMU + .mmap = vhost_vdpa_mmap, +#endif /* CONFIG_MMU */ + .compat_ioctl = compat_ptr_ioctl, +}; + +static void vhost_vdpa_release_dev(struct device *device) +{ + struct vhost_vdpa *v = + container_of(device, struct vhost_vdpa, dev); + + ida_simple_remove(&vhost_vdpa_ida, v->minor); + kfree(v->vqs); + kfree(v); +} + +static int vhost_vdpa_probe(struct vdpa_device *vdpa) +{ + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_vdpa *v; + int minor; + int i, r; + + /* We can't support platform IOMMU device with more than 1 + * group or as + */ + if (!ops->set_map && !ops->dma_map && + (vdpa->ngroups > 1 || vdpa->nas > 1)) + return -EOPNOTSUPP; + + v = kzalloc(sizeof(*v), GFP_KERNEL | __GFP_RETRY_MAYFAIL); + if (!v) + return -ENOMEM; + + minor = ida_simple_get(&vhost_vdpa_ida, 0, + VHOST_VDPA_DEV_MAX, GFP_KERNEL); + if (minor < 0) { + kfree(v); + return minor; + } + + atomic_set(&v->opened, 0); + v->minor = minor; + v->vdpa = vdpa; + v->nvqs = vdpa->nvqs; + v->virtio_id = ops->get_device_id(vdpa); + + device_initialize(&v->dev); + v->dev.release = vhost_vdpa_release_dev; + v->dev.parent = &vdpa->dev; + v->dev.devt = MKDEV(MAJOR(vhost_vdpa_major), minor); + v->vqs = kmalloc_array(v->nvqs, sizeof(struct vhost_virtqueue), + GFP_KERNEL); + if (!v->vqs) { + r = -ENOMEM; + goto err; + } + + vhost_iotlb_init(&v->resv_iotlb, 0, 0); + + r = dev_set_name(&v->dev, "vhost-vdpa-%u", minor); + if (r) + goto err; + + cdev_init(&v->cdev, &vhost_vdpa_fops); + v->cdev.owner = THIS_MODULE; + + r = cdev_device_add(&v->cdev, &v->dev); + if (r) + goto err; + + init_completion(&v->completion); + vdpa_set_drvdata(vdpa, v); + + for (i = 0; i < VHOST_VDPA_IOTLB_BUCKETS; i++) + INIT_HLIST_HEAD(&v->as[i]); + + return 0; + +err: + put_device(&v->dev); + return r; +} + +static void vhost_vdpa_remove(struct vdpa_device *vdpa) +{ + struct vhost_vdpa *v = vdpa_get_drvdata(vdpa); + int opened; + + cdev_device_del(&v->cdev, &v->dev); + + do { + opened = atomic_cmpxchg(&v->opened, 0, 1); + if (!opened) + break; + wait_for_completion(&v->completion); + } while (1); + + put_device(&v->dev); +} + +static struct vdpa_driver vhost_vdpa_driver = { + .driver = { + .name = "vhost_vdpa", + }, + .probe = vhost_vdpa_probe, + .remove = vhost_vdpa_remove, +}; + +static int __init vhost_vdpa_init(void) +{ + int r; + + r = alloc_chrdev_region(&vhost_vdpa_major, 0, VHOST_VDPA_DEV_MAX, + "vhost-vdpa"); + if (r) + goto err_alloc_chrdev; + + r = vdpa_register_driver(&vhost_vdpa_driver); + if (r) + goto err_vdpa_register_driver; + + return 0; + +err_vdpa_register_driver: + unregister_chrdev_region(vhost_vdpa_major, VHOST_VDPA_DEV_MAX); +err_alloc_chrdev: + return r; +} +module_init(vhost_vdpa_init); + +static void __exit vhost_vdpa_exit(void) +{ + vdpa_unregister_driver(&vhost_vdpa_driver); + unregister_chrdev_region(vhost_vdpa_major, VHOST_VDPA_DEV_MAX); +} +module_exit(vhost_vdpa_exit); + +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("vDPA-based vhost backend for virtio"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vhost.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vhost.c new file mode 100644 index 0000000..0e5f59f --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vhost.c @@ -0,0 +1,2670 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * + * Author: Michael S. Tsirkin + * + * Inspiration, some code, and most witty comments come from + * Documentation/virtual/lguest/lguest.c, by Rusty Russell + * + * Generic code for virtio server in host kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vhost.h" + +static ushort max_mem_regions = 64; +module_param(max_mem_regions, ushort, 0444); +MODULE_PARM_DESC(max_mem_regions, + "Maximum number of memory regions in memory map. (default: 64)"); +static int max_iotlb_entries = 2048; +module_param(max_iotlb_entries, int, 0444); +MODULE_PARM_DESC(max_iotlb_entries, + "Maximum number of iotlb entries. (default: 2048)"); + +enum { + VHOST_MEMORY_F_LOG = 0x1, +}; + +#define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num]) +#define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num]) + +#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY +static void vhost_disable_cross_endian(struct vhost_virtqueue *vq) +{ + vq->user_be = !virtio_legacy_is_little_endian(); +} + +static void vhost_enable_cross_endian_big(struct vhost_virtqueue *vq) +{ + vq->user_be = true; +} + +static void vhost_enable_cross_endian_little(struct vhost_virtqueue *vq) +{ + vq->user_be = false; +} + +static long vhost_set_vring_endian(struct vhost_virtqueue *vq, int __user *argp) +{ + struct vhost_vring_state s; + + if (vq->private_data) + return -EBUSY; + + if (copy_from_user(&s, argp, sizeof(s))) + return -EFAULT; + + if (s.num != VHOST_VRING_LITTLE_ENDIAN && + s.num != VHOST_VRING_BIG_ENDIAN) + return -EINVAL; + + if (s.num == VHOST_VRING_BIG_ENDIAN) + vhost_enable_cross_endian_big(vq); + else + vhost_enable_cross_endian_little(vq); + + return 0; +} + +static long vhost_get_vring_endian(struct vhost_virtqueue *vq, u32 idx, + int __user *argp) +{ + struct vhost_vring_state s = { + .index = idx, + .num = vq->user_be + }; + + if (copy_to_user(argp, &s, sizeof(s))) + return -EFAULT; + + return 0; +} + +static void vhost_init_is_le(struct vhost_virtqueue *vq) +{ + /* Note for legacy virtio: user_be is initialized at reset time + * according to the host endianness. If userspace does not set an + * explicit endianness, the default behavior is native endian, as + * expected by legacy virtio. + */ + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be; +} +#else +static void vhost_disable_cross_endian(struct vhost_virtqueue *vq) +{ +} + +static long vhost_set_vring_endian(struct vhost_virtqueue *vq, int __user *argp) +{ + return -ENOIOCTLCMD; +} + +static long vhost_get_vring_endian(struct vhost_virtqueue *vq, u32 idx, + int __user *argp) +{ + return -ENOIOCTLCMD; +} + +static void vhost_init_is_le(struct vhost_virtqueue *vq) +{ + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) + || virtio_legacy_is_little_endian(); +} +#endif /* CONFIG_VHOST_CROSS_ENDIAN_LEGACY */ + +static void vhost_reset_is_le(struct vhost_virtqueue *vq) +{ + vhost_init_is_le(vq); +} + +struct vhost_flush_struct { + struct vhost_work work; + struct completion wait_event; +}; + +static void vhost_flush_work(struct vhost_work *work) +{ + struct vhost_flush_struct *s; + + s = container_of(work, struct vhost_flush_struct, work); + complete(&s->wait_event); +} + +static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh, + poll_table *pt) +{ + struct vhost_poll *poll; + + poll = container_of(pt, struct vhost_poll, table); + poll->wqh = wqh; + add_wait_queue(wqh, &poll->wait); +} + +static int vhost_poll_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, + void *key) +{ + struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait); + struct vhost_work *work = &poll->work; + + if (!(key_to_poll(key) & poll->mask)) + return 0; + + if (!poll->dev->use_worker) + work->fn(work); + else + vhost_poll_queue(poll); + + return 0; +} + +void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn) +{ + clear_bit(VHOST_WORK_QUEUED, &work->flags); + work->fn = fn; +} +EXPORT_SYMBOL_GPL(vhost_work_init); + +/* Init poll structure */ +void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, + __poll_t mask, struct vhost_dev *dev) +{ + init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); + init_poll_funcptr(&poll->table, vhost_poll_func); + poll->mask = mask; + poll->dev = dev; + poll->wqh = NULL; + + vhost_work_init(&poll->work, fn); +} +EXPORT_SYMBOL_GPL(vhost_poll_init); + +/* Start polling a file. We add ourselves to file's wait queue. The caller must + * keep a reference to a file until after vhost_poll_stop is called. */ +int vhost_poll_start(struct vhost_poll *poll, struct file *file) +{ + __poll_t mask; + + if (poll->wqh) + return 0; + + mask = vfs_poll(file, &poll->table); + if (mask) + vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask)); + if (mask & EPOLLERR) { + vhost_poll_stop(poll); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(vhost_poll_start); + +/* Stop polling a file. After this function returns, it becomes safe to drop the + * file reference. You must also flush afterwards. */ +void vhost_poll_stop(struct vhost_poll *poll) +{ + if (poll->wqh) { + remove_wait_queue(poll->wqh, &poll->wait); + poll->wqh = NULL; + } +} +EXPORT_SYMBOL_GPL(vhost_poll_stop); + +void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) +{ + struct vhost_flush_struct flush; + + if (dev->worker) { + init_completion(&flush.wait_event); + vhost_work_init(&flush.work, vhost_flush_work); + + vhost_work_queue(dev, &flush.work); + wait_for_completion(&flush.wait_event); + } +} +EXPORT_SYMBOL_GPL(vhost_work_flush); + +/* Flush any work that has been scheduled. When calling this, don't hold any + * locks that are also used by the callback. */ +void vhost_poll_flush(struct vhost_poll *poll) +{ + vhost_work_flush(poll->dev, &poll->work); +} +EXPORT_SYMBOL_GPL(vhost_poll_flush); + +void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work) +{ + if (!dev->worker) + return; + + if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) { + /* We can only add the work to the list after we're + * sure it was not in the list. + * test_and_set_bit() implies a memory barrier. + */ + llist_add(&work->node, &dev->work_list); + wake_up_process(dev->worker); + } +} +EXPORT_SYMBOL_GPL(vhost_work_queue); + +/* A lockless hint for busy polling code to exit the loop */ +bool vhost_has_work(struct vhost_dev *dev) +{ + return !llist_empty(&dev->work_list); +} +EXPORT_SYMBOL_GPL(vhost_has_work); + +void vhost_poll_queue(struct vhost_poll *poll) +{ + vhost_work_queue(poll->dev, &poll->work); +} +EXPORT_SYMBOL_GPL(vhost_poll_queue); + +static void __vhost_vq_meta_reset(struct vhost_virtqueue *vq) +{ + int j; + + for (j = 0; j < VHOST_NUM_ADDRS; j++) + vq->meta_iotlb[j] = NULL; +} + +static void vhost_vq_meta_reset(struct vhost_dev *d) +{ + int i; + + for (i = 0; i < d->nvqs; ++i) + __vhost_vq_meta_reset(d->vqs[i]); +} + +static void vhost_vring_call_reset(struct vhost_vring_call *call_ctx) +{ + call_ctx->ctx = NULL; + memset(&call_ctx->producer, 0x0, sizeof(struct irq_bypass_producer)); +} + +bool vhost_vq_is_setup(struct vhost_virtqueue *vq) +{ + return vq->avail && vq->desc && vq->used && vhost_vq_access_ok(vq); +} +EXPORT_SYMBOL_GPL(vhost_vq_is_setup); + +static void vhost_vq_reset(struct vhost_dev *dev, + struct vhost_virtqueue *vq) +{ + vq->num = 1; + vq->desc = NULL; + vq->avail = NULL; + vq->used = NULL; + vq->last_avail_idx = 0; + vq->avail_idx = 0; + vq->last_used_idx = 0; + vq->signalled_used = 0; + vq->signalled_used_valid = false; + vq->used_flags = 0; + vq->log_used = false; + vq->log_addr = -1ull; + vq->private_data = NULL; + vq->acked_features = 0; + vq->acked_backend_features = 0; + vq->log_base = NULL; + vq->error_ctx = NULL; + vq->kick = NULL; + vq->log_ctx = NULL; + vhost_disable_cross_endian(vq); + vhost_reset_is_le(vq); + vq->busyloop_timeout = 0; + vq->umem = NULL; + vq->iotlb = NULL; + vhost_vring_call_reset(&vq->call_ctx); + __vhost_vq_meta_reset(vq); +} + +static int vhost_worker(void *data) +{ + struct vhost_dev *dev = data; + struct vhost_work *work, *work_next; + struct llist_node *node; + + kthread_use_mm(dev->mm); + + for (;;) { + /* mb paired w/ kthread_stop */ + set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) { + __set_current_state(TASK_RUNNING); + break; + } + + node = llist_del_all(&dev->work_list); + if (!node) + schedule(); + + node = llist_reverse_order(node); + /* make sure flag is seen after deletion */ + smp_wmb(); + llist_for_each_entry_safe(work, work_next, node, node) { + clear_bit(VHOST_WORK_QUEUED, &work->flags); + __set_current_state(TASK_RUNNING); + kcov_remote_start_common(dev->kcov_handle); + work->fn(work); + kcov_remote_stop(); + if (need_resched()) + schedule(); + } + } + kthread_unuse_mm(dev->mm); + return 0; +} + +static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq) +{ + kfree(vq->indirect); + vq->indirect = NULL; + kfree(vq->log); + vq->log = NULL; + kfree(vq->heads); + vq->heads = NULL; +} + +/* Helper to allocate iovec buffers for all vqs. */ +static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) +{ + struct vhost_virtqueue *vq; + int i; + + for (i = 0; i < dev->nvqs; ++i) { + vq = dev->vqs[i]; + vq->indirect = kmalloc_array(UIO_MAXIOV, + sizeof(*vq->indirect), + GFP_KERNEL); + vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log), + GFP_KERNEL); + vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads), + GFP_KERNEL); + if (!vq->indirect || !vq->log || !vq->heads) + goto err_nomem; + } + return 0; + +err_nomem: + for (; i >= 0; --i) + vhost_vq_free_iovecs(dev->vqs[i]); + return -ENOMEM; +} + +static void vhost_dev_free_iovecs(struct vhost_dev *dev) +{ + int i; + + for (i = 0; i < dev->nvqs; ++i) + vhost_vq_free_iovecs(dev->vqs[i]); +} + +bool vhost_exceeds_weight(struct vhost_virtqueue *vq, + int pkts, int total_len) +{ + struct vhost_dev *dev = vq->dev; + + if ((dev->byte_weight && total_len >= dev->byte_weight) || + pkts >= dev->weight) { + vhost_poll_queue(&vq->poll); + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(vhost_exceeds_weight); + +static size_t vhost_get_avail_size(struct vhost_virtqueue *vq, + unsigned int num) +{ + size_t event __maybe_unused = + vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0; + + return sizeof(*vq->avail) + + sizeof(*vq->avail->ring) * num + event; +} + +static size_t vhost_get_used_size(struct vhost_virtqueue *vq, + unsigned int num) +{ + size_t event __maybe_unused = + vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0; + + return sizeof(*vq->used) + + sizeof(*vq->used->ring) * num + event; +} + +static size_t vhost_get_desc_size(struct vhost_virtqueue *vq, + unsigned int num) +{ + return sizeof(*vq->desc) * num; +} + +void vhost_dev_init(struct vhost_dev *dev, + struct vhost_virtqueue **vqs, int nvqs, + int iov_limit, int weight, int byte_weight, + bool use_worker, + int (*msg_handler)(struct vhost_dev *dev, u32 asid, + struct vhost_iotlb_msg *msg)) +{ + struct vhost_virtqueue *vq; + int i; + + dev->vqs = vqs; + dev->nvqs = nvqs; + mutex_init(&dev->mutex); + dev->log_ctx = NULL; + dev->umem = NULL; + dev->iotlb = NULL; + dev->mm = NULL; + dev->worker = NULL; + dev->iov_limit = iov_limit; + dev->weight = weight; + dev->byte_weight = byte_weight; + dev->use_worker = use_worker; + dev->msg_handler = msg_handler; + init_llist_head(&dev->work_list); + init_waitqueue_head(&dev->wait); + INIT_LIST_HEAD(&dev->read_list); + INIT_LIST_HEAD(&dev->pending_list); + spin_lock_init(&dev->iotlb_lock); + + + for (i = 0; i < dev->nvqs; ++i) { + vq = dev->vqs[i]; + vq->log = NULL; + vq->indirect = NULL; + vq->heads = NULL; + vq->dev = dev; + mutex_init(&vq->mutex); + vhost_vq_reset(dev, vq); + if (vq->handle_kick) + vhost_poll_init(&vq->poll, vq->handle_kick, + EPOLLIN, dev); + } +} +EXPORT_SYMBOL_GPL(vhost_dev_init); + +/* Caller should have device mutex */ +long vhost_dev_check_owner(struct vhost_dev *dev) +{ + /* Are you the owner? If not, I don't think you mean to do that */ + return dev->mm == current->mm ? 0 : -EPERM; +} +EXPORT_SYMBOL_GPL(vhost_dev_check_owner); + +struct vhost_attach_cgroups_struct { + struct vhost_work work; + struct task_struct *owner; + int ret; +}; + +static void vhost_attach_cgroups_work(struct vhost_work *work) +{ + struct vhost_attach_cgroups_struct *s; + + s = container_of(work, struct vhost_attach_cgroups_struct, work); + s->ret = cgroup_attach_task_all(s->owner, current); +} + +static int vhost_attach_cgroups(struct vhost_dev *dev) +{ + struct vhost_attach_cgroups_struct attach; + + attach.owner = current; + vhost_work_init(&attach.work, vhost_attach_cgroups_work); + vhost_work_queue(dev, &attach.work); + vhost_work_flush(dev, &attach.work); + return attach.ret; +} + +/* Caller should have device mutex */ +bool vhost_dev_has_owner(struct vhost_dev *dev) +{ + return dev->mm; +} +EXPORT_SYMBOL_GPL(vhost_dev_has_owner); + +static void vhost_attach_mm(struct vhost_dev *dev) +{ + /* No owner, become one */ + if (dev->use_worker) { + dev->mm = get_task_mm(current); + } else { + /* vDPA device does not use worker thead, so there's + * no need to hold the address space for mm. This help + * to avoid deadlock in the case of mmap() which may + * held the refcnt of the file and depends on release + * method to remove vma. + */ + dev->mm = current->mm; + mmgrab(dev->mm); + } +} + +static void vhost_detach_mm(struct vhost_dev *dev) +{ + if (!dev->mm) + return; + + if (dev->use_worker) + mmput(dev->mm); + else + mmdrop(dev->mm); + + dev->mm = NULL; +} + +/* Caller should have device mutex */ +long vhost_dev_set_owner(struct vhost_dev *dev) +{ + struct task_struct *worker; + int err; + + /* Is there an owner already? */ + if (vhost_dev_has_owner(dev)) { + err = -EBUSY; + goto err_mm; + } + + vhost_attach_mm(dev); + + dev->kcov_handle = kcov_common_handle(); + if (dev->use_worker) { + worker = kthread_create(vhost_worker, dev, + "vhost-%d", current->pid); + if (IS_ERR(worker)) { + err = PTR_ERR(worker); + goto err_worker; + } + + dev->worker = worker; + wake_up_process(worker); /* avoid contributing to loadavg */ + + err = vhost_attach_cgroups(dev); + if (err) + goto err_cgroup; + } + + err = vhost_dev_alloc_iovecs(dev); + if (err) + goto err_cgroup; + + return 0; +err_cgroup: + if (dev->worker) { + kthread_stop(dev->worker); + dev->worker = NULL; + } +err_worker: + vhost_detach_mm(dev); + dev->kcov_handle = 0; +err_mm: + return err; +} +EXPORT_SYMBOL_GPL(vhost_dev_set_owner); + +static struct vhost_iotlb *iotlb_alloc(void) +{ + return vhost_iotlb_alloc(max_iotlb_entries, + VHOST_IOTLB_FLAG_RETIRE); +} + +struct vhost_iotlb *vhost_dev_reset_owner_prepare(void) +{ + return iotlb_alloc(); +} +EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare); + +/* Caller should have device mutex */ +void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_iotlb *umem) +{ + int i; + + vhost_dev_cleanup(dev); + + dev->umem = umem; + /* We don't need VQ locks below since vhost_dev_cleanup makes sure + * VQs aren't running. + */ + for (i = 0; i < dev->nvqs; ++i) + dev->vqs[i]->umem = umem; +} +EXPORT_SYMBOL_GPL(vhost_dev_reset_owner); + +void vhost_dev_stop(struct vhost_dev *dev) +{ + int i; + + for (i = 0; i < dev->nvqs; ++i) { + if (dev->vqs[i]->kick && dev->vqs[i]->handle_kick) { + vhost_poll_stop(&dev->vqs[i]->poll); + vhost_poll_flush(&dev->vqs[i]->poll); + } + } +} +EXPORT_SYMBOL_GPL(vhost_dev_stop); + +static void vhost_clear_msg(struct vhost_dev *dev) +{ + struct vhost_msg_node *node, *n; + + spin_lock(&dev->iotlb_lock); + + list_for_each_entry_safe(node, n, &dev->read_list, node) { + list_del(&node->node); + kfree(node); + } + + list_for_each_entry_safe(node, n, &dev->pending_list, node) { + list_del(&node->node); + kfree(node); + } + + spin_unlock(&dev->iotlb_lock); +} + +void vhost_dev_cleanup(struct vhost_dev *dev) +{ + int i; + + for (i = 0; i < dev->nvqs; ++i) { + if (dev->vqs[i]->error_ctx) + eventfd_ctx_put(dev->vqs[i]->error_ctx); + if (dev->vqs[i]->kick) + fput(dev->vqs[i]->kick); + if (dev->vqs[i]->call_ctx.ctx) + eventfd_ctx_put(dev->vqs[i]->call_ctx.ctx); + vhost_vq_reset(dev, dev->vqs[i]); + } + vhost_dev_free_iovecs(dev); + if (dev->log_ctx) + eventfd_ctx_put(dev->log_ctx); + dev->log_ctx = NULL; + /* No one will access memory at this point */ + vhost_iotlb_free(dev->umem); + dev->umem = NULL; + vhost_iotlb_free(dev->iotlb); + dev->iotlb = NULL; + vhost_clear_msg(dev); + wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); + WARN_ON(!llist_empty(&dev->work_list)); + if (dev->worker) { + kthread_stop(dev->worker); + dev->worker = NULL; + dev->kcov_handle = 0; + } + vhost_detach_mm(dev); +} +EXPORT_SYMBOL_GPL(vhost_dev_cleanup); + +static bool log_access_ok(void __user *log_base, u64 addr, unsigned long sz) +{ + u64 a = addr / VHOST_PAGE_SIZE / 8; + + /* Make sure 64 bit math will not overflow. */ + if (a > ULONG_MAX - (unsigned long)log_base || + a + (unsigned long)log_base > ULONG_MAX) + return false; + + return access_ok(log_base + a, + (sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8); +} + +/* Make sure 64 bit math will not overflow. */ +static bool vhost_overflow(u64 uaddr, u64 size) +{ + if (uaddr > ULONG_MAX || size > ULONG_MAX) + return true; + + if (!size) + return false; + + return uaddr > ULONG_MAX - size + 1; +} + +/* Caller should have vq mutex and device mutex. */ +static bool vq_memory_access_ok(void __user *log_base, struct vhost_iotlb *umem, + int log_all) +{ + struct vhost_iotlb_map *map; + + if (!umem) + return false; + + list_for_each_entry(map, &umem->list, link) { + unsigned long a = map->addr; + + if (vhost_overflow(map->addr, map->size)) + return false; + + + if (!access_ok((void __user *)a, map->size)) + return false; + else if (log_all && !log_access_ok(log_base, + map->start, + map->size)) + return false; + } + return true; +} + +static inline void __user *vhost_vq_meta_fetch(struct vhost_virtqueue *vq, + u64 addr, unsigned int size, + int type) +{ + const struct vhost_iotlb_map *map = vq->meta_iotlb[type]; + + if (!map) + return NULL; + + return (void __user *)(uintptr_t)(map->addr + addr - map->start); +} + +/* Can we switch to this memory table? */ +/* Caller should have device mutex but not vq mutex */ +static bool memory_access_ok(struct vhost_dev *d, struct vhost_iotlb *umem, + int log_all) +{ + int i; + + for (i = 0; i < d->nvqs; ++i) { + bool ok; + bool log; + + mutex_lock(&d->vqs[i]->mutex); + log = log_all || vhost_has_feature(d->vqs[i], VHOST_F_LOG_ALL); + /* If ring is inactive, will check when it's enabled. */ + if (d->vqs[i]->private_data) + ok = vq_memory_access_ok(d->vqs[i]->log_base, + umem, log); + else + ok = true; + mutex_unlock(&d->vqs[i]->mutex); + if (!ok) + return false; + } + return true; +} + +static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, + struct iovec iov[], int iov_size, int access); + +static int vhost_copy_to_user(struct vhost_virtqueue *vq, void __user *to, + const void *from, unsigned size) +{ + int ret; + + if (!vq->iotlb) + return __copy_to_user(to, from, size); + else { + /* This function should be called after iotlb + * prefetch, which means we're sure that all vq + * could be access through iotlb. So -EAGAIN should + * not happen in this case. + */ + struct iov_iter t; + void __user *uaddr = vhost_vq_meta_fetch(vq, + (u64)(uintptr_t)to, size, + VHOST_ADDR_USED); + + if (uaddr) + return __copy_to_user(uaddr, from, size); + + ret = translate_desc(vq, (u64)(uintptr_t)to, size, vq->iotlb_iov, + ARRAY_SIZE(vq->iotlb_iov), + VHOST_ACCESS_WO); + if (ret < 0) + goto out; + iov_iter_init(&t, WRITE, vq->iotlb_iov, ret, size); + ret = copy_to_iter(from, size, &t); + if (ret == size) + ret = 0; + } +out: + return ret; +} + +static int vhost_copy_from_user(struct vhost_virtqueue *vq, void *to, + void __user *from, unsigned size) +{ + int ret; + + if (!vq->iotlb) + return __copy_from_user(to, from, size); + else { + /* This function should be called after iotlb + * prefetch, which means we're sure that vq + * could be access through iotlb. So -EAGAIN should + * not happen in this case. + */ + void __user *uaddr = vhost_vq_meta_fetch(vq, + (u64)(uintptr_t)from, size, + VHOST_ADDR_DESC); + struct iov_iter f; + + if (uaddr) + return __copy_from_user(to, uaddr, size); + + ret = translate_desc(vq, (u64)(uintptr_t)from, size, vq->iotlb_iov, + ARRAY_SIZE(vq->iotlb_iov), + VHOST_ACCESS_RO); + if (ret < 0) { + vq_err(vq, "IOTLB translation failure: uaddr " + "%p size 0x%llx\n", from, + (unsigned long long) size); + goto out; + } + iov_iter_init(&f, READ, vq->iotlb_iov, ret, size); + ret = copy_from_iter(to, size, &f); + if (ret == size) + ret = 0; + } + +out: + return ret; +} + +static void __user *__vhost_get_user_slow(struct vhost_virtqueue *vq, + void __user *addr, unsigned int size, + int type) +{ + int ret; + + ret = translate_desc(vq, (u64)(uintptr_t)addr, size, vq->iotlb_iov, + ARRAY_SIZE(vq->iotlb_iov), + VHOST_ACCESS_RO); + if (ret < 0) { + vq_err(vq, "IOTLB translation failure: uaddr " + "%p size 0x%llx\n", addr, + (unsigned long long) size); + return NULL; + } + + if (ret != 1 || vq->iotlb_iov[0].iov_len != size) { + vq_err(vq, "Non atomic userspace memory access: uaddr " + "%p size 0x%llx\n", addr, + (unsigned long long) size); + return NULL; + } + + return vq->iotlb_iov[0].iov_base; +} + +/* This function should be called after iotlb + * prefetch, which means we're sure that vq + * could be access through iotlb. So -EAGAIN should + * not happen in this case. + */ +static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq, + void __user *addr, unsigned int size, + int type) +{ + void __user *uaddr = vhost_vq_meta_fetch(vq, + (u64)(uintptr_t)addr, size, type); + if (uaddr) + return uaddr; + + return __vhost_get_user_slow(vq, addr, size, type); +} + +#define vhost_put_user(vq, x, ptr) \ +({ \ + int ret; \ + if (!vq->iotlb) { \ + ret = __put_user(x, ptr); \ + } else { \ + __typeof__(ptr) to = \ + (__typeof__(ptr)) __vhost_get_user(vq, ptr, \ + sizeof(*ptr), VHOST_ADDR_USED); \ + if (to != NULL) \ + ret = __put_user(x, to); \ + else \ + ret = -EFAULT; \ + } \ + ret; \ +}) + +static inline int vhost_put_avail_event(struct vhost_virtqueue *vq) +{ + return vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx), + vhost_avail_event(vq)); +} + +static inline int vhost_put_used(struct vhost_virtqueue *vq, + struct vring_used_elem *head, int idx, + int count) +{ + return vhost_copy_to_user(vq, vq->used->ring + idx, head, + count * sizeof(*head)); +} + +static inline int vhost_put_used_flags(struct vhost_virtqueue *vq) + +{ + return vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags), + &vq->used->flags); +} + +static inline int vhost_put_used_idx(struct vhost_virtqueue *vq) + +{ + return vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx), + &vq->used->idx); +} + +#define vhost_get_user(vq, x, ptr, type) \ +({ \ + int ret; \ + if (!vq->iotlb) { \ + ret = __get_user(x, ptr); \ + } else { \ + __typeof__(ptr) from = \ + (__typeof__(ptr)) __vhost_get_user(vq, ptr, \ + sizeof(*ptr), \ + type); \ + if (from != NULL) \ + ret = __get_user(x, from); \ + else \ + ret = -EFAULT; \ + } \ + ret; \ +}) + +#define vhost_get_avail(vq, x, ptr) \ + vhost_get_user(vq, x, ptr, VHOST_ADDR_AVAIL) + +#define vhost_get_used(vq, x, ptr) \ + vhost_get_user(vq, x, ptr, VHOST_ADDR_USED) + +static void vhost_dev_lock_vqs(struct vhost_dev *d) +{ + int i = 0; + for (i = 0; i < d->nvqs; ++i) + mutex_lock_nested(&d->vqs[i]->mutex, i); +} + +static void vhost_dev_unlock_vqs(struct vhost_dev *d) +{ + int i = 0; + for (i = 0; i < d->nvqs; ++i) + mutex_unlock(&d->vqs[i]->mutex); +} + +static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq, + __virtio16 *idx) +{ + return vhost_get_avail(vq, *idx, &vq->avail->idx); +} + +static inline int vhost_get_avail_head(struct vhost_virtqueue *vq, + __virtio16 *head, int idx) +{ + return vhost_get_avail(vq, *head, + &vq->avail->ring[idx & (vq->num - 1)]); +} + +static inline int vhost_get_avail_flags(struct vhost_virtqueue *vq, + __virtio16 *flags) +{ + return vhost_get_avail(vq, *flags, &vq->avail->flags); +} + +static inline int vhost_get_used_event(struct vhost_virtqueue *vq, + __virtio16 *event) +{ + return vhost_get_avail(vq, *event, vhost_used_event(vq)); +} + +static inline int vhost_get_used_idx(struct vhost_virtqueue *vq, + __virtio16 *idx) +{ + return vhost_get_used(vq, *idx, &vq->used->idx); +} + +static inline int vhost_get_desc(struct vhost_virtqueue *vq, + struct vring_desc *desc, int idx) +{ + return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc)); +} + +static void vhost_iotlb_notify_vq(struct vhost_dev *d, + struct vhost_iotlb_msg *msg) +{ + struct vhost_msg_node *node, *n; + + spin_lock(&d->iotlb_lock); + + list_for_each_entry_safe(node, n, &d->pending_list, node) { + struct vhost_iotlb_msg *vq_msg = &node->msg.iotlb; + if (msg->iova <= vq_msg->iova && + msg->iova + msg->size - 1 >= vq_msg->iova && + vq_msg->type == VHOST_IOTLB_MISS) { + vhost_poll_queue(&node->vq->poll); + list_del(&node->node); + kfree(node); + } + } + + spin_unlock(&d->iotlb_lock); +} + +static bool umem_access_ok(u64 uaddr, u64 size, int access) +{ + unsigned long a = uaddr; + + /* Make sure 64 bit math will not overflow. */ + if (vhost_overflow(uaddr, size)) + return false; + + if ((access & VHOST_ACCESS_RO) && + !access_ok((void __user *)a, size)) + return false; + if ((access & VHOST_ACCESS_WO) && + !access_ok((void __user *)a, size)) + return false; + return true; +} + +static int vhost_process_iotlb_msg(struct vhost_dev *dev, u32 asid, + struct vhost_iotlb_msg *msg) +{ + int ret = 0; + + if (asid != 0) + return -EINVAL; + + mutex_lock(&dev->mutex); + vhost_dev_lock_vqs(dev); + switch (msg->type) { + case VHOST_IOTLB_UPDATE: + if (!dev->iotlb) { + ret = -EFAULT; + break; + } + if (!umem_access_ok(msg->uaddr, msg->size, msg->perm)) { + ret = -EFAULT; + break; + } + vhost_vq_meta_reset(dev); + if (vhost_iotlb_add_range(dev->iotlb, msg->iova, + msg->iova + msg->size - 1, + msg->uaddr, msg->perm)) { + ret = -ENOMEM; + break; + } + vhost_iotlb_notify_vq(dev, msg); + break; + case VHOST_IOTLB_INVALIDATE: + if (!dev->iotlb) { + ret = -EFAULT; + break; + } + vhost_vq_meta_reset(dev); + vhost_iotlb_del_range(dev->iotlb, msg->iova, + msg->iova + msg->size - 1); + break; + default: + ret = -EINVAL; + break; + } + + vhost_dev_unlock_vqs(dev); + mutex_unlock(&dev->mutex); + + return ret; +} +ssize_t vhost_chr_write_iter(struct vhost_dev *dev, + struct iov_iter *from) +{ + struct vhost_iotlb_msg msg; + size_t offset; + int type, ret; + u32 asid = 0; + + ret = copy_from_iter(&type, sizeof(type), from); + if (ret != sizeof(type)) { + ret = -EINVAL; + goto done; + } + + switch (type) { + case VHOST_IOTLB_MSG: + /* There maybe a hole after type for V1 message type, + * so skip it here. + */ + offset = offsetof(struct vhost_msg, iotlb) - sizeof(int); + break; + case VHOST_IOTLB_MSG_V2: + if (vhost_backend_has_feature(dev->vqs[0], + VHOST_BACKEND_F_IOTLB_ASID)) { + ret = copy_from_iter(&asid, sizeof(asid), from); + if (ret != sizeof(asid)) { + ret = -EINVAL; + goto done; + } + offset = 0; + } else + offset = sizeof(__u32); + break; + default: + ret = -EINVAL; + goto done; + } + + iov_iter_advance(from, offset); + ret = copy_from_iter(&msg, sizeof(msg), from); + if (ret != sizeof(msg)) { + ret = -EINVAL; + goto done; + } + + if ((msg.type == VHOST_IOTLB_UPDATE || + msg.type == VHOST_IOTLB_INVALIDATE) && + msg.size == 0) { + ret = -EINVAL; + goto done; + } + + if (dev->msg_handler) + ret = dev->msg_handler(dev, asid, &msg); + else + ret = vhost_process_iotlb_msg(dev, asid, &msg); + if (ret) { + ret = -EFAULT; + goto done; + } + + ret = (type == VHOST_IOTLB_MSG) ? sizeof(struct vhost_msg) : + sizeof(struct vhost_msg_v2); +done: + return ret; +} +EXPORT_SYMBOL(vhost_chr_write_iter); + +__poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev, + poll_table *wait) +{ + __poll_t mask = 0; + + poll_wait(file, &dev->wait, wait); + + if (!list_empty(&dev->read_list)) + mask |= EPOLLIN | EPOLLRDNORM; + + return mask; +} +EXPORT_SYMBOL(vhost_chr_poll); + +ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to, + int noblock) +{ + DEFINE_WAIT(wait); + struct vhost_msg_node *node; + ssize_t ret = 0; + unsigned size = sizeof(struct vhost_msg); + + if (iov_iter_count(to) < size) + return 0; + + while (1) { + if (!noblock) + prepare_to_wait(&dev->wait, &wait, + TASK_INTERRUPTIBLE); + + node = vhost_dequeue_msg(dev, &dev->read_list); + if (node) + break; + if (noblock) { + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + if (!dev->iotlb) { + ret = -EBADFD; + break; + } + + schedule(); + } + + if (!noblock) + finish_wait(&dev->wait, &wait); + + if (node) { + struct vhost_iotlb_msg *msg; + void *start = &node->msg; + + switch (node->msg.type) { + case VHOST_IOTLB_MSG: + size = sizeof(node->msg); + msg = &node->msg.iotlb; + break; + case VHOST_IOTLB_MSG_V2: + size = sizeof(node->msg_v2); + msg = &node->msg_v2.iotlb; + break; + default: + BUG(); + break; + } + + ret = copy_to_iter(start, size, to); + if (ret != size || msg->type != VHOST_IOTLB_MISS) { + kfree(node); + return ret; + } + vhost_enqueue_msg(dev, &dev->pending_list, node); + } + + return ret; +} +EXPORT_SYMBOL_GPL(vhost_chr_read_iter); + +static int vhost_iotlb_miss(struct vhost_virtqueue *vq, u64 iova, int access) +{ + struct vhost_dev *dev = vq->dev; + struct vhost_msg_node *node; + struct vhost_iotlb_msg *msg; + bool v2 = vhost_backend_has_feature(vq, VHOST_BACKEND_F_IOTLB_MSG_V2); + + node = vhost_new_msg(vq, v2 ? VHOST_IOTLB_MSG_V2 : VHOST_IOTLB_MSG); + if (!node) + return -ENOMEM; + + if (v2) { + node->msg_v2.type = VHOST_IOTLB_MSG_V2; + msg = &node->msg_v2.iotlb; + } else { + msg = &node->msg.iotlb; + } + + msg->type = VHOST_IOTLB_MISS; + msg->iova = iova; + msg->perm = access; + + vhost_enqueue_msg(dev, &dev->read_list, node); + + return 0; +} + +static bool vq_access_ok(struct vhost_virtqueue *vq, unsigned int num, + vring_desc_t __user *desc, + vring_avail_t __user *avail, + vring_used_t __user *used) + +{ + /* If an IOTLB device is present, the vring addresses are + * GIOVAs. Access validation occurs at prefetch time. */ + if (vq->iotlb) + return true; + + return access_ok(desc, vhost_get_desc_size(vq, num)) && + access_ok(avail, vhost_get_avail_size(vq, num)) && + access_ok(used, vhost_get_used_size(vq, num)); +} + +static void vhost_vq_meta_update(struct vhost_virtqueue *vq, + const struct vhost_iotlb_map *map, + int type) +{ + int access = (type == VHOST_ADDR_USED) ? + VHOST_ACCESS_WO : VHOST_ACCESS_RO; + + if (likely(map->perm & access)) + vq->meta_iotlb[type] = map; +} + +static bool iotlb_access_ok(struct vhost_virtqueue *vq, + int access, u64 addr, u64 len, int type) +{ + const struct vhost_iotlb_map *map; + struct vhost_iotlb *umem = vq->iotlb; + u64 s = 0, size, orig_addr = addr, last = addr + len - 1; + + if (vhost_vq_meta_fetch(vq, addr, len, type)) + return true; + + while (len > s) { + map = vhost_iotlb_itree_first(umem, addr, last); + if (map == NULL || map->start > addr) { + vhost_iotlb_miss(vq, addr, access); + return false; + } else if (!(map->perm & access)) { + /* Report the possible access violation by + * request another translation from userspace. + */ + return false; + } + + size = map->size - addr + map->start; + + if (orig_addr == addr && size >= len) + vhost_vq_meta_update(vq, map, type); + + s += size; + addr += size; + } + + return true; +} + +int vq_meta_prefetch(struct vhost_virtqueue *vq) +{ + unsigned int num = vq->num; + + if (!vq->iotlb) + return 1; + + return iotlb_access_ok(vq, VHOST_MAP_RO, (u64)(uintptr_t)vq->desc, + vhost_get_desc_size(vq, num), VHOST_ADDR_DESC) && + iotlb_access_ok(vq, VHOST_MAP_RO, (u64)(uintptr_t)vq->avail, + vhost_get_avail_size(vq, num), + VHOST_ADDR_AVAIL) && + iotlb_access_ok(vq, VHOST_MAP_WO, (u64)(uintptr_t)vq->used, + vhost_get_used_size(vq, num), VHOST_ADDR_USED); +} +EXPORT_SYMBOL_GPL(vq_meta_prefetch); + +/* Can we log writes? */ +/* Caller should have device mutex but not vq mutex */ +bool vhost_log_access_ok(struct vhost_dev *dev) +{ + return memory_access_ok(dev, dev->umem, 1); +} +EXPORT_SYMBOL_GPL(vhost_log_access_ok); + +static bool vq_log_used_access_ok(struct vhost_virtqueue *vq, + void __user *log_base, + bool log_used, + u64 log_addr) +{ + /* If an IOTLB device is present, log_addr is a GIOVA that + * will never be logged by log_used(). */ + if (vq->iotlb) + return true; + + return !log_used || log_access_ok(log_base, log_addr, + vhost_get_used_size(vq, vq->num)); +} + +/* Verify access for write logging. */ +/* Caller should have vq mutex and device mutex */ +static bool vq_log_access_ok(struct vhost_virtqueue *vq, + void __user *log_base) +{ + return vq_memory_access_ok(log_base, vq->umem, + vhost_has_feature(vq, VHOST_F_LOG_ALL)) && + vq_log_used_access_ok(vq, log_base, vq->log_used, vq->log_addr); +} + +/* Can we start vq? */ +/* Caller should have vq mutex and device mutex */ +bool vhost_vq_access_ok(struct vhost_virtqueue *vq) +{ + if (!vq_log_access_ok(vq, vq->log_base)) + return false; + + return vq_access_ok(vq, vq->num, vq->desc, vq->avail, vq->used); +} +EXPORT_SYMBOL_GPL(vhost_vq_access_ok); + +static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) +{ + struct vhost_memory mem, *newmem; + struct vhost_memory_region *region; + struct vhost_iotlb *newumem, *oldumem; + unsigned long size = offsetof(struct vhost_memory, regions); + int i; + + if (copy_from_user(&mem, m, size)) + return -EFAULT; + if (mem.padding) + return -EOPNOTSUPP; + if (mem.nregions > max_mem_regions) + return -E2BIG; + newmem = kvzalloc(struct_size(newmem, regions, mem.nregions), + GFP_KERNEL); + if (!newmem) + return -ENOMEM; + + memcpy(newmem, &mem, size); + if (copy_from_user(newmem->regions, m->regions, + flex_array_size(newmem, regions, mem.nregions))) { + kvfree(newmem); + return -EFAULT; + } + + newumem = iotlb_alloc(); + if (!newumem) { + kvfree(newmem); + return -ENOMEM; + } + + for (region = newmem->regions; + region < newmem->regions + mem.nregions; + region++) { + if (vhost_iotlb_add_range(newumem, + region->guest_phys_addr, + region->guest_phys_addr + + region->memory_size - 1, + region->userspace_addr, + VHOST_MAP_RW)) + goto err; + } + + if (!memory_access_ok(d, newumem, 0)) + goto err; + + oldumem = d->umem; + d->umem = newumem; + + /* All memory accesses are done under some VQ mutex. */ + for (i = 0; i < d->nvqs; ++i) { + mutex_lock(&d->vqs[i]->mutex); + d->vqs[i]->umem = newumem; + mutex_unlock(&d->vqs[i]->mutex); + } + + kvfree(newmem); + vhost_iotlb_free(oldumem); + return 0; + +err: + vhost_iotlb_free(newumem); + kvfree(newmem); + return -EFAULT; +} + +static long vhost_vring_set_num(struct vhost_dev *d, + struct vhost_virtqueue *vq, + void __user *argp) +{ + struct vhost_vring_state s; + + /* Resizing ring with an active backend? + * You don't want to do that. */ + if (vq->private_data) + return -EBUSY; + + if (copy_from_user(&s, argp, sizeof s)) + return -EFAULT; + + if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) + return -EINVAL; + vq->num = s.num; + + return 0; +} + +static long vhost_vring_set_addr(struct vhost_dev *d, + struct vhost_virtqueue *vq, + void __user *argp) +{ + struct vhost_vring_addr a; + + if (copy_from_user(&a, argp, sizeof a)) + return -EFAULT; + if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) + return -EOPNOTSUPP; + + /* For 32bit, verify that the top 32bits of the user + data are set to zero. */ + if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr || + (u64)(unsigned long)a.used_user_addr != a.used_user_addr || + (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr) + return -EFAULT; + + /* Make sure it's safe to cast pointers to vring types. */ + BUILD_BUG_ON(__alignof__ *vq->avail > VRING_AVAIL_ALIGN_SIZE); + BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE); + if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) || + (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) || + (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1))) + return -EINVAL; + + /* We only verify access here if backend is configured. + * If it is not, we don't as size might not have been setup. + * We will verify when backend is configured. */ + if (vq->private_data) { + if (!vq_access_ok(vq, vq->num, + (void __user *)(unsigned long)a.desc_user_addr, + (void __user *)(unsigned long)a.avail_user_addr, + (void __user *)(unsigned long)a.used_user_addr)) + return -EINVAL; + + /* Also validate log access for used ring if enabled. */ + if (!vq_log_used_access_ok(vq, vq->log_base, + a.flags & (0x1 << VHOST_VRING_F_LOG), + a.log_guest_addr)) + return -EINVAL; + } + + vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG)); + vq->desc = (void __user *)(unsigned long)a.desc_user_addr; + vq->avail = (void __user *)(unsigned long)a.avail_user_addr; + vq->log_addr = a.log_guest_addr; + vq->used = (void __user *)(unsigned long)a.used_user_addr; + + return 0; +} + +static long vhost_vring_set_num_addr(struct vhost_dev *d, + struct vhost_virtqueue *vq, + unsigned int ioctl, + void __user *argp) +{ + long r; + + mutex_lock(&vq->mutex); + + switch (ioctl) { + case VHOST_SET_VRING_NUM: + r = vhost_vring_set_num(d, vq, argp); + break; + case VHOST_SET_VRING_ADDR: + r = vhost_vring_set_addr(d, vq, argp); + break; + default: + BUG(); + } + + mutex_unlock(&vq->mutex); + + return r; +} +long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) +{ + struct file *eventfp, *filep = NULL; + bool pollstart = false, pollstop = false; + struct eventfd_ctx *ctx = NULL; + u32 __user *idxp = argp; + struct vhost_virtqueue *vq; + struct vhost_vring_state s; + struct vhost_vring_file f; + u32 idx; + long r; + + r = get_user(idx, idxp); + if (r < 0) + return r; + if (idx >= d->nvqs) + return -ENOBUFS; + + idx = array_index_nospec(idx, d->nvqs); + vq = d->vqs[idx]; + + if (ioctl == VHOST_SET_VRING_NUM || + ioctl == VHOST_SET_VRING_ADDR) { + return vhost_vring_set_num_addr(d, vq, ioctl, argp); + } + + mutex_lock(&vq->mutex); + + switch (ioctl) { + case VHOST_SET_VRING_BASE: + /* Moving base with an active backend? + * You don't want to do that. */ + if (vq->private_data) { + r = -EBUSY; + break; + } + if (copy_from_user(&s, argp, sizeof s)) { + r = -EFAULT; + break; + } + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) { + vq->last_avail_idx = s.num & 0xffff; + vq->last_used_idx = (s.num >> 16) & 0xffff; + } else { + if (s.num > 0xffff) { + r = -EINVAL; + break; + } + vq->last_avail_idx = s.num; + } + + /* Forget the cached index value. */ + vq->avail_idx = vq->last_avail_idx; + printk("set vring base. avail idx 0x%x used idx 0x%x\n", vq->last_avail_idx, vq->last_used_idx); + break; + case VHOST_GET_VRING_BASE: + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) + s.num = (u32)vq->last_avail_idx | ((u32)vq->last_used_idx << 16); + else + s.num = vq->last_avail_idx; + if (copy_to_user(argp, &s, sizeof s)) + r = -EFAULT; + break; + case VHOST_SET_VRING_KICK: + if (copy_from_user(&f, argp, sizeof f)) { + r = -EFAULT; + break; + } + eventfp = f.fd == VHOST_FILE_UNBIND ? NULL : eventfd_fget(f.fd); + if (IS_ERR(eventfp)) { + r = PTR_ERR(eventfp); + break; + } + if (eventfp != vq->kick) { + pollstop = (filep = vq->kick) != NULL; + pollstart = (vq->kick = eventfp) != NULL; + } else + filep = eventfp; + break; + case VHOST_SET_VRING_CALL: + if (copy_from_user(&f, argp, sizeof f)) { + r = -EFAULT; + break; + } + ctx = f.fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(f.fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); + break; + } + + swap(ctx, vq->call_ctx.ctx); + break; + case VHOST_SET_VRING_ERR: + if (copy_from_user(&f, argp, sizeof f)) { + r = -EFAULT; + break; + } + ctx = f.fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(f.fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); + break; + } + swap(ctx, vq->error_ctx); + break; + case VHOST_SET_VRING_ENDIAN: + r = vhost_set_vring_endian(vq, argp); + break; + case VHOST_GET_VRING_ENDIAN: + r = vhost_get_vring_endian(vq, idx, argp); + break; + case VHOST_SET_VRING_BUSYLOOP_TIMEOUT: + if (copy_from_user(&s, argp, sizeof(s))) { + r = -EFAULT; + break; + } + vq->busyloop_timeout = s.num; + break; + case VHOST_GET_VRING_BUSYLOOP_TIMEOUT: + s.index = idx; + s.num = vq->busyloop_timeout; + if (copy_to_user(argp, &s, sizeof(s))) + r = -EFAULT; + break; + default: + r = -ENOIOCTLCMD; + } + + if (pollstop && vq->handle_kick) + vhost_poll_stop(&vq->poll); + + if (!IS_ERR_OR_NULL(ctx)) + eventfd_ctx_put(ctx); + if (filep) + fput(filep); + + if (pollstart && vq->handle_kick) + r = vhost_poll_start(&vq->poll, vq->kick); + + mutex_unlock(&vq->mutex); + + if (pollstop && vq->handle_kick) + vhost_poll_flush(&vq->poll); + return r; +} +EXPORT_SYMBOL_GPL(vhost_vring_ioctl); + +int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled) +{ + struct vhost_iotlb *niotlb, *oiotlb; + int i; + + niotlb = iotlb_alloc(); + if (!niotlb) + return -ENOMEM; + + oiotlb = d->iotlb; + d->iotlb = niotlb; + + for (i = 0; i < d->nvqs; ++i) { + struct vhost_virtqueue *vq = d->vqs[i]; + + mutex_lock(&vq->mutex); + vq->iotlb = niotlb; + __vhost_vq_meta_reset(vq); + mutex_unlock(&vq->mutex); + } + + vhost_iotlb_free(oiotlb); + + return 0; +} +EXPORT_SYMBOL_GPL(vhost_init_device_iotlb); + +/* Caller must have device mutex */ +long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) +{ + struct eventfd_ctx *ctx; + u64 p; + long r; + int i, fd; + + /* If you are not the owner, you can become one */ + if (ioctl == VHOST_SET_OWNER) { + r = vhost_dev_set_owner(d); + goto done; + } + + /* You must be the owner to do anything else */ + r = vhost_dev_check_owner(d); + if (r) + goto done; + + switch (ioctl) { + case VHOST_SET_MEM_TABLE: + r = vhost_set_memory(d, argp); + break; + case VHOST_SET_LOG_BASE: + if (copy_from_user(&p, argp, sizeof p)) { + r = -EFAULT; + break; + } + if ((u64)(unsigned long)p != p) { + r = -EFAULT; + break; + } + for (i = 0; i < d->nvqs; ++i) { + struct vhost_virtqueue *vq; + void __user *base = (void __user *)(unsigned long)p; + vq = d->vqs[i]; + mutex_lock(&vq->mutex); + /* If ring is inactive, will check when it's enabled. */ + if (vq->private_data && !vq_log_access_ok(vq, base)) + r = -EFAULT; + else + vq->log_base = base; + mutex_unlock(&vq->mutex); + } + break; + case VHOST_SET_LOG_FD: + r = get_user(fd, (int __user *)argp); + if (r < 0) + break; + ctx = fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); + break; + } + swap(ctx, d->log_ctx); + for (i = 0; i < d->nvqs; ++i) { + mutex_lock(&d->vqs[i]->mutex); + d->vqs[i]->log_ctx = d->log_ctx; + mutex_unlock(&d->vqs[i]->mutex); + } + if (ctx) + eventfd_ctx_put(ctx); + break; + default: + r = -ENOIOCTLCMD; + break; + } +done: + return r; +} +EXPORT_SYMBOL_GPL(vhost_dev_ioctl); + +/* TODO: This is really inefficient. We need something like get_user() + * (instruction directly accesses the data, with an exception table entry + * returning -EFAULT). See Documentation/x86/exception-tables.rst. + */ +static int set_bit_to_user(int nr, void __user *addr) +{ + unsigned long log = (unsigned long)addr; + struct page *page; + void *base; + int bit = nr + (log % PAGE_SIZE) * 8; + int r; + + r = pin_user_pages_fast(log, 1, FOLL_WRITE, &page); + if (r < 0) + return r; + BUG_ON(r != 1); + base = kmap_atomic(page); + set_bit(bit, base); + kunmap_atomic(base); + unpin_user_pages_dirty_lock(&page, 1, true); + return 0; +} + +static int log_write(void __user *log_base, + u64 write_address, u64 write_length) +{ + u64 write_page = write_address / VHOST_PAGE_SIZE; + int r; + + if (!write_length) + return 0; + write_length += write_address % VHOST_PAGE_SIZE; + for (;;) { + u64 base = (u64)(unsigned long)log_base; + u64 log = base + write_page / 8; + int bit = write_page % 8; + if ((u64)(unsigned long)log != log) + return -EFAULT; + r = set_bit_to_user(bit, (void __user *)(unsigned long)log); + if (r < 0) + return r; + if (write_length <= VHOST_PAGE_SIZE) + break; + write_length -= VHOST_PAGE_SIZE; + write_page += 1; + } + return r; +} + +static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len) +{ + struct vhost_iotlb *umem = vq->umem; + struct vhost_iotlb_map *u; + u64 start, end, l, min; + int r; + bool hit = false; + + while (len) { + min = len; + /* More than one GPAs can be mapped into a single HVA. So + * iterate all possible umems here to be safe. + */ + list_for_each_entry(u, &umem->list, link) { + if (u->addr > hva - 1 + len || + u->addr - 1 + u->size < hva) + continue; + start = max(u->addr, hva); + end = min(u->addr - 1 + u->size, hva - 1 + len); + l = end - start + 1; + r = log_write(vq->log_base, + u->start + start - u->addr, + l); + if (r < 0) + return r; + hit = true; + min = min(l, min); + } + + if (!hit) + return -EFAULT; + + len -= min; + hva += min; + } + + return 0; +} + +static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len) +{ + struct iovec *iov = vq->log_iov; + int i, ret; + + if (!vq->iotlb) + return log_write(vq->log_base, vq->log_addr + used_offset, len); + + ret = translate_desc(vq, (uintptr_t)vq->used + used_offset, + len, iov, 64, VHOST_ACCESS_WO); + if (ret < 0) + return ret; + + for (i = 0; i < ret; i++) { + ret = log_write_hva(vq, (uintptr_t)iov[i].iov_base, + iov[i].iov_len); + if (ret) + return ret; + } + + return 0; +} + +int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, + unsigned int log_num, u64 len, struct iovec *iov, int count) +{ + int i, r; + + /* Make sure data written is seen before log. */ + smp_wmb(); + + if (vq->iotlb) { + for (i = 0; i < count; i++) { + r = log_write_hva(vq, (uintptr_t)iov[i].iov_base, + iov[i].iov_len); + if (r < 0) + return r; + } + return 0; + } + + for (i = 0; i < log_num; ++i) { + u64 l = min(log[i].len, len); + r = log_write(vq->log_base, log[i].addr, l); + if (r < 0) + return r; + len -= l; + if (!len) { + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + return 0; + } + } + /* Length written exceeds what we have stored. This is a bug. */ + BUG(); + return 0; +} +EXPORT_SYMBOL_GPL(vhost_log_write); + +static int vhost_update_used_flags(struct vhost_virtqueue *vq) +{ + void __user *used; + if (vhost_put_used_flags(vq)) + return -EFAULT; + if (unlikely(vq->log_used)) { + /* Make sure the flag is seen before log. */ + smp_wmb(); + /* Log used flag write. */ + used = &vq->used->flags; + log_used(vq, (used - (void __user *)vq->used), + sizeof vq->used->flags); + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + } + return 0; +} + +static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event) +{ + if (vhost_put_avail_event(vq)) + return -EFAULT; + if (unlikely(vq->log_used)) { + void __user *used; + /* Make sure the event is seen before log. */ + smp_wmb(); + /* Log avail event write */ + used = vhost_avail_event(vq); + log_used(vq, (used - (void __user *)vq->used), + sizeof *vhost_avail_event(vq)); + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + } + return 0; +} + +int vhost_vq_init_access(struct vhost_virtqueue *vq) +{ + __virtio16 last_used_idx; + int r; + bool is_le = vq->is_le; + + if (!vq->private_data) + return 0; + + vhost_init_is_le(vq); + + r = vhost_update_used_flags(vq); + if (r) + goto err; + vq->signalled_used_valid = false; + if (!vq->iotlb && + !access_ok(&vq->used->idx, sizeof vq->used->idx)) { + r = -EFAULT; + goto err; + } + r = vhost_get_used_idx(vq, &last_used_idx); + if (r) { + vq_err(vq, "Can't access used idx at %p\n", + &vq->used->idx); + goto err; + } + vq->last_used_idx = vhost16_to_cpu(vq, last_used_idx); + return 0; + +err: + vq->is_le = is_le; + return r; +} +EXPORT_SYMBOL_GPL(vhost_vq_init_access); + +static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, + struct iovec iov[], int iov_size, int access) +{ + const struct vhost_iotlb_map *map; + struct vhost_dev *dev = vq->dev; + struct vhost_iotlb *umem = dev->iotlb ? dev->iotlb : dev->umem; + struct iovec *_iov; + u64 s = 0; + int ret = 0; + + while ((u64)len > s) { + u64 size; + if (unlikely(ret >= iov_size)) { + ret = -ENOBUFS; + break; + } + + map = vhost_iotlb_itree_first(umem, addr, addr + len - 1); + if (map == NULL || map->start > addr) { + if (umem != dev->iotlb) { + ret = -EFAULT; + break; + } + ret = -EAGAIN; + break; + } else if (!(map->perm & access)) { + ret = -EPERM; + break; + } + + _iov = iov + ret; + size = map->size - addr + map->start; + _iov->iov_len = min((u64)len - s, size); + _iov->iov_base = (void __user *)(unsigned long) + (map->addr + addr - map->start); + s += size; + addr += size; + ++ret; + } + + if (ret == -EAGAIN) + vhost_iotlb_miss(vq, addr, access); + return ret; +} + +/* Each buffer in the virtqueues is actually a chain of descriptors. This + * function returns the next descriptor in the chain, + * or -1U if we're at the end. */ +static unsigned next_desc(struct vhost_virtqueue *vq, struct vring_desc *desc) +{ + unsigned int next; + + /* If this descriptor says it doesn't chain, we're done. */ + if (!(desc->flags & cpu_to_vhost16(vq, VRING_DESC_F_NEXT))) + return -1U; + + /* Check they're not leading us off end of descriptors. */ + next = vhost16_to_cpu(vq, READ_ONCE(desc->next)); + return next; +} + +static int get_indirect(struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num, + struct vring_desc *indirect) +{ + struct vring_desc desc; + unsigned int i = 0, count, found = 0; + u32 len = vhost32_to_cpu(vq, indirect->len); + struct iov_iter from; + int ret, access; + + /* Sanity check */ + if (unlikely(len % sizeof desc)) { + vq_err(vq, "Invalid length in indirect descriptor: " + "len 0x%llx not multiple of 0x%zx\n", + (unsigned long long)len, + sizeof desc); + return -EINVAL; + } + + ret = translate_desc(vq, vhost64_to_cpu(vq, indirect->addr), len, vq->indirect, + UIO_MAXIOV, VHOST_ACCESS_RO); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Translation failure %d in indirect.\n", ret); + return ret; + } + iov_iter_init(&from, READ, vq->indirect, ret, len); + count = len / sizeof desc; + /* Buffers are chained via a 16 bit next field, so + * we can have at most 2^16 of these. */ + if (unlikely(count > USHRT_MAX + 1)) { + vq_err(vq, "Indirect buffer length too big: %d\n", + indirect->len); + return -E2BIG; + } + + do { + unsigned iov_count = *in_num + *out_num; + if (unlikely(++found > count)) { + vq_err(vq, "Loop detected: last one at %u " + "indirect size %u\n", + i, count); + return -EINVAL; + } + if (unlikely(!copy_from_iter_full(&desc, sizeof(desc), &from))) { + vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", + i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc); + return -EINVAL; + } + if (unlikely(desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_INDIRECT))) { + vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n", + i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc); + return -EINVAL; + } + + if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) + access = VHOST_ACCESS_WO; + else + access = VHOST_ACCESS_RO; + + ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr), + vhost32_to_cpu(vq, desc.len), iov + iov_count, + iov_size - iov_count, access); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Translation failure %d indirect idx %d\n", + ret, i); + return ret; + } + /* If this is an input descriptor, increment that count. */ + if (access == VHOST_ACCESS_WO) { + *in_num += ret; + if (unlikely(log && ret)) { + log[*log_num].addr = vhost64_to_cpu(vq, desc.addr); + log[*log_num].len = vhost32_to_cpu(vq, desc.len); + ++*log_num; + } + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (unlikely(*in_num)) { + vq_err(vq, "Indirect descriptor " + "has out after in: idx %d\n", i); + return -EINVAL; + } + *out_num += ret; + } + } while ((i = next_desc(vq, &desc)) != -1); + return 0; +} + +/* This looks in the virtqueue and for the first available buffer, and converts + * it to an iovec for convenient access. Since descriptors consist of some + * number of output then some number of input descriptors, it's actually two + * iovecs, but we pack them into one and note how many of each there were. + * + * This function returns the descriptor number found, or vq->num (which is + * never a valid descriptor number) if none was found. A negative code is + * returned on error. */ +int vhost_get_vq_desc(struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num) +{ + struct vring_desc desc; + unsigned int i, head, found = 0; + u16 last_avail_idx; + __virtio16 avail_idx; + __virtio16 ring_head; + int ret, access; + + /* Check it isn't doing very strange things with descriptor numbers. */ + last_avail_idx = vq->last_avail_idx; + + if (vq->avail_idx == vq->last_avail_idx) { + if (unlikely(vhost_get_avail_idx(vq, &avail_idx))) { + vq_err(vq, "Failed to access avail idx at %p\n", + &vq->avail->idx); + return -EFAULT; + } + vq->avail_idx = vhost16_to_cpu(vq, avail_idx); + + if (unlikely((u16)(vq->avail_idx - last_avail_idx) > vq->num)) { + vq_err(vq, "Guest moved used index from %u to %u", + last_avail_idx, vq->avail_idx); + return -EFAULT; + } + + /* If there's nothing new since last we looked, return + * invalid. + */ + if (vq->avail_idx == last_avail_idx) + return vq->num; + + /* Only get avail ring entries after they have been + * exposed by guest. + */ + smp_rmb(); + } + + /* Grab the next descriptor number they're advertising, and increment + * the index we've seen. */ + if (unlikely(vhost_get_avail_head(vq, &ring_head, last_avail_idx))) { + vq_err(vq, "Failed to read head: idx %d address %p\n", + last_avail_idx, + &vq->avail->ring[last_avail_idx % vq->num]); + return -EFAULT; + } + + head = vhost16_to_cpu(vq, ring_head); + + /* If their number is silly, that's an error. */ + if (unlikely(head >= vq->num)) { + vq_err(vq, "Guest says index %u > %u is available", + head, vq->num); + return -EINVAL; + } + + /* When we start there are none of either input nor output. */ + *out_num = *in_num = 0; + if (unlikely(log)) + *log_num = 0; + + i = head; + do { + unsigned iov_count = *in_num + *out_num; + if (unlikely(i >= vq->num)) { + vq_err(vq, "Desc index is %u > %u, head = %u", + i, vq->num, head); + return -EINVAL; + } + if (unlikely(++found > vq->num)) { + vq_err(vq, "Loop detected: last one at %u " + "vq size %u head %u\n", + i, vq->num, head); + return -EINVAL; + } + ret = vhost_get_desc(vq, &desc, i); + if (unlikely(ret)) { + vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", + i, vq->desc + i); + return -EFAULT; + } + if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_INDIRECT)) { + ret = get_indirect(vq, iov, iov_size, + out_num, in_num, + log, log_num, &desc); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Failure detected " + "in indirect descriptor at idx %d\n", i); + return ret; + } + continue; + } + + if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) + access = VHOST_ACCESS_WO; + else + access = VHOST_ACCESS_RO; + ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr), + vhost32_to_cpu(vq, desc.len), iov + iov_count, + iov_size - iov_count, access); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Translation failure %d descriptor idx %d\n", + ret, i); + return ret; + } + if (access == VHOST_ACCESS_WO) { + /* If this is an input descriptor, + * increment that count. */ + *in_num += ret; + if (unlikely(log && ret)) { + log[*log_num].addr = vhost64_to_cpu(vq, desc.addr); + log[*log_num].len = vhost32_to_cpu(vq, desc.len); + ++*log_num; + } + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (unlikely(*in_num)) { + vq_err(vq, "Descriptor has out after in: " + "idx %d\n", i); + return -EINVAL; + } + *out_num += ret; + } + } while ((i = next_desc(vq, &desc)) != -1); + + /* On success, increment avail index. */ + vq->last_avail_idx++; + + /* Assume notifications from guest are disabled at this point, + * if they aren't we would need to update avail_event index. */ + BUG_ON(!(vq->used_flags & VRING_USED_F_NO_NOTIFY)); + return head; +} +EXPORT_SYMBOL_GPL(vhost_get_vq_desc); + +/* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */ +void vhost_discard_vq_desc(struct vhost_virtqueue *vq, int n) +{ + vq->last_avail_idx -= n; +} +EXPORT_SYMBOL_GPL(vhost_discard_vq_desc); + +/* After we've used one of their buffers, we tell them about it. We'll then + * want to notify the guest, using eventfd. */ +int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) +{ + struct vring_used_elem heads = { + cpu_to_vhost32(vq, head), + cpu_to_vhost32(vq, len) + }; + + return vhost_add_used_n(vq, &heads, 1); +} +EXPORT_SYMBOL_GPL(vhost_add_used); + +static int __vhost_add_used_n(struct vhost_virtqueue *vq, + struct vring_used_elem *heads, + unsigned count) +{ + vring_used_elem_t __user *used; + u16 old, new; + int start; + + start = vq->last_used_idx & (vq->num - 1); + used = vq->used->ring + start; + if (vhost_put_used(vq, heads, start, count)) { + vq_err(vq, "Failed to write used"); + return -EFAULT; + } + if (unlikely(vq->log_used)) { + /* Make sure data is seen before log. */ + smp_wmb(); + /* Log used ring entry write. */ + log_used(vq, ((void __user *)used - (void __user *)vq->used), + count * sizeof *used); + } + old = vq->last_used_idx; + new = (vq->last_used_idx += count); + /* If the driver never bothers to signal in a very long while, + * used index might wrap around. If that happens, invalidate + * signalled_used index we stored. TODO: make sure driver + * signals at least once in 2^16 and remove this. */ + if (unlikely((u16)(new - vq->signalled_used) < (u16)(new - old))) + vq->signalled_used_valid = false; + return 0; +} + +/* After we've used one of their buffers, we tell them about it. We'll then + * want to notify the guest, using eventfd. */ +int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, + unsigned count) +{ + int start, n, r; + + start = vq->last_used_idx & (vq->num - 1); + n = vq->num - start; + if (n < count) { + r = __vhost_add_used_n(vq, heads, n); + if (r < 0) + return r; + heads += n; + count -= n; + } + r = __vhost_add_used_n(vq, heads, count); + + /* Make sure buffer is written before we update index. */ + smp_wmb(); + if (vhost_put_used_idx(vq)) { + vq_err(vq, "Failed to increment used idx"); + return -EFAULT; + } + if (unlikely(vq->log_used)) { + /* Make sure used idx is seen before log. */ + smp_wmb(); + /* Log used index update. */ + log_used(vq, offsetof(struct vring_used, idx), + sizeof vq->used->idx); + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + } + return r; +} +EXPORT_SYMBOL_GPL(vhost_add_used_n); + +static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + __u16 old, new; + __virtio16 event; + bool v; + /* Flush out used index updates. This is paired + * with the barrier that the Guest executes when enabling + * interrupts. */ + smp_mb(); + + if (vhost_has_feature(vq, VIRTIO_F_NOTIFY_ON_EMPTY) && + unlikely(vq->avail_idx == vq->last_avail_idx)) + return true; + + if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) { + __virtio16 flags; + if (vhost_get_avail_flags(vq, &flags)) { + vq_err(vq, "Failed to get flags"); + return true; + } + return !(flags & cpu_to_vhost16(vq, VRING_AVAIL_F_NO_INTERRUPT)); + } + old = vq->signalled_used; + v = vq->signalled_used_valid; + new = vq->signalled_used = vq->last_used_idx; + vq->signalled_used_valid = true; + + if (unlikely(!v)) + return true; + + if (vhost_get_used_event(vq, &event)) { + vq_err(vq, "Failed to get used event idx"); + return true; + } + return vring_need_event(vhost16_to_cpu(vq, event), new, old); +} + +/* This actually signals the guest, using eventfd. */ +void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + /* Signal the Guest tell them we used something up. */ + if (vq->call_ctx.ctx && vhost_notify(dev, vq)) + eventfd_signal(vq->call_ctx.ctx, 1); +} +EXPORT_SYMBOL_GPL(vhost_signal); + +/* And here's the combo meal deal. Supersize me! */ +void vhost_add_used_and_signal(struct vhost_dev *dev, + struct vhost_virtqueue *vq, + unsigned int head, int len) +{ + vhost_add_used(vq, head, len); + vhost_signal(dev, vq); +} +EXPORT_SYMBOL_GPL(vhost_add_used_and_signal); + +/* multi-buffer version of vhost_add_used_and_signal */ +void vhost_add_used_and_signal_n(struct vhost_dev *dev, + struct vhost_virtqueue *vq, + struct vring_used_elem *heads, unsigned count) +{ + vhost_add_used_n(vq, heads, count); + vhost_signal(dev, vq); +} +EXPORT_SYMBOL_GPL(vhost_add_used_and_signal_n); + +/* return true if we're sure that avaiable ring is empty */ +bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + __virtio16 avail_idx; + int r; + + if (vq->avail_idx != vq->last_avail_idx) + return false; + + r = vhost_get_avail_idx(vq, &avail_idx); + if (unlikely(r)) + return false; + vq->avail_idx = vhost16_to_cpu(vq, avail_idx); + + return vq->avail_idx == vq->last_avail_idx; +} +EXPORT_SYMBOL_GPL(vhost_vq_avail_empty); + +/* OK, now we need to know about added descriptors. */ +bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + __virtio16 avail_idx; + int r; + + if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY)) + return false; + vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; + if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) { + r = vhost_update_used_flags(vq); + if (r) { + vq_err(vq, "Failed to enable notification at %p: %d\n", + &vq->used->flags, r); + return false; + } + } else { + r = vhost_update_avail_event(vq, vq->avail_idx); + if (r) { + vq_err(vq, "Failed to update avail event index at %p: %d\n", + vhost_avail_event(vq), r); + return false; + } + } + /* They could have slipped one in as we were doing that: make + * sure it's written, then check again. */ + smp_mb(); + r = vhost_get_avail_idx(vq, &avail_idx); + if (r) { + vq_err(vq, "Failed to check avail idx at %p: %d\n", + &vq->avail->idx, r); + return false; + } + + return vhost16_to_cpu(vq, avail_idx) != vq->avail_idx; +} +EXPORT_SYMBOL_GPL(vhost_enable_notify); + +/* We don't need to be notified again. */ +void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + int r; + + if (vq->used_flags & VRING_USED_F_NO_NOTIFY) + return; + vq->used_flags |= VRING_USED_F_NO_NOTIFY; + if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) { + r = vhost_update_used_flags(vq); + if (r) + vq_err(vq, "Failed to disable notification at %p: %d\n", + &vq->used->flags, r); + } +} +EXPORT_SYMBOL_GPL(vhost_disable_notify); + +/* Create a new message. */ +struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type) +{ + /* Make sure all padding within the structure is initialized. */ + struct vhost_msg_node *node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return NULL; + + node->vq = vq; + node->msg.type = type; + return node; +} +EXPORT_SYMBOL_GPL(vhost_new_msg); + +void vhost_enqueue_msg(struct vhost_dev *dev, struct list_head *head, + struct vhost_msg_node *node) +{ + spin_lock(&dev->iotlb_lock); + list_add_tail(&node->node, head); + spin_unlock(&dev->iotlb_lock); + + wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); +} +EXPORT_SYMBOL_GPL(vhost_enqueue_msg); + +struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev, + struct list_head *head) +{ + struct vhost_msg_node *node = NULL; + + spin_lock(&dev->iotlb_lock); + if (!list_empty(head)) { + node = list_first_entry(head, struct vhost_msg_node, + node); + list_del(&node->node); + } + spin_unlock(&dev->iotlb_lock); + + return node; +} +EXPORT_SYMBOL_GPL(vhost_dequeue_msg); + +void vhost_set_backend_features(struct vhost_dev *dev, u64 features) +{ + struct vhost_virtqueue *vq; + int i; + + mutex_lock(&dev->mutex); + for (i = 0; i < dev->nvqs; ++i) { + vq = dev->vqs[i]; + mutex_lock(&vq->mutex); + vq->acked_backend_features = features; + mutex_unlock(&vq->mutex); + } + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(vhost_set_backend_features); + +static int __init vhost_init(void) +{ + return 0; +} + +static void __exit vhost_exit(void) +{ +} + +module_init(vhost_init); +module_exit(vhost_exit); + +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael S. Tsirkin"); +MODULE_DESCRIPTION("Host kernel accelerator for virtio"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vhost.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vhost.h new file mode 100644 index 0000000..19753a9 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.0-136.12.oe2203sp1/vhost/vhost.h @@ -0,0 +1,325 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _VHOST_H +#define _VHOST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct vhost_work; +typedef void (*vhost_work_fn_t)(struct vhost_work *work); + +#define VHOST_WORK_QUEUED 1 +struct vhost_work { + struct llist_node node; + vhost_work_fn_t fn; + unsigned long flags; +}; + +/* Poll a file (eventfd or socket) */ +/* Note: there's nothing vhost specific about this structure. */ +struct vhost_poll { + poll_table table; + wait_queue_head_t *wqh; + wait_queue_entry_t wait; + struct vhost_work work; + __poll_t mask; + struct vhost_dev *dev; +}; + +void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn); +void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work); +bool vhost_has_work(struct vhost_dev *dev); + +void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, + __poll_t mask, struct vhost_dev *dev); +int vhost_poll_start(struct vhost_poll *poll, struct file *file); +void vhost_poll_stop(struct vhost_poll *poll); +void vhost_poll_flush(struct vhost_poll *poll); +void vhost_poll_queue(struct vhost_poll *poll); +void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work); +long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp); + +struct vhost_log { + u64 addr; + u64 len; +}; + +enum vhost_uaddr_type { + VHOST_ADDR_DESC = 0, + VHOST_ADDR_AVAIL = 1, + VHOST_ADDR_USED = 2, + VHOST_NUM_ADDRS = 3, +}; + +struct vhost_vring_call { + struct eventfd_ctx *ctx; + struct irq_bypass_producer producer; +}; + +/* The virtqueue structure describes a queue attached to a device. */ +struct vhost_virtqueue { + struct vhost_dev *dev; + + /* The actual ring of buffers. */ + struct mutex mutex; + unsigned int num; + vring_desc_t __user *desc; + vring_avail_t __user *avail; + vring_used_t __user *used; + const struct vhost_iotlb_map *meta_iotlb[VHOST_NUM_ADDRS]; + struct file *kick; + struct vhost_vring_call call_ctx; + struct eventfd_ctx *error_ctx; + struct eventfd_ctx *log_ctx; + + struct vhost_poll poll; + + /* The routine to call when the Guest pings us, or timeout. */ + vhost_work_fn_t handle_kick; + + /* Last available index we saw. */ + u16 last_avail_idx; + + /* Caches available index value from user. */ + u16 avail_idx; + + /* Last index we used. */ + u16 last_used_idx; + + /* Used flags */ + u16 used_flags; + + /* Last used index value we have signalled on */ + u16 signalled_used; + + /* Last used index value we have signalled on */ + bool signalled_used_valid; + + /* Log writes to used structure. */ + bool log_used; + u64 log_addr; + + struct iovec iov[UIO_MAXIOV]; + struct iovec iotlb_iov[64]; + struct iovec *indirect; + struct vring_used_elem *heads; + /* Protected by virtqueue mutex. */ + struct vhost_iotlb *umem; + struct vhost_iotlb *iotlb; + void *private_data; + u64 acked_features; + u64 acked_backend_features; + /* Log write descriptors */ + void __user *log_base; + struct vhost_log *log; + struct iovec log_iov[64]; + + /* Ring endianness. Defaults to legacy native endianness. + * Set to true when starting a modern virtio device. */ + bool is_le; +#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY + /* Ring endianness requested by userspace for cross-endian support. */ + bool user_be; +#endif + u32 busyloop_timeout; +}; + +struct vhost_msg_node { + union { + struct vhost_msg msg; + struct vhost_msg_v2 msg_v2; + }; + struct vhost_virtqueue *vq; + struct list_head node; +}; + +struct vhost_dev { + struct mm_struct *mm; + struct mutex mutex; + struct vhost_virtqueue **vqs; + int nvqs; + struct eventfd_ctx *log_ctx; + struct llist_head work_list; + struct task_struct *worker; + struct vhost_iotlb *umem; + struct vhost_iotlb *iotlb; + spinlock_t iotlb_lock; + struct list_head read_list; + struct list_head pending_list; + wait_queue_head_t wait; + int iov_limit; + int weight; + int byte_weight; + u64 kcov_handle; + bool use_worker; + int (*msg_handler)(struct vhost_dev *dev, u32 asid, + struct vhost_iotlb_msg *msg); +}; + +bool vhost_exceeds_weight(struct vhost_virtqueue *vq, int pkts, int total_len); +void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, + int nvqs, int iov_limit, int weight, int byte_weight, + bool use_worker, + int (*msg_handler)(struct vhost_dev *dev, u32 asid, + struct vhost_iotlb_msg *msg)); +long vhost_dev_set_owner(struct vhost_dev *dev); +bool vhost_dev_has_owner(struct vhost_dev *dev); +long vhost_dev_check_owner(struct vhost_dev *); +struct vhost_iotlb *vhost_dev_reset_owner_prepare(void); +void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_iotlb *iotlb); +void vhost_dev_cleanup(struct vhost_dev *); +void vhost_dev_stop(struct vhost_dev *); +long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp); +long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp); +bool vhost_vq_access_ok(struct vhost_virtqueue *vq); +bool vhost_log_access_ok(struct vhost_dev *); + +int vhost_get_vq_desc(struct vhost_virtqueue *, + struct iovec iov[], unsigned int iov_count, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num); +void vhost_discard_vq_desc(struct vhost_virtqueue *, int n); + +bool vhost_vq_is_setup(struct vhost_virtqueue *vq); +int vhost_vq_init_access(struct vhost_virtqueue *); +int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); +int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads, + unsigned count); +void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *, + unsigned int id, int len); +void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *, + struct vring_used_elem *heads, unsigned count); +void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *); +void vhost_disable_notify(struct vhost_dev *, struct vhost_virtqueue *); +bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *); +bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *); + +int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, + unsigned int log_num, u64 len, + struct iovec *iov, int count); +int vq_meta_prefetch(struct vhost_virtqueue *vq); + +struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type); +void vhost_enqueue_msg(struct vhost_dev *dev, + struct list_head *head, + struct vhost_msg_node *node); +struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev, + struct list_head *head); +void vhost_set_backend_features(struct vhost_dev *dev, u64 features); + +__poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev, + poll_table *wait); +ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to, + int noblock); +ssize_t vhost_chr_write_iter(struct vhost_dev *dev, + struct iov_iter *from); +int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled); + +void vhost_iotlb_map_free(struct vhost_iotlb *iotlb, + struct vhost_iotlb_map *map); + +#define vq_err(vq, fmt, ...) do { \ + pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \ + if ((vq)->error_ctx) \ + eventfd_signal((vq)->error_ctx, 1);\ + } while (0) + +enum { + VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | + (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | + (1ULL << VIRTIO_RING_F_EVENT_IDX) | + (1ULL << VHOST_F_LOG_ALL) | + (1ULL << VIRTIO_F_ANY_LAYOUT) | + (1ULL << VIRTIO_F_VERSION_1) +}; + +/** + * vhost_vq_set_backend - Set backend. + * + * @vq Virtqueue. + * @private_data The private data. + * + * Context: Need to call with vq->mutex acquired. + */ +static inline void vhost_vq_set_backend(struct vhost_virtqueue *vq, + void *private_data) +{ + vq->private_data = private_data; +} + +/** + * vhost_vq_get_backend - Get backend. + * + * @vq Virtqueue. + * + * Context: Need to call with vq->mutex acquired. + * Return: Private data previously set with vhost_vq_set_backend. + */ +static inline void *vhost_vq_get_backend(struct vhost_virtqueue *vq) +{ + return vq->private_data; +} + +static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit) +{ + return vq->acked_features & (1ULL << bit); +} + +static inline bool vhost_backend_has_feature(struct vhost_virtqueue *vq, int bit) +{ + return vq->acked_backend_features & (1ULL << bit); +} + +#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY +static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq) +{ + return vq->is_le; +} +#else +static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq) +{ + return virtio_legacy_is_little_endian() || vq->is_le; +} +#endif + +/* Memory accessors */ +static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val) +{ + return __virtio16_to_cpu(vhost_is_little_endian(vq), val); +} + +static inline __virtio16 cpu_to_vhost16(struct vhost_virtqueue *vq, u16 val) +{ + return __cpu_to_virtio16(vhost_is_little_endian(vq), val); +} + +static inline u32 vhost32_to_cpu(struct vhost_virtqueue *vq, __virtio32 val) +{ + return __virtio32_to_cpu(vhost_is_little_endian(vq), val); +} + +static inline __virtio32 cpu_to_vhost32(struct vhost_virtqueue *vq, u32 val) +{ + return __cpu_to_virtio32(vhost_is_little_endian(vq), val); +} + +static inline u64 vhost64_to_cpu(struct vhost_virtqueue *vq, __virtio64 val) +{ + return __virtio64_to_cpu(vhost_is_little_endian(vq), val); +} + +static inline __virtio64 cpu_to_vhost64(struct vhost_virtqueue *vq, u64 val) +{ + return __cpu_to_virtio64(vhost_is_little_endian(vq), val); +} +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/include/linux/vdpa.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/include/linux/vdpa.h new file mode 100644 index 0000000..e2fb636 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/include/linux/vdpa.h @@ -0,0 +1,362 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_VDPA_H +#define _LINUX_VDPA_H + +#include +#include +#include +#include + +/** + * vDPA callback definition. + * @callback: interrupt callback function + * @private: the data passed to the callback function + */ +struct vdpa_callback { + irqreturn_t (*callback)(void *data); + void *private; +}; + +/** + * vDPA notification area + * @addr: base address of the notification area + * @size: size of the notification area + */ +struct vdpa_notification_area { + resource_size_t addr; + resource_size_t size; +}; + +/** + * struct vdpa_vq_state_split - vDPA split virtqueue state + * @avail_index: available index + */ +struct vdpa_vq_state_split { + u16 avail_index; +}; + +/** + * struct vdpa_vq_state_packed - vDPA packed virtqueue state + * @last_avail_counter: last driver ring wrap counter observed by device + * @last_avail_idx: device available index + * @last_used_counter: device ring wrap counter + * @last_used_idx: used index + */ +struct vdpa_vq_state_packed { + u16 last_avail_counter:1; + u16 last_avail_idx:15; + u16 last_used_counter:1; + u16 last_used_idx:15; +}; + +struct vdpa_vq_state { + union { + struct vdpa_vq_state_split split; + struct vdpa_vq_state_packed packed; + }; +}; + +/** + * vDPA device - representation of a vDPA device + * @dev: underlying device + * @dma_dev: the actual device that is performing DMA + * @config: the configuration ops for this device. + * @index: device index + * @features_valid: were features initialized? for legacy guests + */ +struct vdpa_device { + struct device dev; + struct device *dma_dev; + const struct vdpa_config_ops *config; + unsigned int index; + bool features_valid; + int nvqs; +}; + +/** + * vDPA IOVA range - the IOVA range support by the device + * @first: start of the IOVA range + * @last: end of the IOVA range + */ +struct vdpa_iova_range { + u64 first; + u64 last; +}; + +/** + * vDPA_config_ops - operations for configuring a vDPA device. + * Note: vDPA device drivers are required to implement all of the + * operations unless it is mentioned to be optional in the following + * list. + * + * @set_vq_address: Set the address of virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * @desc_area: address of desc area + * @driver_area: address of driver area + * @device_area: address of device area + * Returns integer: success (0) or error (< 0) + * @set_vq_num: Set the size of virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * @num: the size of virtqueue + * @kick_vq: Kick the virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * @set_vq_cb: Set the interrupt callback function for + * a virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * @cb: virtio-vdev interrupt callback structure + * @set_vq_ready: Set ready status for a virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * @ready: ready (true) not ready(false) + * @get_vq_ready: Get ready status for a virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * Returns boolean: ready (true) or not (false) + * @set_vq_state: Set the state for a virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * @state: pointer to set virtqueue state (last_avail_idx) + * Returns integer: success (0) or error (< 0) + * @get_vq_state: Get the state for a virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * @state: pointer to returned state (last_avail_idx) + * @get_vq_notification: Get the notification area for a virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * Returns the notifcation area + * @get_vq_irq: Get the irq number of a virtqueue (optional, + * but must implemented if require vq irq offloading) + * @vdev: vdpa device + * @idx: virtqueue index + * Returns int: irq number of a virtqueue, + * negative number if no irq assigned. + * @get_vq_align: Get the virtqueue align requirement + * for the device + * @vdev: vdpa device + * Returns virtqueue algin requirement + * @get_features: Get virtio features supported by the device + * @vdev: vdpa device + * Returns the virtio features support by the + * device + * @set_features: Set virtio features supported by the driver + * @vdev: vdpa device + * @features: feature support by the driver + * Returns integer: success (0) or error (< 0) + * @set_config_cb: Set the config interrupt callback + * @vdev: vdpa device + * @cb: virtio-vdev interrupt callback structure + * @get_vq_num_max: Get the max size of virtqueue + * @vdev: vdpa device + * Returns u16: max size of virtqueue + * @get_device_id: Get virtio device id + * @vdev: vdpa device + * Returns u32: virtio device id + * @get_vendor_id: Get id for the vendor that provides this device + * @vdev: vdpa device + * Returns u32: virtio vendor id + * @get_status: Get the device status + * @vdev: vdpa device + * Returns u8: virtio device status + * @set_status: Set the device status + * @vdev: vdpa device + * @status: virtio device status + * @get_config: Read from device specific configuration space + * @vdev: vdpa device + * @offset: offset from the beginning of + * configuration space + * @buf: buffer used to read to + * @len: the length to read from + * configuration space + * @set_config: Write to device specific configuration space + * @vdev: vdpa device + * @offset: offset from the beginning of + * configuration space + * @buf: buffer used to write from + * @len: the length to write to + * configuration space + * @get_generation: Get device config generation (optional) + * @vdev: vdpa device + * Returns u32: device generation + * @get_iova_range: Get supported iova range (optional) + * @vdev: vdpa device + * Returns the iova range supported by + * the device. + * @set_map: Set device memory mapping (optional) + * Needed for device that using device + * specific DMA translation (on-chip IOMMU) + * @vdev: vdpa device + * @iotlb: vhost memory mapping to be + * used by the vDPA + * Returns integer: success (0) or error (< 0) + * @dma_map: Map an area of PA to IOVA (optional) + * Needed for device that using device + * specific DMA translation (on-chip IOMMU) + * and preferring incremental map. + * @vdev: vdpa device + * @iova: iova to be mapped + * @size: size of the area + * @pa: physical address for the map + * @perm: device access permission (VHOST_MAP_XX) + * Returns integer: success (0) or error (< 0) + * @dma_unmap: Unmap an area of IOVA (optional but + * must be implemented with dma_map) + * Needed for device that using device + * specific DMA translation (on-chip IOMMU) + * and preferring incremental unmap. + * @vdev: vdpa device + * @iova: iova to be unmapped + * @size: size of the area + * Returns integer: success (0) or error (< 0) + * @free: Free resources that belongs to vDPA (optional) + * @vdev: vdpa device + */ +struct vdpa_config_ops { + /* Virtqueue ops */ + int (*set_vq_address)(struct vdpa_device *vdev, + u16 idx, u64 desc_area, u64 driver_area, + u64 device_area); + void (*set_vq_num)(struct vdpa_device *vdev, u16 idx, u32 num); + void (*kick_vq)(struct vdpa_device *vdev, u16 idx); + void (*set_vq_cb)(struct vdpa_device *vdev, u16 idx, + struct vdpa_callback *cb); + void (*set_vq_ready)(struct vdpa_device *vdev, u16 idx, bool ready); + bool (*get_vq_ready)(struct vdpa_device *vdev, u16 idx); + int (*set_vq_state)(struct vdpa_device *vdev, u16 idx, + const struct vdpa_vq_state *state); + int (*get_vq_state)(struct vdpa_device *vdev, u16 idx, + struct vdpa_vq_state *state); + struct vdpa_notification_area + (*get_vq_notification)(struct vdpa_device *vdev, u16 idx); + /* vq irq is not expected to be changed once DRIVER_OK is set */ + int (*get_vq_irq)(struct vdpa_device *vdv, u16 idx); + + /* Device ops */ + u32 (*get_vq_align)(struct vdpa_device *vdev); + u64 (*get_features)(struct vdpa_device *vdev); + int (*set_features)(struct vdpa_device *vdev, u64 features); + void (*set_config_cb)(struct vdpa_device *vdev, + struct vdpa_callback *cb); + u16 (*get_vq_num_max)(struct vdpa_device *vdev); + u32 (*get_device_id)(struct vdpa_device *vdev); + u32 (*get_vendor_id)(struct vdpa_device *vdev); + u8 (*get_status)(struct vdpa_device *vdev); + void (*set_status)(struct vdpa_device *vdev, u8 status); + void (*get_config)(struct vdpa_device *vdev, unsigned int offset, + void *buf, unsigned int len); + void (*set_config)(struct vdpa_device *vdev, unsigned int offset, + const void *buf, unsigned int len); + u32 (*get_generation)(struct vdpa_device *vdev); + struct vdpa_iova_range (*get_iova_range)(struct vdpa_device *vdev); + + /* Migration ops */ + int (*set_log_base)(struct vdpa_device *vdev, u64 log_base, u64 log_size); + + /* DMA ops */ + int (*set_map)(struct vdpa_device *vdev, struct vhost_iotlb *iotlb); + int (*dma_map)(struct vdpa_device *vdev, u64 iova, u64 size, + u64 pa, u32 perm); + int (*dma_unmap)(struct vdpa_device *vdev, u64 iova, u64 size); + + /* Free device resources */ + void (*free)(struct vdpa_device *vdev); +}; + +struct vdpa_device *__vdpa_alloc_device(struct device *parent, + const struct vdpa_config_ops *config, + int nvqs, + size_t size); + +#define vdpa_alloc_device(dev_struct, member, parent, config, nvqs) \ + container_of(__vdpa_alloc_device( \ + parent, config, nvqs, \ + sizeof(dev_struct) + \ + BUILD_BUG_ON_ZERO(offsetof( \ + dev_struct, member))), \ + dev_struct, member) + +int vdpa_register_device(struct vdpa_device *vdev); +void vdpa_unregister_device(struct vdpa_device *vdev); + +/** + * vdpa_driver - operations for a vDPA driver + * @driver: underlying device driver + * @probe: the function to call when a device is found. Returns 0 or -errno. + * @remove: the function to call when a device is removed. + */ +struct vdpa_driver { + struct device_driver driver; + int (*probe)(struct vdpa_device *vdev); + void (*remove)(struct vdpa_device *vdev); +}; + +#define vdpa_register_driver(drv) \ + __vdpa_register_driver(drv, THIS_MODULE) +int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner); +void vdpa_unregister_driver(struct vdpa_driver *drv); + +#define module_vdpa_driver(__vdpa_driver) \ + module_driver(__vdpa_driver, vdpa_register_driver, \ + vdpa_unregister_driver) + +static inline struct vdpa_driver *drv_to_vdpa(struct device_driver *driver) +{ + return container_of(driver, struct vdpa_driver, driver); +} + +static inline struct vdpa_device *dev_to_vdpa(struct device *_dev) +{ + return container_of(_dev, struct vdpa_device, dev); +} + +static inline void *vdpa_get_drvdata(const struct vdpa_device *vdev) +{ + return dev_get_drvdata(&vdev->dev); +} + +static inline void vdpa_set_drvdata(struct vdpa_device *vdev, void *data) +{ + dev_set_drvdata(&vdev->dev, data); +} + +static inline struct device *vdpa_get_dma_dev(struct vdpa_device *vdev) +{ + return vdev->dma_dev; +} + +static inline void vdpa_reset(struct vdpa_device *vdev) +{ + const struct vdpa_config_ops *ops = vdev->config; + + vdev->features_valid = false; + ops->set_status(vdev, 0); +} + +static inline int vdpa_set_features(struct vdpa_device *vdev, u64 features) +{ + const struct vdpa_config_ops *ops = vdev->config; + + vdev->features_valid = true; + return ops->set_features(vdev, features); +} + + +static inline void vdpa_get_config(struct vdpa_device *vdev, unsigned offset, + void *buf, unsigned int len) +{ + const struct vdpa_config_ops *ops = vdev->config; + + /* + * Config accesses aren't supposed to trigger before features are set. + * If it does happen we assume a legacy guest. + */ + if (!vdev->features_valid) + vdpa_set_features(vdev, 0); + ops->get_config(vdev, offset, buf, len); +} + +#endif /* _LINUX_VDPA_H */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vdpa/Makefile b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vdpa/Makefile new file mode 100644 index 0000000..7356f28 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vdpa/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-m += vdpa.o + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build/ +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +install: + install -D -m 644 Module.symvers /lib/modules/$(shell uname -r)/extern-symvers/vdpa.symvers + +clean: + @\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vdpa/vdpa.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vdpa/vdpa.c new file mode 100644 index 0000000..a69ffc9 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vdpa/vdpa.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * vDPA bus. + * + * Copyright (c) 2020, Red Hat. All rights reserved. + * Author: Jason Wang + * + */ + +#include +#include +#include +#include + +static DEFINE_IDA(vdpa_index_ida); + +static int vdpa_dev_probe(struct device *d) +{ + struct vdpa_device *vdev = dev_to_vdpa(d); + struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver); + int ret = 0; + + if (drv && drv->probe) + ret = drv->probe(vdev); + + return ret; +} + +static int vdpa_dev_remove(struct device *d) +{ + struct vdpa_device *vdev = dev_to_vdpa(d); + struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver); + + if (drv && drv->remove) + drv->remove(vdev); + + return 0; +} + +static struct bus_type vdpa_bus = { + .name = "vdpa", + .probe = vdpa_dev_probe, + .remove = vdpa_dev_remove, +}; + +static void vdpa_release_dev(struct device *d) +{ + struct vdpa_device *vdev = dev_to_vdpa(d); + const struct vdpa_config_ops *ops = vdev->config; + + if (ops->free) + ops->free(vdev); + + ida_simple_remove(&vdpa_index_ida, vdev->index); + kfree(vdev); +} + +/** + * __vdpa_alloc_device - allocate and initilaize a vDPA device + * This allows driver to some prepartion after device is + * initialized but before registered. + * @parent: the parent device + * @config: the bus operations that is supported by this device + * @nvqs: number of virtqueues supported by this device + * @size: size of the parent structure that contains private data + * + * Driver should use vdpa_alloc_device() wrapper macro instead of + * using this directly. + * + * Returns an error when parent/config/dma_dev is not set or fail to get + * ida. + */ +struct vdpa_device *__vdpa_alloc_device(struct device *parent, + const struct vdpa_config_ops *config, + int nvqs, + size_t size) +{ + struct vdpa_device *vdev; + int err = -EINVAL; + + if (!config) + goto err; + + if (!!config->dma_map != !!config->dma_unmap) + goto err; + + err = -ENOMEM; + vdev = kzalloc(size, GFP_KERNEL); + if (!vdev) + goto err; + + err = ida_simple_get(&vdpa_index_ida, 0, 0, GFP_KERNEL); + if (err < 0) + goto err_ida; + + vdev->dev.bus = &vdpa_bus; + vdev->dev.parent = parent; + vdev->dev.release = vdpa_release_dev; + vdev->index = err; + vdev->config = config; + vdev->features_valid = false; + vdev->nvqs = nvqs; + + err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index); + if (err) + goto err_name; + + device_initialize(&vdev->dev); + + return vdev; + +err_name: + ida_simple_remove(&vdpa_index_ida, vdev->index); +err_ida: + kfree(vdev); +err: + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(__vdpa_alloc_device); + +/** + * vdpa_register_device - register a vDPA device + * Callers must have a succeed call of vdpa_alloc_device() before. + * @vdev: the vdpa device to be registered to vDPA bus + * + * Returns an error when fail to add to vDPA bus + */ +int vdpa_register_device(struct vdpa_device *vdev) +{ + return device_add(&vdev->dev); +} +EXPORT_SYMBOL_GPL(vdpa_register_device); + +/** + * vdpa_unregister_device - unregister a vDPA device + * @vdev: the vdpa device to be unregisted from vDPA bus + */ +void vdpa_unregister_device(struct vdpa_device *vdev) +{ + device_unregister(&vdev->dev); +} +EXPORT_SYMBOL_GPL(vdpa_unregister_device); + +/** + * __vdpa_register_driver - register a vDPA device driver + * @drv: the vdpa device driver to be registered + * @owner: module owner of the driver + * + * Returns an err when fail to do the registration + */ +int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner) +{ + drv->driver.bus = &vdpa_bus; + drv->driver.owner = owner; + + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(__vdpa_register_driver); + +/** + * vdpa_unregister_driver - unregister a vDPA device driver + * @drv: the vdpa device driver to be unregistered + */ +void vdpa_unregister_driver(struct vdpa_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(vdpa_unregister_driver); + +static int vdpa_init(void) +{ + return bus_register(&vdpa_bus); +} + +static void __exit vdpa_exit(void) +{ + bus_unregister(&vdpa_bus); + ida_destroy(&vdpa_index_ida); +} +core_initcall(vdpa_init); +module_exit(vdpa_exit); + +MODULE_AUTHOR("Jason Wang "); +MODULE_LICENSE("GPL v2"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/Makefile b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/Makefile new file mode 100644 index 0000000..a78ffba --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-m += vhost_vdpa.o +vhost_vdpa-y := vdpa.o + +obj-m += vhost.o + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build/ +# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers +# # KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers +KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + @\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/vdpa.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/vdpa.c new file mode 100644 index 0000000..8c24d31 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/vdpa.c @@ -0,0 +1,1202 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2020 Intel Corporation. + * Copyright (C) 2020 Red Hat, Inc. + * + * Author: Tiwei Bie + * Jason Wang + * + * Thanks Michael S. Tsirkin for the valuable comments and + * suggestions. And thanks to Cunming Liang and Zhihong Wang for all + * their supports. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vhost.h" + +enum { + VHOST_VDPA_BACKEND_FEATURES = + (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2) | + (1ULL << VHOST_BACKEND_F_IOTLB_BATCH), +}; + +#define VHOST_VDPA_DEV_MAX (1U << MINORBITS) + +struct vhost_vdpa { + struct vhost_dev vdev; + struct iommu_domain *domain; + struct vhost_virtqueue *vqs; + struct completion completion; + struct vdpa_device *vdpa; + struct device dev; + struct cdev cdev; + atomic_t opened; + int nvqs; + int virtio_id; + int minor; + struct eventfd_ctx *config_ctx; + int in_batch; + struct vdpa_iova_range range; +}; + +static DEFINE_IDA(vhost_vdpa_ida); + +static dev_t vhost_vdpa_major; + +static void handle_vq_kick(struct vhost_work *work) +{ + struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, + poll.work); + struct vhost_vdpa *v = container_of(vq->dev, struct vhost_vdpa, vdev); + const struct vdpa_config_ops *ops = v->vdpa->config; + + ops->kick_vq(v->vdpa, vq - v->vqs); +} + +static irqreturn_t vhost_vdpa_virtqueue_cb(void *private) +{ + struct vhost_virtqueue *vq = private; + struct eventfd_ctx *call_ctx = vq->call_ctx.ctx; + + if (call_ctx) + eventfd_signal(call_ctx, 1); + + return IRQ_HANDLED; +} + +static irqreturn_t vhost_vdpa_config_cb(void *private) +{ + struct vhost_vdpa *v = private; + struct eventfd_ctx *config_ctx = v->config_ctx; + + if (config_ctx) + eventfd_signal(config_ctx, 1); + + return IRQ_HANDLED; +} + +static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid) +{ + struct vhost_virtqueue *vq = &v->vqs[qid]; + const struct vdpa_config_ops *ops = v->vdpa->config; + struct vdpa_device *vdpa = v->vdpa; + int ret, irq; + + if (!ops->get_vq_irq) + return; + + irq = ops->get_vq_irq(vdpa, qid); + if (irq < 0) + return; + + irq_bypass_unregister_producer(&vq->call_ctx.producer); + if (!vq->call_ctx.ctx) + return; + + vq->call_ctx.producer.token = vq->call_ctx.ctx; + vq->call_ctx.producer.irq = irq; + ret = irq_bypass_register_producer(&vq->call_ctx.producer); + if (unlikely(ret)) + dev_info(&v->dev, "vq %u, irq bypass producer (token %p) registration fails, ret = %d\n", + qid, vq->call_ctx.producer.token, ret); +} + +static void vhost_vdpa_unsetup_vq_irq(struct vhost_vdpa *v, u16 qid) +{ + struct vhost_virtqueue *vq = &v->vqs[qid]; + + irq_bypass_unregister_producer(&vq->call_ctx.producer); +} + +static void vhost_vdpa_reset(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + + vdpa_reset(vdpa); + v->in_batch = 0; +} + +static long vhost_vdpa_get_device_id(struct vhost_vdpa *v, u8 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u32 device_id; + + device_id = ops->get_device_id(vdpa); + + if (copy_to_user(argp, &device_id, sizeof(device_id))) + return -EFAULT; + + return 0; +} + +static long vhost_vdpa_get_status(struct vhost_vdpa *v, u8 __user *statusp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u8 status; + + status = ops->get_status(vdpa); + + if (copy_to_user(statusp, &status, sizeof(status))) + return -EFAULT; + + return 0; +} + +static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u8 status, status_old; + int nvqs = v->nvqs; + u16 i; + + if (copy_from_user(&status, statusp, sizeof(status))) + return -EFAULT; + + status_old = ops->get_status(vdpa); + + /* + * Userspace shouldn't remove status bits unless reset the + * status to 0. + */ + if (status != 0 && (ops->get_status(vdpa) & ~status) != 0) + return -EINVAL; + + ops->set_status(vdpa, status); + + if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && !(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) + for (i = 0; i < nvqs; i++) + vhost_vdpa_setup_vq_irq(v, i); + + if ((status_old & VIRTIO_CONFIG_S_DRIVER_OK) && !(status & VIRTIO_CONFIG_S_DRIVER_OK)) + for (i = 0; i < nvqs; i++) + vhost_vdpa_unsetup_vq_irq(v, i); + + return 0; +} + +static int vhost_vdpa_config_validate(struct vhost_vdpa *v, + struct vhost_vdpa_config *c) +{ + long size = 0; + + switch (v->virtio_id) { + case VIRTIO_ID_NET: + size = sizeof(struct virtio_net_config); + break; + } + + if (c->len == 0 || c->off > size) + return -EINVAL; + + if (c->len > size - c->off) + return -E2BIG; + + return 0; +} + +static long vhost_vdpa_get_config(struct vhost_vdpa *v, + struct vhost_vdpa_config __user *c) +{ + struct vdpa_device *vdpa = v->vdpa; + struct vhost_vdpa_config config; + unsigned long size = offsetof(struct vhost_vdpa_config, buf); + u8 *buf; + + if (copy_from_user(&config, c, size)) + return -EFAULT; + if (vhost_vdpa_config_validate(v, &config)) + return -EINVAL; + buf = kvzalloc(config.len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + vdpa_get_config(vdpa, config.off, buf, config.len); + + if (copy_to_user(c->buf, buf, config.len)) { + kvfree(buf); + return -EFAULT; + } + + kvfree(buf); + return 0; +} + +static long vhost_vdpa_set_config(struct vhost_vdpa *v, + struct vhost_vdpa_config __user *c) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_vdpa_config config; + unsigned long size = offsetof(struct vhost_vdpa_config, buf); + u8 *buf; + + if (copy_from_user(&config, c, size)) + return -EFAULT; + if (vhost_vdpa_config_validate(v, &config)) + return -EINVAL; + buf = kvzalloc(config.len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, c->buf, config.len)) { + kvfree(buf); + return -EFAULT; + } + + ops->set_config(vdpa, config.off, buf, config.len); + + kvfree(buf); + return 0; +} + +static long vhost_vdpa_get_features(struct vhost_vdpa *v, u64 __user *featurep) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u64 features; + + features = ops->get_features(vdpa); + + if (copy_to_user(featurep, &features, sizeof(features))) + return -EFAULT; + + return 0; +} + +static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_dev *d = &v->vdev; + u64 actual_features; + u64 features; + int i; + + /* + * It's not allowed to change the features after they have + * been negotiated. except for migration + */ + if (copy_from_user(&features, featurep, sizeof(features))) + return -EFAULT; + + if (!(features & (1 << VHOST_F_LOG_ALL)) && + (ops->get_status(vdpa) & VIRTIO_CONFIG_S_FEATURES_OK)) + return -EBUSY; + + if (vdpa_set_features(vdpa, features)) + return -EINVAL; + + /* let the vqs know what has been configured */ + /* TODO: add the ops of get_driver_features */ + //actual_features = ops->get_driver_features(vdpa); + actual_features = features; + for (i = 0; i < d->nvqs; ++i) { + struct vhost_virtqueue *vq = d->vqs[i]; + + mutex_lock(&vq->mutex); + vq->acked_features = actual_features; + mutex_unlock(&vq->mutex); + } + return 0; +} + +static long vhost_vdpa_get_vring_num(struct vhost_vdpa *v, u16 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + u16 num; + + num = ops->get_vq_num_max(vdpa); + + if (copy_to_user(argp, &num, sizeof(num))) + return -EFAULT; + + return 0; +} + +static void vhost_vdpa_config_put(struct vhost_vdpa *v) +{ + if (v->config_ctx) { + eventfd_ctx_put(v->config_ctx); + v->config_ctx = NULL; + } +} + +static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp) +{ + struct vdpa_callback cb; + int fd; + struct eventfd_ctx *ctx; + + cb.callback = vhost_vdpa_config_cb; + cb.private = v; + if (copy_from_user(&fd, argp, sizeof(fd))) + return -EFAULT; + + ctx = fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(fd); + swap(ctx, v->config_ctx); + + if (!IS_ERR_OR_NULL(ctx)) + eventfd_ctx_put(ctx); + + if (IS_ERR(v->config_ctx)) { + long ret = PTR_ERR(v->config_ctx); + + v->config_ctx = NULL; + return ret; + } + + v->vdpa->config->set_config_cb(v->vdpa, &cb); + + return 0; +} + +static long vhost_vdpa_set_log_base(struct vhost_vdpa *v, u64 __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + u64 log_base; + u64 log_size; + + if (copy_from_user(&log_size, argp, sizeof(log_size))) + return -EFAULT; + /*angus:we must be the same with qemu vdpa*/ + if (copy_from_user(&log_base, argp + 2, sizeof(log_base))) + return -EFAULT; + + dev_info(&v->dev, "enter vhost_vdpa_set_log_base log base=0x%llx size=0x%llx\n", + log_base, log_size); + + v->vdpa->config->set_log_base(vdpa, log_base, log_size); + + return 0; +} + +static long vhost_vdpa_get_iova_range(struct vhost_vdpa *v, u32 __user *argp) +{ + struct vhost_vdpa_iova_range range = { + .first = v->range.first, + .last = v->range.last, + }; + + if (copy_to_user(argp, &range, sizeof(range))) + return -EFAULT; + return 0; +} + +static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, + void __user *argp) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_vq_state vq_state; + struct vdpa_callback cb; + struct vhost_virtqueue *vq; + struct vhost_vring_state s; + u32 idx; + long r; + + r = get_user(idx, (u32 __user *)argp); + if (r < 0) + return r; + + if (idx >= v->nvqs) + return -ENOBUFS; + + idx = array_index_nospec(idx, v->nvqs); + vq = &v->vqs[idx]; + + switch (cmd) { + case VHOST_VDPA_SET_VRING_ENABLE: + if (copy_from_user(&s, argp, sizeof(s))) + return -EFAULT; + ops->set_vq_ready(vdpa, idx, s.num); + return 0; + case VHOST_GET_VRING_BASE: + r = ops->get_vq_state(v->vdpa, idx, &vq_state); + if (r) + return r; + + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) { + vq->last_avail_idx = vq_state.packed.last_avail_idx | + (vq_state.packed.last_avail_counter << 15); + vq->last_used_idx = vq_state.packed.last_used_idx | + (vq_state.packed.last_used_counter << 15); + } else { + vq->last_avail_idx = vq_state.split.avail_index; + } + break; + } + + r = vhost_vring_ioctl(&v->vdev, cmd, argp); + if (r) { + printk("vring ioctl errro. cmd %d err %ld\n", cmd, r); + return r; + } + + switch (cmd) { + case VHOST_SET_VRING_ADDR: + if (ops->set_vq_address(vdpa, idx, + (u64)(uintptr_t)vq->desc, + (u64)(uintptr_t)vq->avail, + (u64)(uintptr_t)vq->used)) + r = -EINVAL; + break; + + case VHOST_SET_VRING_BASE: + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) { + vq_state.packed.last_avail_idx = vq->last_avail_idx & 0x7fff; + vq_state.packed.last_avail_counter = !!(vq->last_avail_idx & 0x8000); + vq_state.packed.last_used_idx = vq->last_used_idx & 0x7fff; + vq_state.packed.last_used_counter = !!(vq->last_used_idx & 0x8000); + } else { + vq_state.split.avail_index = vq->last_avail_idx; + } + if (ops->set_vq_state(vdpa, idx, &vq_state)) + r = -EINVAL; + break; + + case VHOST_SET_VRING_CALL: + if (vq->call_ctx.ctx) { + cb.callback = vhost_vdpa_virtqueue_cb; + cb.private = vq; + } else { + cb.callback = NULL; + cb.private = NULL; + } + ops->set_vq_cb(vdpa, idx, &cb); + vhost_vdpa_setup_vq_irq(v, idx); + break; + + case VHOST_SET_VRING_NUM: + ops->set_vq_num(vdpa, idx, vq->num); + break; + } + + return r; +} + +static long vhost_vdpa_unlocked_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + struct vhost_vdpa *v = filep->private_data; + struct vhost_dev *d = &v->vdev; + void __user *argp = (void __user *)arg; + u64 __user *featurep = argp; + u64 features; + long r = 0; + + if (cmd == VHOST_SET_BACKEND_FEATURES) { + if (copy_from_user(&features, featurep, sizeof(features))) + return -EFAULT; + if (features & ~VHOST_VDPA_BACKEND_FEATURES) + return -EOPNOTSUPP; + vhost_set_backend_features(&v->vdev, features); + return 0; + } + + mutex_lock(&d->mutex); + + switch (cmd) { + case VHOST_VDPA_GET_DEVICE_ID: + r = vhost_vdpa_get_device_id(v, argp); + break; + case VHOST_VDPA_GET_STATUS: + r = vhost_vdpa_get_status(v, argp); + break; + case VHOST_VDPA_SET_STATUS: + r = vhost_vdpa_set_status(v, argp); + break; + case VHOST_VDPA_GET_CONFIG: + r = vhost_vdpa_get_config(v, argp); + break; + case VHOST_VDPA_SET_CONFIG: + r = vhost_vdpa_set_config(v, argp); + break; + case VHOST_GET_FEATURES: + r = vhost_vdpa_get_features(v, argp); + break; + case VHOST_SET_FEATURES: + r = vhost_vdpa_set_features(v, argp); + break; + case VHOST_VDPA_GET_VRING_NUM: + r = vhost_vdpa_get_vring_num(v, argp); + break; + case VHOST_SET_LOG_BASE: + r = vhost_vdpa_set_log_base(v, argp); + break; + case VHOST_SET_LOG_FD: + r = -ENOIOCTLCMD; + break; + case VHOST_VDPA_SET_CONFIG_CALL: + r = vhost_vdpa_set_config_call(v, argp); + break; + case VHOST_GET_BACKEND_FEATURES: + features = VHOST_VDPA_BACKEND_FEATURES; + if (copy_to_user(featurep, &features, sizeof(features))) + r = -EFAULT; + break; + case VHOST_VDPA_GET_IOVA_RANGE: + r = vhost_vdpa_get_iova_range(v, argp); + break; + default: + r = vhost_dev_ioctl(&v->vdev, cmd, argp); + if (r == -ENOIOCTLCMD) + r = vhost_vdpa_vring_ioctl(v, cmd, argp); + break; + } + + mutex_unlock(&d->mutex); + return r; +} + +static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, u64 start, u64 last) +{ + struct vhost_dev *dev = &v->vdev; + struct vhost_iotlb *iotlb = dev->iotlb; + struct vhost_iotlb_map *map; + struct page *page; + unsigned long pfn, pinned; + + while ((map = vhost_iotlb_itree_first(iotlb, start, last)) != NULL) { + pinned = map->size >> PAGE_SHIFT; + for (pfn = map->addr >> PAGE_SHIFT; + pinned > 0; pfn++, pinned--) { + page = pfn_to_page(pfn); + if (map->perm & VHOST_ACCESS_WO) + set_page_dirty_lock(page); + unpin_user_page(page); + } + atomic64_sub(map->size >> PAGE_SHIFT, &dev->mm->pinned_vm); + vhost_iotlb_map_free(iotlb, map); + } +} + +static void vhost_vdpa_iotlb_free(struct vhost_vdpa *v) +{ + struct vhost_dev *dev = &v->vdev; + + vhost_vdpa_iotlb_unmap(v, 0ULL, 0ULL - 1); + kfree(dev->iotlb); + dev->iotlb = NULL; +} + +static int perm_to_iommu_flags(u32 perm) +{ + int flags = 0; + + switch (perm) { + case VHOST_ACCESS_WO: + flags |= IOMMU_WRITE; + break; + case VHOST_ACCESS_RO: + flags |= IOMMU_READ; + break; + case VHOST_ACCESS_RW: + flags |= (IOMMU_WRITE | IOMMU_READ); + break; + default: + WARN(1, "invalidate vhost IOTLB permission\n"); + break; + } + + return flags | IOMMU_CACHE; +} + +static int vhost_vdpa_map(struct vhost_vdpa *v, + u64 iova, u64 size, u64 pa, u32 perm) +{ + struct vhost_dev *dev = &v->vdev; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + int r = 0; + + r = vhost_iotlb_add_range(dev->iotlb, iova, iova + size - 1, + pa, perm); + if (r) + return r; + + if (ops->dma_map) { + r = ops->dma_map(vdpa, iova, size, pa, perm); + } else if (ops->set_map) { + if (!v->in_batch) + r = ops->set_map(vdpa, dev->iotlb); + } else { + r = iommu_map(v->domain, iova, pa, size, + perm_to_iommu_flags(perm)); + } + + if (r) + vhost_iotlb_del_range(dev->iotlb, iova, iova + size - 1); + else + atomic64_add(size >> PAGE_SHIFT, &dev->mm->pinned_vm); + + return r; +} + +static void vhost_vdpa_unmap(struct vhost_vdpa *v, u64 iova, u64 size) +{ + struct vhost_dev *dev = &v->vdev; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + vhost_vdpa_iotlb_unmap(v, iova, iova + size - 1); + + if (ops->dma_map) { + ops->dma_unmap(vdpa, iova, size); + } else if (ops->set_map) { + if (!v->in_batch) + ops->set_map(vdpa, dev->iotlb); + } else { + iommu_unmap(v->domain, iova, size); + } +} + +static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v, + struct vhost_iotlb_msg *msg) +{ + struct vhost_dev *dev = &v->vdev; + struct vhost_iotlb *iotlb = dev->iotlb; + struct page **page_list; + unsigned long list_size = PAGE_SIZE / sizeof(struct page *); + unsigned int gup_flags = FOLL_LONGTERM; + unsigned long npages, cur_base, map_pfn, last_pfn = 0; + unsigned long lock_limit, sz2pin, nchunks, i; + u64 iova = msg->iova; + long pinned; + int ret = 0; + + if (msg->iova < v->range.first || !msg->size || + msg->iova > U64_MAX - msg->size + 1 || + msg->iova + msg->size - 1 > v->range.last) + return -EINVAL; + + if (vhost_iotlb_itree_first(iotlb, msg->iova, + msg->iova + msg->size - 1)) + return -EEXIST; + + /* Limit the use of memory for bookkeeping */ + page_list = (struct page **) __get_free_page(GFP_KERNEL); + if (!page_list) + return -ENOMEM; + + if (msg->perm & VHOST_ACCESS_WO) + gup_flags |= FOLL_WRITE; + + npages = PAGE_ALIGN(msg->size + (iova & ~PAGE_MASK)) >> PAGE_SHIFT; + if (!npages) { + ret = -EINVAL; + goto free; + } + + mmap_read_lock(dev->mm); + + lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + if (npages + atomic64_read(&dev->mm->pinned_vm) > lock_limit) { + ret = -ENOMEM; + goto unlock; + } + + cur_base = msg->uaddr & PAGE_MASK; + iova &= PAGE_MASK; + nchunks = 0; + + while (npages) { + sz2pin = min_t(unsigned long, npages, list_size); + pinned = pin_user_pages(cur_base, sz2pin, + gup_flags, page_list, NULL); + if (sz2pin != pinned) { + if (pinned < 0) { + ret = pinned; + } else { + unpin_user_pages(page_list, pinned); + ret = -ENOMEM; + } + goto out; + } + nchunks++; + + if (!last_pfn) + map_pfn = page_to_pfn(page_list[0]); + + for (i = 0; i < pinned; i++) { + unsigned long this_pfn = page_to_pfn(page_list[i]); + u64 csize; + + if (last_pfn && (this_pfn != last_pfn + 1)) { + /* Pin a contiguous chunk of memory */ + csize = (last_pfn - map_pfn + 1) << PAGE_SHIFT; + ret = vhost_vdpa_map(v, iova, csize, + map_pfn << PAGE_SHIFT, + msg->perm); + if (ret) { + /* + * Unpin the pages that are left unmapped + * from this point on in the current + * page_list. The remaining outstanding + * ones which may stride across several + * chunks will be covered in the common + * error path subsequently. + */ + unpin_user_pages(&page_list[i], + pinned - i); + goto out; + } + + map_pfn = this_pfn; + iova += csize; + nchunks = 0; + } + + last_pfn = this_pfn; + } + + cur_base += pinned << PAGE_SHIFT; + npages -= pinned; + } + + /* Pin the rest chunk */ + ret = vhost_vdpa_map(v, iova, (last_pfn - map_pfn + 1) << PAGE_SHIFT, + map_pfn << PAGE_SHIFT, msg->perm); +out: + if (ret) { + if (nchunks) { + unsigned long pfn; + + /* + * Unpin the outstanding pages which are yet to be + * mapped but haven't due to vdpa_map() or + * pin_user_pages() failure. + * + * Mapped pages are accounted in vdpa_map(), hence + * the corresponding unpinning will be handled by + * vdpa_unmap(). + */ + WARN_ON(!last_pfn); + for (pfn = map_pfn; pfn <= last_pfn; pfn++) + unpin_user_page(pfn_to_page(pfn)); + } + vhost_vdpa_unmap(v, msg->iova, msg->size); + } +unlock: + mmap_read_unlock(dev->mm); +free: + free_page((unsigned long)page_list); + return ret; +} + +static int vhost_vdpa_process_iotlb_msg(struct vhost_dev *dev, + struct vhost_iotlb_msg *msg) +{ + struct vhost_vdpa *v = container_of(dev, struct vhost_vdpa, vdev); + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + int r = 0; + + mutex_lock(&dev->mutex); + + r = vhost_dev_check_owner(dev); + if (r) + goto unlock; + + switch (msg->type) { + case VHOST_IOTLB_UPDATE: + r = vhost_vdpa_process_iotlb_update(v, msg); + break; + case VHOST_IOTLB_INVALIDATE: + vhost_vdpa_unmap(v, msg->iova, msg->size); + break; + case VHOST_IOTLB_BATCH_BEGIN: + v->in_batch = true; + break; + case VHOST_IOTLB_BATCH_END: + if (v->in_batch && ops->set_map) + ops->set_map(vdpa, dev->iotlb); + v->in_batch = false; + break; + default: + r = -EINVAL; + break; + } +unlock: + mutex_unlock(&dev->mutex); + + return r; +} + +static ssize_t vhost_vdpa_chr_write_iter(struct kiocb *iocb, + struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct vhost_vdpa *v = file->private_data; + struct vhost_dev *dev = &v->vdev; + + return vhost_chr_write_iter(dev, from); +} + +static int vhost_vdpa_alloc_domain(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct device *dma_dev = vdpa_get_dma_dev(vdpa); + struct bus_type *bus; + int ret; + + /* Device want to do DMA by itself */ + if (ops->set_map || ops->dma_map) + return 0; + + bus = dma_dev->bus; + if (!bus) + return -EFAULT; + + if (!iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY)) + return -ENOTSUPP; + + v->domain = iommu_domain_alloc(bus); + if (!v->domain) + return -EIO; + + ret = iommu_attach_device(v->domain, dma_dev); + if (ret) + goto err_attach; + + return 0; + +err_attach: + iommu_domain_free(v->domain); + return ret; +} + +static void vhost_vdpa_free_domain(struct vhost_vdpa *v) +{ + struct vdpa_device *vdpa = v->vdpa; + struct device *dma_dev = vdpa_get_dma_dev(vdpa); + + if (v->domain) { + iommu_detach_device(v->domain, dma_dev); + iommu_domain_free(v->domain); + } + + v->domain = NULL; +} + +static void vhost_vdpa_set_iova_range(struct vhost_vdpa *v) +{ + struct vdpa_iova_range *range = &v->range; + struct iommu_domain_geometry geo; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + + if (ops->get_iova_range) { + *range = ops->get_iova_range(vdpa); + } else if (v->domain && + !iommu_domain_get_attr(v->domain, + DOMAIN_ATTR_GEOMETRY, &geo) && + geo.force_aperture) { + range->first = geo.aperture_start; + range->last = geo.aperture_end; + } else { + range->first = 0; + range->last = ULLONG_MAX; + } +} + +static int vhost_vdpa_open(struct inode *inode, struct file *filep) +{ + struct vhost_vdpa *v; + struct vhost_dev *dev; + struct vhost_virtqueue **vqs; + int nvqs, i, r, opened; + + v = container_of(inode->i_cdev, struct vhost_vdpa, cdev); + + opened = atomic_cmpxchg(&v->opened, 0, 1); + if (opened) + return -EBUSY; + + nvqs = v->nvqs; + vhost_vdpa_reset(v); + + vqs = kmalloc_array(nvqs, sizeof(*vqs), GFP_KERNEL); + if (!vqs) { + r = -ENOMEM; + goto err; + } + + dev = &v->vdev; + for (i = 0; i < nvqs; i++) { + vqs[i] = &v->vqs[i]; + vqs[i]->handle_kick = handle_vq_kick; + } + vhost_dev_init(dev, vqs, nvqs, 0, 0, 0, false, + vhost_vdpa_process_iotlb_msg); + + dev->iotlb = vhost_iotlb_alloc(0, 0); + if (!dev->iotlb) { + r = -ENOMEM; + goto err_init_iotlb; + } + + r = vhost_vdpa_alloc_domain(v); + if (r) + goto err_init_iotlb; + + vhost_vdpa_set_iova_range(v); + + filep->private_data = v; + + return 0; + +err_init_iotlb: + vhost_dev_cleanup(&v->vdev); + kfree(vqs); +err: + atomic_dec(&v->opened); + return r; +} + +static void vhost_vdpa_clean_irq(struct vhost_vdpa *v) +{ + int i; + + for (i = 0; i < v->nvqs; i++) + vhost_vdpa_unsetup_vq_irq(v, i); +} + +static int vhost_vdpa_release(struct inode *inode, struct file *filep) +{ + struct vhost_vdpa *v = filep->private_data; + struct vhost_dev *d = &v->vdev; + + mutex_lock(&d->mutex); + filep->private_data = NULL; + vhost_vdpa_reset(v); + vhost_dev_stop(&v->vdev); + vhost_vdpa_iotlb_free(v); + vhost_vdpa_free_domain(v); + vhost_vdpa_config_put(v); + vhost_vdpa_clean_irq(v); + vhost_dev_cleanup(&v->vdev); + kfree(v->vdev.vqs); + mutex_unlock(&d->mutex); + + atomic_dec(&v->opened); + complete(&v->completion); + + return 0; +} + +#ifdef CONFIG_MMU +static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) +{ + struct vhost_vdpa *v = vmf->vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + struct vm_area_struct *vma = vmf->vma; + u16 index = vma->vm_pgoff; + + notify = ops->get_vq_notification(vdpa, index); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + if (remap_pfn_range(vma, vmf->address & PAGE_MASK, + notify.addr >> PAGE_SHIFT, PAGE_SIZE, + vma->vm_page_prot)) + return VM_FAULT_SIGBUS; + + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct vhost_vdpa_vm_ops = { + .fault = vhost_vdpa_fault, +}; + +static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct vhost_vdpa *v = vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + unsigned long index = vma->vm_pgoff; + + if (vma->vm_end - vma->vm_start != PAGE_SIZE) + return -EINVAL; + if ((vma->vm_flags & VM_SHARED) == 0) + return -EINVAL; + if (vma->vm_flags & VM_READ) + return -EINVAL; + if (index > 65535) + return -EINVAL; + if (!ops->get_vq_notification) + return -ENOTSUPP; + + /* To be safe and easily modelled by userspace, We only + * support the doorbell which sits on the page boundary and + * does not share the page with other registers. + */ + notify = ops->get_vq_notification(vdpa, index); + if (notify.addr & (PAGE_SIZE - 1)) + return -EINVAL; + if (vma->vm_end - vma->vm_start != notify.size) + return -ENOTSUPP; + + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_ops = &vhost_vdpa_vm_ops; + return 0; +} +#endif /* CONFIG_MMU */ + +static const struct file_operations vhost_vdpa_fops = { + .owner = THIS_MODULE, + .open = vhost_vdpa_open, + .release = vhost_vdpa_release, + .write_iter = vhost_vdpa_chr_write_iter, + .unlocked_ioctl = vhost_vdpa_unlocked_ioctl, +#ifdef CONFIG_MMU + .mmap = vhost_vdpa_mmap, +#endif /* CONFIG_MMU */ + .compat_ioctl = compat_ptr_ioctl, +}; + +static void vhost_vdpa_release_dev(struct device *device) +{ + struct vhost_vdpa *v = + container_of(device, struct vhost_vdpa, dev); + + ida_simple_remove(&vhost_vdpa_ida, v->minor); + kfree(v->vqs); + kfree(v); +} + +static int vhost_vdpa_probe(struct vdpa_device *vdpa) +{ + const struct vdpa_config_ops *ops = vdpa->config; + struct vhost_vdpa *v; + int minor; + int r; + + /* Currently, we only accept the network devices. */ + if (ops->get_device_id(vdpa) != VIRTIO_ID_NET) + return -ENOTSUPP; + + v = kzalloc(sizeof(*v), GFP_KERNEL | __GFP_RETRY_MAYFAIL); + if (!v) + return -ENOMEM; + + minor = ida_simple_get(&vhost_vdpa_ida, 0, + VHOST_VDPA_DEV_MAX, GFP_KERNEL); + if (minor < 0) { + kfree(v); + return minor; + } + + atomic_set(&v->opened, 0); + v->minor = minor; + v->vdpa = vdpa; + v->nvqs = vdpa->nvqs; + v->virtio_id = ops->get_device_id(vdpa); + + device_initialize(&v->dev); + v->dev.release = vhost_vdpa_release_dev; + v->dev.parent = &vdpa->dev; + v->dev.devt = MKDEV(MAJOR(vhost_vdpa_major), minor); + v->vqs = kmalloc_array(v->nvqs, sizeof(struct vhost_virtqueue), + GFP_KERNEL); + if (!v->vqs) { + r = -ENOMEM; + goto err; + } + + r = dev_set_name(&v->dev, "vhost-vdpa-%u", minor); + if (r) + goto err; + + cdev_init(&v->cdev, &vhost_vdpa_fops); + v->cdev.owner = THIS_MODULE; + + r = cdev_device_add(&v->cdev, &v->dev); + if (r) + goto err; + + init_completion(&v->completion); + vdpa_set_drvdata(vdpa, v); + + return 0; + +err: + put_device(&v->dev); + return r; +} + +static void vhost_vdpa_remove(struct vdpa_device *vdpa) +{ + struct vhost_vdpa *v = vdpa_get_drvdata(vdpa); + int opened; + + cdev_device_del(&v->cdev, &v->dev); + + do { + opened = atomic_cmpxchg(&v->opened, 0, 1); + if (!opened) + break; + wait_for_completion(&v->completion); + } while (1); + + put_device(&v->dev); +} + +static struct vdpa_driver vhost_vdpa_driver = { + .driver = { + .name = "vhost_vdpa", + }, + .probe = vhost_vdpa_probe, + .remove = vhost_vdpa_remove, +}; + +static int __init vhost_vdpa_init(void) +{ + int r; + + r = alloc_chrdev_region(&vhost_vdpa_major, 0, VHOST_VDPA_DEV_MAX, + "vhost-vdpa"); + if (r) + goto err_alloc_chrdev; + + r = vdpa_register_driver(&vhost_vdpa_driver); + if (r) + goto err_vdpa_register_driver; + + return 0; + +err_vdpa_register_driver: + unregister_chrdev_region(vhost_vdpa_major, VHOST_VDPA_DEV_MAX); +err_alloc_chrdev: + return r; +} +module_init(vhost_vdpa_init); + +static void __exit vhost_vdpa_exit(void) +{ + vdpa_unregister_driver(&vhost_vdpa_driver); + unregister_chrdev_region(vhost_vdpa_major, VHOST_VDPA_DEV_MAX); +} +module_exit(vhost_vdpa_exit); + +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("vDPA-based vhost backend for virtio"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/vhost.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/vhost.c new file mode 100644 index 0000000..0af561d --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/5.10.134-13.an8/vhost/vhost.c @@ -0,0 +1,2651 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * + * Author: Michael S. Tsirkin + * + * Inspiration, some code, and most witty comments come from + * Documentation/virtual/lguest/lguest.c, by Rusty Russell + * + * Generic code for virtio server in host kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vhost.h" + +static ushort max_mem_regions = 64; +module_param(max_mem_regions, ushort, 0444); +MODULE_PARM_DESC(max_mem_regions, + "Maximum number of memory regions in memory map. (default: 64)"); +static int max_iotlb_entries = 2048; +module_param(max_iotlb_entries, int, 0444); +MODULE_PARM_DESC(max_iotlb_entries, + "Maximum number of iotlb entries. (default: 2048)"); + +enum { + VHOST_MEMORY_F_LOG = 0x1, +}; + +#define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num]) +#define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num]) + +#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY +static void vhost_disable_cross_endian(struct vhost_virtqueue *vq) +{ + vq->user_be = !virtio_legacy_is_little_endian(); +} + +static void vhost_enable_cross_endian_big(struct vhost_virtqueue *vq) +{ + vq->user_be = true; +} + +static void vhost_enable_cross_endian_little(struct vhost_virtqueue *vq) +{ + vq->user_be = false; +} + +static long vhost_set_vring_endian(struct vhost_virtqueue *vq, int __user *argp) +{ + struct vhost_vring_state s; + + if (vq->private_data) + return -EBUSY; + + if (copy_from_user(&s, argp, sizeof(s))) + return -EFAULT; + + if (s.num != VHOST_VRING_LITTLE_ENDIAN && + s.num != VHOST_VRING_BIG_ENDIAN) + return -EINVAL; + + if (s.num == VHOST_VRING_BIG_ENDIAN) + vhost_enable_cross_endian_big(vq); + else + vhost_enable_cross_endian_little(vq); + + return 0; +} + +static long vhost_get_vring_endian(struct vhost_virtqueue *vq, u32 idx, + int __user *argp) +{ + struct vhost_vring_state s = { + .index = idx, + .num = vq->user_be + }; + + if (copy_to_user(argp, &s, sizeof(s))) + return -EFAULT; + + return 0; +} + +static void vhost_init_is_le(struct vhost_virtqueue *vq) +{ + /* Note for legacy virtio: user_be is initialized at reset time + * according to the host endianness. If userspace does not set an + * explicit endianness, the default behavior is native endian, as + * expected by legacy virtio. + */ + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) || !vq->user_be; +} +#else +static void vhost_disable_cross_endian(struct vhost_virtqueue *vq) +{ +} + +static long vhost_set_vring_endian(struct vhost_virtqueue *vq, int __user *argp) +{ + return -ENOIOCTLCMD; +} + +static long vhost_get_vring_endian(struct vhost_virtqueue *vq, u32 idx, + int __user *argp) +{ + return -ENOIOCTLCMD; +} + +static void vhost_init_is_le(struct vhost_virtqueue *vq) +{ + vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1) + || virtio_legacy_is_little_endian(); +} +#endif /* CONFIG_VHOST_CROSS_ENDIAN_LEGACY */ + +static void vhost_reset_is_le(struct vhost_virtqueue *vq) +{ + vhost_init_is_le(vq); +} + +struct vhost_flush_struct { + struct vhost_work work; + struct completion wait_event; +}; + +static void vhost_flush_work(struct vhost_work *work) +{ + struct vhost_flush_struct *s; + + s = container_of(work, struct vhost_flush_struct, work); + complete(&s->wait_event); +} + +static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh, + poll_table *pt) +{ + struct vhost_poll *poll; + + poll = container_of(pt, struct vhost_poll, table); + poll->wqh = wqh; + add_wait_queue(wqh, &poll->wait); +} + +static int vhost_poll_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, + void *key) +{ + struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait); + struct vhost_work *work = &poll->work; + + if (!(key_to_poll(key) & poll->mask)) + return 0; + + if (!poll->dev->use_worker) + work->fn(work); + else + vhost_poll_queue(poll); + + return 0; +} + +void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn) +{ + clear_bit(VHOST_WORK_QUEUED, &work->flags); + work->fn = fn; +} +EXPORT_SYMBOL_GPL(vhost_work_init); + +/* Init poll structure */ +void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, + __poll_t mask, struct vhost_dev *dev) +{ + init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); + init_poll_funcptr(&poll->table, vhost_poll_func); + poll->mask = mask; + poll->dev = dev; + poll->wqh = NULL; + + vhost_work_init(&poll->work, fn); +} +EXPORT_SYMBOL_GPL(vhost_poll_init); + +/* Start polling a file. We add ourselves to file's wait queue. The caller must + * keep a reference to a file until after vhost_poll_stop is called. */ +int vhost_poll_start(struct vhost_poll *poll, struct file *file) +{ + __poll_t mask; + + if (poll->wqh) + return 0; + + mask = vfs_poll(file, &poll->table); + if (mask) + vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask)); + if (mask & EPOLLERR) { + vhost_poll_stop(poll); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(vhost_poll_start); + +/* Stop polling a file. After this function returns, it becomes safe to drop the + * file reference. You must also flush afterwards. */ +void vhost_poll_stop(struct vhost_poll *poll) +{ + if (poll->wqh) { + remove_wait_queue(poll->wqh, &poll->wait); + poll->wqh = NULL; + } +} +EXPORT_SYMBOL_GPL(vhost_poll_stop); + +void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) +{ + struct vhost_flush_struct flush; + + if (dev->worker) { + init_completion(&flush.wait_event); + vhost_work_init(&flush.work, vhost_flush_work); + + vhost_work_queue(dev, &flush.work); + wait_for_completion(&flush.wait_event); + } +} +EXPORT_SYMBOL_GPL(vhost_work_flush); + +/* Flush any work that has been scheduled. When calling this, don't hold any + * locks that are also used by the callback. */ +void vhost_poll_flush(struct vhost_poll *poll) +{ + vhost_work_flush(poll->dev, &poll->work); +} +EXPORT_SYMBOL_GPL(vhost_poll_flush); + +void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work) +{ + if (!dev->worker) + return; + + if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) { + /* We can only add the work to the list after we're + * sure it was not in the list. + * test_and_set_bit() implies a memory barrier. + */ + llist_add(&work->node, &dev->work_list); + wake_up_process(dev->worker); + } +} +EXPORT_SYMBOL_GPL(vhost_work_queue); + +/* A lockless hint for busy polling code to exit the loop */ +bool vhost_has_work(struct vhost_dev *dev) +{ + return !llist_empty(&dev->work_list); +} +EXPORT_SYMBOL_GPL(vhost_has_work); + +void vhost_poll_queue(struct vhost_poll *poll) +{ + vhost_work_queue(poll->dev, &poll->work); +} +EXPORT_SYMBOL_GPL(vhost_poll_queue); + +static void __vhost_vq_meta_reset(struct vhost_virtqueue *vq) +{ + int j; + + for (j = 0; j < VHOST_NUM_ADDRS; j++) + vq->meta_iotlb[j] = NULL; +} + +static void vhost_vq_meta_reset(struct vhost_dev *d) +{ + int i; + + for (i = 0; i < d->nvqs; ++i) + __vhost_vq_meta_reset(d->vqs[i]); +} + +static void vhost_vring_call_reset(struct vhost_vring_call *call_ctx) +{ + call_ctx->ctx = NULL; + memset(&call_ctx->producer, 0x0, sizeof(struct irq_bypass_producer)); +} + +bool vhost_vq_is_setup(struct vhost_virtqueue *vq) +{ + return vq->avail && vq->desc && vq->used && vhost_vq_access_ok(vq); +} +EXPORT_SYMBOL_GPL(vhost_vq_is_setup); + +static void vhost_vq_reset(struct vhost_dev *dev, + struct vhost_virtqueue *vq) +{ + vq->num = 1; + vq->desc = NULL; + vq->avail = NULL; + vq->used = NULL; + vq->last_avail_idx = 0; + vq->avail_idx = 0; + vq->last_used_idx = 0; + vq->signalled_used = 0; + vq->signalled_used_valid = false; + vq->used_flags = 0; + vq->log_used = false; + vq->log_addr = -1ull; + vq->private_data = NULL; + vq->acked_features = 0; + vq->acked_backend_features = 0; + vq->log_base = NULL; + vq->error_ctx = NULL; + vq->kick = NULL; + vq->log_ctx = NULL; + vhost_disable_cross_endian(vq); + vhost_reset_is_le(vq); + vq->busyloop_timeout = 0; + vq->umem = NULL; + vq->iotlb = NULL; + vhost_vring_call_reset(&vq->call_ctx); + __vhost_vq_meta_reset(vq); +} + +static int vhost_worker(void *data) +{ + struct vhost_dev *dev = data; + struct vhost_work *work, *work_next; + struct llist_node *node; + + kthread_use_mm(dev->mm); + + for (;;) { + /* mb paired w/ kthread_stop */ + set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) { + __set_current_state(TASK_RUNNING); + break; + } + + node = llist_del_all(&dev->work_list); + if (!node) + schedule(); + + node = llist_reverse_order(node); + /* make sure flag is seen after deletion */ + smp_wmb(); + llist_for_each_entry_safe(work, work_next, node, node) { + clear_bit(VHOST_WORK_QUEUED, &work->flags); + __set_current_state(TASK_RUNNING); + kcov_remote_start_common(dev->kcov_handle); + work->fn(work); + kcov_remote_stop(); + if (need_resched()) + schedule(); + } + } + kthread_unuse_mm(dev->mm); + return 0; +} + +static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq) +{ + kfree(vq->indirect); + vq->indirect = NULL; + kfree(vq->log); + vq->log = NULL; + kfree(vq->heads); + vq->heads = NULL; +} + +/* Helper to allocate iovec buffers for all vqs. */ +static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) +{ + struct vhost_virtqueue *vq; + int i; + + for (i = 0; i < dev->nvqs; ++i) { + vq = dev->vqs[i]; + vq->indirect = kmalloc_array(UIO_MAXIOV, + sizeof(*vq->indirect), + GFP_KERNEL); + vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log), + GFP_KERNEL); + vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads), + GFP_KERNEL); + if (!vq->indirect || !vq->log || !vq->heads) + goto err_nomem; + } + return 0; + +err_nomem: + for (; i >= 0; --i) + vhost_vq_free_iovecs(dev->vqs[i]); + return -ENOMEM; +} + +static void vhost_dev_free_iovecs(struct vhost_dev *dev) +{ + int i; + + for (i = 0; i < dev->nvqs; ++i) + vhost_vq_free_iovecs(dev->vqs[i]); +} + +bool vhost_exceeds_weight(struct vhost_virtqueue *vq, + int pkts, int total_len) +{ + struct vhost_dev *dev = vq->dev; + + if ((dev->byte_weight && total_len >= dev->byte_weight) || + pkts >= dev->weight) { + vhost_poll_queue(&vq->poll); + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(vhost_exceeds_weight); + +static size_t vhost_get_avail_size(struct vhost_virtqueue *vq, + unsigned int num) +{ + size_t event __maybe_unused = + vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0; + + return sizeof(*vq->avail) + + sizeof(*vq->avail->ring) * num + event; +} + +static size_t vhost_get_used_size(struct vhost_virtqueue *vq, + unsigned int num) +{ + size_t event __maybe_unused = + vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0; + + return sizeof(*vq->used) + + sizeof(*vq->used->ring) * num + event; +} + +static size_t vhost_get_desc_size(struct vhost_virtqueue *vq, + unsigned int num) +{ + return sizeof(*vq->desc) * num; +} + +void vhost_dev_init(struct vhost_dev *dev, + struct vhost_virtqueue **vqs, int nvqs, + int iov_limit, int weight, int byte_weight, + bool use_worker, + int (*msg_handler)(struct vhost_dev *dev, + struct vhost_iotlb_msg *msg)) +{ + struct vhost_virtqueue *vq; + int i; + + dev->vqs = vqs; + dev->nvqs = nvqs; + mutex_init(&dev->mutex); + dev->log_ctx = NULL; + dev->umem = NULL; + dev->iotlb = NULL; + dev->mm = NULL; + dev->worker = NULL; + dev->iov_limit = iov_limit; + dev->weight = weight; + dev->byte_weight = byte_weight; + dev->use_worker = use_worker; + dev->msg_handler = msg_handler; + init_llist_head(&dev->work_list); + init_waitqueue_head(&dev->wait); + INIT_LIST_HEAD(&dev->read_list); + INIT_LIST_HEAD(&dev->pending_list); + spin_lock_init(&dev->iotlb_lock); + + + for (i = 0; i < dev->nvqs; ++i) { + vq = dev->vqs[i]; + vq->log = NULL; + vq->indirect = NULL; + vq->heads = NULL; + vq->dev = dev; + mutex_init(&vq->mutex); + vhost_vq_reset(dev, vq); + if (vq->handle_kick) + vhost_poll_init(&vq->poll, vq->handle_kick, + EPOLLIN, dev); + } +} +EXPORT_SYMBOL_GPL(vhost_dev_init); + +/* Caller should have device mutex */ +long vhost_dev_check_owner(struct vhost_dev *dev) +{ + /* Are you the owner? If not, I don't think you mean to do that */ + return dev->mm == current->mm ? 0 : -EPERM; +} +EXPORT_SYMBOL_GPL(vhost_dev_check_owner); + +struct vhost_attach_cgroups_struct { + struct vhost_work work; + struct task_struct *owner; + int ret; +}; + +static void vhost_attach_cgroups_work(struct vhost_work *work) +{ + struct vhost_attach_cgroups_struct *s; + + s = container_of(work, struct vhost_attach_cgroups_struct, work); + s->ret = cgroup_attach_task_all(s->owner, current); +} + +static int vhost_attach_cgroups(struct vhost_dev *dev) +{ + struct vhost_attach_cgroups_struct attach; + + attach.owner = current; + vhost_work_init(&attach.work, vhost_attach_cgroups_work); + vhost_work_queue(dev, &attach.work); + vhost_work_flush(dev, &attach.work); + return attach.ret; +} + +/* Caller should have device mutex */ +bool vhost_dev_has_owner(struct vhost_dev *dev) +{ + return dev->mm; +} +EXPORT_SYMBOL_GPL(vhost_dev_has_owner); + +static void vhost_attach_mm(struct vhost_dev *dev) +{ + /* No owner, become one */ + if (dev->use_worker) { + dev->mm = get_task_mm(current); + } else { + /* vDPA device does not use worker thead, so there's + * no need to hold the address space for mm. This help + * to avoid deadlock in the case of mmap() which may + * held the refcnt of the file and depends on release + * method to remove vma. + */ + dev->mm = current->mm; + mmgrab(dev->mm); + } +} + +static void vhost_detach_mm(struct vhost_dev *dev) +{ + if (!dev->mm) + return; + + if (dev->use_worker) + mmput(dev->mm); + else + mmdrop(dev->mm); + + dev->mm = NULL; +} + +/* Caller should have device mutex */ +long vhost_dev_set_owner(struct vhost_dev *dev) +{ + struct task_struct *worker; + int err; + + /* Is there an owner already? */ + if (vhost_dev_has_owner(dev)) { + err = -EBUSY; + goto err_mm; + } + + vhost_attach_mm(dev); + + dev->kcov_handle = kcov_common_handle(); + if (dev->use_worker) { + worker = kthread_create(vhost_worker, dev, + "vhost-%d", current->pid); + if (IS_ERR(worker)) { + err = PTR_ERR(worker); + goto err_worker; + } + + dev->worker = worker; + wake_up_process(worker); /* avoid contributing to loadavg */ + + err = vhost_attach_cgroups(dev); + if (err) + goto err_cgroup; + } + + err = vhost_dev_alloc_iovecs(dev); + if (err) + goto err_cgroup; + + return 0; +err_cgroup: + if (dev->worker) { + kthread_stop(dev->worker); + dev->worker = NULL; + } +err_worker: + vhost_detach_mm(dev); + dev->kcov_handle = 0; +err_mm: + return err; +} +EXPORT_SYMBOL_GPL(vhost_dev_set_owner); + +static struct vhost_iotlb *iotlb_alloc(void) +{ + return vhost_iotlb_alloc(max_iotlb_entries, + VHOST_IOTLB_FLAG_RETIRE); +} + +struct vhost_iotlb *vhost_dev_reset_owner_prepare(void) +{ + return iotlb_alloc(); +} +EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare); + +/* Caller should have device mutex */ +void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_iotlb *umem) +{ + int i; + + vhost_dev_cleanup(dev); + + dev->umem = umem; + /* We don't need VQ locks below since vhost_dev_cleanup makes sure + * VQs aren't running. + */ + for (i = 0; i < dev->nvqs; ++i) + dev->vqs[i]->umem = umem; +} +EXPORT_SYMBOL_GPL(vhost_dev_reset_owner); + +void vhost_dev_stop(struct vhost_dev *dev) +{ + int i; + + for (i = 0; i < dev->nvqs; ++i) { + if (dev->vqs[i]->kick && dev->vqs[i]->handle_kick) { + vhost_poll_stop(&dev->vqs[i]->poll); + vhost_poll_flush(&dev->vqs[i]->poll); + } + } +} +EXPORT_SYMBOL_GPL(vhost_dev_stop); + +static void vhost_clear_msg(struct vhost_dev *dev) +{ + struct vhost_msg_node *node, *n; + + spin_lock(&dev->iotlb_lock); + + list_for_each_entry_safe(node, n, &dev->read_list, node) { + list_del(&node->node); + kfree(node); + } + + list_for_each_entry_safe(node, n, &dev->pending_list, node) { + list_del(&node->node); + kfree(node); + } + + spin_unlock(&dev->iotlb_lock); +} + +void vhost_dev_cleanup(struct vhost_dev *dev) +{ + int i; + + for (i = 0; i < dev->nvqs; ++i) { + if (dev->vqs[i]->error_ctx) + eventfd_ctx_put(dev->vqs[i]->error_ctx); + if (dev->vqs[i]->kick) + fput(dev->vqs[i]->kick); + if (dev->vqs[i]->call_ctx.ctx) + eventfd_ctx_put(dev->vqs[i]->call_ctx.ctx); + vhost_vq_reset(dev, dev->vqs[i]); + } + vhost_dev_free_iovecs(dev); + if (dev->log_ctx) + eventfd_ctx_put(dev->log_ctx); + dev->log_ctx = NULL; + /* No one will access memory at this point */ + vhost_iotlb_free(dev->umem); + dev->umem = NULL; + vhost_iotlb_free(dev->iotlb); + dev->iotlb = NULL; + vhost_clear_msg(dev); + wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); + WARN_ON(!llist_empty(&dev->work_list)); + if (dev->worker) { + kthread_stop(dev->worker); + dev->worker = NULL; + dev->kcov_handle = 0; + } + vhost_detach_mm(dev); +} +EXPORT_SYMBOL_GPL(vhost_dev_cleanup); + +static bool log_access_ok(void __user *log_base, u64 addr, unsigned long sz) +{ + u64 a = addr / VHOST_PAGE_SIZE / 8; + + /* Make sure 64 bit math will not overflow. */ + if (a > ULONG_MAX - (unsigned long)log_base || + a + (unsigned long)log_base > ULONG_MAX) + return false; + + return access_ok(log_base + a, + (sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8); +} + +/* Make sure 64 bit math will not overflow. */ +static bool vhost_overflow(u64 uaddr, u64 size) +{ + if (uaddr > ULONG_MAX || size > ULONG_MAX) + return true; + + if (!size) + return false; + + return uaddr > ULONG_MAX - size + 1; +} + +/* Caller should have vq mutex and device mutex. */ +static bool vq_memory_access_ok(void __user *log_base, struct vhost_iotlb *umem, + int log_all) +{ + struct vhost_iotlb_map *map; + + if (!umem) + return false; + + list_for_each_entry(map, &umem->list, link) { + unsigned long a = map->addr; + + if (vhost_overflow(map->addr, map->size)) + return false; + + + if (!access_ok((void __user *)a, map->size)) + return false; + else if (log_all && !log_access_ok(log_base, + map->start, + map->size)) + return false; + } + return true; +} + +static inline void __user *vhost_vq_meta_fetch(struct vhost_virtqueue *vq, + u64 addr, unsigned int size, + int type) +{ + const struct vhost_iotlb_map *map = vq->meta_iotlb[type]; + + if (!map) + return NULL; + + return (void __user *)(uintptr_t)(map->addr + addr - map->start); +} + +/* Can we switch to this memory table? */ +/* Caller should have device mutex but not vq mutex */ +static bool memory_access_ok(struct vhost_dev *d, struct vhost_iotlb *umem, + int log_all) +{ + int i; + + for (i = 0; i < d->nvqs; ++i) { + bool ok; + bool log; + + mutex_lock(&d->vqs[i]->mutex); + log = log_all || vhost_has_feature(d->vqs[i], VHOST_F_LOG_ALL); + /* If ring is inactive, will check when it's enabled. */ + if (d->vqs[i]->private_data) + ok = vq_memory_access_ok(d->vqs[i]->log_base, + umem, log); + else + ok = true; + mutex_unlock(&d->vqs[i]->mutex); + if (!ok) + return false; + } + return true; +} + +static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, + struct iovec iov[], int iov_size, int access); + +static int vhost_copy_to_user(struct vhost_virtqueue *vq, void __user *to, + const void *from, unsigned size) +{ + int ret; + + if (!vq->iotlb) + return __copy_to_user(to, from, size); + else { + /* This function should be called after iotlb + * prefetch, which means we're sure that all vq + * could be access through iotlb. So -EAGAIN should + * not happen in this case. + */ + struct iov_iter t; + void __user *uaddr = vhost_vq_meta_fetch(vq, + (u64)(uintptr_t)to, size, + VHOST_ADDR_USED); + + if (uaddr) + return __copy_to_user(uaddr, from, size); + + ret = translate_desc(vq, (u64)(uintptr_t)to, size, vq->iotlb_iov, + ARRAY_SIZE(vq->iotlb_iov), + VHOST_ACCESS_WO); + if (ret < 0) + goto out; + iov_iter_init(&t, WRITE, vq->iotlb_iov, ret, size); + ret = copy_to_iter(from, size, &t); + if (ret == size) + ret = 0; + } +out: + return ret; +} + +static int vhost_copy_from_user(struct vhost_virtqueue *vq, void *to, + void __user *from, unsigned size) +{ + int ret; + + if (!vq->iotlb) + return __copy_from_user(to, from, size); + else { + /* This function should be called after iotlb + * prefetch, which means we're sure that vq + * could be access through iotlb. So -EAGAIN should + * not happen in this case. + */ + void __user *uaddr = vhost_vq_meta_fetch(vq, + (u64)(uintptr_t)from, size, + VHOST_ADDR_DESC); + struct iov_iter f; + + if (uaddr) + return __copy_from_user(to, uaddr, size); + + ret = translate_desc(vq, (u64)(uintptr_t)from, size, vq->iotlb_iov, + ARRAY_SIZE(vq->iotlb_iov), + VHOST_ACCESS_RO); + if (ret < 0) { + vq_err(vq, "IOTLB translation failure: uaddr " + "%p size 0x%llx\n", from, + (unsigned long long) size); + goto out; + } + iov_iter_init(&f, READ, vq->iotlb_iov, ret, size); + ret = copy_from_iter(to, size, &f); + if (ret == size) + ret = 0; + } + +out: + return ret; +} + +static void __user *__vhost_get_user_slow(struct vhost_virtqueue *vq, + void __user *addr, unsigned int size, + int type) +{ + int ret; + + ret = translate_desc(vq, (u64)(uintptr_t)addr, size, vq->iotlb_iov, + ARRAY_SIZE(vq->iotlb_iov), + VHOST_ACCESS_RO); + if (ret < 0) { + vq_err(vq, "IOTLB translation failure: uaddr " + "%p size 0x%llx\n", addr, + (unsigned long long) size); + return NULL; + } + + if (ret != 1 || vq->iotlb_iov[0].iov_len != size) { + vq_err(vq, "Non atomic userspace memory access: uaddr " + "%p size 0x%llx\n", addr, + (unsigned long long) size); + return NULL; + } + + return vq->iotlb_iov[0].iov_base; +} + +/* This function should be called after iotlb + * prefetch, which means we're sure that vq + * could be access through iotlb. So -EAGAIN should + * not happen in this case. + */ +static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq, + void __user *addr, unsigned int size, + int type) +{ + void __user *uaddr = vhost_vq_meta_fetch(vq, + (u64)(uintptr_t)addr, size, type); + if (uaddr) + return uaddr; + + return __vhost_get_user_slow(vq, addr, size, type); +} + +#define vhost_put_user(vq, x, ptr) \ +({ \ + int ret; \ + if (!vq->iotlb) { \ + ret = __put_user(x, ptr); \ + } else { \ + __typeof__(ptr) to = \ + (__typeof__(ptr)) __vhost_get_user(vq, ptr, \ + sizeof(*ptr), VHOST_ADDR_USED); \ + if (to != NULL) \ + ret = __put_user(x, to); \ + else \ + ret = -EFAULT; \ + } \ + ret; \ +}) + +static inline int vhost_put_avail_event(struct vhost_virtqueue *vq) +{ + return vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx), + vhost_avail_event(vq)); +} + +static inline int vhost_put_used(struct vhost_virtqueue *vq, + struct vring_used_elem *head, int idx, + int count) +{ + return vhost_copy_to_user(vq, vq->used->ring + idx, head, + count * sizeof(*head)); +} + +static inline int vhost_put_used_flags(struct vhost_virtqueue *vq) + +{ + return vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags), + &vq->used->flags); +} + +static inline int vhost_put_used_idx(struct vhost_virtqueue *vq) + +{ + return vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx), + &vq->used->idx); +} + +#define vhost_get_user(vq, x, ptr, type) \ +({ \ + int ret; \ + if (!vq->iotlb) { \ + ret = __get_user(x, ptr); \ + } else { \ + __typeof__(ptr) from = \ + (__typeof__(ptr)) __vhost_get_user(vq, ptr, \ + sizeof(*ptr), \ + type); \ + if (from != NULL) \ + ret = __get_user(x, from); \ + else \ + ret = -EFAULT; \ + } \ + ret; \ +}) + +#define vhost_get_avail(vq, x, ptr) \ + vhost_get_user(vq, x, ptr, VHOST_ADDR_AVAIL) + +#define vhost_get_used(vq, x, ptr) \ + vhost_get_user(vq, x, ptr, VHOST_ADDR_USED) + +static void vhost_dev_lock_vqs(struct vhost_dev *d) +{ + int i = 0; + for (i = 0; i < d->nvqs; ++i) + mutex_lock_nested(&d->vqs[i]->mutex, i); +} + +static void vhost_dev_unlock_vqs(struct vhost_dev *d) +{ + int i = 0; + for (i = 0; i < d->nvqs; ++i) + mutex_unlock(&d->vqs[i]->mutex); +} + +static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq, + __virtio16 *idx) +{ + return vhost_get_avail(vq, *idx, &vq->avail->idx); +} + +static inline int vhost_get_avail_head(struct vhost_virtqueue *vq, + __virtio16 *head, int idx) +{ + return vhost_get_avail(vq, *head, + &vq->avail->ring[idx & (vq->num - 1)]); +} + +static inline int vhost_get_avail_flags(struct vhost_virtqueue *vq, + __virtio16 *flags) +{ + return vhost_get_avail(vq, *flags, &vq->avail->flags); +} + +static inline int vhost_get_used_event(struct vhost_virtqueue *vq, + __virtio16 *event) +{ + return vhost_get_avail(vq, *event, vhost_used_event(vq)); +} + +static inline int vhost_get_used_idx(struct vhost_virtqueue *vq, + __virtio16 *idx) +{ + return vhost_get_used(vq, *idx, &vq->used->idx); +} + +static inline int vhost_get_desc(struct vhost_virtqueue *vq, + struct vring_desc *desc, int idx) +{ + return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc)); +} + +static void vhost_iotlb_notify_vq(struct vhost_dev *d, + struct vhost_iotlb_msg *msg) +{ + struct vhost_msg_node *node, *n; + + spin_lock(&d->iotlb_lock); + + list_for_each_entry_safe(node, n, &d->pending_list, node) { + struct vhost_iotlb_msg *vq_msg = &node->msg.iotlb; + if (msg->iova <= vq_msg->iova && + msg->iova + msg->size - 1 >= vq_msg->iova && + vq_msg->type == VHOST_IOTLB_MISS) { + vhost_poll_queue(&node->vq->poll); + list_del(&node->node); + kfree(node); + } + } + + spin_unlock(&d->iotlb_lock); +} + +static bool umem_access_ok(u64 uaddr, u64 size, int access) +{ + unsigned long a = uaddr; + + /* Make sure 64 bit math will not overflow. */ + if (vhost_overflow(uaddr, size)) + return false; + + if ((access & VHOST_ACCESS_RO) && + !access_ok((void __user *)a, size)) + return false; + if ((access & VHOST_ACCESS_WO) && + !access_ok((void __user *)a, size)) + return false; + return true; +} + +static int vhost_process_iotlb_msg(struct vhost_dev *dev, + struct vhost_iotlb_msg *msg) +{ + int ret = 0; + + mutex_lock(&dev->mutex); + vhost_dev_lock_vqs(dev); + switch (msg->type) { + case VHOST_IOTLB_UPDATE: + if (!dev->iotlb) { + ret = -EFAULT; + break; + } + if (!umem_access_ok(msg->uaddr, msg->size, msg->perm)) { + ret = -EFAULT; + break; + } + vhost_vq_meta_reset(dev); + if (vhost_iotlb_add_range(dev->iotlb, msg->iova, + msg->iova + msg->size - 1, + msg->uaddr, msg->perm)) { + ret = -ENOMEM; + break; + } + vhost_iotlb_notify_vq(dev, msg); + break; + case VHOST_IOTLB_INVALIDATE: + if (!dev->iotlb) { + ret = -EFAULT; + break; + } + vhost_vq_meta_reset(dev); + vhost_iotlb_del_range(dev->iotlb, msg->iova, + msg->iova + msg->size - 1); + break; + default: + ret = -EINVAL; + break; + } + + vhost_dev_unlock_vqs(dev); + mutex_unlock(&dev->mutex); + + return ret; +} +ssize_t vhost_chr_write_iter(struct vhost_dev *dev, + struct iov_iter *from) +{ + struct vhost_iotlb_msg msg; + size_t offset; + int type, ret; + + ret = copy_from_iter(&type, sizeof(type), from); + if (ret != sizeof(type)) { + ret = -EINVAL; + goto done; + } + + switch (type) { + case VHOST_IOTLB_MSG: + /* There maybe a hole after type for V1 message type, + * so skip it here. + */ + offset = offsetof(struct vhost_msg, iotlb) - sizeof(int); + break; + case VHOST_IOTLB_MSG_V2: + offset = sizeof(__u32); + break; + default: + ret = -EINVAL; + goto done; + } + + iov_iter_advance(from, offset); + ret = copy_from_iter(&msg, sizeof(msg), from); + if (ret != sizeof(msg)) { + ret = -EINVAL; + goto done; + } + + if (dev->msg_handler) + ret = dev->msg_handler(dev, &msg); + else + ret = vhost_process_iotlb_msg(dev, &msg); + if (ret) { + ret = -EFAULT; + goto done; + } + + ret = (type == VHOST_IOTLB_MSG) ? sizeof(struct vhost_msg) : + sizeof(struct vhost_msg_v2); +done: + return ret; +} +EXPORT_SYMBOL(vhost_chr_write_iter); + +__poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev, + poll_table *wait) +{ + __poll_t mask = 0; + + poll_wait(file, &dev->wait, wait); + + if (!list_empty(&dev->read_list)) + mask |= EPOLLIN | EPOLLRDNORM; + + return mask; +} +EXPORT_SYMBOL(vhost_chr_poll); + +ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to, + int noblock) +{ + DEFINE_WAIT(wait); + struct vhost_msg_node *node; + ssize_t ret = 0; + unsigned size = sizeof(struct vhost_msg); + + if (iov_iter_count(to) < size) + return 0; + + while (1) { + if (!noblock) + prepare_to_wait(&dev->wait, &wait, + TASK_INTERRUPTIBLE); + + node = vhost_dequeue_msg(dev, &dev->read_list); + if (node) + break; + if (noblock) { + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + if (!dev->iotlb) { + ret = -EBADFD; + break; + } + + schedule(); + } + + if (!noblock) + finish_wait(&dev->wait, &wait); + + if (node) { + struct vhost_iotlb_msg *msg; + void *start = &node->msg; + + switch (node->msg.type) { + case VHOST_IOTLB_MSG: + size = sizeof(node->msg); + msg = &node->msg.iotlb; + break; + case VHOST_IOTLB_MSG_V2: + size = sizeof(node->msg_v2); + msg = &node->msg_v2.iotlb; + break; + default: + BUG(); + break; + } + + ret = copy_to_iter(start, size, to); + if (ret != size || msg->type != VHOST_IOTLB_MISS) { + kfree(node); + return ret; + } + vhost_enqueue_msg(dev, &dev->pending_list, node); + } + + return ret; +} +EXPORT_SYMBOL_GPL(vhost_chr_read_iter); + +static int vhost_iotlb_miss(struct vhost_virtqueue *vq, u64 iova, int access) +{ + struct vhost_dev *dev = vq->dev; + struct vhost_msg_node *node; + struct vhost_iotlb_msg *msg; + bool v2 = vhost_backend_has_feature(vq, VHOST_BACKEND_F_IOTLB_MSG_V2); + + node = vhost_new_msg(vq, v2 ? VHOST_IOTLB_MSG_V2 : VHOST_IOTLB_MSG); + if (!node) + return -ENOMEM; + + if (v2) { + node->msg_v2.type = VHOST_IOTLB_MSG_V2; + msg = &node->msg_v2.iotlb; + } else { + msg = &node->msg.iotlb; + } + + msg->type = VHOST_IOTLB_MISS; + msg->iova = iova; + msg->perm = access; + + vhost_enqueue_msg(dev, &dev->read_list, node); + + return 0; +} + +static bool vq_access_ok(struct vhost_virtqueue *vq, unsigned int num, + vring_desc_t __user *desc, + vring_avail_t __user *avail, + vring_used_t __user *used) + +{ + /* If an IOTLB device is present, the vring addresses are + * GIOVAs. Access validation occurs at prefetch time. */ + if (vq->iotlb) + return true; + + return access_ok(desc, vhost_get_desc_size(vq, num)) && + access_ok(avail, vhost_get_avail_size(vq, num)) && + access_ok(used, vhost_get_used_size(vq, num)); +} + +static void vhost_vq_meta_update(struct vhost_virtqueue *vq, + const struct vhost_iotlb_map *map, + int type) +{ + int access = (type == VHOST_ADDR_USED) ? + VHOST_ACCESS_WO : VHOST_ACCESS_RO; + + if (likely(map->perm & access)) + vq->meta_iotlb[type] = map; +} + +static bool iotlb_access_ok(struct vhost_virtqueue *vq, + int access, u64 addr, u64 len, int type) +{ + const struct vhost_iotlb_map *map; + struct vhost_iotlb *umem = vq->iotlb; + u64 s = 0, size, orig_addr = addr, last = addr + len - 1; + + if (vhost_vq_meta_fetch(vq, addr, len, type)) + return true; + + while (len > s) { + map = vhost_iotlb_itree_first(umem, addr, last); + if (map == NULL || map->start > addr) { + vhost_iotlb_miss(vq, addr, access); + return false; + } else if (!(map->perm & access)) { + /* Report the possible access violation by + * request another translation from userspace. + */ + return false; + } + + size = map->size - addr + map->start; + + if (orig_addr == addr && size >= len) + vhost_vq_meta_update(vq, map, type); + + s += size; + addr += size; + } + + return true; +} + +int vq_meta_prefetch(struct vhost_virtqueue *vq) +{ + unsigned int num = vq->num; + + if (!vq->iotlb) + return 1; + + return iotlb_access_ok(vq, VHOST_MAP_RO, (u64)(uintptr_t)vq->desc, + vhost_get_desc_size(vq, num), VHOST_ADDR_DESC) && + iotlb_access_ok(vq, VHOST_MAP_RO, (u64)(uintptr_t)vq->avail, + vhost_get_avail_size(vq, num), + VHOST_ADDR_AVAIL) && + iotlb_access_ok(vq, VHOST_MAP_WO, (u64)(uintptr_t)vq->used, + vhost_get_used_size(vq, num), VHOST_ADDR_USED); +} +EXPORT_SYMBOL_GPL(vq_meta_prefetch); + +/* Can we log writes? */ +/* Caller should have device mutex but not vq mutex */ +bool vhost_log_access_ok(struct vhost_dev *dev) +{ + return memory_access_ok(dev, dev->umem, 1); +} +EXPORT_SYMBOL_GPL(vhost_log_access_ok); + +static bool vq_log_used_access_ok(struct vhost_virtqueue *vq, + void __user *log_base, + bool log_used, + u64 log_addr) +{ + /* If an IOTLB device is present, log_addr is a GIOVA that + * will never be logged by log_used(). */ + if (vq->iotlb) + return true; + + return !log_used || log_access_ok(log_base, log_addr, + vhost_get_used_size(vq, vq->num)); +} + +/* Verify access for write logging. */ +/* Caller should have vq mutex and device mutex */ +static bool vq_log_access_ok(struct vhost_virtqueue *vq, + void __user *log_base) +{ + return vq_memory_access_ok(log_base, vq->umem, + vhost_has_feature(vq, VHOST_F_LOG_ALL)) && + vq_log_used_access_ok(vq, log_base, vq->log_used, vq->log_addr); +} + +/* Can we start vq? */ +/* Caller should have vq mutex and device mutex */ +bool vhost_vq_access_ok(struct vhost_virtqueue *vq) +{ + if (!vq_log_access_ok(vq, vq->log_base)) + return false; + + return vq_access_ok(vq, vq->num, vq->desc, vq->avail, vq->used); +} +EXPORT_SYMBOL_GPL(vhost_vq_access_ok); + +static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) +{ + struct vhost_memory mem, *newmem; + struct vhost_memory_region *region; + struct vhost_iotlb *newumem, *oldumem; + unsigned long size = offsetof(struct vhost_memory, regions); + int i; + + if (copy_from_user(&mem, m, size)) + return -EFAULT; + if (mem.padding) + return -EOPNOTSUPP; + if (mem.nregions > max_mem_regions) + return -E2BIG; + newmem = kvzalloc(struct_size(newmem, regions, mem.nregions), + GFP_KERNEL); + if (!newmem) + return -ENOMEM; + + memcpy(newmem, &mem, size); + if (copy_from_user(newmem->regions, m->regions, + flex_array_size(newmem, regions, mem.nregions))) { + kvfree(newmem); + return -EFAULT; + } + + newumem = iotlb_alloc(); + if (!newumem) { + kvfree(newmem); + return -ENOMEM; + } + + for (region = newmem->regions; + region < newmem->regions + mem.nregions; + region++) { + if (vhost_iotlb_add_range(newumem, + region->guest_phys_addr, + region->guest_phys_addr + + region->memory_size - 1, + region->userspace_addr, + VHOST_MAP_RW)) + goto err; + } + + if (!memory_access_ok(d, newumem, 0)) + goto err; + + oldumem = d->umem; + d->umem = newumem; + + /* All memory accesses are done under some VQ mutex. */ + for (i = 0; i < d->nvqs; ++i) { + mutex_lock(&d->vqs[i]->mutex); + d->vqs[i]->umem = newumem; + mutex_unlock(&d->vqs[i]->mutex); + } + + kvfree(newmem); + vhost_iotlb_free(oldumem); + return 0; + +err: + vhost_iotlb_free(newumem); + kvfree(newmem); + return -EFAULT; +} + +static long vhost_vring_set_num(struct vhost_dev *d, + struct vhost_virtqueue *vq, + void __user *argp) +{ + struct vhost_vring_state s; + + /* Resizing ring with an active backend? + * You don't want to do that. */ + if (vq->private_data) + return -EBUSY; + + if (copy_from_user(&s, argp, sizeof s)) + return -EFAULT; + + if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) + return -EINVAL; + vq->num = s.num; + + return 0; +} + +static long vhost_vring_set_addr(struct vhost_dev *d, + struct vhost_virtqueue *vq, + void __user *argp) +{ + struct vhost_vring_addr a; + + if (copy_from_user(&a, argp, sizeof a)) + return -EFAULT; + if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) + return -EOPNOTSUPP; + + /* For 32bit, verify that the top 32bits of the user + data are set to zero. */ + if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr || + (u64)(unsigned long)a.used_user_addr != a.used_user_addr || + (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr) + return -EFAULT; + + /* Make sure it's safe to cast pointers to vring types. */ + BUILD_BUG_ON(__alignof__ *vq->avail > VRING_AVAIL_ALIGN_SIZE); + BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE); + if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) || + (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) || + (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1))) + return -EINVAL; + + /* We only verify access here if backend is configured. + * If it is not, we don't as size might not have been setup. + * We will verify when backend is configured. */ + if (vq->private_data) { + if (!vq_access_ok(vq, vq->num, + (void __user *)(unsigned long)a.desc_user_addr, + (void __user *)(unsigned long)a.avail_user_addr, + (void __user *)(unsigned long)a.used_user_addr)) + return -EINVAL; + + /* Also validate log access for used ring if enabled. */ + if (!vq_log_used_access_ok(vq, vq->log_base, + a.flags & (0x1 << VHOST_VRING_F_LOG), + a.log_guest_addr)) + return -EINVAL; + } + + vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG)); + vq->desc = (void __user *)(unsigned long)a.desc_user_addr; + vq->avail = (void __user *)(unsigned long)a.avail_user_addr; + vq->log_addr = a.log_guest_addr; + vq->used = (void __user *)(unsigned long)a.used_user_addr; + + return 0; +} + +static long vhost_vring_set_num_addr(struct vhost_dev *d, + struct vhost_virtqueue *vq, + unsigned int ioctl, + void __user *argp) +{ + long r; + + mutex_lock(&vq->mutex); + + switch (ioctl) { + case VHOST_SET_VRING_NUM: + r = vhost_vring_set_num(d, vq, argp); + break; + case VHOST_SET_VRING_ADDR: + r = vhost_vring_set_addr(d, vq, argp); + break; + default: + BUG(); + } + + mutex_unlock(&vq->mutex); + + return r; +} +long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) +{ + struct file *eventfp, *filep = NULL; + bool pollstart = false, pollstop = false; + struct eventfd_ctx *ctx = NULL; + u32 __user *idxp = argp; + struct vhost_virtqueue *vq; + struct vhost_vring_state s; + struct vhost_vring_file f; + u32 idx; + long r; + + r = get_user(idx, idxp); + if (r < 0) + return r; + if (idx >= d->nvqs) + return -ENOBUFS; + + idx = array_index_nospec(idx, d->nvqs); + vq = d->vqs[idx]; + + if (ioctl == VHOST_SET_VRING_NUM || + ioctl == VHOST_SET_VRING_ADDR) { + return vhost_vring_set_num_addr(d, vq, ioctl, argp); + } + + mutex_lock(&vq->mutex); + + switch (ioctl) { + case VHOST_SET_VRING_BASE: + printk("set vring base qid %d features 0x%llx\n", idx, vq->acked_features); + /* Moving base with an active backend? + * You don't want to do that. */ + if (vq->private_data) { + r = -EBUSY; + break; + } + if (copy_from_user(&s, argp, sizeof s)) { + r = -EFAULT; + break; + } + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) { + vq->last_avail_idx = s.num & 0xffff; + vq->last_used_idx = (s.num >> 16) & 0xffff; + } else { + if (s.num > 0xffff) { + r = -EINVAL; + break; + } + vq->last_avail_idx = s.num; + } + /* Forget the cached index value. */ + vq->avail_idx = vq->last_avail_idx; + printk("set vring base. avail idx 0x%x used idx 0x%x\n", vq->last_avail_idx, vq->last_used_idx); + break; + case VHOST_GET_VRING_BASE: + if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) + s.num = (u32)vq->last_avail_idx | ((u32)vq->last_used_idx << 16); + else + s.num = vq->last_avail_idx; + if (copy_to_user(argp, &s, sizeof s)) + r = -EFAULT; + break; + case VHOST_SET_VRING_KICK: + if (copy_from_user(&f, argp, sizeof f)) { + r = -EFAULT; + break; + } + eventfp = f.fd == VHOST_FILE_UNBIND ? NULL : eventfd_fget(f.fd); + if (IS_ERR(eventfp)) { + r = PTR_ERR(eventfp); + break; + } + if (eventfp != vq->kick) { + pollstop = (filep = vq->kick) != NULL; + pollstart = (vq->kick = eventfp) != NULL; + } else + filep = eventfp; + break; + case VHOST_SET_VRING_CALL: + if (copy_from_user(&f, argp, sizeof f)) { + r = -EFAULT; + break; + } + ctx = f.fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(f.fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); + break; + } + + swap(ctx, vq->call_ctx.ctx); + break; + case VHOST_SET_VRING_ERR: + if (copy_from_user(&f, argp, sizeof f)) { + r = -EFAULT; + break; + } + ctx = f.fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(f.fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); + break; + } + swap(ctx, vq->error_ctx); + break; + case VHOST_SET_VRING_ENDIAN: + r = vhost_set_vring_endian(vq, argp); + break; + case VHOST_GET_VRING_ENDIAN: + r = vhost_get_vring_endian(vq, idx, argp); + break; + case VHOST_SET_VRING_BUSYLOOP_TIMEOUT: + if (copy_from_user(&s, argp, sizeof(s))) { + r = -EFAULT; + break; + } + vq->busyloop_timeout = s.num; + break; + case VHOST_GET_VRING_BUSYLOOP_TIMEOUT: + s.index = idx; + s.num = vq->busyloop_timeout; + if (copy_to_user(argp, &s, sizeof(s))) + r = -EFAULT; + break; + default: + r = -ENOIOCTLCMD; + } + + if (pollstop && vq->handle_kick) + vhost_poll_stop(&vq->poll); + + if (!IS_ERR_OR_NULL(ctx)) + eventfd_ctx_put(ctx); + if (filep) + fput(filep); + + if (pollstart && vq->handle_kick) + r = vhost_poll_start(&vq->poll, vq->kick); + + mutex_unlock(&vq->mutex); + + if (pollstop && vq->handle_kick) + vhost_poll_flush(&vq->poll); + return r; +} +EXPORT_SYMBOL_GPL(vhost_vring_ioctl); + +int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled) +{ + struct vhost_iotlb *niotlb, *oiotlb; + int i; + + niotlb = iotlb_alloc(); + if (!niotlb) + return -ENOMEM; + + oiotlb = d->iotlb; + d->iotlb = niotlb; + + for (i = 0; i < d->nvqs; ++i) { + struct vhost_virtqueue *vq = d->vqs[i]; + + mutex_lock(&vq->mutex); + vq->iotlb = niotlb; + __vhost_vq_meta_reset(vq); + mutex_unlock(&vq->mutex); + } + + vhost_iotlb_free(oiotlb); + + return 0; +} +EXPORT_SYMBOL_GPL(vhost_init_device_iotlb); + +/* Caller must have device mutex */ +long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) +{ + struct eventfd_ctx *ctx; + u64 p; + long r; + int i, fd; + + /* If you are not the owner, you can become one */ + if (ioctl == VHOST_SET_OWNER) { + r = vhost_dev_set_owner(d); + goto done; + } + + /* You must be the owner to do anything else */ + r = vhost_dev_check_owner(d); + if (r) + goto done; + + switch (ioctl) { + case VHOST_SET_MEM_TABLE: + r = vhost_set_memory(d, argp); + break; + case VHOST_SET_LOG_BASE: + if (copy_from_user(&p, argp, sizeof p)) { + r = -EFAULT; + break; + } + if ((u64)(unsigned long)p != p) { + r = -EFAULT; + break; + } + for (i = 0; i < d->nvqs; ++i) { + struct vhost_virtqueue *vq; + void __user *base = (void __user *)(unsigned long)p; + vq = d->vqs[i]; + mutex_lock(&vq->mutex); + /* If ring is inactive, will check when it's enabled. */ + if (vq->private_data && !vq_log_access_ok(vq, base)) + r = -EFAULT; + else + vq->log_base = base; + mutex_unlock(&vq->mutex); + } + break; + case VHOST_SET_LOG_FD: + r = get_user(fd, (int __user *)argp); + if (r < 0) + break; + ctx = fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); + break; + } + swap(ctx, d->log_ctx); + for (i = 0; i < d->nvqs; ++i) { + mutex_lock(&d->vqs[i]->mutex); + d->vqs[i]->log_ctx = d->log_ctx; + mutex_unlock(&d->vqs[i]->mutex); + } + if (ctx) + eventfd_ctx_put(ctx); + break; + default: + r = -ENOIOCTLCMD; + break; + } +done: + return r; +} +EXPORT_SYMBOL_GPL(vhost_dev_ioctl); + +/* TODO: This is really inefficient. We need something like get_user() + * (instruction directly accesses the data, with an exception table entry + * returning -EFAULT). See Documentation/x86/exception-tables.rst. + */ +static int set_bit_to_user(int nr, void __user *addr) +{ + unsigned long log = (unsigned long)addr; + struct page *page; + void *base; + int bit = nr + (log % PAGE_SIZE) * 8; + int r; + + r = pin_user_pages_fast(log, 1, FOLL_WRITE, &page); + if (r < 0) + return r; + BUG_ON(r != 1); + base = kmap_atomic(page); + set_bit(bit, base); + kunmap_atomic(base); + unpin_user_pages_dirty_lock(&page, 1, true); + return 0; +} + +static int log_write(void __user *log_base, + u64 write_address, u64 write_length) +{ + u64 write_page = write_address / VHOST_PAGE_SIZE; + int r; + + if (!write_length) + return 0; + write_length += write_address % VHOST_PAGE_SIZE; + for (;;) { + u64 base = (u64)(unsigned long)log_base; + u64 log = base + write_page / 8; + int bit = write_page % 8; + if ((u64)(unsigned long)log != log) + return -EFAULT; + r = set_bit_to_user(bit, (void __user *)(unsigned long)log); + if (r < 0) + return r; + if (write_length <= VHOST_PAGE_SIZE) + break; + write_length -= VHOST_PAGE_SIZE; + write_page += 1; + } + return r; +} + +static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len) +{ + struct vhost_iotlb *umem = vq->umem; + struct vhost_iotlb_map *u; + u64 start, end, l, min; + int r; + bool hit = false; + + while (len) { + min = len; + /* More than one GPAs can be mapped into a single HVA. So + * iterate all possible umems here to be safe. + */ + list_for_each_entry(u, &umem->list, link) { + if (u->addr > hva - 1 + len || + u->addr - 1 + u->size < hva) + continue; + start = max(u->addr, hva); + end = min(u->addr - 1 + u->size, hva - 1 + len); + l = end - start + 1; + r = log_write(vq->log_base, + u->start + start - u->addr, + l); + if (r < 0) + return r; + hit = true; + min = min(l, min); + } + + if (!hit) + return -EFAULT; + + len -= min; + hva += min; + } + + return 0; +} + +static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len) +{ + struct iovec *iov = vq->log_iov; + int i, ret; + + if (!vq->iotlb) + return log_write(vq->log_base, vq->log_addr + used_offset, len); + + ret = translate_desc(vq, (uintptr_t)vq->used + used_offset, + len, iov, 64, VHOST_ACCESS_WO); + if (ret < 0) + return ret; + + for (i = 0; i < ret; i++) { + ret = log_write_hva(vq, (uintptr_t)iov[i].iov_base, + iov[i].iov_len); + if (ret) + return ret; + } + + return 0; +} + +int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, + unsigned int log_num, u64 len, struct iovec *iov, int count) +{ + int i, r; + + /* Make sure data written is seen before log. */ + smp_wmb(); + + if (vq->iotlb) { + for (i = 0; i < count; i++) { + r = log_write_hva(vq, (uintptr_t)iov[i].iov_base, + iov[i].iov_len); + if (r < 0) + return r; + } + return 0; + } + + for (i = 0; i < log_num; ++i) { + u64 l = min(log[i].len, len); + r = log_write(vq->log_base, log[i].addr, l); + if (r < 0) + return r; + len -= l; + if (!len) { + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + return 0; + } + } + /* Length written exceeds what we have stored. This is a bug. */ + BUG(); + return 0; +} +EXPORT_SYMBOL_GPL(vhost_log_write); + +static int vhost_update_used_flags(struct vhost_virtqueue *vq) +{ + void __user *used; + if (vhost_put_used_flags(vq)) + return -EFAULT; + if (unlikely(vq->log_used)) { + /* Make sure the flag is seen before log. */ + smp_wmb(); + /* Log used flag write. */ + used = &vq->used->flags; + log_used(vq, (used - (void __user *)vq->used), + sizeof vq->used->flags); + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + } + return 0; +} + +static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event) +{ + if (vhost_put_avail_event(vq)) + return -EFAULT; + if (unlikely(vq->log_used)) { + void __user *used; + /* Make sure the event is seen before log. */ + smp_wmb(); + /* Log avail event write */ + used = vhost_avail_event(vq); + log_used(vq, (used - (void __user *)vq->used), + sizeof *vhost_avail_event(vq)); + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + } + return 0; +} + +int vhost_vq_init_access(struct vhost_virtqueue *vq) +{ + __virtio16 last_used_idx; + int r; + bool is_le = vq->is_le; + + if (!vq->private_data) + return 0; + + vhost_init_is_le(vq); + + r = vhost_update_used_flags(vq); + if (r) + goto err; + vq->signalled_used_valid = false; + if (!vq->iotlb && + !access_ok(&vq->used->idx, sizeof vq->used->idx)) { + r = -EFAULT; + goto err; + } + r = vhost_get_used_idx(vq, &last_used_idx); + if (r) { + vq_err(vq, "Can't access used idx at %p\n", + &vq->used->idx); + goto err; + } + vq->last_used_idx = vhost16_to_cpu(vq, last_used_idx); + return 0; + +err: + vq->is_le = is_le; + return r; +} +EXPORT_SYMBOL_GPL(vhost_vq_init_access); + +static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, + struct iovec iov[], int iov_size, int access) +{ + const struct vhost_iotlb_map *map; + struct vhost_dev *dev = vq->dev; + struct vhost_iotlb *umem = dev->iotlb ? dev->iotlb : dev->umem; + struct iovec *_iov; + u64 s = 0; + int ret = 0; + + while ((u64)len > s) { + u64 size; + if (unlikely(ret >= iov_size)) { + ret = -ENOBUFS; + break; + } + + map = vhost_iotlb_itree_first(umem, addr, addr + len - 1); + if (map == NULL || map->start > addr) { + if (umem != dev->iotlb) { + ret = -EFAULT; + break; + } + ret = -EAGAIN; + break; + } else if (!(map->perm & access)) { + ret = -EPERM; + break; + } + + _iov = iov + ret; + size = map->size - addr + map->start; + _iov->iov_len = min((u64)len - s, size); + _iov->iov_base = (void __user *)(unsigned long) + (map->addr + addr - map->start); + s += size; + addr += size; + ++ret; + } + + if (ret == -EAGAIN) + vhost_iotlb_miss(vq, addr, access); + return ret; +} + +/* Each buffer in the virtqueues is actually a chain of descriptors. This + * function returns the next descriptor in the chain, + * or -1U if we're at the end. */ +static unsigned next_desc(struct vhost_virtqueue *vq, struct vring_desc *desc) +{ + unsigned int next; + + /* If this descriptor says it doesn't chain, we're done. */ + if (!(desc->flags & cpu_to_vhost16(vq, VRING_DESC_F_NEXT))) + return -1U; + + /* Check they're not leading us off end of descriptors. */ + next = vhost16_to_cpu(vq, READ_ONCE(desc->next)); + return next; +} + +static int get_indirect(struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num, + struct vring_desc *indirect) +{ + struct vring_desc desc; + unsigned int i = 0, count, found = 0; + u32 len = vhost32_to_cpu(vq, indirect->len); + struct iov_iter from; + int ret, access; + + /* Sanity check */ + if (unlikely(len % sizeof desc)) { + vq_err(vq, "Invalid length in indirect descriptor: " + "len 0x%llx not multiple of 0x%zx\n", + (unsigned long long)len, + sizeof desc); + return -EINVAL; + } + + ret = translate_desc(vq, vhost64_to_cpu(vq, indirect->addr), len, vq->indirect, + UIO_MAXIOV, VHOST_ACCESS_RO); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Translation failure %d in indirect.\n", ret); + return ret; + } + iov_iter_init(&from, READ, vq->indirect, ret, len); + count = len / sizeof desc; + /* Buffers are chained via a 16 bit next field, so + * we can have at most 2^16 of these. */ + if (unlikely(count > USHRT_MAX + 1)) { + vq_err(vq, "Indirect buffer length too big: %d\n", + indirect->len); + return -E2BIG; + } + + do { + unsigned iov_count = *in_num + *out_num; + if (unlikely(++found > count)) { + vq_err(vq, "Loop detected: last one at %u " + "indirect size %u\n", + i, count); + return -EINVAL; + } + if (unlikely(!copy_from_iter_full(&desc, sizeof(desc), &from))) { + vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", + i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc); + return -EINVAL; + } + if (unlikely(desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_INDIRECT))) { + vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n", + i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc); + return -EINVAL; + } + + if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) + access = VHOST_ACCESS_WO; + else + access = VHOST_ACCESS_RO; + + ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr), + vhost32_to_cpu(vq, desc.len), iov + iov_count, + iov_size - iov_count, access); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Translation failure %d indirect idx %d\n", + ret, i); + return ret; + } + /* If this is an input descriptor, increment that count. */ + if (access == VHOST_ACCESS_WO) { + *in_num += ret; + if (unlikely(log && ret)) { + log[*log_num].addr = vhost64_to_cpu(vq, desc.addr); + log[*log_num].len = vhost32_to_cpu(vq, desc.len); + ++*log_num; + } + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (unlikely(*in_num)) { + vq_err(vq, "Indirect descriptor " + "has out after in: idx %d\n", i); + return -EINVAL; + } + *out_num += ret; + } + } while ((i = next_desc(vq, &desc)) != -1); + return 0; +} + +/* This looks in the virtqueue and for the first available buffer, and converts + * it to an iovec for convenient access. Since descriptors consist of some + * number of output then some number of input descriptors, it's actually two + * iovecs, but we pack them into one and note how many of each there were. + * + * This function returns the descriptor number found, or vq->num (which is + * never a valid descriptor number) if none was found. A negative code is + * returned on error. */ +int vhost_get_vq_desc(struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num) +{ + struct vring_desc desc; + unsigned int i, head, found = 0; + u16 last_avail_idx; + __virtio16 avail_idx; + __virtio16 ring_head; + int ret, access; + + /* Check it isn't doing very strange things with descriptor numbers. */ + last_avail_idx = vq->last_avail_idx; + + if (vq->avail_idx == vq->last_avail_idx) { + if (unlikely(vhost_get_avail_idx(vq, &avail_idx))) { + vq_err(vq, "Failed to access avail idx at %p\n", + &vq->avail->idx); + return -EFAULT; + } + vq->avail_idx = vhost16_to_cpu(vq, avail_idx); + + if (unlikely((u16)(vq->avail_idx - last_avail_idx) > vq->num)) { + vq_err(vq, "Guest moved used index from %u to %u", + last_avail_idx, vq->avail_idx); + return -EFAULT; + } + + /* If there's nothing new since last we looked, return + * invalid. + */ + if (vq->avail_idx == last_avail_idx) + return vq->num; + + /* Only get avail ring entries after they have been + * exposed by guest. + */ + smp_rmb(); + } + + /* Grab the next descriptor number they're advertising, and increment + * the index we've seen. */ + if (unlikely(vhost_get_avail_head(vq, &ring_head, last_avail_idx))) { + vq_err(vq, "Failed to read head: idx %d address %p\n", + last_avail_idx, + &vq->avail->ring[last_avail_idx % vq->num]); + return -EFAULT; + } + + head = vhost16_to_cpu(vq, ring_head); + + /* If their number is silly, that's an error. */ + if (unlikely(head >= vq->num)) { + vq_err(vq, "Guest says index %u > %u is available", + head, vq->num); + return -EINVAL; + } + + /* When we start there are none of either input nor output. */ + *out_num = *in_num = 0; + if (unlikely(log)) + *log_num = 0; + + i = head; + do { + unsigned iov_count = *in_num + *out_num; + if (unlikely(i >= vq->num)) { + vq_err(vq, "Desc index is %u > %u, head = %u", + i, vq->num, head); + return -EINVAL; + } + if (unlikely(++found > vq->num)) { + vq_err(vq, "Loop detected: last one at %u " + "vq size %u head %u\n", + i, vq->num, head); + return -EINVAL; + } + ret = vhost_get_desc(vq, &desc, i); + if (unlikely(ret)) { + vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", + i, vq->desc + i); + return -EFAULT; + } + if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_INDIRECT)) { + ret = get_indirect(vq, iov, iov_size, + out_num, in_num, + log, log_num, &desc); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Failure detected " + "in indirect descriptor at idx %d\n", i); + return ret; + } + continue; + } + + if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) + access = VHOST_ACCESS_WO; + else + access = VHOST_ACCESS_RO; + ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr), + vhost32_to_cpu(vq, desc.len), iov + iov_count, + iov_size - iov_count, access); + if (unlikely(ret < 0)) { + if (ret != -EAGAIN) + vq_err(vq, "Translation failure %d descriptor idx %d\n", + ret, i); + return ret; + } + if (access == VHOST_ACCESS_WO) { + /* If this is an input descriptor, + * increment that count. */ + *in_num += ret; + if (unlikely(log && ret)) { + log[*log_num].addr = vhost64_to_cpu(vq, desc.addr); + log[*log_num].len = vhost32_to_cpu(vq, desc.len); + ++*log_num; + } + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (unlikely(*in_num)) { + vq_err(vq, "Descriptor has out after in: " + "idx %d\n", i); + return -EINVAL; + } + *out_num += ret; + } + } while ((i = next_desc(vq, &desc)) != -1); + + /* On success, increment avail index. */ + vq->last_avail_idx++; + + /* Assume notifications from guest are disabled at this point, + * if they aren't we would need to update avail_event index. */ + BUG_ON(!(vq->used_flags & VRING_USED_F_NO_NOTIFY)); + return head; +} +EXPORT_SYMBOL_GPL(vhost_get_vq_desc); + +/* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */ +void vhost_discard_vq_desc(struct vhost_virtqueue *vq, int n) +{ + vq->last_avail_idx -= n; +} +EXPORT_SYMBOL_GPL(vhost_discard_vq_desc); + +/* After we've used one of their buffers, we tell them about it. We'll then + * want to notify the guest, using eventfd. */ +int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) +{ + struct vring_used_elem heads = { + cpu_to_vhost32(vq, head), + cpu_to_vhost32(vq, len) + }; + + return vhost_add_used_n(vq, &heads, 1); +} +EXPORT_SYMBOL_GPL(vhost_add_used); + +static int __vhost_add_used_n(struct vhost_virtqueue *vq, + struct vring_used_elem *heads, + unsigned count) +{ + vring_used_elem_t __user *used; + u16 old, new; + int start; + + start = vq->last_used_idx & (vq->num - 1); + used = vq->used->ring + start; + if (vhost_put_used(vq, heads, start, count)) { + vq_err(vq, "Failed to write used"); + return -EFAULT; + } + if (unlikely(vq->log_used)) { + /* Make sure data is seen before log. */ + smp_wmb(); + /* Log used ring entry write. */ + log_used(vq, ((void __user *)used - (void __user *)vq->used), + count * sizeof *used); + } + old = vq->last_used_idx; + new = (vq->last_used_idx += count); + /* If the driver never bothers to signal in a very long while, + * used index might wrap around. If that happens, invalidate + * signalled_used index we stored. TODO: make sure driver + * signals at least once in 2^16 and remove this. */ + if (unlikely((u16)(new - vq->signalled_used) < (u16)(new - old))) + vq->signalled_used_valid = false; + return 0; +} + +/* After we've used one of their buffers, we tell them about it. We'll then + * want to notify the guest, using eventfd. */ +int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, + unsigned count) +{ + int start, n, r; + + start = vq->last_used_idx & (vq->num - 1); + n = vq->num - start; + if (n < count) { + r = __vhost_add_used_n(vq, heads, n); + if (r < 0) + return r; + heads += n; + count -= n; + } + r = __vhost_add_used_n(vq, heads, count); + + /* Make sure buffer is written before we update index. */ + smp_wmb(); + if (vhost_put_used_idx(vq)) { + vq_err(vq, "Failed to increment used idx"); + return -EFAULT; + } + if (unlikely(vq->log_used)) { + /* Make sure used idx is seen before log. */ + smp_wmb(); + /* Log used index update. */ + log_used(vq, offsetof(struct vring_used, idx), + sizeof vq->used->idx); + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + } + return r; +} +EXPORT_SYMBOL_GPL(vhost_add_used_n); + +static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + __u16 old, new; + __virtio16 event; + bool v; + /* Flush out used index updates. This is paired + * with the barrier that the Guest executes when enabling + * interrupts. */ + smp_mb(); + + if (vhost_has_feature(vq, VIRTIO_F_NOTIFY_ON_EMPTY) && + unlikely(vq->avail_idx == vq->last_avail_idx)) + return true; + + if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) { + __virtio16 flags; + if (vhost_get_avail_flags(vq, &flags)) { + vq_err(vq, "Failed to get flags"); + return true; + } + return !(flags & cpu_to_vhost16(vq, VRING_AVAIL_F_NO_INTERRUPT)); + } + old = vq->signalled_used; + v = vq->signalled_used_valid; + new = vq->signalled_used = vq->last_used_idx; + vq->signalled_used_valid = true; + + if (unlikely(!v)) + return true; + + if (vhost_get_used_event(vq, &event)) { + vq_err(vq, "Failed to get used event idx"); + return true; + } + return vring_need_event(vhost16_to_cpu(vq, event), new, old); +} + +/* This actually signals the guest, using eventfd. */ +void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + /* Signal the Guest tell them we used something up. */ + if (vq->call_ctx.ctx && vhost_notify(dev, vq)) + eventfd_signal(vq->call_ctx.ctx, 1); +} +EXPORT_SYMBOL_GPL(vhost_signal); + +/* And here's the combo meal deal. Supersize me! */ +void vhost_add_used_and_signal(struct vhost_dev *dev, + struct vhost_virtqueue *vq, + unsigned int head, int len) +{ + vhost_add_used(vq, head, len); + vhost_signal(dev, vq); +} +EXPORT_SYMBOL_GPL(vhost_add_used_and_signal); + +/* multi-buffer version of vhost_add_used_and_signal */ +void vhost_add_used_and_signal_n(struct vhost_dev *dev, + struct vhost_virtqueue *vq, + struct vring_used_elem *heads, unsigned count) +{ + vhost_add_used_n(vq, heads, count); + vhost_signal(dev, vq); +} +EXPORT_SYMBOL_GPL(vhost_add_used_and_signal_n); + +/* return true if we're sure that avaiable ring is empty */ +bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + __virtio16 avail_idx; + int r; + + if (vq->avail_idx != vq->last_avail_idx) + return false; + + r = vhost_get_avail_idx(vq, &avail_idx); + if (unlikely(r)) + return false; + vq->avail_idx = vhost16_to_cpu(vq, avail_idx); + + return vq->avail_idx == vq->last_avail_idx; +} +EXPORT_SYMBOL_GPL(vhost_vq_avail_empty); + +/* OK, now we need to know about added descriptors. */ +bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + __virtio16 avail_idx; + int r; + + if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY)) + return false; + vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; + if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) { + r = vhost_update_used_flags(vq); + if (r) { + vq_err(vq, "Failed to enable notification at %p: %d\n", + &vq->used->flags, r); + return false; + } + } else { + r = vhost_update_avail_event(vq, vq->avail_idx); + if (r) { + vq_err(vq, "Failed to update avail event index at %p: %d\n", + vhost_avail_event(vq), r); + return false; + } + } + /* They could have slipped one in as we were doing that: make + * sure it's written, then check again. */ + smp_mb(); + r = vhost_get_avail_idx(vq, &avail_idx); + if (r) { + vq_err(vq, "Failed to check avail idx at %p: %d\n", + &vq->avail->idx, r); + return false; + } + + return vhost16_to_cpu(vq, avail_idx) != vq->avail_idx; +} +EXPORT_SYMBOL_GPL(vhost_enable_notify); + +/* We don't need to be notified again. */ +void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + int r; + + if (vq->used_flags & VRING_USED_F_NO_NOTIFY) + return; + vq->used_flags |= VRING_USED_F_NO_NOTIFY; + if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) { + r = vhost_update_used_flags(vq); + if (r) + vq_err(vq, "Failed to disable notification at %p: %d\n", + &vq->used->flags, r); + } +} +EXPORT_SYMBOL_GPL(vhost_disable_notify); + +/* Create a new message. */ +struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type) +{ + struct vhost_msg_node *node = kmalloc(sizeof *node, GFP_KERNEL); + if (!node) + return NULL; + + /* Make sure all padding within the structure is initialized. */ + memset(&node->msg, 0, sizeof node->msg); + node->vq = vq; + node->msg.type = type; + return node; +} +EXPORT_SYMBOL_GPL(vhost_new_msg); + +void vhost_enqueue_msg(struct vhost_dev *dev, struct list_head *head, + struct vhost_msg_node *node) +{ + spin_lock(&dev->iotlb_lock); + list_add_tail(&node->node, head); + spin_unlock(&dev->iotlb_lock); + + wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); +} +EXPORT_SYMBOL_GPL(vhost_enqueue_msg); + +struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev, + struct list_head *head) +{ + struct vhost_msg_node *node = NULL; + + spin_lock(&dev->iotlb_lock); + if (!list_empty(head)) { + node = list_first_entry(head, struct vhost_msg_node, + node); + list_del(&node->node); + } + spin_unlock(&dev->iotlb_lock); + + return node; +} +EXPORT_SYMBOL_GPL(vhost_dequeue_msg); + +void vhost_set_backend_features(struct vhost_dev *dev, u64 features) +{ + struct vhost_virtqueue *vq; + int i; + + mutex_lock(&dev->mutex); + for (i = 0; i < dev->nvqs; ++i) { + vq = dev->vqs[i]; + mutex_lock(&vq->mutex); + vq->acked_backend_features = features; + mutex_unlock(&vq->mutex); + } + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(vhost_set_backend_features); + +static int __init vhost_init(void) +{ + return 0; +} + +static void __exit vhost_exit(void) +{ +} + +module_init(vhost_init); +module_exit(vhost_exit); + +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael S. Tsirkin"); +MODULE_DESCRIPTION("Host kernel accelerator for virtio"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/README b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/README new file mode 100644 index 0000000..d0c7c66 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/README @@ -0,0 +1,12 @@ +kernel-crete-front-driver 目录: + 说明: + 云豹内核pf驱动+vdpa驱动 + 编译方式: + sh build_nic.sh anolis_kernel龙蜥系统编译 + sh build_nic.sh openeuler_kernel 欧拉系统编译 + sh build_nic.sh all 编译所有驱动 + 编译产出物: + crete_core.ko 基础通道驱动 + crete_pnic.ko pf驱动 + jm_auxiliary.ko auxiliary驱动 + crete_vdpa.ko vdpa驱动 diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build.sh b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build.sh new file mode 100644 index 0000000..5627ed6 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build.sh @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2023, Jaguar Micro. All rights reserved. +#!/usr/bin/env bash +function build_core() { + pushd crete-core + make clean + make + make install + popd +} +function build_vnet() { + pushd crete-vnet + make clean + make + popd +} + +build_core +build_vnet diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build_nic.sh b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build_nic.sh new file mode 100755 index 0000000..e3d132a --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build_nic.sh @@ -0,0 +1,136 @@ +# SPDX-License-Identifier: GPL-2.0 +#!/bin/bash +# common build rules useful for out-of-tree Linux driver builds +# +distro_info_dict=(/etc/anolis-release \ + /etc/bclinux-release \ + /etc/openEuler-release) +OS_KEY="" +distro_version="" +exit_not_found_failure() { exit 3; } + +find_distro_info() +{ + # Save the first valid kernel source path + for file in "${distro_info_dict[@]}"; do + if [ -f ${file} ]; then + distro_version=${file} + break + fi + done +} + +get_os_key() +{ + if [ -z "${distro_version}" ]; then + CFLAGS_KEY="" + return + fi + distro_info=`cat ${distro_version}` + if [ -z "${distro_info}" ]; then + echo "cat ${distro_info} is null" + fi + case $distro_info in + "Anolis OS release 8.8") + echo "You system is Anolis OS release 8.8" + OS_KEY="anolis-8.8" + CFLAGS_KEY="-DSNIC_ANOLIS_VERSION14" + ;; + "Anolis OS release 8.6") + echo "You system is Anolis OS release 8.6" + OS_KEY="anolis-8.6" + CFLAGS_KEY="-DSNIC_ANOLIS_VERSION14" + ;; + "BigCloud Enterprise Linux release 21.10U4 LTS") + echo "You system is BigCloud Enterprise Linux release 21.10U4 LTS" + OS_KEY="bclinux-21.10U4" + CFLAGS_KEY="-DBCLINUX2110U4" + ;; + *) + echo "You system is $distro_info" + CFLAGS_KEY="" + OS_KEY="default" + ;; + esac +} + + + + + +usage() { + echo "Usage: $0 [all | anolis_kernel | openeuler_kernel | clean]" + echo "all : build all kernels" + echo "anolis_kernel : build snic with anolis 5.10.134-14" + echo "openeuler_kernel : build snic with openeuler 5.10.0-136.12" + echo "clean : clean the anolis the kernel" + exit 1 +} + + +if [ $# -eq 0 ]; then + usage +fi + +find_distro_info +get_os_key + +case "$1" in + anolis_kernel) + echo "Build nic modules" + echo "build crete core modules" + cd crete-core + make EXTRA_CFLAGS="-DSNIC_ANOLIS_VERSION14" + make install + cd .. + echo "build crete pnic modules" + cd crete-pnic + make EXTRA_CFLAGS="-DSNIC_ANOLIS_VERSION14" + ;; + openeuler_kernel) + echo "Build nic modules" + echo "build crete core modules" + cd crete-core + make clean + make EXTRA_CFLAGS="-DSNIC_OPENEULER_VERSION136" + make install + cd .. + echo "build crete pnic modules" + cd crete-pnic + make clean + make EXTRA_CFLAGS="-DSNIC_OPENEULER_VERSION136" + cd ../ + echo "build crete vdpa modules" + cd crete-vnet + ./build_euler.sh + ;; + all) + echo "Build nic modules" + echo "build crete core modules" + echo "EXTRA_CFLAGS is $CFLAGS_KEY" + cd crete-core + make clean + make EXTRA_CFLAGS=$CFLAGS_KEY + cd .. + echo "build crete pnic modules" + cd crete-pnic + make clean + make EXTRA_CFLAGS=$CFLAGS_KEY + ;; + clean) + echo "Clean build dir ......" + cd crete-core + make clean + cd .. + cd crete-pnic + make clean + ;; + *) + usage + ;; +esac + +echo "Building kernel..." + +echo "Building kernel..." + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/Makefile b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/Makefile new file mode 100644 index 0000000..5d88d4c --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/Makefile @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 +# EXTRA_CFLAGS += -DCONFIG_NOSIM_DEBUG +KBUILD :=/lib/modules/$(shell uname -r)/build +ifeq ($(KERNELRELEASE), ) +DRIVER := crete_core +COMMON_MK ?= $(wildcard common.mk) +ifeq (${COMMON_MK},) + $(error Cannot find common.mk build rules) +else + include ${COMMON_MK} +endif + +all: + +$(call kernelbuild,modules) +clean: + +$(call kernelbuild,clean) + @\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod .*.cmd .tmp_versions -rf +install: + install -D -m 644 Module.symvers /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers + +auxiliary_info: + @./scripts/check_aux_bus.sh --verbose --ksrc="${KSRC}" --build-kernel="${BUILD_KERNEL}" + +ifeq (${NEED_AUX_BUS},1) +all: auxiliary_info +endif + +else +ifeq (${NEED_AUX_BUS},2) +KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers +export KBUILD_EXTRA_SYMBOLS +endif +obj-m := crete_core.o +crete_core-y := crete.o \ + crete_rdma_dev.o \ + crete_rdma_adapt.o \ + crete_aux_dev.o \ + crete_cmd.o \ + crete_cmd_if.o \ + crete_txrx.o \ + crete_event.o \ + crete_sriov.o \ + crete_eswitch.o \ + crete_devlink.o \ + crete_dcb_nl.o \ + crete_sriov_sysfs.o \ + crete_ptp.o \ + crete_stub.o \ + crete_ethtool.o \ + crete_eswoffloads.o \ + crete_fw_update.o \ + crete_pldmfw_lib.o \ + crete_rep.o \ + crete_core_debugfs.o \ + crete_lag.o \ + crete_lag_debugfs.o \ + crete_debugfs_statistics.o +endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/README b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/README new file mode 100644 index 0000000..bc78344 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/README @@ -0,0 +1,28 @@ +编译提示: +SIM环境编译时:需关闭CONFIG_NOSIM_DEBUG +内核模拟环境调试:需打开CONFIG_NOSIM_DEBUG +默认关闭:CONFIG_NOSIM_DEBUG + + +定义后端编号为idx的tx q的控制寄存器 +0x1000 + (idx * 0x100) 最多8个 + +定义后端编号为idx的tx q的描述符长度寄存器 +0x1004 + (idx * 0x100) + +定义描述符地址lo寄存器 +0x1008 + idx * 0x100 + +定义描述符地址hi寄存器 +0x100c + idx * 0x100 + +定义doorbell寄存器 +0x1010 + idx * 0x100 + +定义中断使能寄存器 0x3000 + (idx * 0x10) + +增加netlink套接字,用于后续用户态调试 +测试用例详见ssh://git@bit.jaguarmicro.com:7999/~foryun.ma/shell_kernel_test.git 中,test_netlink函数 + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/common.mk b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/common.mk new file mode 100644 index 0000000..fe874dc --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/common.mk @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2023, Jaguar Micro. All rights reserved. + +# +# common Makefile rules useful for out-of-tree Linux driver builds +# +# Usage: include filename.mk +# +# After including, you probably want to add a minimum_kver_check call +# +# Required Variables: +# DRIVER +# -- Set to the lowercase driver name + +##################### +# Helpful functions # +##################### + +readlink = $(shell readlink -f ${1}) + +# helper functions for converting kernel version to version codes +get_kver = $(or $(word ${2},$(subst ., ,${1})),0) +get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \ + [ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \ + [ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \ + printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) ) + +################ +# depmod Macro # +################ + +cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \ + $(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \ + -a ${KVER} + +################ +# dracut Macro # +################ + +cmd_initrd := $(shell \ + if which dracut > /dev/null 2>&1 ; then \ + echo "dracut --force"; \ + elif which update-initramfs > /dev/null 2>&1 ; then \ + echo "update-initramfs -u"; \ + fi ) + +##################### +# Environment tests # +##################### + +DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]") + +ifeq (,${BUILD_KERNEL}) +BUILD_KERNEL=$(shell uname -r) +endif + +# Kernel Search Path +# All the places we look for kernel source +KSP := /lib/modules/${BUILD_KERNEL}/source \ + /lib/modules/${BUILD_KERNEL}/build \ + /usr/src/linux-${BUILD_KERNEL} \ + /usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \ + /usr/src/kernel-headers-${BUILD_KERNEL} \ + /usr/src/kernel-source-${BUILD_KERNEL} \ + /usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ + /usr/src/linux \ + /usr/src/kernels/${BUILD_KERNEL} \ + /usr/src/kernels \ + ${KBUILD} + +# prune the list down to only values that exist and have an include/linux +# sub-directory. We can't use include/config because some older kernels don't +# have this. +test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir}) +KSP := $(foreach dir, ${KSP}, ${test_dir}) + +# we will use this first valid entry in the search path +ifeq (,${KSRC}) + KSRC := $(firstword ${KSP}) +endif + +ifeq (,${KSRC}) + $(warning *** Kernel header files not in any of the expected locations.) + $(warning *** Install the appropriate kernel development package, e.g.) + $(error kernel-devel, for building kernel modules and try again) +else +ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC}) + KOBJ := /lib/modules/${BUILD_KERNEL}/build +else + KOBJ := ${KSRC} +endif +endif + +SCRIPT_PATH := ${KSRC}/scripts + +# Version file Search Path +VSP := ${KOBJ}/include/generated/utsrelease.h \ + ${KOBJ}/include/linux/utsrelease.h \ + ${KOBJ}/include/linux/version.h \ + ${KOBJ}/include/generated/uapi/linux/version.h \ + /boot/vmlinuz.version.h + +# Config file Search Path +CSP := ${KOBJ}/include/generated/autoconf.h \ + ${KOBJ}/include/linux/autoconf.h \ + /boot/vmlinuz.autoconf.h + +# System.map Search Path (for depmod) +MSP := ${KSRC}/System.map \ + /usr/lib/debug/boot/System.map-${BUILD_KERNEL} \ + /boot/System.map-${BUILD_KERNEL} + +# prune the lists down to only files that exist +test_file = $(shell [ -f ${1} ] && echo ${1}) +VSP := $(foreach file, ${VSP}, $(call test_file,${file})) +CSP := $(foreach file, ${CSP}, $(call test_file,${file})) +MSP := $(foreach file, ${MSP}, $(call test_file,${file})) + + +# and use the first valid entry in the Search Paths +ifeq (,${VERSION_FILE}) + VERSION_FILE := $(firstword ${VSP}) +endif + +ifeq (,${CONFIG_FILE}) + CONFIG_FILE := $(firstword ${CSP}) +endif + +ifeq (,${SYSTEM_MAP_FILE}) + SYSTEM_MAP_FILE := $(firstword ${MSP}) +endif + +ifeq (,$(wildcard ${VERSION_FILE})) + $(error Linux kernel source not configured - missing version header file) +endif + +ifeq (,$(wildcard ${CONFIG_FILE})) + $(error Linux kernel source not configured - missing autoconf.h) +endif + +ifeq (,$(wildcard ${SYSTEM_MAP_FILE})) + $(warning Missing System.map file - depmod will not check for missing symbols during module installation) +endif + +ifneq ($(words $(subst :, ,$(CURDIR))), 1) + $(error Sources directory '$(CURDIR)' cannot contain spaces nor colons. Rename directory or move sources to another path) +endif + +######################## +# Extract config value # +######################## + +get_config_value = $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\ + grep -m 1 ${1} | awk '{ print $$3 }') + + +####################### +# Linux Version Setup # +####################### + +# The following command line parameter is intended for development of KCOMPAT +# against upstream kernels such as net-next which have broken or non-updated +# version codes in their Makefile. They are intended for debugging and +# development purpose only so that we can easily test new KCOMPAT early. If you +# don't know what this means, you do not need to set this flag. There is no +# arcane magic here. + +# Convert LINUX_VERSION into LINUX_VERSION_CODE +ifneq (${LINUX_VERSION},) + LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3)) +endif + +# Honor LINUX_VERSION_CODE +ifneq (${LINUX_VERSION_CODE},) + $(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.) + KVER_CODE := ${LINUX_VERSION_CODE} + EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE} +endif + +# Determine SLE_KERNEL_REVISION for SuSE SLE >= 11 (needed by kcompat) +# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string +# appended to the stable kernel version on which their kernel is based with +# additional versioning information (up to 3 numbers), a possible abbreviated +# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default +# or CONFIG_LOCALVERSION=-999.gdeadbee-default +# SLE >= 15SP3 added additional information about version and service pack +# to their kernel version e.g CONFIG_LOCALVERSION=-150300.59.43.1-default +# +# SLE_LOCALVERSION_CODE is also exported to support legacy kcompat.h +# definitions. +ifeq (1,$(call get_config_value,CONFIG_SUSE_KERNEL)) + +ifneq (10,$(call get_config_value,CONFIG_SLE_VERSION)) + + CONFIG_LOCALVERSION := $(call get_config_value,CONFIG_LOCALVERSION) + LOCALVERSION := $(shell echo ${CONFIG_LOCALVERSION} | \ + cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//') + LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1) +ifeq ($(shell test ${LOCALVER_A} -gt 65535; echo $$?),0) + LOCAL_VER_MAJOR := $(shell echo ${LOCALVER_A:0:3}) + LOCAL_VER_MINOR := $(shell echo ${LOCALVER_A:3:3}) + LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2) + LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3) + LOCALVER_D := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f4) + SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_B} \* 65536 + \ + 0${LOCALVER_C} \* 256 + 0${LOCALVER_D}) + EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE} + EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_B} +else + LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2) + LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3) + SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \ + 0${LOCALVER_B} \* 256 + 0${LOCALVER_C}) + EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE} + EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_A} +endif +endif +endif + +# Check if it is Oracle Linux UEK kernel and take release patch number from it +ifneq (,$(findstring uek,${BUILD_KERNEL})) + EXTRAVERSION := $(shell echo ${BUILD_KERNEL} | cut -s -d '-' -f2-) + UEK_RELEASE_NUMBER := $(shell echo ${EXTRAVERSION} | cut -s -d '.' -f1) + UEK_MINOR_RELEASE_NUMBER := $(shell echo ${EXTRAVERSION} | cut -s -d '.' -f2) + EXTRA_CFLAGS += -DUEK_RELEASE_NUMBER=${UEK_RELEASE_NUMBER} + EXTRA_CFLAGS += -DUEK_MINOR_RELEASE_NUMBER=${UEK_MINOR_RELEASE_NUMBER} +endif + +EXTRA_CFLAGS += ${CFLAGS_EXTRA} + +# get the kernel version - we use this to find the correct install path +KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \ + awk '{ print $$3 }' | sed 's/\"//g') + +# assume source symlink is the same as build, otherwise adjust KOBJ +ifneq (,$(wildcard /lib/modules/${KVER}/build)) + ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build)) + KOBJ=/lib/modules/${KVER}/build + endif +endif + +ifeq (${KVER_CODE},) + KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\ + grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g') +endif + +# minimum_kver_check +# +# helper function to provide uniform output for different drivers to abort the +# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)". +define _minimum_kver_check +ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?")) + $$(warning *** Aborting the build.) + $$(error This driver is not supported on kernel versions older than ${1}.${2}.${3}) +endif +endef +minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3})) + +############################# +# kcompat definitions setup # +############################# + +# In most cases, kcompat flags can be checked within the driver source files +# using simple CPP checks. However, it may be necessary to check for a flag +# value within the Makefile for some specific edge cases. For example, if an +# entire feature ought to be excluded on some kernels due to missing +# functionality. +# +# To support this, kcompat_defs.h is compiled and converted into a word list +# that can be checked to determine whether a given kcompat feature flag will +# be defined for this kernel. +# +# KCOMPAT_DEFINITIONS holds the set of all macros which are defined. Note +# this does include a large number of standard/builtin definitions. +# +# Use is_kcompat_defined as a $(call) function to check whether a given flag +# is defined or undefined. For example: +# +# ifeq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1) +# +# ifneq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1) +# +# The is_kcompat_defined function returns 1 if the macro name is defined, +# and the empty string otherwise. +# +# There is no mechanism to extract the value of the kcompat definition. +# Supporting this would be non-trivial as Make does not have a map variable +# type. +# +# Note that only the new layout is supported. Legacy definitions in +# kcompat.h are not supported. If you need to check one of these, please +# refactor it into the new layout. + +ifneq ($(wildcard ./kcompat_defs.h),) +KCOMPAT_DEFINITIONS := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM \ + -I${KOBJ}/include \ + -I${KOBJ}/include/generated/uapi \ + kcompat_defs.h | awk '{ print $$2 }') + +is_kcompat_defined = $(if $(filter ${1},${KCOMPAT_DEFINITIONS}),1,) +else +KCOMPAT_DEFINITIONS := +is_kcompat_defined = +endif + +################ +# Manual Pages # +################ + +MANSECTION = 7 + +ifeq (,${MANDIR}) + # find the best place to install the man page + MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g') + ifneq (,${MANPATH}) + # test based on inclusion in MANPATH + test_dir = $(findstring ${dir}, ${MANPATH}) + else + # no MANPATH, test based on directory existence + test_dir = $(shell [ -e ${dir} ] && echo ${dir}) + endif + # our preferred install path + # should /usr/local/man be in here ? + MANDIR := /usr/share/man /usr/man + MANDIR := $(foreach dir, ${MANDIR}, ${test_dir}) + MANDIR := $(firstword ${MANDIR}) +endif +ifeq (,${MANDIR}) + # fallback to /usr/man + MANDIR := /usr/man +endif + +#################### +# CCFLAGS variable # +#################### + +# set correct CCFLAGS variable for kernels older than 2.6.24 +ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?)) +CCFLAGS_VAR := EXTRA_CFLAGS +else +CCFLAGS_VAR := ccflags-y +endif + +################# +# KBUILD_OUTPUT # +################# + +# Only set KBUILD_OUTPUT if the real paths of KOBJ and KSRC differ +ifneq ($(call readlink,${KSRC}),$(call readlink,${KOBJ})) +export KBUILD_OUTPUT ?= ${KOBJ} +endif + +############################ +# Module Install Directory # +############################ + +# Default to using updates/drivers/net/ethernet/jm/ path, since depmod since +# v3.1 defaults to checking updates folder first, and only checking kernels/ +# and extra afterwards. We use updates instead of kernel/* due to desire to +# prevent over-writing built-in modules files. +export INSTALL_MOD_DIR ?= updates/drivers/net/ethernet/jm/${DRIVER} + +################# +# Auxiliary Bus # +################# + +# If the check_aux_bus script exists, then this driver depends on the +# auxiliary module. Run the script to determine if we need to include +# auxiliary files with this build. +CHECK_AUX_BUS ?= ./scripts/check_aux_bus.sh +ifneq ($(call test_file,${CHECK_AUX_BUS}),) +NEED_AUX_BUS := $(shell ${CHECK_AUX_BUS} --ksrc="${KSRC}" --build-kernel="${BUILD_KERNEL}" >/dev/null 2>&1; echo $$?) +endif # check_aux_bus exists + +# The out-of-tree auxiliary module we ship should be moved into this +# directory as part of installation. +export INSTALL_AUX_DIR ?= updates/drivers/net/ethernet/jm/auxiliary + +# If we're installing auxiliary bus out-of-tree, the following steps are +# necessary to ensure the relevant files get put in place. +AUX_BUS_HEADER ?= linux/auxiliary_bus.h +ifeq (${NEED_AUX_BUS},2) +define auxiliary_post_install + install -D -m 644 Module.symvers ${INSTALL_MOD_PATH}/lib/modules/${KVER}/extern-symvers/jm_auxiliary.symvers + install -d ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR} + install -D -m 644 jm_auxiliary.ko ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR}/ + install -D -m 644 ${AUX_BUS_HEADER} ${INSTALL_MOD_PATH}/${KSRC}/include/linux/auxiliary_bus.h +endef +else +auxiliary_post_install = +endif + +ifeq (${NEED_AUX_BUS},2) +define auxiliary_post_uninstall + rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/extern-symvers/jm_auxiliary.symvers + rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR}/jm_auxiliary.ko + rm -f ${INSTALL_MOD_PATH}/${KSRC}/include/linux/auxiliary_bus.h +endef +else +auxiliary_post_uninstall = +endif + +ifeq (${NEED_AUX_BUS},2) +EXTRA_CFLAGS += -DUSE_JM_AUX_BUS +endif +###################### +# Kernel Build Macro # +###################### + +# kernel build function +# ${1} is the kernel build target +# ${2} may contain any extra rules to pass directly to the sub-make process +# +# This function is expected to be executed by +# @+$(call kernelbuild,,) +# from within a Makefile recipe. +# +# The following variables are expected to be defined for its use: +# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS +# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable +# KSRC -- the location of the kernel source tree to build against +# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER +# W -- if set, enables the W= kernel warnings options +# C -- if set, enables the C= kernel sparse build options +# +kernelbuild = ${MAKE} ${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \ + -C "${KSRC}" \ + CONFIG_${DRIVER_UPPERCASE}=m \ + M="${CURDIR}" \ + $(if ${W},W="${W}") \ + $(if ${C},C="${C}") \ + $(if ${NEED_AUX_BUS},NEED_AUX_BUS="${NEED_AUX_BUS}") \ + ${2} ${1} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.c new file mode 100644 index 0000000..78c8299 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.c @@ -0,0 +1,2441 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crete.h" +#include "crete_regs.h" +#include "crete_cmd.h" +#include "crete_cmd_if.h" +#include "crete_txrx.h" +#include "crete_sriov.h" +#include "crete_stub.h" +#include "crete_rdma_dev.h" +#include "crete_rdma_adapt.h" +#include "crete_devlink.h" +#include "crete_eswitch.h" +#include "crete_event.h" + +char crete_driver_name[] = "crete"; + +struct crete_core_dev *g_cdev_test[2]; +EXPORT_SYMBOL(g_cdev_test); + +static const struct pci_device_id crete_pci_tbl[] = { + { PCI_VDEVICE(CRETE, PF_DEVICE_ID) }, + { PCI_VDEVICE(CRETE, VF_DEVICE_ID), CRETE_PCI_DEV_IS_VF }, + { PCI_VDEVICE(CRETE, PF_DEVICE_ID_SIM) }, + { PCI_VDEVICE(CRETE, VF_DEVICE_ID_SIM), CRETE_PCI_DEV_IS_VF }, + { PCI_VDEVICE(CRETE, PF_DEVICE_ID_NIC) }, + { PCI_VDEVICE(CRETE, VF_DEVICE_ID_NIC), CRETE_PCI_DEV_IS_VF }, + { PCI_VDEVICE(CRETE, PF_DEVICE_ID_CMCC) }, +#ifdef SNIC_OPENEULER_VERSION136 + { PCI_VDEVICE(CRETE, VF_DEVICE_ID_CMCC), CRETE_PCI_DEV_IS_VF }, +#endif + /* required last entry */ + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, crete_pci_tbl); +static int crete_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id); +static void crete_remove_one(struct pci_dev *pdev); +static int crete_init_one(struct crete_core_dev *core_dev); +static void crete_uninit_one(struct crete_core_dev *core_dev); +static int crete_sw_init(struct crete_core_dev *, struct crete_hw *); +static int crete_hw_init(struct crete_core_dev *, struct crete_hw *); +static int crete_sw_uninit(struct crete_core_dev *, struct crete_hw *); +static int crete_hw_uninit(struct crete_core_dev *, struct crete_hw *); +static void crete_shutdown(struct pci_dev *); +static int crete_load(struct crete_core_dev *dev); +static void crete_unload(struct crete_core_dev *dev); +static int crete_init(void); +static void crete_cleanup(void); +static int crete_init_mac_addr(struct net_device *netdev); +static int crete_cap_init(struct crete_core_dev *core_dev, struct crete_hw *hw); +static bool crete_uc_list_updated(struct net_device *dev); + +static pci_ers_result_t __maybe_unused crete_pci_err_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct crete_core_dev *dev = pci_get_drvdata(pdev); + bool abort = false; + + crete_detach_device(dev); + rtnl_lock(); + netif_device_detach(dev->netdev); + + if (test_and_set_bit(__CRETE_RESETING, &dev->state)) { + crete_err(dev->device, "Firmware reset already in progress\n"); + abort = true; + } + + if (abort || state == pci_channel_io_perm_failure) { + rtnl_unlock(); + return PCI_ERS_RESULT_DISCONNECT; + } + + if (netif_running(dev->netdev)) + crete_close(dev->netdev); + + if (pci_is_enabled(pdev)) + pci_disable_device(pdev); + + /* Request a slot reset. */ + rtnl_unlock(); + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t crete_pci_err_slot_reset(struct pci_dev *pdev) +{ + enum pci_ers_result res = PCI_ERS_RESULT_DISCONNECT; + struct crete_core_dev *dev = pci_get_drvdata(pdev); + int err; + + crete_info(dev->device, "PCI Slot Reset..\n"); + err = pci_enable_device(pdev); + if (err) { + crete_err(dev->device, "%s: failed with error code: %d\n", __func__, err); + goto out; + } + + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + + res = PCI_ERS_RESULT_RECOVERED; +out: + crete_info(dev->device, "%s Device state = %ld. Exit, err = %d\n", + __func__, dev->state, err); + return res; +} + +static void crete_pci_resume(struct pci_dev *pdev) +{ + struct crete_core_dev *dev = pci_get_drvdata(pdev); + int err; + + crete_info(dev->device, "PCI Slot Resume..\n"); + rtnl_lock(); + + if (netif_running(dev->netdev)) + err = crete_open(dev->netdev); + + if (!err) + netif_device_attach(dev->netdev); + + rtnl_unlock(); + + crete_attach_device(dev); +} + +static const struct pci_error_handlers crete_pci_err_handler = { + // current error dected do nothing + .error_detected = NULL, + .slot_reset = crete_pci_err_slot_reset, + .resume = crete_pci_resume +}; + +static struct pci_driver crete_pci_driver = { + .name = crete_driver_name, + .id_table = crete_pci_tbl, + .probe = crete_probe_one, + .remove = crete_remove_one, + .shutdown = crete_shutdown, + .sriov_configure = crete_pci_sriov_configure, + .err_handler = &crete_pci_err_handler +}; + +MODULE_LICENSE("GPL v2"); + +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +/** + * crete_init_module - Driver Registration Routine + * + * crete_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + **/ +static int __init crete_init_module(void) +{ + int err; + + pr_info("init crete module\n"); + + crete_register_debugfs(); + + err = pci_register_driver(&crete_pci_driver); + if (err) + return err; + err = crete_init(); + if (err) + goto err_crete_init; + return 0; + +err_crete_init: + pci_unregister_driver(&crete_pci_driver); + crete_unregister_debugfs(); + return err; +} + +module_init(crete_init_module); + +/** + * crete_exit_module - Driver Exit Cleanup Routine + * + * crete_exit_module is called just before the driver is removed + * from memory. + **/ +static void __exit crete_exit_module(void) +{ + pr_info("exit crete module\n"); + crete_cleanup(); + pci_unregister_driver(&crete_pci_driver); + crete_unregister_debugfs(); +} + +module_exit(crete_exit_module); + +static int crete_get_max_irq(struct crete_core_dev *core_dev) +{ + struct pci_dev *pdev; + u16 ctrl; + int num_vectors; + + pdev = core_dev->pdev; + if (!pdev->msix_cap) + return 0; + + pci_read_config_word(pdev, pdev->msix_cap + PCI_MSIX_FLAGS, &ctrl); + num_vectors = (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1; + pr_info("MSIX: num_vectors=%d\n", num_vectors); + return num_vectors; +} + +static void crete_init_rdma_vec_num(struct crete_core_dev *core_dev) +{ + if (!crete_have_rdma_cap(core_dev)) { + dev_warn(&core_dev->pdev->dev, "not support rdma capability\n"); + core_dev->rdma_adp.vector_num = 0; + } else + core_dev->rdma_adp.vector_num = JM_AUX_VECTOR_NUM; + dev_warn(&core_dev->pdev->dev, "rdma_dev->vector_num=%d\n", + core_dev->rdma_adp.vector_num); +} + +static int crete_get_rdma_vec_num(struct crete_core_dev *core_dev) +{ + return core_dev->rdma_adp.vector_num; +} + +static void crete_init_rdma_vec_base(struct crete_core_dev *core_dev, + int vec_base) +{ + if (!crete_have_rdma_cap(core_dev)) { + dev_warn(&core_dev->pdev->dev, "not support rdma capability\n"); + core_dev->rdma_adp.vector_base = 0xfff; + } else + core_dev->rdma_adp.vector_base = vec_base; + dev_warn(&core_dev->pdev->dev, "rdma_dev->vector_base=%d\n", vec_base); +} + +void crete_init_msix(struct crete_core_dev *core_dev) +{ + int i, total_vecs, min, max_num, rdma_vecs; + struct pci_dev *pdev; + struct msix_entry *msix_ent; + struct crete_irq_info *irq_info; + + if ((core_dev->flags & CRETE_FLAG_HAS_MSIX)) { + dev_info(&core_dev->pdev->dev, "crete msix already init.\n"); + return; + } + + pdev = core_dev->pdev; + max_num = crete_get_max_irq(core_dev); + crete_init_rdma_vec_num(core_dev); + rdma_vecs = crete_get_rdma_vec_num(core_dev); + if (max_num < 3) { + pr_info("msix irq num lower than 2 return now!\n"); + return; + } + + msix_ent = kcalloc(max_num, sizeof(struct msix_entry), GFP_KERNEL); + if (!msix_ent) + return; + + for (i = 0; i < max_num; i++) { + msix_ent[i].entry = i; + msix_ent[i].vector = 0; + } + + min = 3; /* IO Queue vec num */ + min += rdma_vecs; + total_vecs = pci_enable_msix_range(pdev, msix_ent, min, max_num); + if (total_vecs < 0) { + pr_warn("msix alloc range min:%d max:%d\n", min, max_num); + kfree(msix_ent); + return; + } + + irq_info = + kcalloc(total_vecs, sizeof(struct crete_irq_info), GFP_KERNEL); + if (!irq_info) { + kfree(msix_ent); + return; + } + + for (i = 0; i < total_vecs; i++) { + irq_info[i].handler = NULL; + irq_info[i].requested = 0; + irq_info[i].vector = msix_ent[i].vector; + } + bitmap_zero(core_dev->irqbit, CRETE_MAX_MSIX_NUM); + core_dev->msix_ent = msix_ent; + core_dev->irq_info = irq_info; + core_dev->irq_num = total_vecs - rdma_vecs; + core_dev->flags |= CRETE_FLAG_HAS_MSIX; + crete_init_rdma_vec_base(core_dev, core_dev->irq_num); + /* reserve the rdma irq vector */ + for (i = core_dev->irq_num; i < total_vecs; i++) + set_bit(i, core_dev->irqbit); + + dev_warn(&pdev->dev, "MSI-X total vecs:%d, min:%d, max:%d, rdma:%d\n", + total_vecs, min, max_num, rdma_vecs); +} +EXPORT_SYMBOL(crete_init_msix); + +int crete_req_msixirq(struct crete_core_dev *core_dev) +{ + int ret; + unsigned long bits; + + spin_lock(&core_dev->lock); + bits = find_first_zero_bit(core_dev->irqbit, CRETE_MAX_MSIX_NUM); + if (bits >= CRETE_MAX_MSIX_NUM) { + ret = -1; + } else { + set_bit(bits, core_dev->irqbit); + ret = (int)bits; + } + spin_unlock(&core_dev->lock); + + return ret; +} +EXPORT_SYMBOL(crete_req_msixirq); + +void crete_free_msixirq(struct crete_core_dev *core_dev, int irq) +{ + if (irq >= CRETE_MAX_MSIX_NUM) + return; + + spin_lock(&core_dev->lock); + clear_bit(irq, core_dev->irqbit); + spin_unlock(&core_dev->lock); +} +EXPORT_SYMBOL(crete_free_msixirq); + +void crete_exit_irq(struct crete_core_dev *core_dev) +{ + struct pci_dev *pdev; + pdev = core_dev->pdev; + if (!(core_dev->flags & CRETE_FLAG_HAS_MSIX)) + return; + kfree(core_dev->irq_info); + core_dev->irq_info = NULL; + kfree(core_dev->msix_ent); + core_dev->msix_ent = NULL; + + pci_disable_msix(core_dev->pdev); + core_dev->flags &= ~CRETE_FLAG_HAS_MSIX; + dev_info(&pdev->dev, "disable irq. flags 0x%x\n", core_dev->flags); +} +EXPORT_SYMBOL(crete_exit_irq); + +extern const struct net_device_ops crete_netdev_ops; +static int crete_set_dma_caps(struct pci_dev *pdev) +{ + int err; + + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (err) { + dev_warn(&pdev->dev, + "Warning: couldn't set 64-bit PCI DMA mask\n"); + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, + "Can't set PCI DMA mask, aborting\n"); + return err; + } + } + + /* dma_set_max_seg_size(&pdev->dev, 2u * 1024 * 1024 * 1024); */ + return err; +} + +static int crete_pci_init(struct crete_core_dev *core_dev, struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int err; + size_t bar_len; + + pr_info("crete probe begin\n"); + pci_set_drvdata(core_dev->pdev, core_dev); + err = pci_enable_device_mem(pdev); + if (err) + return err; + + err = pci_request_mem_regions(pdev, crete_driver_name); + if (err) { + dev_err(&pdev->dev, "request mem regions err\n"); + goto err_pci_request_mem_regions; + } + err = crete_set_dma_caps(pdev); + if (err) + goto err_crete_set_dma_caps; + + pci_enable_pcie_error_reporting(pdev); + + pci_set_master(pdev); + + core_dev->bar_addr = pci_resource_start(pdev, 0); + bar_len = pci_resource_len(pdev, 0); + core_dev->io_addr = pci_iomap(pdev, 0, bar_len); + if (!core_dev->io_addr) { + dev_err(&pdev->dev, "map bar err\n"); + err = -EFAULT; + goto err_pci_iomap; + } + + return 0; + +err_crete_set_dma_caps: + pci_release_regions(pdev); +err_pci_request_mem_regions: + pci_iounmap(pdev, core_dev->io_addr); +err_pci_iomap: + pci_disable_device(pdev); + return err; +} + +static int crete_pci_close(struct crete_core_dev *core_dev) +{ + struct pci_dev *pdev = core_dev->pdev; + + pci_iounmap(pdev, core_dev->io_addr); + pci_release_mem_regions(pdev); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + return 0; +} + +static int crete_cdev_cap_init(struct crete_core_dev *cdev) +{ + int ret; + u16 max_queue_size = 0; + u8 max_qp_num, ctrl_queue_size = 0; + + ret = crete_get_qp_cap(cdev, + &max_queue_size, &max_qp_num, &ctrl_queue_size); + if (ret) { + crete_err(cdev->device, "crete core dev get cap failed\n"); + return ret; + } + + cdev->cap.qpcap.ctrl_queue_size = ctrl_queue_size; + cdev->cap.qpcap.max_qp_num = max_qp_num; + cdev->cap.qpcap.max_queue_size = max_queue_size; + return 0; +} + +int crete_attach_netdev(struct crete_core_dev *core_dev) +{ + struct crete_hw *hw; + static int count; + int err; + + hw = &core_dev->hw; + // crete_core_dev init + pr_info("core dev init\n"); + pr_info("core dev set globle count :%d\n", count & 0x1); + g_cdev_test[count & 0x1] = core_dev; + count++; + + err = crete_cdev_cap_init(core_dev); + if (err < 0) + goto err_crete_get_func_caps; + + err = crete_get_func_caps(core_dev); + if (err < 0) { + //dev_err(&pdev->dev, "crete hw init failed\n"); + goto err_crete_get_func_caps; + } + + /* setup the private structure */ + err = crete_sw_init(core_dev, hw); + if (err) { + //dev_err(&pdev->dev, "crete sw init failed\n"); + goto err_crete_sw_init; + } + + return 0; +err_crete_sw_init: +err_crete_get_func_caps: + pr_info("core dev init failed, err:%d\n", err); + return err; +} + +void crete_detach_netdev(struct crete_core_dev *core_dev) +{ + struct crete_hw *hw; + + hw = &core_dev->hw; + crete_sw_uninit(core_dev, hw); + /* note:must be free all irq */ +} + +int crete_rescan_drivers(struct crete_core_dev *dev) +{ + int ret; + + crete_dev_list_lock(); + ret = crete_rescan_drivers_locked(dev); + crete_dev_list_unlock(); + return ret; +} + +static int crete_build_nic_netdev(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + + SET_NETDEV_DEV(netdev, &pdev->dev); + netdev->netdev_ops = &crete_netdev_ops; + crete_dcbnl_build_netdev(netdev); + //crete_set_ethtool_ops(netdev); //delay to init + netdev->watchdog_timeo = 5 * HZ; + netdev->ethtool_ops = &crete_ethtool_ops; + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + netdev->mem_start = pci_resource_start(pdev, 0); + netdev->mem_end = pci_resource_end(pdev, 0); + /* + * just for aux test + * step 1:crete_adev_init + * step 2:attach device + */ + + if (crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_RX_IPV4_CSUM) || + crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_RX_TCP_CSUM) || + crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_RX_UDP_CSUM) || + crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_RX_SCTP_CSUM)) { + netdev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_RXCSUM; + } + + if (crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_RX_RSS_HASH)) + netdev->hw_features |= NETIF_F_RXHASH; + + if (crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_TX_TCP_TSO) || + crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_TX_IP_TNL_TSO) || + crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_TX_UDP_TNL_TSO)) + netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; + +#define CRETE_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ + NETIF_F_GSO_GRE_CSUM | \ + NETIF_F_GSO_IPXIP4 | \ + NETIF_F_GSO_IPXIP6 | \ + NETIF_F_GSO_UDP_TUNNEL | \ + NETIF_F_GSO_UDP_TUNNEL_CSUM) + + netdev->gso_partial_features = CRETE_GSO_PARTIAL_FEATURES; + netdev->features |= NETIF_F_GSO_PARTIAL | CRETE_GSO_PARTIAL_FEATURES; + + /* copy netdev features into list of user selectable features */ + if (crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_RX_VLAN_FILTER) || + crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_RX_VLAN_STRIP) || + crete_has_feature(core_dev, CRETE_FEATURE_OFFLOAD, CRETE_NET_F_TX_VLAN_INSERT)) { + netdev->features = NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_RXALL; + } + + /* MTU range: 68 - 9216 */ + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; + + strcpy(netdev->name, "eth%d"); + + return 0; +} + +/* Allow PF, trusted VFs to be in promiscuous mode */ +static bool crete_promisc_ok(struct crete_core_dev *coredev) +{ + if (crete_core_is_vf(coredev) + && !crete_is_trusted_vf(coredev->netdev, &coredev->vf)) + return false; + + return true; +} + +static int crete_cmd_set_uc_mac(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_uc_mac_in); + int out_len = CRETE_ST_SZ_BYTES(set_uc_mac_out); + void *in, *out, *uc_mac_list_in_base; + int uc_list_num = priv->uc_filter_count; + int uc_mac_list_size = uc_list_num * CRETE_ST_SZ_BYTES(uc_mac_list); + + in_len += ALIGN_TO_DW(uc_mac_list_size); + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + uc_mac_list_in_base = in + in_len - ALIGN_TO_DW(uc_mac_list_size); + + CRETE_SET(set_uc_mac_in, in, cmd_op, 0); + CRETE_SET(set_uc_mac_in, in, cmd_id, CRETE_CMD_SET_UC_MAC); + CRETE_SET(set_uc_mac_in, in, uc_list_num, priv->uc_filter_count); + memcpy(uc_mac_list_in_base, priv->uc_list, uc_mac_list_size); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_uc_mac_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_uc_mac_out, out, err_type); + crete_err(&pdev->dev, + "crete set uc mac failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + crete_err(&pdev->dev, "%s return:%x\n", __func__, ret); + return ret; +} + +static int crete_cmd_set_mc_filter(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_rx_mode_in); + int out_len = CRETE_ST_SZ_BYTES(set_rx_mode_out); + void *in, *out, *mc_mac_list_in_base; + int vlan_range_list_size; + int mc_mac_list_size; + int vlan_range_num = 0; + int mc_list_num = priv->mc_list_count; + int mc_list_size = mc_list_num * ETH_ALEN; + + vlan_range_list_size = vlan_range_num * CRETE_ST_SZ_BYTES(vlan_range); + in_len += vlan_range_list_size; + + mc_mac_list_size = mc_list_num * CRETE_ST_SZ_BYTES(mc_mac_list); + in_len += ALIGN_TO_DW(mc_mac_list_size); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + mc_mac_list_in_base = in + in_len - ALIGN_TO_DW(mc_mac_list_size); + + CRETE_SET(set_rx_mode_in, in, cmd_op, 0); + CRETE_SET(set_rx_mode_in, in, cmd_id, CRETE_CMD_SET_VPORT_RX_MODE); + CRETE_SET(set_rx_mode_in, in, multicast, 1); + CRETE_SET(set_rx_mode_in, in, mc_list_num, priv->mc_list_count); + memcpy(mc_mac_list_in_base, priv->mc_list, mc_list_size); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_rx_mode_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_rx_mode_out, out, err_type); + crete_err(&pdev->dev, + "crete set mc filter failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + return ret; +} + +static int crete_cmd_set_rx_mask(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_rx_mode_in); + int out_len = CRETE_ST_SZ_BYTES(set_rx_mode_out); + void *in, *out; + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(set_rx_mode_in, in, cmd_op, 0); + CRETE_SET(set_rx_mode_in, in, cmd_id, CRETE_CMD_SET_VPORT_RX_MODE); + + if (priv->rx_mask & L2_SET_RX_MASK_REQ_MASK_BCAST) + CRETE_SET(set_rx_mode_in, in, broadcast, 1); + + if (priv->rx_mask & L2_SET_RX_MASK_REQ_MASK_ALL_MCAST) + CRETE_SET(set_rx_mode_in, in, all_multicast, 1); + + if (priv->rx_mask & L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS) + CRETE_SET(set_rx_mode_in, in, promiscuous, 1); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_rx_mode_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_rx_mode_out, out, err_type); + crete_err(&pdev->dev, + "crete set rx mask failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + return ret; +} + +static int crete_set_default_mac(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + int rc; + + memcpy(priv->uc_list, netdev->dev_addr, ETH_ALEN); + priv->uc_filter_count = 1; + + rc = crete_cmd_set_uc_mac(netdev); + if (rc) + priv->uc_filter_count = 0; + + return rc; +} + +static int crete_set_uc_filter(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct netdev_hw_addr *ha; + int off = 0; + + netif_addr_lock_bh(netdev); + if (netdev_uc_count(netdev) > (CRETE_MAX_UC_ADDRS - 1)) { + priv->rx_mask |= L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + } else { + netdev_for_each_uc_addr(ha, netdev) { + memcpy(priv->uc_list + off, ha->addr, ETH_ALEN); + off += ETH_ALEN; + priv->uc_filter_count++; + } + } + netif_addr_unlock_bh(netdev); + + return crete_cmd_set_uc_mac(netdev); +} + +void crete_set_rx_mode_work(struct work_struct *work) +{ + struct crete_priv *priv = container_of(work, struct crete_priv, + set_rx_mode_work); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct net_device *netdev = priv->netdev; + bool uc_update; + int rc; + + netif_addr_lock_bh(netdev); + uc_update = crete_uc_list_updated(netdev); + netif_addr_unlock_bh(netdev); + + if (uc_update) { + rc = crete_set_uc_filter(netdev); + if (rc) + dev_err(&pdev->dev, + "HWRM l2 uc filter failure rc: %d\n", rc); + } + if (priv->rx_mask & L2_SET_RX_MASK_REQ_MASK_MCAST) { + rc = crete_cmd_set_mc_filter(netdev); + if (rc) { + dev_err(&pdev->dev, + "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n", + rc); + priv->rx_mask &= ~L2_SET_RX_MASK_REQ_MASK_MCAST; + priv->rx_mask |= L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + priv->mc_list_count = 0; + } + } + /*promisc check */ + if ((priv->rx_mask & L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS) && + !crete_promisc_ok(core_dev)) + priv->rx_mask &= ~L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + + rc = crete_cmd_set_rx_mask(netdev); + if (rc) + dev_err(&pdev->dev, "HWRM l2 rx mask failure rc: %d\n", rc); +} + +/* crete generic netdev management API (move to en_common.c) */ +int crete_priv_init(struct crete_priv *priv, struct net_device *netdev, + struct crete_core_dev *core_dev) +{ + int mem_size = (CRETE_MAX_UC_ADDRS - 1) * ETH_ALEN; + int rc = 0; + + /* priv init */ + priv->coredev = core_dev; + priv->netdev = netdev; + + priv->uc_list = kmalloc(mem_size, GFP_KERNEL); + if (!priv->uc_list) { + rc = -ENOMEM; + goto err_uc_list_alloc; + } + priv->mc_list_size = CRETE_MAX_MC_ADDRS * ETH_ALEN; + priv->mc_list = kmalloc(priv->mc_list_size, GFP_KERNEL); + if (!priv->mc_list) { + rc = -ENOMEM; + goto err_mc_list_alloc; + } + + INIT_WORK(&priv->set_rx_mode_work, crete_set_rx_mode_work); + priv->wq = create_singlethread_workqueue("crete_rx_mode"); + if (!priv->wq) { + rc = -ENOMEM; + goto err_workqueue; + } + return 0; +err_workqueue: + kfree(priv->mc_list); + priv->mc_list = NULL; +err_mc_list_alloc: + kfree(priv->uc_list); + priv->uc_list = NULL; +err_uc_list_alloc: + return rc; +} + +void crete_priv_cleanup(struct crete_priv *priv) +{ + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev; + + if (!priv->coredev) + return; + + pdev = core_dev->pdev; + dev_err(&pdev->dev, "enter crete_priv_cleanup\n"); + cancel_work_sync(&priv->set_rx_mode_work); + destroy_workqueue(priv->wq); + + kfree(priv->mc_list); + priv->mc_list = NULL; + + kfree(priv->uc_list); + priv->uc_list = NULL; + + memset(priv, 0, sizeof(*priv)); + dev_err(&pdev->dev, "exit crete_priv_cleanup\n"); + +} + +struct net_device *crete_create_netdev(struct crete_core_dev *coredev) +{ + struct net_device *netdev; + unsigned int txqs, rxqs; + struct crete_priv *priv; + struct pci_dev *pdev = coredev->pdev; + int err; + +// txqs = coredev->cap.qpcap.max_qp_num; +// rxqs = coredev->cap.qpcap.max_qp_num; + /* get the trim ring size */ + txqs = coredev->ring_size; + rxqs = coredev->ring_size; + /* crete netdevice with max qp number */ + netdev = alloc_etherdev_mqs(sizeof(struct crete_priv), txqs, rxqs); + if (!netdev) { + dev_err(&pdev->dev, "alloc_etherdev_mqs() failed\n"); + return NULL; + } + priv = netdev_priv(netdev); + coredev->netdev = netdev; + err = crete_priv_init(priv, netdev, coredev); + if (err) { + dev_err(&pdev->dev, "crete_priv_init failed\n"); + goto err_priv_init; + } + netif_carrier_off(netdev); + netif_tx_disable(netdev); + return netdev; + +err_priv_init: + free_netdev(netdev); + return NULL; +} + +void crete_destroy_netdev(struct net_device *netdev) +{ + struct crete_priv *priv; + + priv = netdev_priv(netdev); + crete_priv_cleanup(priv); + free_netdev(netdev); +} + +int crete_coredev_init(struct crete_core_dev *dev) +{ + int err; + + err = crete_adev_init(dev); + return err; +} + +void crete_coredev_uninit(struct crete_core_dev *dev) +{ + crete_adev_cleanup(dev); +} + +static enum crete_device_type crete_get_device_type(struct pci_dev *pdev, const struct pci_device_id *id) +{ + enum crete_device_type device_type; + + switch (pdev->device) { + case PF_DEVICE_ID: + device_type = CRETE_DEVICE_CRETE; + break; + case PF_DEVICE_ID_NIC: + case VF_DEVICE_ID_NIC: + case PF_DEVICE_ID_CMCC: + case VF_DEVICE_ID_CMCC: + device_type = CRETE_DEVICE_PNIC; + break; + case PF_DEVICE_ID_FAKE: + device_type = CRETE_DEVICE_FAKE; + break; + default: + device_type = CRETE_DEVICE_CRETE; + } + pr_info("device type %d\n", device_type); + return device_type; +} + +static int crete_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct crete_core_dev *core_dev; + struct devlink *devlink; + int err; + enum crete_coredev_type coredev_type; + enum crete_device_type device_type; + + coredev_type = id->driver_data & CRETE_PCI_DEV_IS_VF ? + CRETE_COREDEV_VF : CRETE_COREDEV_PF; + device_type = crete_get_device_type(pdev, id); + devlink = + crete_devlink_alloc(&pdev->dev, coredev_type == CRETE_COREDEV_PF); + if (!devlink) { + dev_err(&pdev->dev, "devlink alloc failed\n"); + return -ENOMEM; + } + + core_dev = devlink_priv(devlink); + core_dev->device = &pdev->dev; + core_dev->pdev = pdev; + spin_lock_init(&core_dev->lock); + core_dev->coredev_type = coredev_type; + core_dev->device_type = device_type; + + core_dev->adev_idx = crete_adev_idx_alloc(); + if (core_dev->adev_idx < 0) { + err = core_dev->adev_idx; + goto err_adev_idx_init; + } + + err = crete_coredev_init(core_dev); + if (err) + goto err_coredev_init; + err = crete_pci_init(core_dev, pdev, id); + if (err) + goto err_pci_init; + err = crete_init_one(core_dev); + if (err) + goto err_init_one; + + pci_save_state(pdev); + + err = crete_devlink_register(devlink); + if (err) { + dev_err(&pdev->dev, "Failed to register devlink %d\n", err); + goto err_devlink_reg; + } + + return 0; +err_devlink_reg: + crete_uninit_one(core_dev); +err_init_one: + crete_pci_close(core_dev); +err_pci_init: + crete_coredev_uninit(core_dev); +err_coredev_init: + crete_adev_idx_free(core_dev->adev_idx); +err_adev_idx_init: + crete_devlink_free(devlink); + return err; +} + +static void crete_remove_one(struct pci_dev *pdev) +{ + struct crete_core_dev *dev = pci_get_drvdata(pdev); + struct devlink *devlink = priv_to_devlink(dev); + crete_devlink_unregister(devlink); + + /* with the pf device need to clean the sriov with remove one */ + if(crete_core_is_pf(dev)) + crete_sriov_disable(pdev); + + crete_uninit_one(dev); + crete_pci_close(dev); + crete_coredev_uninit(dev); + crete_adev_idx_free(dev->adev_idx); + crete_devlink_free(devlink); +} + +static int crete_init_once(struct crete_core_dev *dev) +{ + int err; + +#ifndef CONFIG_NOSIM_DEBUG + err = crete_hw_init(dev, &dev->hw); + if (err) { + dev_err(&dev->pdev->dev, "crete hw init failed\n"); + return err; + } +#endif + err = crete_rdma_coredev_init(dev); + if (err) { + dev_err(&dev->pdev->dev, "crete rdma coredev init failed\n"); + goto err_rdma_coredev_init; + + } + /* crete init msix interrupt */ + crete_init_msix(dev); + + err = crete_sriov_init(dev); + if (err) { + dev_err(&dev->pdev->dev, "Failed to init sriov %d\n", err); + goto err_sriov_init; + } + err = crete_eswitch_init(dev); + if (err) { + dev_err(&dev->pdev->dev, "Failed to init eswitch %d\n", err); + goto err_eswitch_init; + } + + return 0; + +err_eswitch_init: + crete_sriov_cleanup(dev); +err_sriov_init: + crete_rdma_coredev_uninit(dev); +err_rdma_coredev_init: +#ifndef CONFIG_NOSIM_DEBUG + (void)crete_hw_uninit(dev, &dev->hw); +#endif + return err; +} + +static void crete_cleanup_once(struct crete_core_dev *dev) +{ + int num_vfs = pci_num_vf(dev->pdev); + + pr_info("cleanup once enter\n"); + if (dev->sriov_cfg == 1) + crete_device_disable_sriov(dev, num_vfs, true); + + crete_eswitch_cleanup(dev->eswitch); + crete_sriov_cleanup(dev); + + crete_exit_irq(dev); + crete_rdma_coredev_uninit(dev); +#ifndef CONFIG_NOSIM_DEBUG + (void)crete_hw_uninit(dev, &dev->hw); +#endif + + debugfs_remove(dev->dbg.dbg_root); + + pr_info("cleanup once exit\n"); +} + +static int crete_init_one(struct crete_core_dev *core_dev) +{ + int err; + struct pci_dev *pdev; + struct crete_hw *hw; + + pr_info("init one enter\n"); + + core_dev->dbg.dbg_root = debugfs_create_dir(dev_name(core_dev->device), + crete_debugfs_root); + + pdev = core_dev->pdev; + err = crete_init_once(core_dev); + if (err) { + dev_err(&pdev->dev, "sw objs init failed\n"); + return err; + } + hw = &core_dev->hw; +#ifdef CONFIG_NOSIM_DEBUG + core_dev->db_base = core_dev->io_addr; + pr_info("Get db base address:0x%p\n", core_dev->db_base); +#else + core_dev->db_base = core_dev->io_addr + ((hw->jnd.offset) << 12); + pr_info("Get db base address:0x%p, offset:%u\n", core_dev->db_base, + hw->jnd.offset); +#endif + err = crete_event_init(hw); + if (err < 0) { + pr_info("crete_event_init failed\n"); + goto err_crete_event_init; + } + + err = crete_cmd_init(core_dev); + if (err < 0) { + //dev_err(&pdev->dev, "crete cmd init failed\n"); + goto err_crete_cmd_init; + } + + /* get sfi info */ + err = crete_get_dev_sfi(core_dev, CRETE_GET_SFI_CURR, 0, &core_dev->sfi_id); + if (err) { + pr_err("get sfi error info\n"); + goto err_load; + } + pr_info("get the current device sfi id %u\n", core_dev->sfi_id); + + err = crete_load(core_dev); + if (err) + goto err_load; + + err = crete_lag_add(core_dev); + if (err) + goto err_reg_device; + + err = crete_register_device(core_dev); + pr_info("init one exit\n"); + if (err) { + dev_err(&pdev->dev, "sw objs init failed\n"); + goto err_add_lag; + } + return 0; + +err_add_lag: + crete_lag_remove(core_dev); +err_reg_device: + crete_unload(core_dev); +err_load: + crete_cmd_exit(core_dev); +err_crete_cmd_init: + crete_event_exit(hw); +err_crete_event_init: + crete_cleanup_once(core_dev); + return err; +} + +void crete_uninit_one(struct crete_core_dev *core_dev) +{ + crete_unregister_device(core_dev); + crete_unregister_debugfs_statistics(core_dev); + crete_unload(core_dev); + crete_lag_remove(core_dev); + crete_cmd_exit(core_dev); + crete_event_exit(&core_dev->hw); + crete_cleanup_once(core_dev); +} + +unsigned int crete_get_max_rss_queues(struct crete_core_dev *core_dev) +{ + return CRETE_MAX_RX_QUEUES; +} + +static void crete_init_queue_configuration(struct crete_core_dev *core_dev) +{ + u32 max_rss_queues; + + max_rss_queues = crete_get_max_rss_queues(core_dev); + core_dev->rss_queues = min_t(u32, max_rss_queues, num_online_cpus()); +} + +static int crete_cap_parse(struct crete_core_dev *core_dev, u8 __iomem *addr, + struct crete_hw *hw) +{ + uint16_t cap_type = readw(addr); + + switch (cap_type) { + case CRETE_NET_CONF_CAP: + crete_ioread32(addr, &hw->jnd, 2); + break; + case CRETE_RDMA_CONF_CAP: + crete_ioread32(addr, &hw->rdma_desc, 2); + break; + case CRETE_OFFLOAD_CONF_CAP: + crete_ioread32(addr, &hw->offload_desc, 2); + break; + case CRETE_RES_CONF_CAP: + crete_ioread32(addr, &hw->jrd, 2); + break; + case CRETE_DEVS_CONF_CAP: + crete_ioread32(addr, &hw->dev_spec_desc, 2); + break; + case CRETE_SHARES_DB_CAP: + crete_ioread32(addr, &hw->share_data_desc, 2); + break; + default: + pr_err("cap not found\n"); + return -EIO; + } + + return 0; +} + +static int crete_net_cap_lookup(struct crete_core_dev *core_dev, + struct crete_hw *hw) +{ + int i = 0; + uint16_t cap_type; + uint8_t __iomem *addr = core_dev->io_addr + CRETE_JND_OFFSET; + + hw->io_addr = (struct crete_init_seg *)(core_dev->io_addr + + hw->jdh.offset * sizeof(int)); + + for (i = 0; i < hw->jdh.cap_cnt; i++) { + cap_type = readw(addr); + if (cap_type == CRETE_NET_CONF_CAP) + return 0; + addr += CRETE_CAP_OFFSET; + } + + return -ENXIO; +} + +static int crete_cap_init(struct crete_core_dev *core_dev, struct crete_hw *hw) +{ + u8 __iomem *addr = core_dev->io_addr + CRETE_JND_OFFSET; + int i = 0; + int err = 0; + + for (i = 0; i < hw->jdh.cap_cnt; i++) { + err = crete_cap_parse(core_dev, addr, hw); + if (err < 0) { + pr_err("parse cap err\n"); + return err; + } + addr += CRETE_CAP_OFFSET; + } + + return err; +} + +static int crete_reset(struct crete_hw *hw) +{ + int cnt = 0; + + writeb(CRETE_HW_RESET, &hw->io_addr->reset_dev); + + for (cnt = 0; cnt < CRETE_HW_RESET_TIMEOUT; cnt++) { + if (!readb(&hw->io_addr->dev_status)) + break; + + msleep(20); + } + + if (cnt == CRETE_HW_RESET_TIMEOUT) { + pr_err("crete reset polling failed to complete.\n"); + return -EIO; + } + + return 0; +} + +static int crete_hw_init(struct crete_core_dev *core_dev, struct crete_hw *hw) +{ + int err = -EINVAL; + u8 val = 0; + + /* TODO:may be this can be saved in memory */ + crete_ioread32((CRETE_JDH_OFFSET + core_dev->io_addr), &hw->jdh, 2); + + if (hw->jdh.magic != CRETE_MAGIC_NUM) { + dev_err(&core_dev->pdev->dev, + "crete hear err, magic:0x%x,cap cnt:0x%x\n", + hw->jdh.magic, hw->jdh.cap_cnt); + goto done; + } + + hw->io_addr = (struct crete_init_seg *)(core_dev->io_addr + + hw->jdh.offset * sizeof(int)); + pr_err("func:%s-line:%d-offset:0x%x\n", __func__, __LINE__, + hw->jdh.offset); + + err = crete_reset(hw); + if (err < 0) + goto done; + + val = CRETE_DEV_ACK | CRETE_DEV_DRV; + writeb(val, &hw->io_addr->dev_status); + + err = crete_net_cap_lookup(core_dev, hw); + if (err < 0) { + dev_err(&core_dev->pdev->dev, "net cap not found\n"); + val = CRETE_DEV_FAIL; + writeb(val, &hw->io_addr->dev_status); + goto done; + } + + err = crete_cap_init(core_dev, hw); + if (!err) { + val = readb(&hw->io_addr->dev_status); + val |= CRETE_DEV_CAP; + writeb(val, &hw->io_addr->dev_status); + } +done: + return err; + +} + +static int crete_hw_uninit(struct crete_core_dev *core_dev, struct crete_hw *hw) +{ + return 0; +} + +static int crete_sw_init(struct crete_core_dev *core_dev, struct crete_hw *hw) +{ + /* Assume MSI-X interrupts, will be checked during IRQ allocation */ +// core_dev->flags |= CRETE_FLAG_HAS_MSIX; + + /* get queue num */ + crete_init_queue_configuration(core_dev); + + set_bit(__CRETE_DOWN, &core_dev->state); + + return 0; +} + +static int crete_sw_uninit(struct crete_core_dev *core_dev, struct crete_hw *hw) +{ + /* do nothing */ + return 0; +} + +static void crete_shutdown(struct pci_dev *pdev) +{ +} + +static int crete_load(struct crete_core_dev *dev) +{ + int err; + + err = crete_attach_device(dev); + if (err) + return err; + if (crete_have_rdma_cap(dev)) { + err = jm_attach_device(&dev->rdma_coredev); + if (err) + crete_detach_device(dev); + } + + return err; +} + +static void crete_unload(struct crete_core_dev *dev) +{ + if (crete_have_rdma_cap(dev)) + jm_detach_device(&dev->rdma_coredev); + + crete_eswitch_disable(dev->eswitch); + crete_detach_device(dev); +} + +int crete_create_mdev_resources(struct crete_core_dev *core_dev) +{ + return 0; +} + +void crete_destroy_coredev_resources(struct crete_core_dev *core_dev) +{ +} + +static int crete_resume(struct auxiliary_device *adev) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = aux_dev->core_dev; + struct net_device *netdev = core_dev->netdev; + int err; + + if (netif_device_present(netdev)) + return 0; + + err = crete_create_mdev_resources(core_dev); + if (err) + return err; + + err = crete_attach_netdev(core_dev); + if (err) { + crete_destroy_coredev_resources(core_dev); + return err; + } + + return 0; +} + +static int crete_suspend(struct auxiliary_device *adev, pm_message_t state) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = aux_dev->core_dev; + struct net_device *netdev = core_dev->netdev; + + if (!netif_device_present(netdev)) + return -ENODEV; + + crete_detach_netdev(core_dev); + crete_destroy_coredev_resources(core_dev); + return 0; +} + +static int crete_cdev_ring_init(struct crete_core_dev *cdev) +{ + int ret; + int qpnum; + struct pci_dev *pdev; + + pdev = cdev->pdev; + qpnum = cdev->ring_size; + + cdev->jnapi = kcalloc(2 * qpnum, sizeof(struct crete_napi), GFP_KERNEL); + if (!cdev->jnapi) + return -ENOMEM; + + cdev->rxring = + kcalloc(qpnum, sizeof(struct crete_rxring_info), GFP_KERNEL); + if (!cdev->rxring) { + kfree(cdev->jnapi); + return -ENOMEM; + } + + cdev->rxring_mapping = kcalloc(qpnum, sizeof(u16), GFP_KERNEL); + if (!cdev->rxring_mapping) { + ret = -ENOMEM; + goto err_rxmapping; + } + + cdev->txring = + kcalloc(qpnum, sizeof(struct crete_txring_info), GFP_KERNEL); + if (!cdev->txring) { + ret = -ENOMEM; + goto err_txring; + } + + cdev->txring_mapping = kcalloc(qpnum, sizeof(u16), GFP_KERNEL); + if (!cdev->txring_mapping) { + ret = -ENOMEM; + goto err_txmapping; + } + + cdev->db = kzalloc(sizeof(struct crete_db), GFP_KERNEL); + if (!cdev->db) { + ret = -ENOMEM; + goto err_db; + } + + cdev->db->db_addr = cdev->db_base; // all the queue will share the doorbell address + cdev->rxcpring = + kcalloc(qpnum, sizeof(struct crete_rxcp_ring_info), GFP_KERNEL); + cdev->txcpring = + kcalloc(qpnum, sizeof(struct crete_txcp_ring_info), GFP_KERNEL); + + return 0; + +err_db: + kfree(cdev->txring_mapping); + cdev->txring_mapping = NULL; + +err_txmapping: + kfree(cdev->txring); + cdev->txring = NULL; + +err_txring: + kfree(cdev->rxring_mapping); + cdev->rxring_mapping = NULL; + +err_rxmapping: + kfree(cdev->jnapi); + cdev->jnapi = NULL; + kfree(cdev->rxring); + cdev->rxring = NULL; + + return ret; +} + +static int crete_alloc_rxring_mem(struct crete_core_dev *cdev, + struct crete_rxring_info *rxring) +{ + dma_addr_t mapping; + void *addr; + int i; + struct device *dev = &cdev->pdev->dev; + u16 queuesize = cdev->cap.qpcap.max_queue_size; + size_t len = L1_CACHE_ALIGN(queuesize * CRETE_ENTRY_DFAULT_SIZE); + + /* if the length is zero + * or the length is not power of 2 return error + */ + if (!len || !is_power_of_2(len)) { + crete_err(dev, "queue size not correct\n"); + return -EINVAL; + } + + addr = dma_alloc_coherent(dev, len, &mapping, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + crete_info(dev, "rxring mem dma handle 0x%llx, addr 0x%lx\n", mapping, + (unsigned long)addr); + + rxring->rx_bd = addr; + rxring->rx_bd_mapping = mapping; + rxring->rx_ring_size = queuesize; + rxring->rx_ring_mask = queuesize - 1; + rxring->rx_cons = rxring->rx_prod = 0; + rxring->bd_len = len; + rxring->rx_buf = + kcalloc(queuesize, sizeof(struct crete_rx_buf), GFP_KERNEL); + rxring->rxq_stats = kcalloc(1, sizeof(struct crete_rxq_stats), GFP_KERNEL); + if (!rxring->rxq_stats) { + return -ENOMEM; + } + u64_stats_init(&rxring->rxq_stats->syncp); + + /* init the rx ring buffer ref conter is 0*/ + for (i = 0; i < queuesize; i++) + refcount_set(&rxring->rx_buf[i].kref, 0); + + return 0; +} + +static int crete_alloc_txring_mem(struct crete_core_dev *cdev, + struct crete_txring_info *txring) +{ + dma_addr_t mapping; + void *addr; + int i; + struct device *dev = &cdev->pdev->dev; + u16 queuesize = cdev->cap.qpcap.max_queue_size; + size_t len = L1_CACHE_ALIGN(queuesize * CRETE_ENTRY_DFAULT_SIZE); + + crete_info(dev, "crete alloc txring mem ring id:%d cpring:0x%lx\n", + txring->id, (unsigned long)txring->cpring); + + if (!len || !is_power_of_2(len)) { + crete_warn(dev, "is not power of 2\n"); + return -EINVAL; + } + + addr = dma_alloc_coherent(dev, len, &mapping, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + crete_info(dev, "txring mem dma handle 0x%llx, addr 0x%lx\n", mapping, + (unsigned long)addr); + + txring->tx_bd = addr; + txring->tx_bd_mapping = mapping; + txring->tx_ring_size = queuesize; + txring->tx_ring_mask = queuesize - 1; + atomic_set(&txring->ring_avail, queuesize); + txring->bd_len = len; + txring->tx_buf = + kcalloc(queuesize, sizeof(struct crete_tx_buf), GFP_KERNEL); + txring->txq_stats = kcalloc(1, sizeof(struct crete_txq_stats), GFP_KERNEL); + if (!txring->txq_stats) { + return -ENOMEM; + } + u64_stats_init(&txring->txq_stats->syncp); + + /* init the tx ring buffer ref conter is 0*/ + for (i = 0; i < queuesize; i++) + refcount_set(&txring->tx_buf[i].kref, 0); + + return 0; +} + +static int crete_alloc_txcpring_mem(struct crete_core_dev *cdev, + struct crete_txcp_ring_info *txcpr) +{ + dma_addr_t mapping; + void *addr; + struct device *dev = &cdev->pdev->dev; + u16 queuesize = cdev->cap.qpcap.max_queue_size; + size_t len = L1_CACHE_ALIGN(queuesize * CRETE_ENTRY_DFAULT_SIZE); + + if (!len || !is_power_of_2(len)) { + crete_warn(dev, "is not power of 2\n"); + return -EINVAL; + } + + addr = dma_alloc_coherent(dev, len, &mapping, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + txcpr->txcq_base = addr; + txcpr->txcq_mapping = mapping; + txcpr->ring_size = queuesize; + txcpr->ring_mask = queuesize - 1; + txcpr->bd_len = len; + atomic_set(&txcpr->ring_avail, queuesize); + return 0; + +} + +static int crete_alloc_rxcpring_mem(struct crete_core_dev *cdev, + struct crete_rxcp_ring_info *rxcpr) +{ + dma_addr_t mapping; + void *addr; + struct device *dev = &cdev->pdev->dev; + u16 queuesize = cdev->cap.qpcap.max_queue_size; + size_t len = L1_CACHE_ALIGN(queuesize * CRETE_ENTRY_DFAULT_SIZE); + + if (!len || !is_power_of_2(len)) { + crete_warn(dev, "is not power of 2\n"); + return -EINVAL; + } + + addr = dma_alloc_coherent(dev, len, &mapping, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + rxcpr->rxcq_base = addr; + rxcpr->rxcq_mapping = mapping; + rxcpr->ring_size = queuesize; + rxcpr->ring_mask = queuesize - 1; + rxcpr->bd_len = len; + + return 0; +} + +static int crete_alloc_rings(struct crete_core_dev *cdev) +{ + int ret; + int ring_size = cdev->ring_size; + int i; + struct crete_rxring_info *rxring; + struct crete_txring_info *txring; + struct crete_rxcp_ring_info *rxcpring; + struct crete_txcp_ring_info *txcpring; + struct device *dev = cdev->device; + + if (ring_size <= 0) + return -EBUSY; + + rxring = cdev->rxring; + crete_info(dev, "rx ring alloc mem ring size:%u\n", ring_size); + for (i = 0; i < ring_size; i++) { + ret = crete_alloc_rxring_mem(cdev, &rxring[i]); + if (ret) + return -ENOMEM; + } + + crete_info(dev, "tx ring alloc mem ring size:%u\n", ring_size); + txring = cdev->txring; + for (i = 0; i < ring_size; i++) { + ret = crete_alloc_txring_mem(cdev, &txring[i]); + if (ret) + return -ENOMEM; + } + + rxcpring = cdev->rxcpring; + for (i = 0; i < ring_size; i++) { + ret = crete_alloc_rxcpring_mem(cdev, &rxcpring[i]); + if (ret) + return -ENOMEM; + } + + crete_info(dev, "rxcpring mem alloc mem\n"); + txcpring = cdev->txcpring; + for (i = 0; i < ring_size; i++) { + ret = crete_alloc_txcpring_mem(cdev, &txcpring[i]); + if (ret) + return -ENOMEM; + } + + for (i = 0; i < ring_size; i++) { + txcpring->wrap_counter = 0; + rxcpring->wrap_counter = 0; + rxcpring += 1; + txcpring += 1; + } + + return 0; +} + +static int crete_free_rxring_mem(struct crete_core_dev *cdev) +{ + int i; + struct crete_rxring_info *rxr; + struct device *dev = &cdev->pdev->dev; + + crete_info(dev, "free rxring mem\n"); + for (i = 0; i < cdev->ring_size; i++) { + rxr = &cdev->rxring[i]; + dma_free_coherent(dev, rxr->bd_len, (void *)rxr->rx_bd, + rxr->rx_bd_mapping); + rxr->rx_bd = NULL; + rxr->rx_bd_mapping = 0; + rxr->bd_len = 0; + kfree(rxr->rxq_stats); + rxr->rxq_stats = NULL; + } + + return 0; +} + +static int crete_free_txring_mem(struct crete_core_dev *cdev) +{ + int i; + struct device *dev = &cdev->pdev->dev; + struct crete_txring_info *txr; + + crete_info(dev, "free txring mem\n"); + for (i = 0; i < cdev->ring_size; i++) { + txr = &cdev->txring[i]; + dma_free_coherent(dev, txr->bd_len, (void *)txr->tx_bd, + txr->tx_bd_mapping); + txr->tx_bd = NULL; + txr->tx_bd_mapping = 0; + txr->bd_len = 0; + kfree(txr->txq_stats); + txr->txq_stats = NULL; + } + + return 0; +} + +static int crete_free_txcpring_mem(struct crete_core_dev *cdev) +{ + int i; + struct device *dev = &cdev->pdev->dev; + struct crete_txcp_ring_info *txcpr; + + crete_info(dev, "free txcpring mem\n"); + for (i = 0; i < cdev->ring_size; i++) { + txcpr = &cdev->txcpring[i]; + dma_free_coherent(dev, txcpr->bd_len, (void *)txcpr->txcq_base, + txcpr->txcq_mapping); + txcpr->txcq_base = NULL; + txcpr->txcq_mapping = 0; + txcpr->bd_len = 0; + } + + return 0; +} + +static int crete_free_rxcpring_mem(struct crete_core_dev *cdev) +{ + int i; + struct device *dev = &cdev->pdev->dev; + struct crete_rxcp_ring_info *rxcpr; + + dev = &cdev->pdev->dev; + crete_info(dev, "free rxcpring mem\n"); + for (i = 0; i < cdev->ring_size; i++) { + rxcpr = &cdev->rxcpring[i]; + dma_free_coherent(dev, rxcpr->bd_len, (void *)rxcpr->rxcq_base, + rxcpr->rxcq_mapping); + rxcpr->rxcq_base = NULL; + rxcpr->rxcq_mapping = 0; + rxcpr->bd_len = 0; + } + + return 0; +} + +static void crete_free_rings(struct crete_core_dev *cdev) +{ + crete_free_rxring_mem(cdev); + crete_free_txring_mem(cdev); + crete_free_txcpring_mem(cdev); + crete_free_rxcpring_mem(cdev); +} + +static void crete_cdev_ring_exit(struct crete_core_dev *cdev) +{ + kfree(cdev->rxcpring); + kfree(cdev->txcpring); + kfree(cdev->db); + kfree(cdev->txring_mapping); + kfree(cdev->txring); + kfree(cdev->rxring_mapping); + kfree(cdev->rxring); + kfree(cdev->jnapi); + cdev->rxcpring = NULL; + cdev->txcpring = NULL; + cdev->db = NULL; + cdev->txring_mapping = NULL; + cdev->txring = NULL; + cdev->rxring_mapping = NULL; + cdev->rxring = NULL; + cdev->jnapi = NULL; +} + +void crete_rel_msixirq(struct crete_core_dev *cdev); +static void crete_delete_rings(struct crete_core_dev *cdev) +{ + crete_rel_msixirq(cdev); + + crete_free_rings(cdev); + crete_cdev_ring_exit(cdev); +} + +static int crete_trim_rings(struct crete_core_dev *cdev) +{ + int cpunums = num_online_cpus(); + int maxqpnums = cdev->cap.qpcap.max_qp_num; + + cdev->ring_size = min(cpunums, maxqpnums); + if (!cdev->ring_size) { + crete_err(cdev->device, "ring size zero not right\n"); + return -1; + } + + cdev->max_qp_num = cdev->ring_size; + + return 0; +} + +static void crete_init_napi(struct crete_core_dev *cdev) +{ + int i; + struct crete_napi *jnapi; + struct crete_napi *rx_jnapi; + struct crete_napi *tx_jnapi; + + jnapi = cdev->jnapi; + crete_info(&cdev->pdev->dev, "crete init napi\n"); + + for (i = 0; i < cdev->ring_size; i++) { + rx_jnapi = &jnapi[i * 2]; // rx ring is even number + tx_jnapi = &jnapi[i * 2 + 1]; // tx ring is odd number + + rx_jnapi->cdev = cdev; + rx_jnapi->rxring = &cdev->rxring[i]; + rx_jnapi->rxring->id = i * 2; + rx_jnapi->rxring->priv = rx_jnapi; + rx_jnapi->rxcpring = &cdev->rxcpring[i]; + rx_jnapi->rxcpring->priv = rx_jnapi; + + tx_jnapi->cdev = cdev; + tx_jnapi->txring = &cdev->txring[i]; + tx_jnapi->txring->id = i * 2 + 1; + tx_jnapi->txring->priv = tx_jnapi; + tx_jnapi->txcpring = &cdev->txcpring[i]; + tx_jnapi->txcpring->priv = tx_jnapi; + } + +} + +/* reserve the msix irq vector */ +static int crete_reserve_msixirq(struct crete_core_dev *cdev) +{ +#define TX_IRQ_NAME "%s-tx-%d" +#define RX_IRQ_NAME "%s-rx-%d" + int i, rc = 0, qp_num, max_irqs, qp_irqs, irqno; + struct crete_irq_info *irq_info; + struct crete_napi *jnapi; + struct crete_rxring_info *rxr; + struct crete_txring_info *txr; + + if (!(cdev->flags & CRETE_FLAG_HAS_MSIX)) { + crete_err(cdev->device, "no msix cap, return failed\n"); + return -EINVAL; + } + + qp_num = cdev->ring_size; + qp_irqs = qp_num << 1; + max_irqs = cdev->irq_num; + + if (max_irqs < qp_irqs) + return 0; + + for (i = 0; i < qp_irqs; i++) { + irqno = crete_req_msixirq(cdev); + irq_info = &cdev->irq_info[irqno]; + jnapi = &cdev->jnapi[i]; + crete_info(cdev->device, "irqno =%d vector =%d i=%d add lyx\n", irqno, + irq_info->vector, i); + snprintf(irq_info->name, IFNAMSIZ + 2, + (i & 0x1) ? TX_IRQ_NAME : RX_IRQ_NAME, + pci_name(cdev->pdev), i >> 1); + if (i & 0x1) { + txr = jnapi->txring; + txr->vec = irqno; + } else { + rxr = jnapi->rxring; + rxr->vec = irqno; + } + irq_info->requested = 1; + } + + return rc; +} + +void crete_rel_msixirq(struct crete_core_dev *cdev) +{ + int i, qp_irqs, irqno; + struct crete_irq_info *irq_info; + struct crete_napi *jnapi; + + if (!(cdev->flags & CRETE_FLAG_HAS_MSIX)) + return; + + qp_irqs = cdev->ring_size << 1; + + for (i = 0; i < qp_irqs; i++) { + jnapi = &cdev->jnapi[i]; + irqno = (i & 0x1) ? jnapi->txring->vec : jnapi->rxring->vec; + irq_info = &cdev->irq_info[irqno]; + if (!irq_info->requested) + break; + irq_info->requested = 0; + crete_free_msixirq(cdev, irqno); + } + +} + +static int crete_reserve_rings(struct crete_core_dev *cdev) +{ + int ret, i; + + /* + * alloc ring memory + */ + ret = crete_cdev_ring_init(cdev); + if (ret) + return ret; + + /* + * alloc ring bd dma memory + */ + ret = crete_alloc_rings(cdev); + if (ret) + goto err; + + /* init ring napi */ + crete_init_napi(cdev); + + /* request msix irq vectors */ + crete_reserve_msixirq(cdev); + + /* create the hw qp */ + for (i = 0; i < cdev->ring_size; i++) { + ret = crete_create_txrxqp(cdev, i); + if (ret) + goto err1; + } + + return 0; + +err1: + crete_rel_msixirq(cdev); + + crete_free_rings(cdev); + +err: + crete_cdev_ring_exit(cdev); + + return ret; +} + +static int crete_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = aux_dev->core_dev; + struct pci_dev *pdev = core_dev->pdev; + struct device *dev = &pdev->dev; + struct crete_priv *priv; + struct net_device *netdev; + pm_message_t state = { }; + int err; + + err = crete_set_dev_type(core_dev, CRETE_JNET_DEV); + if (err < 0) { + dev_err(&core_dev->pdev->dev, "set jnet dev type failed\n"); + return -EINVAL; + } + /* get core dev cap init */ + err = crete_cdev_cap_init(core_dev); + if (err) { + dev_err(dev, "crete core dev get cap failed\n"); + return -EINVAL; + } + + err = crete_features_negotiate(core_dev); + if (err < 0) { + dev_err(&core_dev->pdev->dev, "features negotiate failed\n"); + return -EINVAL; + } + /* reserve the ring size */ + err = crete_trim_rings(core_dev); + if (err) + return err; + + netdev = crete_create_netdev(core_dev); + if (!netdev) { + dev_err(dev, "crete_create_netdev failed\n"); + return -ENOMEM; + } + + err = crete_build_nic_netdev(netdev); + priv = netdev_priv(netdev); + //auxiliary_set_drvdata(adev, priv); + + err = crete_resume(adev); + if (err) { + dev_err(dev, "crete_resume failed, %d\n", err); + goto err_crete_resume; + } + + err = crete_init_mac_addr(netdev); + if (err) { + dev_err(dev, "Unable to initialize mac address.\n"); + goto err_init_mac_addr; + } + + err = crete_reserve_rings(core_dev); + if (err) { + dev_err(dev, "Reserve rings failed\n"); + goto err_init_mac_addr; + } + + crete_dcbnl_init_app(priv); + crete_dcbnl_initialize(priv); + + err = register_netdev(netdev); + if (err) { + dev_err(dev, "register_netdev failed, %d\n", err); + goto err_register_netdev; + } + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + return 0; + +err_register_netdev: + crete_delete_rings(core_dev); + +err_init_mac_addr: + crete_suspend(adev, state); + +err_crete_resume: + crete_destroy_netdev(netdev); + + return err; +} + +/* + * about the anolis 5.10.134-14 kernel version + * auxliary define with return int value + */ +#ifdef SNIC_ANOLIS_VERSION14 + +static int crete_remove(struct auxiliary_device *adev) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = aux_dev->core_dev; + struct net_device *netdev = core_dev->netdev; + pm_message_t state = { }; + + unregister_netdev(netdev); + + crete_delete_rings(core_dev); + + crete_suspend(adev, state); + crete_destroy_netdev(netdev); + return 0; +} + +#else + +static void crete_remove(struct auxiliary_device *adev) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = aux_dev->core_dev; + struct net_device *netdev = core_dev->netdev; + pm_message_t state = { }; + + unregister_netdev(netdev); + + crete_delete_rings(core_dev); + + crete_suspend(adev, state); + crete_destroy_netdev(netdev); +} + +#endif + +static const struct auxiliary_device_id crete_id_table[] = { + {.name = CRETE_ADEV_NAME ".eth", }, + { }, +}; + +MODULE_DEVICE_TABLE(auxiliary, crete_id_table); + +static struct auxiliary_driver crete_aux_driver = { + .name = "eth", + .probe = crete_probe, + .remove = crete_remove, + .suspend = crete_suspend, + .resume = crete_resume, + .id_table = crete_id_table, +}; + +int crete_init(void) +{ + int ret; + + ret = auxiliary_driver_register(&crete_aux_driver); + if (ret) + return ret; + /* + *ret = crete_rep_init(); + *if (ret) + * auxiliary_driver_unregister(&crete_aux_driver); + */ + return ret; +} + +void crete_cleanup(void) +{ + /* crete_rep_cleanup(); */ + auxiliary_driver_unregister(&crete_aux_driver); +} + +#if 0 +/* NEED_ETH_HW_ADDR_SET + * + * eth_hw_addr_set was added by upstream commit + * 48eab831ae8b ("net: create netdev->dev_addr assignment helpers") + * + * Using eth_hw_addr_set became required in 5.17, when the dev_addr field in + * the netdev struct was constified. See 48eab831ae8b ("net: create + * netdev->dev_addr assignment helpers") + */ +#ifdef NEED_ETH_HW_ADDR_SET +static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr) +{ + ether_addr_copy(dev->dev_addr, addr); +} +#endif /* NEED_ETH_HW_ADDR_SET */ +#endif + +int crete_change_mac_addr(struct net_device *netdev, void *p) +{ + struct sockaddr *addr = p; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + + int rc = 0; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + if (ether_addr_equal(addr->sa_data, netdev->dev_addr)) + return 0; + + rc = crete_approve_mac(core_dev, addr->sa_data); + if (rc) + return rc; + dev_err(&pdev->dev, "VF MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned char)addr->sa_data[0], + (unsigned char)addr->sa_data[1], + (unsigned char)addr->sa_data[2], + (unsigned char)addr->sa_data[3], + (unsigned char)addr->sa_data[4], + (unsigned char)addr->sa_data[5]); + netif_addr_lock_bh(netdev); + eth_hw_addr_set(netdev, addr->sa_data); + netif_addr_unlock_bh(netdev); + rc = crete_set_default_mac(netdev); + if (rc) + return rc; + crete_set_rx_mode(netdev); + return rc; +} + +static int crete_init_mac_addr(struct net_device *netdev) +{ + int rc = 0; + static int count1; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + + if (crete_core_is_pf(core_dev)) { + /* pf stub mac */ + count1++; + core_dev->pf.mac_addr[0] = 0x52; + core_dev->pf.mac_addr[1] = (PCI_VENDOR_ID_CRETE >> 8) & 0xff; + core_dev->pf.mac_addr[2] = PCI_VENDOR_ID_CRETE & 0xff; + core_dev->pf.mac_addr[3] = (PF_DEVICE_ID >> 8) & 0xff; + core_dev->pf.mac_addr[4] = PF_DEVICE_ID & 0xff; + core_dev->pf.mac_addr[5] = count1 & 0xff; + eth_hw_addr_set(netdev, core_dev->pf.mac_addr); + rc = crete_set_default_mac(netdev); + if (rc) { + dev_err(&pdev->dev, + "Set pf default MAC address failed rc:0x%x", + rc); + return rc; + } + + } else { + struct crete_vf_info *vf = &core_dev->vf; + + if (is_valid_ether_addr(vf->mac_addr)) { + /* overwrite netdev dev_addr with admin VF MAC */ + eth_hw_addr_set(netdev, vf->mac_addr); + } else { + eth_hw_addr_random(netdev); + } + rc = crete_set_default_mac(netdev); + if (rc) { + dev_err(&pdev->dev, + "Set vf default MAC address failed rc:0x%x", + rc); + return rc; + } + + rc = crete_approve_mac(core_dev, netdev->dev_addr); + if (rc) { + dev_err(&pdev->dev, + "Set approve vf MAC address failed rc:0x%x", + rc); + return rc; + } + } + return rc; +} + +static bool crete_uc_list_updated(struct net_device *dev) +{ + struct crete_priv *priv = netdev_priv(dev); + struct netdev_hw_addr *ha; + int off = 0; + + if (netdev_uc_count(dev) != (priv->uc_filter_count - 1)) + return true; + + netdev_for_each_uc_addr(ha, dev) { + if (!ether_addr_equal(ha->addr, priv->uc_list + off)) + return true; + + off += ETH_ALEN; + } + return false; +} + +static bool crete_mc_list_updated(struct net_device *dev, u32 *rx_mask) +{ + struct crete_priv *priv = netdev_priv(dev); + struct netdev_hw_addr *ha; + int mc_count = 0; + bool update = false; + int off = 0; + + netdev_for_each_mc_addr(ha, dev) { + if (mc_count >= CRETE_MAX_MC_ADDRS) { + *rx_mask |= L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + priv->mc_list_count = 0; + return false; + } + if (!ether_addr_equal(ha->addr, priv->mc_list + off)) { + memcpy(priv->mc_list + off, ha->addr, ETH_ALEN); + update = true; + } + off += ETH_ALEN; + mc_count++; + } + if (mc_count) + *rx_mask |= L2_SET_RX_MASK_REQ_MASK_MCAST; + + if (mc_count != priv->mc_list_count) { + priv->mc_list_count = mc_count; + update = true; + } + return update; +} + +static void crete_queuework_set_rx_mode(struct crete_priv *priv) +{ + /* no rx mode for uplink rep */ + + queue_work(priv->wq, &priv->set_rx_mode_work); +} + +void crete_set_rx_mode(struct net_device *dev) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *core_dev = priv->coredev; + bool mc_update; + bool uc_update = false; + u32 mask; + + /* dev open */ + if (!test_bit(__CRETE_DOWN, &core_dev->state)) + return; + + mask = priv->rx_mask; + mask &= ~(L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS | + L2_SET_RX_MASK_REQ_MASK_MCAST | + L2_SET_RX_MASK_REQ_MASK_ALL_MCAST | + L2_SET_RX_MASK_REQ_MASK_BCAST); + + if (dev->flags & IFF_PROMISC) + mask |= L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + + uc_update = crete_uc_list_updated(dev); + + if (dev->flags & IFF_BROADCAST) + mask |= L2_SET_RX_MASK_REQ_MASK_BCAST; + if (dev->flags & IFF_ALLMULTI) { + mask |= L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + priv->mc_list_count = 0; + } else if (dev->flags & IFF_MULTICAST) { + mc_update = crete_mc_list_updated(dev, &mask); + } + + if (mask != priv->rx_mask || uc_update || mc_update) { + priv->rx_mask = mask; + crete_queuework_set_rx_mode(priv); + } +} + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.h new file mode 100644 index 0000000..3a6abec --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.h @@ -0,0 +1,736 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _CRETE_H_ +#define _CRETE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef USE_JM_AUX_BUS +#include +#else +#include "linux/auxiliary_bus.h" +#endif +#include "kcompat_std_defs.h" +#include "rdma.h" +#include "crete_txrx.h" +#include "crete_sriov.h" +#include "crete_eswitch.h" +#include "crete_dcb_nl.h" +#include "crete_lag.h" +#include "crete_debugfs_statistics.h" +/*micro filed*/ +#define MAX_MSIX_ENTRIES 10 +#define MAX_Q_VECTORS 8 + +#define CRETE_MAX_TX_QUEUES 8 +#define CRETE_MAX_RX_QUEUES 8 + +#define CRETE_DEFAULT_TXD 256 +#define CRETE_DEFAULT_TX_WORK 128 +#define CRETE_MIN_TXD 80 +#define CRETE_MAX_TXD 4096 + +#define CRETE_DEFAULT_RXD 256 +#define CRETE_MIN_RXD 80 +#define CRETE_MAX_RXD 4096 + +#define CRETE_DEFAULT_ITR 3 /* dynamic */ +#define CRETE_MAX_ITR_USECS 10000 +#define CRETE_MIN_ITR_USECS 10 +#define CRETE_Q_VECTORS 1 + +#define CRETE_ETH_PKT_HDR_PAD (ETH_HLEN + ETH_FCS_LEN) + +/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */ +#define MAX_JUMBO_FRAME_SIZE 0x2600 +#define MAX_STD_JUMBO_FRAME_SIZE 9216 + +/* Supported Rx Buffer Sizes */ +#define CRETE_RXBUFFER_256 256 +#define CRETE_RXBUFFER_1536 1536 +#define CRETE_RXBUFFER_2048 2048 +#define CRETE_TS_HDR_LEN 16 +#define ALIGN_TO_DW(a) (((a) + 3ULL) & (~3)) +#define CRETE_CMD_WQ_MAX_NAME 32 + +/* device desc offset */ +#define CRETE_JDH_OFFSET (CRETE_LEGACY_RESV) +#define CRETE_JND_OFFSET (CRETE_JDH_OFFSET + sizeof(struct crete_desc_hdr)) +#define CRETE_JRD_OFFSET (CRETE_JND_OFFSET + sizeof(struct crete_ndc_dpt)) +#define CRETE_CAP_OFFSET 8 + +enum { + CRETE_FLAG_DISABLE_ALL_ADEV = 1 << 0, + CRETE_PAGE_MODE = 1 << 1, + CRETE_FLAG_HAS_MSIX = 1 << 13, +}; + +#define CRETE_LEGACY_RESV 0x0 +#define CRETE_MAGIC_NUM 0xdeadbeef + +#define CRETE_EVENT_VECTOR 0 + +#define CRETE_CMD_DATA_BLOCK_SIZE 512 + +enum crete_coredev_type { + CRETE_COREDEV_PF, + CRETE_COREDEV_VF, + CRETE_COREDEV_SF, +}; + + +enum crete_device_type { + CRETE_DEVICE_CRETE, + CRETE_DEVICE_PNIC, + CRETE_DEVICE_RNIC, + CRETE_DEVICE_FAKE, +}; + +enum { + CRETE_PCI_DEV_IS_VF = 1 << 0, +}; + +#define CRETE_ADEV_NAME "crete_core" + +/*enum filed*/ +enum crete_state_t { + __CRETE_TESTING, + __CRETE_RESETING, + __CRETE_DOWN, +}; + +/* Device Capability type */ +enum crete_cap_type { + CRETE_NET_CONF_CAP = 2, + CRETE_RDMA_CONF_CAP = 3, + CRETE_OFFLOAD_CONF_CAP = 4, + CRETE_RES_CONF_CAP = 5, + CRETE_DEVS_CONF_CAP = 6, + CRETE_SHARES_DB_CAP = 7, + CRETE_CAP_MAX, +}; + +struct crete_init_seg { + uint16_t fw_ver_minor; + uint16_t fw_ver_major; + uint16_t fw_revision; + uint16_t cmd_interface_rev; + uint8_t cp_status; + uint8_t cp_caps; + uint8_t dev_status; + uint8_t reset_dev; + uint32_t cmd_path_db; + uint32_t cmd_path_entry[16]; + uint32_t resv1[8]; + uint32_t event_buffer[8]; + uint32_t event_buffer_addr_low; + uint32_t event_buffer_addr_hi; + uint8_t event_busy; + uint8_t event_buffer_size; + uint16_t event_vector; + uint32_t event_credit_doorbell; + uint16_t resv2; + uint16_t aq_queue_size; + uint32_t aq_queue_db; + uint32_t aq_base_addr_low; + uint32_t aq_base_addr_hi; + uint32_t shared_res_lock; + uint32_t shared_res_db; + uint32_t extra_admin_db; + uint32_t resv3[13]; + uint32_t timestamp[2]; +} __packed; + +struct cmd_info { + uint32_t owner:1; + uint32_t out_inline:1; + uint32_t in_inline:1; + uint32_t event_notify:1; + uint32_t status:4; + uint32_t sig:8; + uint32_t cmd_encap_type:8; + uint32_t cid:8; +}; + +struct crete_cmd_entry { + uint32_t in_len; + uint32_t out_len; + uint64_t in_ptr; + uint64_t out_ptr; + uint8_t inline_data[36]; + union { + struct cmd_info cmd_info; + uint32_t cmd_info_data; + }; +} __packed; + +struct crete_cmd_prot_block { + u8 sig; + u8 block_num; + u8 rsvd0; + u8 cid; + uint32_t cmd_data_len;//CRETE_CMD_DATA_BLOCK_SIZE + uint64_t next; + uint32_t next_len; + uint32_t cmd_data[]; +} __packed; + +struct crete_cmd_mailbox { + void *buf; + dma_addr_t dma; + struct crete_cmd_mailbox *next; +}; +struct crete_cmd_msg { + struct list_head list; + u32 msg_mode; + u32 len; + struct crete_cmd_mailbox *next; + u8 inline_data[36]; //inline bd Optimize todo +}__aligned(8); + +#define CRETE_MAX_COMMANDS 32 +struct crete_cmd_work_ent { + unsigned long state; + struct crete_cmd_msg *inb; + struct crete_cmd_msg *outb; + void *out; + int out_size; + int idx; + struct completion handling; + struct completion done; + struct crete_cmd *cmd; + struct work_struct work; + struct crete_cmd_entry *lay; + int ret; + u8 status;//fw return cmd status + u16 cmd_id; + bool polling; + u64 ts1; + u64 ts2; + /* Track the max comp handlers */ + refcount_t refcnt; +}; +struct crete_cmd { + struct crete_nb nb; + u8 mode; + u8 poll_mode; + void *cmd_buf; + dma_addr_t cmd_dma; + u32 cmd_size; + u32 cmd_stride; + struct dma_pool *pool; + int max_cmds; + unsigned long bitmask; + char wq_name[CRETE_CMD_WQ_MAX_NAME]; + struct workqueue_struct *wq; + struct semaphore sem; + spinlock_t alloc_lock; + struct crete_cmd_work_ent *ent_arr[CRETE_MAX_COMMANDS]; +}; + +/* for test qp create */ +struct crete_qbase_info { + void *va; + dma_addr_t pa; +}; + +struct crete_queue_info { + uint8_t rx_qid; + uint16_t q_size; + uint16_t vec[2]; + struct crete_qbase_info sq[2]; + struct crete_qbase_info cq[2]; +}; +/* + *Device Capability Descriptor + *Device Capability Descriptor Header + */ +struct crete_desc_hdr { + uint32_t magic; + uint32_t cap_cnt:8; + uint32_t len:12; + uint32_t offset:12; +}; + +// net device configuration descriptor,cap_type = 2 +struct crete_ndc_dpt { + uint32_t type:8; + uint32_t resv:24; + uint32_t len:12; + uint32_t offset:20; +}; + +// Rdma Device Configuration Descriptor,cap_type = 3 +struct crete_rdma_cfg_desc { + uint32_t cap_type:8; + uint32_t resv:24; + uint32_t len:12; + uint32_t offset:20; +}; + +// Offload Configuration Descriptor,cap_type = 4 +struct crete_offload_cfg_desc { + uint32_t cap_type:8; + uint32_t resv:24; + uint32_t len:12; + uint32_t offset:20; +}; + + +// resource configuration descriptor,cap_type = 5 +struct crete_rc_dpt { + uint32_t type:8; + uint32_t ru_size:12; + uint32_t ru_max:12; + uint32_t len:12; + uint32_t offset:20; +}; + +//Device-specific Configuration Descriptor,cap_type = 6 +struct crete_devs_dpt { + uint32_t cap_type:8; + uint32_t resv:24; + uint32_t len:12; + uint32_t offset:20; +}; + +//Shared Data Descriptor,cap_type = 7 +struct crete_shared_dpt { + uint32_t cap_type:8; + uint32_t len:24; + uint32_t offset; +}; + + +/* hw */ +struct crete_hw { + struct crete_init_seg __iomem *io_addr; + struct crete_desc_hdr jdh; + struct crete_ndc_dpt jnd; + struct crete_rdma_cfg_desc rdma_desc; + struct crete_offload_cfg_desc offload_desc; + struct crete_rc_dpt jrd; + struct crete_devs_dpt dev_spec_desc; + struct crete_shared_dpt share_data_desc; +}; + +struct crete_aux_dev { + struct crete_core_dev *core_dev; + struct auxiliary_device adev; + int idx; +}; + +#define CRETE_MAX_UC_ADDRS 4 +#define CRETE_MAX_MC_ADDRS 16 + + +#define L2_SET_RX_MASK_REQ_MASK_MCAST 0x1UL +#define L2_SET_RX_MASK_REQ_MASK_ALL_MCAST 0x2UL +#define L2_SET_RX_MASK_REQ_MASK_BCAST 0x4UL +#define L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS 0x8UL + +struct crete_priv { + struct crete_core_dev *coredev; + struct crete_esw_rep *rep; + struct net_device *netdev; + struct workqueue_struct *wq; + struct work_struct set_rx_mode_work; + struct crete_dcbx dcbx; + struct crete_dcbx_dp dcbx_dp; + + /* vport rx mode */ + u32 rx_mask; + __le64 fw_l2_filter_id[CRETE_MAX_UC_ADDRS]; + /* index 0 always dev_addr */ + u16 uc_filter_count; + u8 *uc_list; + + u8 *mc_list; + int mc_list_size; + int mc_list_count; + + int vlan_range_num; +}; + +struct crete_debugfs_entries { + struct dentry *dbg_root; + struct dentry *lag_debugfs; + struct dentry *statistics_debugfs; +}; + +struct crete_irq_info { + char name[IFNAMSIZ + 2]; + irq_handler_t handler; + unsigned int vector; + u8 requested:1; + u8 have_cpumask:1; +}; + +struct crete_pf_info { + u16 fw_fid; + u16 port_id; + u8 mac_addr[ETH_ALEN]; + u32 first_vf_id; + u16 active_vfs; + u16 registered_vfs; + u16 max_vfs; + + void *hwrm_cmd_req_addr[4]; + dma_addr_t hwrm_cmd_req_dma_addr[4]; + struct crete_vf_info *vf; + + struct kobject *config; + struct kobject *groups_config; + struct crete_sriov_vf_sysfs *vf_sysfs; +}; + +struct rdma_dev_adapt { + unsigned int flags; + unsigned int priv_flags; + unsigned int bar_offset; + unsigned int bar_len; + phys_addr_t uar_base; + unsigned int uar_size; + void __iomem *reg_addr; /*bar addr*/ + __le32 *cmd_db_reg; /* cmd db addr*/ + __le32 __iomem *eq_db_reg; + struct mutex intf_state_mutex; + unsigned int vector_base; + unsigned int vector_num; +}; + +struct crete_qp_context { + __le16 rx_qid; /* must be even */ + __le16 event_credit; + __le16 rx_sq_vq_size; /* vnet rx vq size */ + __le16 rx_cq_size; /* unless for vnet */ + __le16 tx_sq_vq_size; /* tx vq size for vnet */ + __le16 tx_cq_size; /* useless for vnet */ + __le16 rx_queue_vec; /* rx queue interrupt vector */ + __le16 tx_queue_vec; /* tx queue interrupt vector */ + __le64 rx_sq_desc_base; /* rx queue desc base address for vnet */ + __le64 rx_cq_used_base; /* rx cq address ,rx used ring address for vnet */ + __le64 tx_sq_desc_base; /* tx sq address, tx queue desc address for vnet */ + __le64 tx_cq_used_base; /* tx cq address, tx queue used ring address for vnet */ +}; + +struct crete_queue_context { + __le16 qid; /* must be even */ + __le16 queue_size; /* vnet io vq size */ + __le16 cq_size; /* vnet cq size */ + __le16 queue_vec; /*queue interrupt vector */ + __le16 resv; /*reserved */ + __le64 queue_desc_base; /* rx queue desc base address for vnet */ + __le64 queue_used_base; /* rx cq address ,rx used ring address for vnet */ +}; + +struct crete_core_qpcap { + u16 max_queue_size; + u8 max_qp_num; + u8 ctrl_queue_size; +}; + +struct crete_core_cap { + struct crete_core_qpcap qpcap; + __le64 hw_features; + __le64 driver_features; + // pf core cap need more +}; + +struct crete_qp_cap { + u8 ctrl_queue_size; + u8 max_qp_num; + __le16 max_queue_size; +} __packed; + +struct crete_txq_stats { + struct u64_stats_sync syncp; + u64 packets; + u64 bytes; + u64 kicks; +}; + +struct crete_rxq_stats { + struct u64_stats_sync syncp; + u64 packets; + u64 bytes; + u64 drops; + u64 kicks; +}; + +#define CRETE_TXQ_STATS(m) offsetof(struct crete_txq_stats, m) +#define CRETE_RXQ_STATS(m) offsetof(struct crete_rxq_stats, m) + +struct crete_core_dev { +#define CRETE_MAX_MSIX_NUM 4096U + spinlock_t lock; + struct device *device; + void __iomem *db_base; + struct pci_dev *pdev; + + struct crete_core_cap cap; + struct crete_txring_info *txring; + u16 *txring_mapping; +// u16 txring_size; + struct crete_rxring_info *rxring; + u16 *rxring_mapping; +// u16 rxring_size; + u16 ring_size; + // ring parameters + u32 rx_buf_size; + u32 rx_buf_use_size; /* useable size */ + u16 rx_offset; + u16 rx_dma_offset; + + struct crete_db *db; + //struct crete_core_cap *cap; + struct crete_napi *jnapi; + struct crete_rxcp_ring_info *rxcpring; + struct crete_txcp_ring_info *txcpring; + + u16 max_qp_num; + unsigned long state; + + struct net_device *netdev; + u64 netdev_features; + u64 offload_features; + unsigned int flags; + u32 rss_queues; + u8 __iomem *io_addr; + phys_addr_t bar_addr; //for further consider + + struct crete_hw hw; + struct crete_queue_info q_info; // for create qp test + struct crete_aux_dev **adev; + int adev_idx; + struct crete_irq_info *irq_info; + struct crete_cmd cmd; + struct crete_event_irq *event_irq; + u16 irq_num; + unsigned long irqbit[BITS_TO_LONGS(CRETE_MAX_MSIX_NUM)]; + struct msix_entry *msix_ent; + enum crete_coredev_type coredev_type; + enum crete_device_type device_type; + struct crete_pf_info pf; + struct crete_vf_info vf; + bool sriov_cfg; + + struct jm_rdma_core rdma_coredev; + struct rdma_dev_adapt rdma_adp; + + struct crete_eswitch *eswitch; + struct crete_lag_cap lag_cap; + struct crete_debugfs_entries dbg; + struct crete_lag *lag_dev; + struct crete_debugfs_statistics *debugfs_statis; + u16 sfi_id; + u16 lag_enable; +}; + + + +enum crete_feature_type { + CRETE_FEATURE_NETDEV, + CRETE_FEATURE_OFFLOAD +}; + +static inline unsigned int crete_rd32(struct crete_core_dev *p, u32 reg) +{ + u8 __iomem *ioaddr = READ_ONCE(p->io_addr); + u32 value = 0; + + value = readl(&ioaddr[reg]); + + return value; +} + +static inline void crete_ioread32(void __iomem *addr, void *buffer, + unsigned int count) +{ + int i = 0; + u32 *buf = buffer; + u8 __iomem *address = addr; + + if (count) { + for (i = 0; i < count; i++) + readsl(address + i * 4, buf++, 1); + } +} + +static inline void crete_iowrite32(void __iomem *addr, void *buffer, + unsigned int count) +{ + int i = 0; + u32 *buf = buffer; + u8 __iomem *address = addr; + + if (count) { + for (i = 0; i < count; i++) + writesl(address + i * 4, buf++, 1); + } +} + +static inline struct device *crete_hw_to_dev(struct crete_hw *hw) +{ + struct crete_core_dev *core_dev = container_of(hw, struct crete_core_dev, hw); + + return &core_dev->pdev->dev; +} +int crete_adev_idx_alloc(void); +void crete_adev_idx_free(int idx); +static inline bool crete_sriov_is_enabled(struct crete_core_dev *dev) +{ + return pci_num_vf(dev->pdev) ? true : false; +} + +static inline bool crete_core_is_pf(const struct crete_core_dev *dev) +{ + return dev->coredev_type == CRETE_COREDEV_PF; +} + +static inline bool crete_core_is_vf(const struct crete_core_dev *dev) +{ + return dev->coredev_type == CRETE_COREDEV_VF; +} + +static inline bool crete_have_rdma_cap(const struct crete_core_dev *dev) +{ + return dev->hw.rdma_desc.cap_type == CRETE_RDMA_CONF_CAP; +} + +static inline bool crete_have_net_cap(const struct crete_core_dev *dev) +{ + return dev->hw.jnd.type == CRETE_NET_CONF_CAP; +} + +static inline u16 fw_ver_maj(struct crete_core_dev *dev) +{ + struct crete_hw *hw = &dev->hw; + + return readw(&hw->io_addr->fw_ver_major); +} + +static inline u16 fw_ver_min(struct crete_core_dev *dev) +{ + struct crete_hw *hw = &dev->hw; + + return readw(&hw->io_addr->fw_ver_minor); +} + +static inline u16 fw_ver_sub(struct crete_core_dev *dev) +{ + struct crete_hw *hw = &dev->hw; + + return readw(&hw->io_addr->cmd_interface_rev); +} + +static inline u16 fw_ver_rev(struct crete_core_dev *dev) +{ + struct crete_hw *hw = &dev->hw; + + return readw(&hw->io_addr->fw_revision); +} + +int crete_req_msixirq(struct crete_core_dev *core_dev); +void crete_free_msixirq(struct crete_core_dev *core_dev, int irq); + +static inline bool __crete_test_bit(const u64 features, unsigned int fbit) +{ + /* Did you forget to fix assumptions on max features? */ + if (__builtin_constant_p(fbit)) + BUILD_BUG_ON(fbit >= 64); + else + WARN_ON_ONCE(fbit >= 64); + + return features & BIT_ULL(fbit); +} + +static inline bool crete_has_feature(const struct crete_core_dev *cdev, + enum crete_feature_type feature_type, unsigned int fbit) +{ + if (feature_type == CRETE_FEATURE_NETDEV) + return __crete_test_bit(cdev->netdev_features, fbit); + else + return __crete_test_bit(cdev->offload_features, fbit); +} + +/* NEED_ETH_HW_ADDR_SET + * + * eth_hw_addr_set was added by upstream commit + * 48eab831ae8b ("net: create netdev->dev_addr assignment helpers") + * + * Using eth_hw_addr_set became required in 5.17, when the dev_addr field in + * the netdev struct was constified. See 48eab831ae8b ("net: create + * netdev->dev_addr assignment helpers") + */ +#ifdef NEED_ETH_HW_ADDR_SET +static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr) +{ + ether_addr_copy(dev->dev_addr, addr); +} +#endif /* NEED_ETH_HW_ADDR_SET */ + +int crete_cmd_init(struct crete_core_dev *cdev); +int crete_event_init(struct crete_hw *hw); +void crete_cmd_exit(struct crete_core_dev *cdev); +void crete_event_exit(struct crete_hw *hw); +int crete_adev_init(struct crete_core_dev *core_dev); +void crete_adev_cleanup(struct crete_core_dev *core_dev); +int crete_rescan_drivers_locked(struct crete_core_dev *core_dev); +int crete_rescan_drivers(struct crete_core_dev *dev); +void crete_dev_list_lock(void); +void crete_dev_list_unlock(void); +int crete_dev_list_trylock(void); +void crete_sriov_disable(struct pci_dev *pdev); +int crete_register_device(struct crete_core_dev *core_dev); +void crete_unregister_device(struct crete_core_dev *core_dev); + +void crete_detach_device(struct crete_core_dev *core_dev); +int crete_attach_device(struct crete_core_dev *core_dev); +int crete_change_mac_addr(struct net_device *netdev, void *p); +void crete_set_rx_mode(struct net_device *dev); +void crete_init_msix(struct crete_core_dev *core_dev); +void crete_exit_irq(struct crete_core_dev *core_dev); +extern struct dentry *crete_debugfs_root; +void crete_register_debugfs(void); +void crete_unregister_debugfs(void); +struct dentry *crete_debugfs_get_dev_root(struct crete_core_dev *dev); +extern const struct net_device_ops crete_netdev_ops; +extern const struct ethtool_ops crete_ethtool_ops; +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_aux_dev.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_aux_dev.c new file mode 100644 index 0000000..38a86a9 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_aux_dev.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "crete.h" +#include "crete_rdma_dev.h" +#include "crete_devlink.h" +static DEFINE_MUTEX(crete_intf_mutex); +static DEFINE_IDA(crete_adev_ida); + + + + +enum { + CRETE_INTERFACE_PROTOCOL_ETH, + CRETE_INTERFACE_PROTOCOL_ETH_REP, + + CRETE_INTERFACE_PROTOCOL_IB, + CRETE_INTERFACE_PROTOCOL_IB_REP, + CRETE_INTERFACE_PROTOCOL_VNET, + CRETE_INTERFACE_PROTOCOL_VNIC, + CRETE_INTERFACE_PROTOCOL_MAX +}; + +static const struct crete_adev_device { + const char *suffix; + bool (*is_supported)(struct crete_core_dev *core_dev); + bool (*is_enabled)(struct crete_core_dev *core_dev); +} crete_adev_devices[] = { + [CRETE_INTERFACE_PROTOCOL_ETH] = { .suffix = "eth", + .is_supported = &crete_eth_supported, + .is_enabled = &crete_eth_enabled }, + [CRETE_INTERFACE_PROTOCOL_ETH_REP] = { .suffix = "eth-rep", + .is_supported = &crete_eth_rep_supported, + .is_enabled = &crete_eth_rep_enabled }, +/* + * [CRETE_INTERFACE_PROTOCOL_IB] = { .suffix = "rdma", + * .is_supported = &crete_rdma_supported, + * .is_enabled = &crete_rdma_enabled }, + * [CRETE_INTERFACE_PROTOCOL_IB_REP] = { .suffix = "rdma-rep", + * .is_supported = &crete_rdma_rep_supported, + * .is_enabled = &crete_rdma_rep_enabled }, + */ + [CRETE_INTERFACE_PROTOCOL_VNET] = { .suffix = "vnet", + .is_supported = &crete_vnet_supported, + .is_enabled = &crete_vnet_enabled }, + [CRETE_INTERFACE_PROTOCOL_VNIC] = { .suffix = "nic", + .is_supported = &crete_nic_supported, + .is_enabled = &crete_nic_enabled }, +}; + +int crete_adev_idx_alloc(void) +{ + return ida_alloc(&crete_adev_ida, GFP_KERNEL); +} + +void crete_adev_idx_free(int idx) +{ + ida_free(&crete_adev_ida, idx); +} + + +int crete_adev_init(struct crete_core_dev *core_dev) +{ + struct crete_aux_dev **adev; + + adev = kcalloc(ARRAY_SIZE(crete_adev_devices), + sizeof(struct crete_aux_dev *), GFP_KERNEL | GFP_ATOMIC); + if (!adev) + return -ENOMEM; + + core_dev->adev = adev; + + return 0; +} + +void crete_adev_cleanup(struct crete_core_dev *core_dev) +{ + struct crete_aux_dev **adev = core_dev->adev; + + kfree(adev); +} + +static void crete_adev_release(struct device *dev) +{ + struct crete_aux_dev *crete_adev = + container_of(dev, struct crete_aux_dev, adev.dev); + int idx = crete_adev->idx; + struct crete_core_dev *core_dev = crete_adev->core_dev; + + kfree(crete_adev); + core_dev->adev[idx] = NULL; +} + +static struct crete_aux_dev *add_adev(struct crete_core_dev *core_dev, + int idx) +{ + const char *suffix = crete_adev_devices[idx].suffix; + struct auxiliary_device *adev; + struct crete_aux_dev *madev; + int ret; + + madev = kzalloc(sizeof(*madev), GFP_KERNEL); + if (!madev) + return ERR_PTR(-ENOMEM); + + adev = &madev->adev; + adev->id = core_dev->adev_idx; + adev->name = suffix; + adev->dev.parent = &core_dev->pdev->dev; + adev->dev.release = crete_adev_release; + madev->core_dev = core_dev; + madev->idx = idx; + + ret = auxiliary_device_init(adev); + if (ret) { + kfree(madev); + return ERR_PTR(ret); + } + + ret = auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ERR_PTR(ret); + } + return madev; +} + +static void del_adev(struct auxiliary_device *adev) +{ + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +int crete_attach_device(struct crete_core_dev *core_dev) +{ + struct crete_aux_dev **crete_adev = core_dev->adev; + struct auxiliary_device *adev; + struct auxiliary_driver *adrv; + int ret = 0, i; + + mutex_lock(&crete_intf_mutex); + + for (i = 0; i < ARRAY_SIZE(crete_adev_devices); i++) { + if (!crete_adev[i]) { + bool is_supported = false; + + if (crete_adev_devices[i].is_enabled) { + bool enabled; + + enabled = crete_adev_devices[i].is_enabled(core_dev); + if (!enabled) + continue; + } + + if (crete_adev_devices[i].is_supported) + is_supported = crete_adev_devices[i].is_supported(core_dev); + + if (!is_supported) + continue; + + crete_adev[i] = add_adev(core_dev, i); + if (IS_ERR(crete_adev[i])) { + ret = PTR_ERR(crete_adev[i]); + crete_adev[i] = NULL; + } + } else { + adev = &crete_adev[i]->adev; + + if (!adev->dev.driver) + continue; + adrv = to_auxiliary_drv(adev->dev.driver); + + if (adrv->resume) + ret = adrv->resume(adev); + } + if (ret) { + WARN_ONCE(1, "Device[%d] (%s) failed to load\n", + i, crete_adev_devices[i].suffix); + + break; + } + } + mutex_unlock(&crete_intf_mutex); + return ret; +} + +void crete_detach_device(struct crete_core_dev *core_dev) +{ + struct crete_aux_dev **crete_adev = core_dev->adev; + struct auxiliary_device *adev; + struct auxiliary_driver *adrv; + pm_message_t pm = {}; + int i; + + if (!crete_adev) + pr_err("crete adev null\n"); + + mutex_lock(&crete_intf_mutex); + for (i = ARRAY_SIZE(crete_adev_devices) - 1; i >= 0; i--) { + if (!crete_adev[i]) + continue; + + if (crete_adev_devices[i].is_enabled) { + bool enabled; + + enabled = crete_adev_devices[i].is_enabled(core_dev); + if (!enabled) + goto skip_suspend; + } + + adev = &crete_adev[i]->adev; + /* Auxiliary driver was unbind manually through sysfs */ + if (!adev->dev.driver) + goto skip_suspend; + + adrv = to_auxiliary_drv(adev->dev.driver); + + if (adrv->suspend) { + adrv->suspend(adev, pm); + continue; + } + +skip_suspend: + del_adev(&crete_adev[i]->adev); + crete_adev[i] = NULL; + } + + mutex_unlock(&crete_intf_mutex); +} + +int crete_register_device(struct crete_core_dev *core_dev) +{ + int ret; + + mutex_lock(&crete_intf_mutex); + core_dev->flags &= ~CRETE_FLAG_DISABLE_ALL_ADEV; + ret = crete_rescan_drivers_locked(core_dev); + if (crete_have_rdma_cap(core_dev)) + ret |= jm_rescan_drivers_locked(&core_dev->rdma_coredev); + mutex_unlock(&crete_intf_mutex); + if (ret) + crete_unregister_device(core_dev); + + return ret; +} + +void crete_unregister_device(struct crete_core_dev *core_dev) +{ + mutex_lock(&crete_intf_mutex); + core_dev->flags |= CRETE_FLAG_DISABLE_ALL_ADEV; + if (crete_have_rdma_cap(core_dev)) + jm_rescan_drivers_locked(&core_dev->rdma_coredev); + crete_rescan_drivers_locked(core_dev); + mutex_unlock(&crete_intf_mutex); +} + + + +static int add_drivers(struct crete_core_dev *core_dev) +{ + int i, ret = 0; + struct crete_aux_dev **crete_adev = core_dev->adev; + + for (i = 0; i < ARRAY_SIZE(crete_adev_devices); i++) { + bool is_supported = false; + + if (crete_adev[i]) + continue; + + if (crete_adev_devices[i].is_supported) + is_supported = crete_adev_devices[i].is_supported(core_dev); + + if (!is_supported) + continue; + + crete_adev[i] = add_adev(core_dev, i); + if (IS_ERR(crete_adev[i])) { + WARN_ONCE(1, "Device[%d] (%s) failed to load\n", + i, crete_adev_devices[i].suffix); + /* We continue to rescan drivers and leave to the caller + * to make decision if to release everything or continue. + */ + ret = PTR_ERR(crete_adev[i]); + crete_adev[i] = NULL; + } + } + return ret; +} + +static void delete_drivers(struct crete_core_dev *core_dev) +{ + struct crete_aux_dev **crete_adev = core_dev->adev; + bool delete_all; + int i; + + delete_all = core_dev->flags & CRETE_FLAG_DISABLE_ALL_ADEV; + for (i = ARRAY_SIZE(crete_adev_devices) - 1; i >= 0; i--) { + bool is_supported = false; + + if (!crete_adev[i]) + continue; + + if (crete_adev_devices[i].is_enabled) { + bool enabled; + + enabled = crete_adev_devices[i].is_enabled(core_dev); + if (!enabled) + goto del_adev; + } + + if (crete_adev_devices[i].is_supported && !delete_all) + is_supported = crete_adev_devices[i].is_supported(core_dev); + + if (is_supported) + continue; + +del_adev: + del_adev(&crete_adev[i]->adev); + crete_adev[i] = NULL; + } +} + + +int crete_rescan_drivers_locked(struct crete_core_dev *core_dev) +{ + int err = 0; + + delete_drivers(core_dev); + if (core_dev->flags & CRETE_FLAG_DISABLE_ALL_ADEV) + return 0; + + err = add_drivers(core_dev); + return err; +} +void crete_dev_list_lock(void) +{ + mutex_lock(&crete_intf_mutex); +} +void crete_dev_list_unlock(void) +{ + mutex_unlock(&crete_intf_mutex); +} + +int crete_dev_list_trylock(void) +{ + return mutex_trylock(&crete_intf_mutex); +} + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd.c new file mode 100644 index 0000000..6e0fd6d --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd.c @@ -0,0 +1,1106 @@ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include "crete.h" +#include "crete_cmd.h" +#include "crete_regs.h" +#include "crete_txrx.h" +#include "crete_event.h" +bool adminq_enable = false; +module_param(adminq_enable, bool, 0444); +MODULE_PARM_DESC(adminq_enable, "use adminq commands for crtl_path"); + +static int cmd_timeout = 60; +module_param(cmd_timeout, int, 0444); +MODULE_PARM_DESC(adminq_enable, "adminq cmd wait imu reply max timeout(s)"); + +unsigned int crete_cmd_debug_sw = 0; +module_param_named(debug_sw, crete_cmd_debug_sw, uint, 0644); +MODULE_PARM_DESC(debug_sw, "debug switch: 1 = dump cmd data, Default=0"); + +static void crete_cmd_comp_handler(struct crete_core_dev *dev, u64 vec, bool forced); + +struct crete_cmd_mbox_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_mbox_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; +}; + +static u16 in_to_cmdid(void *in) +{ + return CRETE_GET16(mbox_in, in, cmd_id); +} + +static struct crete_cmd_entry *get_cmd_inst(struct crete_cmd *cmd, int idx) +{ + return cmd->cmd_buf + (idx << cmd->cmd_stride); +} + +bool crete_cmd_is_down(struct crete_core_dev *cdev) +{ + return pci_channel_offline(cdev->pdev); +} + +static void crete_print_initseg(struct crete_hw *hw) +{ + struct crete_init_seg *seg = hw->io_addr; + struct device *dev = crete_hw_to_dev(hw); + + crete_info(dev, "\t\tminor ver 0x%x\n", readw(&seg->fw_ver_minor)); + crete_info(dev, "\t\tmajor ver 0x%x\n", readw(&seg->fw_ver_major)); + crete_info(dev, "\t\trever 0x%x\n", readw(&seg->fw_revision)); + crete_info(dev, "\t\tcmd interface rev 0x%x\n", readw(&seg->cmd_interface_rev)); + crete_info(dev, "\t\tdev cp_status 0x%x\n", readb(&seg->cp_status)); + crete_info(dev, "\t\tdev cp_caps 0x%x\n", readb(&seg->cp_caps)); + crete_info(dev, "\t\tdev status 0x%x\n", readb(&seg->dev_status)); + crete_info(dev, "\t\treset dev 0x%x\n", readb(&seg->reset_dev)); + crete_info(dev, "\t\tcmd_path_db 0x%x\n", readb(&seg->cmd_path_db)); +} + +static void set_wqname(struct crete_core_dev *cdev) +{ + struct crete_cmd *cmd = &cdev->cmd; + + snprintf(cmd->wq_name, sizeof(cmd->wq_name), "crete_cmd_%s", + dev_name(cdev->device)); +} + +static struct crete_cmd_work_ent * +cmd_alloc_ent(struct crete_cmd *cmd, struct crete_cmd_msg *inb, + struct crete_cmd_msg *outb, void *uout, int uout_size, u16 cmd_id) +{ + gfp_t alloc_flags = GFP_KERNEL; + struct crete_cmd_work_ent *ent; + + ent = kzalloc(sizeof(*ent), alloc_flags); + if (!ent) + return ERR_PTR(-ENOMEM); + + ent->idx = -EINVAL; + ent->inb = inb; + ent->outb = outb; + ent->out = uout; + ent->out_size = uout_size; + ent->cmd = cmd; + ent->cmd_id = cmd_id; + refcount_set(&ent->refcnt, 1); + + return ent; +} + +static void cmd_free_ent(struct crete_cmd_work_ent *ent) +{ + kfree(ent); +} + +static int cmd_alloc_index(struct crete_cmd *cmd) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&cmd->alloc_lock, flags); + ret = find_first_bit(&cmd->bitmask, cmd->max_cmds); + if (ret < cmd->max_cmds) + clear_bit(ret, &cmd->bitmask); + spin_unlock_irqrestore(&cmd->alloc_lock, flags); + + return ret < cmd->max_cmds ? ret : -ENOMEM; +} + +static void cmd_free_index(struct crete_cmd *cmd, int idx) +{ + lockdep_assert_held(&cmd->alloc_lock); + set_bit(idx, &cmd->bitmask); +} + +static void cmd_ent_get(struct crete_cmd_work_ent *ent) +{ + refcount_inc(&ent->refcnt); +} + +static void cmd_ent_put(struct crete_cmd_work_ent *ent) +{ + struct crete_cmd *cmd = ent->cmd; + unsigned long flags; + + spin_lock_irqsave(&cmd->alloc_lock, flags); + if (!refcount_dec_and_test(&ent->refcnt)) + goto out; + + if (ent->idx >= 0) { + cmd_free_index(cmd, ent->idx); + up(&cmd->sem); + } + + cmd_free_ent(ent); +out: + spin_unlock_irqrestore(&cmd->alloc_lock, flags); +} + +static int deliv_status_to_err(u8 status) +{ + switch (status) { + case CRETE_CMD_DELIVERY_STAT_OK: + return 0; + default: + return -EINVAL; + } +} + +static const char *deliv_status_to_str(u8 status) +{ + switch (status) { + case CRETE_CMD_DELIVERY_STAT_OK: + return "Delivery Success"; + case CRETE_CMD_DELIVERY_STAT_SIGNAT_ERR: + return "Signature verification error on the device side"; + case CRETE_CMD_DELIVERY_STAT_CID_ERR: + return "CID mismatch in command data BD"; + case CRETE_CMD_DELIVERY_STAT_DATA_FORMAT_ERR: + return "Format error in command data BD"; + case CRETE_CMD_DELIVERY_STAT_OUT_INSUFFICIENT_ERR: + return "Insufficient output buffer size"; + case CRETE_CMD_DELIVERY_STAT_OWNER_ERR: + return "Event notify completed,the entry's owner bit not set to 0"; + default: + return "unknown status code"; + } +} + +const char *crete_command_str(int command) +{ + switch (command) { + CRETE_COMMAND_STR_CASE(GET_STATUS); + CRETE_COMMAND_STR_CASE(SET_STATUS); + CRETE_COMMAND_STR_CASE(GET_FEAT); + CRETE_COMMAND_STR_CASE(SET_FEAT); + CRETE_COMMAND_STR_CASE(GET_DEV_TYPE); + CRETE_COMMAND_STR_CASE(SET_DEV_TYPE); + CRETE_COMMAND_STR_CASE(RESET_DEV); + CRETE_COMMAND_STR_CASE(STOP_DEV); + CRETE_COMMAND_STR_CASE(RESTORE_DEV); + CRETE_COMMAND_STR_CASE(GET_QP_CAP); + CRETE_COMMAND_STR_CASE(CREATE_QP); + CRETE_COMMAND_STR_CASE(DESTORY_QP); + CRETE_COMMAND_STR_CASE(CREATE_QUEUE); + CRETE_COMMAND_STR_CASE(DESTROY_QUEUE); + CRETE_COMMAND_STR_CASE(ENABLE_QUEUE); + CRETE_COMMAND_STR_CASE(DISABLE_QUEUE); + CRETE_COMMAND_STR_CASE(RESET_QUEUE); + CRETE_COMMAND_STR_CASE(GET_Q_STATE); + + CRETE_COMMAND_STR_CASE(SET_VPORT_RX_MODE); + CRETE_COMMAND_STR_CASE(GET_VORT_RX_MODE); + CRETE_COMMAND_STR_CASE(SET_VPORT_LINK_STATE); + CRETE_COMMAND_STR_CASE(GET_VPORT_LINK_STATE); + CRETE_COMMAND_STR_CASE(SET_TCP_LRO); + CRETE_COMMAND_STR_CASE(GET_TCP_LRO); + CRETE_COMMAND_STR_CASE(SET_RX_RSS); + CRETE_COMMAND_STR_CASE(GET_RX_RSS); + CRETE_COMMAND_STR_CASE(SET_RX_TIMESTAMP); + CRETE_COMMAND_STR_CASE(GET_RX_TIMESTAMP); + CRETE_COMMAND_STR_CASE(SET_TRUST); + CRETE_COMMAND_STR_CASE(GET_TRUST); + CRETE_COMMAND_STR_CASE(SET_UC_MAC); + CRETE_COMMAND_STR_CASE(SET_VF_SHAPER); + + CRETE_COMMAND_STR_CASE(SET_PORT_TRUST_STATUS); + CRETE_COMMAND_STR_CASE(SET_PCP_MAP_TC); + CRETE_COMMAND_STR_CASE(SET_DSCP_MAP_TC); + CRETE_COMMAND_STR_CASE(SET_FC_ENABLE); + CRETE_COMMAND_STR_CASE(SET_FC_TIMEOUT); + CRETE_COMMAND_STR_CASE(SET_PFC_ENABLE); + CRETE_COMMAND_STR_CASE(SET_ETS); + CRETE_COMMAND_STR_CASE(GET_PORT_SPEED_DUPLEX_MODE); + CRETE_COMMAND_STR_CASE(SET_PORT_SPEED_DUPLEX_MODE); + CRETE_COMMAND_STR_CASE(GET_PORT_FEC_MODE); + CRETE_COMMAND_STR_CASE(SET_PORT_FEC_MODE); + + CRETE_COMMAND_STR_CASE(SET_SOP_PADDING); + CRETE_COMMAND_STR_CASE(GET_SOP_PADDING); + CRETE_COMMAND_STR_CASE(SET_AUTO_SUPPRESS); + CRETE_COMMAND_STR_CASE(GET_AUTO_SUPPRESS); + CRETE_COMMAND_STR_CASE(SET_MODERATION_TEMP); + CRETE_COMMAND_STR_CASE(GET_MODERATION_TEMP); + CRETE_COMMAND_STR_CASE(SET_INT_MODERATION); + CRETE_COMMAND_STR_CASE(GET_INT_MODERATION); + CRETE_COMMAND_STR_CASE(SET_TX_INORDER); + CRETE_COMMAND_STR_CASE(GET_TX_INORDER); + CRETE_COMMAND_STR_CASE(SET_CQE_AGGREGATION_TEMP); + CRETE_COMMAND_STR_CASE(GET_CQE_AGGREGATION_TEMP); + CRETE_COMMAND_STR_CASE(SET_CQE_AGGREGATION); + CRETE_COMMAND_STR_CASE(GET_CQE_AGGREGATION); + CRETE_COMMAND_STR_CASE(SET_RX_MERGE); + CRETE_COMMAND_STR_CASE(GET_RX_MERGE); + CRETE_COMMAND_STR_CASE(GET_VQ_MIG_STATE); + CRETE_COMMAND_STR_CASE(GET_VQ_MIG_STATE_BATCH); + CRETE_COMMAND_STR_CASE(SET_VQ_MIG_STATE); + CRETE_COMMAND_STR_CASE(SET_MIG_LOG_BASE); + CRETE_COMMAND_STR_CASE(SET_MIG_LOG_STATE); + CRETE_COMMAND_STR_CASE(FWU_LOCK); + CRETE_COMMAND_STR_CASE(FWU_UNLOCK); + CRETE_COMMAND_STR_CASE(FWU_PKEY); + CRETE_COMMAND_STR_CASE(FWU_VER); + CRETE_COMMAND_STR_CASE(FWU_XFER); + CRETE_COMMAND_STR_CASE(FWU_END); + CRETE_COMMAND_STR_CASE(GET_VF_MAC); + default: return "unknown command cmd_id"; + } +} + +static void dump_data(void *data, int size) +{ + uint32_t *p = data; + int i; + int offset = 0; + + for (i = 0; i < size; i += 16) { + pr_info("block data: %03x: %08x %08x %08x %08x\n", + offset, p[0], p[1], p[2], p[3]); + p += 4; + offset += 16; + } + pr_info("\n"); +} + +static void dump_block(struct crete_cmd_msg *cmd_msg) +{ + struct crete_cmd_mailbox *head = cmd_msg->next; + struct crete_cmd_prot_block *block; + + while (head) { + block = head->buf; + pr_info("\t\tblock_num 0x%x\n", block->block_num); + pr_info("\t\tsig 0x%x\n", block->sig); + pr_info("\t\tcid 0x%x\n", block->cid); + pr_info("\t\tcmd_data_len 0x%x\n", block->cmd_data_len); + pr_info("\t\tnext 0x%llx\n", block->next); + pr_info("\t\tnext_len %d\n", block->next_len); + dump_data((char *)block->cmd_data, block->cmd_data_len << 2); + head = head->next; + } +} + +static void dump_buf(void *buf, int size, int offset, int idx) +{ + uint32_t *p = buf; + int i; + + for (i = 0; i < size; i += 16) { + pr_info("cmd[%d]: %03x: %08x %08x %08x %08x\n", + idx, offset, p[0], p[1], p[2], p[3]); + p += 4; + offset += 16; + } + pr_info("\n"); +} + +static void dump_command(struct crete_core_dev *cdev, + struct crete_cmd_work_ent *ent, int input) +{ + struct crete_cmd_msg *dump_msg = input ? ent->inb : ent->outb; + + u16 cmd_id = ent->cmd_id; + u32 offset = 0; + + if (!crete_cmd_debug_sw) + return; + + crete_info(cdev->device, "cmd[%d]: start dump\n", ent->idx); + + crete_info(cdev->device, "cmd[%d]: dump command %s(0x%x) %s\n", + ent->idx, crete_command_str(cmd_id), cmd_id, + input ? "INPUT" : "OUTPUT"); + dump_buf(ent->lay, sizeof(struct crete_cmd_entry), offset, ent->idx); + if (dump_msg->msg_mode) + return; + + pr_info("cmd[%d] dump block data:\n", ent->idx); + dump_block(dump_msg); + crete_info(cdev->device, "cmd[%d]: end dump\n", ent->idx); +} + +static struct crete_cmd_mailbox *alloc_cmd_box(struct crete_core_dev *cdev, + gfp_t flags) +{ + struct crete_cmd_mailbox *mailbox; + + mailbox = kmalloc(sizeof(*mailbox), flags); + if (!mailbox) + return ERR_PTR(-ENOMEM); + + mailbox->buf = dma_pool_zalloc(cdev->cmd.pool, flags, + &mailbox->dma); + if (!mailbox->buf) { + crete_err(cdev->device, "failed allocation\n"); + kfree(mailbox); + return ERR_PTR(-ENOMEM); + } + mailbox->next = NULL; + + return mailbox; +} + +static void free_cmd_box(struct crete_core_dev *cdev, + struct crete_cmd_mailbox *mailbox) +{ + dma_pool_free(cdev->cmd.pool, mailbox->buf, mailbox->dma); + kfree(mailbox); +} + +static void crete_free_cmd_msg(struct crete_core_dev *dev, + struct crete_cmd_msg *msg) +{ + struct crete_cmd_mailbox *head = msg->next; + struct crete_cmd_mailbox *next; + + if (msg->msg_mode) { + kfree(msg); + return; + } + + while (head) { + next = head->next; + free_cmd_box(dev, head); + head = next; + } + kfree(msg); +} + +static struct crete_cmd_msg *crete_alloc_cmd_msg(struct crete_core_dev *cdev, int size, + gfp_t gfp) +{ + struct crete_cmd_mailbox *tmp, *head = NULL; + struct crete_cmd_prot_block *block; + struct crete_cmd_msg *msg; + u32 msg_mode; + int err; + int n; + int i; + + msg = kzalloc(sizeof(*msg), gfp); + if (!msg) + return ERR_PTR(-ENOMEM); + + msg_mode = (size <= CRETE_CMD_INLINE_LEN) ? 1 : 0; + msg->len = size; + if (msg_mode) { + msg->msg_mode = 1; + return msg; + } + + n = DIV_ROUND_UP(size, CRETE_CMD_DATA_BLOCK_SIZE); + crete_info(cdev->device, "ori_data size [%d]need [%d] block size\n", size, n); + + for (i = 0; i < n; i++) { + tmp = alloc_cmd_box(cdev, gfp); + if (IS_ERR(tmp)) { + crete_warn(cdev->device, "failed allocating block\n"); + err = PTR_ERR(tmp); + goto err_alloc; + } + + block = tmp->buf; + tmp->next = head; + block->next = tmp->next ? tmp->next->dma : 0; + block->block_num = n - i - 1; + block->next_len = CRETE_GET_CMD_BD_LEN(size); + if (block->block_num == n-1) { + block->next_len = 0; + block->cmd_data_len = (size - (n - 1) * CRETE_CMD_DATA_BLOCK_SIZE) >> 2; + } else { + block->next_len = + CRETE_GET_CMD_BD_LEN(size - (n - i) * CRETE_CMD_DATA_BLOCK_SIZE); + block->cmd_data_len = CRETE_CMD_DATA_BLOCK_SIZE >> 2; + } + + head = tmp; + } + msg->next = head; + return msg; + +err_alloc: + while (head) { + tmp = head->next; + free_cmd_box(cdev, head); + head = tmp; + } + kfree(msg); + return ERR_PTR(err); +} + +static int crete_copy_from_msg(void *to, struct crete_cmd_msg *from, int size) +{ + struct crete_cmd_prot_block *block; + struct crete_cmd_mailbox *next; + int copy; + + if (!to || !from) + return -ENOMEM; + + if (from->msg_mode) { + memcpy(to, &from->inline_data, size); + return 0; + } + + next = from->next; + while (size) { + if (!next) { + /* this is a BUG */ + return -ENOMEM; + } + copy = min_t(int, size, CRETE_CMD_DATA_BLOCK_SIZE); + block = next->buf; + memcpy(to, block->cmd_data, copy); + + to += copy; + size -= copy; + next = next->next; + } + + return 0; +} + +static int crete_copy_to_msg(struct crete_cmd_msg *to, void *from, int size) +{ + struct crete_cmd_prot_block *block; + struct crete_cmd_mailbox *next; + int copy; + + if (!to || !from) + return -ENOMEM; + + if (to->msg_mode) { + memcpy(&to->inline_data, from, size); + return 0; + } + + next = to->next; + while (size) { + if (!next) { + return -ENOMEM; + } + copy = min_t(int, size, CRETE_CMD_DATA_BLOCK_SIZE); + block = next->buf; + memcpy(block->cmd_data, from, copy); + //block->cmd_data_len = copy >> 2; + from += copy; + size -= copy; + next = next->next; + } + return 0; +} + +int crete_cmd_check(struct crete_core_dev *dev, int err, void *in, void *out) +{ + return err; +} + +static int cmd_status_err(struct crete_core_dev *cdev, int err, u16 cmd_id, void *out) +{ + u32 err_type = CRETE_GET16(mbox_out, out, err_type); + u8 status = CRETE_GET16(mbox_out, out, status); + + crete_cmd_dbg(cdev, "cmd_out: cmd_id [0x%x] err_type[%d], status[%d]\n", + cmd_id, err_type, status); + if (err == -EREMOTEIO) + err = -EIO; + + if (!err && status != SUCCESS) + err = -EREMOTEIO; + + return err; +} + +static int cmd_comp_notifier(struct notifier_block *nb, + unsigned long type, void *data) +{ + struct crete_core_dev *cdev; + struct crete_hw *hw; + struct crete_cmd *cmd; + struct crete_event_entry *cee = data; + uint8_t event_sub_type = CRETE_EVENT_STYPE_ADMIN; + uint16_t entry_id; + uint32_t event_data; + + cmd = crete_nb_cof(nb, struct crete_cmd, nb); + cdev = container_of(cmd, struct crete_core_dev, cmd); + hw = &cdev->hw; + + switch (event_sub_type) { + case CRETE_EVENT_STYPE_CMDPATH: + crete_info(cdev->device, "CTRL PATH: Event with CMDPATH\n"); + //crete_cmd_comp_handler(cdev, 0, false); + break; + case CRETE_EVENT_STYPE_ADMIN: + crete_info(cdev->device, "CTRL PATH: Event with ADMIN\n"); +#ifndef CONFIG_NOSIM_DEBUG + crete_ioread32(&hw->io_addr->event_buffer[1], + &event_data, 1); + entry_id = (uint16_t)(event_data & 0xFFFF); +#else + entry_id = 0; +#endif + crete_cmd_comp_handler(cdev, entry_id, false); + break; + default: + crete_info(cdev->device, "CTRL PATH: Event with unrecognized subtype: event_sub_type %d\n", + cee->event_sub_type); + } + + return NOTIFY_OK; +} + +void crete_cmd_use_events(struct crete_core_dev *dev) +{ + CRETE_NB_INIT(&dev->cmd.nb, cmd_comp_notifier, CP); + crete_event_notifier_register(dev, &dev->cmd.nb); + //crete_cmd_change_mod(dev, CMD_MODE_EVENTS); +} + +void crete_cmd_use_polling(struct crete_core_dev *dev) +{ + //crete_cmd_change_mod(dev, CMD_MODE_POLLING); + crete_event_notifier_unregister(dev, &dev->cmd.nb); +} + +static void crete_cmd_comp_handler(struct crete_core_dev *cdev, u64 vec, bool forced) +{ + struct crete_cmd *cmd = &cdev->cmd; + struct crete_cmd_work_ent *ent; + int i; + unsigned long vector; + + /* there can be at most 32 command queues */ + vector = vec & 0xffffffff; + for (i = 0; i < CRETE_MAX_COMMANDS; i++) { + if (test_bit(i, &vector)) { + ent = cmd->ent_arr[i]; + + /* if we already completed the command, ignore it */ + if (!test_and_clear_bit(CRETE_CMD_ENT_STATE_PENDING_COMP, + &ent->state)) { + /* only real completion can free the cmd slot */ + if (!forced) { + crete_err(cdev->device, "Command completion arrived after timeout (entry idx = %d).\n", + ent->idx); + cmd_ent_put(ent); + } + continue; + } + + if (!forced || /* Real FW completion */ + crete_cmd_is_down(cdev)) /* No real FW completion is expected */ + cmd_ent_put(ent); + + ent->ts2 = ktime_get_ns(); + if (ent->outb->msg_mode) + memcpy(ent->outb->inline_data, ent->lay->inline_data, + sizeof(ent->outb->inline_data)); + + dump_command(cdev, ent, 0); + + if (vec & CRETE_TRIGGERED_CMD_COMP) + ent->ret = -ENXIO; + + if (!ent->ret) { /* Command completed by FW */ + ent->status = ent->lay->cmd_info.status; + crete_info(cdev->device, "command completed. ret 0x%x, delivery status %s(0x%x)\n", + ent->ret, deliv_status_to_str(ent->status), ent->status); + } + /* release wait_func() so crete_cmd_invoke() + * can make the final ent_put() + */ + complete(&ent->done); + } + } +} + +static void poll_timeout(struct crete_cmd_work_ent *ent) +{ + u64 cmd_to_ms = max(cmd_timeout * 1000, CRETE_TO_CMD_MS); + unsigned long poll_end; + u8 own; + + poll_end = jiffies + msecs_to_jiffies(cmd_to_ms + 1000); + + do { + own = READ_ONCE(ent->lay->cmd_info_data) & OWNER_MASK; + if (!(own & CMD_OWNER_HW)) { + ent->ret = 0; + return; + } + cond_resched(); + } while (time_before(jiffies, poll_end)); + + ent->ret = -ETIMEDOUT; +} + +enum { + CRETE_CMD_TIMEOUT_RECOVER_MSEC = 5 * 1000, +}; + +static void wait_func_handle_exec_timeout(struct crete_core_dev *cdev, + struct crete_cmd_work_ent *ent) +{ + unsigned long timeout = msecs_to_jiffies(CRETE_CMD_TIMEOUT_RECOVER_MSEC); + + //crete_cmd_recover(dev); + + + /* Re-wait on the ent->done after executing the recovery flow. If the + * recovery flow (or any other recovery flow running simultaneously) + * has recovered an EQE, it should cause the entry to be completed by + * the command interface. + */ + if (wait_for_completion_timeout(&ent->done, timeout)) { + crete_warn(cdev->device, "cmd[%d]: %s(0x%x) recovered after timeout\n", ent->idx, + crete_command_str(ent->cmd_id), ent->cmd_id); + return; + } + + crete_warn(cdev->device, "cmd[%d]: %s(0x%x) No done completion\n", ent->idx, + crete_command_str(ent->cmd_id), ent->cmd_id); + + ent->ret = -ETIMEDOUT; + crete_cmd_comp_handler(cdev, 1ULL << ent->idx, true); +} + + +static int wait_func(struct crete_core_dev *cdev, struct crete_cmd_work_ent *ent) +{ + unsigned long timeout = msecs_to_jiffies(CRETE_TO_CMD_MS); + struct crete_cmd *cmd = &cdev->cmd; + int err; + + if (!wait_for_completion_timeout(&ent->handling, timeout) && + cancel_work_sync(&ent->work)) { + ent->ret = -ECANCELED; + goto out_err; + } + if (cmd->poll_mode == CMD_MODE_POLLING || ent->polling) + wait_for_completion(&ent->done); + else if (!wait_for_completion_timeout(&ent->done, timeout)) + wait_func_handle_exec_timeout(cdev, ent); + +out_err: + err = ent->ret; + + if (err == -ETIMEDOUT) { + crete_warn(cdev->device, "%s(0x%x) timeout. Will cause a leak of a command resource\n", + crete_command_str(ent->cmd_id), ent->cmd_id); + } else if (err == -ECANCELED) { + crete_warn(cdev->device, "%s(0x%x) canceled on out of queue timeout.\n", + crete_command_str(ent->cmd_id), ent->cmd_id); + } + crete_info(cdev->device, "err %d, delivery status %s(%d)\n", + err, deliv_status_to_str(ent->status), ent->status); + + return err; +} + +static void cmd_work_handler(struct work_struct *work) +{ + struct crete_cmd_work_ent *ent = container_of(work, struct crete_cmd_work_ent, work); + struct crete_cmd *cmd = ent->cmd; + bool poll_cmd = ent->polling; + struct crete_cmd_entry *lay; + struct cmd_info cmd_info; + struct crete_core_dev *cdev; + struct semaphore *sem; + unsigned long flags; + int alloc_ret; + u8 poll_mode; + + cdev = container_of(cmd, struct crete_core_dev, cmd); + + complete(&ent->handling); + sem = &cmd->sem; + down(sem); + if (cmd->mode & CRETE_CP_ADQ) { + alloc_ret = cmd_alloc_index(cmd); + if (alloc_ret < 0) { + crete_err(cdev->device, "failed to allocate command entry\n"); + ent->ret = -EAGAIN; + complete(&ent->done); + up(sem); + return; + } + ent->idx = alloc_ret; + } else { + ent->idx = cmd->max_cmds - 1; + spin_lock_irqsave(&cmd->alloc_lock, flags); + clear_bit(ent->idx, &cmd->bitmask); + spin_unlock_irqrestore(&cmd->alloc_lock, flags); + } + + cmd->ent_arr[ent->idx] = ent; + lay = get_cmd_inst(cmd, ent->idx); + ent->lay = lay; + + memset(lay, 0, sizeof(*lay)); + memset(&cmd_info, 0, 4); + + /* in msg */ + if (ent->inb->msg_mode) { + lay->in_len = DIV_ROUND_UP(ent->inb->len, 4); + cmd_info.in_inline = 1; + memcpy(lay->inline_data, ent->inb->inline_data, sizeof(lay->inline_data)); + } else { + cmd_info.in_inline = 0; + lay->in_len = CRETE_GET_CMD_BD_LEN(ent->inb->len); + lay->in_ptr = ent->inb->next->dma; + } + /* out msg */ + if (ent->outb->msg_mode) { + cmd_info.out_inline = 1; + lay->out_len = DIV_ROUND_UP(ent->outb->len, 4); + } else { + cmd_info.out_inline = 0; + lay->out_len = CRETE_GET_CMD_BD_LEN(ent->outb->len); + lay->out_ptr = ent->outb->next->dma; + } + + cmd_info.event_notify = 0; + cmd_info.cmd_encap_type = 0; + cmd_info.owner = CMD_OWNER_HW; + lay->cmd_info_data = *(uint32_t *)&cmd_info; + + dump_command(cdev, ent, 1); + ent->ts1 = ktime_get_ns(); + poll_mode = cmd->poll_mode; + + set_bit(CRETE_CMD_ENT_STATE_PENDING_COMP, &ent->state); + + cmd_ent_get(ent); /* for the _real_ FW event on completion */ + /* Skip sending command to fw if internal error */ + if (crete_cmd_is_down(cdev)) { + ent->ret = -ENXIO; + crete_cmd_comp_handler(cdev, 1ULL << ent->idx, true); + return; + } + + /* ring doorbell after the descriptor is valid */ + crete_cmd_dbg(cdev, "writing 0x%x to command doorbell\n", + ((cmd->mode & CRETE_CP_CMDPATH) ? 1 : 1 << ent->idx)); +/* ring doorbell after the descriptor is valid */ + wmb(); + + if (cmd->mode & CRETE_CP_CMDPATH) { + iseg_wd32(&cdev->hw, struct crete_init_seg, + cmd_path_db, 1); + } else { + iseg_wd32(&cdev->hw, struct crete_init_seg, + aq_queue_db, (1 << ent->idx)); + } + + /* if not in polling don't use ent after this point */ + if (poll_mode == CMD_MODE_POLLING || poll_cmd) { + poll_timeout(ent); + /* make sure we read the descriptor after ownership is SW */ + rmb(); + crete_cmd_comp_handler(cdev, 1ULL << ent->idx, (ent->ret == -ETIMEDOUT)); + } +} + +static int crete_cmd_invoke(struct crete_core_dev *cdev, struct crete_cmd_msg *inb, + struct crete_cmd_msg *outb, void *out, int out_size, + bool force_polling, u16 cmd_id) +{ + struct crete_cmd *cmd = &cdev->cmd; + struct crete_cmd_work_ent *ent; + u8 status = 0; + int err = 0; + s64 ds; + + + ent = cmd_alloc_ent(cmd, inb, outb, out, out_size, cmd_id); + if (IS_ERR(ent)) + return PTR_ERR(ent); + + ent->polling = force_polling; + init_completion(&ent->handling); + init_completion(&ent->done); + INIT_WORK(&ent->work, cmd_work_handler); + + if (cmd->mode & CRETE_CP_CMDPATH) { + cmd_work_handler(&ent->work); + } else if (!queue_work(cmd->wq, &ent->work)) { + crete_warn(cdev->device, "failed to queue work\n"); + err = -EALREADY; + goto out_free; + } + + err = wait_func(cdev, ent); + if (err == -ETIMEDOUT || err == -ECANCELED) + goto out_free; + + ds = ent->ts2 - ent->ts1; + crete_info(cdev->device, "fw exec time for %s is %lld nsec\n", + crete_command_str(ent->cmd_id), ds); + +out_free: + status = ent->status; + cmd_ent_put(ent); + return err ? : status; +} + +static int cmd_exec(struct crete_core_dev *cdev, void *in, int in_size, void *out, + int out_size, bool force_polling) +{ + struct crete_cmd_msg *inb, *outb; + u16 cmd_id = in_to_cmdid(in); + gfp_t gfp = GFP_KERNEL; + int err; + + crete_cmd_dbg(cdev, "crete cmd exec cmd_id:[0x%x] in_size:[%d] out_size:[%d]", + cmd_id, in_size, out_size); + + if (crete_cmd_is_down(cdev)) + return -ENXIO; + + inb = crete_alloc_cmd_msg(cdev, in_size, gfp); + if (IS_ERR(inb)) { + err = PTR_ERR(inb); + goto out_up; + } + err = crete_copy_to_msg(inb, in, in_size); + if (err) { + crete_err(cdev->device, "copy to msg error"); + goto out_in; + } + + outb = crete_alloc_cmd_msg(cdev, out_size, gfp); + if (IS_ERR(inb)) { + err = PTR_ERR(inb); + goto out_in; + } + + err = crete_cmd_invoke(cdev, inb, outb, out, out_size, force_polling, cmd_id); + if (err > 0) /* Failed in FW, command didn't execute */ + err = deliv_status_to_err(err); + + if (err) + goto out_out; + + /* command completed by FW */ + err = crete_copy_from_msg(out, outb, out_size); +out_out: + crete_free_cmd_msg(cdev, outb); +out_in: + crete_free_cmd_msg(cdev, inb); +out_up: + return err; + +} + +int crete_cmd_exec_polling(struct crete_core_dev *dev, void *in, int in_size, + void *out, int out_size) +{ + int err = cmd_exec(dev, in, in_size, out, out_size, true); + u16 cmd_id = in_to_cmdid(in); + + err = cmd_status_err(dev, err, cmd_id, out); + + return err; +} +EXPORT_SYMBOL(crete_cmd_exec_polling); + +static int crete_adq_alloc_entry_buf(struct crete_core_dev *cdev, + struct crete_cmd *cmd) +{ + size_t size = cmd->max_cmds * sizeof(struct crete_cmd_entry); + struct crete_hw *hw = &cdev->hw; + + crete_info(cdev->device, "cmd->max_cmds:%d\n", cmd->max_cmds); + cmd->cmd_size = size; + + cmd->cmd_buf = dma_alloc_coherent(cdev->device, size, + &cmd->cmd_dma, GFP_KERNEL | __GFP_ZERO); + if (!cmd->cmd_buf) + return -ENOMEM; + + cmd->cmd_stride = ilog2(sizeof(struct crete_cmd_entry)); + + crete_info(cdev->device, "adq cmd_dma addr:0x%llx\n", cmd->cmd_dma); + +#ifndef CONFIG_NOSIM_DEBUG + iseg_wd32(hw, struct crete_init_seg, aq_base_addr_low, + (u32)(cmd->cmd_dma & 0xffffffff)); + + iseg_wd32(hw, struct crete_init_seg, + aq_base_addr_hi, (u32)(cmd->cmd_dma >> 32)); +#endif + /* Make sure firmware sees the complete address before we proceed */ + wmb(); + + return 0; +} + +static int crete_init_adq(struct crete_core_dev *cdev) +{ + struct crete_cmd *cmd = &cdev->cmd; + struct crete_hw *hw = &cdev->hw; + + cmd->max_cmds = readw(&hw->io_addr->aq_queue_size); + if (cmd->max_cmds > CRETE_MAX_COMMANDS) { + crete_err(cdev->device, "firmware reports too many outstanding commands %d\n", + cmd->max_cmds); + return -EINVAL; + } + cmd->mode = CRETE_CP_ADQ & 0xFF; + cmd->bitmask = (1UL << cmd->max_cmds) - 1; + sema_init(&cmd->sem, cmd->max_cmds); + + return crete_adq_alloc_entry_buf(cdev, cmd); +} + +static int crete_init_cmdpath(struct crete_core_dev *cdev) +{ + struct crete_cmd *cmd = &cdev->cmd; + struct crete_hw *hw = &cdev->hw; + + cmd->max_cmds = 1; + cmd->mode = CRETE_CP_CMDPATH & 0xFF; + cmd->bitmask = (1UL << cmd->max_cmds) - 1; + cmd->cmd_size = sizeof(struct crete_cmd_entry); + cmd->cmd_stride = 0; + sema_init(&cmd->sem, cmd->max_cmds); + cmd->cmd_buf = (struct crete_cmd_entry *)&(hw->io_addr->cmd_path_entry); + crete_info(cdev->device, "cmdpath cmd_buf addr:0x%llx\n", (u64)cmd->cmd_buf); + return 0; +} + +int crete_cmd_init(struct crete_core_dev *cdev) +{ + uint8_t val; + int err; + int size = sizeof(struct crete_cmd_prot_block) + CRETE_CMD_DATA_BLOCK_SIZE; + int align = roundup_pow_of_two(size); + struct crete_cmd *cmd = &cdev->cmd; + struct crete_hw *hw = &cdev->hw; + + memset(cmd, 0, sizeof(*cmd)); + crete_info(cdev->device, "crete_cmd block size[%d], aligh[%d]\n", size, align); + cmd->pool = dma_pool_create("crete_cmd", cdev->device, size, align, 0); + if (!cmd->pool) + return -ENOMEM; + + crete_print_initseg(hw); + val = readb(&hw->io_addr->cp_caps); + if (!(val & (CRETE_CP_CMDPATH | CRETE_CP_ADQ))) { + crete_err(cdev->device, "cmd path is null\n"); + + val = CRETE_DEV_FAIL; + writeb(val, &hw->io_addr->dev_status); + + err = -EINVAL; + goto err_free_pool; + } + + if ((adminq_enable || (crete_core_is_pf(cdev))) && + (val & CRETE_CP_ADQ)) { + err = crete_init_adq(cdev); + if (err < 0) { + if (val & CRETE_CP_CMDPATH) { + err = crete_init_cmdpath(cdev); + if (err < 0) + goto err_free_pool; + POLL_CTRL_PATH_STATUS(hw, CRETE_CP_CMDPATH, cdev, err); + } else + goto err_free_pool; + } + POLL_CTRL_PATH_STATUS(hw, CRETE_CP_ADQ, cdev, err); + } else if (val & CRETE_CP_CMDPATH) { + err = crete_init_cmdpath(cdev); + if (err < 0) { + if (val & CRETE_CP_ADQ) { + err = crete_init_adq(cdev); + if (err < 0) + goto err_free_pool; + POLL_CTRL_PATH_STATUS(hw, CRETE_CP_ADQ, cdev, err); + } else + goto err_free_pool; + } + POLL_CTRL_PATH_STATUS(hw, CRETE_CP_CMDPATH, cdev, err); + } + + if (err == -EBUSY) + goto err_exit_adq; + + val = readb(&hw->io_addr->dev_status); + val |= CRETE_DEV_CP; + writeb(val, &hw->io_addr->dev_status); + + set_wqname(cdev); + cmd->wq = create_singlethread_workqueue(cmd->wq_name); + if (!cmd->wq) { + crete_err(cdev->device, "failed to create command workqueue\n"); + err = -ENOMEM; + goto err_exit_adq; + } + cmd->poll_mode = CMD_MODE_POLLING; + if (cdev->event_irq) + crete_cmd_use_events(cdev); + return 0; + +err_exit_adq: + if (cmd->mode & CRETE_CP_ADQ) + dma_free_coherent(cdev->device, cdev->cmd.cmd_size, + cdev->cmd.cmd_buf, cdev->cmd.cmd_dma); + +err_free_pool: + dma_pool_destroy(cmd->pool); + return err; + +} + +void crete_cmd_exit(struct crete_core_dev *cdev) +{ + destroy_workqueue(cdev->cmd.wq); + if (cdev->cmd.mode & CRETE_CP_ADQ) { + dma_free_coherent(cdev->device, cdev->cmd.cmd_size, + cdev->cmd.cmd_buf, cdev->cmd.cmd_dma); + cdev->cmd.cmd_buf = NULL; + cdev->cmd.cmd_dma = 0; + cdev->cmd.cmd_size = 0; + } + + dma_pool_destroy(cdev->cmd.pool); + cdev->cmd.pool = NULL; +} + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd.h new file mode 100644 index 0000000..b928a7d --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd.h @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CRETE_CMD_H +#define _CRETE_CMD_H + +#include "crete.h" +#include +#include + +extern uint crete_cmd_debug_sw; + +#define CRETE_CMD_INLINE_LEN 36 +#define CRETE_CMD_TRY_NUM 60 +#define CRETE_TO_CMD_MS 60000 +#define OWNER_MASK 0x1 +#define CRETE_GET_CMD_BD_LEN(len) \ + (((len) > CRETE_CMD_DATA_BLOCK_SIZE) ? \ + DIV_ROUND_UP(CRETE_CMD_DATA_BLOCK_SIZE + sizeof(struct crete_cmd_prot_block), 4) : \ + DIV_ROUND_UP((len) + sizeof(struct crete_cmd_prot_block), 4)) + +#define CRETE_COMMAND_STR_CASE(__cmd) case CRETE_CMD_ ## __cmd: return #__cmd + +#define crete_cmd_dbg(__dev, format, ...) \ + dev_dbg((__dev)->device, "%s:%d:(pid %d): " format, \ + __func__, __LINE__, current->pid, \ + ##__VA_ARGS__) + +#define crete_cmd_dbg_mask(__dev, mask, format, ...) \ +do { \ + if ((mask) & crete_cmd_debug_sw) \ + crete_cmd_dbg(__dev, format, ##__VA_ARGS__); \ +} while (0) + +/* helper macros */ +#define __crete_nullp(typ) ((struct crete_cmd_##typ##_bits *)0) +#define __crete_bit_sz(typ, fld) sizeof(__crete_nullp(typ)->fld) +#define __crete_bit_off(typ, fld) (offsetof(struct crete_cmd_##typ##_bits, fld)) +#define __crete_16_off(typ, fld) (__crete_bit_off(typ, fld) / 16) +#define __crete_dw_off(typ, fld) (__crete_bit_off(typ, fld) / 32) +#define __crete_64_off(typ, fld) (__crete_bit_off(typ, fld) / 64) +#define __crete_16_bit_off(typ, fld) (__crete_bit_off(typ, fld) & 0xf) +#define __crete_dw_bit_off(typ, fld) (__crete_bit_off(typ, fld) & 0x1f) +#define __crete_mask(typ, fld) ((u32)((1ull << __crete_bit_sz(typ, fld)) - 1)) +#define __crete_dw_mask(typ, fld) (__crete_mask(typ, fld) << __crete_dw_bit_off(typ, fld)) +#define __crete_mask16(typ, fld) ((u16)((1ull << __crete_bit_sz(typ, fld)) - 1)) +#define __crete_16_mask(typ, fld) (__crete_mask16(typ, fld) << __crete_16_bit_off(typ, fld)) +#define __crete_st_sz_bits(typ) sizeof(struct crete_cmd_##typ##_bits) + +#define CRETE_FLD_SZ_BYTES(typ, fld) (__crete_bit_sz(typ, fld) / 8) +#define CRETE_ST_SZ_BYTES(typ) (sizeof(struct crete_cmd_##typ##_bits) / 8) +#define CRETE_ST_SZ_DW(typ) (sizeof(struct crete_cmd_##typ##_bits) / 32) +#define CRETE_ST_SZ_QW(typ) (sizeof(struct crete_cmd_##typ##_bits) / 64) +#define CRETE_UN_SZ_BYTES(typ) (sizeof(union crete_cmd_##typ##_bits) / 8) +#define CRETE_UN_SZ_DW(typ) (sizeof(union crete_cmd_##typ##_bits) / 32) +#define CRETE_BYTE_OFF(typ, fld) (__crete_bit_off(typ, fld) / 8) +#define CRETE_ADDR_OF(typ, p, fld) ((void *)((uint8_t *)(p) + CRETE_BYTE_OFF(typ, fld))) + +/* insert a value to a struct */ +#define CRETE_SET(typ, p, fld, v) do { \ + u32 _v = v; \ + BUILD_BUG_ON(__crete_st_sz_bits(typ) % 32); \ + *((__le32 *)(p) + __crete_dw_off(typ, fld)) = \ + cpu_to_le32((le32_to_cpu(*((__le32 *)(p) + __crete_dw_off(typ, fld))) & \ + (~__crete_dw_mask(typ, fld))) | (((_v) & __crete_mask(typ, fld)) \ + << __crete_dw_bit_off(typ, fld))); \ +} while (0) + +#define CRETE_ARRAY_SET(typ, p, fld, idx, v) do { \ + BUILD_BUG_ON(__crete_bit_off(typ, fld) % 32); \ + CRETE_SET(typ, p, fld[idx], v); \ +} while (0) + +#define CRETE_SET_TO_ONES(typ, p, fld) do { \ + BUILD_BUG_ON(__crete_st_sz_bits(typ) % 32); \ + *((__le32 *)(p) + __crete_dw_off(typ, fld)) = \ + cpu_to_le32((le32_to_cpu(*((__le32 *)(p) + __crete_dw_off(typ, fld))) & \ + (~__crete_dw_mask(typ, fld))) | ((__crete_mask(typ, fld)) \ + << __crete_dw_bit_off(typ, fld))); \ +} while (0) + +#define CRETE_GET(typ, p, fld) ((le32_to_cpu(*((__le32 *)(p) +\ +__crete_dw_off(typ, fld))) >> __crete_dw_bit_off(typ, fld)) & \ +__crete_mask(typ, fld)) + +#define CRETE_GET_PR(typ, p, fld) ({ \ + u32 ___t = CRETE_GET(typ, p, fld); \ + pr_debug(#fld " = 0x%x\n", ___t); \ + ___t; \ +}) + +#define __CRETE_SET64(typ, p, fld, v) do { \ + BUILD_BUG_ON(__crete_bit_sz(typ, fld) != 64); \ + *((__le64 *)(p) + __crete_64_off(typ, fld)) = cpu_to_le64(v); \ +} while (0) + +#define CRETE_SET64(typ, p, fld, v) do { \ + BUILD_BUG_ON(__crete_bit_off(typ, fld) % 64); \ + __CRETE_SET64(typ, p, fld, v); \ +} while (0) + +#define CRETE_ARRAY_SET64(typ, p, fld, idx, v) do { \ + BUILD_BUG_ON(__crete_bit_off(typ, fld) % 64); \ + __CRETE_SET64(typ, p, fld[idx], v); \ +} while (0) + +#define CRETE_GET64(typ, p, fld) le64_to_cpu(*((__le64 *)(p) + __crete_64_off(typ, fld))) + +#define CRETE_GET64_PR(typ, p, fld) ({ \ + u64 ___t = CRETE_GET64(typ, p, fld); \ + pr_debug(#fld " = 0x%llx\n", ___t); \ + ___t; \ +}) + +#define CRETE_GET16(typ, p, fld) ((le16_to_cpu(*((__le16 *)(p) +\ +__crete_16_off(typ, fld))) >> __crete_16_bit_off(typ, fld)) & \ +__crete_mask16(typ, fld)) + +#define CRETE_SET16(typ, p, fld, v) do { \ + u16 _v = v; \ + BUILD_BUG_ON(__crete_st_sz_bits(typ) % 16); \ + *((__le16 *)(p) + __crete_16_off(typ, fld)) = \ + cpu_to_le16((le16_to_cpu(*((__le16 *)(p) + __crete_16_off(typ, fld))) & \ + (~__crete_16_mask(typ, fld))) | (((_v) & __crete_mask16(typ, fld)) \ + << __crete_16_bit_off(typ, fld))); \ +} while (0) + + +enum { + CMD_MODE_POLLING, + CMD_MODE_EVENTS +}; + +enum { + CMD_OWNER_SW = 0x0, + CMD_OWNER_HW = 0x1, +}; + +/* cmd delivery status */ +enum crete_cmd_status { + CRETE_CMD_DELIVERY_STAT_OK = 0x0, + CRETE_CMD_DELIVERY_STAT_SIGNAT_ERR = 0x1, + CRETE_CMD_DELIVERY_STAT_CID_ERR = 0x2, + CRETE_CMD_DELIVERY_STAT_DATA_FORMAT_ERR = 0x3, + CRETE_CMD_DELIVERY_STAT_OUT_INSUFFICIENT_ERR = 0x4, + CRETE_CMD_DELIVERY_STAT_OWNER_ERR = 0x5, +}; + +/* return cmd status */ +enum return_cmd_status { + SUCCESS, + INTERNAL_ERR, + BAD_ID, + BAD_OP, + BAD_PARAM, + BAD_STATE, + BAD_RESOURCE, +}; + + +enum { + CRETE_CMD_ENT_STATE_PENDING_COMP, +}; + +enum { + CRETE_TRIGGERED_CMD_COMP = (u64)1 << 32, +}; + +/* cmd id */ +enum crete_gener_cmd_id { + CRETE_CMD_GET_STATUS = 0x100, + CRETE_CMD_SET_STATUS, + CRETE_CMD_GET_FEAT, + CRETE_CMD_SET_FEAT, + CRETE_CMD_GET_DEV_TYPE, + CRETE_CMD_SET_DEV_TYPE, + CRETE_CMD_RESET_DEV, + CRETE_CMD_STOP_DEV, + CRETE_CMD_RESTORE_DEV, + CRETE_CMD_GET_DEV_ATTR, + CRETE_CMD_SET_QP_NUM = 0x10a, + CRETE_CMD_GET_SFI = 0x110, + CRETE_CMD_GEN_MAX, +}; + +/* qp group */ +enum crete_qp_cmd_id { + CRETE_CMD_GET_QP_CAP = 0x300, + CRETE_CMD_CREATE_QP, + CRETE_CMD_DESTORY_QP, + CRETE_CMD_CREATE_QUEUE, + CRETE_CMD_DESTROY_QUEUE = 0x304, + CRETE_CMD_ENABLE_QUEUE = 0x305, + CRETE_CMD_DISABLE_QUEUE = 0x306, + CRETE_CMD_ENABLE_RXEN, + CRETE_CMD_DISABLE_RXEN, + CRETE_CMD_RESET_QUEUE = 0x309, + CRETE_CMD_GET_Q_STATE, + CRETE_CMD_QP_MAX, +}; + + +enum crete_vport_cmd_id { + CRETE_CMD_SET_VPORT_RX_MODE = 0x500, + CRETE_CMD_SET_ESWITCH_MODE = 0x501, + CRETE_CMD_VPORT_ATTR_GET = 0x502, + + CRETE_CMD_SET_VPORT_LINK_STATE = 0x505, + CRETE_CMD_SET_MTU = 0x506, + + CRETE_CMD_SET_TRUST = 0x508, + CRETE_CMD_GET_VPORT_PKT_STAT = 0x509, + + CRETE_CMD_GET_VPORT_LINK_STATE, + CRETE_CMD_GET_VORT_RX_MODE, + CRETE_CMD_SET_TCP_LRO, + CRETE_CMD_GET_TCP_LRO, + CRETE_CMD_SET_RX_RSS, + CRETE_CMD_GET_RX_RSS, + CRETE_CMD_SET_RX_TIMESTAMP, + CRETE_CMD_GET_RX_TIMESTAMP, + CRETE_CMD_GET_TRUST, + CRETE_CMD_SET_UC_MAC, + CRETE_CMD_SET_VF_SHAPER = 0x551, + CRETE_CMD_VPORT_MAX, +}; + +/* +enum crete_vport_cmd_id { + CRETE_CMD_SET_VPORT_RX_MODE = 0x500, + CRETE_CMD_GET_VORT_RX_MODE, + CRETE_CMD_VPORT_ATTR_GET, +// CRETE_CMD_SET_VPORT_LINK_STATE, + CRETE_CMD_GET_VPORT_LINK_STATE, + CRETE_CMD_SET_TCP_LRO, + CRETE_CMD_GET_TCP_LRO, + CRETE_CMD_SET_RX_RSS, + CRETE_CMD_GET_RX_RSS, + CRETE_CMD_SET_RX_TIMESTAMP, + CRETE_CMD_GET_RX_TIMESTAMP, + CRETE_CMD_SET_TRUST, + CRETE_CMD_GET_TRUST, + CRETE_CMD_SET_UC_MAC = 0x50c, + CRETE_CMD_SET_VF_SHAPER = 0x50d, + CRETE_CMD_SET_VPORT_LINK_STATE, + CRETE_CMD_VPORT_MAX, +}; + +*/ + +/* port group */ +enum crete_port_cmd_id { + CRETE_CMD_SET_PORT_TRUST_STATUS = 0x801, + CRETE_CMD_SET_PCP_MAP_TC, + CRETE_CMD_SET_DSCP_MAP_TC, + CRETE_CMD_SET_FC_ENABLE, + CRETE_CMD_SET_FC_TIMEOUT, + CRETE_CMD_SET_PFC_ENABLE, + CRETE_CMD_SET_ETS, + CRETE_CMD_GET_PORT_NUM = 0x808, + CRETE_CMD_GET_PORT_LINK_STATUS, + CRETE_CMD_GET_REPORT_PORT_LINK_STATUS, + CRETE_CMD_GET_PORT_SPEED_DUPLEX_MODE, + CRETE_CMD_SET_PORT_SPEED_DUPLEX_MODE, + CRETE_CMD_GET_PORT_FEC_MODE, + CRETE_CMD_SET_PORT_FEC_MODE, + CRETE_CMD_PORT_MAX, +}; + +/* netdev group */ +enum crete_netdev_cmd_id { + CRETE_CMD_SET_SOP_PADDING = 0x400, + CRETE_CMD_GET_SOP_PADDING, + CRETE_CMD_SET_AUTO_SUPPRESS, + CRETE_CMD_GET_AUTO_SUPPRESS, + CRETE_CMD_SET_MODERATION_TEMP, + CRETE_CMD_GET_MODERATION_TEMP, + CRETE_CMD_SET_INT_MODERATION, + CRETE_CMD_GET_INT_MODERATION, + CRETE_CMD_SET_TX_INORDER, + CRETE_CMD_GET_TX_INORDER, + CRETE_CMD_SET_CQE_AGGREGATION_TEMP, + CRETE_CMD_GET_CQE_AGGREGATION_TEMP, + CRETE_CMD_SET_CQE_AGGREGATION, + CRETE_CMD_GET_CQE_AGGREGATION, + CRETE_CMD_SET_RX_MERGE, + CRETE_CMD_GET_RX_MERGE, + CRETE_CMD_NEDEV_MAX, +}; + +enum crete_lag_cmd_id { + CRETE_CMD_GET_LAG_CAP = 0x0503, + CRETE_CMD_LAG_CONFIG = 0x0504, + CRETE_CMD_ENABLE_LAG = 0x050c, +}; + +/* migration cmd*/ +enum crete_lm_cmd_id { + CRETE_CMD_SET_VQ_MIG_STATE = 0x30c, + CRETE_CMD_GET_VQ_MIG_STATE = 0x30d, + CRETE_CMD_GET_VQ_MIG_STATE_BATCH = 0x30e, + CRETE_CMD_SET_MIG_LOG_STATE = 0x112, + CRETE_CMD_SET_MIG_LOG_BASE = 0x113, +}; + +/* firmware */ +enum crete_firmware_cmd_id { + CRETE_CMD_FWU_LOCK = 0x201, + CRETE_CMD_FWU_UNLOCK, + CRETE_CMD_FWU_PKEY, + CRETE_CMD_FWU_VER, + CRETE_CMD_FWU_XFER, + CRETE_CMD_FWU_END, +}; + +/*set mtu*/ +enum crete_set_mtu_op { + CRETE_SET_MTU_MACPORT = 1, + CRETE_SET_MTU_VPORT = 2, +}; + +#define MAC_MTU(v) ((v) + ETH_HLEN) + +/*get vport pkt statistics*/ +enum crete_get_vport_statistics_op { + CRETE_GET_PKT_STATIS_VPORT = 0, + CRETE_GET_PKT_STATIS_MAC = 1, + CRETE_GET_PKT_STATIS_LAG = 2, +}; + +enum crete_tmplate_cmd_id { + CRETE_CMD_GET_VF_MAC = 0x8101, +}; + +int crete_cmd_exec_polling(struct crete_core_dev *dev, void *in, int in_size, + void *out, int out_size); + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd_if.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd_if.c new file mode 100644 index 0000000..df5f62c --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd_if.c @@ -0,0 +1,2228 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "crete_cmd_if.h" +#include "crete_regs.h" + +static void crete_cleanup_queue_for_test(struct crete_core_dev *cdev) +{ + struct pci_dev *pdev = cdev->pdev; + struct device *dev = &pdev->dev; + struct crete_queue_info *q_info = &cdev->q_info; + + dma_free_coherent(dev, 4096, q_info->sq[0].va, q_info->sq[0].pa); + dma_free_coherent(dev, 4096, q_info->sq[1].va, q_info->sq[1].pa); + dma_free_coherent(dev, 4096, q_info->cq[0].va, q_info->cq[0].pa); + dma_free_coherent(dev, 4096, q_info->cq[1].va, q_info->cq[1].pa); + + q_info->sq[0].va = NULL; + q_info->sq[0].pa = 0; + q_info->sq[1].va = NULL; + q_info->sq[1].pa = 0; + + q_info->cq[0].va = NULL; + q_info->cq[0].pa = 0; + q_info->cq[1].va = NULL; + q_info->cq[1].pa = 0; +} + +static int crete_setup_queue_for_test(struct crete_core_dev *cdev) +{ + struct crete_queue_info *q_info; + int err = 0; + + q_info = &cdev->q_info; + + /* for create q test */ + q_info->rx_qid = 0; + q_info->q_size = 128; + q_info->vec[0] = 0; //for rx cq; + q_info->vec[1] = 1; //for tx cq; + + q_info->sq[0].va = dma_alloc_coherent(cdev->device, 4096, + &q_info->sq[0].pa, GFP_KERNEL); + if (!q_info->sq[0].va) { + err = -EINVAL; + + return err; + } + crete_info(cdev->device, "sq 0 addr:0x%llx\n", q_info->sq[0].pa); + + q_info->sq[1].va = dma_alloc_coherent(cdev->device, 4096, + &q_info->sq[1].pa, GFP_KERNEL); + if (!q_info->sq[1].va) { + err = -ENOMEM; + goto err3; + } + crete_info(cdev->device, "sq 1 addr:0x%llx\n", q_info->sq[1].pa); + + q_info->cq[0].va = dma_alloc_coherent(cdev->device, 4096, + &q_info->cq[0].pa, GFP_KERNEL); + if (!q_info->cq[0].va) { + err = -ENOMEM; + goto err2; + } + crete_info(cdev->device, "cq 0 addr:0x%llx\n", q_info->cq[0].pa); + + q_info->cq[1].va = dma_alloc_coherent(cdev->device, 4096, + &q_info->cq[1].pa, GFP_KERNEL); + if (!q_info->cq[1].va) { + err = -ENOMEM; + goto err1; + } + crete_info(cdev->device, "cq 1 addr:0x%llx\n", q_info->cq[1].pa); + + return err; +err1: + dma_free_coherent(cdev->device, 4096, + q_info->cq[0].va, q_info->cq[0].pa); +err2: + dma_free_coherent(cdev->device, 4096, + q_info->sq[1].va, q_info->sq[0].pa); +err3: + dma_free_coherent(cdev->device, 4096, + q_info->sq[0].va, q_info->sq[0].pa); + return err; +} + +int crete_get_status(struct crete_core_dev *cdev, enum crete_status_opcode op, + u8 *status) +{ + u32 in[CRETE_ST_SZ_DW(get_status_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_status_out)] = { 0 }; + u32 dev_status; + int ret = 0; + + CRETE_SET(get_status_in, in, cmd_id, CRETE_CMD_GET_STATUS); + CRETE_SET(get_status_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + *status = CRETE_GET(get_status_out, out, status); + dev_status = CRETE_GET(get_status_out, out, dev_status); + crete_info(cdev->device, "status[%d] dev_status[%d]\n", *status, + dev_status); + + return 0; +} + +EXPORT_SYMBOL(crete_get_status); +int crete_set_status(struct crete_core_dev *cdev, enum crete_status_opcode op, + u32 status) +{ + u32 in[CRETE_ST_SZ_DW(set_status_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_status_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_status_in, in, cmd_id, CRETE_CMD_SET_STATUS); + CRETE_SET(set_status_in, in, opcode, op); + CRETE_SET(set_status_in, in, dev_status, status); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_status_out, out, status); + crete_info(cdev->device, "st[%d] status[%d]\n", st, status); + + return 0; +} + +EXPORT_SYMBOL(crete_set_status); + +int crete_cmd_get_features(struct crete_core_dev *cdev, enum crete_feature_opcode op, + netdev_features_t *feat_bits) +{ + u32 in[CRETE_ST_SZ_DW(get_feat_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(get_feat_out)] = {0}; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_feat_in, in, cmd_id, CRETE_CMD_GET_FEAT); + CRETE_SET(get_feat_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_feat_out, out, status); + + *feat_bits = (u64)(CRETE_GET(get_feat_out, out, + feat_bits_hi)) << 32 | (CRETE_GET(get_feat_out, out, feat_bits_lo)); + crete_info(cdev->device, "status[%d] feat_bits[0x%llx]\n", st, *feat_bits); + + return 0; +} +EXPORT_SYMBOL(crete_cmd_get_features); + +int crete_cmd_set_features(struct crete_core_dev *cdev, enum crete_feature_opcode op, + u64 feat_bits) +{ + u32 in[CRETE_ST_SZ_DW(set_feat_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_feat_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_feat_in, in, cmd_id, CRETE_CMD_SET_FEAT); + CRETE_SET(set_feat_in, in, opcode, op); + CRETE_SET(set_feat_in, in, feat_bits_lo, feat_bits & 0xffffffff); + CRETE_SET(set_feat_in, in, feat_bits_hi, feat_bits >> 32); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_feat_out, out, status); + crete_info(cdev->device, "st[%d] feat_bits[0x%llx]\n", st, feat_bits); + + return 0; +} +EXPORT_SYMBOL(crete_cmd_set_features); + +int crete_get_dev_type(struct crete_core_dev *cdev, u32 *dev_type) +{ + u32 in[CRETE_ST_SZ_DW(get_dev_type_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_dev_type_out)] = { 0 }; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_dev_type_in, in, cmd_id, CRETE_CMD_GET_DEV_TYPE); + //CRETE_SET16(get_dev_type_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_dev_type_out, out, status); + *dev_type = CRETE_GET(get_dev_type_out, out, dev_type); + crete_info(cdev->device, "st[%d] dev_type[%d]\n", st, *dev_type); + + return 0; +} + +EXPORT_SYMBOL(crete_get_dev_type); +int crete_set_dev_type(struct crete_core_dev *cdev, u32 dev_type) +{ + u32 in[CRETE_ST_SZ_DW(set_dev_type_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_dev_type_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_dev_type_in, in, cmd_id, CRETE_CMD_SET_DEV_TYPE); + //CRETE_SET16(set_dev_type_in, in, opcode, op); + CRETE_SET(set_dev_type_in, in, dev_type, dev_type); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_dev_type_out, out, status); + crete_info(cdev->device, "st[%d] dev_type[%d]\n", st, dev_type); + return 0; +} + +EXPORT_SYMBOL(crete_set_dev_type); + +int crete_reset_dev(struct crete_core_dev *cdev, enum crete_reset_opcode op) +{ + u32 in[CRETE_ST_SZ_DW(reset_dev_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(reset_dev_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(reset_dev_in, in, cmd_id, CRETE_CMD_RESET_DEV); + CRETE_SET(reset_dev_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(reset_dev_out, out, status); + return 0; +} + +EXPORT_SYMBOL(crete_reset_dev); + +int crete_stop_dev(struct crete_core_dev *cdev, enum crete_stop_opcode op) +{ + u32 in[CRETE_ST_SZ_DW(stop_dev_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(stop_dev_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(stop_dev_in, in, cmd_id, CRETE_CMD_STOP_DEV); + CRETE_SET(stop_dev_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(stop_dev_out, out, status); + return 0; +} + +EXPORT_SYMBOL(crete_stop_dev); + +int crete_restore_dev(struct crete_core_dev *cdev, enum crete_restore_opcode op) +{ + u32 in[CRETE_ST_SZ_DW(restore_dev_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(restore_dev_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(restore_dev_in, in, cmd_id, CRETE_CMD_RESTORE_DEV); + CRETE_SET(restore_dev_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(restore_dev_out, out, status); + return 0; +} + +EXPORT_SYMBOL(crete_restore_dev); + +int crete_get_qp_cap(struct crete_core_dev *cdev, + u16 *max_queue_size, + u8 *max_qp_num, u8 *ctrl_queue_size) +{ + u32 in[CRETE_ST_SZ_DW(get_qp_cap_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_qp_cap_out)] = { 0 }; + void *qp_out; +// u8 ctrl_q_size, max_qp_num, max_queue_size; + int ret = 0; + int status; + + CRETE_SET(get_qp_cap_in, in, cmd_id, CRETE_CMD_GET_QP_CAP); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + status = CRETE_GET(get_qp_cap_out, out, status); + if (status != SUCCESS) { + u8 err_type = CRETE_GET(get_qp_cap_out, out, err_type); + + crete_err(cdev->device, "failed, err type:0x%x\n", err_type); + ret = -EINVAL; + goto err_out; + } + qp_out = CRETE_ADDR_OF(get_qp_cap_out, out, qp_cap); + *ctrl_queue_size = CRETE_GET_PR(qp_cap, qp_out, ctrl_q_size); + *max_qp_num = CRETE_GET_PR(qp_cap, qp_out, max_qp_num); + *max_queue_size = CRETE_GET_PR(qp_cap, qp_out, max_queue_size); + crete_info(cdev->device, + "ctrl_q_size[%d] max_qp_num[%d] max_queue_size[%d]\n", + *ctrl_queue_size, *max_qp_num, *max_queue_size); + + return 0; +err_out: + return ret; + +} + +EXPORT_SYMBOL(crete_get_qp_cap); + +int crete_create_txrxqp(struct crete_core_dev *cdev, u16 qid) +{ + int in_len = CRETE_ST_SZ_BYTES(create_qp_in); + int out_len = CRETE_ST_SZ_BYTES(create_qp_out); + void *qpc_in, *in; + void *qp_out, *out; + int mqpc_size = 0; + struct crete_queue_info *q_info; + struct crete_napi *jnapi_rx, *jnapi_tx; + int ret = 0; + u8 status; + int rx_qid; + int result; + + if (!cdev) { + crete_err(cdev->device, "cmd create queue, cdev is NULL\n"); + return -EINVAL; + } + q_info = &cdev->q_info; + if (!q_info) { + crete_err(cdev->device, "q info is NULL\n"); + return -EINVAL; + } + mqpc_size = CRETE_ST_SZ_BYTES(qp_context); + in_len += mqpc_size; + out_len += CRETE_ST_SZ_BYTES(qp_result); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + jnapi_rx = &cdev->jnapi[2 * qid]; + jnapi_tx = &cdev->jnapi[2 * qid + 1]; + + CRETE_SET(create_qp_in, in, cmd_id, CRETE_CMD_CREATE_QP); + CRETE_SET(set_status_in, in, opcode, 0); + qpc_in = CRETE_ADDR_OF(create_qp_in, in, qp_context); + + CRETE_SET(qp_context, qpc_in, rx_qid, qid); + CRETE_SET(qp_context, qpc_in, rx_sq_size, + jnapi_rx->rxring->rx_ring_size); + CRETE_SET(qp_context, qpc_in, rx_cq_size, + jnapi_rx->rxring->rx_ring_size); + CRETE_SET(qp_context, qpc_in, tx_sq_size, + jnapi_tx->txring->tx_ring_size); + CRETE_SET(qp_context, qpc_in, tx_cq_size, + jnapi_tx->txring->tx_ring_size); + + CRETE_SET(qp_context, qpc_in, rx_q_vec, jnapi_rx->rxring->vec); + CRETE_SET64(qp_context, qpc_in, rx_sq_base, + jnapi_rx->rxring->rx_bd_mapping); + CRETE_SET64(qp_context, qpc_in, rx_cq_base, + jnapi_rx->rxcpring->rxcq_mapping); + + CRETE_SET(qp_context, qpc_in, tx_q_vec, jnapi_tx->txring->vec); + CRETE_SET64(qp_context, qpc_in, tx_sq_base, + jnapi_tx->txring->tx_bd_mapping); + CRETE_SET64(qp_context, qpc_in, tx_cq_base, + jnapi_tx->txcpring->txcq_mapping); + + crete_info(cdev->device, + "rx_qid:%d sqbd dma handle addr:0x%llx, cqbd dma handle addr:0x%llx\n", + qid, jnapi_rx->rxring->rx_bd_mapping, + jnapi_rx->rxcpring->rxcq_mapping); + crete_info(cdev->device, + "tx_qid:%d sqbd dma handle addr:0x%llx, cqbd dma handle addr:0x%llx\n", + qid, jnapi_tx->txring->tx_bd_mapping, + jnapi_tx->txcpring->txcq_mapping); + + hexdump((char *)in, in_len); +#ifndef CONFIG_NOSIM_DEBUG + ret = crete_cmd_exec_polling(cdev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(create_qp_out, out, status); + if (status != SUCCESS) { + u8 err_type = CRETE_GET(create_qp_out, out, err_type); + + crete_err(cdev->device, + "crete create qp failed, status:0x%x err type:0x%x\n", + status, err_type); + ret = -EINVAL; + goto err_out; + } + qp_out = CRETE_ADDR_OF(create_qp_out, out, qp_result); + rx_qid = CRETE_GET_PR(qp_result, qp_out, rx_qid); + result = CRETE_GET_PR(qp_result, qp_out, result); + crete_info(cdev->device, + "CRETE_CREATE_QP Complete :rx_qid[%d] result[%d]\n", rx_qid, + result); +#endif +err_out: + kvfree(in); + kvfree(out); + return ret; +} + +int crete_create_queue_core(struct crete_core_dev *cdev, u16 num_q, void *mqc) +{ + int ret = 0; + int in_len = CRETE_ST_SZ_BYTES(create_q_in); + int out_len = CRETE_ST_SZ_BYTES(create_q_out); + void *qc_in, *in; + void *q_out, *out; + int mqc_size = 0; + u8 status; + int qid; + int result; + int i; + struct device *dev = cdev->device; + + mqc_size = num_q * CRETE_ST_SZ_BYTES(queue_context); + in_len += mqc_size; + out_len += num_q * CRETE_ST_SZ_BYTES(queue_result); + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(create_q_in, in, cmd_op, num_q); + CRETE_SET(create_q_in, in, cmd_id, CRETE_CMD_CREATE_QUEUE); + qc_in = CRETE_ADDR_OF(create_q_in, in, q_context); + memcpy(qc_in, mqc, mqc_size); + + hexdump((char *)qc_in, mqc_size); + + ret = crete_cmd_exec_polling(cdev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(create_q_out, out, status); + if (status != SUCCESS) { + u8 err_type = CRETE_GET(create_q_out, out, err_type); + + crete_err(dev, "crete create queue failed, err type:0x%x\n", + err_type); + ret = -EINVAL; + } + q_out = CRETE_ADDR_OF(create_q_out, out, q_result); + for (i = 0; i < num_q; i++, q_out += CRETE_ST_SZ_BYTES(queue_result)) { + qid = CRETE_GET_PR(queue_result, q_out, qid); + result = CRETE_GET_PR(queue_result, q_out, result); + crete_info(dev, + "CRETE_CREATE_QP Complete :rx_qid[%d] result[%d]\n", + qid, result); + } +err_out: + kvfree(in); + kvfree(out); + return ret; +} + +/* crete support single qp create */ +int crete_cmd_create_qp(struct crete_core_dev *cdev, + struct crete_qp_context *qpctx) +{ + int in_len = CRETE_ST_SZ_BYTES(create_qp_in); + int out_len = CRETE_ST_SZ_BYTES(create_qp_out); + void *qpc_in, *in; + void *qp_out, *out; + int ret = 0; + u8 status; + int rx_qid; + int result; + + in_len += CRETE_ST_SZ_BYTES(qp_context); + out_len += CRETE_ST_SZ_BYTES(qp_result); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET16(create_qp_in, in, cmd_id, CRETE_CMD_CREATE_QP); + CRETE_SET16(set_status_in, in, opcode, 0); + qpc_in = CRETE_ADDR_OF(create_qp_in, in, qp_context); + + CRETE_SET16(qp_context, qpc_in, rx_qid, qpctx->rx_qid); + CRETE_SET16(qp_context, qpc_in, rx_sq_size, qpctx->rx_sq_vq_size); + CRETE_SET16(qp_context, qpc_in, rx_cq_size, qpctx->rx_cq_size); + CRETE_SET16(qp_context, qpc_in, tx_sq_size, qpctx->tx_sq_vq_size); + CRETE_SET16(qp_context, qpc_in, tx_cq_size, qpctx->tx_cq_size); + + CRETE_SET16(qp_context, qpc_in, rx_q_vec, qpctx->rx_queue_vec); + CRETE_SET64(qp_context, qpc_in, rx_sq_base, qpctx->rx_sq_desc_base); + CRETE_SET64(qp_context, qpc_in, rx_cq_base, qpctx->rx_cq_used_base); + + CRETE_SET16(qp_context, qpc_in, tx_q_vec, qpctx->tx_queue_vec); + CRETE_SET64(qp_context, qpc_in, tx_sq_base, qpctx->tx_sq_desc_base); + CRETE_SET64(qp_context, qpc_in, tx_cq_base, qpctx->tx_cq_used_base); + + crete_info(cdev->device, + "rx_qid:%d sqbd dma handle addr:0x%llx, cqbd dma handle addr:0x%llx\n", + qpctx->rx_qid, qpctx->rx_sq_desc_base, + qpctx->rx_cq_used_base); + crete_info(cdev->device, + "tx_qid:%d sqbd dma handle addr:0x%llx, cqbd dma handle addr:0x%llx\n", + qpctx->rx_qid, qpctx->tx_sq_desc_base, + qpctx->tx_cq_used_base); + + hexdump((char *)in, in_len); + + ret = crete_cmd_exec_polling(cdev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(create_qp_out, out, status); + if (status != SUCCESS) { + u8 err_type = CRETE_GET(create_qp_out, out, err_type); + + crete_err(cdev->device, + "crete create qp failed, status:0x%x err type:0x%x\n", + status, err_type); + ret = -EINVAL; + goto err_out; + } + qp_out = CRETE_ADDR_OF(create_qp_out, out, qp_result); + rx_qid = CRETE_GET_PR(qp_result, qp_out, rx_qid); + result = CRETE_GET_PR(qp_result, qp_out, result); + crete_info(cdev->device, + "CRETE_CREATE_QP Complete :rx_qid[%d] result[%d]\n", rx_qid, + result); + +err_out: + kvfree(in); + kvfree(out); + return ret; + +} +EXPORT_SYMBOL(crete_cmd_create_qp); + +/* crete support single q create */ +int crete_cmd_create_signal_queue(struct crete_core_dev *cdev, + struct crete_queue_context *qctx) +{ + int in_len = CRETE_ST_SZ_BYTES(create_q_in); + int out_len = CRETE_ST_SZ_BYTES(create_q_out); + void *q_in, *in; + void *q_out, *out; + int ret = 0; + int qid; + u8 status; + int result; + + in_len += CRETE_ST_SZ_BYTES(queue_context); + out_len += CRETE_ST_SZ_BYTES(queue_result); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET16(create_q_in, in, cmd_id, CRETE_CMD_CREATE_QUEUE); + CRETE_SET16(create_q_in, in, cmd_op, 1); + q_in = CRETE_ADDR_OF(create_q_in, in, q_context); + + CRETE_SET16(queue_context, q_in, qid, qctx->qid); + CRETE_SET16(queue_context, q_in, event_credit, 0); + CRETE_SET16(queue_context, q_in, sq_size, qctx->queue_size); + CRETE_SET16(queue_context, q_in, cq_size, qctx->cq_size); + CRETE_SET16(queue_context, q_in, resv1, 0); + + CRETE_SET16(queue_context, q_in, queue_vec, qctx->queue_vec); + CRETE_SET(queue_context, q_in, sq_base_hi, qctx->queue_desc_base >> 32); + CRETE_SET(queue_context, q_in, sq_base_lo, + qctx->queue_desc_base & 0xffffffff); + + CRETE_SET(queue_context, q_in, cq_base_hi, qctx->queue_used_base >> 32); + CRETE_SET(queue_context, q_in, cq_base_lo, + qctx->queue_used_base & 0xffffffff); + + crete_info(cdev->device, + "qid:%d dma desc addr:0x%llx, dma used lo addr:0x%llx\n", + qctx->qid, qctx->queue_desc_base, qctx->queue_used_base); + + hexdump((char *)in, in_len); + + ret = crete_cmd_exec_polling(cdev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(create_q_out, out, status); + if (status != SUCCESS) { + u8 err_type = CRETE_GET(create_q_out, out, err_type); + + crete_err(cdev->device, + "crete create qp failed, status:0x%x err type:0x%x\n", + status, err_type); + ret = -EINVAL; + goto err_out; + } + q_out = CRETE_ADDR_OF(create_q_out, out, q_result); + qid = CRETE_GET_PR(queue_result, q_out, qid); + result = CRETE_GET_PR(queue_result, q_out, result); + crete_info(cdev->device, + "CRETE_CREATE_QP Complete :qid[%d] result[%d]\n", qid, + result); + +err_out: + kvfree(in); + kvfree(out); + return ret; + +} +EXPORT_SYMBOL(crete_cmd_create_signal_queue); + +int crete_create_queue(struct crete_core_dev *cdev, u16 num_q) +{ + int mqc_size = 0, i = 0; + void *mqc, *tmp_mqc; + struct crete_queue_info *q_info; + int ret = 0; + struct device *dev = cdev->device; + + if (!cdev) { + crete_err(dev, "cmd create queue, cdev is NULL\n"); + return -EINVAL; + } + + if (num_q <= 0 || num_q > 128) { + crete_err(dev, "num_queue[%d] is illegal\n", num_q); + return -EINVAL; + } + + ret = crete_setup_queue_for_test(cdev); + if (ret < 0) { + ret = -ENOMEM; + return ret; + } + q_info = &cdev->q_info; + if (!q_info) { + crete_err(dev, "q info is NULL\n"); + return -EINVAL; + } + + mqc_size = num_q * CRETE_ST_SZ_BYTES(queue_context); + mqc = kvzalloc(mqc_size, GFP_KERNEL); + if (!mqc) { + ret = -ENOMEM; + goto out_mqc; + } + + crete_info(dev, "create queue num[%d]\n", num_q); + crete_info(dev, "create queue mqc_size[%d]\n", mqc_size); + tmp_mqc = mqc; + + for (i = 0; i < num_q; i++, tmp_mqc += CRETE_ST_SZ_BYTES(queue_context)) { + CRETE_SET(queue_context, tmp_mqc, qid, i); + CRETE_SET(queue_context, tmp_mqc, sq_size, 128); + CRETE_SET(queue_context, tmp_mqc, cq_size, 128); + + //debug same qc for mqc + CRETE_SET(queue_context, tmp_mqc, queue_vec, q_info->vec[0]); + CRETE_SET(queue_context, tmp_mqc, sq_base_lo, + (q_info->sq[0].pa) & 0xffffffff); + CRETE_SET(queue_context, tmp_mqc, sq_base_hi, + (q_info->sq[0].pa) >> 32); + CRETE_SET(queue_context, tmp_mqc, cq_base_lo, + (q_info->cq[0].pa) & 0xffffffff); + CRETE_SET(queue_context, tmp_mqc, cq_base_hi, + (q_info->cq[0].pa) >> 32); + } + //hexdump((char *)mqc, mqc_size); + ret = crete_create_queue_core(cdev, num_q, mqc); + if (ret < 0) + crete_err(dev, "test create queue failed\n"); + + kvfree(mqc); +out_mqc: + crete_cleanup_queue_for_test(cdev); + return ret; +} + +EXPORT_SYMBOL(crete_create_queue); + +int crete_create_qp_one_core(struct crete_core_dev *cdev, u16 qid) +{ + int in_len = CRETE_ST_SZ_BYTES(create_qp_in); + int out_len = CRETE_ST_SZ_BYTES(create_qp_out); + void *qpc_in, *in; + void *qp_out, *out; + int mqpc_size = 0; + int rx_qid; + int result; + struct crete_queue_info *q_info; + int ret = 0; + u8 status; + struct device *dev = cdev->device; + + if (!cdev) { + crete_err(dev, "cmd create queue, cdev is NULL\n"); + return -EINVAL; + } + + q_info = &cdev->q_info; + if (!q_info) { + crete_err(dev, "q info is NULL\n"); + return -EINVAL; + } + mqpc_size = CRETE_ST_SZ_BYTES(qp_context); + in_len += mqpc_size; + out_len += CRETE_ST_SZ_BYTES(qp_result); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(create_qp_in, in, cmd_id, CRETE_CMD_CREATE_QP); + qpc_in = CRETE_ADDR_OF(create_qp_in, in, qp_context); + CRETE_SET(qp_context, qpc_in, rx_qid, q_info->rx_qid); + CRETE_SET(qp_context, qpc_in, rx_cq_size, q_info->q_size); + CRETE_SET(qp_context, qpc_in, rx_sq_size, q_info->q_size); + CRETE_SET(qp_context, qpc_in, tx_sq_size, q_info->q_size); + CRETE_SET(qp_context, qpc_in, tx_cq_size, q_info->q_size); + + CRETE_SET(qp_context, qpc_in, rx_q_vec, q_info->vec[0]); + CRETE_SET64(qp_context, qpc_in, rx_sq_base, q_info->sq[0].pa); + CRETE_SET64(qp_context, qpc_in, rx_cq_base, q_info->cq[0].pa); + + CRETE_SET(qp_context, qpc_in, tx_q_vec, q_info->vec[1]); + CRETE_SET64(qp_context, qpc_in, tx_sq_base, q_info->sq[1].pa); + CRETE_SET64(qp_context, qpc_in, tx_cq_base, q_info->cq[1].pa); + + crete_info(dev, + "rx_qid:%d sqbd dma handle addr:0x%llx, cqbd dma handle addr:0x%llx\n", + q_info->rx_qid, q_info->sq[0].pa, q_info->cq[0].pa); + crete_info(dev, + "tx_qid:%d sqbd dma handle addr:0x%llx, cqbd dma handle addr:0x%llx\n", + q_info->rx_qid + 1, q_info->sq[1].pa, q_info->cq[1].pa); + + hexdump((char *)in, in_len); + + ret = crete_cmd_exec_polling(cdev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(create_qp_out, out, status); + if (status != SUCCESS) { + u8 err_type = CRETE_GET(create_qp_out, out, err_type); + + crete_err(dev, "crete create qp failed, err type:0x%x\n", + err_type); + ret = -EINVAL; + goto err_out; + } + qp_out = CRETE_ADDR_OF(create_qp_out, out, qp_result); + rx_qid = CRETE_GET_PR(qp_result, qp_out, rx_qid); + result = CRETE_GET_PR(qp_result, qp_out, result); + crete_info(dev, "CRETE_CREATE_QP Complete :rx_qid[%d] result[%d]\n", + rx_qid, result); +err_out: + kvfree(in); + kvfree(out); + return ret; +} + +int crete_create_qp_one(struct crete_core_dev *cdev) +{ + int ret = 0; + + ret = crete_setup_queue_for_test(cdev); + if (ret < 0) { + crete_err(cdev->device, "test qp_one create failed\n"); + return ret; + } + + ret = crete_create_qp_one_core(cdev, 0); + if (ret < 0) + crete_err(cdev->device, "test qp_one 0 create failed\n"); + + crete_cleanup_queue_for_test(cdev); + + return ret; +} + +EXPORT_SYMBOL(crete_create_qp_one); + +int crete_create_qp_core(struct crete_core_dev *cdev, u16 num_qp, void *mqpc) +{ + int ret = 0; + int in_len = CRETE_ST_SZ_BYTES(create_qp_in); + int out_len = CRETE_ST_SZ_BYTES(create_qp_out); + void *qpc_in, *in; + void *qp_out, *out; + int mqpc_size = 0; + u8 status; + int rx_qid; + int result; + int i; + struct device *dev = cdev->device; + + mqpc_size = num_qp * CRETE_ST_SZ_BYTES(qp_context); + in_len += mqpc_size; + out_len += num_qp * CRETE_ST_SZ_BYTES(qp_result); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(create_qp_in, in, cmd_op, num_qp); + CRETE_SET(create_qp_in, in, cmd_id, CRETE_CMD_CREATE_QP); + qpc_in = CRETE_ADDR_OF(create_qp_in, in, qp_context); + memcpy(qpc_in, mqpc, mqpc_size); + + hexdump((char *)qpc_in, mqpc_size); + + ret = crete_cmd_exec_polling(cdev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(create_qp_out, out, status); + if (status != SUCCESS) { + u8 err_type = CRETE_GET(create_qp_out, out, err_type); + + crete_err(dev, "crete create qp failed, err type:0x%x\n", + err_type); + ret = -EINVAL; + } + qp_out = CRETE_ADDR_OF(create_qp_out, out, qp_result); + for (i = 0; i < num_qp; i++, qp_out += CRETE_ST_SZ_BYTES(qp_result)) { + rx_qid = CRETE_GET_PR(qp_result, qp_out, rx_qid); + result = CRETE_GET_PR(qp_result, qp_out, result); + crete_info(dev, + "CRETE_CREATE_QP Complete :rx_qid[%d] result[%d]\n", + rx_qid, result); + } +err_out: + kvfree(in); + kvfree(out); + return ret; +} + +int crete_create_qp(struct crete_core_dev *cdev, u16 num_qp) +{ + int mqpc_size = 0, i = 0; + void *mqpc, *tmp_mqpc; + struct crete_queue_info *q_info; + int ret = 0; + struct device *dev = cdev->device; + + if (!cdev) { + crete_err(dev, "cmd create queue, cdev is NULL\n"); + return -EINVAL; + } + + if (num_qp <= 0 || num_qp > 128) { + crete_err(dev, "crete_test_mqp_create num is illegal\n"); + return -EINVAL; + } + + q_info = &cdev->q_info; + if (!q_info) { + crete_err(dev, "q info is NULL\n"); + return -EINVAL; + } + + mqpc_size = num_qp * CRETE_ST_SZ_BYTES(qp_context); + mqpc = kvzalloc(mqpc_size, GFP_KERNEL); + if (!mqpc) { + ret = -ENOMEM; + goto out_mqc; + } + + ret = crete_setup_queue_for_test(cdev); + if (ret < 0) { + crete_err(dev, "test queue create failed\n"); + return ret; + } + crete_info(dev, "create qp num[%d]\n", num_qp); + crete_info(dev, "create qp mqpc_size[%d]\n", mqpc_size); + tmp_mqpc = mqpc; + for (i = 0; i < num_qp; i++, tmp_mqpc += CRETE_ST_SZ_BYTES(qp_context)) { + CRETE_SET(qp_context, tmp_mqpc, rx_qid, i); + CRETE_SET(qp_context, tmp_mqpc, rx_sq_size, 128); + CRETE_SET(qp_context, tmp_mqpc, rx_cq_size, 128); + CRETE_SET(qp_context, tmp_mqpc, tx_sq_size, 128); + CRETE_SET(qp_context, tmp_mqpc, tx_cq_size, 128); + + //debug same qpc for mqp + CRETE_SET(qp_context, tmp_mqpc, rx_q_vec, q_info->vec[0]); + CRETE_SET64(qp_context, tmp_mqpc, rx_sq_base, q_info->sq[0].pa); + CRETE_SET64(qp_context, tmp_mqpc, rx_cq_base, q_info->cq[0].pa); + + CRETE_SET(qp_context, tmp_mqpc, tx_q_vec, q_info->vec[1]); + CRETE_SET64(qp_context, tmp_mqpc, tx_sq_base, q_info->sq[1].pa); + CRETE_SET64(qp_context, tmp_mqpc, tx_cq_base, q_info->cq[1].pa); + } + //hexdump((char *)mqpc, mqpc_size); + ret = crete_create_qp_core(cdev, num_qp, mqpc); + if (ret < 0) + crete_err(dev, "test mqp create failed\n"); + kvfree(mqpc); +out_mqc: + crete_cleanup_queue_for_test(cdev); + return ret; +} + +EXPORT_SYMBOL(crete_create_qp); + +int crete_reset_queue(struct crete_core_dev *cdev, u16 op) +{ + u32 *in, *out; + int outlen = CRETE_ST_SZ_BYTES(reset_queue_out); + int inlen = CRETE_ST_SZ_BYTES(reset_queue_in); + int ret = 0; + void *q_out; + int qid; + int result; + u8 st = 0; + int i = 0; + + if (op <= 0 || op > 128) { + crete_err(cdev->device, "reset queue num is illegal\n"); + return -EINVAL; + } + inlen += op * CRETE_FLD_SZ_BYTES(reset_queue_in, qid[0]); + outlen += op * CRETE_FLD_SZ_BYTES(reset_queue_out, q_result[0]); + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + crete_err(cdev->device, "in vzalloc failed %d\n", inlen); + goto err; + } + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + crete_err(cdev->device, "out vzalloc failed %d\n", outlen); + goto err; + } + + CRETE_SET(reset_queue_in, in, cmd_op, op); + CRETE_SET(reset_queue_in, in, cmd_id, CRETE_CMD_RESET_QUEUE); + + for (i = 0; i < op; i++) + CRETE_ARRAY_SET(reset_queue_in, in, qid, i, i); + + ret = crete_cmd_exec_polling(cdev, in, inlen, out, outlen); + if (ret < 0) + goto err; + + st = CRETE_GET(reset_queue_out, out, status); + crete_info(cdev->device, "st[%d]\n", st); + + q_out = CRETE_ADDR_OF(reset_queue_out, out, q_result); + for (i = 0; i < op; i++, q_out += CRETE_ST_SZ_BYTES(queue_result)) { + qid = CRETE_GET_PR(queue_result, q_out, qid); + result = CRETE_GET_PR(queue_result, q_out, result); + crete_info(cdev->device, "Complete :rx_qid[%d] result[%d]\n", + qid, result); + } + + kvfree(in); + kvfree(out); + return 0; +err: + kvfree(in); + kvfree(out); + return ret; +} + +EXPORT_SYMBOL(crete_reset_queue); + +int crete_reset_singlequeue(struct crete_core_dev *cdev, u16 queueid) +{ + u32 *in, *out; + int outlen = CRETE_ST_SZ_BYTES(reset_queue_out); + int inlen = CRETE_ST_SZ_BYTES(reset_queue_in); + int ret = 0; + void *q_out; + int qid; + int result; + u8 st = 0; + + inlen += CRETE_FLD_SZ_BYTES(reset_queue_in, qid[0]); + outlen += CRETE_FLD_SZ_BYTES(reset_queue_out, q_result[0]); + + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + crete_err(cdev->device, "in vzalloc failed %d\n", inlen); + goto err; + } + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + crete_err(cdev->device, "out vzalloc failed %d\n", outlen); + goto err; + } + + CRETE_SET16(reset_queue_in, in, cmd_op, 1); + CRETE_SET16(reset_queue_in, in, cmd_id, CRETE_CMD_RESET_QUEUE); + + CRETE_ARRAY_SET(reset_queue_in, in, qid, 0, queueid); + + ret = crete_cmd_exec_polling(cdev, in, inlen, out, outlen); + if (ret < 0) + goto err; + + st = CRETE_GET(reset_queue_out, out, status); + crete_info(cdev->device, "st[%d]\n", st); + + q_out = CRETE_ADDR_OF(reset_queue_out, out, q_result); + qid = CRETE_GET_PR(queue_result, q_out, qid); + result = CRETE_GET_PR(queue_result, q_out, result); + crete_info(cdev->device, "Complete :rx_qid[%d] result[%d]\n", qid, + result); + + kvfree(in); + kvfree(out); + return 0; +err: + kvfree(in); + kvfree(out); + return ret; +} +EXPORT_SYMBOL(crete_reset_singlequeue); + +/* + * crete single queue opeartions + * queue common operation + */ +int crete_singlequeue_rawcmd(struct crete_core_dev *cdev, u16 queueid, int ops) +{ + u32 *in, *out; + int outlen = CRETE_ST_SZ_BYTES(raw_queue_out); + int inlen = CRETE_ST_SZ_BYTES(raw_queue_in); + int ret = 0; + void *q_out; + int qid; + int result; + u8 st = 0; + + inlen += CRETE_FLD_SZ_BYTES(raw_queue_in, qid[0]); + outlen += CRETE_FLD_SZ_BYTES(raw_queue_out, q_result[0]); + + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + crete_err(cdev->device, "in vzalloc failed %d\n", inlen); + goto err; + } + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + crete_err(cdev->device, "out vzalloc failed %d\n", outlen); + goto err; + } + + CRETE_SET16(raw_queue_in, in, cmd_op, 1); + CRETE_SET16(raw_queue_in, in, cmd_id, ops); + + CRETE_ARRAY_SET(raw_queue_in, in, qid, 0, queueid); + + ret = crete_cmd_exec_polling(cdev, in, inlen, out, outlen); + if (ret < 0) + goto err; + + st = CRETE_GET(raw_queue_out, out, status); + crete_info(cdev->device, "st[%d]\n", st); + + q_out = CRETE_ADDR_OF(raw_queue_out, out, q_result); + qid = CRETE_GET_PR(queue_result, q_out, qid); + result = CRETE_GET_PR(queue_result, q_out, result); + crete_info(cdev->device, "Complete :rx_qid[%d] result[%d]\n", qid, result); + + kvfree(in); + kvfree(out); + return 0; +err: + kvfree(in); + kvfree(out); + return ret; +} + +int crete_enable_singlequeue(struct crete_core_dev *cdev, u16 queueid) +{ + return crete_singlequeue_rawcmd(cdev, queueid, CRETE_CMD_ENABLE_QUEUE); +} + +int crete_disable_singlequeue(struct crete_core_dev *cdev, u16 queueid) +{ + return crete_singlequeue_rawcmd(cdev, queueid, CRETE_CMD_DISABLE_QUEUE); +} + + +int crete_get_q_state(struct crete_core_dev *cdev, u16 op) +{ + u32 *in, *out; + int outlen = CRETE_ST_SZ_BYTES(get_q_state_out); + int inlen = CRETE_ST_SZ_BYTES(get_q_state_in); + int ret = 0; + void *q_out; + int qid; + int result; + u8 st = 0; + int i = 0; + + if (op <= 0 || op > 128) { + crete_err(cdev->device, "reset queue num is illegal\n"); + return -EINVAL; + } + + inlen += op * CRETE_FLD_SZ_BYTES(get_q_state_in, qid[0]); + outlen += op * CRETE_FLD_SZ_BYTES(get_q_state_out, q_result[0]); + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + crete_err(cdev->device, "in vzalloc failed %d\n", inlen); + goto err; + } + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + crete_err(cdev->device, "out vzalloc failed %d\n", outlen); + goto err; + } + + CRETE_SET(get_q_state_in, in, cmd_op, op); + CRETE_SET(get_q_state_in, in, cmd_id, CRETE_CMD_GET_Q_STATE); + + for (i = 0; i < op; i++) + CRETE_ARRAY_SET(get_q_state_in, in, qid, i, i); + + ret = crete_cmd_exec_polling(cdev, in, inlen, out, outlen); + if (ret < 0) + goto err; + + st = CRETE_GET(get_q_state_out, out, status); + crete_info(cdev->device, "st[%d]\n", st); + + q_out = CRETE_ADDR_OF(get_q_state_out, out, q_result); + for (i = 0; i < op; i++, q_out += CRETE_ST_SZ_BYTES(queue_result)) { + qid = CRETE_GET_PR(queue_result, q_out, qid); + result = CRETE_GET_PR(queue_result, q_out, result); + crete_info(cdev->device, "Complete :rx_qid[%d] result[%d]\n", + qid, result); + } + kvfree(in); + kvfree(out); + return 0; + +err: + kvfree(in); + kvfree(out); + return ret; + +} + +EXPORT_SYMBOL(crete_get_q_state); + +int crete_set_port_trust_status(struct crete_core_dev *cdev, u8 trust_status, + u8 port_id) +{ + u32 in[CRETE_ST_SZ_DW(set_port_trust_status_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_port_trust_status_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_port_trust_status_in, in, cmd_id, + CRETE_CMD_SET_PORT_TRUST_STATUS); + CRETE_SET(set_port_trust_status_in, in, port_id, port_id); + CRETE_SET(set_port_trust_status_in, in, trust_status, trust_status); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_port_trust_status_out, out, status); + crete_info(cdev->device, "st[%d] trust_status[%d] port_id[%d]\n", + st, trust_status, port_id); + return 0; +} +EXPORT_SYMBOL(crete_set_port_trust_status); + +#define CRETE_CMD_PCP_BIT_WIDTH 0x4 +#define CRETE_CMD_PCP_TC_MASK 0x7 +#define CRETE_CMD_PCP_EN_SHIFT 0x3 +int crete_set_pcp_map_tc(struct crete_core_dev *cdev, u8 port_id, + struct pcp_configuration *pcp_conf) +{ + u32 in[CRETE_ST_SZ_DW(set_pcp_map_tc_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_pcp_map_tc_out)] = { 0 }; + u32 pcp, value; + int ret = 0; + u8 st = 0; + int i, offset; + + CRETE_SET(set_pcp_map_tc_in, in, cmd_id, CRETE_CMD_SET_PCP_MAP_TC); + CRETE_SET(set_pcp_map_tc_in, in, port_id, port_id); + + for (i = 0; i < CRETE_SUPPORTED_PCP; i++) { + offset = i * CRETE_CMD_PCP_BIT_WIDTH; + value = (pcp_conf[i].tc & CRETE_CMD_PCP_TC_MASK) | + ((pcp_conf[i].en & 0x1) << CRETE_CMD_PCP_EN_SHIFT); + pcp |= (value << offset); + } + CRETE_SET(set_pcp_map_tc_in, in, pcp, pcp); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_pcp_map_tc_out, out, status); + crete_info(cdev->device, "set_pcp_map_tc st[%d]\n", st); + return 0; +} + +EXPORT_SYMBOL(crete_set_pcp_map_tc); + +int crete_set_dscp_map_tc(struct crete_core_dev *cdev, u8 port_id, + struct dscp_configuration *dscp_conf) +{ + int sz = CRETE_ST_SZ_BYTES(set_dscp_map_tc_in); + u32 out[CRETE_ST_SZ_DW(set_dscp_map_tc_out)] = { 0 }; + int err; + void *in; + u8 st = 0; + u32 qdscp, value; + int i, j, offset, dscp_index; + + in = kzalloc(sz, GFP_KERNEL); + if (!in) { + err = -ENOMEM; + goto out; + } + + CRETE_SET(set_dscp_map_tc_in, in, cmd_id, CRETE_CMD_SET_DSCP_MAP_TC); + CRETE_SET(set_dscp_map_tc_in, in, port_id, port_id); + + for (i = 0; i < CRETE_CMD_QDSCP_NUM; i++) { + value = 0; + offset = 0; + for (j = 0; j < CRETE_CMD_QSCP_NUM_PERQ; j++) { + dscp_index = i * CRETE_CMD_QSCP_NUM_PERQ + j; + offset = j * CRETE_CMD_DSCP_BIT_WIDTH; + value = + (dscp_conf[dscp_index].tc & CRETE_CMD_DSCP_TC_MASK) | + ((dscp_conf[dscp_index].en & 0x1) << CRETE_CMD_DSCP_EN_SHIFT); + qdscp |= (value << offset); + } + CRETE_ARRAY_SET(set_dscp_map_tc_in, in, qdscp, i, qdscp); + } + + err = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (err) + crete_info(cdev->device, "CRETE_CMD_SET_DSCP_MAP_TC err[%d]", + err); + + st = CRETE_GET(set_dscp_map_tc_out, out, status); + crete_info(cdev->device, "set_dscp_map_tc st[%d]\n", st); + +out: + kfree(in); + return err; +} + +EXPORT_SYMBOL(crete_set_dscp_map_tc); + +int crete_set_fc_enable(struct crete_core_dev *cdev, u8 port_id, u32 rx_fc_en, + u32 tx_fc_en) +{ + u32 in[CRETE_ST_SZ_DW(set_fc_enable_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_fc_enable_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_fc_enable_in, in, cmd_id, CRETE_CMD_SET_FC_ENABLE); + CRETE_SET(set_fc_enable_in, in, port_id, port_id); + CRETE_SET(set_fc_enable_in, in, rx_fc_en, rx_fc_en); + CRETE_SET(set_fc_enable_in, in, tx_fc_en, tx_fc_en); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_fc_enable_out, out, status); + crete_info(cdev->device, "st[%d] rx_fc_en[%d] tx_fc_en[%d]\n", st, + rx_fc_en, tx_fc_en); + return 0; +} +EXPORT_SYMBOL(crete_set_fc_enable); + +int crete_get_pfc_enable(struct crete_core_dev *cdev, u8 *rx_pfc_en, + u8 *tx_pfc_en) +{ +// u32 in[CRETE_ST_SZ_DW(get_pfc_enable_in)] = {0}; +// u32 out[CRETE_ST_SZ_DW(get_pfc_enable_out)] = {0}; +// int ret = 0; +// u8 st = 0; +// +// CRETE_SET(get_pfc_enable_in, in, cmd_id, CRETE_CMD_GET_PFC_ENABLE); +// CRETE_SET(get_pfc_enable_in, in, port_id, 1); +// +// +// ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); +// if (ret < 0) +// return ret; +// +// st = CRETE_GET(get_pfc_enable_out, out, status); +// crete_info(cdev->device, "st[%d] rx_pfc_en[%d] tx_pfc_en[%d]\n", st, rx_pfc_en, tx_pfc_en); + if (rx_pfc_en) + *rx_pfc_en = 0; + if (tx_pfc_en) + *tx_pfc_en = 0; + + return 0; +} + +EXPORT_SYMBOL(crete_get_pfc_enable); + +int crete_set_pfc_enable(struct crete_core_dev *cdev, u8 port_id, u8 rx_pfc_en, + u8 tx_pfc_en) +{ + u32 in[CRETE_ST_SZ_DW(set_pfc_enable_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_pfc_enable_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_pfc_enable_in, in, cmd_id, CRETE_CMD_SET_PFC_ENABLE); + CRETE_SET(set_pfc_enable_in, in, port_id, port_id); + CRETE_SET(set_pfc_enable_in, in, rx_pfc_en, rx_pfc_en); + CRETE_SET(set_pfc_enable_in, in, tx_pfc_en, tx_pfc_en); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_pfc_enable_out, out, status); + crete_info(cdev->device, "st[%d] rx_pfc_en[%d] tx_pfc_en[%d]\n", st, + rx_pfc_en, tx_pfc_en); + return 0; +} + +EXPORT_SYMBOL(crete_set_pfc_enable); + +int crete_set_ets(struct crete_core_dev *cdev, u8 port_id, + struct tc_configuration *tc_conf) +{ + u32 in[CRETE_ST_SZ_DW(set_ets_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_ets_out)] = { 0 }; + int err; + u8 st = 0; + void *tc_configuration; + int i; + + CRETE_SET(set_ets_in, in, cmd_id, CRETE_CMD_SET_ETS); + CRETE_SET(set_ets_in, in, port_id, port_id); + + for (i = 0; i <= 8; i++) { + tc_configuration = + CRETE_ADDR_OF(set_ets_in, in, tc_configuration[i]); + CRETE_SET(set_tc_configuration, tc_configuration, weight, + tc_conf[i].weight); + CRETE_SET(set_tc_configuration, tc_configuration, unit, + tc_conf[i].unit); + CRETE_SET(set_tc_configuration, tc_configuration, unit, + tc_conf[i].unit); + CRETE_SET(set_tc_configuration, tc_configuration, maxrate, + tc_conf[i].maxrate); + } + + err = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (err) + crete_info(cdev->device, "CRETE_CMD_SET_ETS err[%d]", err); + + st = CRETE_GET(set_ets_out, out, status); + crete_info(cdev->device, "set_ets st[%d]", st); + + return err; +} + +EXPORT_SYMBOL(crete_set_ets); + +/* crete set status function + * in: crete_cmd_start_q_in_bits + * out: crete_cmd_start_q_out_bits + * notice: single queue + */ +int crete_start_singlequeue(struct crete_core_dev *cdev, u16 queueid) +{ + u32 *in, *out; + int outlen = CRETE_ST_SZ_BYTES(start_q_out); + int inlen = CRETE_ST_SZ_BYTES(start_q_in); + void *q_out; + int qid; + int result; + int ret = 0; + u8 st = 0; + + inlen += CRETE_FLD_SZ_BYTES(start_q_in, qid[0]); + outlen += CRETE_FLD_SZ_BYTES(start_q_out, q_result[0]); + + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + crete_err(cdev->device, "in vzalloc failed %d\n", inlen); + goto err; + } + + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + crete_err(cdev->device, "out vzalloc failed %d\n", outlen); + goto err; + } + + CRETE_SET16(start_q_in, in, cmd_id, CRETE_CMD_ENABLE_QUEUE); + CRETE_SET16(start_q_in, in, cmd_op, 1); /* default num is 1 */ + + CRETE_ARRAY_SET(start_q_in, in, qid, 0, queueid); + + ret = crete_cmd_exec_polling(cdev, in, inlen, out, outlen); + if (ret < 0) + goto err; + + st = CRETE_GET(start_q_out, out, status); + crete_info(cdev->device, "st[%d]\n", st); + + q_out = CRETE_ADDR_OF(start_q_out, out, q_result); + qid = CRETE_GET_PR(queue_result, q_out, qid); + result = CRETE_GET_PR(queue_result, q_out, result); + crete_info(cdev->device, "Complete :rx_qid[%d] result[%d]\n", qid, + result); + + kvfree(in); + kvfree(out); + return 0; + +err: + kvfree(in); + kvfree(out); + return ret; + +} +EXPORT_SYMBOL(crete_start_singlequeue); + +int crete_get_sop_padding(struct crete_core_dev *cdev, u32 *sop_padding_status) +{ + u32 in[CRETE_ST_SZ_DW(get_sop_padding_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(get_sop_padding_out)] = {0}; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_sop_padding_in, in, cmd_id, CRETE_CMD_GET_SOP_PADDING); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_sop_padding_out, out, status); + *sop_padding_status = CRETE_GET(get_sop_padding_out, out, sop_padding_status); + crete_info(cdev->device, "st[%d] sop_padding_status[%d]\n", st, *sop_padding_status); + + return 0; +} +EXPORT_SYMBOL(crete_get_sop_padding); + +int crete_set_sop_padding(struct crete_core_dev *cdev, u32 op) +{ + u32 in[CRETE_ST_SZ_DW(set_sop_padding_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(set_sop_padding_out)] = {0}; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_sop_padding_in, in, cmd_id, CRETE_CMD_SET_SOP_PADDING); + CRETE_SET(set_sop_padding_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_sop_padding_out, out, status); + crete_info(cdev->device, "st[%d] sop_padding op[%d]\n", st, op); + return 0; +} +EXPORT_SYMBOL(crete_set_sop_padding); + +int crete_get_auto_suppress(struct crete_core_dev *cdev, u32 *auto_suppress_status) +{ + u32 in[CRETE_ST_SZ_DW(get_auto_suppress_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(get_auto_suppress_out)] = {0}; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_auto_suppress_in, in, cmd_id, CRETE_CMD_GET_AUTO_SUPPRESS); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_auto_suppress_out, out, status); + *auto_suppress_status = CRETE_GET(get_auto_suppress_out, out, auto_suppress_status); + crete_info(cdev->device, "st[%d] auto_suppress_status[%d]\n", st, *auto_suppress_status); + + return 0; +} +EXPORT_SYMBOL(crete_get_auto_suppress); + +int crete_set_auto_suppress(struct crete_core_dev *cdev, u32 op) +{ + u32 in[CRETE_ST_SZ_DW(set_auto_suppress_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(set_auto_suppress_out)] = {0}; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_auto_suppress_in, in, cmd_id, CRETE_CMD_SET_AUTO_SUPPRESS); + CRETE_SET(set_auto_suppress_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_auto_suppress_out, out, status); + crete_info(cdev->device, "st[%d] auto_suppress op[%d]\n", st, op); + return 0; +} +EXPORT_SYMBOL(crete_set_auto_suppress); + +int crete_get_tx_inorder(struct crete_core_dev *cdev, u32 *tx_inorder_status) +{ + u32 in[CRETE_ST_SZ_DW(get_tx_inorder_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(get_tx_inorder_out)] = {0}; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_tx_inorder_in, in, cmd_id, CRETE_CMD_GET_TX_INORDER); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_tx_inorder_out, out, status); + *tx_inorder_status = CRETE_GET(get_tx_inorder_out, out, tx_inorder_status); + crete_info(cdev->device, "st[%d] tx_inorder_status[%d]\n", st, *tx_inorder_status); + + return 0; +} +EXPORT_SYMBOL(crete_get_tx_inorder); + +int crete_set_tx_inorder(struct crete_core_dev *cdev, u32 op) +{ + u32 in[CRETE_ST_SZ_DW(set_tx_inorder_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(set_tx_inorder_out)] = {0}; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_tx_inorder_in, in, cmd_id, CRETE_CMD_SET_TX_INORDER); + CRETE_SET(set_tx_inorder_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_tx_inorder_out, out, status); + crete_info(cdev->device, "st[%d] set tx_inorder op[%d]\n", st, op); + return 0; +} +EXPORT_SYMBOL(crete_set_tx_inorder); + + +int crete_get_rx_merge(struct crete_core_dev *cdev, u32 *rx_merge_status) +{ + u32 in[CRETE_ST_SZ_DW(get_rx_merge_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(get_rx_merge_out)] = {0}; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_rx_merge_in, in, cmd_id, CRETE_CMD_GET_RX_MERGE); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_rx_merge_out, out, status); + *rx_merge_status = CRETE_GET(get_rx_merge_out, out, rx_merge_status); + crete_info(cdev->device, "st[%d] rx_merge_status[%d]\n", st, *rx_merge_status); + + return 0; +} +EXPORT_SYMBOL(crete_get_rx_merge); + +int crete_set_rx_merge(struct crete_core_dev *cdev, u32 op) +{ + u32 in[CRETE_ST_SZ_DW(set_rx_merge_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(set_rx_merge_out)] = {0}; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_rx_merge_in, in, cmd_id, CRETE_CMD_SET_RX_MERGE); + CRETE_SET(set_rx_merge_in, in, opcode, op); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_rx_merge_out, out, status); + crete_info(cdev->device, "st[%d] set rx_merge op[%d]\n", st, op); + return 0; +} +EXPORT_SYMBOL(crete_set_rx_merge); + +int crete_get_dev_sfi(struct crete_core_dev *cdev, u16 opcode, u32 pf_id, u16 *sfi) +{ + u32 in[CRETE_ST_SZ_DW(get_sfi_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(get_sfi_out)] = {0}; + int ret = 0; + u8 st = 0; + + CRETE_SET(get_sfi_in, in, cmd_id, CRETE_CMD_GET_SFI); + CRETE_SET(get_sfi_in, in, opcode, opcode); + CRETE_SET(get_sfi_in, in, pf_id, pf_id); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_sfi_out, out, status); + if (st != SUCCESS) { + u8 err_type = CRETE_GET(get_sfi_out, out, err_type); + + crete_err(cdev->device, "Get dev sfi failed, err type:0x%x\n", err_type); + return -1; + } + + *sfi = (u16)CRETE_GET(get_sfi_out, out, sfi); + crete_info(cdev->device, "st[%d] [%u]\n", st, *sfi); + + return 0; +} +EXPORT_SYMBOL(crete_get_dev_sfi); + +int crete_get_dev_macattr(struct crete_core_dev *cdev, struct sockaddr *addr) +{ + u32 in[CRETE_ST_SZ_DW(get_dev_attr_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_dev_attr_out)] = { 0 }; + u8 st = 0; + int ret = 0; + int i = 0; + u32 mac_low; + u16 mac_high; + + CRETE_SET(get_dev_attr_in, in, cmd_id, CRETE_CMD_VPORT_ATTR_GET); + CRETE_SET(get_dev_attr_in, in, sfi, cdev->sfi_id); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_dev_attr_out, out, status); + mac_low = CRETE_GET(get_dev_attr_out, out, def_mac1); + mac_high = CRETE_GET(get_dev_attr_out, out, def_mac2); + + addr->sa_data[i++] = (mac_high >> 8) & 0xff; + addr->sa_data[i++] = mac_high & 0xff; + addr->sa_data[i++] = (mac_low >> 24) & 0xff; + addr->sa_data[i++] = (mac_low >> 16) & 0xff; + addr->sa_data[i++] = (mac_low >> 8) & 0xff; + addr->sa_data[i++] = mac_low & 0xff; + + st = CRETE_GET(get_dev_attr_out, out, status); + crete_info(cdev->device, "st[%d] get mac addr:%x:%x:%x:%x:%x:%x\n", + st, addr->sa_data[0], addr->sa_data[1], addr->sa_data[2], + addr->sa_data[3], addr->sa_data[4], addr->sa_data[5]); + + if (st != SUCCESS) { + u8 err_type = CRETE_GET(get_dev_attr_out, out, err_type); + + crete_err(cdev->device, "Get dev attr failed, err type:0x%x\n", err_type); + return -1; + } + + return 0; +} +EXPORT_SYMBOL(crete_get_dev_macattr); + +int crete_get_dev_linkattr(struct crete_core_dev *cdev, bool *linkstat) +{ + u32 in[CRETE_ST_SZ_DW(get_dev_attr_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_dev_attr_out)] = { 0 }; + u8 st = 0; + int ret = 0; + u8 linkstats = 0; + + CRETE_SET(get_dev_attr_in, in, cmd_id, CRETE_CMD_VPORT_ATTR_GET); + CRETE_SET(get_dev_attr_in, in, sfi, cdev->sfi_id); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + linkstats = CRETE_GET(get_dev_attr_out, out, link_state); + st = CRETE_GET(get_dev_attr_out, out, status); + crete_info(cdev->device, "st[%d] linkstatus %d\n", st, linkstats); + + if (st != SUCCESS) { + u8 err_type = CRETE_GET(get_dev_attr_out, out, err_type); + + crete_err(cdev->device, "Get dev attr failed, err type:0x%x\n", err_type); + return -1; + } + + *linkstat = !!linkstats; + + return 0; +} +EXPORT_SYMBOL(crete_get_dev_linkattr); + +int crete_set_vq_mig_state(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, u16 qid, u16 last_used) +{ + u32 in[CRETE_ST_SZ_DW(set_vq_mig_state_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_vq_mig_state_out)] = { 0 }; + int ret; + + CRETE_SET(set_vq_mig_state_in, in, cmd_id, CRETE_CMD_SET_VQ_MIG_STATE); + CRETE_SET(set_vq_mig_state_in, in, cmd_op, op); + CRETE_SET(set_vq_mig_state_in, in, qid, qid); + CRETE_SET(set_vq_mig_state_in, in, last_used, last_used); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + crete_info(cdev->device, "set vq mig last_used [%d] qid %d\n", + last_used, qid); + return 0; +} +EXPORT_SYMBOL(crete_set_vq_mig_state); + +int crete_get_vq_mig_state_batch(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, + u8 start_qid, u8 qnum, u16 *last_used_set) +{ + u32 in[CRETE_ST_SZ_DW(get_vq_mig_state_batch_in)] = { 0 }; + //u32 out[CRETE_ST_SZ_DW(get_vq_mig_state_batch_out)] = { 0 }; + int out_len = CRETE_ST_SZ_BYTES(get_vq_mig_state_batch_out); + void *out, *out_res; + int ret, i; + u8 status; + + CRETE_SET(get_vq_mig_state_batch_in, in, cmd_id, CRETE_CMD_GET_VQ_MIG_STATE_BATCH); + CRETE_SET(get_vq_mig_state_batch_in, in, cmd_op, op); + CRETE_SET(get_vq_mig_state_batch_in, in, start_qid, start_qid); + CRETE_SET(get_vq_mig_state_batch_in, in, queues, qnum); + + out_len += qnum * CRETE_ST_SZ_BYTES(get_vq_mig_state_batch_result); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + return ret; + } + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, out_len); + if (ret <0) + goto err_out; + + status = CRETE_GET(get_vq_mig_state_batch_out, out, status); + if (status != SUCCESS) { + /* can't get last avail index from hardware */ + crete_err(cdev->device, "crete get vq mig state batch failed. status %d\n", status); + ret = -EINVAL; + } + + out_res = CRETE_ADDR_OF(get_vq_mig_state_batch_out, out, last_used_array); + for (i = 0; i < qnum; i++) { + u16 last_index = CRETE_GET(get_vq_mig_state_batch_result, out_res, last_index); + *(last_used_set + i) = last_index; + out_res += CRETE_ST_SZ_BYTES(get_vq_mig_state_batch_result); + } +err_out: + if (out) + kvfree(out); + + return ret; +} +EXPORT_SYMBOL(crete_get_vq_mig_state_batch); + +int crete_get_vq_mig_state(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, u16 qid, u16 *last_used) +{ + u32 in[CRETE_ST_SZ_DW(get_vq_mig_state_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_vq_mig_state_out)] = { 0 }; + u16 qid_out; + int ret; + + CRETE_SET(get_vq_mig_state_in, in, cmd_id, CRETE_CMD_GET_VQ_MIG_STATE); + CRETE_SET(get_vq_mig_state_in, in, cmd_op, op); + CRETE_SET(get_vq_mig_state_in, in, qid, qid); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + *last_used = CRETE_GET(get_vq_mig_state_out, out, last_used); + qid_out = CRETE_GET(get_vq_mig_state_out, out, qid); + crete_info(cdev->device, "get vq mig last_used [%d] qid [%d] %d\n", + *last_used, qid_out, qid); + + return 0; +} +EXPORT_SYMBOL(crete_get_vq_mig_state); + +int crete_set_mig_log_state(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, u16 log_state) +{ + u32 in[CRETE_ST_SZ_DW(set_mig_log_state_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_mig_log_state_out)] = { 0 }; + int ret; + + CRETE_SET(set_mig_log_state_in, in, cmd_id, CRETE_CMD_SET_MIG_LOG_STATE); + CRETE_SET(set_mig_log_state_in, in, cmd_op, op); + CRETE_SET(set_mig_log_state_in, in, state, log_state); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + crete_info(cdev->device, "set vq mig log state [%d]\n", + log_state); + return 0; +} +EXPORT_SYMBOL(crete_set_mig_log_state); + +int crete_set_mig_log_base(struct crete_core_dev *cdev, + enum crete_mig_dev_type_opcode op, u8 group_size, + u32 log_base_lo, u32 log_base_hi, + u32 iova0_addr_lo, u32 iova0_addr_hi, + u32 iova0_size_lo, u32 iova0_size_hi) +{ + u32 in[CRETE_ST_SZ_DW(set_mig_log_base_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_mig_log_base_out)] = { 0 }; + int ret; + + CRETE_SET(set_mig_log_base_in, in, cmd_id, CRETE_CMD_SET_MIG_LOG_BASE); + CRETE_SET(set_mig_log_base_in, in, cmd_op, op); + + CRETE_SET(set_mig_log_base_in, in, group_size, group_size); + + CRETE_SET(set_mig_log_base_in, in, log_base_lo, log_base_lo); + CRETE_SET(set_mig_log_base_in, in, log_base_hi, log_base_hi); + + CRETE_SET(set_mig_log_base_in, in, iova0_addr_lo, iova0_addr_lo); + CRETE_SET(set_mig_log_base_in, in, iova0_addr_hi, iova0_addr_hi); + + CRETE_SET(set_mig_log_base_in, in, iova0_size_lo, iova0_size_lo); + CRETE_SET(set_mig_log_base_in, in, iova0_size_hi, iova0_size_hi); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + crete_info(cdev->device, "set mig log base 0x%08x%08x " + "iova addr 0x%08x%08x iova size 0x%08x%08x group size %d\n", + log_base_hi, log_base_lo, iova0_addr_hi, iova0_addr_lo, + iova0_size_hi, iova0_size_lo, group_size); + return 0; +} +EXPORT_SYMBOL(crete_set_mig_log_base); + +int crete_set_qp_num(struct crete_core_dev *cdev, u32 qpnum) +{ + u32 in[CRETE_ST_SZ_DW(set_qpnum_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_qpnum_out)] = { 0 }; + u8 st = 0; + int ret = 0; + + CRETE_SET(set_qpnum_in, in, cmd_id, CRETE_CMD_SET_QP_NUM); + CRETE_SET(set_qpnum_in, in, qp_num, qpnum); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_qpnum_out, out, status); + + if (st != SUCCESS) { + u8 err_type = CRETE_GET(set_qpnum_out, out, err_type); + + crete_err(cdev->device, "Set qp number failed, err type:0x%x\n", err_type); + return -1; + } + + return 0; +} +EXPORT_SYMBOL(crete_set_qp_num); + +int crete_set_trust_vf(struct crete_core_dev *core_dev, u16 vfsfi_id, u16 trust_state) +{ + u32 in[CRETE_ST_SZ_DW(set_trust_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_trust_out)] = { 0 }; + int ret = 0, status = 0, err_type = 0; + + CRETE_SET(set_trust_in, in, cmd_id, CRETE_CMD_SET_TRUST); + + CRETE_SET(set_trust_in, in, svport_id, core_dev->sfi_id); + CRETE_SET(set_trust_in, in, dvport_id, vfsfi_id); + CRETE_SET(set_trust_in, in, trust_state, trust_state); + + ret = crete_cmd_exec_polling(core_dev, in, sizeof(in), out, sizeof(out)); + if (ret < 0){ + crete_err(core_dev->device, "%s , ret:0x%x\n", __func__, ret); + return ret; + } + + status = CRETE_GET(set_trust_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_trust_out, out, err_type); + crete_err(core_dev->device, "pf (%u) set vnic trust vf (%u) failed, err type:0x%x status:0x%x\n", + core_dev->sfi_id, vfsfi_id, err_type, status); + ret = -EINVAL; + } + return ret; +} +EXPORT_SYMBOL(crete_set_trust_vf); + +int crete_get_port_statistics(struct crete_core_dev *core_dev, struct crete_port_statistics *port_statistics) +{ + int ret = 0; + if(port_statistics){ + port_statistics->rx_pkts = 1; + port_statistics->rx_bytes = 1; + port_statistics->tx_pkts = 1; + port_statistics->tx_bytes = 1; + } + return ret; +} +EXPORT_SYMBOL(crete_get_port_statistics); + +int crete_set_port_mtu(struct crete_core_dev *core_dev, u16 opcode, u32 new_mtu) +{ + u32 in[CRETE_ST_SZ_DW(set_mtu_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_mtu_out)] = { 0 }; + int ret = 0, status = 0, err_type = 0; + + CRETE_SET(set_mtu_in, in, cmd_id, CRETE_CMD_SET_MTU); + CRETE_SET(set_mtu_in, in, cmd_op, opcode); + CRETE_SET(set_mtu_in, in, svport_id, core_dev->sfi_id); + CRETE_SET(set_mtu_in, in, dvport_id, core_dev->sfi_id); + CRETE_SET(set_mtu_in, in, mtu, new_mtu); + + ret = crete_cmd_exec_polling(core_dev, in, sizeof(in), out, sizeof(out)); + if (ret < 0){ + crete_err(core_dev->device, "%s , ret:0x%x\n", __func__, ret); + return ret; + } + + status = CRETE_GET(set_mtu_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_mtu_out, out, err_type); + crete_err(core_dev->device, "set port (%u) mtu failed, err type:0x%x status:0x%x\n", + core_dev->sfi_id, err_type, status); + ret = -EINVAL; + } + return ret; +} +EXPORT_SYMBOL(crete_set_port_mtu); + +int crete_get_vport_pkt_statistics(struct crete_core_dev *core_dev, u16 opcode, + struct crete_port_statistics *port_statis) +{ + u32 in[CRETE_ST_SZ_DW(get_vport_pkt_stats_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_vport_pkt_stats_out)] = { 0 }; + int ret = 0, status = 0, err_type = 0; + u64 temp = 0; + + CRETE_SET(get_vport_pkt_stats_in, in, cmd_id, CRETE_CMD_GET_VPORT_PKT_STAT); + CRETE_SET(get_vport_pkt_stats_in, in, cmd_op, opcode); + CRETE_SET(get_vport_pkt_stats_in, in, vport_id, core_dev->sfi_id); + + ret = crete_cmd_exec_polling(core_dev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) { + crete_err(core_dev->device, "%s , ret:0x%x\n", __func__, ret); + return ret; + } + + status = CRETE_GET(get_vport_pkt_stats_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(get_vport_pkt_stats_out, out, err_type); + crete_err(core_dev->device, "get port (%u) phy statistics failed, err type:0x%x status:0x%x\n", + core_dev->sfi_id, err_type, status); + ret = -EINVAL; + } + + if (port_statis) { + temp = CRETE_GET(get_vport_pkt_stats_out, out, tx_pkts_h); + temp = temp << 32; + temp += CRETE_GET(get_vport_pkt_stats_out, out, tx_pkts_l); + port_statis->tx_pkts = temp; + + temp = CRETE_GET(get_vport_pkt_stats_out, out, tx_bytes_h); + temp = temp << 32; + temp += CRETE_GET(get_vport_pkt_stats_out, out, tx_bytes_l); + port_statis->tx_bytes = temp; + + temp = CRETE_GET(get_vport_pkt_stats_out, out, rx_pkts_h); + temp = temp << 32; + temp += CRETE_GET(get_vport_pkt_stats_out, out, rx_pkts_l); + port_statis->rx_pkts = temp; + + temp = CRETE_GET(get_vport_pkt_stats_out, out, rx_bytes_h); + temp = temp << 32; + temp += CRETE_GET(get_vport_pkt_stats_out, out, rx_bytes_l); + port_statis->rx_bytes = temp; + } + + return 0; +} +EXPORT_SYMBOL(crete_get_vport_pkt_statistics); + +int crete_get_port_speed_duplex(struct crete_core_dev *cdev, struct crete_speed_duplex *sd) +{ + u32 in[CRETE_ST_SZ_DW(get_port_speed_duplex_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_port_speed_duplex_out)] = { 0 }; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_port_speed_duplex_in, in, cmd_id, + CRETE_CMD_GET_PORT_SPEED_DUPLEX_MODE); + CRETE_SET(get_port_speed_duplex_in, in, vport_id, cdev->sfi_id); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_port_speed_duplex_out, out, status); + if (st != SUCCESS) { + u8 err_type = CRETE_GET(get_port_speed_duplex_out, out, err_type); + + crete_err(cdev->device, "get speed duplex failed, err type:0x%x\n", err_type); + return -1; + } + + sd->speed = CRETE_GET(get_port_speed_duplex_out, out, speed); + sd->duplex = CRETE_GET(get_port_speed_duplex_out, out, duplex_mode); + sd->duplex_cap = CRETE_GET(get_port_speed_duplex_out, out, duplex_cap); + sd->speed_cap = CRETE_GET(get_port_speed_duplex_out, out, speed_cap); + + return 0; +} +EXPORT_SYMBOL(crete_get_port_speed_duplex); + +int crete_set_port_speed_duplex(struct crete_core_dev *cdev, u16 link_mode, u16 duplex, u16 op_bit) +{ + u32 in[CRETE_ST_SZ_DW(set_port_speed_duplex_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_port_speed_duplex_out)] = { 0 }; + u8 st = 0; + int ret = 0; + + CRETE_SET(set_port_speed_duplex_in, in, cmd_id, + CRETE_CMD_SET_PORT_SPEED_DUPLEX_MODE); + CRETE_SET(set_port_speed_duplex_in, in, cmd_op, op_bit); + CRETE_SET(set_port_speed_duplex_in, in, vport_id, cdev->sfi_id); + CRETE_SET(set_port_speed_duplex_in, in, speed, link_mode); + CRETE_SET(set_port_speed_duplex_in, in, duplex_mode, duplex); + + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_port_speed_duplex_out, out, status); + if (st != SUCCESS) { + u8 err_type = CRETE_GET(set_port_speed_duplex_out, out, err_type); + + crete_err(cdev->device, "get speed duplex failed, err type:0x%x\n", err_type); + return -1; + } + + return 0; +} +EXPORT_SYMBOL(crete_set_port_speed_duplex); + +int crete_get_fec_mode(struct crete_core_dev *cdev, u16 *fec_mode, u16 *fec_cap) +{ + u32 in[CRETE_ST_SZ_DW(get_port_fec_mode_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(get_port_fec_mode_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(get_port_fec_mode_in, in, cmd_id, CRETE_CMD_GET_PORT_FEC_MODE); + CRETE_SET(get_port_fec_mode_in, in, vport_id, cdev->sfi_id); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_port_fec_mode_out, out, status); + if (st != SUCCESS) { + u8 err_type = CRETE_GET(get_port_fec_mode_out, out, err_type); + + crete_err(cdev->device, "get fec mode failed, err type:0x%x\n", err_type); + return -1; + } + + *fec_mode = CRETE_GET(get_port_fec_mode_out, out, fec_mode); + *fec_cap = CRETE_GET(get_port_fec_mode_out, out, fec_cap); + return 0; +} +EXPORT_SYMBOL(crete_get_fec_mode); + +int crete_set_fec_mode(struct crete_core_dev *cdev, u16 fec_mode) +{ + u32 in[CRETE_ST_SZ_DW(set_port_fec_mode_in)] = { 0 }; + u32 out[CRETE_ST_SZ_DW(set_port_fec_mode_out)] = { 0 }; + int ret = 0; + u8 st = 0; + + CRETE_SET(set_port_fec_mode_in, in, cmd_id, CRETE_CMD_SET_PORT_FEC_MODE); + CRETE_SET(get_port_fec_mode_in, in, vport_id, cdev->sfi_id); + CRETE_SET(set_port_fec_mode_in, in, fec_mode, fec_mode); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(set_port_fec_mode_out, out, status); + if (st != SUCCESS) { + u8 err_type = CRETE_GET(set_port_fec_mode_out, out, err_type); + + crete_err(cdev->device, "set fec mode failed, err type:0x%x\n", err_type); + return -1; + } + + return 0; +} +EXPORT_SYMBOL(crete_set_fec_mode); + +int crete_get_vf_mac(struct crete_core_dev *cdev, u8 *mac) +{ + u32 in[CRETE_ST_SZ_DW(get_vf_mac_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(get_vf_mac_out)] = {0}; + u8 st = 0; + int ret = 0; + + CRETE_SET(get_vf_mac_in, in, cmd_id, CRETE_CMD_GET_VF_MAC); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(get_vf_mac_out, out, status); + if (st != SUCCESS) { + u8 err_type = CRETE_GET(get_vf_mac_out, out, err_type); + crete_err(cdev->device, "get vf mac failed, err type:0x%x\n", err_type); + return -1; + } + + mac[0] = CRETE_GET(get_vf_mac_out, out, mac0); + mac[1] = CRETE_GET(get_vf_mac_out, out, mac1); + mac[2] = CRETE_GET(get_vf_mac_out, out, mac2); + mac[3] = CRETE_GET(get_vf_mac_out, out, mac3); + mac[4] = CRETE_GET(get_vf_mac_out, out, mac4); + mac[5] = CRETE_GET(get_vf_mac_out, out, mac5); + + return 0; +} + +EXPORT_SYMBOL(crete_get_vf_mac); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd_if.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd_if.h new file mode 100644 index 0000000..fbc9470 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_cmd_if.h @@ -0,0 +1,1242 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CRETE_CMD_IF_H +#define _CRETE_CMD_IF_H + +#include "crete_cmd.h" +#include "crete_dcb_nl.h" +#include "crete_ethtool_common.h" +#include +#include + + +enum crete_status_opcode { + CRETE_NET_DEV_STATUS = 1, + CRETE_NET_OFFLOAD_STATUS, + CRETE_RDMA_STATUS, +}; +enum crete_reset_opcode { + CRETE_RESET_ALL_DEV, + CRETE_RESET_NET_DEV, + CRETE_RESET_NETOFF_DEV, +}; +enum crete_stop_opcode { + CRETE_STOP_ALL_DEV, + CRETE_STOP_NET_DEV, + CRETE_STOP_NETOFF_DEV, +}; +enum crete_restore_opcode { + CRETE_RESTORE_ALL_DEV, + CRETE_RESTORE_NET_DEV, + CRETE_RESTORE_NETOFF_DEV, +}; + +enum crete_feature_opcode { + CRETE_NET_DEV_FEAT, + CRETE_VIRTIO_NET_DEV_FEAT, + CRETE_OFFLOAD_FEAT, + CRETE_RDMA_FEAT, + CRETE_GLOBAL_FEAT, + CRETE_CURRENT_DEV_FEAT = 0x8000, +}; + +enum crete_dev_type { + CRETE_VNET_DEV, + CRETE_JNET_DEV, +}; + +enum crete_lag_opcode { + CRETE_CREATE_LAG, + CRETE_MODIFY_LAG, + CRETE_QUERY_LAG, + CRETE_DESTROY_LAG, +}; + +enum crete_mig_dev_type_opcode { + CRETE_MIG_DEV_VIRTIO = 0x1, +}; + +enum crete_rx_mode_cmdop { + CRETE_RX_MODE_SETMULMODE, + CRETE_RX_MODE_UC_MAC_LIST_ADD, + CRETE_RX_MODE_UC_MAC_LIST_DEL, + CRETE_RX_MODE_MC_MAC_LIST_ADD, + CRETE_RX_MODE_MC_MAC_LIST_DEL +}; + +/* cmd struct */ +struct crete_cmd_get_status_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_status_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 dev_status[0x20]; +}; + +struct crete_cmd_reset_dev_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_reset_dev_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_stop_dev_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_stop_dev_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_restore_dev_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_restore_dev_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_status_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + u8 dev_status[0x20]; +}; + +struct crete_cmd_set_status_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_feat_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_feat_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 feat_bits_lo[0x20]; // virtio 8 bytes + u8 feat_bits_hi[0x20]; +}; + +struct crete_cmd_set_feat_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + u8 feat_bits_lo[0x20]; // virtio 8 bytes + u8 feat_bits_hi[0x20]; +}; + +struct crete_cmd_set_feat_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_dev_type_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_dev_type_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 dev_type[0x20]; +}; + +struct crete_cmd_set_dev_type_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + u8 dev_type[0x20]; +}; + +struct crete_cmd_set_dev_type_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + + +struct crete_cmd_reset_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_reset_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +/* QP */ +struct crete_cmd_qp_cap_bits { + u8 ctrl_q_size[8]; + u8 max_qp_num[8]; + u8 max_queue_size[0x10]; +}; + +struct crete_cmd_get_qp_cap_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_qp_cap_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_qp_cap_bits qp_cap; +}; + + +struct crete_cmd_qp_context_bits { + u8 rx_qid[0x10]; + u8 event_credit[0x10]; + u8 rx_sq_size[0x10]; + u8 rx_cq_size[0x10]; + u8 tx_sq_size[0x10]; + u8 tx_cq_size[0x10]; + u8 rx_q_vec[0x10]; + u8 tx_q_vec[0x10]; + u8 rx_sq_base[0x40]; + u8 rx_cq_base[0x40]; + u8 tx_sq_base[0x40]; + u8 tx_cq_base[0x40]; +}; + +struct crete_cmd_qp_result_bits { + u8 rx_qid[0x10]; + u8 result[0x10]; +}; + +struct crete_cmd_create_qp_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + struct crete_cmd_qp_context_bits qp_context[]; +}; + +struct crete_cmd_create_qp_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_qp_result_bits qp_result[]; +}; + +/* vnet create ctrlq */ +struct crete_cmd_queue_context_bits { + u8 qid[0x10]; + u8 event_credit[0x10]; + u8 sq_size[0x10]; + u8 cq_size[0x10]; + u8 resv1[0x10]; + u8 queue_vec[0x10]; + u8 sq_base_lo[0x20]; + u8 sq_base_hi[0x20]; + u8 cq_base_lo[0x20]; + u8 cq_base_hi[0x20]; +}; + +struct crete_cmd_queue_result_bits { + u8 qid[0x10]; + u8 result[0x10]; +}; + +struct crete_cmd_create_q_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + struct crete_cmd_queue_context_bits q_context[]; +}; + +struct crete_cmd_create_q_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_queue_result_bits q_result[]; +}; + +struct crete_cmd_reset_queue_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 qid[][0x20]; +}; + +struct crete_cmd_reset_queue_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_queue_result_bits q_result[]; +}; + +struct crete_cmd_get_lag_cap_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + u8 vport_id[0x10]; + u8 resv[0x10]; +}; + +struct crete_cmd_get_lag_cap_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; + u8 lag_master[0x8]; + u8 lag_id[0x8]; + u8 mode_support[0x8]; + u8 hash_type[0x8]; + u8 num_ports[0x8]; + u8 pf_id[0x8]; + u8 resv[0x10]; +}; + +struct crete_cmd_lag_context_bits { + u8 lag_id[0x8]; + u8 lag_mode[0x8]; + u8 hash_type[0x8]; + u8 lu_te_num[0x8]; + u8 lu_te_mem[4][0x10]; + u8 resv[0x40]; +}; + +struct crete_cmd_create_lag_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + struct crete_cmd_lag_context_bits lag_context[]; +}; + +struct crete_cmd_create_lag_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; +}; + +struct crete_cmd_modify_lag_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + struct crete_cmd_lag_context_bits lag_context[]; +}; + +struct crete_cmd_modify_lag_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; +}; + +struct crete_cmd_destroy_lag_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + struct crete_cmd_lag_context_bits lag_context[]; +}; + +struct crete_cmd_destroy_lag_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; +}; + + +struct crete_cmd_get_q_state_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 qid[][0x20]; +}; + +struct crete_cmd_get_q_state_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_queue_result_bits q_result[]; +}; + +struct crete_cmd_vlan_range_bits { + u8 start_vlan[0x10]; + u8 end_vlan[0x10]; +}; +struct crete_cmd_mc_mac_list_bits { + u8 mc_mac[0x30]; +}; +struct crete_cmd_uc_mac_list_bits { + u8 uc_mac[0x30]; +}; + +struct crete_cmd_get_dev_attr_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 sfi[0x20]; +}; + +struct crete_cmd_get_dev_attr_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 vnic_id[0x10]; + u8 flow_ver[0x10]; + u8 fw_ver[0x100]; + u8 def_mac1[0x20]; + u8 def_mac2[0x10]; + u8 is_pf[0x1]; + u8 is_trust[0x1]; + u8 mac_portid[0x3]; + u8 lag_id[0x3]; + u8 lag_en[0x1]; + u8 link_state[0x1]; + u8 is_sriov[0x1]; + u8 is_vf0[0x1]; + u8 rsvd[0x4]; +}; + +enum crete_get_dev_sfi_opcode { + CRETE_GET_SFI_CURR, + CRETE_GET_SFI_BDF, + CRETE_GET_SFI_VF, +}; + +struct crete_cmd_get_sfi_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + u8 pf_id[0x20]; +}; + +struct crete_cmd_get_sfi_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; + u8 sfi[0x20]; +}; + +struct crete_cmd_set_rx_mode_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 cmd_resv[0x8]; + u8 vlan_filter_mode[0x2]; + u8 vlan_strip[0x1]; + u8 vlan_fliter[0x1]; + u8 promiscuous[0x1]; + u8 broadcast[0x1]; + u8 all_multicast[0x1]; + u8 multicast[0x1]; + u8 vport_id[0x10]; + /*offset 08h*/ + u8 vlan_tpid[0x10]; + u8 vlan_range_num[0x8]; + u8 mc_list_num[0x8]; + /*offset 0ch*/ + struct crete_cmd_vlan_range_bits vlan_range_list[]; + //struct crete_cmd_mc_mac_list_bits mc_mac_list[]; +};/* pading to DW */ + +struct crete_cmd_set_rx_mode_new_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 svport_id[0x10]; + u8 dvport_id[0x10]; + u8 mc_list_num[0x8]; + u8 uc_list_num[0x8]; + u8 rsvd1[0x7]; + u8 vlan_insert[0x1]; + u8 vst_flag[0x1]; + u8 vlan_filter_mode[0x2]; + u8 vlan_strip[0x1]; + u8 vlan_filter[0x1]; + u8 promiscuous[0x1]; + u8 broadcast[0x1]; + u8 all_mmulticast[0x1]; + u8 vlan_tp_id[0x10]; + u8 rsvd2[0x8]; + u8 vlan_range_num[0x8]; + struct crete_cmd_uc_mac_list_bits uc_mac_list[]; +}; + +struct crete_cmd_set_rx_mode_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_uc_mac_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 cmd_resv[0x8]; + u8 uc_list_num[0x8]; + u8 vport_id[0x10]; + /*offset 08h*/ + struct crete_cmd_uc_mac_list_bits uc_mac_list[]; +};/* pading to DW */ + +struct crete_cmd_set_uc_mac_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_vport_link_state_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 link_state[0x10]; + u8 vport_id[0x10]; +}; + +struct crete_cmd_set_vport_link_state_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_vport_link_state_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_vport_link_state_out_bits { + u8 err_type[0x18]; + u8 status[8]; + /*offset 04h*/ + u8 link_state[0x10]; + u8 vport_id[0x10]; +}; + +struct crete_cmd_set_vport_trust_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 trust_state[0x10]; + u8 vport_id[0x10]; +}; + +struct crete_cmd_set_vport_trust_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_vport_trust_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 cmd_resv[0x10]; + u8 vport_id[0x10]; +}; + +struct crete_cmd_get_vport_trust_out_bits { + u8 err_type[0x18]; + u8 status[8]; + /*offset 04h*/ + u8 trust_state[0x20]; +}; + +struct crete_cmd_set_trust_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 svport_id[0x10]; + u8 dvport_id[0x10]; + /*offset 08h*/ + u8 trust_state[0x10]; + u8 Rsvd[0x10]; +}; + +struct crete_cmd_set_trust_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_vport_spoof_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 spoof_state[0x10]; + u8 vport_id[0x10]; +}; + +struct crete_cmd_set_vport_spoof_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_vf_shaper_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 mode[0x10]; + u8 vport_id[0x10]; + + /*offset 08h*/ + u8 max_rate[0x20]; +}; + +struct crete_cmd_set_vf_shaper_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_port_trust_status_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 trust_status[0x1]; + u8 resv1[0xf]; + u8 port_id[0x2]; + u8 resv2[0xe]; +}; + +struct crete_cmd_set_port_trust_status_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_pcp_map_tc_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 resv1[0x10]; + u8 port_id[0x2]; + u8 resv2[0xe]; + u8 pcp[0x20]; +}; + +struct crete_cmd_set_pcp_map_tc_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_dscp_map_tc_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 resv1[0x10]; + u8 port_id[0x2]; + u8 resv2[0xe]; + u8 qdscp[CRETE_CMD_QDSCP_NUM][0x20]; +}; + +struct crete_cmd_set_dscp_map_tc_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_fc_enable_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 resv1[0x10]; + u8 port_id[0x2]; + u8 resv2[0xe]; + u8 tx_fc_en[0x10]; + u8 rx_fc_en[0x10]; +}; + +struct crete_cmd_set_fc_enable_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_pfc_enable_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 resv1[0x10]; + u8 port_id[0x2]; + u8 resv2[0xe]; + u8 tx_pfc_en[0x10]; + u8 rx_pfc_en[0x10]; +}; + +struct crete_cmd_set_pfc_enable_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_set_tc_configuration_bits { + u8 weight[0x6]; + u8 unit[0x4]; + u8 resv1[0x6]; + u8 pg_id[0x4]; + u8 resv2[0x9]; + u8 g[0x1]; + u8 b[0x1]; + u8 r[0x1]; + u8 maxrate[0x20]; +}; + +struct crete_cmd_set_ets_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 resv1[0x10]; + u8 port_id[0x2]; + u8 resv2[0xe]; + struct crete_cmd_set_tc_configuration_bits tc_configuration[8]; +}; + +struct crete_cmd_set_ets_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_start_q_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 qid[][0x20]; +}; + +struct crete_cmd_start_q_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_queue_result_bits q_result[]; +}; + +/* netdev group */ + +struct crete_cmd_set_sop_padding_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_set_sop_padding_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_sop_padding_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_sop_padding_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 sop_padding_status[0x20]; +}; + +struct crete_cmd_set_auto_suppress_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_set_auto_suppress_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_auto_suppress_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_auto_suppress_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 auto_suppress_status[0x20]; +}; + +struct crete_cmd_set_tx_inorder_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_set_tx_inorder_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_tx_inorder_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_tx_inorder_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 tx_inorder_status[0x20]; +}; + +struct crete_cmd_set_rx_merge_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_set_rx_merge_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_rx_merge_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_rx_merge_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 rx_merge_status[0x20]; +}; + +struct crete_cmd_raw_queue_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 qid[][0x20]; +}; + +struct crete_cmd_raw_queue_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_queue_result_bits q_result[]; +}; + +/* migration command */ +struct crete_cmd_get_vq_mig_state_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 qid[0x10]; + u8 resv[0x10]; +}; + +struct crete_cmd_get_vq_mig_state_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 qid[0x10]; + u8 last_used[0x10]; +}; + +struct crete_cmd_get_vq_mig_state_batch_result_bits { + u8 last_index[0x10]; +}; + +struct crete_cmd_get_vq_mig_state_batch_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 start_qid[0x8]; + u8 queues[0x8]; + u8 resv[0x10]; +}; + +struct crete_cmd_get_vq_mig_state_batch_out_bits { + u8 err_type[0x18]; + u8 status[8]; + struct crete_cmd_get_vq_mig_state_batch_result_bits last_used_array[]; +}; + +struct crete_cmd_set_vq_mig_state_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 qid[0x10]; + u8 last_used[0x10]; +}; + +struct crete_cmd_set_vq_mig_state_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; +}; + +struct crete_cmd_set_mig_log_base_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 group_size[0x8]; + u8 resv[0x18]; + u8 log_base_lo[0x20]; + u8 log_base_hi[0x20]; + u8 iova0_addr_lo[0x20]; + u8 iova0_addr_hi[0x20]; + u8 iova0_size_lo[0x20]; + u8 iova0_size_hi[0x20]; + /* TODO: should define array */ +}; + +struct crete_cmd_set_mig_log_base_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; +}; + +struct crete_cmd_set_mig_log_state_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 state[0x10]; + u8 resv[0x10]; +}; + +struct crete_cmd_set_mig_log_state_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; +}; + +struct crete_cmd_set_qpnum_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 qp_num[0x20]; +}; + +struct crete_cmd_set_qpnum_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; +}; + +/* firmware update */ +struct crete_cmd_fwu_lock_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 flag[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_fwu_lock_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 status_inner[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_fwu_pkey_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 flag[0x10]; + u8 len[0x10]; + u8 hashkey[16][0x20]; +}; + +struct crete_cmd_fwu_pkey_out_bits { + u8 err_type[0x18]; + u8 status[8]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 status_inner[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_fwu_ver_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 flag[0x10]; + u8 len[0x10]; + u8 comp_list[][0x10]; +}; + +struct crete_cmd_version_list_bits { + u8 version[0x20]; + u8 version_efuse[0x20]; +}; + +struct crete_cmd_fwu_ver_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 status_inner[0x10]; + u8 len[0x10]; + struct crete_cmd_version_list_bits version_list[]; +}; + +struct crete_cmd_fwu_xfer_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 flag[0x10]; + u8 len[0x10]; + u8 offset[0x20]; + u8 crc[0x20]; + u8 data[][0x20]; +}; + +struct crete_cmd_fwu_xfer_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 status_inner[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_fwu_end_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 flag[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_fwu_end_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 status_inner[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_fwu_unlock_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 flag[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_fwu_unlock_out_bits { + u8 err_type[0x18]; + u8 status[0x8]; + u8 cmd[0x10]; + u8 seq_id[0x10]; + u8 status_inner[0x10]; + u8 pad[0x10]; +}; + +struct crete_cmd_get_vport_pkt_stats_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 vport_id[0x10]; + u8 resv[0x10]; +}; + +struct crete_cmd_get_vport_pkt_stats_out_bits { + /*offset 00h*/ + u8 err_type[0x18]; + u8 status[0x08]; + /*offset 04h*/ + u8 tx_pkts_l[0x20]; + u8 tx_pkts_h[0x20]; + u8 tx_bytes_l[0x20]; + u8 tx_bytes_h[0x20]; + /*offset 14h*/ + u8 rx_pkts_l[0x20]; + u8 rx_pkts_h[0x20]; + u8 rx_bytes_l[0x20]; + u8 rx_bytes_h[0x20]; +}; + +struct crete_port_statistics { + uint64_t tx_pkts; + uint64_t tx_bytes; + + uint64_t rx_pkts; + uint64_t rx_bytes; +}; + +struct crete_cmd_set_mtu_in_bits { + /*offset 00h*/ + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + /*offset 04h*/ + u8 svport_id[0x10]; + u8 dvport_id[0x10]; + /*offset 08h*/ + u8 mtu[0x20]; +}; + +struct crete_cmd_set_mtu_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_lag_enable_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; + u8 vport_id[0x10]; + u8 lag_enable[0x10]; +}; + +struct crete_cmd_lag_enable_out_bits { + u8 err_type[0x18]; + u8 status[8]; +}; + +struct crete_cmd_get_port_speed_duplex_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 vport_id[0x10]; + u8 resv[0x10]; +}; + +struct crete_cmd_get_port_speed_duplex_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; + u8 speed[0x10]; + u8 duplex_mode[0x10]; + u8 duplex_cap[0x20]; + u8 speed_cap[0x20]; +}; + +struct crete_cmd_set_port_speed_duplex_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 vport_id[0x10]; + u8 autoneg[0x10]; + u8 speed[0x10]; + u8 duplex_mode[0x10]; +}; + +struct crete_cmd_set_port_speed_duplex_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; +}; + +struct crete_cmd_get_port_fec_mode_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 vport_id[0x10]; + u8 resv[0x10]; +}; + +struct crete_cmd_get_port_fec_mode_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; + u8 fec_mode[0x10]; + u8 fec_cap[0x10]; +}; + +struct crete_cmd_set_port_fec_mode_in_bits { + u8 cmd_op[0x10]; + u8 cmd_id[0x10]; + u8 vport_id[0x10]; + u8 fec_mode[0x10]; +}; + +struct crete_cmd_set_port_fec_mode_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; +}; + +struct crete_cmd_get_vf_mac_in_bits { + u8 opcode[0x10]; + u8 cmd_id[0x10]; +}; + +struct crete_cmd_get_vf_mac_out_bits { + u8 err_type[0x18]; + u8 status[0x08]; + u8 mac0[0x08]; + u8 mac1[0x08]; + u8 mac2[0x08]; + u8 mac3[0x08]; + u8 mac4[0x08]; + u8 mac5[0x08]; + u8 resv[0x10]; +}; + +/* function cmd */ +int crete_get_status(struct crete_core_dev *cdev, enum crete_status_opcode op, + u8 *status); +int crete_set_status(struct crete_core_dev *cdev, enum crete_status_opcode op, + u32 status); + +int crete_cmd_get_features(struct crete_core_dev *cdev, enum crete_feature_opcode op, + netdev_features_t *feat_bits); +int crete_cmd_set_features(struct crete_core_dev *cdev, enum crete_feature_opcode op, + netdev_features_t feat_bits); +int crete_get_dev_type(struct crete_core_dev *cdev, u32 *dev_type); +int crete_set_dev_type(struct crete_core_dev *cdev, u32 dev_type); +int crete_reset_dev(struct crete_core_dev *cdev, enum crete_reset_opcode op); +int crete_stop_dev(struct crete_core_dev *cdev, enum crete_stop_opcode op); +int crete_restore_dev(struct crete_core_dev *cdev, enum crete_restore_opcode op); + +/* qp cmd */ +int crete_create_txrxqp(struct crete_core_dev *cdev, u16 qid); +//int crete_get_qp_cap(struct crete_core_dev *cdev); +int crete_get_qp_cap(struct crete_core_dev *cdev, + u16 *max_queue_size, + u8 *max_qp_num, + u8 *ctrl_queue_size); +int crete_create_queue(struct crete_core_dev *cdev, u16 num_q); +int crete_create_qp_one(struct crete_core_dev *cdev); +int crete_create_qp(struct crete_core_dev *cdev, u16 num_qp); +int crete_reset_queue(struct crete_core_dev *cdev, u16 op); +int crete_get_q_state(struct crete_core_dev *cdev, u16 op); + +int crete_get_pfc_enable(struct crete_core_dev *cdev, u8 *rx_pfc_en, u8 *tx_pfc_en); +int crete_set_pfc_enable(struct crete_core_dev *cdev, u8 port_id, u8 rx_pfc_en, u8 tx_pfc_en); +int crete_set_fc_enable(struct crete_core_dev *cdev, u8 port_id, u32 rx_fc_en, u32 tx_fc_en); + +/* netdev group */ +int crete_get_sop_padding(struct crete_core_dev *cdev, u32 *sop_padding_status); +int crete_set_sop_padding(struct crete_core_dev *cdev, u32 op); +int crete_get_auto_suppress(struct crete_core_dev *cdev, u32 *auto_suppress_status); +//int crete_set_auto_suppress(struct crete_core_dev *cdev, u32 op); +int crete_get_tx_inorder(struct crete_core_dev *cdev, u32 *tx_inorder_status); +int crete_set_tx_inorder(struct crete_core_dev *cdev, u32 op); +int crete_get_rx_merge(struct crete_core_dev *cdev, u32 *rx_merge_status); +int crete_set_rx_merge(struct crete_core_dev *cdev, u32 op); + +int crete_start_singlequeue(struct crete_core_dev *cdev, u16 queueid); +int crete_cmd_create_signal_queue(struct crete_core_dev *cdev, struct crete_queue_context *qctx); +int crete_cmd_create_qp(struct crete_core_dev *cdev, struct crete_qp_context *qpctx); +int crete_reset_singlequeue(struct crete_core_dev *cdev, u16 queueid); +int crete_singlequeue_rawcmd(struct crete_core_dev *cdev, u16 queueid, int ops); + +int crete_enable_singlequeue(struct crete_core_dev *cdev, u16 queueid); + +int crete_disable_singlequeue(struct crete_core_dev *cdev, u16 queueid); + +int crete_set_vq_mig_state(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, u16 qid, u16 last_used); +int crete_get_vq_mig_state(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, u16 qid, u16 *last_used); +int crete_set_mig_log_state(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, u16 log_state); + +int crete_set_mig_log_base(struct crete_core_dev *cdev, + enum crete_mig_dev_type_opcode op, u8 group_size, + u32 log_base_lo, u32 log_base_hi, + u32 iova0_addr_lo, u32 iova0_addr_hi, + u32 iova0_size_lo, u32 iova0_size_hi); + +int crete_get_dev_sfi(struct crete_core_dev *cdev, u16 opcode, u32 pf_id, u16 *sfi); +int crete_get_dev_macattr(struct crete_core_dev *cdev, struct sockaddr *addr); +int crete_get_dev_linkattr(struct crete_core_dev *cdev, bool *linkstat); +int crete_set_qp_num(struct crete_core_dev *cdev, u32 qpnum); +int crete_get_port_speed_duplex(struct crete_core_dev *cdev, + struct crete_speed_duplex *sd); +int crete_set_port_speed_duplex(struct crete_core_dev *cdev, u16 link_mode, u16 duplex, u16 op_bit); +int crete_set_trust_vf(struct crete_core_dev *core_dev, u16 vfsfi_id, u16 trust_state); +int crete_get_port_statistics(struct crete_core_dev *core_dev, struct crete_port_statistics *port_statistics); +int crete_set_port_mtu(struct crete_core_dev *core_dev, u16 opcode, u32 new_mtu); +int crete_get_vport_pkt_statistics(struct crete_core_dev *core_dev, u16 opcode, + struct crete_port_statistics *port_statis); +int crete_get_fec_mode(struct crete_core_dev *cdev, u16 *fec_mode, u16 *fec_cap); +int crete_set_fec_mode(struct crete_core_dev *cdev, u16 fec_mode); +int crete_get_vq_mig_state_batch(struct crete_core_dev *cdev, enum crete_mig_dev_type_opcode op, + u8 start_qid, u8 qnum, u16 *last_used_set); + +int crete_get_vf_mac(struct crete_core_dev *cdev, u8 *mac); +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_core_debugfs.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_core_debugfs.c new file mode 100644 index 0000000..aecaa4a --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_core_debugfs.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include "crete.h" + +struct dentry *crete_debugfs_root; +EXPORT_SYMBOL(crete_debugfs_root); + +void crete_register_debugfs(void) +{ + crete_debugfs_root = debugfs_create_dir("crete", NULL); +} + +void crete_unregister_debugfs(void) +{ + debugfs_remove(crete_debugfs_root); +} + +struct dentry *crete_debugfs_get_dev_root(struct crete_core_dev *dev) +{ + return dev->dbg.dbg_root; +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_dcb_nl.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_dcb_nl.c new file mode 100644 index 0000000..4910553 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_dcb_nl.c @@ -0,0 +1,1200 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include "crete_cmd_if.h" +#include "crete.h" + +#define CRETE_MAX_PRIORITY (8) +#define CRETE_MAX_TC (8) +#define CRETE_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */ +enum { + CRETE_LOWEST_PRIO_GROUP = 0, + CRETE_VENDOR_TC_GROUP_NUM = 7, +}; + +#define CRETE_CEE_STATE_UP 1 +#define CRETE_CEE_STATE_DOWN 0 + +enum { + CRETE_DCB_CHG_RESET, + CRETE_DCB_NO_CHG, + CRETE_DCB_CHG_NO_RESET, +}; + +int crete_query_port_prio_tc(struct crete_core_dev *cdev, + u8 prio, u8 *tc) +{ + *tc = 0; + /* TODO */ + return 0; +} + +int crete_query_port_tc_group(struct crete_core_dev *cdev, + u8 tc, u8 *tc_group) +{ + *tc_group = 0; + return 0; +} + +int crete_query_port_tc_bw_alloc(struct crete_core_dev *cdev, + u8 tc, u8 *bw_pct) +{ + *bw_pct = 0; + return 0; +} + +static int crete_dcbnl_ieee_getets(struct net_device *netdev, + struct ieee_ets *ets) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *cdev = priv->coredev; + u8 tc_group[IEEE_8021QAZ_MAX_TCS]; + bool is_tc_group_6_exist = false; + bool is_zero_bw_ets_tc = false; + int err = 0; + int i; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + err = crete_query_port_prio_tc(cdev, i, &ets->prio_tc[i]); + if (err) + return err; + } + + ets->ets_cap = CRETE_MAX_TC; + for (i = 0; i < ets->ets_cap; i++) { + err = crete_query_port_tc_group(cdev, i, &tc_group[i]); + if (err) + return err; + + err = crete_query_port_tc_bw_alloc(cdev, i, &ets->tc_tx_bw[i]); + if (err) + return err; + + if (ets->tc_tx_bw[i] < CRETE_MAX_BW_ALLOC && + tc_group[i] == (CRETE_LOWEST_PRIO_GROUP + 1)) + is_zero_bw_ets_tc = true; + + if (tc_group[i] == (CRETE_VENDOR_TC_GROUP_NUM - 1)) + is_tc_group_6_exist = true; + } + + /* Report 0% ets tc if exits*/ + if (is_zero_bw_ets_tc) { + for (i = 0; i < ets->ets_cap; i++) + if (tc_group[i] == CRETE_LOWEST_PRIO_GROUP) + ets->tc_tx_bw[i] = 0; + } + + /* Update tc_tsa based on fw setting*/ + for (i = 0; i < ets->ets_cap; i++) { + if (ets->tc_tx_bw[i] < CRETE_MAX_BW_ALLOC) + priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS; + else if (tc_group[i] == CRETE_VENDOR_TC_GROUP_NUM && + !is_tc_group_6_exist) + priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR; + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + return 0; +} + +static void crete_build_tc_group(struct ieee_ets *ets, u8 *tc_group) +{ + bool any_tc_mapped_to_ets = false; + bool ets_zero_bw = false; + int strict_group; + int i; + + for (i = 0; i < CRETE_MAX_TC; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { + any_tc_mapped_to_ets = true; + if (!ets->tc_tx_bw[i]) + ets_zero_bw = true; + } + } + + /* strict group has higher priority than ets group */ + strict_group = CRETE_LOWEST_PRIO_GROUP; + if (any_tc_mapped_to_ets) + strict_group++; + if (ets_zero_bw) + strict_group++; + + for (i = 0; i < CRETE_MAX_TC; i++) { + switch (ets->tc_tsa[i]) { + case IEEE_8021QAZ_TSA_VENDOR: + tc_group[i] = CRETE_VENDOR_TC_GROUP_NUM; + break; + case IEEE_8021QAZ_TSA_STRICT: + tc_group[i] = strict_group++; + break; + case IEEE_8021QAZ_TSA_ETS: + tc_group[i] = CRETE_LOWEST_PRIO_GROUP; + if (ets->tc_tx_bw[i] && ets_zero_bw) + tc_group[i] = CRETE_LOWEST_PRIO_GROUP + 1; + break; + } + } +} + +static void crete_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw, + u8 *tc_group) +{ + int bw_for_ets_zero_bw_tc = 0; + int last_ets_zero_bw_tc = -1; + int num_ets_zero_bw = 0; + int i; + + for (i = 0; i < CRETE_MAX_TC; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS && + !ets->tc_tx_bw[i]) { + num_ets_zero_bw++; + last_ets_zero_bw_tc = i; + } + } + + if (num_ets_zero_bw) + bw_for_ets_zero_bw_tc = CRETE_MAX_BW_ALLOC / num_ets_zero_bw; + + for (i = 0; i < CRETE_MAX_TC; i++) { + switch (ets->tc_tsa[i]) { + case IEEE_8021QAZ_TSA_VENDOR: + tc_tx_bw[i] = CRETE_MAX_BW_ALLOC; + break; + case IEEE_8021QAZ_TSA_STRICT: + tc_tx_bw[i] = CRETE_MAX_BW_ALLOC; + break; + case IEEE_8021QAZ_TSA_ETS: + tc_tx_bw[i] = ets->tc_tx_bw[i] ? + ets->tc_tx_bw[i] : + bw_for_ets_zero_bw_tc; + break; + } + } + + /* Make sure the total bw for ets zero bw group is 100% */ + if (last_ets_zero_bw_tc != -1) + tc_tx_bw[last_ets_zero_bw_tc] += + CRETE_MAX_BW_ALLOC % num_ets_zero_bw; +} + +int crete_set_port_tc_group(struct crete_core_dev *cdev, u8 *tc_group) +{ + u32 in[CRETE_ST_SZ_DW(set_ets_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(set_ets_out)] = {0}; + int i, err; + u8 status; + + CRETE_SET(set_ets_in, in, cmd_id, CRETE_CMD_SET_ETS); + CRETE_SET(set_ets_in, in, port_id, 1); + + for (i = 0; i < CRETE_MAX_TC; i++) { + CRETE_SET(set_ets_in, in, tc_configuration[i].g, 1); + CRETE_SET(set_ets_in, in, tc_configuration[i].pg_id, tc_group[i]); + } + + err = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (err) + crete_info(cdev->device, "CRETE_CMD_SET_ETS tc_group err[%d]", err); + + status = CRETE_GET(set_ets_out, out, status); + crete_info(cdev->device, "set_ets tc_group st[%d]\n", status); + + return err; +} +EXPORT_SYMBOL_GPL(crete_set_port_tc_group); + +int crete_set_port_tc_bw_alloc(struct crete_core_dev *cdev, u8 *tc_bw) +{ + u32 in[CRETE_ST_SZ_DW(set_ets_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(set_ets_out)] = {0}; + int i, err; + u8 status; + + CRETE_SET(set_ets_in, in, cmd_id, CRETE_CMD_SET_ETS); + CRETE_SET(set_ets_in, in, port_id, 1); + + for (i = 0; i < CRETE_MAX_TC; i++) { + CRETE_SET(set_ets_in, in, tc_configuration[i].b, 1); + CRETE_SET(set_ets_in, in, tc_configuration[i].weight, tc_bw[i]); + } + + err = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (err) + crete_info(cdev->device, "CRETE_CMD_SET_ETS tc_group err[%d]", err); + + status = CRETE_GET(set_ets_out, out, status); + crete_info(cdev->device, "set_ets bw_alloc st[%d]\n", status); + + return err; +} +EXPORT_SYMBOL_GPL(crete_set_port_tc_bw_alloc); + +int crete_query_port_ets_rate_limit(struct crete_core_dev *cdev, + u8 *max_bw_value, + u8 *max_bw_units) +{ + int i; + + //TODO GET FROM FIREWARE + for (i = 0; i < CRETE_MAX_TC; i++) { + max_bw_value[i] = 0; + max_bw_units[i] = 0; + } + + return 0; +} +EXPORT_SYMBOL_GPL(crete_query_port_ets_rate_limit); + +int crete_modify_port_ets_rate_limit(struct crete_core_dev *cdev, + u8 *max_bw_value, + u8 *max_bw_units) +{ + u32 in[CRETE_ST_SZ_DW(set_ets_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(set_ets_out)] = {0}; + void *ets_tc_conf; + int i, err; + u8 status; + + CRETE_SET(set_ets_in, in, cmd_id, CRETE_CMD_SET_ETS); + CRETE_SET(set_ets_in, in, port_id, 1); + + for (i = 0; i < CRETE_MAX_TC; i++) { + ets_tc_conf = CRETE_ADDR_OF(set_ets_in, in, tc_configuration[i]); + + CRETE_SET(set_tc_configuration, ets_tc_conf, r, 1); + CRETE_SET(set_tc_configuration, ets_tc_conf, unit, max_bw_units[i]); + CRETE_SET(set_tc_configuration, ets_tc_conf, maxrate, max_bw_value[i]); + } + + err = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (err) + crete_info(cdev->device, "CRETE_CMD_SET_ETS tc_group err[%d]", err); + + status = CRETE_GET(set_ets_out, out, status); + crete_info(cdev->device, "set_ets tc_group st[%d]\n", status); + + return err; +} +EXPORT_SYMBOL_GPL(crete_modify_port_ets_rate_limit); + +static int crete_dcbnl_ieee_setets_core(struct crete_priv *priv, struct ieee_ets *ets) +{ + struct crete_core_dev *cdev = priv->coredev; + u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS]; + u8 tc_group[IEEE_8021QAZ_MAX_TCS]; + int err, i; + + crete_build_tc_group(ets, tc_group); + crete_build_tc_tx_bw(ets, tc_tx_bw, tc_group); + +// err = crete_set_port_prio_tc(cdev, ets->prio_tc); +// if (err) +// return err; + + err = crete_set_port_tc_group(cdev, tc_group); + if (err) + return err; + + err = crete_set_port_tc_bw_alloc(cdev, tc_tx_bw); + if (err) + return err; + + memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa)); + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + netdev_dbg(priv->netdev, "%s: prio_%d <=> tc_%d\n", + __func__, i, ets->prio_tc[i]); + netdev_dbg(priv->netdev, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n", + __func__, i, tc_tx_bw[i], tc_group[i]); + } + + return err; +} + +static int crete_dcbnl_validate_ets(struct net_device *netdev, + struct ieee_ets *ets, + bool zero_sum_allowed) +{ + bool have_ets_tc = false; + int bw_sum = 0; + int i; + + /* Validate Priority */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->prio_tc[i] >= CRETE_MAX_PRIORITY) { + netdev_err(netdev, + "Failed to validate ETS: priority value greater than max(%d)\n", + CRETE_MAX_PRIORITY); + return -EINVAL; + } + } + + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { + have_ets_tc = true; + bw_sum += ets->tc_tx_bw[i]; + } + } + + if (have_ets_tc && bw_sum != 100) { + if (bw_sum || (!bw_sum && !zero_sum_allowed)) + netdev_err(netdev, + "Failed to validate ETS: BW sum is illegal\n"); + return -EINVAL; + } + return 0; +} +static int crete_dcbnl_ieee_setets(struct net_device *netdev, + struct ieee_ets *ets) +{ + struct crete_priv *priv = netdev_priv(netdev); + int err; + + err = crete_dcbnl_validate_ets(netdev, ets, false); + if (err) + return err; + + err = crete_dcbnl_ieee_setets_core(priv, ets); + if (err) + return err; + + return 0; +} + +static int crete_dcbnl_ieee_getmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *cdev = priv->coredev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + int err; + int i; + + err = crete_query_port_ets_rate_limit(cdev, max_bw_value, max_bw_unit); + if (err) + return err; + + memset(maxrate->tc_maxrate, 0, sizeof(maxrate->tc_maxrate)); + + for (i = 0; i < CRETE_MAX_TC; i++) { + switch (max_bw_unit[i]) { + case CRETE_DISABLE_MAXRATE: + break; + case CRETE_KBPS_UNIT: + break; + case CRETE_MBPS_UNIT: + break; + case CRETE_GBPS_UNIT: + break; + case CRETE_PPS_UNIT: + break; + case CRETE_KPPS_UNIT: + break; + case CRETE_MPPS_UNIT: + break; + default: + netdev_dbg(netdev, "non-supported BW unit"); + break; + } + } + + return 0; +} +static int crete_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *coredev = priv->coredev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + + for (i = 0; i < CRETE_MAX_TC; i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = CRETE_DISABLE_MAXRATE; + continue; + } + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + CRETE_1GB); + + max_bw_unit[i] = CRETE_GBPS_UNIT; + } + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n", + __func__, i, max_bw_value[i]); + } + + return crete_modify_port_ets_rate_limit(coredev, max_bw_value, max_bw_unit); + +} +static int crete_dcbnl_ieee_getpfc(struct net_device *netdev, + struct ieee_pfc *pfc) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *cdev = priv->coredev; + int i; + + pfc->pfc_cap = CRETE_MAX_TC; + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + pfc->requests[i] = 0; + pfc->indications[i] = 0; + } + + return crete_get_pfc_enable(cdev, &pfc->pfc_en, NULL); +} +static int crete_dcbnl_ieee_setpfc(struct net_device *netdev, + struct ieee_pfc *pfc) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *cdev = priv->coredev; + int ret; + + /* pfc_en */ + // crete_query_port_pfc(cdev, &curr_pfc_en, NULL); + + ret = crete_set_pfc_enable(cdev, 1, pfc->pfc_en, pfc->pfc_en); + if (ret) + return ret; + + netdev_err(netdev, " debuging %s stub\n", __func__); + return 0; +} + +static int crete_update_trust_state_hw(struct crete_priv *priv, u8 trust_state) +{ + struct crete_core_dev *cdev = priv->coredev; + u32 in[CRETE_ST_SZ_DW(set_port_trust_status_in)] = {}; + u32 out[CRETE_ST_SZ_DW(set_port_trust_status_out)] = {}; + int ret, st; + + CRETE_SET(set_port_trust_status_in, in, port_id, 1); + CRETE_SET(set_port_trust_status_in, in, trust_status, trust_state); + + ret = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (ret) + return ret; + + st = CRETE_GET(set_port_trust_status_out, out, status); + crete_info(cdev->device, "st[%d] trust_status[%d]\n", st, trust_state); + + WRITE_ONCE(priv->dcbx_dp.trust_state, trust_state); + + return 0; +} + +static int crete_set_trust_state(struct crete_priv *priv, u8 trust_state) +{ + int err; + + err = crete_update_trust_state_hw(priv, trust_state); + + // to do + // mutex_lock(&priv->state_lock); + // + // new_params = priv->channels.params; + // crete_params_calc_trust_tx_min_inline_mode(priv->coredev, &new_params, + // trust_state); + // + // /* Skip if tx_min_inline is the same */ + // if (new_params.tx_min_inline_mode == priv->channels.params.tx_min_inline_mode) + // reset = false; + // + // err = crete_safe_switch_params(priv, &new_params, + // crete_update_trust_state_hw, + // &trust_state, reset); + // + // mutex_unlock(&priv->state_lock); + + return err; +} + + +int crete_set_dscp2prio(struct crete_priv *priv, u8 dscp, u8 prio) +{ + struct crete_core_dev *cdev = priv->coredev; + int sz = CRETE_ST_SZ_BYTES(set_dscp_map_tc_in); + u32 out[CRETE_ST_SZ_DW(set_dscp_map_tc_out)] = {0}; + void *in; + int err, st; + u8 qdscp_index, qdscp_value, value, offset; + + in = kzalloc(sz, GFP_KERNEL); + if (!in) { + err = -ENOMEM; + goto out; + } + // to do query + + CRETE_SET(set_dscp_map_tc_in, in, cmd_id, CRETE_CMD_SET_DSCP_MAP_TC); + CRETE_SET(set_dscp_map_tc_in, in, port_id, 1); + + /* Update the corresponding dscp entry */ + qdscp_index = dscp / CRETE_CMD_QSCP_NUM_PERQ; + offset = (dscp % CRETE_CMD_QSCP_NUM_PERQ) * CRETE_CMD_DSCP_BIT_WIDTH; + value = (prio & CRETE_CMD_DSCP_TC_MASK) | (1 << CRETE_CMD_DSCP_EN_SHIFT); + qdscp_value |= (value << offset); + + CRETE_ARRAY_SET(set_dscp_map_tc_in, in, qdscp, qdscp_index, qdscp_value); + err = crete_cmd_exec_polling(cdev, in, sizeof(in), out, sizeof(out)); + if (err) { + crete_info(cdev->device, "CRETE_CMD_SET_DSCP_MAP_TC err[%d]", err); + goto out; + } + + st = CRETE_GET(set_dscp_map_tc_out, out, status); + crete_info(cdev->device, "set_dscp_map_tc st[%d]\n", st); + priv->dcbx_dp.dscp2prio[dscp] = prio; +out: + kfree(in); + return err; +} + +/* Non-std selector values */ +#define DCB_APP_SEL_PCP 255 +static int crete_dcb_app_validate(struct net_device *netdev, + const struct dcb_app *app) +{ + int err = 0; + + switch (app->selector) { + /* Dscp checks */ + case IEEE_8021QAZ_APP_SEL_DSCP: + if (app->protocol >= CRETE_SUPPORTED_DSCP) + err = -EINVAL; + else if (app->priority >= CRETE_MAX_TC) + err = -ERANGE; + break; + /* Pcp checks */ + case DCB_APP_SEL_PCP: + if (app->protocol >= CRETE_SUPPORTED_PCP) + err = -EINVAL; + else if (app->priority >= CRETE_MAX_TC) + err = -ERANGE; + break; + default: + err = -EINVAL; + break; + } + + if (err) + netdev_err(netdev, "Invalid entry: %d:%d\n", app->protocol, + app->priority); + + return err; +} + + +static int crete_dcbnl_ieee_setapp(struct net_device *netdev, struct dcb_app *app) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct dcb_app temp; + bool is_new; + int err; + + err = crete_dcb_app_validate(netdev, app); + if (err) + return err; + + + /* Save the old entry info */ + temp.selector = IEEE_8021QAZ_APP_SEL_DSCP; + temp.protocol = app->protocol; + temp.priority = priv->dcbx_dp.dscp2prio[app->protocol]; + + /* Check if need to switch to dscp trust state */ + if (!priv->dcbx.dscp_app_cnt) { + err = crete_set_trust_state(priv, CRETE_PORT_TRUST_DSCP); + if (err) + return err; + } + + /* Skip the fw command if new and old mapping are the same */ + if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol]) { + err = crete_set_dscp2prio(priv, app->protocol, app->priority); + if (err) + goto fw_err; + } + + /* Delete the old entry if exists */ + is_new = false; + err = dcb_ieee_delapp(netdev, &temp); + if (err) + is_new = true; + + /* Add new entry and update counter */ + err = dcb_ieee_setapp(netdev, app); + if (err) + return err; + + if (is_new) + priv->dcbx.dscp_app_cnt++; + + return err; + +fw_err: + crete_set_trust_state(priv, CRETE_PORT_TRUST_PCP); + return err; +} + +static int crete_dcbnl_ieee_delapp(struct net_device *netdev, struct dcb_app *app) +{ + struct crete_priv *priv = netdev_priv(netdev); + int err; + + if ((app->selector != IEEE_8021QAZ_APP_SEL_DSCP) || + (app->protocol >= CRETE_SUPPORTED_DSCP)) + return -EINVAL; + + /* Skip if no dscp app entry */ + if (!priv->dcbx.dscp_app_cnt) + return -ENOENT; + + /* Check if the entry matches fw setting */ + if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol]) + return -ENOENT; + + /* Delete the app entry */ + err = dcb_ieee_delapp(netdev, app); + if (err) + return err; + + /* Reset the priority mapping back to zero */ + err = crete_set_dscp2prio(priv, app->protocol, 0); + if (err) + goto fw_err; + + priv->dcbx.dscp_app_cnt--; + + /* Check if need to switch to pcp trust state */ + if (!priv->dcbx.dscp_app_cnt) + err = crete_set_trust_state(priv, CRETE_PORT_TRUST_PCP); + + return err; + +fw_err: + crete_set_trust_state(priv, CRETE_PORT_TRUST_PCP); + return err; +} + +int crete_query_port_dcbx_param(struct crete_core_dev *cdev, u32 *out) +{ + *out = 0x1f; + //to do fw + return 0; +} + +int crete_set_port_dcbx_param(struct crete_core_dev *cdev, u32 *in) +{ + //to do fw + + return 0; +} + +static int crete_dcbnl_set_dcbx_mode(struct crete_priv *priv, + enum crete_dcbx_oper_mode mode) +{ + struct crete_core_dev *cdev = priv->coredev; + u32 *param = NULL; + int err; + + err = crete_query_port_dcbx_param(cdev, param); + if (err) + return err; + + return crete_set_port_dcbx_param(cdev, param); +} + +static int crete_dcbnl_switch_to_host_mode(struct crete_priv *priv) +{ + struct crete_dcbx *dcbx = &priv->dcbx; + int err; + + if (dcbx->mode == CRETE_DCBX_PARAM_VER_OPER_HOST) + return 0; + + err = crete_dcbnl_set_dcbx_mode(priv, CRETE_DCBX_PARAM_VER_OPER_HOST); + if (err) + return err; + + dcbx->mode = CRETE_DCBX_PARAM_VER_OPER_HOST; + return 0; +} + +static u8 crete_dcbnl_getdcbx(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + + return priv->dcbx.cap; +} + +static u8 crete_dcbnl_setdcbx(struct net_device *netdev, u8 mode) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_dcbx *dcbx = &priv->dcbx; + + if (mode & DCB_CAP_DCBX_LLD_MANAGED) + return 1; + + if (!mode) { + if (dcbx->mode == CRETE_DCBX_PARAM_VER_OPER_AUTO) + return 0; + + /* set dcbx to fw controlled */ + if (!crete_dcbnl_set_dcbx_mode(priv, CRETE_DCBX_PARAM_VER_OPER_AUTO)) { + dcbx->mode = CRETE_DCBX_PARAM_VER_OPER_AUTO; + dcbx->cap &= ~DCB_CAP_DCBX_HOST; + return 0; + } + + return 1; + } + + if (!(mode & DCB_CAP_DCBX_HOST)) + return 1; + + if (crete_dcbnl_switch_to_host_mode(netdev_priv(netdev))) + return 1; + + dcbx->cap = mode; + + return 0; +} +static int crete_dcbnl_getbuffer(struct net_device *netdev, + struct dcbnl_buffer *dcb_buffer) +{ + netdev_err(netdev, " debuging %s stub\n", __func__); + return 0; +} +static int crete_dcbnl_setbuffer(struct net_device *netdev, + struct dcbnl_buffer *dcb_buffer) +{ + netdev_err(netdev, " debuging %s stub\n", __func__); + return 0; +} + +static u8 crete_dcbnl_setall(struct net_device *netdev) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_cee_config *cee_cfg = &priv->dcbx.cee_cfg; + struct ieee_ets ets; + struct ieee_pfc pfc; + int err = -EOPNOTSUPP; + int i; + + memset(&ets, 0, sizeof(ets)); + memset(&pfc, 0, sizeof(pfc)); + + ets.ets_cap = IEEE_8021QAZ_MAX_TCS; + for (i = 0; i < CEE_DCBX_MAX_PGS; i++) { + ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i]; + ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i]; + ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS; + ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i]; + netdev_dbg(netdev, + "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n", + __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i], + ets.prio_tc[i]); + } + + err = crete_dcbnl_validate_ets(netdev, &ets, true); + if (err) + goto out; + + err = crete_dcbnl_ieee_setets_core(priv, &ets); + if (err) { + netdev_err(netdev, + "%s, Failed to set ETS: %d\n", __func__, err); + goto out; + } + + /* Set PFC */ + pfc.pfc_cap = CRETE_MAX_TC; + if (!cee_cfg->pfc_enable) + pfc.pfc_en = 0; + else + for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) + pfc.pfc_en |= cee_cfg->pfc_setting[i] << i; + + err = crete_dcbnl_ieee_setpfc(netdev, &pfc); + if (err) { + netdev_err(netdev, + "%s, Failed to set PFC: %d\n", __func__, err); + goto out; + } +out: + return err ? CRETE_DCB_NO_CHG : CRETE_DCB_CHG_RESET; + +} +static u8 crete_dcbnl_getstate(struct net_device *netdev) +{ + return CRETE_CEE_STATE_UP; +} +static void crete_dcbnl_getpermhwaddr(struct net_device *netdev, + u8 *perm_addr) +{ + if (!perm_addr) + return; + memset(perm_addr, 0xff, MAX_ADDR_LEN); +} +static void crete_dcbnl_setpgtccfgtx(struct net_device *netdev, + int priority, u8 prio_type, + u8 pgid, u8 bw_pct, u8 up_map) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_cee_config *cee_cfg = &priv->dcbx.cee_cfg; + + if (priority >= CEE_DCBX_MAX_PRIO) { + netdev_err(netdev, + "%s, priority is out of range\n", __func__); + return; + } + + if (pgid >= CEE_DCBX_MAX_PGS) { + netdev_err(netdev, + "%s, priority group is out of range\n", __func__); + return; + } + + cee_cfg->prio_to_pg_map[priority] = pgid; +} +static void crete_dcbnl_setpgbwgcfgtx(struct net_device *netdev, + int pgid, u8 bw_pct) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_cee_config *cee_cfg = &priv->dcbx.cee_cfg; + + if (pgid >= CEE_DCBX_MAX_PGS) { + netdev_err(netdev, + "%s, priority group is out of range\n", __func__); + return; + } + + cee_cfg->pg_bw_pct[pgid] = bw_pct; +} +static void crete_dcbnl_getpgtccfgtx(struct net_device *netdev, + int priority, u8 *prio_type, + u8 *pgid, u8 *bw_pct, u8 *up_map) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *mdev = priv->coredev; + + if (priority >= CEE_DCBX_MAX_PRIO) { + netdev_err(netdev, + "%s, priority is out of range\n", __func__); + return; + } + + *prio_type = 0; + *bw_pct = 0; + *up_map = 0; + + if (crete_query_port_prio_tc(mdev, priority, pgid)) + *pgid = 0; +} +static void crete_dcbnl_getpgbwgcfgtx(struct net_device *netdev, + int pgid, u8 *bw_pct) +{ + struct ieee_ets ets; + + if (pgid >= CEE_DCBX_MAX_PGS) { + netdev_err(netdev, + "%s, priority group is out of range\n", __func__); + return; + } + + crete_dcbnl_ieee_getets(netdev, &ets); + *bw_pct = ets.tc_tx_bw[pgid]; +} + +static void crete_dcbnl_setpfccfg(struct net_device *netdev, + int priority, u8 setting) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_cee_config *cee_cfg = &priv->dcbx.cee_cfg; + + if (priority >= CEE_DCBX_MAX_PRIO) { + netdev_err(netdev, + "%s, priority is out of range\n", __func__); + return; + } + + if (setting > 1) + return; + + cee_cfg->pfc_setting[priority] = setting; +} + +static int +crete_dcbnl_get_priority_pfc(struct net_device *netdev, + int priority, u8 *setting) +{ + struct ieee_pfc pfc; + int err; + + err = crete_dcbnl_ieee_getpfc(netdev, &pfc); + + if (err) + *setting = 0; + else + *setting = (pfc.pfc_en >> priority) & 0x01; + + return err; +} + +static void crete_dcbnl_getpfccfg(struct net_device *netdev, + int priority, u8 *setting) +{ + if (priority >= CEE_DCBX_MAX_PRIO) { + netdev_err(netdev, + "%s, priority is out of range\n", __func__); + return; + } + + if (!setting) + return; + + crete_dcbnl_get_priority_pfc(netdev, priority, setting); +} +static u8 crete_dcbnl_getcap(struct net_device *netdev, + int capid, u8 *cap) +{ + struct crete_priv *priv = netdev_priv(netdev); + u8 rval = 0; + + switch (capid) { + case DCB_CAP_ATTR_PG: + *cap = true; + break; + case DCB_CAP_ATTR_PFC: + *cap = true; + break; + case DCB_CAP_ATTR_UP2TC: + *cap = false; + break; + case DCB_CAP_ATTR_PG_TCS: + *cap = 1 << (CRETE_MAX_TC - 1); + break; + case DCB_CAP_ATTR_PFC_TCS: + *cap = 1 << (CRETE_MAX_TC - 1); + break; + case DCB_CAP_ATTR_GSP: + *cap = false; + break; + case DCB_CAP_ATTR_BCN: + *cap = false; + break; + case DCB_CAP_ATTR_DCBX: + *cap = priv->dcbx.cap | + DCB_CAP_DCBX_VER_CEE | + DCB_CAP_DCBX_VER_IEEE; + break; + default: + *cap = 0; + rval = 1; + break; + } + + return rval; + +} +static int crete_dcbnl_getnumtcs(struct net_device *netdev, + int tcs_id, u8 *num) +{ + switch (tcs_id) { + case DCB_NUMTCS_ATTR_PG: + case DCB_NUMTCS_ATTR_PFC: + *num = CRETE_MAX_TC; + break; + default: + return -EINVAL; + } + return 0; +} + +static u8 crete_dcbnl_getpfcstate(struct net_device *netdev) +{ + struct ieee_pfc pfc; + + if (crete_dcbnl_ieee_getpfc(netdev, &pfc)) + return CRETE_CEE_STATE_DOWN; + + return pfc.pfc_en ? CRETE_CEE_STATE_UP : CRETE_CEE_STATE_DOWN; + +} + +static void crete_dcbnl_setpfcstate(struct net_device *netdev, u8 state) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_cee_config *cee_cfg = &priv->dcbx.cee_cfg; + + if ((state != CRETE_CEE_STATE_UP) && (state != CRETE_CEE_STATE_DOWN)) + return; + + cee_cfg->pfc_enable = state; +} + +static const struct dcbnl_rtnl_ops crete_dcbx_ops = { + .ieee_getets = crete_dcbnl_ieee_getets, + .ieee_setets = crete_dcbnl_ieee_setets, + .ieee_getmaxrate = crete_dcbnl_ieee_getmaxrate, + .ieee_setmaxrate = crete_dcbnl_ieee_setmaxrate, + .ieee_getpfc = crete_dcbnl_ieee_getpfc, + .ieee_setpfc = crete_dcbnl_ieee_setpfc, + .ieee_setapp = crete_dcbnl_ieee_setapp, + .ieee_delapp = crete_dcbnl_ieee_delapp, + .getdcbx = crete_dcbnl_getdcbx, + .setdcbx = crete_dcbnl_setdcbx, + .dcbnl_getbuffer = crete_dcbnl_getbuffer, + .dcbnl_setbuffer = crete_dcbnl_setbuffer, + +/* CEE interfaces */ + .setall = crete_dcbnl_setall, + .getstate = crete_dcbnl_getstate, + .getpermhwaddr = crete_dcbnl_getpermhwaddr, + + .setpgtccfgtx = crete_dcbnl_setpgtccfgtx, + .setpgbwgcfgtx = crete_dcbnl_setpgbwgcfgtx, + .getpgtccfgtx = crete_dcbnl_getpgtccfgtx, + .getpgbwgcfgtx = crete_dcbnl_getpgbwgcfgtx, + + .setpfccfg = crete_dcbnl_setpfccfg, + .getpfccfg = crete_dcbnl_getpfccfg, + .getcap = crete_dcbnl_getcap, + .getnumtcs = crete_dcbnl_getnumtcs, + .getpfcstate = crete_dcbnl_getpfcstate, + .setpfcstate = crete_dcbnl_setpfcstate, +}; + +void crete_dcbnl_build_netdev(struct net_device *netdev) +{ + netdev->dcbnl_ops = &crete_dcbx_ops; +} + +static void crete_dcbnl_dscp_app(struct crete_priv *priv, int action) +{ + struct dcb_app temp; + int i; + + /* No SEL_DSCP entry in non DSCP state */ + if (priv->dcbx_dp.trust_state != CRETE_PORT_TRUST_DSCP) + return; + + temp.selector = IEEE_8021QAZ_APP_SEL_DSCP; + for (i = 0; i < CRETE_SUPPORTED_DSCP; i++) { + temp.protocol = i; + temp.priority = priv->dcbx_dp.dscp2prio[i]; + if (action == INIT) + dcb_ieee_setapp(priv->netdev, &temp); + else + dcb_ieee_delapp(priv->netdev, &temp); + } + + priv->dcbx.dscp_app_cnt = (action == INIT) ? CRETE_SUPPORTED_DSCP : 0; +} + +void crete_dcbnl_delete_app(struct crete_priv *priv) +{ + crete_dcbnl_dscp_app(priv, DELETE); +} + +void crete_dcbnl_init_app(struct crete_priv *priv) +{ + crete_dcbnl_dscp_app(priv, INIT); +} + +static int crete_trust_initialize(struct crete_priv *priv) +{ + u8 trust_state; + + trust_state = CRETE_PORT_TRUST_PCP; + WRITE_ONCE(priv->dcbx_dp.trust_state, trust_state); + + if (priv->dcbx_dp.trust_state == CRETE_PORT_TRUST_PCP && priv->dcbx.dscp_app_cnt) { + /* + * Align the driver state with the fw state. + * Temporary state change is required to enable the app list reset. + */ + priv->dcbx_dp.trust_state = CRETE_PORT_TRUST_DSCP; + crete_dcbnl_delete_app(priv); + priv->dcbx_dp.trust_state = CRETE_PORT_TRUST_PCP; + } + + return 0; +} + +static void crete_ets_init(struct crete_priv *priv) +{ + struct ieee_ets ets; + int err; + int i; + + memset(&ets, 0, sizeof(ets)); + ets.ets_cap = CRETE_MAX_TC; + for (i = 0; i < ets.ets_cap; i++) { + ets.tc_tx_bw[i] = CRETE_MAX_BW_ALLOC; + ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR; + ets.prio_tc[i] = i; + } + + if (ets.ets_cap > 1) { + /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */ + ets.prio_tc[0] = 1; + ets.prio_tc[1] = 0; + } + + err = crete_dcbnl_ieee_setets_core(priv, &ets); + if (err) + netdev_err(priv->netdev, + "%s, Failed to init ETS: %d\n", __func__, err); +} + +void crete_dcbnl_initialize(struct crete_priv *priv) +{ + crete_trust_initialize(priv); + + priv->dcbx.cap = DCB_CAP_DCBX_VER_CEE | + DCB_CAP_DCBX_VER_IEEE; + if (priv->dcbx.mode == CRETE_DCBX_PARAM_VER_OPER_HOST) + priv->dcbx.cap |= DCB_CAP_DCBX_HOST; + + priv->dcbx.manual_buffer = false; + priv->dcbx.cable_len = CRETE_DEFAULT_CABLE_LEN; + crete_ets_init(priv); +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_dcb_nl.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_dcb_nl.h new file mode 100644 index 0000000..ffb4b3e --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_dcb_nl.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __CRETE_DCBX_H__ +#define __CRETE_DCBX_H__ +#include +#include +#include +#include +#include + + +#define CRETE_SUPPORTED_DSCP 64 +#define CRETE_SUPPORTED_PCP 8 + +#define CRETE_CMD_DSCP_BIT_WIDTH 0x8 +#define CRETE_CMD_DSCP_TC_MASK 0xF +#define CRETE_CMD_DSCP_EN_SHIFT 0x7 +#define CRETE_CMD_QDSCP_NUM 16 +#define CRETE_CMD_QSCP_NUM_PERQ 4 +#define CRETE_DEFAULT_CABLE_LEN 7 /* 7 meters */ + +#define CRETE_1GB (1000000) +#define CRETE_100MB (100000) + +enum crete_dcbx_oper_mode { + CRETE_DCBX_PARAM_VER_OPER_HOST = 0x0, + CRETE_DCBX_PARAM_VER_OPER_AUTO = 0x3, +}; + +enum { + INIT, + DELETE, +}; + +struct crete_cee_config { + /* bw pct for priority group */ + u8 pg_bw_pct[CEE_DCBX_MAX_PGS]; + u8 prio_to_pg_map[CEE_DCBX_MAX_PRIO]; + bool pfc_setting[CEE_DCBX_MAX_PRIO]; + bool pfc_enable; +}; + +struct crete_dcbx_dp { + u8 dscp2prio[CRETE_SUPPORTED_DSCP]; + u8 trust_state; +}; + + +struct crete_dcbx { + enum crete_dcbx_oper_mode mode; + struct crete_cee_config cee_cfg; /* pending configuration */ + u8 dscp_app_cnt; + + /* The only setting that cannot be read from FW */ + u8 tc_tsa[IEEE_8021QAZ_MAX_TCS]; + u8 cap; + + /* Buffer configuration */ + bool manual_buffer; + u32 cable_len; + u32 xoff; + u16 port_buff_cell_sz; +}; + +enum crete_port_trust_state { + CRETE_PORT_TRUST_PCP = 1, + CRETE_PORT_TRUST_DSCP = 2, +}; + + +enum { + CRETE_DISABLE_MAXRATE = 0, + CRETE_KBPS_UNIT = 1, + CRETE_MBPS_UNIT = 2, + CRETE_GBPS_UNIT = 3, + CRETE_PPS_UNIT = 4, + CRETE_KPPS_UNIT = 5, + CRETE_MPPS_UNIT = 6, +}; + +struct tc_configuration { + u8 weight; + u8 unit; + u8 pg_id; + u32 maxrate; +}; + +struct dscp_configuration { + u8 tc : 4; + u8 en : 1; +}; + +struct pcp_configuration { + u8 tc : 3; + u8 en : 1; +}; + +struct crete_priv; +void crete_dcbnl_build_netdev(struct net_device *netdev); +void crete_dcbnl_initialize(struct crete_priv *priv); +void crete_dcbnl_init_app(struct crete_priv *priv); + + + + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_debugfs_statistics.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_debugfs_statistics.c new file mode 100644 index 0000000..7bdc874 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_debugfs_statistics.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "crete.h" +#include "crete_cmd_if.h" + +static int statistics_show(struct seq_file *file, void *priv) +{ + struct crete_core_dev *core_dev = file->private; + struct crete_debugfs_statistics *debugfs_statis = core_dev->debugfs_statis; + struct crete_port_statistics port_statistics; + int ret = 0; + + mutex_lock(&debugfs_statis->statis_mutex); + + ret = crete_get_port_statistics(core_dev, &port_statistics); + if(ret){ + mutex_unlock(&debugfs_statis->statis_mutex); + return ret; + } + + debugfs_statis->rx_bytes += port_statistics.rx_bytes; + debugfs_statis->rx_pkts += port_statistics.rx_pkts; + debugfs_statis->tx_bytes += port_statistics.tx_bytes; + debugfs_statis->tx_pkts += port_statistics.tx_pkts; + + seq_printf(file, "rx bytes : 0x%llx\n", debugfs_statis->rx_bytes); + seq_printf(file, "rx pkts : 0x%llx\n", debugfs_statis->rx_pkts); + seq_printf(file, "tx bytes : 0x%llx\n", debugfs_statis->tx_bytes); + seq_printf(file, "tx pkts : 0x%llx\n", debugfs_statis->tx_pkts); + + mutex_unlock(&debugfs_statis->statis_mutex); + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(statistics); + +int crete_register_debugfs_statistics(struct crete_core_dev *dev) +{ + struct crete_debugfs_statistics *debugfs_statis = NULL; + struct dentry *debugfs = NULL; + + debugfs_statis = kzalloc(sizeof(*debugfs_statis), GFP_KERNEL); + if(!debugfs_statis){ + dev_err(dev->device, "failed to alloc debugfs statistics\n"); + return -1; + } + mutex_init(&debugfs_statis->statis_mutex); + dev->debugfs_statis = debugfs_statis; + + debugfs = debugfs_create_file("statistics", 0444, crete_debugfs_get_dev_root(dev), dev, &statistics_fops); + if(!debugfs){ + dev_err(dev->device, "failed to create debugfs file statistics\n"); + return -1; + } + dev->dbg.statistics_debugfs = debugfs; + + return 0; +} + +int crete_unregister_debugfs_statistics(struct crete_core_dev *dev) +{ + if(dev->dbg.statistics_debugfs){ + debugfs_remove_recursive(dev->dbg.statistics_debugfs); + } + + if(dev->debugfs_statis){ + kfree(dev->debugfs_statis); + dev->debugfs_statis = NULL; + } + + return 0; +} \ No newline at end of file diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_debugfs_statistics.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_debugfs_statistics.h new file mode 100644 index 0000000..d90ee41 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_debugfs_statistics.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include + +struct crete_debugfs_statistics { + + struct mutex statis_mutex; + + uint64_t tx_pkts; + uint64_t tx_bytes; + + uint64_t rx_pkts; + uint64_t rx_bytes; +}; + +int crete_register_debugfs_statistics(struct crete_core_dev *dev); +int crete_unregister_debugfs_statistics(struct crete_core_dev *dev); + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_devlink.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_devlink.c new file mode 100644 index 0000000..6d5059b --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_devlink.c @@ -0,0 +1,542 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include "crete.h" +#include "crete_eswitch.h" +#include "crete_fw_update.h" + +struct crete_eswitch *crete_devlink_eswitch_get(struct devlink *devlink) +{ + struct crete_core_dev *dev = devlink_priv(devlink); + + return dev->eswitch; +} + +static int esw_mode_from_devlink(u16 mode, u16 *crete_mode) +{ + switch (mode) { + case DEVLINK_ESWITCH_MODE_LEGACY: + *crete_mode = CRETE_ESWITCH_LEGACY; + break; + case DEVLINK_ESWITCH_MODE_SWITCHDEV: + *crete_mode = CRETE_ESWITCH_OFFLOADS; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int esw_mode_to_devlink(u16 crete_mode, u16 *mode) +{ + switch (crete_mode) { + case CRETE_ESWITCH_LEGACY: + *mode = DEVLINK_ESWITCH_MODE_LEGACY; + break; + case CRETE_ESWITCH_OFFLOADS: + *mode = DEVLINK_ESWITCH_MODE_SWITCHDEV; + break; + default: + return -EINVAL; + } + + return 0; +} + +int crete_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, + struct netlink_ext_ack *extack) +{ + u16 cur_crete_mode, crete_mode = 0; + struct crete_eswitch *esw; + int err = 0; + + esw = crete_devlink_eswitch_get(devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + if (esw_mode_from_devlink(mode, &crete_mode)) + return -EINVAL; + + err = crete_esw_try_lock(esw); + if (err < 0) { + NL_SET_ERR_MSG_MOD(extack, "Can't change mode, E-Switch is busy"); + goto eswitch_busy; + } + cur_crete_mode = err; + err = 0; + + if (cur_crete_mode == crete_mode) + goto unlock; + /* cmd queue notify firmware */ + crete_eswitch_disable_locked(esw); + if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) { + err = esw_offloads_start(esw, extack); + crete_rescan_drivers_locked(esw->dev); + } else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) { + crete_rescan_drivers_locked(esw->dev); + err = esw_offloads_stop(esw, extack); + //crete_rescan_drivers_locked(esw->dev); + } else { + err = -EINVAL; + } + +unlock: + crete_esw_unlock(esw); +eswitch_busy: + return err; +} + +int crete_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode) +{ + struct crete_eswitch *esw; + int err; + + esw = crete_devlink_eswitch_get(devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + down_read(&esw->mode_lock); + err = esw_mode_to_devlink(esw->mode, mode); + up_read(&esw->mode_lock); + return err; +} + +static int crete_devlink_flash_update(struct devlink *devlink, + struct devlink_flash_update_params *params, + struct netlink_ext_ack *extack) +{ + struct crete_core_dev *cdev = devlink_priv(devlink); +#ifndef CONFIG_DEVLINK_CARRYOUT_OPTIMIZE + const struct firmware *fw; + int err; + + err = request_firmware_direct(&fw, params->file_name, cdev->device); + if (err) + return err; + + err = crete_firmware_flash(cdev, fw, extack, CRETE_FWU_DEVLINK); + release_firmware(fw); +#else + return crete_firmware_flash(cdev, params->fw, extack, CRETE_FWU_DEVLINK); +#endif + return 0; +} + +static u8 crete_fw_ver_major(u32 version) +{ + return (version >> 24) & 0xff; +} + +static u8 crete_fw_ver_minor(u32 version) +{ + return (version >> 16) & 0xff; +} + +static u16 crete_fw_ver_subminor(u32 version) +{ + return version & 0xffff; +} + +#define DEVLINK_FW_STRING_LEN 32 +int crete_fw_version_query(struct crete_core_dev *dev, + u32 *running_ver, u32 *pending_ver) +{ + dev_warn(&dev->pdev->dev, "%s devlink info get fw version stub\n", __func__); + *running_ver = 0x20231025; + *pending_ver = 0x20231024; + return 0; +} + +static int +crete_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + struct crete_core_dev *dev = devlink_priv(devlink); + char version_str[DEVLINK_FW_STRING_LEN]; + u32 running_fw, stored_fw; + int err; + char *psid_stub = "crete_stub_psid"; + + err = devlink_info_version_fixed_put(req, "fw.psid", psid_stub); + if (err) + return err; + + err = crete_fw_version_query(dev, &running_fw, &stored_fw); + if (err) + return err; + + snprintf(version_str, sizeof(version_str), "%d.%d.%04d", + crete_fw_ver_major(running_fw), crete_fw_ver_minor(running_fw), + crete_fw_ver_subminor(running_fw)); + err = devlink_info_version_running_put(req, "fw.version", version_str); + if (err) + return err; + err = devlink_info_version_running_put(req, + DEVLINK_INFO_VERSION_GENERIC_FW, + version_str); + if (err) + return err; + + /* no pending version, return running (stored) version */ + if (stored_fw == 0) + stored_fw = running_fw; + + snprintf(version_str, sizeof(version_str), "%d.%d.%04d", + crete_fw_ver_major(stored_fw), crete_fw_ver_minor(stored_fw), + crete_fw_ver_subminor(stored_fw)); + err = devlink_info_version_stored_put(req, "fw.version", version_str); + if (err) + return err; + return devlink_info_version_stored_put(req, + DEVLINK_INFO_VERSION_GENERIC_FW, + version_str); +} + + +static struct devlink_ops crete_pf_dl_ops = { + .eswitch_mode_set = crete_devlink_eswitch_mode_set, + .eswitch_mode_get = crete_devlink_eswitch_mode_get, + .info_get = crete_devlink_info_get, + .flash_update = crete_devlink_flash_update, +}; + + +static struct devlink_ops crete_dft_dl_ops; + + +struct devlink *crete_devlink_alloc(struct device *dev, bool is_pf) +{ + struct devlink_ops *dl_ops; + + if (is_pf) + dl_ops = &crete_pf_dl_ops; + else + dl_ops = &crete_dft_dl_ops; + +#ifndef NEED_DEVLINK_ALLOC_SETS_DEV + return devlink_alloc(dl_ops, sizeof(struct crete_core_dev), + dev); +#else + return devlink_alloc(dl_ops, sizeof(struct crete_core_dev)); +#endif +} + +void crete_devlink_free(struct devlink *devlink) +{ + devlink_free(devlink); +} + +bool crete_eth_supported(struct crete_core_dev *core_dev) +{ + if (core_dev->device_type != CRETE_DEVICE_CRETE) + return false; + if (!crete_have_net_cap(core_dev)) + return false; + return true; +} + +bool crete_eth_enabled(struct crete_core_dev *core_dev) +{ + return true; +} + +bool crete_eth_rep_supported(struct crete_core_dev *core_dev) +{ + if(core_dev->device_type == CRETE_DEVICE_PNIC) + return false; + + return true; +} + +bool crete_eth_rep_enabled(struct crete_core_dev *core_dev) +{ + return true; +} + + +bool crete_rdma_supported(struct crete_core_dev *core_dev) +{ + if(core_dev->device_type == CRETE_DEVICE_PNIC) + return false; + + return true; +} + +bool crete_rdma_enabled(struct crete_core_dev *core_dev) +{ + return true; +} + +bool crete_rdma_rep_supported(struct crete_core_dev *core_dev) +{ + return true; +} + +bool crete_rdma_rep_enabled(struct crete_core_dev *core_dev) +{ + return true; +} + +bool crete_vnet_supported(struct crete_core_dev *core_dev) +{ + if (core_dev->coredev_type == CRETE_COREDEV_PF) + return false; + + if (core_dev->device_type == CRETE_DEVICE_PNIC) + return true; + + if (core_dev->device_type != CRETE_DEVICE_CRETE) + return false; + + if (!crete_have_net_cap(core_dev)) + return false; + + return true; +} + +bool crete_vnet_enabled(struct crete_core_dev *core_dev) +{ + return true; +} + +bool crete_nic_supported(struct crete_core_dev *core_dev) +{ + if (core_dev->device_type != CRETE_DEVICE_PNIC || + !crete_core_is_pf(core_dev)) + return false; + + if (!crete_have_net_cap(core_dev)) + return false; + + return true; +} + +bool crete_nic_enabled(struct crete_core_dev *core_dev) +{ + return true; +} + +#ifndef CONFIG_WITHOUT_DEVLINK_PARAM_ETH +static const struct devlink_param enable_eth_param = + DEVLINK_PARAM_GENERIC(ENABLE_ETH, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), + NULL, NULL, NULL); + +static int crete_devlink_eth_param_register(struct devlink *devlink) +{ + struct crete_core_dev *dev = devlink_priv(devlink); + union devlink_param_value value; + int err; + + if (!crete_eth_supported(dev)) + return 0; + + err = devlink_param_register(devlink, &enable_eth_param); + if (err) + return err; + + value.vbool = true; + devlink_param_driverinit_value_set(devlink, + DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, + value); + devlink_param_publish(devlink, &enable_eth_param); + return 0; +} + +static void crete_devlink_eth_param_unregister(struct devlink *devlink) +{ + struct crete_core_dev *dev = devlink_priv(devlink); + + if (!crete_eth_supported(dev)) + return; + + devlink_param_unpublish(devlink, &enable_eth_param); + devlink_param_unregister(devlink, &enable_eth_param); +} + +static int crete_devlink_enable_rdma_validate(struct devlink *devlink, u32 id, + union devlink_param_value val, + struct netlink_ext_ack *extack) +{ + struct crete_core_dev *dev = devlink_priv(devlink); + bool new_state = val.vbool; + + if (new_state && !crete_rdma_supported(dev)) + return -EOPNOTSUPP; + return 0; +} + +static const struct devlink_param enable_rdma_param = + DEVLINK_PARAM_GENERIC(ENABLE_RDMA, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), + NULL, NULL, crete_devlink_enable_rdma_validate); + +static int crete_devlink_rdma_param_register(struct devlink *devlink) +{ + union devlink_param_value value; + int err; + + if (!IS_ENABLED(CONFIG_crete_INFINIBAND)) + return 0; + + err = devlink_param_register(devlink, &enable_rdma_param); + if (err) + return err; + + value.vbool = true; + devlink_param_driverinit_value_set(devlink, + DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, + value); + devlink_param_publish(devlink, &enable_rdma_param); + return 0; +} + +static void crete_devlink_rdma_param_unregister(struct devlink *devlink) +{ + if (!IS_ENABLED(CONFIG_crete_INFINIBAND)) + return; + + devlink_param_unpublish(devlink, &enable_rdma_param); + devlink_param_unregister(devlink, &enable_rdma_param); +} + +static const struct devlink_param enable_vnet_param = + DEVLINK_PARAM_GENERIC(ENABLE_VNET, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), + NULL, NULL, NULL); + +static int crete_devlink_vnet_param_register(struct devlink *devlink) +{ + struct crete_core_dev *dev = devlink_priv(devlink); + union devlink_param_value value; + int err; + + if (!crete_vnet_supported(dev)) + return 0; + + err = devlink_param_register(devlink, &enable_vnet_param); + if (err) + return err; + + value.vbool = true; + devlink_param_driverinit_value_set(devlink, + DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, + value); + devlink_param_publish(devlink, &enable_rdma_param); + return 0; +} + +static void crete_devlink_vnet_param_unregister(struct devlink *devlink) +{ + struct crete_core_dev *dev = devlink_priv(devlink); + + if (!crete_vnet_supported(dev)) + return; + + devlink_param_unpublish(devlink, &enable_vnet_param); + devlink_param_unregister(devlink, &enable_vnet_param); +} +#endif + +static int crete_devlink_auxdev_params_register(struct devlink *devlink) +{ +#ifndef CONFIG_WITHOUT_DEVLINK_PARAM_ETH + int err; + + err = crete_devlink_eth_param_register(devlink); + if (err) + return err; + + err = crete_devlink_rdma_param_register(devlink); + if (err) + goto rdma_err; + + err = crete_devlink_vnet_param_register(devlink); + if (err) + goto vnet_err; + return 0; + +vnet_err: + crete_devlink_rdma_param_unregister(devlink); +rdma_err: + crete_devlink_eth_param_unregister(devlink); + return err; +#else + return 0; +#endif +} + +static void crete_devlink_auxdev_params_unregister(struct devlink *devlink) +{ +#ifndef CONFIG_WITHOUT_DEVLINK_PARAM_ETH + crete_devlink_vnet_param_unregister(devlink); + crete_devlink_rdma_param_unregister(devlink); + crete_devlink_eth_param_unregister(devlink); +#endif +} + + +int crete_devlink_register(struct devlink *devlink) +{ + int err; + struct crete_core_dev *core_dev = devlink_priv(devlink); + struct pci_dev *pdev = core_dev->pdev; + + dev_info(&pdev->dev, "devlink register"); +#ifndef HAVE_DEVLINK_REGISTER_SETS_DEV + devlink_register(devlink); + err = 0; +#else + err = devlink_register(devlink, &pdev->dev); +#endif + + if (err) + return err; + + err = crete_devlink_auxdev_params_register(devlink); + if (err) + goto auxdev_reg_err; + + return 0; + +auxdev_reg_err: + devlink_unregister(devlink); + return err; +} + +void crete_devlink_unregister(struct devlink *devlink) +{ + crete_devlink_auxdev_params_unregister(devlink); + devlink_unregister(devlink); +} + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_devlink.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_devlink.h new file mode 100644 index 0000000..a2aff59 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_devlink.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __CRETE_DEVLINK_H__ +#define __CRETE_DEVLINK_H__ + +#include + +struct devlink *crete_devlink_alloc(struct device *dev, bool is_pf); +void crete_devlink_free(struct devlink *devlink); +int crete_devlink_register(struct devlink *devlink); +void crete_devlink_unregister(struct devlink *devlink); + + +bool crete_eth_supported(struct crete_core_dev *core_dev); +bool crete_eth_enabled(struct crete_core_dev *core_dev); +bool crete_eth_rep_supported(struct crete_core_dev *core_dev); +bool crete_eth_rep_enabled(struct crete_core_dev *core_dev); +bool crete_rdma_supported(struct crete_core_dev *core_dev); +bool crete_rdma_enabled(struct crete_core_dev *core_dev); +bool crete_rdma_rep_supported(struct crete_core_dev *core_dev); +bool crete_rdma_rep_enabled(struct crete_core_dev *core_dev); +bool crete_vnet_supported(struct crete_core_dev *core_dev); +bool crete_vnet_enabled(struct crete_core_dev *core_dev); +bool crete_nic_supported(struct crete_core_dev *core_dev); +bool crete_nic_enabled(struct crete_core_dev *core_dev); + + +#endif /* __CRETE_DEVLINK_H__ */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswitch.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswitch.c new file mode 100644 index 0000000..f8c89f2 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswitch.c @@ -0,0 +1,1379 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crete.h" +#include "crete_sriov.h" +#include "crete_eswitch.h" +#include "crete_regs.h" +#include "crete_cmd.h" +#include "crete_cmd_if.h" +#include "crete_eswoffloads.h" + +#define esw_info(__dev, format, ...) \ + dev_info(__dev, "E-Switch: " format, ##__VA_ARGS__) + +#define esw_warn(__dev, format, ...) \ + dev_warn(__dev, "E-Switch: " format, ##__VA_ARGS__) + +#define esw_debug(__dev, format, ...) \ + dev_dbg(__dev, format, ##__VA_ARGS__) + + +#define CRETE_ESWITCH_MANAGER(mdev) crete_core_is_pf(mdev) +static int esw_offloads_enable(struct crete_eswitch *esw); +static void esw_offloads_disable(struct crete_eswitch *esw); + +static bool crete_esw_allowed(const struct crete_eswitch *esw) +{ + return esw && CRETE_ESWITCH_MANAGER(esw->dev); +} + +static bool +crete_esw_is_manager_vport(const struct crete_eswitch *esw, u16 vport_num) +{ + return esw->manager_vport == vport_num; +} + +static u16 crete_core_max_vfs(const struct crete_core_dev *dev) +{ + return dev->pf.max_vfs; +} + +/* The returned number is valid only when the dev is eswitch manager. */ +static u16 crete_eswitch_manager_vport(struct crete_core_dev *dev) +{ + return CRETE_VPORT_PF; +} + +static u16 crete_eswitch_first_host_vport_num(struct crete_core_dev *dev) +{ + return CRETE_VPORT_FIRST_VF; +} + +static bool crete_esw_is_fdb_created(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s stub\n", __func__); + return false; +} + +static void esw_vport_change_handle_locked(struct crete_vport *vport) +{ + struct crete_core_dev *dev = vport->dev; + struct device *device = &dev->pdev->dev; + + u8 mac[ETH_ALEN]; + + //crete_query_nic_vport_mac_address(dev, vport->vport, true, mac); + esw_debug(device, "vport[%d] Context Changed: perm mac: %pM\n", + vport->vport, mac); + + if (vport->enabled_events & CRETE_VPORT_UC_ADDR_CHANGE) { + //esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); + //esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC); + esw_debug(device, "vport[%d] CRETE_VPORT_UC_ADDR_CHANGE\n", vport->vport); + } + + if (vport->enabled_events & CRETE_VPORT_MC_ADDR_CHANGE) + esw_debug(device, "vport[%d] CRETE_VPORT_UC_ADDR_CHANGE\n", vport->vport); + //esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); + + if (vport->enabled_events & CRETE_VPORT_PROMISC_CHANGE) { + //esw_update_vport_rx_mode(esw, vport); + esw_debug(device, "vport[%d] CRETE_VPORT_PROMISC_CHANGE\n", vport->vport); + } + + if (vport->enabled_events & (CRETE_VPORT_PROMISC_CHANGE | CRETE_VPORT_MC_ADDR_CHANGE)) { + //esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC); + esw_debug(device, "vport[%d] esw_apply_vport_addr_list\n", vport->vport); + } + + esw_debug(device, "vport[%d] Context Changed: Done\n", vport->vport); + if (vport->enabled) { + esw_debug(device, "vport[%d] arm_vport_context_events_cmd\n", vport->vport); + //arm_vport_context_events_cmd(dev, vport->vport, + // vport->enabled_events); + } +} + +static void esw_vport_change_handler(struct work_struct *work) +{ + struct crete_vport *vport = + container_of(work, struct crete_vport, vport_change_handler); + struct crete_eswitch *esw = vport->dev->eswitch; + + mutex_lock(&esw->state_lock); + esw_vport_change_handle_locked(vport); + mutex_unlock(&esw->state_lock); +} + + +static int crete_esw_vport_alloc(struct crete_eswitch *esw, + int index, u16 vport_num) +{ + struct crete_vport *vport; + int err; + + vport = kzalloc(sizeof(*vport), GFP_KERNEL); + if (!vport) + return -ENOMEM; + + vport->dev = esw->dev; + vport->vport = vport_num; + vport->index = index; + vport->info.link_state = CRETE_VPORT_ADMIN_STATE_AUTO; + INIT_WORK(&vport->vport_change_handler, esw_vport_change_handler); + err = xa_insert(&esw->vports, vport_num, vport, GFP_KERNEL); + if (err) + goto insert_err; + + esw->total_vports++; + return 0; + +insert_err: + kfree(vport); + return err; +} + +static void crete_esw_vport_free(struct crete_eswitch *esw, struct crete_vport *vport) +{ + cancel_work_sync(&vport->vport_change_handler); + xa_erase(&esw->vports, vport->vport); + kfree(vport); +} + +static void crete_esw_vports_cleanup(struct crete_eswitch *esw) +{ + struct crete_vport *vport; + unsigned long i; + + crete_esw_for_each_vport(esw, i, vport) + crete_esw_vport_free(esw, vport); + xa_destroy(&esw->vports); +} + +static int crete_esw_vports_init(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + int idx = 0; + int err; + int i; + + xa_init(&esw->vports); + + err = crete_esw_vport_alloc(esw, idx, CRETE_VPORT_PF); + if (err) + goto err; + if (esw->first_host_vport == CRETE_VPORT_PF) + xa_set_mark(&esw->vports, idx, CRETE_ESW_VPT_HOST_FN); + idx++; + + for (i = 0; i < crete_core_max_vfs(dev); i++) { + err = crete_esw_vport_alloc(esw, idx, idx); + if (err) + goto err; + xa_set_mark(&esw->vports, idx, CRETE_ESW_VPT_VF); + xa_set_mark(&esw->vports, idx, CRETE_ESW_VPT_HOST_FN); + idx++; + } + + err = crete_esw_vport_alloc(esw, idx, CRETE_VPORT_UPLINK); + if (err) + goto err; + return 0; + +err: + crete_esw_vports_cleanup(esw); + return err; +} + + +int crete_eswitch_init(struct crete_core_dev *dev) +{ + struct crete_eswitch *esw; + int err; + struct device *device = &dev->pdev->dev; + + esw = kzalloc(sizeof(*esw), GFP_KERNEL); + if (!esw) + return -ENOMEM; + + esw->dev = dev; + esw->manager_vport = crete_eswitch_manager_vport(dev); + esw->first_host_vport = crete_eswitch_first_host_vport_num(dev); + esw->work_queue = create_singlethread_workqueue("crete_esw_wq"); + if (!esw->work_queue) { + err = -ENOMEM; + goto free_esw; + } + + err = crete_esw_vports_init(esw); + if (err) + goto esw_vports_init_fail; + + + mutex_init(&esw->state_lock); + init_rwsem(&esw->mode_lock); + + esw->enabled_vports = 0; + esw->mode = CRETE_ESWITCH_LEGACY; + + dev->eswitch = esw; + esw_info(device, + "Total vports %d, per vport: max uc(%d) max mc(%d)\n", + esw->total_vports, + CRETE_MAX_UC_PER_VPORT(dev), + CRETE_MAX_MC_PER_VPORT(dev)); + return 0; +esw_vports_init_fail: + if (esw->work_queue) + destroy_workqueue(esw->work_queue); + + +free_esw: + kfree(esw); + return err; +} + +void crete_eswitch_cleanup(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + if (!esw) + return; + + esw_info(device, "cleanup\n"); + + esw->dev->eswitch = NULL; + destroy_workqueue(esw->work_queue); + mutex_destroy(&esw->state_lock); + crete_esw_vports_cleanup(esw); + kfree(esw); +} + + +static int esw_create_legacy_table(struct crete_eswitch *esw) +{ + return 0; +} + +static void esw_destroy_legacy_table(struct crete_eswitch *esw) +{ + +} + +struct crete_vport * +crete_eswitch_get_vport(struct crete_eswitch *esw, u16 vport_num) +{ + struct crete_vport *vport; + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + if (!esw) + return ERR_PTR(-EPERM); + + vport = xa_load(&esw->vports, vport_num); + if (!vport) { + esw_debug(device, "vport out of range: num(0x%x)\n", vport_num); + return ERR_PTR(-EINVAL); + } + return vport; +} + +int crete_modify_vport_admin_state(struct crete_core_dev *mdev, u8 opmod, + u16 vport, u8 other_vport, u8 state) +{ + //adminQ API + struct device *device = &mdev->pdev->dev; + + dev_warn(device, "%s modify vport admin state stub\n", __func__); + return 0; +} + +int crete_modify_nic_vport_mac_address(struct crete_core_dev *mdev, + u16 vport, const u8 *addr) +{ + struct device *device = &mdev->pdev->dev; + + dev_warn(device, "%s modify vport mac address stub\n", __func__); + return 0; +} + + +/* Apply vport rx mode to HW FDB table */ +static void esw_apply_vport_rx_mode(struct crete_eswitch *esw, + struct crete_vport *vport, + bool promisc, bool mc_promisc) +{ + //adminQ API + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s modify vport set rx mod stub\n", __func__); +} + +static int esw_vport_setup(struct crete_eswitch *esw, struct crete_vport *vport) +{ + u16 vport_num = vport->vport; + + if (crete_esw_is_manager_vport(esw, vport_num)) + return 0; + + crete_modify_vport_admin_state(esw->dev, + CRETE_VPORT_STATE_OP_MOD_ESW_VPORT, + vport_num, 1, + vport->info.link_state); + + /* Host PF has its own mac. */ + if (vport_num) { + crete_modify_nic_vport_mac_address(esw->dev, vport_num, + vport->info.mac); + } + + + return 0; +} + +/* Don't cleanup vport->info, it's needed to restore vport configuration */ +static void esw_vport_cleanup(struct crete_eswitch *esw, struct crete_vport *vport) +{ + u16 vport_num = vport->vport; + + if (!crete_esw_is_manager_vport(esw, vport_num)) + crete_modify_vport_admin_state(esw->dev, + CRETE_VPORT_STATE_OP_MOD_ESW_VPORT, + vport_num, 1, + CRETE_VPORT_ADMIN_STATE_DOWN); +} + + + +int crete_esw_vport_enable(struct crete_eswitch *esw, u16 vport_num, + enum crete_esw_vport_event enabled_events) +{ + struct crete_vport *vport; + int ret; + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + vport = crete_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + mutex_lock(&esw->state_lock); + WARN_ON(vport->enabled); + + esw_debug(device, "Enabling VPORT(%d)\n", vport_num); + + ret = esw_vport_setup(esw, vport); + if (ret) + goto done; + + /* Sync with current vport context */ + vport->enabled_events = enabled_events; + vport->enabled = true; + + /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well + * in smartNIC as it's a vport group manager. + */ + esw_vport_change_handle_locked(vport); + + esw->enabled_vports++; + esw_debug(device, "Enabled VPORT(%d)\n", vport_num); +done: + mutex_unlock(&esw->state_lock); + return ret; +} + +void crete_esw_vport_disable(struct crete_eswitch *esw, u16 vport_num) +{ + struct crete_vport *vport; + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + vport = crete_eswitch_get_vport(esw, vport_num); + if (IS_ERR(vport)) + return; + + mutex_lock(&esw->state_lock); + if (!vport->enabled) + goto done; + + esw_debug(device, "Disabling vport(%d)\n", vport_num); + /* Mark this vport as disabled to discard new events */ + vport->enabled = false; + + /* We don't assume VFs will cleanup after themselves. + * Calling vport change handler while vport is disabled will cleanup + * the vport resources. + */ + esw_vport_change_handle_locked(vport); + vport->enabled_events = 0; + esw_apply_vport_rx_mode(esw, vport, false, false); + esw_vport_cleanup(esw, vport); + esw->enabled_vports--; + +done: + mutex_unlock(&esw->state_lock); +} + + +/* Public E-Switch API */ +int crete_eswitch_load_vport(struct crete_eswitch *esw, u16 vport_num, + enum crete_esw_vport_event enabled_events) +{ + int err; + + err = crete_esw_vport_enable(esw, vport_num, enabled_events); + if (err) + return err; + + return err; +} + +void crete_eswitch_unload_vport(struct crete_eswitch *esw, u16 vport_num) +{ + crete_esw_vport_disable(esw, vport_num); +} + +void crete_eswitch_unload_vf_vports(struct crete_eswitch *esw, u16 num_vfs) +{ + struct crete_vport *vport; + unsigned long i; + + crete_esw_for_each_vf_vport(esw, i, vport, num_vfs) { + if (!vport->enabled) + continue; + crete_eswitch_unload_vport(esw, vport->vport); + } +} + + +int crete_eswitch_load_vf_vports(struct crete_eswitch *esw, u16 num_vfs, + enum crete_esw_vport_event enabled_events) +{ + struct crete_vport *vport; + unsigned long i; + int err; + + crete_esw_for_each_vf_vport(esw, i, vport, num_vfs) { + err = crete_eswitch_load_vport(esw, vport->vport, enabled_events); + if (err) + goto vf_err; + } + + return 0; + +vf_err: + crete_eswitch_unload_vf_vports(esw, num_vfs); + return err; +} + +/* crete_eswitch_enable_pf_vf_vports() enables vports of PF, VFs + * whichever are present on the eswitch. + */ +int +crete_eswitch_enable_pf_vf_vports(struct crete_eswitch *esw, + enum crete_esw_vport_event enabled_events) +{ + int ret; + + /* Enable PF vport */ + ret = crete_eswitch_load_vport(esw, CRETE_VPORT_PF, enabled_events); + if (ret) + return ret; + + /* Enable VF vports */ + ret = crete_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs, + enabled_events); + if (ret) + goto vf_err; + return 0; + +vf_err: + crete_eswitch_unload_vport(esw, CRETE_VPORT_PF); + return ret; +} + + +/* crete_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs + * whichever are previously enabled on the eswitch. + */ +void crete_eswitch_disable_pf_vf_vports(struct crete_eswitch *esw) +{ + crete_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); + + crete_eswitch_unload_vport(esw, CRETE_VPORT_PF); +} + + +int esw_legacy_enable(struct crete_eswitch *esw) +{ + struct crete_vport *vport; + unsigned long i; + int ret; + + ret = esw_create_legacy_table(esw); + if (ret) + return ret; + + crete_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) + vport->info.link_state = CRETE_VPORT_ADMIN_STATE_AUTO; + + ret = crete_eswitch_enable_pf_vf_vports(esw, CRETE_LEGACY_SRIOV_VPORT_EVENTS); + if (ret) + esw_destroy_legacy_table(esw); + + crete_offloads_rep_cleanup(esw); + + return ret; +} + +void esw_legacy_disable(struct crete_eswitch *esw) +{ + crete_eswitch_disable_pf_vf_vports(esw); + + esw_destroy_legacy_table(esw); +} + +static int eswitch_vport_event(struct notifier_block *nb, + unsigned long type, void *data) +{ + struct crete_eswitch *esw = crete_nb_cof(nb, struct crete_eswitch, nb); + //struct crete_eqe *eqe = data; + struct crete_vport *vport; + u16 vport_num = 0; + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s vport event stub\n", __func__); + //vport_num = be16_to_cpu(eqe->data.vport_change.vport_num); + vport = crete_eswitch_get_vport(esw, vport_num); + if (!IS_ERR(vport)) + queue_work(esw->work_queue, &vport->vport_change_handler); + return NOTIFY_OK; +} + +static void crete_eswitch_event_handlers_register(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + CRETE_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); + //crete_eq_notifier_register(esw->dev, &esw->nb); + dev_warn(device, "%s vport event eq_notifier_register stub\n", __func__); +} + +static void crete_eswitch_event_handlers_unregister(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + //crete_eq_notifier_unregister(esw->dev, &esw->nb); + dev_warn(device, "%s vport event eq_notifier_unregister stub\n", __func__); + + flush_workqueue(esw->work_queue); +} + + +static void +crete_eswitch_update_num_of_vfs(struct crete_eswitch *esw, int num_vfs) +{ + if (num_vfs < 0) + return; + esw->esw_funcs.num_vfs = num_vfs; +} + +/** + * crete_eswitch_enable_locked - Enable eswitch + * @esw: Pointer to eswitch + * @num_vfs: Enable eswitch for given number of VFs. This is optional. + * Valid value are 0, > 0 and CRETE_ESWITCH_IGNORE_NUM_VFS. + * Caller should pass num_vfs > 0 when enabling eswitch for + * vf vports. Caller should pass num_vfs = 0, when eswitch + * is enabled without sriov VFs. Caller should pass < 0 when num_vfs should be + * completely ignored. This is typically the case when eswitch + * is enabled without sriov regardless of PF system. + * crete_eswitch_enable_locked() Enables eswitch in either legacy or offloads + * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports. + * It returns 0 on success or error code on failure. + */ +int crete_eswitch_enable_locked(struct crete_eswitch *esw, int num_vfs) +{ + int err; + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + lockdep_assert_held(&esw->mode_lock); + crete_eswitch_update_num_of_vfs(esw, num_vfs); + + if (esw->mode == CRETE_ESWITCH_LEGACY) { + err = esw_legacy_enable(esw); + if (err) + return err; + } else { + dev_warn(device, "%s eswitch enable fake offload mode\n", __func__); + err = esw_offloads_enable(esw); + crete_rescan_drivers(esw->dev); + } + + crete_eswitch_event_handlers_register(esw); + + esw_info(device, "Enable: mode(%s), nvfs(%d), active vports(%d)\n", + esw->mode == CRETE_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", + esw->esw_funcs.num_vfs, esw->enabled_vports); + + return 0; +} + +/** + * crete_eswitch_enable - Enable eswitch + * @esw: Pointer to eswitch + * @num_vfs: Enable eswitch switch for given number of VFs. + * Caller must pass num_vfs > 0 when enabling eswitch for + * vf vports. + * crete_eswitch_enable() returns 0 on success or error code on failure. + */ +int crete_eswitch_enable(struct crete_eswitch *esw, int num_vfs) +{ + int ret = 0; + + if (!crete_esw_allowed(esw)) + return 0; + + down_write(&esw->mode_lock); + if (!crete_esw_is_fdb_created(esw)) { + ret = crete_eswitch_enable_locked(esw, num_vfs); + } else { + enum crete_esw_vport_event vport_events; + + vport_events = (esw->mode == CRETE_ESWITCH_LEGACY) ? + CRETE_LEGACY_SRIOV_VPORT_EVENTS : CRETE_VPORT_UC_ADDR_CHANGE; + + ret = crete_eswitch_load_vf_vports(esw, num_vfs, vport_events); + if (!ret) + esw->esw_funcs.num_vfs = num_vfs; + + crete_load_reps_all_vport(esw); + } + + up_write(&esw->mode_lock); + + return ret; +} + +void crete_eswitch_disable(struct crete_eswitch *esw) +{ + if (!crete_esw_allowed(esw)) + return; + + down_write(&esw->mode_lock); + crete_eswitch_disable_locked(esw); + esw->mode = CRETE_ESWITCH_LEGACY; + up_write(&esw->mode_lock); +} + +static void crete_eswitch_clear_vf_vports_info(struct crete_eswitch *esw) +{ + struct crete_vport *vport; + unsigned long i; + + crete_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) { + memset(&vport->qos, 0, sizeof(vport->qos)); + memset(&vport->info, 0, sizeof(vport->info)); + vport->info.link_state = CRETE_VPORT_ADMIN_STATE_AUTO; + } +} + +/* When disabling sriov, free driver level resources. */ +void crete_eswitch_disable_sriov(struct crete_eswitch *esw, bool clear_vf) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + if (!crete_esw_allowed(esw)) + return; + + down_write(&esw->mode_lock); + /* If driver is unloaded, this function is called twice by remove_one() + * and crete_unload(). Prevent the second call. + */ + if (!esw->esw_funcs.num_vfs && !clear_vf) + goto unlock; + + esw_info(device, "Unload vfs: mode(%s), nvfs(%d), active vports(%d)\n", + esw->mode == CRETE_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", + esw->esw_funcs.num_vfs, esw->enabled_vports); + + + crete_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); + if (clear_vf) + crete_eswitch_clear_vf_vports_info(esw); + + crete_unload_reps_all_vport(esw); + + /* Destroy legacy fdb when disabling sriov in legacy mode. */ + if (esw->mode == CRETE_ESWITCH_LEGACY) + crete_eswitch_disable_locked(esw); + + esw->esw_funcs.num_vfs = 0; + + +unlock: + up_write(&esw->mode_lock); +} + +/* Free resources for corresponding eswitch mode. It is called by devlink + * when changing eswitch mode or modprobe when unloading driver. + */ +void crete_eswitch_disable_locked(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + /* Notify eswitch users that it is exiting from current mode. + * So that it can do necessary cleanup before the eswitch is disabled. + */ + crete_eswitch_event_handlers_unregister(esw); + + esw_info(device, "Disable: mode(%s), nvfs(%d), active vports(%d)\n", + esw->mode == CRETE_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", + esw->esw_funcs.num_vfs, esw->enabled_vports); + + if (esw->mode == CRETE_ESWITCH_OFFLOADS) + esw_offloads_disable(esw); + else if (esw->mode == CRETE_ESWITCH_LEGACY) + esw_legacy_disable(esw); +} + +static int crete_cmd_set_esw_vport_uc_mac(struct crete_eswitch *esw, + u16 vport_num, const u8 *mac) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_uc_mac_in); + int out_len = CRETE_ST_SZ_BYTES(set_uc_mac_out); + void *in, *out, *uc_mac_list_in_base; + int uc_list_num = 1; + int uc_mac_list_size = uc_list_num * CRETE_ST_SZ_BYTES(uc_mac_list); + + in_len += ALIGN_TO_DW(uc_mac_list_size); + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + uc_mac_list_in_base = in + in_len - ALIGN_TO_DW(uc_mac_list_size); + + CRETE_SET(set_uc_mac_in, in, cmd_op, 1); + CRETE_SET(set_uc_mac_in, in, cmd_id, CRETE_CMD_SET_UC_MAC); + CRETE_SET(set_uc_mac_in, in, uc_list_num, uc_list_num); + CRETE_SET(set_uc_mac_in, in, vport_id, vport_num); + memcpy(uc_mac_list_in_base, mac, ETH_ALEN); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_uc_mac_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_uc_mac_out, out, err_type); + dev_warn(device, "crete esw_vport_uc_mac failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + + dev_warn(device, "%s esw_vport_uc_mac ret:0x%x\n", __func__, ret); + + return ret; +} + +static int crete_cmd_set_esw_vport_state(struct crete_eswitch *esw, + u16 vport_num, int link_state) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_vport_link_state_in); + int out_len = CRETE_ST_SZ_BYTES(set_vport_link_state_out); + void *in, *out; + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(set_vport_link_state_in, in, cmd_op, 1); + CRETE_SET(set_vport_link_state_in, in, cmd_id, CRETE_CMD_SET_VPORT_LINK_STATE); + CRETE_SET(set_vport_link_state_in, in, vport_id, vport_num); + CRETE_SET(set_vport_link_state_in, in, link_state, link_state); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_vport_link_state_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_vport_link_state_out, out, err_type); + dev_warn(device, "crete esw_vport_link_state failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + + dev_warn(device, "%s esw_vport_link_state ret:0x%x\n", __func__, ret); + + return ret; +} + +static int crete_cmd_set_esw_vport_trust(struct crete_eswitch *esw, + u16 vport_num, bool setting) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_vport_trust_in); + int out_len = CRETE_ST_SZ_BYTES(set_vport_trust_out); + void *in, *out; + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(set_vport_trust_in, in, cmd_op, 1); + CRETE_SET(set_vport_trust_in, in, cmd_id, CRETE_CMD_SET_TRUST); + CRETE_SET(set_vport_trust_in, in, vport_id, vport_num); + if (setting) + CRETE_SET(set_vport_trust_in, in, trust_state, 1); + else + CRETE_SET(set_vport_trust_in, in, trust_state, 0); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_vport_trust_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_vport_trust_out, out, err_type); + dev_warn(device, "crete esw_vport_trust_out failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + + dev_warn(device, "%s esw_vport_trust_out ret:0x%x\n", __func__, ret); + + return ret; +} + +static int crete_cmd_set_esw_vport_spoof(struct crete_eswitch *esw, + u16 vport_num, bool spoofchk) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_vport_spoof_in); + int out_len = CRETE_ST_SZ_BYTES(set_vport_spoof_out); + void *in, *out; + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(set_vport_spoof_in, in, cmd_op, 1); + CRETE_SET(set_vport_spoof_in, in, cmd_id, CRETE_CMD_SET_VPORT_LINK_STATE); + CRETE_SET(set_vport_spoof_in, in, vport_id, vport_num); + if (spoofchk) + CRETE_SET(set_vport_spoof_in, in, spoof_state, 1); + else + CRETE_SET(set_vport_spoof_in, in, spoof_state, 0); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_vport_spoof_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_vport_spoof_out, out, err_type); + dev_warn(device, "crete esw_vport_spoof_out failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + + dev_warn(device, "%s esw_vport_spoof_out ret:0x%x\n", __func__, ret); + + return ret; +} + +static int crete_cmd_set_esw_vport_vlan(struct crete_eswitch *esw, + int vport, u16 vlan, u8 qos, __be16 vlan_proto) +{ + struct crete_core_dev *core_dev = esw->dev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_rx_mode_in); + int out_len = CRETE_ST_SZ_BYTES(set_rx_mode_out); + void *in, *out, *vlan_list_in_base; + int vlan_range_num = 1; + int vlan_range_list_size = vlan_range_num * CRETE_ST_SZ_BYTES(vlan_range); + + in_len += ALIGN_TO_DW(vlan_range_list_size); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + vlan_list_in_base = in + in_len - ALIGN_TO_DW(vlan_range_list_size); + + CRETE_SET(set_rx_mode_in, in, cmd_op, 1); + CRETE_SET(set_rx_mode_in, in, cmd_id, CRETE_CMD_SET_VPORT_RX_MODE); + CRETE_SET(set_rx_mode_in, in, vport_id, vport); + if (vlan == 0) { + CRETE_SET(set_rx_mode_in, in, vlan_fliter, 0); + CRETE_SET(set_rx_mode_in, in, vlan_filter_mode, 0); + in_len -= ALIGN_TO_DW(vlan_range_list_size); + } else { + CRETE_SET(set_rx_mode_in, in, vlan_fliter, 1); + CRETE_SET(set_rx_mode_in, in, vlan_tpid, 1); + CRETE_SET(set_rx_mode_in, in, vlan_filter_mode, 2); + CRETE_SET(set_rx_mode_in, in, vlan_range_num, vlan_range_num); + CRETE_SET(vlan_range, vlan_list_in_base, start_vlan, vlan); + CRETE_SET(vlan_range, vlan_list_in_base, end_vlan, vlan); + } + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_rx_mode_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_rx_mode_out, out, err_type); + crete_err(&pdev->dev, "crete set vport_vlan failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + return ret; + + dev_warn(&pdev->dev, "%s esw_vport_vlan ret:0x%x\n", __func__, ret); + + return ret; +} + + +static int crete_cmd_set_esw_vport_rate(struct crete_eswitch *esw, + u16 vport, u32 max_rate) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_vf_shaper_in); + int out_len = CRETE_ST_SZ_BYTES(set_vf_shaper_out); + void *in, *out; + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(set_vf_shaper_in, in, cmd_op, 1); + CRETE_SET(set_vf_shaper_in, in, cmd_id, CRETE_CMD_SET_VF_SHAPER); + CRETE_SET(set_vf_shaper_in, in, mode, 0); + CRETE_SET(set_vf_shaper_in, in, vport_id, vport); + CRETE_SET(set_vf_shaper_in, in, max_rate, max_rate); + + hexdump((char *)in, in_len); + ret = crete_cmd_exec_polling(dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_vf_shaper_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_vf_shaper_out, out, err_type); + dev_warn(device, "crete set_vf_shaper_out failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + + dev_warn(device, "%s set_vf_shaper_out ret:0x%x\n", __func__, ret); + + return ret; +} + + +int crete_eswitch_set_vport_mac(struct crete_eswitch *esw, + u16 vport, const u8 *mac) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s set vport mac adminQ\n", __func__); + return crete_cmd_set_esw_vport_uc_mac(esw, vport, mac); +} +int crete_eswitch_set_vport_state(struct crete_eswitch *esw, + u16 vport, int link_state) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s set vport link state adminQ\n", __func__); + return crete_cmd_set_esw_vport_state(esw, vport, link_state); +} + +int crete_eswitch_set_vport_vlan(struct crete_eswitch *esw, + int vport, u16 vlan, u8 qos, __be16 vlan_proto) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s set vport vlan adminQ\n", __func__); + return crete_cmd_set_esw_vport_vlan(esw, vport, vlan, qos, vlan_proto); +} + +int crete_eswitch_set_vport_spoofchk(struct crete_eswitch *esw, + u16 vport, bool spoofchk) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s set vport spoofchk adminQ\n", __func__); + return crete_cmd_set_esw_vport_spoof(esw, vport, spoofchk); +} + +int crete_eswitch_set_vport_trust(struct crete_eswitch *esw, + u16 vport_num, bool setting) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s set vport trust adminQ\n", __func__); + return crete_cmd_set_esw_vport_trust(esw, vport_num, setting); +} + +int crete_eswitch_set_vport_rate(struct crete_eswitch *esw, u16 vport, + u32 max_rate, u32 min_rate) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s set vport rate\n", __func__); + return crete_cmd_set_esw_vport_rate(esw, vport, max_rate); +} + + +/** + * crete_esw_hold() - Try to take a read lock on esw mode lock. + * @mdev: crete core device. + * + * Should be called by esw resources callers. + * + * Return: true on success or false. + */ +bool crete_esw_hold(struct crete_core_dev *mdev) +{ + struct crete_eswitch *esw = mdev->eswitch; + + /* e.g. VF doesn't have eswitch so nothing to do */ + if (!crete_esw_allowed(esw)) + return true; + + if (down_read_trylock(&esw->mode_lock) != 0) + return true; + + return false; +} + +/** + * crete_esw_release() - Release a read lock on esw mode lock. + * @mdev: crete core device. + */ +void crete_esw_release(struct crete_core_dev *mdev) +{ + struct crete_eswitch *esw = mdev->eswitch; + + if (crete_esw_allowed(esw)) + up_read(&esw->mode_lock); +} + +/** + * crete_esw_get() - Increase esw user count. + * @mdev: crete core device. + */ +void crete_esw_get(struct crete_core_dev *mdev) +{ + struct crete_eswitch *esw = mdev->eswitch; + + if (crete_esw_allowed(esw)) + atomic64_inc(&esw->user_count); +} + +/** + * crete_esw_put() - Decrease esw user count. + * @mdev: crete core device. + */ +void crete_esw_put(struct crete_core_dev *mdev) +{ + struct crete_eswitch *esw = mdev->eswitch; + + if (crete_esw_allowed(esw)) + atomic64_dec_if_positive(&esw->user_count); +} + +/** + * crete_esw_try_lock() - Take a write lock on esw mode lock. + * @esw: eswitch device. + * + * Should be called by esw mode change routine. + * + * Return: + * * 0 - esw mode if successfully locked and refcount is 0. + * * -EBUSY - refcount is not 0. + * * -EINVAL - In the middle of switching mode or lock is already held. + */ +int crete_esw_try_lock(struct crete_eswitch *esw) +{ + if (down_write_trylock(&esw->mode_lock) == 0) + return -EINVAL; + + if (atomic64_read(&esw->user_count) > 0) { + up_write(&esw->mode_lock); + return -EBUSY; + } + + return esw->mode; +} + +/** + * crete_esw_unlock() - Release write lock on esw mode lock + * @esw: eswitch device. + */ +void crete_esw_unlock(struct crete_eswitch *esw) +{ + up_write(&esw->mode_lock); +} + + +int esw_offloads_start(struct crete_eswitch *esw, + struct netlink_ext_ack *extack) +{ + int err; + int vf_nums = crete_core_max_vfs(esw->dev); + + esw->mode = CRETE_ESWITCH_OFFLOADS; + err = crete_eswitch_enable_locked(esw, vf_nums); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Failed setting eswitch to offloads"); + esw->mode = CRETE_ESWITCH_LEGACY; + crete_rescan_drivers(esw->dev); + return err; + } + + return 0; +} + +int esw_offloads_stop(struct crete_eswitch *esw, + struct netlink_ext_ack *extack) +{ + int err; + + esw->mode = CRETE_ESWITCH_LEGACY; + + /* If changing from switchdev to legacy mode without sriov enabled, + * no need to create legacy fdb. + */ + if (!crete_core_is_pf(esw->dev) || !crete_sriov_is_enabled(esw->dev)) + return 0; + + err = crete_eswitch_enable_locked(esw, CRETE_ESWITCH_IGNORE_NUM_VFS); + if (err) + NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy"); + + return err; +} + +static int esw_offloads_enable(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + crete_offloads_rep_init(esw); + dev_warn(device, "%s eswitch enable offload mode stub\n", __func__); + return 0; +} +static void esw_offloads_disable(struct crete_eswitch *esw) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s eswitch disable offload mode stub\n", __func__); + +} + +int crete_eswitch_add_vport_trunk_range(struct crete_eswitch *esw, + int vport, u16 start_vlan, u16 end_vlan) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s eswitch stub\n", __func__); + + return 0; +} + +int crete_eswitch_del_vport_trunk_range(struct crete_eswitch *esw, + int vport, u16 start_vlan, u16 end_vlan) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s eswitch stub\n", __func__); + + return 0; +} + +int crete_esw_qos_set_sysfs_group_max_rate(struct crete_eswitch *esw, + struct crete_esw_rate_group *group, + u32 max_rate) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s eswitch stub\n", __func__); + return 0; +} + +int crete_esw_qos_set_sysfs_group_min_rate(struct crete_eswitch *esw, + struct crete_esw_rate_group *group, + u32 min_rate) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s eswitch stub\n", __func__); + return 0; +} + +int crete_esw_qos_vport_update_sysfs_group(struct crete_eswitch *esw, int vport_num, u32 group_id) +{ + struct crete_core_dev *dev = esw->dev; + struct device *device = &dev->pdev->dev; + + dev_warn(device, "%s eswitch stub\n", __func__); + return 0; +} + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswitch.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswitch.h new file mode 100644 index 0000000..7368ed3 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswitch.h @@ -0,0 +1,295 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __CRETE_ESWITCH_H +#define __CRETE_ESWITCH_H +#include +#include +#include +#include +#include +#include "crete_event.h" + +/* The vport iterator is valid only after vport are initialized in mlx5_eswitch_init. + * Borrowed the idea from xa_for_each_marked() but with support for desired last element. + */ + +#define crete_esw_for_each_vport(esw, index, vport) \ + xa_for_each(&((esw)->vports), index, vport) + +#define crete_esw_for_each_rep(esw, i, rep) \ + xa_for_each(&((esw)->eswoffloads.vport_reps), i, rep) + +#define crete_esw_for_each_entry_marked(xa, index, entry, last, filter) \ + for (index = 0, entry = xa_find(xa, &index, last, filter); \ + entry; entry = xa_find_after(xa, &index, last, filter)) + +#define crete_esw_for_each_vport_marked(esw, index, vport, last, filter) \ + crete_esw_for_each_entry_marked(&((esw)->vports), index, vport, last, filter) + +#define crete_esw_for_each_vf_vport(esw, index, vport, last) \ + crete_esw_for_each_vport_marked(esw, index, vport, last, CRETE_ESW_VPT_VF) + +#define crete_esw_for_each_host_func_vport(esw, index, vport, last) \ + crete_esw_for_each_vport_marked(esw, index, vport, last, CRETE_ESW_VPT_HOST_FN) + +/* Each mark identifies eswitch vport type. + * CRETE_ESW_VPT_HOST_FN is used to identify both PF and VF ports using + * a single mark. + * MLX5_ESW_VPT_VF identifies a SRIOV VF vport. + * MLX5_ESW_VPT_SF identifies SF vport. + */ +#define CRETE_ESW_VPT_HOST_FN XA_MARK_0 +#define CRETE_ESW_VPT_VF XA_MARK_1 +#define CRETE_ESW_VPT_SF XA_MARK_2 + +/* stub start*/ +#define CRETE_MAX_UC_PER_VPORT(dev) (8) +#define CRETE_MAX_MC_PER_VPORT(dev) (8) +#define CRETE_EVENT_TYPE_NIC_VPORT_CHANGE 0xd +#define CRETE_EVENT_TYPE_ESW_FUNCTIONS_CHANGED 0xe +#define CRETE_MAX_CFA_CODE (65535) +#define CRETE_VF_IDX_INVALID 0xffff + +/* stub end*/ +#define CRETE_ESWITCH_IGNORE_NUM_VFS (-1) + +struct crete_esw_fun { + struct crete_nb nb; + u16 num_vfs; +}; + +/* Vport number for each function must keep unchanged */ +enum { + CRETE_VPORT_PF = 0x0, + CRETE_VPORT_FIRST_VF = 0x1, + CRETE_VPORT_UPLINK = 0xffff +}; + +#define VPORT(vfid) (vfid + CRETE_VPORT_FIRST_VF) +enum { + CRETE_VPORT_STATE_OP_MOD_VNIC_VPORT = 0x0, + CRETE_VPORT_STATE_OP_MOD_ESW_VPORT = 0x1, + CRETE_VPORT_STATE_OP_MOD_UPLINK = 0x2, +}; + +struct crete_vport_info { + u8 mac[ETH_ALEN]; + u16 vlan; + int link_state; + u8 qos; + __be16 vlan_proto; + u8 spoofchk:1; + u8 trusted:1; + /* the admin approved vlan list */ + DECLARE_BITMAP(vlan_trunk_8021q_bitmap, VLAN_N_VID); + u32 group; + +}; + +/* Vport context events */ +enum crete_esw_vport_event { + CRETE_VPORT_UC_ADDR_CHANGE = BIT(0), + CRETE_VPORT_MC_ADDR_CHANGE = BIT(1), + CRETE_VPORT_PROMISC_CHANGE = BIT(3), +}; + +enum { + CRETE_VPORT_ADMIN_STATE_DOWN = 0x0, + CRETE_VPORT_ADMIN_STATE_UP = 0x1, + CRETE_VPORT_ADMIN_STATE_AUTO = 0x2, +}; + +enum { + CRETE_ESWITCH_LEGACY, + CRETE_ESWITCH_OFFLOADS +}; + +enum { + REP_UNREGISTERED, + REP_REGISTERED, + REP_LOADED, +}; + +#define CRETE_LEGACY_SRIOV_VPORT_EVENTS (CRETE_VPORT_UC_ADDR_CHANGE | \ + CRETE_VPORT_MC_ADDR_CHANGE | \ + CRETE_VPORT_PROMISC_CHANGE) + +struct crete_vport { + struct crete_core_dev *dev; + struct crete_vport_info info; + struct work_struct vport_change_handler; + + struct { + bool enabled; + u32 min_rate; + u32 max_rate; + struct crete_esw_rate_group *group; + + } qos; + + u16 vport; + bool enabled; + enum crete_esw_vport_event enabled_events; + int index; + struct devlink_port *dl_port; +}; + +enum { + CRETE_ESW_FDB_CREATED = BIT(0), +}; + +struct crete_esw_rep; + +struct crete_esw_offload { + struct xarray vport_reps; + u16 *cfa_code_map; + +}; + +struct crete_vf_rep_stats { + u64 packets; + u64 bytes; + u64 dropped; +}; + +struct crete_esw_rep { + struct crete_core_dev *cdev; + struct net_device *dev; + struct metadata_dst *dst; + u16 vport_idx; + u16 tx_cfa_action; + u16 rx_cfa_code; + u16 sfi_code; + + struct crete_vf_rep_stats rx_stats; + struct crete_vf_rep_stats tx_stats; + struct crete_eswitch *esw; + atomic_t state; +}; + +struct crete_eswitch { + struct crete_core_dev *dev; + struct xarray vports; + int total_vports; /* nums(PF) + nums(VF) + nums(uplink) */ + int enabled_vports; + int mode; /* legacy or offload */ + u16 manager_vport; /* vport0(PF) */ + u16 first_host_vport; /* first vf */ + + /* Synchronize between vport change events + * and async SRIOV admin state changes + */ + struct mutex state_lock; + /* Protects eswitch mode change that occurs via one or more + * user commands, i.e. sriov state change, devlink commands. + */ + struct rw_semaphore mode_lock; + atomic64_t user_count; + + struct workqueue_struct *work_queue; /* vport change handle */ + + struct crete_nb nb; + struct crete_esw_fun esw_funcs; + struct crete_esw_offload eswoffloads; +}; + +/** + * crete_esw_event_info - Indicates eswitch mode changed/changing. + * + * @new_mode: New mode of eswitch. + */ +struct crete_esw_event_info { + u16 new_mode; +}; + +/* Init API */ +int crete_eswitch_init(struct crete_core_dev *dev); +void crete_eswitch_cleanup(struct crete_eswitch *esw); + +/* SRIOV API */ +int crete_eswitch_enable(struct crete_eswitch *esw, int num_vfs); +void crete_eswitch_disable_sriov(struct crete_eswitch *esw, bool clear_vf); +void crete_eswitch_disable(struct crete_eswitch *esw); +void crete_eswitch_disable_locked(struct crete_eswitch *esw); + +/* eswitch vport API */ +int crete_eswitch_set_vport_mac(struct crete_eswitch *esw, + u16 vport, const u8 *mac); +int crete_eswitch_set_vport_state(struct crete_eswitch *esw, + u16 vport, int link_state); +int crete_eswitch_set_vport_vlan(struct crete_eswitch *esw, + int vport, u16 vlan, u8 qos, + __be16 vlan_proto); +int crete_eswitch_set_vport_spoofchk(struct crete_eswitch *esw, u16 vport, + bool spoofchk); +int crete_eswitch_set_vport_trust(struct crete_eswitch *esw, u16 vport_num, + bool setting); +int crete_eswitch_set_vport_rate(struct crete_eswitch *esw, u16 vport, + u32 max_rate, u32 min_rate); + +/* eswitch rw lock API */ +bool crete_esw_hold(struct crete_core_dev *dev); +void crete_esw_release(struct crete_core_dev *dev); +void crete_esw_get(struct crete_core_dev *dev); +void crete_esw_put(struct crete_core_dev *dev); +int crete_esw_try_lock(struct crete_eswitch *esw); +void crete_esw_unlock(struct crete_eswitch *esw); + +/* devlink API */ +int esw_offloads_start(struct crete_eswitch *esw, + struct netlink_ext_ack *extack); +int esw_offloads_stop(struct crete_eswitch *esw, + struct netlink_ext_ack *extack); + +struct crete_vport *crete_eswitch_get_vport(struct crete_eswitch *esw, + u16 vport_num); + +int crete_eswitch_add_vport_trunk_range(struct crete_eswitch *esw, + int vport, u16 start_vlan, + u16 end_vlan); + +int crete_eswitch_del_vport_trunk_range(struct crete_eswitch *esw, + int vport, u16 start_vlan, + u16 end_vlan); + +int crete_esw_qos_set_sysfs_group_max_rate(struct crete_eswitch *esw, + struct crete_esw_rate_group *group, + u32 max_rate); +int crete_esw_qos_set_sysfs_group_min_rate(struct crete_eswitch *esw, + struct crete_esw_rate_group *group, + u32 min_rate); +int crete_esw_qos_vport_update_sysfs_group(struct crete_eswitch *esw, + int vport_num, u32 group_id); + +#endif /* __CRETE_ESWITCH_H */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswoffloads.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswoffloads.c new file mode 100644 index 0000000..32e8e26 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswoffloads.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crete.h" +#include "crete_eswitch.h" +#include "crete_rep.h" + +int crete_offloads_rep_cleanup(struct crete_eswitch *esw) +{ + struct crete_esw_rep *rep; + unsigned long i; + + crete_esw_for_each_rep(esw, i, rep) { + xa_erase(&esw->eswoffloads.vport_reps, rep->vport_idx); + kfree(rep); + } + + xa_destroy(&esw->eswoffloads.vport_reps); + kfree(esw->eswoffloads.cfa_code_map); + esw->eswoffloads.cfa_code_map = NULL; + + return 0; +} + +/* + * crete offloads representors initial + * init the offloads reps xarray + * alloc the reps struct and cfa code map + */ +int crete_offloads_rep_init(struct crete_eswitch *esw) +{ + struct crete_vport *vport; + struct crete_esw_rep *rep; + unsigned long i; + int err; + + xa_init(&esw->eswoffloads.vport_reps); + + crete_esw_for_each_vport(esw, i, vport) { + rep = kzalloc(sizeof(*rep), GFP_KERNEL); + if (!rep) { + err = -ENOMEM; + goto err; + } + rep->vport_idx = vport->index; + atomic_set(&rep->state, REP_UNREGISTERED); + + err = + xa_insert(&esw->eswoffloads.vport_reps, vport->index, rep, + GFP_KERNEL); + if (err) { + kfree(rep); + goto err; + } + } + + esw->eswoffloads.cfa_code_map = kcalloc(CRETE_MAX_CFA_CODE, + sizeof(*esw->eswoffloads.cfa_code_map), GFP_KERNEL); + if (!esw->eswoffloads.cfa_code_map) { + err = -ENOMEM; + goto err; + } + + for (i = 0; i < CRETE_MAX_CFA_CODE; i++) + esw->eswoffloads.cfa_code_map[i] = CRETE_VF_IDX_INVALID; + + return 0; + +err: + crete_offloads_rep_cleanup(esw); + return err; +} + +void crete_unload_reps_all_vport(struct crete_eswitch *esw) +{ + struct crete_esw_rep *rep; + unsigned long i; + + crete_esw_for_each_rep(esw, i, rep) { + + if (atomic_read(&rep->state) != REP_LOADED) + continue; + + crete_alloc_vf_rep_unload(esw->dev, rep); + + atomic_set(&rep->state, REP_REGISTERED); + + } +} + +int crete_load_reps_all_vport(struct crete_eswitch *esw) +{ + struct crete_esw_rep *rep; + unsigned long i; + int err; + + crete_esw_for_each_rep(esw, i, rep) { + + /* not exceed the max enable vf numbers */ + if (i >= esw->esw_funcs.num_vfs) + break; + /* check the rep is registered */ + if (atomic_read(&rep->state) != REP_REGISTERED) + continue; + + if (crete_alloc_vf_rep_load(esw->dev, rep)) { + err = -ENOMEM; + goto err; + } + + atomic_set(&rep->state, REP_LOADED); + + } + + return 0; + +err: + crete_unload_reps_all_vport(esw); + return err; +} + +static void crete_eswitch_register_vport_reps(struct crete_eswitch *esw) +{ + struct crete_esw_rep *rep; + unsigned long i; + + crete_esw_for_each_rep(esw, i, rep) { + rep->esw = esw; + atomic_set(&rep->state, REP_REGISTERED); + } + +} + +static void crete_eswitch_unregister_vport_reps(struct crete_eswitch *esw) +{ + struct crete_esw_rep *rep; + unsigned long i; + + if (esw->mode == CRETE_ESWITCH_OFFLOADS) + crete_unload_reps_all_vport(esw); + + crete_esw_for_each_rep(esw, i, rep) + atomic_set(&rep->state, REP_UNREGISTERED); + +} + +static int crete_rep_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *cdev = aux_dev->core_dev; + struct crete_eswitch *esw = cdev->eswitch; + + /* rep init */ + crete_eswitch_register_vport_reps(esw); + + return 0; +} + +/* + * about the anolis 5.10.134-14 kernel version + * auxliary define with return int value + */ +#ifdef SNIC_ANOLIS_VERSION14 + +static int crete_rep_remove(struct auxiliary_device *adev) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + + crete_eswitch_unregister_vport_reps(aux_dev->core_dev->eswitch); + return 0; +} + +#else + +static void crete_rep_remove(struct auxiliary_device *adev) +{ + struct crete_aux_dev *aux_dev = + container_of(adev, struct crete_aux_dev, adev); + + crete_eswitch_unregister_vport_reps(aux_dev->core_dev->eswitch); +} + +#endif + +static const struct auxiliary_device_id crete_rep_id_table[] = { + {.name = CRETE_ADEV_NAME ".eth-rep", }, + { } +}; + +struct auxiliary_driver crete_rep_driver = { + .name = CRETE_ADEV_NAME ".eth-rep", + .probe = crete_rep_probe, + .remove = crete_rep_remove, + .id_table = crete_rep_id_table, +}; diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswoffloads.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswoffloads.h new file mode 100644 index 0000000..4def051 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_eswoffloads.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __ESWOFFLOADS_ +#define __ESWOFFLOADS_ + +int crete_offloads_rep_cleanup(struct crete_eswitch *esw); +int crete_offloads_rep_init(struct crete_eswitch *esw); +int crete_load_reps_all_vport(struct crete_eswitch *esw); +void crete_unload_reps_all_vport(struct crete_eswitch *esw); + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ethtool.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ethtool.c new file mode 100644 index 0000000..9d38ca5 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ethtool.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "crete.h" +#include "crete_cmd_if.h" +#include "crete_regs.h" +#include "crete_fw_update.h" + +struct crete_stats_desc { + char desc[ETH_GSTRING_LEN]; + size_t offset; +}; + +struct crete_stats_desc crete_txq_stats_desc[] = { + {"packets", CRETE_TXQ_STATS(packets)}, + {"bytes", CRETE_TXQ_STATS(bytes)}, + {"kicks", CRETE_TXQ_STATS(kicks)}, +}; + +struct crete_stats_desc crete_rxq_stats_desc[] = { + {"packets", CRETE_RXQ_STATS(packets)}, + {"bytes", CRETE_RXQ_STATS(bytes)}, + {"drops", CRETE_RXQ_STATS(drops)}, + {"kicks", CRETE_RXQ_STATS(kicks)}, +}; + +#define CRETE_TXQ_STATS_LEN ARRAY_SIZE(crete_txq_stats_desc) +#define CRETE_RXQ_STATS_LEN ARRAY_SIZE(crete_rxq_stats_desc) + +void crete_ethtool_get_drvinfo(struct crete_priv *priv, + struct ethtool_drvinfo *drvinfo) +{ + struct crete_core_dev *coredev = priv->coredev; + int count; + + strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%d.%d.%d.%d", fw_ver_maj(coredev), + fw_ver_min(coredev), fw_ver_sub(coredev), fw_ver_rev(coredev)); + + strscpy(drvinfo->bus_info, dev_name(&coredev->pdev->dev), + sizeof(drvinfo->bus_info)); +} + +static void crete_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + struct crete_priv *priv = netdev_priv(dev); + + crete_ethtool_get_drvinfo(priv, drvinfo); +} + +static void get_speed_duplex(struct net_device *netdev, + struct ethtool_link_ksettings *link_ksettings) +{ + u32 speed = SPEED_UNKNOWN; + u8 duplex = DUPLEX_UNKNOWN; + + if (!netif_carrier_ok(netdev)) + goto out; + + /* get speed TODO */ + + duplex = DUPLEX_FULL; + +out: + link_ksettings->base.speed = speed; + link_ksettings->base.duplex = duplex; +} + +int crete_ethtool_get_link_ksettings(struct crete_priv *priv, + struct ethtool_link_ksettings *link_ksettings) +{ + ethtool_link_ksettings_zero_link_mode(link_ksettings, supported); + ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); + + get_speed_duplex(priv->netdev, link_ksettings); + + return 0; +} + +static int crete_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *link_ksettings) +{ + struct crete_priv *priv = netdev_priv(netdev); + + return crete_ethtool_get_link_ksettings(priv, link_ksettings); +} + +int crete_ethtool_set_link_ksettings(struct crete_priv *priv, + const struct ethtool_link_ksettings *link_ksettings) +{ + struct crete_core_dev *cdev = priv->coredev; + u32 speed; + + speed = link_ksettings->base.speed; + crete_info(&cdev->pdev->dev, "set link speed:%u\n", speed); + + return 0; +} + +static int crete_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *link_ksettings) +{ + struct crete_priv *priv = netdev_priv(netdev); + + return crete_ethtool_set_link_ksettings(priv, link_ksettings); +} + +int crete_ethtool_set_pauseparam(struct crete_priv *priv, + struct ethtool_pauseparam *pauseparam) +{ + struct crete_core_dev *cdev = priv->coredev; + int err; + +// if (pauseparam->autoneg) +// return -EINVAL; + + err = crete_set_fc_enable(cdev, 1, + pauseparam->rx_pause ? 1 : 0, + pauseparam->tx_pause ? 1 : 0); + if (err) { + netdev_err(priv->netdev, "%s: crete_set_fc_enable failed:0x%x\n", + __func__, err); + } + + return err; +} + +int crete_query_port_pause(struct crete_core_dev *dev, + u32 *rx_pause, u32 *tx_pause) +{ + *rx_pause = 0; + *tx_pause = 0; + + return 0; +} + +void crete_ethtool_get_pauseparam(struct crete_priv *priv, + struct ethtool_pauseparam *pauseparam) +{ + struct crete_core_dev *cdev = priv->coredev; + int err; + + err = crete_query_port_pause(cdev, &pauseparam->rx_pause, + &pauseparam->tx_pause); + if (err) { + netdev_err(priv->netdev, "%s: crete_query_port_pause failed:0x%x\n", + __func__, err); + } +} + +static int crete_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pauseparam) +{ + struct crete_priv *priv = netdev_priv(netdev); + + return crete_ethtool_set_pauseparam(priv, pauseparam); +} + +void crete_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pauseparam) +{ + struct crete_priv *priv = netdev_priv(netdev); + + crete_ethtool_get_pauseparam(priv, pauseparam); +} + +int crete_ethtool_flash_device(struct crete_priv *priv, + struct ethtool_flash *flash) +{ + struct crete_core_dev *cdev = priv->coredev; + struct net_device *dev = priv->netdev; + const struct firmware *fw; + int err; + + if (flash->region != ETHTOOL_FLASH_ALL_REGIONS) + return -EOPNOTSUPP; + + err = request_firmware_direct(&fw, flash->data, &dev->dev); + if (err) + return err; + + dev_hold(dev); + rtnl_unlock(); + + err = crete_firmware_flash(cdev, fw, NULL, CRETE_FWU_ETHTOOL); + release_firmware(fw); + + rtnl_lock(); + dev_put(dev); + return err; +} + + +static int crete_flash_device(struct net_device *dev, + struct ethtool_flash *flash) +{ + struct crete_priv *priv = netdev_priv(dev); + + return crete_ethtool_flash_device(priv, flash); +} + +static void crete_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *cdev = priv->coredev; + char *p = (char *)data; + unsigned int i, j; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < cdev->ring_size; i++) { + for (j = 0; j < CRETE_RXQ_STATS_LEN; j++) { + snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_%s", + i, crete_rxq_stats_desc[j].desc); + p += ETH_GSTRING_LEN; + } + } + + for (i = 0; i < cdev->ring_size; i++) { + for (j = 0; j < CRETE_TXQ_STATS_LEN; j++) { + snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_%s", + i, crete_txq_stats_desc[j].desc); + p += ETH_GSTRING_LEN; + } + } + break; + } +} + +static void crete_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *cdev = priv->coredev; + unsigned int idx = 0, start, i, j; + const u8 *stats_base; + size_t offset; + + for (i = 0; i < cdev->ring_size; i++) { + stats_base = (u8 *)cdev->rxring[i].rxq_stats; + do { + start = u64_stats_fetch_begin_irq(&cdev->rxring[i].rxq_stats->syncp); + for (j = 0; j < CRETE_RXQ_STATS_LEN; j++) { + offset = crete_rxq_stats_desc[j].offset; + data[idx + j] = *(u64 *) (stats_base + offset); + } + } while (u64_stats_fetch_retry_irq(&cdev->rxring[i].rxq_stats->syncp, start)); + idx += CRETE_RXQ_STATS_LEN; + } + + for (i = 0; i < cdev->ring_size; i++) { + stats_base = (u8 *)&cdev->txring[i].txq_stats; + do { + start = u64_stats_fetch_begin_irq(&cdev->txring[i].txq_stats->syncp); + for (j = 0; j < CRETE_TXQ_STATS_LEN; j++) { + offset = crete_txq_stats_desc[j].offset; + data[idx + j] = *(u64 *) (stats_base + offset); + } + } while (u64_stats_fetch_retry_irq(&cdev->txring[i].txq_stats->syncp, start)); + idx += CRETE_TXQ_STATS_LEN; + } +} + +const struct ethtool_ops crete_ethtool_ops = { + .get_drvinfo = crete_get_drvinfo, + .get_link_ksettings = crete_get_link_ksettings, + .set_link_ksettings = crete_set_link_ksettings, + //.get_pauseparam = crete_get_pauseparam, + .set_pauseparam = crete_set_pauseparam, + .flash_device = crete_flash_device, + .get_strings = crete_get_strings, + .get_ethtool_stats = crete_get_ethtool_stats, +}; + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ethtool_common.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ethtool_common.h new file mode 100644 index 0000000..665995e --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ethtool_common.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __CRETE_ETHTOOL_COMMON_H__ +#define __CRETE_ETHTOOL_COMMON_H__ + +#include "crete.h" +#include + +#define AUTO_NEG_OP_BIT BIT(2) +#define DUPLEX_MODE_OP_BIT BIT(1) +#define LINK_SPEED_OP_BIT BIT(0) + +enum crete_link_mode { + CRETE_10GBASE = 1, + CRETE_25GBASE, + CRETE_40GBASE, + CRETE_50GBASE, + CRETE_100GBASE, + CRETE_200GBASE, + CRETE_400GBASE, + CRETE_LINK_MODES_NUMBER, +}; + +enum crete_link_mode_bit { + CRETE_10GBASE_BIT, + CRETE_25GBASE_BIT, + CRETE_40GBASE_BIT, + CRETE_50GBASE_BIT, + CRETE_100GBASE_BIT, + CRETE_200GBASE_BIT, + CRETE_400GBASE_BIT, + CRETE_LINK_MODES_CAP_BIT, +}; + +enum crete_duplex { + CRETE_HALF_DUPLEX, + CRETE_FULL_DUPLEX, + CRETE_DUPLEX_MAX, +}; +enum crete_fec_mode { + CRETE_FEC_OFF = 0, + CRETE_FEC_AUTO, + CRETE_FEC_RS, + CRETE_FEC_BASER, + CRETE_FEC_LLRS, +}; + +static const u32 crete_link_speed[CRETE_LINK_MODES_NUMBER] = { + 0, + [CRETE_10GBASE] = SPEED_10000, + [CRETE_25GBASE] = SPEED_25000, + [CRETE_40GBASE] = SPEED_40000, + [CRETE_50GBASE] = SPEED_50000, + [CRETE_100GBASE] = SPEED_100000, + [CRETE_200GBASE] = SPEED_200000, + [CRETE_400GBASE] = SPEED_400000, +}; + +static const u32 crete_fec_2_ethtool[] = { + [CRETE_FEC_OFF] = ETHTOOL_FEC_OFF, + [CRETE_FEC_AUTO] = ETHTOOL_FEC_AUTO, + [CRETE_FEC_RS] = ETHTOOL_FEC_RS, + [CRETE_FEC_BASER] = ETHTOOL_FEC_BASER, + [CRETE_FEC_LLRS] = ETHTOOL_FEC_LLRS, +}; + +static const u32 crete_fec_2_ethtool_bit[] = { + [CRETE_FEC_OFF] = ETHTOOL_LINK_MODE_FEC_NONE_BIT, + [CRETE_FEC_RS] = ETHTOOL_LINK_MODE_FEC_RS_BIT, + [CRETE_FEC_BASER] = ETHTOOL_LINK_MODE_FEC_BASER_BIT, + [CRETE_FEC_LLRS] = ETHTOOL_LINK_MODE_FEC_LLRS_BIT, +}; + +static const u8 crete_link_duplex[CRETE_DUPLEX_MAX] = { + [CRETE_HALF_DUPLEX] = DUPLEX_HALF, + [CRETE_FULL_DUPLEX] = DUPLEX_FULL, +}; + +struct crete_speed_duplex { + uint16_t speed; + uint16_t duplex; + uint32_t duplex_cap; + uint32_t speed_cap; +}; + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_event.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_event.c new file mode 100644 index 0000000..bf91264 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_event.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "crete.h" +#include "crete_cmd.h" +#include "crete_regs.h" + +#define EVNET_IN_MASK 0x02 +#define EVNET_BUSY_MASK 0x01 +#define EVNET_NO_BUSY_MASK 0xFE + +static irqreturn_t irq_int_handler(int irq, void *dev) +{ + struct crete_core_dev *cdev = (struct crete_core_dev *)dev; + struct crete_event_irq *event_irq = cdev->event_irq; + struct crete_event_entry cee; + struct crete_event_buffer_head event_buffer_head; + struct crete_hw *hw = &cdev->hw; + uint32_t total_len_dw; + uint32_t index = 1; + uint8_t val = 0; + bool device_owner = false; + bool buf_inline = false; + + val = readb(&hw->io_addr->event_busy); + if (val & EVNET_BUSY_MASK) { + device_owner = true; + buf_inline = !!(val & EVNET_IN_MASK); + } else { + dev_err(cdev->device, "device is not set owner!\n"); + return IRQ_HANDLED; + } + if(!buf_inline) { + dev_err(cdev->device, "current not support not inline!\n"); + writeb(val & EVNET_NO_BUSY_MASK, &hw->io_addr->event_busy); + return IRQ_HANDLED; + } + crete_ioread32(&hw->io_addr->event_buffer[0], + &event_buffer_head, 1); + total_len_dw = event_buffer_head.event_entry_length; + + memset(&cee, 0, sizeof(struct crete_event_entry)); + while (index <= total_len_dw) { + crete_ioread32(&hw->io_addr->event_buffer[index], &cee, 1); + if (cee.event_length) + crete_ioread32(&hw->io_addr->event_buffer[index+1], + cee.event_data, cee.event_length); + atomic_notifier_call_chain(&event_irq->nh[cee.event_type], cee.event_type, &cee); + pr_info("crete event handle event type:%u\n", cee.event_type); + index += (cee.event_length + 1); + } + writeb(val & EVNET_NO_BUSY_MASK, &hw->io_addr->event_busy); + return IRQ_HANDLED; +} + + +int crete_event_alloc_buf(struct crete_core_dev *cdev, + struct crete_event_irq *event_irq) +{ + struct crete_hw *hw = &cdev->hw; + size_t size = CRETE_EVENT_ALLOC_BUFFER_SIZE * sizeof(uint32_t); + + event_irq->event_buf_size = size; + crete_info(cdev->device, "event_irq->event_buf_size:%ld", size); + + event_irq->event_buf = dma_alloc_coherent(cdev->device, CRETE_EVENT_ALLOC_BUFFER_SIZE*4, + &event_irq->event_dma, GFP_KERNEL | __GFP_ZERO); + if (!event_irq->event_buf) + return -ENOMEM; + + crete_info(cdev->device, "event buffer dma addr:0x%llx\n", event_irq->event_dma); + + iseg_wd8(hw, struct crete_init_seg, + event_buffer_size, (u8)(event_irq->event_buf_size)); + + iseg_wd32(hw, struct crete_init_seg, event_buffer_addr_low, + (u32)(event_irq->event_dma & 0xffffffff)); + + iseg_wd32(hw, struct crete_init_seg, + event_buffer_addr_hi, (u32)(event_irq->event_dma >> 32)); + + /* Make sure firmware sees the complete address before we proceed */ + wmb(); + + return 0; +} + + +static int crete_event_start(struct crete_hw *hw) +{ + int i, err, irqno; + struct crete_event_irq *event_irq; + struct crete_core_dev *cdev = container_of(hw, + struct crete_core_dev, hw); + struct device *dev = crete_hw_to_dev(hw); + struct crete_irq_info *irq_info = NULL; + struct msix_entry *msix_ent = NULL; + + irqno = crete_req_msixirq(cdev); + irq_info = &cdev->irq_info[irqno]; + msix_ent = &cdev->msix_ent[irqno]; + + if (!(cdev->flags & CRETE_FLAG_HAS_MSIX)) + return 0; + + event_irq = kzalloc(sizeof(*event_irq), GFP_KERNEL); + if (!event_irq) + return -ENOMEM; + +#ifndef CONFIG_NOSIM_DEBUG + writew(irqno, &hw->io_addr->event_vector); +#endif + + for (i = 0; i < CRETE_EVENT_TYPE_MAX; i++) + ATOMIC_INIT_NOTIFIER_HEAD(&event_irq->nh[i]); + + snprintf(event_irq->name, sizeof(event_irq->name), "event@pci:%s", pci_name(cdev->pdev)); + crete_info(dev, "event_irq_name[%s]", event_irq->name); + event_irq->vector = irq_info->vector; + event_irq->entry = irqno; + cdev->event_irq = event_irq; + + err = request_irq(event_irq->vector, irq_int_handler, 0, event_irq->name, cdev); + if (err) { + crete_err(dev, "Failed to request irq. err = %d\n", err); + goto err_req_irq; + } + irq_info->requested = 1; + irq_info->handler = irq_int_handler; + crete_info(dev, "crete_event init success event_irq_name[%s], vector[%d], irq[%d]", + event_irq->name, irqno, event_irq->vector); + return 0; + +err_req_irq: + crete_free_msixirq(cdev, irqno); + + kfree(event_irq); + return err; +} + +int crete_event_notifier_register(struct crete_core_dev *dev, struct crete_nb *nb) +{ + struct crete_event_irq *irq_nb = dev->event_irq; + + return atomic_notifier_chain_register(&irq_nb->nh[nb->event_type], &nb->nb); +} +EXPORT_SYMBOL(crete_event_notifier_register); + +int crete_event_notifier_unregister(struct crete_core_dev *dev, struct crete_nb *nb) +{ + struct crete_event_irq *irq_nb = dev->event_irq; + + return atomic_notifier_chain_unregister(&irq_nb->nh[nb->event_type], &nb->nb); +} +EXPORT_SYMBOL(crete_event_notifier_unregister); + +int crete_event_init(struct crete_hw *hw) +{ + int err = 0; + uint8_t val; + struct device *dev = crete_hw_to_dev(hw); + val = readb(&hw->io_addr->cp_caps); + if (val & CRETE_CP_EP) { + err = crete_event_start(hw); + if (err < 0) { + crete_info(dev, "crete_event_start failed!\n"); + return err; + } + + val = readb(&hw->io_addr->cp_status); + val |= CRETE_CP_EP; + writeb(val, &hw->io_addr->cp_status); + } else { + crete_info(dev, "not support event path!\n"); + } + + return err; +} + +void crete_event_exit(struct crete_hw *hw) +{ + struct crete_irq_info *irq_info; + struct crete_core_dev *cdev = container_of(hw, + struct crete_core_dev, hw); + struct device *dev = crete_hw_to_dev(hw); + + if (!cdev->event_irq) { + crete_info(dev, "crete event already exit\n"); + return; + } + + irq_info = &cdev->irq_info[cdev->event_irq->entry]; + + if (irq_info->requested) { + crete_free_msixirq(cdev, cdev->event_irq->vector); + free_irq(irq_info->vector, cdev); + kfree(cdev->event_irq); + cdev->event_irq = NULL; + } + + crete_info(dev, "crete event exit\n"); +} +EXPORT_SYMBOL(crete_event_exit); \ No newline at end of file diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_event.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_event.h new file mode 100644 index 0000000..04670a0 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_event.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CRETE_EVENT_H +#define _CRETE_EVENT_H + +#include "crete.h" +#include +#include + + +#define CRETE_MAX_IRQ_NAME 32 +#define CRETE_EVENT_ALLOC_BUFFER_SIZE 8 + +#define CRETE_EVENT_SUPPORTED(hw) (readb(&(hw)->io_addr->cp_caps) & CRETE_CP_EP) + + +// enum crete_event_offset { +// CRETE_EVENT_TYPE_CMDPATH = 0, +// CRETE_EVENT_TYPE_ADMIN = 1, + +// }; + +enum crete_event_type { + /* Completion group */ + CRETE_EVENT_TYPE_CP = 0, + /* status Change group */ + /* Error Report group */ + /* Data transfer group */ + CRETE_EVENT_PTP_TIMESTAMP = 1, + CRETE_EVENT_PORT_LINK_CHANGE = 0x201, + CRETE_EVENT_TYPE_MAX, +}; + +enum crete_vnet_evnet_subtype { + CRETE_EVENT_VNET_LINK_CHANGE = 0, + CRETE_EVENT_VNET_RESET, +}; + +enum crete_portchange_event_subtype { + CRETE_EVENT_PORT_LINK_DOWN = 0, + CRETE_EVENT_PORT_LINK_UP = 1, + CRETE_EVENT_PORT_LINK_ERR +}; + +enum crete_cp_event_subtype { + CRETE_EVENT_STYPE_CMDPATH = 0, + CRETE_EVENT_STYPE_ADMIN = 1, +}; + +struct crete_event_irq { + struct atomic_notifier_head nh[CRETE_EVENT_TYPE_MAX]; + cpumask_var_t mask; + char name[CRETE_MAX_IRQ_NAME]; + u32 vector; + u16 entry; + void *event_buf; + dma_addr_t event_dma; + u8 event_buf_size; +}; + +struct crete_event_cmd { + uint16_t entry_id; + uint16_t rsvd; +}; + +struct crete_event_buffer_head { + u8 resv0; + u8 event_seq; + uint8_t event_sig; + uint8_t event_entry_length; +}; + + +struct crete_event_entry { + uint8_t event_length; + uint8_t event_sub_type; + uint16_t event_type; + uint32_t event_data[]; //mlx5_eqe +}; + +struct crete_nb { + struct notifier_block nb; + u16 event_type; +}; + +#define CRETE_NB_INIT(name, handler, event) do { \ + (name)->nb.notifier_call = handler; \ + (name)->event_type = CRETE_EVENT_TYPE_##event; \ +} while (0) + +#define crete_nb_cof(ptr, type, member) \ + (container_of(container_of(ptr, struct crete_nb, nb), type, member)) + +extern int crete_event_notifier_register(struct crete_core_dev *dev, struct crete_nb *nb); +extern int crete_event_notifier_unregister(struct crete_core_dev *dev, struct crete_nb *nb); + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_fw_update.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_fw_update.c new file mode 100644 index 0000000..75e6ff4 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_fw_update.c @@ -0,0 +1,515 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "crete.h" +#include "crete_cmd.h" +#include "crete_regs.h" +#include +#include +#include "crete_fw_update.h" +#include "crete_pldmfw_lib.h" +#include "crete_cmd_if.h" + + +static const struct pldmfw_ops crete_fwu_ops = { + .match_record = NULL, + .send_package_data = NULL, + .send_component_table = NULL, + .flash_component = NULL, + .finalize_update = NULL, +}; + +static void crete_fwu_status_notify(struct crete_fwu_priv *fwu_priv, + const char *msg, const char *comp_name, + u32 done_bytes, u32 total_bytes) +{ + devlink_flash_update_status_notify(fwu_priv->devlink, msg, comp_name, + done_bytes, total_bytes); +} + +static int crete_acquire_flashlock(struct crete_fwu_priv *fwu_priv) +{ + u32 in[CRETE_ST_SZ_DW(fwu_lock_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(fwu_lock_out)] = {0}; + u16 seq_id = fwu_priv->seq_id; + int ret = 0; + u8 st = 0; + + CRETE_SET(fwu_lock_in, in, cmd_id, CRETE_CMD_FWU_LOCK); + CRETE_SET(fwu_lock_in, in, seq_id, seq_id); + CRETE_SET(fwu_lock_in, in, cmd, CRETE_FWU_LOCKED); + + ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(fwu_lock_out, out, status); + ret = CRETE_GET16(fwu_lock_out, out, status_inner); + cretefw_info(fwu_priv, "st[%d] fwlock inner status[%d]\n", st, ret); + + return ret; +} + +static int crete_release_flashlock(struct crete_fwu_priv *fwu_priv) +{ + u32 in[CRETE_ST_SZ_DW(fwu_unlock_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(fwu_unlock_out)] = {0}; + u16 seq_id = fwu_priv->seq_id; + int ret = 0; + u8 st = 0; + + CRETE_SET(fwu_unlock_in, in, cmd_id, CRETE_CMD_FWU_UNLOCK); + CRETE_SET(fwu_unlock_in, in, seq_id, seq_id); + CRETE_SET(fwu_unlock_in, in, cmd, CRETE_FWU_UNLOCK); + + ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(fwu_unlock_out, out, status); + ret = CRETE_GET16(fwu_unlock_out, out, status_inner); + cretefw_info(fwu_priv, "st[%d] fwu unlock inner status[%d]\n", st, ret); + + return ret; +} + +static int crete_fwu_pkey(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data) +{ + u32 in[CRETE_ST_SZ_DW(fwu_pkey_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(fwu_pkey_out)] = {0}; + u16 seq_id = fwu_priv->seq_id; + int ret = 0; + u8 st = 0; + + CRETE_SET(fwu_pkey_in, in, cmd_id, CRETE_CMD_FWU_PKEY); + CRETE_SET(fwu_pkey_in, in, seq_id, seq_id); + CRETE_SET(fwu_pkey_in, in, cmd, CRETE_FWU_PKEY); + + ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(fwu_pkey_out, out, status); + ret = CRETE_GET16(fwu_pkey_out, out, status_inner); + cretefw_info(fwu_priv, "st[%d] fwu pkey inner status[%d]\n", st, ret); + + return ret; +} + +static int crete_fwu_ver(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data) +{ + u32 *in, *out; + int outlen = CRETE_ST_SZ_BYTES(fwu_ver_out); + int inlen = CRETE_ST_SZ_BYTES(fwu_ver_in); + u16 seq_id = fwu_priv->seq_id; + int ret = 0; + u8 st = 0; + int component_count = data->component_count; + struct pldmfw_component *component; + int i = 0; + + inlen += component_count * CRETE_FLD_SZ_BYTES(fwu_ver_in, comp_list[0]); + outlen += component_count * CRETE_FLD_SZ_BYTES(fwu_ver_out, version_list[0]); + in = kvzalloc(inlen, GFP_KERNEL); + out = kvzalloc(outlen, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(fwu_ver_in, in, cmd_id, CRETE_CMD_FWU_VER); + CRETE_SET(fwu_ver_in, in, cmd, CRETE_FWU_VER); + CRETE_SET(fwu_ver_in, in, seq_id, seq_id); + + list_for_each_entry(component, &data->components, entry) { + if (i >= component_count) + break; + + CRETE_ARRAY_SET(fwu_ver_in, in, comp_list, i, component->identifier); + i++; + } + + ret = crete_cmd_exec_polling(fwu_priv->cdev, in, inlen, out, outlen); + if (ret < 0) + goto err_out; + + st = CRETE_GET(fwu_ver_out, out, status); + ret = CRETE_GET(fwu_ver_out, out, status_inner); + cretefw_info(fwu_priv, "st[%d] fwu_ver inner status[%d]\n", st, ret); + + /*TODO*/ + /* + * version_out = CRETE_ADDR_OF(fwu_ver_out, out, version_list); + * for (i = 0; i < component_count; i++, version_out += CRETE_ST_SZ_BYTES(version_list)) { + * version = CRETE_GET_PR(version_list, version_out, qid); + * version_efuse = CRETE_GET_PR(version_list, version_out, result); + * crete_fw_checkversion(version, version_efuse, flag); + * } + */ + +err_out: + kvfree(in); + kvfree(out); + return ret; +} + +static void +crete_check_fwu_ack(struct crete_fwu_priv *fwu_priv, const char *comp_name, u16 status_code, + struct netlink_ext_ack *extack) +{ +#define CRETEFW_ACK_PRFX "check fwu_ack: " +#define CRETEFW_CHECK_ACK(msg, err) \ + CRETEFW_ERR_MSG(fwu_priv, extack, CRETEFW_ACK_PRFX msg, err) + + cretefw_info(fwu_priv, "%s: firmware response code 0x%x\n", comp_name, status_code); + + switch (status_code) { + case CRETE_FWU_SUCCESS: + /* firmware indicated this update is good to proceed */ + return; + case CRETE_FWU_ERR_SEQ_ID: + CRETEFW_CHECK_ACK("flash components err seq_id", status_code); + break; + case CRETE_FWU_CRC_ERR: + CRETEFW_CHECK_ACK("flash components crc err", status_code); + break; + case CRETE_FWU_BUSY: + CRETEFW_CHECK_ACK("flash device is busy", status_code); + break; + case CRETE_FWU_LOCK_FAIL: + CRETEFW_CHECK_ACK("flash lock failed", status_code); + break; + case CRETE_FWU_PKEY_ERR: + CRETEFW_CHECK_ACK("flash components pkey err", status_code); + break; + case CRETE_FWU_INVALID_ID: + CRETEFW_CHECK_ACK("flash components invalid img id", status_code); + break; + case CRETE_FWU_FLASH_ERR: + CRETEFW_CHECK_ACK("flash components write err", status_code); + break; + case CRETE_FWU_EFUSE_ERR: + CRETEFW_CHECK_ACK("flash components write efuse err", status_code); + break; + case CRETE_FWU_SYNC_ERR: + CRETEFW_CHECK_ACK("flash components sync err", status_code); + break; + case CRETE_FWU_TRANS_ERR: + CRETEFW_CHECK_ACK("flash components trans err", status_code); + break; + case CRETE_FWU_TIMEOUT: + CRETEFW_CHECK_ACK("flash components wait timeout", status_code); + break; + case CRETE_FWU_STATUS_ERR: + CRETEFW_CHECK_ACK("flash components status mismatch", status_code); + break; + case CRETE_FWU_OTHER_ERR: + CRETEFW_CHECK_ACK("flash components unexpected err", status_code); + break; + default: + CRETEFW_CHECK_ACK("Unrecognized command status code", status_code); + break; + } +} + +static int crete_fwu_end(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data) +{ + u32 in[CRETE_ST_SZ_DW(fwu_end_in)] = {0}; + u32 out[CRETE_ST_SZ_DW(fwu_end_out)] = {0}; + u16 seq_id = fwu_priv->seq_id; + int ret = 0; + u8 st = 0; + + CRETE_SET(fwu_end_in, in, cmd_id, CRETE_CMD_FWU_END); + CRETE_SET(fwu_end_in, in, cmd, CRETE_FWU_IMG_END); + CRETE_SET(fwu_end_in, in, seq_id, seq_id); + + ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out)); + if (ret < 0) + return ret; + + st = CRETE_GET(fwu_end_out, out, status); + ret = CRETE_GET(fwu_end_out, out, status_inner); + cretefw_info(fwu_priv, "st[%d] fwu end inner end [%d]\n", st, ret); + + return ret; + +} + +static int crete_flash_component_block(u32 offset_uint, u16 block_size, u8 *block, + bool last_cmd, u16 identifier, struct crete_fwu_priv *fwu_priv, u16 *st_code) +{ + u32 out[CRETE_ST_SZ_DW(fwu_xfer_out)] = {0}; + u32 *in, *block_ptr; + int inlen = CRETE_ST_SZ_BYTES(fwu_xfer_in); + u32 calculated_crc = 0; + u16 seq_id = fwu_priv->seq_id; + int ret = 0; + u8 st = 0; + int attempts = 0; + + inlen += block_size; + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + goto flash_out; + } + + identifier = last_cmd ? (identifier | BIT(15)) : (identifier & ~BIT(15)); + CRETE_SET(fwu_xfer_in, in, cmd_id, CRETE_CMD_FWU_XFER); + CRETE_SET(fwu_xfer_in, in, seq_id, seq_id); + CRETE_SET(fwu_xfer_in, in, cmd, CRETE_FWU_IMG_XFER); + CRETE_SET(fwu_xfer_in, in, flag, identifier); + CRETE_SET(fwu_xfer_in, in, len, block_size); + CRETE_SET(fwu_xfer_in, in, offset, offset_uint); + + block_ptr = CRETE_ADDR_OF(fwu_xfer_in, in, data); + memcpy(block_ptr, block, block_size); + + calculated_crc = crc32_le(~0, block, block_size) ^ ~0; + CRETE_SET(fwu_xfer_in, in, crc, calculated_crc); + + do { + ret = crete_cmd_exec_polling(fwu_priv->cdev, in, inlen, out, sizeof(out)); + if (ret && ret != -EREMOTEIO) { + cretefw_err(fwu_priv, "fwu_xfer cmd carryout failed ret[%d]\n", ret); + goto flash_out; + } + st = CRETE_GET(fwu_xfer_out, out, status); + *st_code = CRETE_GET(fwu_xfer_out, out, status_inner); + + cretefw_info(fwu_priv, "attempts[%d] st[%d] fwu_xfer status[%d]\n", + attempts, st, *st_code); + + if (!st && *st_code == CRETE_FWU_SUCCESS) + goto flash_out; + + if (*st_code != CRETE_FWU_CRC_ERR) + goto flash_out; + + attempts++; + } while (attempts < CRETE_MAX_ATTEMPTS_XFER); + +flash_out: + kvfree(in); + return ret ? ret : *st_code; +} + +static int crete_flash_component(struct crete_fwu_priv *fwu_priv, + struct pldmfw_component *component) +{ + u32 offset = 0; + u32 offset_uint = 0; + bool last_cmd; + u16 status_code; + int err; + struct netlink_ext_ack *extack = fwu_priv->extack; + u8 *block; + const u8 *image = component->component_data; + u32 length = component->component_size; + const char *comp_name = component->version_string; + + if (comp_name == NULL) + return -EINVAL; + + cretefw_info(fwu_priv, "Beginning write of flash component '%s' size '%d'\n", + comp_name, length); + crete_fwu_status_notify(fwu_priv, "Flashing component", comp_name, 0, length); + + block = kzalloc(CRETE_MAX_FWU_BUF_LEN, GFP_KERNEL); + if (!block) + return -ENOMEM; + + do { + u32 block_size; + + block_size = min_t(u32, CRETE_MAX_FWU_BUF_LEN, length - offset); + last_cmd = !(offset + block_size < length); + memcpy(block, image + offset, block_size); + status_code = CRETE_FWU_OTHER_ERR; + err = crete_flash_component_block(offset_uint, block_size, block, + last_cmd, component->identifier, fwu_priv, &status_code); + if (err) + break; + + offset += block_size; + fwu_priv->seq_id++; + CRETE_FWU_INCREMENT_OFFSET(offset_uint); + crete_fwu_status_notify(fwu_priv, "Flashing component", comp_name, offset, length); + } while (!last_cmd); + + crete_check_fwu_ack(fwu_priv, comp_name, status_code, extack); + + if (err) + crete_fwu_status_notify(fwu_priv, "Flashing failed", + comp_name, length, length); + else + crete_fwu_status_notify(fwu_priv, "Flashing done", + comp_name, length, length); + + kfree(block); + return err; +} + +static int crete_flash_components(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data) +{ + struct pldmfw_record *record; + struct pldmfw_component *component; + unsigned long *bitmap = NULL; + int err = 0; + + list_for_each_entry(record, &data->records, entry) { + bitmap = record->component_bitmap; + list_for_each_entry(component, &data->components, entry) { + u8 index = component->index, transfer_flag = 0; + + if (!test_bit(index, bitmap)) + continue; + cretefw_info(fwu_priv, "identifier: %d\n", component->identifier); + cretefw_info(fwu_priv, "version_string: %s\n", component->version_string); + cretefw_info(fwu_priv, "classification: %d\n", component->classification); + + if(component->version_string == NULL) + continue; + + /* determine whether this is the start, middle, end, or both + * the start and end of the component tables + */ + if (index == find_first_bit(bitmap, data->component_bitmap_len)) + transfer_flag |= PLDM_TRANSFER_FLAG_START; + if (index == find_last_bit(bitmap, data->component_bitmap_len)) + transfer_flag |= PLDM_TRANSFER_FLAG_END; + if (!transfer_flag) + transfer_flag = PLDM_TRANSFER_FLAG_MIDDLE; + err = crete_flash_component(fwu_priv, component); + if (err) + return err; + } + } + return err; +} + +static int crete_flash_image(struct crete_fwu_priv *fwu_priv, const struct firmware *fw) +{ + struct crete_pldmfw_priv *data; + int err; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + INIT_LIST_HEAD(&data->records); + INIT_LIST_HEAD(&data->components); + + data->fw = fw; + data->context = &fwu_priv->context; + + err = crete_pldm_parse_image(data); + if (err) + goto out_release_data; + + cretefw_info(fwu_priv, "total_header_size : %d\n", data->total_header_size); + cretefw_info(fwu_priv, "record_count : %d\n", data->record_count); + cretefw_info(fwu_priv, "component_bitmap_len : %d\n", data->component_bitmap_len); + cretefw_info(fwu_priv, "component_count : %d\n", data->component_count); + + err = crete_fwu_pkey(fwu_priv, data); + if (err) + goto out_release_data; + + err = crete_fwu_ver(fwu_priv, data); + if (err) + goto out_release_data; + + err = crete_flash_components(fwu_priv, data); + if (err) + goto out_release_data; + + err = crete_fwu_end(fwu_priv, data); + +out_release_data: + crete_pldmfw_free_priv(data); + kfree(data); + + return err; +} + +int crete_firmware_flash(struct crete_core_dev *cdev, + const struct firmware *firmware, + struct netlink_ext_ack *extack, enum crete_fwu_type type) +{ + struct crete_fwu_priv fwu_priv; + int err; + + if (!crete_core_is_pf(cdev)) + return 0; + + memset(&fwu_priv, 0, sizeof(fwu_priv)); + fwu_priv.context.ops = &crete_fwu_ops; + fwu_priv.context.dev = cdev->device; + fwu_priv.devlink = priv_to_devlink(cdev); + fwu_priv.extack = extack; + fwu_priv.seq_id = 0; + fwu_priv.cdev = cdev; + + cretefw_info(&fwu_priv, "Initialize firmware flash process\n"); +#ifndef CONFIG_DEVLINK_CARRYOUT_OPTIMIZE + if (type == CRETE_FWU_DEVLINK) + devlink_flash_update_begin_notify(fwu_priv.devlink); +#endif + crete_fwu_status_notify(&fwu_priv, "Preparing to flash", NULL, 0, 0); + + err = crete_acquire_flashlock(&fwu_priv); + if (err) { + CRETEFW_ERR_MSG(&fwu_priv, extack, "Failed to acquire device flash lock", err); + goto flash_out; + } + + err = crete_flash_image(&fwu_priv, firmware); + if (err) + CRETEFW_ERR_MSG(&fwu_priv, extack, "Failed to flash PLDM image", err); + + err = crete_release_flashlock(&fwu_priv); + if (err) + CRETEFW_ERR_MSG(&fwu_priv, extack, "Failed to release device flash lock", err); + +flash_out: +#ifndef CONFIG_DEVLINK_CARRYOUT_OPTIMIZE + if (type == CRETE_FWU_DEVLINK) + devlink_flash_update_end_notify(fwu_priv.devlink); +#endif + return err; +} +EXPORT_SYMBOL(crete_firmware_flash); + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_fw_update.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_fw_update.h new file mode 100644 index 0000000..2a840a6 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_fw_update.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CRETE_FW_UPDATE_H +#define _CRETE_FW_UPDATE_H + +#include +#include +#include + +#define CRETE_MAX_FWU_BUF_LEN 512 +#define CRETE_MAX_FWU_BUF_LEN_UINT 256 +#define CRETE_FWU_OFFSET_INCREMENT (CRETE_MAX_FWU_BUF_LEN / CRETE_MAX_FWU_BUF_LEN_UINT) +#define CRETE_FWU_INCREMENT_OFFSET(offset) ((offset) += CRETE_FWU_OFFSET_INCREMENT) +#define CRETE_MAX_ATTEMPTS_XFER 3 + +#define CRETE_FWU_PKEY_FLAG BIT(1) +#define CRETE_FWU_ACTIVE_FLAG BIT(2) +#define CRETE_FWU_FORCE_FLAG BIT(3) +#define CRETE_FWU_EFUSE_FLAH BIT(4) + + +enum crete_fwu_cmd { + CRETE_FWU_LOCKED = 1, + CRETE_FWU_PKEY, + CRETE_FWU_VER, + CRETE_FWU_IMG_XFER, + CRETE_FWU_IMG_END, + CRETE_FWU_ACT, + CRETE_FWU_SYNC, + CRETE_FWU_EFUSE, + CRETE_FWU_UNLOCK, + CRETE_FWU_QUERY, + CRETE_FWU_LOG, + CRETE_FWU_IMG_INFO, + CRETE_FWU_IMG_READ, + CRETE_FWU_ACK_HALF = 0xfe, + CRETE_FWU_ACK = 0xff, +}; + +enum crete_fwu_ack { + CRETE_FWU_SUCCESS = 0, + CRETE_FWU_ERR_SEQ_ID, + CRETE_FWU_CRC_ERR, + CRETE_FWU_BUSY, + CRETE_FWU_LOCK_FAIL, + CRETE_FWU_PKEY_ERR, + CRETE_FWU_INVALID_ID, + CRETE_FWU_FLASH_ERR, + CRETE_FWU_EFUSE_ERR, + CRETE_FWU_SYNC_ERR, + CRETE_FWU_TRANS_ERR, + CRETE_FWU_TIMEOUT, + CRETE_FWU_STATUS_ERR, + CRETE_FWU_OTHER_ERR, +}; + +enum crete_fwu_type { + CRETE_FWU_ETHTOOL = 0, + CRETE_FWU_DEVLINK = 1, +}; + + + +struct crete_fwu_priv { + struct pldmfw context; + struct devlink *devlink; + struct crete_core_dev *cdev; + struct netlink_ext_ack *extack; + u16 seq_id; +}; + +static inline +struct device *cretefw_dev_dev(struct crete_fwu_priv *fwu_priv) +{ + return fwu_priv->cdev->device; +} + +#define CRETEFW_PRFX "cretefw: " + +#define cretefw_info(fwu_priv, fmt, ...) \ + dev_info(cretefw_dev_dev(fwu_priv), CRETEFW_PRFX fmt, ## __VA_ARGS__) +#define cretefw_err(fwu_priv, fmt, ...) \ + dev_err(cretefw_dev_dev(fwu_priv), CRETEFW_PRFX fmt, ## __VA_ARGS__) +#define cretefw_dbg(fwu_priv, fmt, ...) \ + dev_dbg(cretefw_dev_dev(fwu_priv), CRETEFW_PRFX fmt, ## __VA_ARGS__) + +#define CRETEFW_ERR_PRFX "Firmware flash failed: " +#define CRETEFW_ERR_MSG(fwu_priv, extack, msg, err) do { \ + cretefw_err(fwu_priv, "%s, err (%d)\n", CRETEFW_ERR_PRFX msg, err); \ + NL_SET_ERR_MSG_MOD(extack, CRETEFW_ERR_PRFX msg); \ +} while (0) + +int crete_firmware_flash(struct crete_core_dev *cdev, + const struct firmware *firmware, + struct netlink_ext_ack *extack, enum crete_fwu_type type); + + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag.c new file mode 100644 index 0000000..ba1161a --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag.c @@ -0,0 +1,840 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include "crete.h" +#include "crete_cmd.h" +#include "crete_cmd_if.h" + +static inline bool crete_lag_is_supported(struct crete_core_dev *dev) +{ + if (!dev->lag_cap.lag_master) { + if (dev->lag_cap.num_ports == CRETE_MIN_LAG_PORTS || + dev->lag_cap.num_ports <= CRETE_MAX_LAG_PORTS) + dev->lag_enable = CRETE_LAG_DISABLE; + + return false; + } else { + if (dev->lag_cap.num_ports != CRETE_MIN_LAG_PORTS && + dev->lag_cap.num_ports != CRETE_MAX_LAG_PORTS) { + + dev->lag_enable = CRETE_LAG_DISABLE; + return false; + } + } + + return true; +} + +static inline void crete_ldev_get(struct crete_lag *ldev) +{ + kref_get(&ldev->ref); +} + +static void crete_ldev_free(struct kref *ref) +{ + struct crete_lag *ldev = container_of(ref, struct crete_lag, ref); + + if (ldev->nb.notifier_call) + unregister_netdevice_notifier_net(&init_net, &ldev->nb); + + destroy_workqueue(ldev->wq); + mutex_destroy(&ldev->lock); + kfree(ldev); +} + +static void crete_ldev_put(struct crete_lag *ldev) +{ + kref_put(&ldev->ref, crete_ldev_free); +} + +static void *pci_get_other_drvdata(struct device *this, struct device *other) +{ + if (this->driver != other->driver) + return NULL; + + return pci_get_drvdata(to_pci_dev(other)); +} + +static int _next_phys_dev(struct crete_core_dev *tmp_dev, + const struct crete_core_dev *curr_dev) +{ + + if (tmp_dev == curr_dev) + return 0; + + return 1; +} + +static bool crete_check_in_one_lag(struct crete_core_dev *t, struct crete_core_dev *tmp) +{ + if (t->lag_cap.lag_id != tmp->lag_cap.lag_id || + t->lag_cap.mode_support != tmp->lag_cap.mode_support || + t->lag_cap.hash_type != tmp->lag_cap.hash_type || + t->lag_cap.num_ports != tmp->lag_cap.num_ports) + return false; + + return true; +} + +/* + * should be implemented in the public interface + */ +static int next_phys_lag_dev(struct device *dev, const void *data) +{ + struct crete_core_dev *tmp_dev, *this = (struct crete_core_dev *)data; + + tmp_dev = pci_get_other_drvdata(this->device, dev); + if (!tmp_dev) + goto done; + + if (!crete_core_is_pf(tmp_dev)) + goto done; + + if (!crete_lag_is_supported(tmp_dev)) + goto done; + + if (!crete_check_in_one_lag(this, tmp_dev)) + goto done; + + return _next_phys_dev(tmp_dev, data); +done: + return 0; +} + +/* + * should be implemented in the public interface + */ +static struct crete_core_dev *crete_get_next_dev(struct crete_core_dev *dev, + int (*match)(struct device *dev, const void *data)) +{ + struct device *next; + + if (!crete_core_is_pf(dev)) + return NULL; + + next = bus_find_device(&pci_bus_type, NULL, dev, match); + if (!next) + return NULL; + + put_device(next); + + return pci_get_drvdata(to_pci_dev(next)); +} + +/* + * should be implemented in the public interface + */ +struct crete_core_dev *crete_get_next_phy_dev_lag(struct crete_core_dev *dev) +{ + return crete_get_next_dev(dev, &next_phys_lag_dev); +} + +static void crete_queue_bond_work(struct crete_lag *ldev, unsigned long delay) +{ + queue_delayed_work(ldev->wq, &ldev->bond_work, delay); +} + +struct crete_cmd_lag_context_bits test; + +static int crete_cmd_create_lag(struct crete_lag *ldev) +{ + int in_len = CRETE_ST_SZ_BYTES(create_lag_in); + int out_len = CRETE_ST_SZ_BYTES(create_lag_out); + void *in, *out, *lagc; + int lagc_size = CRETE_ST_SZ_BYTES(lag_context); + struct crete_core_dev *dev = ldev->pf[CRETE_LAG_P1].dev; + int status; + int ret = 0; + int i = 0; + + in_len += lagc_size; + + in = kvzalloc(in_len, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + goto done; + } + + out = kvzalloc(out_len, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + kvfree(in); + goto done; + } + + CRETE_SET(create_lag_in, in, cmd_id, CRETE_CMD_LAG_CONFIG); + CRETE_SET(create_lag_in, in, opcode, CRETE_CREATE_LAG); + lagc = CRETE_ADDR_OF(create_lag_in, in, lag_context); + + CRETE_SET(lag_context, lagc, lag_id, dev->lag_cap.lag_id); + CRETE_SET(lag_context, lagc, lag_mode, ldev->info.upper_lag_mode); + CRETE_SET(lag_context, lagc, hash_type, ldev->info.hash_type); + CRETE_SET(lag_context, lagc, lu_te_num, ldev->ports); + + for (i = 0; i < ldev->ports; i++) + CRETE_ARRAY_SET(lag_context, lagc, lu_te_mem, i, ldev->pf[i].dev->sfi_id); + + ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out)); + if (ret) { + crete_info(dev->device, "create lag cmd err[%d]", ret); + goto out; + } + + status = CRETE_GET(create_lag_out, out, status); + crete_info(dev->device, "create lag status:%d", status); + +out: + kfree(in); + kfree(out); +done: + return ret; + +} + +static void crete_activate_lag(struct crete_lag *ldev) +{ + crete_cmd_create_lag(ldev); + ldev->mode = CRETE_LAG_ACTIVE; +} + +static int crete_cmd_modify_lag(struct crete_lag *ldev) +{ + int in_len = CRETE_ST_SZ_BYTES(modify_lag_in); + int out_len = CRETE_ST_SZ_BYTES(modify_lag_out); + void *in, *out, *lagc; + int lagc_size = CRETE_ST_SZ_BYTES(lag_context); + struct crete_core_dev *dev = ldev->pf[CRETE_LAG_P1].dev; + int status; + int ret = 0; + int i = 0; + + in_len += lagc_size; + + in = kvzalloc(in_len, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + goto done; + } + + out = kvzalloc(out_len, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + kvfree(in); + goto done; + } + + CRETE_SET(modify_lag_in, in, cmd_id, CRETE_CMD_LAG_CONFIG); + CRETE_SET(modify_lag_in, in, opcode, CRETE_MODIFY_LAG); + lagc = CRETE_ADDR_OF(modify_lag_in, in, lag_context); + + CRETE_SET(lag_context, lagc, lag_id, dev->lag_cap.lag_id); + CRETE_SET(lag_context, lagc, lag_mode, ldev->info.upper_lag_mode); + CRETE_SET(lag_context, lagc, hash_type, dev->lag_cap.hash_type); + + for (i = 0; i < ldev->ports; i++) { + if (ldev->info.netdev_state[i].link_up & + ldev->info.netdev_state[i].tx_enabled) { + CRETE_ARRAY_SET(lag_context, lagc, lu_te_mem, ldev->info.netdev_idx, + ldev->pf[i].dev->sfi_id); + ldev->info.netdev_idx++; + pr_debug("func:%s--line:%d sfi_id:0x%x\n", __func__, __LINE__, ldev->pf[i].dev->sfi_id); + } + } + + ldev->info.active_port = ldev->info.netdev_idx; + ldev->info.netdev_idx = 0; + + CRETE_SET(lag_context, lagc, lu_te_num, ldev->info.active_port); + + ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out)); + if (ret) { + crete_info(dev->device, "modify lag cmd err[%d]", ret); + goto out; + } + + status = CRETE_GET(modify_lag_out, out, status); + crete_info(dev->device, "modify lag status:%d", status); + +out: + kfree(in); + kfree(out); +done: + return ret; +} + +static void crete_modify_lag(struct crete_lag *ldev) +{ + crete_cmd_modify_lag(ldev); +} + +static int crete_cmd_destroy_lag(struct crete_lag *ldev, struct crete_core_dev *spec_dev) +{ + int in_len = CRETE_ST_SZ_BYTES(destroy_lag_in); + int out_len = CRETE_ST_SZ_BYTES(destroy_lag_out); + void *in, *out, *lagc; + int lagc_size = CRETE_ST_SZ_BYTES(lag_context); + struct crete_core_dev *dev = + spec_dev == NULL ? ldev->pf[CRETE_LAG_P1].dev : spec_dev; + int status; + int ret = 0; + + in_len += lagc_size; + + in = kvzalloc(in_len, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + goto done; + } + + out = kvzalloc(out_len, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + kvfree(in); + goto done; + } + + CRETE_SET(destroy_lag_in, in, cmd_id, CRETE_CMD_LAG_CONFIG); + CRETE_SET(destroy_lag_in, in, opcode, CRETE_DESTROY_LAG); + lagc = CRETE_ADDR_OF(destroy_lag_in, in, lag_context); + + CRETE_SET(lag_context, lagc, lag_id, dev->lag_cap.lag_id); + + ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out)); + if (ret) { + crete_info(dev->device, "destroy lag cmd err[%d]", ret); + goto out; + } + + status = CRETE_GET(destroy_lag_out, out, status); + crete_info(dev->device, "destroy lag status:%d", status); + +out: + kfree(in); + kfree(out); +done: + return ret; +} + +int crete_cmd_lag_enable(struct crete_core_dev *dev, u16 lag_enable) +{ + int in_len = CRETE_ST_SZ_BYTES(lag_enable_in); + int out_len = CRETE_ST_SZ_BYTES(lag_enable_out); + void *in, *out; + int status; + int ret = 0; + + in = kvzalloc(in_len, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + goto done; + } + + out = kvzalloc(out_len, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + kvfree(in); + goto done; + } + + CRETE_SET(lag_enable_in, in, cmd_id, CRETE_CMD_ENABLE_LAG); + CRETE_SET(lag_enable_in, in, opcode, 0); + CRETE_SET(lag_enable_in, in, vport_id, dev->sfi_id); + CRETE_SET(lag_enable_in, in, lag_enable, lag_enable); + + ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out)); + if (ret) { + crete_info(dev->device, "enable lag cmd err[%d]", ret); + goto out; + } + + status = CRETE_GET(lag_enable_out, out, status); + crete_info(dev->device, "enable lag status:%d", status); + +out: + kfree(in); + kfree(out); +done: + return ret; +} + +static void crete_disable_lag(struct crete_lag *ldev, struct crete_core_dev *dev) +{ + crete_cmd_destroy_lag(ldev, dev); + ldev->mode = CRETE_LAG_INACTIVE; +} + +static void crete_do_bond(struct crete_lag *ldev) +{ + bool do_bond; + struct crete_lag_info lag_info = {}; + + if (!crete_lag_is_ready(ldev)) { + do_bond = false; + } else { + lag_info = ldev->info; + do_bond = lag_info.is_bonded; + } + + if (do_bond && !__crete_lag_is_active(ldev)) { + crete_activate_lag(ldev); + crete_modify_lag(ldev); + } else if (do_bond && __crete_lag_is_active(ldev)) + crete_modify_lag(ldev); + else if (!do_bond && __crete_lag_is_active(ldev)) + crete_disable_lag(ldev, NULL); +} + +static void crete_do_bond_work(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct crete_lag *ldev = container_of(delayed_work, struct crete_lag, + bond_work); + int status; + + status = crete_dev_list_trylock(); + if (!status) { + crete_queue_bond_work(ldev, 100); + return; + } + + mutex_lock(&ldev->lock); + + crete_do_bond(ldev); + mutex_unlock(&ldev->lock); + crete_dev_list_unlock(); +} + +static int crete_lag_dev_get_netdev_idx(struct crete_lag *ldev, + struct net_device *ndev) +{ + int i; + + for (i = 0; i < ldev->ports; i++) { + /* add pointer protect*/ + if (ldev->pf[i].dev) + if (ldev->pf[i].dev->netdev == ndev) + return i; + } + + return -ENOENT; +} + +static int crete_handle_changeupper_event(struct crete_lag *ldev, + struct crete_lag_info *lag_info, + struct netdev_notifier_changeupper_info *info) +{ + struct net_device *upper = info->upper_dev, *ndev_tmp; + struct netdev_lag_upper_info *lag_upper_info = NULL; + struct bonding *bond = netdev_priv(upper); + bool is_bonded, is_in_lag, mode_supported; + bool has_inactive = 0; + struct slave *slave; + u8 bond_status = 0; + int num_slaves = 0; + int changed = 0; + int idx; + + if (!netif_is_lag_master(upper)) + return 0; + + if (info->linking) + lag_upper_info = info->upper_info; + + rcu_read_lock(); + for_each_netdev_in_bond_rcu(upper, ndev_tmp) { + idx = crete_lag_dev_get_netdev_idx(ldev, ndev_tmp); + if (idx >= 0) { + slave = bond_slave_get_rcu(ndev_tmp); + if (slave) + has_inactive |= bond_is_slave_inactive(slave); + bond_status |= (1 << idx); + } + + num_slaves++; + } + rcu_read_unlock(); + + if (!(bond_status & GENMASK(ldev->ports - 1, 0))) + return 0; + + if (lag_upper_info) { + lag_info->tx_type = lag_upper_info->tx_type; + lag_info->hash_type = lag_upper_info->hash_type; + } + + if (bond) + lag_info->upper_lag_mode = BOND_MODE(bond); + + lag_info->has_inactive = has_inactive; + is_in_lag = num_slaves == ldev->ports && + bond_status == GENMASK(ldev->ports - 1, 0); + + /* Lag mode must be activebackup or hash. */ + mode_supported = ((1 << lag_info->upper_lag_mode) & ldev->mode_supported); + + is_bonded = is_in_lag && mode_supported; + if (lag_info->is_bonded != is_bonded) { + lag_info->is_bonded = is_bonded; + changed = 1; + } + + if (!is_in_lag) + return changed; + + if (!crete_lag_is_ready(ldev)) + NL_SET_ERR_MSG_MOD(info->info.extack, + "Can't activate LAG offload"); + else if (!mode_supported) + NL_SET_ERR_MSG_MOD(info->info.extack, + "Can't activate LAG offload, TX type isn't supported"); + + return changed; + +} + +static int crete_handle_changelowerstate_event(struct crete_lag *ldev, + struct crete_lag_info *lag_info, + struct net_device *ndev, + struct netdev_notifier_changelowerstate_info *info) +{ + struct netdev_lag_lower_state_info *lag_lower_info; + int idx; + + if (!netif_is_lag_port(ndev)) + return 0; + + idx = crete_lag_dev_get_netdev_idx(ldev, ndev); + if (idx < 0) + return 0; + + lag_lower_info = info->lower_state_info; + if (!lag_lower_info) + return 0; + + lag_info->netdev_state[idx] = *lag_lower_info; + + return 1; +} + +static int crete_handle_changeinfodata_event(struct crete_lag *ldev, + struct crete_lag_info *lag_info, + struct net_device *ndev) +{ + struct net_device *ndev_tmp; + struct slave *slave; + bool has_inactive = 0; + int idx; + + if (!netif_is_lag_master(ndev)) + return 0; + + rcu_read_lock(); + for_each_netdev_in_bond_rcu(ndev, ndev_tmp) { + idx = crete_lag_dev_get_netdev_idx(ldev, ndev_tmp); + if (idx < 0) + continue; + + slave = bond_slave_get_rcu(ndev_tmp); + if (slave) + has_inactive |= bond_is_slave_inactive(slave); + } + rcu_read_unlock(); + + if (lag_info->has_inactive == has_inactive) + return 0; + + lag_info->has_inactive = has_inactive; + + return 1; +} + +static int crete_lag_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *ndev = netdev_notifier_info_to_dev(ptr); + struct crete_lag_info info; + struct crete_lag *ldev; + int changed = 0, change_lower = 0; + + if (event != NETDEV_CHANGEUPPER && + event != NETDEV_CHANGELOWERSTATE && + event != NETDEV_CHANGEINFODATA) + return NOTIFY_DONE; + + ldev = container_of(this, struct crete_lag, nb); + + info = ldev->info; + + switch (event) { + case NETDEV_CHANGEUPPER: + changed = crete_handle_changeupper_event(ldev, &info, ptr); + break; + case NETDEV_CHANGELOWERSTATE: + change_lower = crete_handle_changelowerstate_event(ldev, &info, + ndev, ptr); + break; + case NETDEV_CHANGEINFODATA: + changed = crete_handle_changeinfodata_event(ldev, &info, ndev); + break; + default: + break; + } + + ldev->info = info; + + if (changed || change_lower) { + pr_debug("func:%s--line:%d, changed:%d change_lower:%d\n", + __func__, __LINE__, changed, change_lower); + if (change_lower) { + crete_queue_bond_work(ldev, 100); + } + else + crete_queue_bond_work(ldev, 0); + } + + return NOTIFY_DONE; +} + +static struct crete_lag *crete_lag_dev_alloc(struct crete_core_dev *dev) +{ + struct crete_lag *ldev; + + ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); + if (!ldev) + return NULL; + + ldev->wq = create_singlethread_workqueue("crete_lag"); + if (!ldev->wq) { + kfree(ldev); + return NULL; + } + + kref_init(&ldev->ref); + mutex_init(&ldev->lock); + INIT_DELAYED_WORK(&ldev->bond_work, crete_do_bond_work); + + ldev->nb.notifier_call = crete_lag_netdev_event; + if (register_netdevice_notifier_net(&init_net, &ldev->nb)) { + ldev->nb.notifier_call = NULL; + dev_err(dev->device, "failed to register LAG dev notifier\n"); + } + + ldev->mode = CRETE_LAG_INACTIVE; + ldev->ports = dev->lag_cap.num_ports; + ldev->mode_supported = dev->lag_cap.mode_support; + ldev->hash_supported = dev->lag_cap.hash_type; + ldev->lag_id = dev->lag_cap.lag_id; + + return ldev; +} + +static inline int crete_get_dev_index(struct crete_core_dev *dev) +{ + int idx = dev->lag_cap.pf_id;; + + if (idx >= 0 && idx < CRETE_MAX_LAG_PORTS) + return idx; + else + return -1; +} + +static void crete_ldev_add(struct crete_lag *ldev, struct crete_core_dev *dev) +{ + int fn = crete_get_dev_index(dev); + + if (fn >= ldev->ports || fn < 0) { + dev_dbg(dev->device, "can't support lag, port id:%d\n", fn); + return; + } + + ldev->pf[fn].dev = dev; + dev->lag_dev = ldev; + + ldev->port_flags |= 1 << fn; + + if (ldev->port_flags == GENMASK(ldev->ports - 1, 0)) { + crete_disable_lag(ldev, NULL); + + set_bit(CRETE_LAG_READY, &ldev->state_flags); + } +} + +static int __crete_lag_dev_add(struct crete_core_dev *dev) +{ + struct crete_lag *ldev = NULL; + struct crete_core_dev *tmp_dev; + + tmp_dev = crete_get_next_phy_dev_lag(dev); + if (tmp_dev) { + dev_info(dev->device, "found peer core dev:%s\n", dev_name(tmp_dev->device)); + ldev = tmp_dev->lag_dev; + } + + if (!ldev) { + ldev = crete_lag_dev_alloc(dev); + if (!ldev) { + dev_err(dev->device, "failed to alloc lag dev\n"); + return 0; + } + + crete_ldev_add(ldev, dev); + return 0; + } + + mutex_lock(&ldev->lock); + crete_ldev_get(ldev); + crete_ldev_add(ldev, dev); + mutex_unlock(&ldev->lock); + + return 0; +} + +static int crete_get_lag_cap(struct crete_core_dev *dev) +{ + int ret; + int in_len = CRETE_ST_SZ_BYTES(get_lag_cap_in); + int out_len = CRETE_ST_SZ_BYTES(get_lag_cap_out); + void *in, *out; + u8 status; + + in = kvzalloc(in_len, GFP_KERNEL); + if (!in) { + ret = -ENOMEM; + goto done; + } + + out = kvzalloc(out_len, GFP_KERNEL); + if (!out) { + ret = -ENOMEM; + kvfree(in); + goto done; + } + + CRETE_SET(get_lag_cap_in, in, cmd_id, CRETE_CMD_GET_LAG_CAP); + CRETE_SET(get_lag_cap_in, in, opcode, 0); + CRETE_SET(get_lag_cap_in, in, vport_id, dev->sfi_id); + + ret = crete_cmd_exec_polling(dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(get_lag_cap_out, out, status); + if (status != SUCCESS) { + u32 err_type = CRETE_GET(get_lag_cap_out, out, err_type); + + crete_err(dev->device, + "crete get lag cap failed, status:0x%x err type:0x%x\n", + status, err_type); + ret = -EINVAL; + goto err_out; + } + + dev->lag_cap.lag_master = CRETE_GET(get_lag_cap_out, out, lag_master); + dev->lag_cap.lag_id = CRETE_GET(get_lag_cap_out, out, lag_id); + dev->lag_cap.mode_support = CRETE_GET(get_lag_cap_out, out, mode_support); + dev->lag_cap.hash_type = CRETE_GET(get_lag_cap_out, out, hash_type); + dev->lag_cap.num_ports = CRETE_GET(get_lag_cap_out, out, num_ports); + dev->lag_cap.pf_id = CRETE_GET(get_lag_cap_out, out, pf_id); + +err_out: + kvfree(in); + kvfree(out); +done: + return ret; +} + + +int crete_lag_add(struct crete_core_dev *dev) +{ + int ret = 0; + + dev->lag_enable = CRETE_LAG_UNSUPPORT; + ret = crete_get_lag_cap(dev); + if (ret < 0) + goto done; + + crete_add_lag_enable_debugfs(dev); + + if (!crete_lag_is_supported(dev)) + goto done; + + dev->lag_enable = CRETE_LAG_ENABLE; +recheck: + crete_dev_list_lock(); + ret = __crete_lag_dev_add(dev); + crete_dev_list_unlock(); + + if (ret) { + msleep(50); + goto recheck; + } + + if (dev->lag_dev) + crete_ldev_add_debugfs(dev); +done: + return ret; +} + +static void crete_ldev_remove(struct crete_lag *ldev, struct crete_core_dev *dev) +{ + int i; + + for (i = 0; i < ldev->ports; i++) + if (ldev->pf[i].dev == dev) + break; + + if (i == ldev->ports) { + if (__crete_lag_is_active(ldev)) + crete_disable_lag(ldev, dev); + return; + } + + ldev->pf[i].dev = NULL; + dev->lag_dev = NULL; +} + +void crete_lag_remove(struct crete_core_dev *dev) +{ + struct crete_lag *ldev; + + ldev = dev->lag_dev; + if (!ldev) + return; + + crete_ldev_remove_debugfs(dev->dbg.lag_debugfs); + mutex_lock(&ldev->lock); + crete_ldev_remove(ldev, dev); + mutex_unlock(&ldev->lock); + crete_ldev_put(ldev); +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag.h new file mode 100644 index 0000000..2b04924 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __CRETE_LAG_H__ +#define __CRETE_LAG_H__ + +#include +#include "crete.h" + + +#define CRETE_MAX_LAG_PORTS 4 +#define CRETE_MIN_LAG_PORTS 2 + +#ifndef DEFINE_SHOW_STORE_ATTRIBUTE +#define DEFINE_SHOW_STORE_ATTRIBUTE(__name) \ + static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ +\ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __name ## _open, \ + .read = seq_read, \ + .write = __name ## _write, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} +#endif + +struct crete_lag_cap { + u8 lag_master; + u8 lag_id; + u8 mode_support; + u8 hash_type; + u8 num_ports; + u8 pf_id; + u8 resv[2]; +}; + +enum { + CRETE_LAG_P1, + CRETE_LAG_P2, + CRETE_LAG_P3, + CRETE_LAG_P4, +}; + +enum crete_lag_mode { + CRETE_LAG_INACTIVE, + CRETE_LAG_ACTIVE, +}; + +enum crete_lag_state { + CRETE_LAG_READY, +}; + +enum crete_lag_pri { + CRETE_LAG_DISABLE, + CRETE_LAG_ENABLE, + CRETE_LAG_UNSUPPORT, + CRETE_LAG_PRI_MAX, +}; + +/* Used for collection of netdev event info. */ +struct crete_lag_info { + enum netdev_lag_tx_type tx_type; + struct netdev_lag_lower_state_info netdev_state[CRETE_MAX_LAG_PORTS]; + unsigned int is_bonded:1; + unsigned int has_inactive:1; + enum netdev_lag_hash hash_type; + u8 upper_lag_mode; + u8 active_port; + u8 netdev_idx; +}; + +struct crete_lag_func { + struct crete_core_dev *dev; + //struct net_device *netdev; + bool has_drop; +}; + +struct crete_lag { + enum crete_lag_mode mode; + unsigned long state_flags; + u8 port_flags; + u8 ports; + u8 mode_supported; + u8 hash_supported; + u8 lag_id; + struct kref ref; + struct crete_lag_func pf[CRETE_MAX_LAG_PORTS]; + struct crete_lag_info info; + struct workqueue_struct *wq; + struct delayed_work bond_work; + struct notifier_block nb; + + struct mutex lock; +}; + +static inline bool crete_is_supported_lag(struct crete_core_dev *dev) +{ + return true; +} + +static inline bool crete_lag_is_ready(struct crete_lag *ldev) +{ + return test_bit(CRETE_LAG_READY, &ldev->state_flags); +} + +static inline bool __crete_lag_is_active(struct crete_lag *ldev) +{ + return (ldev->mode == CRETE_LAG_ACTIVE); +} + +void crete_ldev_add_debugfs(struct crete_core_dev *dev); +void crete_add_lag_enable_debugfs(struct crete_core_dev *dev); +void crete_ldev_remove_debugfs(struct dentry *dbg); +int crete_lag_add(struct crete_core_dev *dev); +void crete_lag_remove(struct crete_core_dev *dev); +int crete_cmd_lag_enable(struct crete_core_dev *dev, u16 lag_enable); + +#if 0 +void crete_lag_add_netdev(struct crete_core_dev *dev, + struct net_device *netdev); +void crete_lag_remove_netdev(struct crete_core_dev *dev, + struct net_device *netdev); +#endif +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag_debugfs.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag_debugfs.c new file mode 100644 index 0000000..2e0fcb6 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_lag_debugfs.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "crete.h" + +static int state_show(struct seq_file *file, void *priv) +{ + struct crete_core_dev *dev = file->private; + struct crete_lag *ldev; + bool active; + + ldev = dev->lag_dev; + mutex_lock(&ldev->lock); + active = __crete_lag_is_active(ldev); + mutex_unlock(&ldev->lock); + seq_printf(file, "%s\n", active ? "active" : "disabled"); + return 0; +} + +static int members_show(struct seq_file *file, void *priv) +{ + struct crete_core_dev *dev = file->private; + struct crete_lag *ldev; + int i; + + ldev = dev->lag_dev; + mutex_lock(&ldev->lock); + for (i = 0; i < ldev->ports; i++) { + if (!ldev->pf[i].dev) + continue; + seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device)); + } + mutex_unlock(&ldev->lock); + + return 0; +} + +static int mode_show(struct seq_file *file, void *priv) +{ + struct crete_core_dev *dev = file->private; + struct crete_lag *ldev = dev->lag_dev; + + mutex_lock(&ldev->lock); + seq_printf(file, "0x%x\n", ldev->mode_supported); + mutex_unlock(&ldev->lock); + + return 0; +} + +static int hash_show(struct seq_file *file, void *priv) +{ + struct crete_core_dev *dev = file->private; + struct crete_lag *ldev = dev->lag_dev; + + mutex_lock(&ldev->lock); + seq_printf(file, "0x%x\n", ldev->hash_supported); + mutex_unlock(&ldev->lock); + + return 0; +} + + +static int lag_id_show(struct seq_file *file, void *priv) +{ + struct crete_core_dev *dev = file->private; + struct crete_lag *ldev = dev->lag_dev; + + mutex_lock(&ldev->lock); + seq_printf(file, "0x%x\n", ldev->lag_id); + mutex_unlock(&ldev->lock); + + return 0; +} + +static int max_port_show(struct seq_file *file, void *priv) +{ + struct crete_core_dev *dev = file->private; + struct crete_lag *ldev = dev->lag_dev; + + mutex_lock(&ldev->lock); + seq_printf(file, "0x%x\n", ldev->ports); + mutex_unlock(&ldev->lock); + + return 0; +} + +static ssize_t lag_enable_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct crete_core_dev *dev = m->private; + u16 lag_enable; + int ret; + + if (dev->lag_enable == CRETE_LAG_UNSUPPORT) + return -EINVAL; + + ret = kstrtou16_from_user(ubuf, len, 10, &lag_enable); + if (ret < 0) + return ret; + + if (lag_enable != CRETE_LAG_DISABLE && + lag_enable != CRETE_LAG_ENABLE) + return -EINVAL; + + if (lag_enable == dev->lag_enable) + return len; + + ret = crete_cmd_lag_enable(dev, lag_enable); + if (ret) + return ret; + + dev->lag_enable = lag_enable; + *offp += len; + + return len; +} + +static int lag_enable_show(struct seq_file *m, void *data) +{ + struct crete_core_dev *dev = m->private; + + if (dev->lag_enable == CRETE_LAG_ENABLE) + seq_puts(m, "lag is enabled\n"); + else if (dev->lag_enable == CRETE_LAG_DISABLE) + seq_puts(m, "lag is disabled\n"); + else + seq_puts(m, "lag is unsupported\n"); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(state); +DEFINE_SHOW_ATTRIBUTE(members); +DEFINE_SHOW_ATTRIBUTE(mode); +DEFINE_SHOW_ATTRIBUTE(hash); +DEFINE_SHOW_ATTRIBUTE(lag_id); +DEFINE_SHOW_ATTRIBUTE(max_port); +DEFINE_SHOW_STORE_ATTRIBUTE(lag_enable); + +void crete_add_lag_enable_debugfs(struct crete_core_dev *dev) +{ + debugfs_create_file("lag_enable", 0644, crete_debugfs_get_dev_root(dev), + dev, &lag_enable_fops); +} + +void crete_ldev_add_debugfs(struct crete_core_dev *dev) +{ + struct dentry *dbg; + + dbg = debugfs_create_dir("lag", crete_debugfs_get_dev_root(dev)); + dev->dbg.lag_debugfs = dbg; + + debugfs_create_file("state", 0444, dbg, dev, &state_fops); + debugfs_create_file("members", 0444, dbg, dev, &members_fops); + debugfs_create_file("mode_supported", 0444, dbg, dev, &mode_fops); + debugfs_create_file("hash_supported", 0444, dbg, dev, &hash_fops); + debugfs_create_file("lag_id", 0444, dbg, dev, &lag_id_fops); + debugfs_create_file("max_port", 0444, dbg, dev, &max_port_fops); +} + +void crete_ldev_remove_debugfs(struct dentry *dbg) +{ + debugfs_remove_recursive(dbg); +} + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_pldmfw_lib.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_pldmfw_lib.c new file mode 100644 index 0000000..64b231f --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_pldmfw_lib.c @@ -0,0 +1,589 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2018-2019, Intel Corporation. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crete_pldmfw_lib.h" +#include "crete_regs.h" + +/** + * crete_pldm_check_fw_space - Verify that the firmware image has space left + * @data: pointer to private data + * @offset: offset to start from + * @length: length to check for + * + * Verify that the firmware data can hold a chunk of bytes with the specified + * offset and length. + * + * Returns: zero on success, or -EFAULT if the image does not have enough + * space left to fit the expected length. + */ +static int +crete_pldm_check_fw_space(struct crete_pldmfw_priv *data, size_t offset, size_t length) +{ + size_t expected_size = offset + length; + struct device *dev = data->context->dev; + + if (data->fw->size < expected_size) { + dev_err(dev, "Firmware file size smaller than expected. Got %zu bytes, needed %zu bytes\n", + data->fw->size, expected_size); + return -EFAULT; + } + + return 0; +} + +/** + * crete_pldm_move_fw_offset - Move the current firmware offset forward + * @data: pointer to private data + * @bytes_to_move: number of bytes to move the offset forward by + * + * Check that there is enough space past the current offset, and then move the + * offset forward by this amount. + * + * Returns: zero on success, or -EFAULT if the image is too small to fit the + * expected length. + */ +static int +crete_pldm_move_fw_offset(struct crete_pldmfw_priv *data, size_t bytes_to_move) +{ + int err; + + err = crete_pldm_check_fw_space(data, data->offset, bytes_to_move); + if (err) + return err; + + data->offset += bytes_to_move; + + return 0; +} + +/** + * crete_pldm_parse_header - Validate and extract details about the PLDM header + * @data: pointer to private data + * + * Performs initial basic verification of the PLDM image, up to the first + * firmware record. + * + * This includes the following checks and extractions + * + * * Verify that the UUID at the start of the header matches the expected + * value as defined in the DSP0267 PLDM specification + * * Check that the revision is 0x01 + * * Extract the total header_size and verify that the image is large enough + * to contain at least the length of this header + * * Extract the size of the component bitmap length + * * Extract a pointer to the start of the record area + * + * Returns: zero on success, or a negative error code on failure. + */ +static int crete_pldm_parse_header(struct crete_pldmfw_priv *data) +{ + const struct __pldmfw_record_area *record_area; + struct device *dev = data->context->dev; + const struct __pldm_header *header; + size_t header_size; + int err; + + err = crete_pldm_move_fw_offset(data, sizeof(*header)); + if (err) + return err; + + header = (const struct __pldm_header *)data->fw->data; + data->header = header; + + if (!uuid_equal(&header->id, &pldm_firmware_header_id)) { + dev_err(dev, "Invalid package header identifier. Expected UUID %pUB, but got %pUB\n", + &pldm_firmware_header_id, &header->id); + return -EINVAL; + } + + if (header->revision != PACKAGE_HEADER_FORMAT_REVISION) { + dev_err(dev, "Invalid package header revision. Expected revision %u but got %u\n", + PACKAGE_HEADER_FORMAT_REVISION, header->revision); + return -EOPNOTSUPP; + } + + data->total_header_size = get_unaligned_le16(&header->size); + header_size = data->total_header_size - sizeof(*header); + + err = crete_pldm_check_fw_space(data, data->offset, header_size); + if (err) + return err; + + data->component_bitmap_len = + get_unaligned_le16(&header->component_bitmap_len); + + if (data->component_bitmap_len % 8 != 0) { + dev_err(dev, "Invalid component bitmap length. The length is %u, which is not a multiple of 8\n", + data->component_bitmap_len); + return -EINVAL; + } + + data->bitmap_size = data->component_bitmap_len / 8; + + err = crete_pldm_move_fw_offset(data, header->version_len); + if (err) + return err; + + /* extract a pointer to the record area, which just follows the main + * PLDM header data. + */ + record_area = (const struct __pldmfw_record_area *)(data->fw->data + + data->offset); + + err = crete_pldm_move_fw_offset(data, sizeof(*record_area)); + if (err) + return err; + + data->record_count = record_area->record_count; + data->record_start = record_area->records; + dev_info(dev, "data->offset [0x%lx] record_count [%d] record_start [%p]\n", data->offset, + record_area->record_count, record_area->records); + + return 0; +} + +/** + * crete_pldm_check_desc_tlv_len - Check that the length matches expectation + * @data: pointer to image details + * @type: the descriptor type + * @size: the length from the descriptor header + * + * If the descriptor type is one of the documented descriptor types according + * to the standard, verify that the provided length matches. + * + * If the type is not recognized or is VENDOR_DEFINED, return zero. + * + * Returns: zero on success, or -EINVAL if the specified size of a standard + * TLV does not match the expected value defined for that TLV. + */ +static int +crete_pldm_check_desc_tlv_len(struct crete_pldmfw_priv *data, u16 type, u16 size) +{ + struct device *dev = data->context->dev; + u16 expected_size; + + switch (type) { + case PLDM_DESC_ID_PCI_VENDOR_ID: + case PLDM_DESC_ID_PCI_DEVICE_ID: + case PLDM_DESC_ID_PCI_SUBVENDOR_ID: + case PLDM_DESC_ID_PCI_SUBDEV_ID: + expected_size = 2; + break; + case PLDM_DESC_ID_PCI_REVISION_ID: + expected_size = 1; + break; + case PLDM_DESC_ID_PNP_VENDOR_ID: + expected_size = 3; + break; + case PLDM_DESC_ID_IANA_ENTERPRISE_ID: + case PLDM_DESC_ID_ACPI_VENDOR_ID: + case PLDM_DESC_ID_PNP_PRODUCT_ID: + case PLDM_DESC_ID_ACPI_PRODUCT_ID: + expected_size = 4; + break; + case PLDM_DESC_ID_UUID: + expected_size = 16; + break; + case PLDM_DESC_ID_VENDOR_DEFINED: + return 0; + default: + /* Do not report an error on an unexpected TLV */ + dev_err(dev, "Found unrecognized TLV type 0x%04x\n", type); + return 0; + } + + if (size != expected_size) { + dev_err(dev, "Found TLV type 0x%04x with unexpected length. Got %u bytes, but expected %u bytes\n", + type, size, expected_size); + return -EINVAL; + } + + return 0; +} + +/** + * pldm_parse_desc_tlvs - Check and skip past a number of TLVs + * @data: pointer to private data + * @record: pointer to the record this TLV belongs too + * @desc_count: descriptor count + * + * From the current offset, read and extract the descriptor TLVs, updating the + * current offset each time. + * + * Returns: zero on success, or a negative error code on failure. + */ +static int +crete_pldm_parse_desc_tlvs(struct crete_pldmfw_priv *data, + struct pldmfw_record *record, u8 desc_count) +{ + const struct __pldmfw_desc_tlv *__desc; + const u8 *desc_start; + u8 i; + + desc_start = data->fw->data + data->offset; + + pldm_for_each_desc_tlv(i, __desc, desc_start, desc_count) { + struct pldmfw_desc_tlv *desc; + int err; + u16 type, size; + + err = crete_pldm_move_fw_offset(data, sizeof(*__desc)); + if (err) + return err; + + type = get_unaligned_le16(&__desc->type); + + /* According to DSP0267, this only includes the data field */ + size = get_unaligned_le16(&__desc->size); + + err = crete_pldm_check_desc_tlv_len(data, type, size); + if (err) + return err; + + /* check that we have space and move the offset forward */ + err = crete_pldm_move_fw_offset(data, size); + if (err) + return err; + + desc = kzalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + desc->type = type; + desc->size = size; + desc->data = __desc->data; + + list_add_tail(&desc->entry, &record->descs); + } + + return 0; +} + +/** + * crete_pldm_parse_one_record - Verify size of one PLDM record + * @data: pointer to image details + * @__record: pointer to the record to check + * + * This function checks that the record size does not exceed either the size + * of the firmware file or the total length specified in the header section. + * + * It also verifies that the recorded length of the start of the record + * matches the size calculated by adding the static structure length, the + * component bitmap length, the version string length, the length of all + * descriptor TLVs, and the length of the package data. + * + * Returns: zero on success, or a negative error code on failure. + */ +static int +crete_pldm_parse_one_record(struct crete_pldmfw_priv *data, + const struct __pldmfw_record_info *__record) +{ + struct pldmfw_record *record; + size_t measured_length; + int err; + const u8 *bitmap_ptr; + u16 record_len; + int i; + + /* Make a copy and insert it into the record list */ + record = kzalloc(sizeof(*record), GFP_KERNEL); + if (!record) + return -ENOMEM; + + INIT_LIST_HEAD(&record->descs); + list_add_tail(&record->entry, &data->records); + + /* Then check that we have space and move the offset */ + err = crete_pldm_move_fw_offset(data, sizeof(*__record)); + if (err) + return err; + + record_len = get_unaligned_le16(&__record->record_len); + record->package_data_len = get_unaligned_le16(&__record->package_data_len); + record->device_update_flags = get_unaligned_le32(&__record->device_update_flags); + record->version_len = __record->version_len; + record->version_type = __record->version_type; + + bitmap_ptr = data->fw->data + data->offset; + + /* check that we have space for the component bitmap length */ + err = crete_pldm_move_fw_offset(data, data->bitmap_size); + if (err) + return err; + + record->component_bitmap_len = data->component_bitmap_len; + record->component_bitmap = bitmap_zalloc(record->component_bitmap_len, + GFP_KERNEL); + if (!record->component_bitmap) + return -ENOMEM; + + for (i = 0; i < data->bitmap_size; i++) + bitmap_set_value8(record->component_bitmap, bitmap_ptr[i], i * 8); + + record->version_string = data->fw->data + data->offset; + + err = crete_pldm_move_fw_offset(data, record->version_len); + if (err) + return err; + + /* Scan through the descriptor TLVs and find the end */ + err = crete_pldm_parse_desc_tlvs(data, record, __record->descriptor_count); + if (err) + return err; + + record->package_data = data->fw->data + data->offset; + + err = crete_pldm_move_fw_offset(data, record->package_data_len); + if (err) + return err; + + measured_length = data->offset - ((const u8 *)__record - data->fw->data); + if (measured_length != record_len) { + dev_err(data->context->dev, "Unexpected record length. Measured record length is %zu bytes, expected length is %u bytes\n", + measured_length, record_len); + return -EFAULT; + } + + return 0; +} + +/** + * crete_pldm_parse_records - Locate the start of the component area + * @data: pointer to private data + * + * Extract the record count, and loop through each record, searching for the + * component area. + * + * Returns: zero on success, or a negative error code on failure. + */ +static int crete_pldm_parse_records(struct crete_pldmfw_priv *data) +{ + const struct __pldmfw_component_area *component_area; + const struct __pldmfw_record_info *record; + int err; + u8 i; + + pldm_for_each_record(i, record, data->record_start, data->record_count) { + err = crete_pldm_parse_one_record(data, record); + if (err) + return err; + } + + /* Extract a pointer to the component area, which just follows the + * PLDM device record data. + */ + component_area = (const struct __pldmfw_component_area *)(data->fw->data + data->offset); + + err = crete_pldm_move_fw_offset(data, sizeof(*component_area)); + if (err) + return err; + + data->component_count = + get_unaligned_le16(&component_area->component_image_count); + data->component_start = component_area->components; + + return 0; +} + +/** + * crete_pldm_parse_components - Locate the CRC header checksum + * @data: pointer to private data + * + * Extract the component count, and find the pointer to the component area. + * Scan through each component searching for the end, which should point to + * the package header checksum. + * + * Extract the package header CRC and save it for verification. + * + * Returns: zero on success, or a negative error code on failure. + */ +static int crete_pldm_parse_components(struct crete_pldmfw_priv *data) +{ + const struct __pldmfw_component_info *__component; + struct device *dev = data->context->dev; + const u8 *header_crc_ptr; + int err; + u8 i; + + pldm_for_each_component(i, __component, data->component_start, data->component_count) { + struct pldmfw_component *component; + u32 offset, size; + + err = crete_pldm_move_fw_offset(data, + sizeof(*__component) + COMPONENT_OPAQUE_DATA_LENGTH); + if (err) + return err; + + err = crete_pldm_move_fw_offset(data, __component->version_len); + if (err) + return err; + + offset = get_unaligned_le32(&__component->location_offset); + size = get_unaligned_le32(&__component->size); + + err = crete_pldm_check_fw_space(data, offset, size); + if (err) + return err; + + component = kzalloc(sizeof(*component), GFP_KERNEL); + if (!component) + return -ENOMEM; + + component->index = i; + component->classification = get_unaligned_le16(&__component->classification); + component->identifier = get_unaligned_le16(&__component->identifier); + component->comparison_stamp = get_unaligned_le32(&__component->comparison_stamp); + component->options = get_unaligned_le16(&__component->options); + component->activation_method = get_unaligned_le16(&__component->activation_method); + component->version_type = __component->version_type; + component->version_len = __component->version_len; + component->version_string = __component->version_string; + component->component_data = data->fw->data + offset; + component->component_size = size; + + list_add_tail(&component->entry, &data->components); + } + + header_crc_ptr = data->fw->data + data->offset; +// dev_err(dev, "printk CRC:\n"); +// hexdump((char *)header_crc_ptr, sizeof(data->header_crc)); + + err = crete_pldm_move_fw_offset(data, sizeof(data->header_crc)); + if (err) + return err; + + /* Make sure that we reached the expected offset */ + if (data->offset != data->total_header_size) { + dev_err(dev, "Invalid firmware header size. Expected %u but got %zu\n", + data->total_header_size, data->offset); + return -EFAULT; + } + + data->header_crc = get_unaligned_le32(header_crc_ptr); + + return 0; +} + +/** + * crete_pldm_verify_header_crc - Verify that the CRC in the header matches + * @data: pointer to private data + * + * Calculates the 32-bit CRC using the standard IEEE 802.3 CRC polynomial and + * compares it to the value stored in the header. + * + * Returns: zero on success if the CRC matches, or -EBADMSG on an invalid CRC. + */ +static int crete_pldm_verify_header_crc(struct crete_pldmfw_priv *data) +{ + struct device *dev = data->context->dev; + u32 calculated_crc; + size_t length; + + /* Calculate the 32-bit CRC of the header contents up to but + * not including the checksum. Note that the Linux crc32_le function + * does not perform an expected final XOR. + */ + length = data->offset - sizeof(data->header_crc); + calculated_crc = crc32_le(~0, data->fw->data, length) ^ ~0; + + if (calculated_crc != data->header_crc) { + dev_err(dev, "Invalid CRC in firmware header. Got 0x%08x but expected 0x%08x\n", + calculated_crc, data->header_crc); + return -EBADMSG; + } + + return 0; +} + +/** + * crete_pldmfw_free_priv - Free memory allocated while parsing the PLDM image + * @data: pointer to the PLDM data structure + * + * Loops through and clears all allocated memory associated with each + * allocated descriptor, record, and component. + */ +void crete_pldmfw_free_priv(struct crete_pldmfw_priv *data) +{ + struct pldmfw_component *component, *c_safe; + struct pldmfw_record *record, *r_safe; + struct pldmfw_desc_tlv *desc, *d_safe; + + list_for_each_entry_safe(component, c_safe, &data->components, entry) { + list_del(&component->entry); + kfree(component); + } + + list_for_each_entry_safe(record, r_safe, &data->records, entry) { + list_for_each_entry_safe(desc, d_safe, &record->descs, entry) { + list_del(&desc->entry); + kfree(desc); + } + + if (record->component_bitmap) { + bitmap_free(record->component_bitmap); + record->component_bitmap = NULL; + } + + list_del(&record->entry); + kfree(record); + } +} +EXPORT_SYMBOL(crete_pldmfw_free_priv); + +/** + * crete_pldm_parse_image - parse and extract details from PLDM image + * @data: pointer to private data + * + * Verify that the firmware file contains valid data for a PLDM firmware + * file. Extract useful pointers and data from the firmware file and store + * them in the data structure. + * + * The PLDM firmware file format is defined in DMTF DSP0267 1.0.0. Care + * should be taken to use get_unaligned_le* when accessing data from the + * pointers in data. + * + * Returns: zero on success, or a negative error code on failure. + */ +int crete_pldm_parse_image(struct crete_pldmfw_priv *data) +{ + int err; + struct device *dev = data->context->dev; + + if (WARN_ON(!(data->context->dev && data->fw->data && data->fw->size))) + return -EINVAL; + + err = crete_pldm_parse_header(data); + if (err) { + dev_err(dev, "crete_pldm parse_header failed err %d\n", err); + return err; + } + + err = crete_pldm_parse_records(data); + if (err) { + dev_err(dev, "crete_pldm parse_records failed err %d\n", err); + return err; + } + + err = crete_pldm_parse_components(data); + if (err) { + dev_err(dev, "crete_pldm parse_components failed err %d\n", err); + return err; + } + + return crete_pldm_verify_header_crc(data); +} +EXPORT_SYMBOL(crete_pldm_parse_image); + + +MODULE_AUTHOR("Jacob Keller "); +MODULE_DESCRIPTION("PLDM firmware flash update library"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_pldmfw_lib.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_pldmfw_lib.h new file mode 100644 index 0000000..104f1b2 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_pldmfw_lib.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2018-2019, Intel Corporation. */ + +#ifndef _CRETE_PLDMFW_LIB_H_ +#define _CRETE_PLDMFW_LIB_H_ + +/* The following data structures define the layout of a firmware binary + * following the "PLDM For Firmware Update Specification", DMTF standard + * #DSP0267. + * + * pldmfw.c uses these structures to implement a simple engine that will parse + * a fw binary file in this format and perform a firmware update for a given + * device. + * + * Due to the variable sized data layout, alignment of fields within these + * structures is not guaranteed when reading. For this reason, all multi-byte + * field accesses should be done using the unaligned access macros. + * Additionally, the standard specifies that multi-byte fields are in + * LittleEndian format. + * + * The structure definitions are not made public, in order to keep direct + * accesses within code that is prepared to deal with the limitation of + * unaligned access. + */ + +/* UUID for PLDM firmware packages: f018878c-cb7d-4943-9800-a02f059aca02 */ +static const uuid_t pldm_firmware_header_id = + UUID_INIT(0xf018878c, 0xcb7d, 0x4943, + 0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02); + +/* Revision number of the PLDM header format this code supports */ +// SIM_DEBUG +#define PACKAGE_HEADER_FORMAT_REVISION 0x03 +#define COMPONENT_OPAQUE_DATA_LENGTH 4 + +/* timestamp104 structure defined in PLDM Base specification */ +#define PLDM_TIMESTAMP_SIZE 13 +struct __pldm_timestamp { + u8 b[PLDM_TIMESTAMP_SIZE]; +} __packed __aligned(1); + +/* Package Header Information */ +struct __pldm_header { + uuid_t id; /* PackageHeaderIdentifier */ + u8 revision; /* PackageHeaderFormatRevision */ + __le16 size; /* PackageHeaderSize */ + struct __pldm_timestamp release_date; /* PackageReleaseDateTime */ + __le16 component_bitmap_len; /* ComponentBitmapBitLength */ + u8 version_type; /* PackageVersionStringType */ + u8 version_len; /* PackageVersionStringLength */ + + /* + * DSP0267 also includes the following variable length fields at the + * end of this structure: + * + * PackageVersionString, length is version_len. + * + * The total size of this section is + * sizeof(pldm_header) + version_len; + */ + u8 version_string[]; /* PackageVersionString */ +} __packed __aligned(1); + +/* Firmware Device ID Record */ +struct __pldmfw_record_info { + __le16 record_len; /* RecordLength */ + u8 descriptor_count; /* DescriptorCount */ + __le32 device_update_flags; /* DeviceUpdateOptionFlags */ + u8 version_type; /* ComponentImageSetVersionType */ + u8 version_len; /* ComponentImageSetVersionLength */ + __le16 package_data_len; /* FirmwareDevicePackageDataLength */ + + /* + * DSP0267 also includes the following variable length fields at the + * end of this structure: + * + * ApplicableComponents, length is component_bitmap_len from header + * ComponentImageSetVersionString, length is version_len + * RecordDescriptors, a series of TLVs with 16bit type and length + * FirmwareDevicePackageData, length is package_data_len + * + * The total size of each record is + * sizeof(pldmfw_record_info) + + * component_bitmap_len (converted to bytes!) + + * version_len + + * + + * package_data_len + */ + u8 variable_record_data[]; +} __packed __aligned(1); + +/* Firmware Descriptor Definition */ +struct __pldmfw_desc_tlv { + __le16 type; /* DescriptorType */ + __le16 size; /* DescriptorSize */ + u8 data[]; /* DescriptorData */ +} __aligned(1); + +/* Firmware Device Identification Area */ +struct __pldmfw_record_area { + u8 record_count; /* DeviceIDRecordCount */ + /* This is not a struct type because the size of each record varies */ + u8 records[]; +} __aligned(1); + +/* Individual Component Image Information */ +struct __pldmfw_component_info { + __le16 classification; /* ComponentClassfication */ + __le16 identifier; /* ComponentIdentifier */ + __le32 comparison_stamp; /* ComponentComparisonStamp */ + __le16 options; /* componentOptions */ + __le16 activation_method; /* RequestedComponentActivationMethod */ + __le32 location_offset; /* ComponentLocationOffset */ + __le32 size; /* ComponentSize */ + u8 version_type; /* ComponentVersionStringType */ + u8 version_len; /* ComponentVersionStringLength */ + + /* + * DSP0267 also includes the following variable length fields at the + * end of this structure: + * + * ComponentVersionString, length is version_len + * + * The total size of this section is + * sizeof(pldmfw_component_info) + version_len; + */ + u8 version_string[]; +} __packed __aligned(1); + +/* Component Image Information Area */ +struct __pldmfw_component_area { + __le16 component_image_count; + /* This is not a struct type because the component size varies */ + u8 components[]; +} __aligned(1); + +/** + * pldm_first_desc_tlv + * @start: byte offset of the start of the descriptor TLVs + * + * Converts the starting offset of the descriptor TLVs into a pointer to the + * first descriptor. + */ +#define pldm_first_desc_tlv(start) \ + ((const struct __pldmfw_desc_tlv *)(start)) + +/** + * pldm_next_desc_tlv + * @desc: pointer to a descriptor TLV + * + * Finds the pointer to the next descriptor following a given descriptor + */ +#define pldm_next_desc_tlv(desc) \ + ((const struct __pldmfw_desc_tlv *)((desc)->data + \ + get_unaligned_le16(&(desc)->size))) + +/** + * pldm_for_each_desc_tlv + * @i: variable to store descriptor index + * @desc: variable to store descriptor pointer + * @start: byte offset of the start of the descriptors + * @count: the number of descriptors + * + * for loop macro to iterate over all of the descriptors of a given PLDM + * record. + */ +#define pldm_for_each_desc_tlv(i, desc, start, count) \ + for ((i) = 0, (desc) = pldm_first_desc_tlv(start); \ + (i) < (count); \ + (i)++, (desc) = pldm_next_desc_tlv(desc)) + +/** + * pldm_first_record + * @start: byte offset of the start of the PLDM records + * + * Converts a starting offset of the PLDM records into a pointer to the first + * record. + */ +#define pldm_first_record(start) \ + ((const struct __pldmfw_record_info *)(start)) + +/** + * pldm_next_record + * @record: pointer to a PLDM record + * + * Finds a pointer to the next record following a given record + */ +#define pldm_next_record(record) \ + ((const struct __pldmfw_record_info *) \ + ((const u8 *)(record) + get_unaligned_le16(&(record)->record_len))) + +/** + * pldm_for_each_record + * @i: variable to store record index + * @record: variable to store record pointer + * @start: byte offset of the start of the records + * @count: the number of records + * + * for loop macro to iterate over all of the records of a PLDM file. + */ +#define pldm_for_each_record(i, record, start, count) \ + for ((i) = 0, (record) = pldm_first_record(start); \ + (i) < (count); \ + (i)++, (record) = pldm_next_record(record)) + +/** + * pldm_first_component + * @start: byte offset of the start of the PLDM components + * + * Convert a starting offset of the PLDM components into a pointer to the + * first component + */ +#define pldm_first_component(start) \ + ((const struct __pldmfw_component_info *)(start)) + +/** + * pldm_next_component + * @component: pointer to a PLDM component + * + * Finds a pointer to the next component following a given component + */ +#define pldm_next_component(component) \ + ((const struct __pldmfw_component_info *)((component)->version_string + \ + (component)->version_len + COMPONENT_OPAQUE_DATA_LENGTH)) + +/** + * pldm_for_each_component + * @i: variable to store component index + * @component: variable to store component pointer + * @start: byte offset to the start of the first component + * @count: the number of components + * + * for loop macro to iterate over all of the components of a PLDM file. + */ +#define pldm_for_each_component(i, component, start, count) \ + for ((i) = 0, (component) = pldm_first_component(start); \ + (i) < (count); \ + (i)++, (component) = pldm_next_component(component)) + +struct crete_pldmfw_priv { + struct pldmfw *context; + const struct firmware *fw; + + /* current offset of firmware image */ + size_t offset; + + struct list_head records; + struct list_head components; + + /* PLDM Firmware Package Header */ + const struct __pldm_header *header; + u16 total_header_size; + + /* length of the component bitmap */ + u16 component_bitmap_len; + u16 bitmap_size; + + /* Start of the component image information */ + u16 component_count; + const u8 *component_start; + + /* Start pf the firmware device id records */ + const u8 *record_start; + u8 record_count; + + /* The CRC at the end of the package header */ + u32 header_crc; + + struct pldmfw_record *matching_record; +}; + + + +int crete_pldm_parse_image(struct crete_pldmfw_priv *data); +void crete_pldmfw_free_priv(struct crete_pldmfw_priv *data); + + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ptp.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ptp.c new file mode 100644 index 0000000..e2bb6cb --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ptp.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include "crete.h" +#include "crete_ptp.h" + +static int crete_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + pr_warn("ptp %s stub\n", __func__); + return 0; +} + +static int crete_ptp_adjphase(struct ptp_clock_info *ptp, s32 delta) +{ + pr_warn("ptp %s stub\n", __func__); + return 0; +} + +static int crete_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + pr_warn("ptp %s stub\n", __func__); + return 0; +} + +static int crete_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + pr_warn("ptp %s stub\n", __func__); + return 0; +} +static int crete_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) +{ + pr_warn("ptp %s stub\n", __func__); + return 0; +} + + +static const struct ptp_clock_info crete_ptp_clock_info = { + .owner = THIS_MODULE, + .name = "crete_ptp", + .max_adj = 50000000, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .n_pins = 0, + .pps = 0, + .adjfine = crete_ptp_adjfine, + .adjphase = crete_ptp_adjphase, + .adjtime = crete_ptp_adjtime, + .gettimex64 = crete_ptp_gettimex, + .settime64 = crete_ptp_settime, + .enable = NULL, + .verify = NULL, +}; + +void crete_init_clock(struct crete_core_dev *mdev) +{ + pr_warn("ptp %s stub\n", __func__); +} +void crete_cleanup_clock(struct crete_core_dev *mdev) +{ + pr_warn("ptp %s stub\n", __func__); +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ptp.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ptp.h new file mode 100644 index 0000000..e818641 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_ptp.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __CRETE_PTP_H +#define __CRETE_PTP_H +#include +#include +#include +#include +#include +#include +#include "crete_eswitch.h" + +struct crete_clock { + struct crete_nb pps_nb; + seqlock_t lock; + struct hwtstamp_config hwtstamp_config; + struct ptp_clock *ptp; + struct ptp_clock_info ptp_info; +}; +void crete_init_clock(struct crete_core_dev *mdev); +void crete_cleanup_clock(struct crete_core_dev *mdev); + + +#endif /* __CRETE_PTP_H */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_adapt.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_adapt.c new file mode 100644 index 0000000..1fd3101 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_adapt.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "crete_rdma_adapt.h" +#include "crete_rdma_dev.h" + +#define RDMA_ERR(pdev, fmt, ...) dev_err(&pdev->dev, fmt, ##__VA_ARGS__) +#define jm_core_dbg(pdev, format, ...) \ + dev_dbg(&pdev->dev, "%s:%d:(pid %d): " format, __func__, \ + __LINE__, current->pid, ##__VA_ARGS__) + +#define TO_EQ_DB_VAL(ci, alt, v0, v1) \ + ((((ci) & 0xffffff) << 2) | (((alt) ? (v0) : (v1)) & 0x3)) + + +static bool crete_rdma_is_error(struct jm_rdma_core *dev) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + if (!dev) { + pr_err("rdma get irq err: dev is null\n"); + return -EINVAL; + } + + return pci_channel_offline(core_dev->pdev); +} + +static void crete_rdma_trigger_doorbell(struct jm_rdma_core *dev, u32 event) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + if (!dev) { + pr_err("rdma get irq err: dev is null\n"); + return; + } + jm_core_dbg(core_dev->pdev, "rdma db base addr:0x%p val:0x%x\r\n", + core_dev->rdma_adp.cmd_db_reg, event); + iowrite32(event, core_dev->rdma_adp.cmd_db_reg); +} + + +static int crete_rdma_get_irqn(struct jm_rdma_core *dev, int index) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + int irq; + + if (!dev) { + pr_err("rdma get irq err: dev is null\n"); + goto ret; + } + if (index >= core_dev->rdma_adp.vector_num + core_dev->rdma_adp.vector_base) { + pr_err("@@@@###index =%d >= num=%d vector_base=%d@@@@\n", + index, core_dev->rdma_adp.vector_num, core_dev->rdma_adp.vector_base); + goto ret; + } + + irq = core_dev->irq_info[index].vector; + + jm_core_dbg(core_dev->pdev, "vector base = %d index = %d irqn =%d\n", + core_dev->rdma_adp.vector_base, index, irq); + return irq; +ret: + return -EINVAL; +} + +struct device *crete_rdma_get_device(struct jm_rdma_core *dev) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + struct pci_dev *pdev = core_dev->pdev; + + return &pdev->dev; +} + +void crete_rdma_get_dev_info(struct jm_rdma_core *dev, u8 *feature, + u8 *rev_id, u16 *dev_id, u16 *vendor) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + struct pci_dev *pdev = core_dev->pdev; + + *rev_id = pdev->revision; + *dev_id = pdev->device; + *vendor = pdev->vendor; + if (!pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64)) + *feature = *feature | JM_DEVICE_FEATURE_ATOMIC_HCA; + +} + + +void crete_rdma_get_bar(struct jm_rdma_core *dev, void **base, void **eq_reg) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + *base = core_dev->rdma_adp.reg_addr; + *eq_reg = core_dev->rdma_adp.eq_db_reg; +} + +void crete_rdma_get_uar(struct jm_rdma_core *dev, phys_addr_t *base, int *len) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + *base = core_dev->rdma_adp.uar_base; + *len = core_dev->rdma_adp.uar_size; +} + +void crete_rdma_get_vector(struct jm_rdma_core *dev, int *num, int *base) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + *num = core_dev->rdma_adp.vector_num; + *base = core_dev->rdma_adp.vector_base; +} + + +static struct jm_rdma_ops jm_pci_core_ops = { + .get_device = crete_rdma_get_device, + .get_dev_info = crete_rdma_get_dev_info, + .cmdq_notify = crete_rdma_trigger_doorbell, + .get_irqn = crete_rdma_get_irqn, + .store_bond_info = NULL, + .get_bar = crete_rdma_get_bar, + .get_uar = crete_rdma_get_uar, + .get_vector = crete_rdma_get_vector, + .is_error = crete_rdma_is_error, + .timer_db = NULL, + .reload = NULL, +}; + + +int crete_rdma_init_core_dev(struct crete_core_dev *core_dev, struct pci_dev *pdev) +{ + struct jm_rdma_core *dev; + int ret = 0; + + dev = &core_dev->rdma_coredev; + + dev->ops = &jm_pci_core_ops; + + mutex_init(&core_dev->rdma_adp.intf_state_mutex); + ret = jm_adev_idx_alloc(); + if (ret < 0) { + RDMA_ERR(pdev, "failed to initialize adev index\n"); + goto err_core_free; + } + dev->adev_idx = ret; + ret = jm_adev_init(dev); + if (ret < 0) { + RDMA_ERR(pdev, "failed to initialize adev table\n"); + goto err_idx_free; + } + return 0; +err_idx_free: + jm_adev_idx_free(dev->adev_idx); +err_core_free: + mutex_destroy(&core_dev->rdma_adp.intf_state_mutex); + return ret; +} + +static void crete_rdma_remove_core_dev(struct crete_core_dev *core_dev) +{ + struct jm_rdma_core *dev; + + dev = &core_dev->rdma_coredev; + jm_adev_cleanup(dev); + jm_adev_idx_free(dev->adev_idx); + mutex_destroy(&core_dev->rdma_adp.intf_state_mutex); +} + +int crete_rdma_coredev_init(struct crete_core_dev *core_dev) +{ + int err; + + if (!crete_have_rdma_cap(core_dev)) { + jm_core_dbg(core_dev->pdev, "not found rdma cap.\n"); + return 0; + } + core_dev->rdma_adp.flags |= CORSICA_RDMA_MASK; + err = crete_rdma_init_core_dev(core_dev, core_dev->pdev); + if (err) + goto err_rdma_init_core_dev; + + + core_dev->rdma_adp.reg_addr = + core_dev->io_addr + core_dev->hw.rdma_desc.offset * CRETE_RDMA_OFFSET_UNIT; + core_dev->rdma_adp.bar_offset = core_dev->hw.rdma_desc.offset * CRETE_RDMA_OFFSET_UNIT; + core_dev->rdma_adp.bar_len = core_dev->hw.rdma_desc.len * CRETE_RDMA_OFFSET_UNIT; + core_dev->rdma_adp.cmd_db_reg = core_dev->rdma_adp.reg_addr + JM_DEV_CMD_DB_OFFSET; + core_dev->rdma_adp.eq_db_reg = core_dev->rdma_adp.reg_addr + JM_DEV_EQ_DB_OFFSET; + core_dev->rdma_adp.uar_base = + core_dev->bar_addr + core_dev->rdma_adp.bar_offset + JM_DEV_INIT_SEG_SIZE; + core_dev->rdma_adp.uar_size = JM_DEV_UAR_SEG_SIZE; + + jm_core_dbg(core_dev->pdev, + "reg_addr =0x%p uar_base =0x%llx uar_size =0x%x bar=%d init_base=0x%llx offset=0x%x\n", + core_dev->rdma_adp.reg_addr, core_dev->rdma_adp.uar_base, + core_dev->rdma_adp.uar_size, JM_DEV_BAR_IDX, core_dev->bar_addr, + core_dev->rdma_adp.bar_offset); + return 0; + +err_rdma_init_core_dev: + crete_rdma_remove_core_dev(core_dev); + return err; +} + +void crete_rdma_coredev_uninit(struct crete_core_dev *core_dev) +{ + if (!crete_have_rdma_cap(core_dev)) + return; + + crete_rdma_remove_core_dev(core_dev); + memset(&core_dev->rdma_coredev, 0, sizeof(core_dev->rdma_coredev)); +} + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_adapt.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_adapt.h new file mode 100644 index 0000000..f7dc9f4 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_adapt.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __CRETE_RDMA_CORE_ADAPT_H +#define __CRETE_RDMA_CORE_ADAPT_H +#include "crete.h" + +#define JM_AUX_VECTOR_NUM 3 + +enum { + JM_EQ_DB_FLAG_ARM = BIT(0), + JM_EQ_DB_FLAG_COMP = BIT(1), +}; + +enum { + JM_PRIV_FLAGS_DISABLE_IB_ADEV = 1 << 0, + JM_PRIV_FLAGS_DISABLE_ALL_ADEV = 1 << 1, + JM_PRIV_FLAGS_DETACH = 1 << 2, +}; + +enum { + JM_DEV_BAR_IDX = 0, + JM_DEV_INIT_SEG_SIZE = 64 * 1024, + JM_DEV_CMD_DB_OFFSET = 0xEFC0, + JM_DEV_EQ_DB_OFFSET = 0xF000, + JM_DEV_UAR_SEG_SIZE = 64 * 1024, +}; + +#define CRETE_RDMA_OFFSET_UNIT 0x1000 +int crete_rdma_coredev_init(struct crete_core_dev *core_dev); +void crete_rdma_coredev_uninit(struct crete_core_dev *core_dev); + +#endif + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_dev.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_dev.c new file mode 100644 index 0000000..0617154 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_dev.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright (c) 2022, Jaguarmicro Technologies, Inc. All rights reserved. + */ + +#include +#include +#include "crete_rdma_dev.h" +#include "rdma.h" +#include "crete_rdma_adapt.h" + +/* intf dev list mutex */ +static DEFINE_MUTEX(jm_intf_mutex); +static DEFINE_IDA(jm_adev_ida); + +bool is_ib_supported(struct jm_rdma_core *dev) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + if (core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DISABLE_IB_ADEV) + return false; + if (!(core_dev->rdma_adp.flags & CORSICA_RDMA_MASK)) + return false; + return true; +} + +enum { + JM_INTERFACE_PROTOCOL_IB, +}; + + +static const struct jm_adev_device { + const char *suffix; + bool (*is_supported)(struct jm_rdma_core *dev); +} jm_adev_devices[] = { + [JM_INTERFACE_PROTOCOL_IB] = { .suffix = "rdma", + .is_supported = &is_ib_supported }, +}; + + +int jm_adev_idx_alloc(void) +{ + return ida_alloc(&jm_adev_ida, GFP_KERNEL); +} + +void jm_adev_idx_free(int idx) +{ + ida_free(&jm_adev_ida, idx); +} + +int jm_adev_init(struct jm_rdma_core *dev) +{ + struct jm_rdma_adev **adev; + + adev = kcalloc(ARRAY_SIZE(jm_adev_devices), + sizeof(struct jm_rdma_adev *), GFP_KERNEL); + if (!adev) + return -ENOMEM; + dev->adev = adev; + return 0; +} + +void jm_adev_cleanup(struct jm_rdma_core *dev) +{ + kfree(dev->adev); +} + +static void adev_release(struct device *dev) +{ + struct jm_rdma_adev *adev = container_of(dev, struct jm_rdma_adev, adev.dev); + + struct jm_rdma_core *core = adev->rdma_core; + int idx = adev->idx; + + kfree(adev); + core->adev[idx] = NULL; +} + +static struct jm_rdma_adev *add_adev(struct jm_rdma_core *dev, int idx) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + const char *suffix = jm_adev_devices[idx].suffix; + struct auxiliary_device *adev; + struct jm_rdma_adev *jadev; + int ret; + + jadev = kzalloc(sizeof(*jadev), GFP_KERNEL); + if (!jadev) + return ERR_PTR(-ENOMEM); + adev = &jadev->adev; + adev->id = dev->adev_idx; + adev->name = suffix; + adev->dev.parent = &core_dev->pdev->dev; + adev->dev.release = adev_release; + jadev->rdma_core = dev; + jadev->idx = idx; + ret = auxiliary_device_init(adev); + if (ret) { + kfree(jadev); + return ERR_PTR(ret); + } + ret = auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ERR_PTR(ret); + } + return jadev; +} + +static void del_adev(struct auxiliary_device *adev) +{ + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + + +int jm_attach_device(struct jm_rdma_core *dev) +{ + struct auxiliary_device *adev; + struct auxiliary_driver *adrv; + struct jm_rdma_adev **jadev = dev->adev; + int ret = 0, i; + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + mutex_lock(&jm_intf_mutex); + core_dev->rdma_adp.priv_flags &= ~JM_PRIV_FLAGS_DETACH; + for (i = 0; i < ARRAY_SIZE(jm_adev_devices); i++) { + if (!jadev[i]) { + bool is_supported = false; + + if (jm_adev_devices[i].is_supported) + is_supported = jm_adev_devices[i].is_supported(dev); + if (!is_supported) + continue; + jadev[i] = add_adev(dev, i); + if (IS_ERR(jadev[i])) { + ret = PTR_ERR(jadev[i]); + jadev[i] = NULL; + } + } else { + adev = &(jadev[i]->adev); + if (!adev->dev.driver) + continue; + adrv = to_auxiliary_drv(adev->dev.driver); + if (adrv->resume) + ret = adrv->resume(adev); + } + if (ret) { + pr_warn("Device[%d] (%s) failed to load\n", + i, jm_adev_devices[i].suffix); + break; + } + } + mutex_unlock(&jm_intf_mutex); + return ret; +} + +void jm_detach_device(struct jm_rdma_core *dev) +{ + struct auxiliary_device *adev; + struct auxiliary_driver *adrv; + struct jm_rdma_adev **jadev = dev->adev; + pm_message_t pm = {}; + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + int i; + + if (!jadev) { + pr_err("jnet adev null\n"); + return; + } + mutex_lock(&jm_intf_mutex); + for (i = ARRAY_SIZE(jm_adev_devices) - 1; i >= 0; i--) { + if (!jadev[i]) + continue; + adev = &jadev[i]->adev; + if (!adev->dev.driver) { + pr_err("adev->dev.driver is null\n"); + goto skip_suspend; + } + adrv = to_auxiliary_drv(adev->dev.driver); + if (adrv->suspend) { + adrv->suspend(adev, pm); + continue; + } +skip_suspend: + del_adev(&jadev[i]->adev); + jadev[i] = NULL; + } + core_dev->rdma_adp.priv_flags |= JM_PRIV_FLAGS_DETACH; + mutex_unlock(&jm_intf_mutex); +} + +static int add_drivers(struct jm_rdma_core *dev) +{ + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(jm_adev_devices); i++) { + bool is_supported = false; + + if (dev->adev[i]) + continue; + if (jm_adev_devices[i].is_supported) + is_supported = jm_adev_devices[i].is_supported(dev); + if (!is_supported) + continue; + dev->adev[i] = add_adev(dev, i); + if (IS_ERR(dev->adev[i])) { + pr_warn("Device[%d] (%s) failed to load\n", i, + jm_adev_devices[i].suffix); + ret = PTR_ERR(dev->adev[i]); + dev->adev[i] = NULL; + } + } + return ret; +} + +static void delete_drivers(struct jm_rdma_core *dev) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + bool delete_all; + int i; + + delete_all = core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DISABLE_ALL_ADEV; + for (i = ARRAY_SIZE(jm_adev_devices) - 1; i >= 0; i--) { + bool is_supported = false; + + if (!dev->adev[i]) + continue; + if (jm_adev_devices[i].is_supported && !delete_all) + is_supported = jm_adev_devices[i].is_supported(dev); + if (is_supported) + continue; + del_adev(&dev->adev[i]->adev); + dev->adev[i] = NULL; + } +} + + +int jm_rescan_drivers_locked(struct jm_rdma_core *dev) +{ + struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev); + + lockdep_assert_held(&jm_intf_mutex); + if (core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DETACH) + return 0; + delete_drivers(dev); + if (core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DISABLE_ALL_ADEV) + return 0; + return add_drivers(dev); +} + + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_dev.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_dev.h new file mode 100644 index 0000000..d43beb8 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rdma_dev.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only*/ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __CRETE_RDMA_DEV_H +#define __CRETE_RDMA_DEV_H +#include "rdma.h" +enum { + CORSICA_RDMA_MASK = 1 << 4, +}; + +int jm_adev_idx_alloc(void); +void jm_adev_idx_free(int idx); +int jm_adev_init(struct jm_rdma_core *dev); +bool is_ib_supported(struct jm_rdma_core *dev); +void jm_adev_cleanup(struct jm_rdma_core *dev); +int jm_attach_device(struct jm_rdma_core *dev); +void jm_detach_device(struct jm_rdma_core *dev); +int jm_rescan_drivers_locked(struct jm_rdma_core *dev); +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_regs.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_regs.h new file mode 100644 index 0000000..379d51b --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_regs.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CRETE_REGS_H +#define _CRETE_REGS_H + +#include "crete.h" +#include + + +/* Additional Transmit Descriptor Control definitions */ +#define CRETE_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */ +#define CRETE_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */ + +#define CRETE_TCTL_EN 0x00000002 +#define CRETE_RCTL_EN 0x00000002 + +#define CRETE_TCTL 0x100 +#define CRETE_RCTL 0x400 + +#define CRETE_TXDCTL(n) (0x1000 + ((n) * 0x100)) +#define CRETE_RXDCTL(n) (0x2000 + ((n) * 0x100)) + +#define CRETE_TDLEN(n) (0x1004 + ((n) * 0x100)) +#define CRETE_RDLEN(n) (0x2004 + ((n) * 0x100)) + +#define CRETE_TD_LO(n) (0x1008 + ((n) * 0x100)) +#define CRETE_TD_HI(n) (0x100c + ((n) * 0x100)) + +#define CRETE_RD_LO(n) (0x2008 + ((n) * 0x100)) +#define CRETE_RD_HI(n) (0x200c + ((n) * 0x100)) + +#define CRETE_TDH(n) (0x1010 + ((n) * 0x100)) +#define CRETE_RDH(n) (0x2010 + (n) * 0x100) + +#define CRETE_TDT(n) (0x1014 + ((n) * 0x100)) +#define CRETE_RDT(n) (0x2014 + ((n) * 0x100)) + +#define CRETE_INTR(n) (0x3000 + ((n) * 0x10)) + +/* reg bits */ +#define CRETE_HW_RESET_OK 0 +#define CRETE_HW_RESET 1 +#define CRETE_HW_RESET_TIMEOUT 10 + +/* dev status */ +#define CRETE_DEV_ACK BIT(0) +#define CRETE_DEV_DRV BIT(1) +#define CRETE_DEV_CAP BIT(2) +#define CRETE_DEV_CP BIT(3) +#define CRETE_DEV_FAIL BIT(7) +#define CRETE_DEV_OK 0 +#define POLL_RETRY_LIMIT 5 + +/* cp caps */ +#define CRETE_CP_CMDPATH BIT(0) +#define CRETE_CP_ADQ BIT(1) +#define CRETE_CP_EP BIT(2) +#define CRETE_CP_CQ_EP BIT(3) + +/*reg ops*/ +//#define wr32(p, reg, val) crete_wr32(p, reg, val) +#ifdef __compiler_offsetof +#define reg_off(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER) +#else +#define reg_off(TYPE, MEMBER) ((size_t) &(((TYPE *)0)->MEMBER)) +#endif + +#define rd32(p, reg) crete_rd32(p, reg) +#define wr32(reg, val) \ +do { \ + u8 __iomem *hw_addr = READ_ONCE(adapter->io_addr); \ + writel((val), &hw_addr[(reg)]); \ +} while (0) + +#define iseg_rd32(hw,type, mem) \ +do { \ + u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE(hw->io_addr); \ + return readl(hw_addr + reg_off(type, mem)); \ +} while (0) + +/* maybe too complex */ +#define iseg_wd32(hw, type, mem, val) \ +do { \ + u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE((hw)->io_addr); \ + writel((val), hw_addr + reg_off(type, mem)); \ +} while (0) + +#define iseg_rd8(hw,type, mem) \ +do { \ + u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE(hw->io_addr); \ + return readb(hw_addr + reg_off(type, mem)); \ +} while (0) + +#define iseg_wd8(hw, type, mem, val) \ +do { \ + u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE(hw->io_addr); \ + writeb((val), hw_addr + reg_off(type, mem)); \ +} while (0) + +#define POLL_CTRL_PATH_STATUS(hw, bit, cdev, err) \ +do { \ + int retry = POLL_RETRY_LIMIT; \ + while (!(val = readb(&(hw)->io_addr->cp_status) & (bit)) && retry) { \ + (retry)--; \ + mdelay(10); \ + crete_err((cdev)->device, "device crtl path not ready\n"); \ + } \ + if (retry == 0) { \ + (err) = -EBUSY; \ + } \ +} while (0) + +static inline void hexdump(const unsigned char *buf, unsigned short len) +{ + print_hex_dump(KERN_ERR," data: ", DUMP_PREFIX_NONE, 16, 1, buf, len, true); +} + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rep.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rep.c new file mode 100644 index 0000000..5fe5c3e --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rep.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include "crete.h" + +u16 crete_xmit_get_sfiinfo(struct sk_buff *skb) +{ + struct metadata_dst *dst = skb_metadata_dst(skb); + + if (!dst || dst->type != METADATA_HW_PORT_MUX) + return CRETE_MAX_CFA_CODE; + + return dst->u.port_info.port_id; +} + +struct net_device *crete_get_vf_rep(struct crete_core_dev *cdev, u16 cfa_code) +{ + u16 vf_idx; + u16 *cfa_code_map = cdev->eswitch->eswoffloads.cfa_code_map; + struct crete_esw_rep *rep; + + if (cfa_code && cfa_code_map) { + vf_idx = cfa_code_map[cfa_code]; + if (vf_idx != CRETE_MAX_CFA_CODE) { + rep = + xa_load(&cdev->eswitch->eswoffloads.vport_reps, + vf_idx); + if (rep) + return rep->dev; + } + } + return NULL; +} + +void crete_vf_rep_rx(struct crete_core_dev *cdev, struct sk_buff *skb) +{ + struct crete_priv *priv = netdev_priv(skb->dev); + struct crete_esw_rep *vf_rep = priv->rep; + + vf_rep->rx_stats.bytes += skb->len; + vf_rep->rx_stats.packets++; + + netif_receive_skb(skb); +} + +static const struct ethtool_ops crete_vf_rep_ethtool_ops = { + .get_drvinfo = NULL +}; + +static int crete_vf_rep_setup_tc(struct net_device *dev, + enum tc_setup_type type, void *type_data) +{ + return 0; +} + +static void +crete_vf_rep_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_esw_rep *vf_rep = priv->rep; + + stats->rx_packets = vf_rep->rx_stats.packets; + stats->rx_bytes = vf_rep->rx_stats.bytes; + stats->tx_packets = vf_rep->tx_stats.packets; + stats->tx_bytes = vf_rep->tx_stats.bytes; +} + +static int crete_vf_rep_open(struct net_device *dev) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *cdev = priv->coredev; + + /* + * with pf netdevice running + * enable the rep netdevice + */ + if (netif_running(cdev->netdev)) { + netif_carrier_on(dev); + netif_tx_start_all_queues(dev); + } + + return 0; +} + +static int crete_vf_rep_close(struct net_device *dev) +{ + netif_carrier_off(dev); + netif_tx_disable(dev); + + return 0; +} + +static netdev_tx_t crete_vf_rep_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_esw_rep *vf_rep = priv->rep; + int err, len = skb->len; + + /* + * drop the skb _skb_refdst + */ + skb_dst_drop(skb); + dst_hold((struct dst_entry *)vf_rep->dst); + /* + * redirection the skb dst with the rep dst info + */ + skb_dst_set(skb, (struct dst_entry *)vf_rep->dst); + /* skb reuse the pf netdevice */ + skb->dev = vf_rep->dst->u.port_info.lower_dev; + + err = dev_queue_xmit(skb); + if (!err) { + vf_rep->tx_stats.bytes += len; + vf_rep->tx_stats.packets++; + } + + return err; +} + +static const struct net_device_ops crete_vf_rep_netdev_ops = { + .ndo_open = crete_vf_rep_open, + .ndo_stop = crete_vf_rep_close, + .ndo_start_xmit = crete_vf_rep_xmit, + .ndo_get_stats64 = crete_vf_rep_get_stats64, + .ndo_setup_tc = crete_vf_rep_setup_tc, +}; + +int crete_alloc_vf_rep_load(struct crete_core_dev *cdev, + struct crete_esw_rep *rep) +{ + struct crete_eswitch *esw = rep->esw; + u16 *cfa_code_map = esw->eswoffloads.cfa_code_map; + struct net_device *dev; + struct net_device *pf_dev = cdev->netdev; + struct crete_priv *priv; + u16 sfi_code = 0; + int err; + + dev = alloc_etherdev(sizeof(*priv)); + if (!dev) + return -ENOMEM; + + priv = netdev_priv(dev); + priv->coredev = cdev; + priv->netdev = dev; + priv->rep = rep; + + /* alloc sfi code from FW */ + //crete_request_sfiinfo(cdev); + rep->sfi_code = sfi_code; + /* cfa code hash map */ +// cfa_code_map[rep->vport_idx] = sfi_code; + cfa_code_map[sfi_code] = rep->vport_idx; + /* + * alloc hw port mux metadata used for rep + * tx and rx function + */ + rep->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL); + if (!rep->dst) { + err = -ENOMEM; + goto err1; + } + + rep->dst->u.port_info.port_id = rep->sfi_code; + rep->dst->u.port_info.lower_dev = cdev->netdev; + + dev->netdev_ops = &crete_vf_rep_netdev_ops; + dev->ethtool_ops = &crete_vf_rep_ethtool_ops; + dev->hw_features = pf_dev->hw_features; + dev->gso_partial_features = pf_dev->gso_partial_features; + dev->vlan_features = pf_dev->vlan_features; + dev->hw_enc_features = pf_dev->hw_enc_features; + dev->features |= pf_dev->features; + /* + * rep net device use the random mac address + * vf rep random mac address + */ + eth_hw_addr_random(dev); + /* + * ********* please notice here ********** + * vf rep mtu need to ref the vf function + */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; + + err = register_netdev(dev); + if (err) + goto err2; + + rep->dev = dev; + +err2: + dst_release((struct dst_entry *)rep->dst); + rep->dst = NULL; + +err1: + free_netdev(dev); + + return err; + +} + +void crete_alloc_vf_rep_unload(struct crete_core_dev *cdev, + struct crete_esw_rep *rep) +{ + struct net_device *dev = rep->dev; + struct crete_eswitch *esw = cdev->eswitch; + u16 *cfa_code_map = esw->eswoffloads.cfa_code_map; + + if (netif_running(dev)) + crete_vf_rep_close(dev); + + cfa_code_map[rep->vport_idx] = CRETE_MAX_CFA_CODE; + + synchronize_net(); + + dst_release((struct dst_entry *)rep->dst); + rep->dst = NULL; + rep->sfi_code = CRETE_MAX_CFA_CODE; + unregister_netdev(dev); + free_netdev(dev); + + rep->dev = NULL; + +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rep.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rep.h new file mode 100644 index 0000000..fe7c403 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_rep.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __CRETE_REP +#define __CRETE_REP + +u16 crete_xmit_get_sfiinfo(struct sk_buff *skb); +struct net_device *crete_get_vf_rep(struct crete_core_dev *cdev, u16 cfa_code); +void crete_vf_rep_rx(struct crete_core_dev *cdev, struct sk_buff *skb); +int crete_alloc_vf_rep_load(struct crete_core_dev *cdev, + struct crete_esw_rep *rep); +void crete_alloc_vf_rep_unload(struct crete_core_dev *cdev, + struct crete_esw_rep *rep); + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov.c new file mode 100644 index 0000000..31e2f7f --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov.c @@ -0,0 +1,611 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include "crete.h" +#include "crete_sriov.h" +#include "crete_eswitch.h" +#include "crete_sriov_sysfs.h" + +static int crete_set_vf_attr(struct crete_core_dev *core_dev, int num_vfs) +{ + int i; + struct crete_vf_info *vf; + + for (i = 0; i < num_vfs; i++) { + vf = &core_dev->pf.vf[i]; + memset(vf, 0, sizeof(*vf)); + } + return 0; +} + +static int crete_alloc_vf_resources(struct crete_core_dev *core_dev, int num_vfs) +{ + core_dev->pf.vf = kcalloc(num_vfs, sizeof(struct crete_vf_info), GFP_KERNEL); + if (!core_dev->pf.vf) + return -ENOMEM; + + crete_set_vf_attr(core_dev, num_vfs); + + return 0; +} + +static void crete_free_vf_resources(struct crete_core_dev *core_dev) +{ + core_dev->pf.active_vfs = 0; + kfree(core_dev->pf.vf); + core_dev->pf.vf = NULL; +} + +static u16 crete_get_max_vfs(struct crete_core_dev *core_dev) +{ + return pci_sriov_get_totalvfs(core_dev->pdev); +} + +int crete_get_func_caps(struct crete_core_dev *core_dev) +{ + struct crete_pf_info *pf = &core_dev->pf; + struct crete_vf_info *vf = &core_dev->vf; + + if (crete_core_is_pf(core_dev)) { + pf->fw_fid = 0; + pf->port_id = 0; + pf->first_vf_id = 0; + pf->max_vfs = crete_get_max_vfs(core_dev); + /* pf mac */ + } else if (crete_core_is_vf(core_dev)) { + vf->fw_fid = 0; + /* vf mac */ + } + return 0; +} +EXPORT_SYMBOL(crete_get_func_caps); + +int crete_sriov_init(struct crete_core_dev *core_dev) +{ + struct pci_dev *pdev = core_dev->pdev; + int err; + + if (!crete_core_is_pf(core_dev)) + return 0; + + core_dev->pf.max_vfs = crete_get_max_vfs(core_dev); + core_dev->pf.active_vfs = pci_num_vf(pdev); + err = crete_sriov_sysfs_init(core_dev); + if (err) { + pr_err("failed to init SRIOV sysfs (%d)\n", err); + return err; + } + + return 0; +} +void crete_sriov_cleanup(struct crete_core_dev *dev) +{ + if (!crete_core_is_pf(dev)) + return; + crete_sriov_sysfs_cleanup(dev); +} + +static int crete_device_enable_sriov(struct crete_core_dev *core_dev, int num_vfs) +{ + struct crete_pf_info *pf = &core_dev->pf; + int vf_id; + int rc; + rc = crete_eswitch_enable(core_dev->eswitch, num_vfs); + if (rc) { + pr_err("failed to enable eswitch SRIOV (%d)\n", rc); + return rc; + } + rc = crete_alloc_vf_resources(core_dev, num_vfs); + if (rc) + goto err_crete_alloc_vf_resources; + + for (vf_id = 0; vf_id < num_vfs; vf_id++) { + pf->vf[vf_id].enabled = 1; + pr_info("successfully enabled VF%d\n", vf_id); + } + rc = crete_create_vfs_sysfs(core_dev, num_vfs); + if (rc) { + pr_err("failed to create SRIOV sysfs (%d)\n", rc); + goto err_crete_crete_vfs_sysfs; + } + core_dev->sriov_cfg = 1; + + return 0; +err_crete_crete_vfs_sysfs: + for (vf_id = num_vfs - 1; vf_id >= 0; vf_id--) { + if (!pf->vf[vf_id].enabled) + continue; + pf->vf[vf_id].enabled = 0; + } + crete_free_vf_resources(core_dev); +err_crete_alloc_vf_resources: + core_dev->sriov_cfg = 0; + crete_eswitch_disable_sriov(core_dev->eswitch, true); + return rc; +} + +void +crete_device_disable_sriov(struct crete_core_dev *core_dev, int num_vfs, bool clear_vf) +{ + struct crete_pf_info *pf = &core_dev->pf; + int vf_id; + + crete_destroy_vfs_sysfs(core_dev, num_vfs); + for (vf_id = num_vfs - 1; vf_id >= 0; vf_id--) { + if (!pf->vf[vf_id].enabled) + continue; + pf->vf[vf_id].enabled = 0; + pr_info("successfully disabled VF%d\n", vf_id); + } + crete_free_vf_resources(core_dev); + core_dev->sriov_cfg = 0; + crete_eswitch_disable_sriov(core_dev->eswitch, clear_vf); +} + + +static int crete_sriov_enable(struct pci_dev *pdev, int num_vfs) +{ + struct crete_core_dev *core_dev = pci_get_drvdata(pdev); + int err; + + err = crete_device_enable_sriov(core_dev, num_vfs); + if (err) { + dev_err(&pdev->dev, "crete_device_enable_sriov failed : %d\n", err); + return err; + } + + err = pci_enable_sriov(pdev, num_vfs); + if (err) { + dev_err(&pdev->dev, "pci_enable_sriov failed : %d\n", err); + crete_device_disable_sriov(core_dev, num_vfs, true); + } + return err; + +} + +void crete_sriov_disable(struct pci_dev *pdev) +{ + struct crete_core_dev *core_dev = pci_get_drvdata(pdev); + + int num_vfs = pci_num_vf(core_dev->pdev); + + pci_disable_sriov(pdev); + crete_device_disable_sriov(core_dev, num_vfs, true); + +} + +int crete_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) +{ + struct crete_core_dev *core_dev = pci_get_drvdata(pdev); + int err = 0; + + if (num_vfs) + err = crete_sriov_enable(pdev, num_vfs); + else + crete_sriov_disable(pdev); + + if (!err) + core_dev->pf.active_vfs = num_vfs; + return err ? err : num_vfs; + +} + + +static int crete_vf_ndo_prep(struct net_device *netdev, int vf_id) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + + if (!pf.active_vfs) { + dev_err(&pdev->dev, "vf ndo called though sriov is disabled\n"); + return -EINVAL; + } + if (vf_id >= pf.active_vfs) { + dev_err(&pdev->dev, "Invalid VF id %d\n", vf_id); + return -EINVAL; + } + return 0; +} + +bool crete_is_trusted_vf(struct net_device *netdev, struct crete_vf_info *vf) +{ + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + + if (crete_core_is_pf(core_dev)) + return !!(vf->flags & CRETE_VF_TRUST); + + dev_err(&pdev->dev, "VF trust %s\n", + !!(vf->func_qcfg_flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF) ? "ON":"OFF"); + + //bnxt_hwrm_func_qcfg_flags(bp, vf); + return !!(vf->func_qcfg_flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF); +} + + +int crete_get_vf_config(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi) +{ + int rc; + struct crete_vf_info *vf; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + + dev_err(&pdev->dev, "get VF:%d config", vf_id); + + rc = crete_vf_ndo_prep(netdev, vf_id); + if (rc) + return rc; + + ivi->vf = vf_id; + vf = &pf.vf[vf_id]; + + if (is_valid_ether_addr(vf->mac_addr)) + memcpy(&ivi->mac, vf->mac_addr, ETH_ALEN); + else + memcpy(&ivi->mac, vf->vf_mac_addr, ETH_ALEN); + ivi->max_tx_rate = vf->max_tx_rate; + ivi->min_tx_rate = vf->min_tx_rate; + ivi->vlan = vf->vlan; + if (vf->flags & CRETE_VF_QOS) + ivi->qos = vf->vlan >> VLAN_PRIO_SHIFT; + else + ivi->qos = 0; + ivi->spoofchk = !!(vf->flags & CRETE_VF_SPOOFCHK); + ivi->trusted = crete_is_trusted_vf(netdev, vf); + if (!(vf->flags & CRETE_VF_LINK_FORCED)) + ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; + else if (vf->flags & CRETE_VF_LINK_UP) + ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE; + else + ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE; + + return 0; + +} + +/* + *Setting the MAC Address for a VF + *To change the MAC address for the specified VF: + *# ip link set vf 0 mac
+ *For example: + *# ip link set vf 0 mac 00:01:02:03:04:05 + *This setting lasts until the PF is reloaded. + *NOTE: For untrusted VFs, assigning a MAC address for a VF from the host will + *disable any subsequent requests to change the MAC address from within the VM. + *This is a security feature. The VM is not aware of this restriction, so if this + *is attempted in the VM, it will trigger MDD events. Trusted VFs are allowed to + *change the MAC address from within the VM. + */ +int crete_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) +{ + int rc; + struct crete_vf_info *vf; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + + rc = crete_vf_ndo_prep(netdev, vf_id); + if (rc) + return rc; + + vf = &pf.vf[vf_id]; + dev_err(&pdev->dev, "Set VF MAC VF id %d mac:%2x-%2x-%2x-%2x-%2x-%2x\n", + vf_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + memcpy(vf->mac_addr, mac, ETH_ALEN); + + return crete_eswitch_set_vport_mac(core_dev->eswitch, VPORT(vf_id), vf->mac_addr); +} + +/* + * Configuring VLAN Tagging on SR-IOV Enabled Adapter Ports + *To configure VLAN tagging for the ports on an SR-IOV enabled adapter, use the + *following command. The VLAN configuration should be done before the VM is booted. + *The VF is not aware of the VLAN tag being + *inserted on transmit and removed on received frames (sometimes called "port + *VLAN" mode). + *# ip link set dev vf vlan + * For example, the following will configure PF eth0 and the first VF on VLAN 10: + *# ip link set dev eth0 vf 0 vlan 10 + *add a VLAN interface on the VF interface. For example: + *# ip link add link eth2 name eth2.100 type vlan id 100 + * Note that the order in which you set the VF to promiscuous mode and add the + *VLAN interface does not matter (you can do either first). The result in this + *example is that the VF will get all traffic that is tagged with VLAN 100. + */ +int crete_set_vf_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, __be16 vlan_proto) +{ + int rc; + struct crete_vf_info *vf; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + u16 vlan_tag; + + rc = crete_vf_ndo_prep(netdev, vf_id); + if (rc) + return rc; + + vf = &pf.vf[vf_id]; + /* TODO: needed to implement proper handling of user priority, + * currently fail the command if there is valid priority + */ + if (vlan_id > 4095 || qos) + return -EINVAL; + + vlan_tag = vlan_id; + if (vlan_tag == vf->vlan) + return 0; + dev_err(&pdev->dev, "Set VF VLAN VF id %d VLAN:%d QOS:%d vlan_proto:%d\n", + vf_id, vlan_id, qos, vlan_proto); + //TBD, add adminQ cmd + rc = crete_eswitch_set_vport_vlan(core_dev->eswitch, + VPORT(vf_id), vlan_id, qos, htons(ETH_P_8021Q)); + if (rc) { + dev_err(&pdev->dev, "Set VF VLAN VF id %d VLAN:%d QOS:%d vlan_proto:%d failed, err:%d\n", + vf_id, vlan_id, qos, vlan_proto, rc); + return rc; + } + vf->vlan = vlan_tag; + + return 0; +} + +/* + *Virtual Function (VF) Tx Rate Limit + *Use the ip command to configure the maximum or minimum Tx rate limit for a VF + *from the PF interface. + *For example, to set a maximum Tx rate limit of 8000Mbps for VF 0: + *# ip link set eth0 vf 0 max_tx_rate 8000 + *For example, to set a minimum Tx rate limit of 1000Mbps for VF 0: + *# ip link set eth0 vf 0 min_tx_rate 1000 + *1.If DCB or ADQ are enabled on a PF, you cannot set a minimum Tx rate on the + *VFs associated with that PF. + *2.If both DCB and ADQ are disabled on a PF, then you can set a minimum Tx rate + *on the VFs associated with that PF. + *3.If you set a minimum Tx rate limit on a PF for SR-IOV VFs and then apply a + *DCB or ADQ configuration, the PF cannot guarantee the minimum Tx rate limits + *for those VFs. + *If you set a minimum Tx rate on VFs across multiple ports that have an + *aggregate bandwidth over 100Gbps, the PFs cannot guarantee the minimum Tx rate + *set for the VFs. + */ +int crete_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, int max_tx_rate) +{ + int rc; + struct crete_vf_info *vf; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + u32 pf_link_speed = 400000; /* TBD get from hw */ + + rc = crete_vf_ndo_prep(netdev, vf_id); + if (rc) + return rc; + + vf = &pf.vf[vf_id]; + if (max_tx_rate > pf_link_speed) { + dev_err(&pdev->dev, "max tx rate %d exceed PF link speed for VF %d\n", + max_tx_rate, vf_id); + return -EINVAL; + } + + if (min_tx_rate > pf_link_speed) { + dev_err(&pdev->dev, "min tx rate %d is invalid for VF %d\n", + min_tx_rate, vf_id); + return -EINVAL; + } + if (min_tx_rate == vf->min_tx_rate && max_tx_rate == vf->max_tx_rate) + return 0; + + rc = crete_eswitch_set_vport_rate(core_dev->eswitch, + VPORT(vf_id), max_tx_rate, min_tx_rate); + if (rc) { + dev_err(&pdev->dev, "Set vf_bw failed %d, vf:%d max_rate min_rate:%d rc:%d\n", + vf_id, max_tx_rate, min_tx_rate, rc); + return rc; + } + vf->min_tx_rate = min_tx_rate; + vf->max_tx_rate = max_tx_rate; + dev_err(&pdev->dev, "Set VF %d vf_bw min_tx_rate:%d max_tx_rate:%d\n", vf_id, + min_tx_rate, max_tx_rate); + + return 0; +} + +int crete_set_vf_link_state(struct net_device *netdev, int vf_id, int link) +{ + int rc; + struct crete_vf_info *vf; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + + rc = crete_vf_ndo_prep(netdev, vf_id); + if (rc) + return rc; + + vf = &pf.vf[vf_id]; + + vf->flags &= ~(CRETE_VF_LINK_UP | CRETE_VF_LINK_FORCED); + switch (link) { + case IFLA_VF_LINK_STATE_AUTO: + vf->flags |= CRETE_VF_LINK_UP; + dev_err(&pdev->dev, "Set VF %d link_state Auto\n", vf_id); + break; + case IFLA_VF_LINK_STATE_DISABLE: + vf->flags |= CRETE_VF_LINK_FORCED; + dev_err(&pdev->dev, "Set VF %d link_state Disable\n", vf_id); + break; + case IFLA_VF_LINK_STATE_ENABLE: + vf->flags |= CRETE_VF_LINK_UP | CRETE_VF_LINK_FORCED; + dev_err(&pdev->dev, "Set VF %d link_state Enable\n", vf_id); + break; + default: + dev_err(&pdev->dev, "Invalid link option\n"); + rc = -EINVAL; + break; + } + + if (vf->flags & (CRETE_VF_LINK_UP | CRETE_VF_LINK_FORCED)) { + rc = crete_eswitch_set_vport_state(core_dev->eswitch, VPORT(vf_id), link); + if (rc) + dev_err(&pdev->dev, "Set link state failed %d, link:%d rc:%d\n", + vf_id, link, rc); + + } + return rc; +} +/* + *MAC and VLAN Anti-Spoofing Feature for VFs + *When a malicious driver on a Virtual Function (VF) interface attempts to send a + *spoofed packet, it is dropped by the hardware and not transmitted. + *NOTE: This feature can be disabled for a specific VF: + *# ip link set vf spoofchk {off|on} + */ +int crete_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool setting) +{ + int rc; + struct crete_vf_info *vf; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + bool old_setting = false; + + rc = crete_vf_ndo_prep(netdev, vf_id); + if (rc) + return rc; + + vf = &pf.vf[vf_id]; + + if (vf->flags & CRETE_VF_SPOOFCHK) + old_setting = true; + if (old_setting == setting) + return 0; + rc = crete_eswitch_set_vport_spoofchk(core_dev->eswitch, VPORT(vf_id), setting); + if (rc) + dev_err(&pdev->dev, "Set VF %d spoofchk %s rc:%d\n", + vf_id, setting ? "ON":"OFF", rc); + + dev_err(&pdev->dev, "Set VF %d spoofchk %s\n", vf_id, setting ? "ON":"OFF"); + + if (setting) + vf->flags |= CRETE_VF_SPOOFCHK; + else + vf->flags &= ~CRETE_VF_SPOOFCHK; + + return 0; +} + +/* + *Trusted VFs and VF Promiscuous Mode + *This feature allows you to designate a particular VF as trusted and allows that + *trusted VF to request selective promiscuous mode on the Physical Function (PF). + *To set a VF as trusted or untrusted, enter the following command in the + *Hypervisor: + *# ip link set dev vf 1 trust [on|off] + *NOTE: It's important to set the VF to trusted before setting promiscuous mode. + *If the VM is not trusted, the PF will ignore promiscuous mode requests from the + *VF. If the VM becomes trusted after the VF driver is loaded, you must make a + *new request to set the VF to promiscuous. + *Once the VF is designated as trusted, use the following commands in the VM to + *set the VF to promiscuous mode. For promiscuous all: + *# ip link set promisc on + * Where is a VF interface in the VM + *For promiscuous Multicast: + *# ip link set allmulticast on + * Where is a VF interface in the VM + */ +int crete_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted) +{ + int rc; + struct crete_vf_info *vf; + struct crete_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_pf_info pf = core_dev->pf; + + rc = crete_vf_ndo_prep(netdev, vf_id); + if (rc) + return rc; + + vf = &pf.vf[vf_id]; + + dev_err(&pdev->dev, "Set VF %d trust %s\n", vf_id, trusted ? "ON":"OFF"); + rc = crete_eswitch_set_vport_trust(core_dev->eswitch, VPORT(vf_id), trusted); + if (rc) { + dev_err(&pdev->dev, "Set VF %d trust %s rc:%d\n", vf_id, trusted ? "ON":"OFF", rc); + return rc; + } + if (trusted) + vf->flags |= CRETE_VF_TRUST; + else + vf->flags &= ~CRETE_VF_TRUST; + + return 0; +} + +int crete_approve_mac(struct crete_core_dev *core_dev, const u8 *mac) +{ + int rc = 0; + struct pci_dev *pdev = core_dev->pdev; + + if (crete_core_is_pf(core_dev)) + return 0; + + if (is_valid_ether_addr(core_dev->vf.mac_addr)) + rc = -EADDRNOTAVAIL; + /* admin Q to PF approve VF MAC */ + + dev_err(&pdev->dev, "VF MAC address %pM approved by the PF\n", mac); + + return 0; +} + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov.h new file mode 100644 index 0000000..6b58faf --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __CRETE_SRIOV_H +#define __CRETE_SRIOV_H + +struct crete_vf_context { + int enabled; + u64 port_guid; + u64 node_guid; + /* Valid bits are used to validate administrative guid only. + * Enabled after ndo_set_vf_guid + */ + u8 port_guid_valid:1; + u8 node_guid_valid:1; +}; + +#define CRETE_VF_QOS 0x1 +#define CRETE_VF_SPOOFCHK 0x2 +#define CRETE_VF_LINK_FORCED 0x4 +#define CRETE_VF_LINK_UP 0x8 +#define CRETE_VF_TRUST 0x10 + +/*stub micro define */ +#define FUNC_QCFG_RESP_FLAGS_TRUSTED_VF 0x40UL + + + +struct crete_vf_info { + u16 fw_fid; + u8 mac_addr[ETH_ALEN]; /* PF assigned MAC Address */ + u8 vf_mac_addr[ETH_ALEN]; /* VF assigned MAC address, only stored by PF. */ + u16 vlan; + u16 func_qcfg_flags; + u32 flags; + u32 min_tx_rate; + u32 max_tx_rate; + u32 enabled; + void *hwrm_cmd_req_addr; + dma_addr_t hwrm_cmd_req_dma_addr; +}; +int crete_get_func_caps(struct crete_core_dev *core_dev); +int crete_sriov_init(struct crete_core_dev *core_dev); +void crete_sriov_cleanup(struct crete_core_dev *dev); +int crete_pci_sriov_configure(struct pci_dev *dev, int num_vfs); +int crete_get_vf_config(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi); +int crete_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac); +int crete_set_vf_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, __be16 vlan_proto); +int crete_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, int max_tx_rate); +int crete_set_vf_link_state(struct net_device *netdev, int vf_id, int link); +int crete_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool setting); +int crete_set_vf_trust(struct net_device *netdev, int vf_id, bool trust); +int crete_approve_mac(struct crete_core_dev *core_dev, const u8 *mac); +bool crete_is_trusted_vf(struct net_device *netdev, struct crete_vf_info *vf); +void crete_device_disable_sriov(struct crete_core_dev *core_dev, int num_vfs, bool clear_vf); + +#endif /* __CRETE_SRIOV_H */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov_sysfs.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov_sysfs.c new file mode 100644 index 0000000..8050579 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov_sysfs.c @@ -0,0 +1,1180 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + + +#include +#include +#include + +#include "crete.h" +#include "crete_sriov.h" +#include "crete_eswitch.h" +#include "crete_sriov_sysfs.h" + + +struct vf_attributes { + struct attribute attr; + ssize_t (*show)(struct crete_sriov_vf_sysfs *vf_sysfs, struct vf_attributes *vf_attr, + char *buf); + ssize_t (*store)(struct crete_sriov_vf_sysfs *vf_sysfs, struct vf_attributes *vf_attr, + const char *buf, size_t count); +}; + +static ssize_t vf_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct vf_attributes *ga = + container_of(attr, struct vf_attributes, attr); + struct crete_sriov_vf_sysfs *g = container_of(kobj, struct crete_sriov_vf_sysfs, kobj); + + if (!ga->show) + return -EIO; + + return ga->show(g, ga, buf); +} + +static ssize_t vf_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t size) +{ + struct vf_attributes *ga = + container_of(attr, struct vf_attributes, attr); + struct crete_sriov_vf_sysfs *g = container_of(kobj, struct crete_sriov_vf_sysfs, kobj); + + if (!ga->store) + return -EIO; + + return ga->store(g, ga, buf, size); +} + +static ssize_t vf_paging_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct vf_attributes *ga = + container_of(attr, struct vf_attributes, attr); + struct crete_sriov_vf_sysfs *g = container_of(kobj, struct crete_sriov_vf_sysfs, page_kobj); + + if (!ga->show) + return -EIO; + + return ga->show(g, ga, buf); +} + +static ssize_t vf_paging_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t size) +{ + struct vf_attributes *ga = + container_of(attr, struct vf_attributes, attr); + struct crete_sriov_vf_sysfs *g = container_of(kobj, struct crete_sriov_vf_sysfs, page_kobj); + + if (!ga->store) + return -EIO; + + return ga->store(g, ga, buf, size); +} + +struct vf_group_attributes { + struct attribute attr; + ssize_t (*show)(struct crete_esw_rate_group *esw_rate_group, + struct vf_group_attributes *vf_group_attr, char *buf); + ssize_t (*store)(struct crete_esw_rate_group *esw_rate_group, + struct vf_group_attributes *vf_group_attr, const char *buf, size_t count); +}; + +static ssize_t vf_group_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct vf_group_attributes *ga = + container_of(attr, struct vf_group_attributes, attr); + struct crete_esw_rate_group *g = container_of(kobj, struct crete_esw_rate_group, kobj); + + if (!ga->show) + return -EIO; + + return ga->show(g, ga, buf); +} + +static ssize_t vf_group_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t size) +{ + struct vf_group_attributes *ga = + container_of(attr, struct vf_group_attributes, attr); + struct crete_esw_rate_group *g = container_of(kobj, struct crete_esw_rate_group, kobj); + + if (!ga->store) + return -EIO; + + return ga->store(g, ga, buf, size); +} + +static ssize_t max_tx_rate_group_show(struct crete_esw_rate_group *g, + struct vf_group_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to set VF group max rate\n"); +} + +static ssize_t max_tx_rate_group_store(struct crete_esw_rate_group *g, + struct vf_group_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + u32 max_rate; + int err; + + err = kstrtou32(buf, 10, &max_rate); + if (err) + return -EINVAL; + + err = crete_esw_qos_set_sysfs_group_max_rate(esw, g, max_rate); + dev_warn(&dev->pdev->dev, "%s stub func\r\n", __func__); + return err ? err : count; +} + + +static ssize_t min_tx_rate_group_show(struct crete_esw_rate_group *g, + struct vf_group_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to set VF group min rate\n"); +} + +static ssize_t min_tx_rate_group_store(struct crete_esw_rate_group *g, + struct vf_group_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + u32 min_rate; + int err; + + err = kstrtou32(buf, 10, &min_rate); + if (err) + return -EINVAL; + + dev_warn(&dev->pdev->dev, "%s stub func\r\n", __func__); + err = crete_esw_qos_set_sysfs_group_min_rate(esw, g, min_rate); + + return err ? err : count; +} + + +static const char *policy_str(enum port_state_policy policy) +{ + switch (policy) { + case CRETE_POLICY_DOWN: return "Down\n"; + case CRETE_POLICY_UP: return "Up\n"; + case CRETE_POLICY_FOLLOW: return "Follow\n"; + default: return "Invalid policy\n"; + } +} + + +static ssize_t policy_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + struct crete_core_dev *dev = g->dev; + const char *p = NULL; + enum port_state_policy policy = CRETE_POLICY_FOLLOW; + int err; + + dev_warn(&dev->pdev->dev, "%s query_vport_context stub func\r\n", __func__); + p = policy_str(policy); + strcpy(buf, p); + + return p ? strlen(p) : err; +} + +static int strpolicy(const char *buf, enum port_state_policy *policy) +{ + if (sysfs_streq(buf, "Down")) { + *policy = CRETE_POLICY_DOWN; + return 0; + } + + if (sysfs_streq(buf, "Up")) { + *policy = CRETE_POLICY_UP; + return 0; + } + + if (sysfs_streq(buf, "Follow")) { + *policy = CRETE_POLICY_FOLLOW; + return 0; + } + return -EINVAL; +} + +static ssize_t policy_store(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + enum port_state_policy policy; + int err; + + err = strpolicy(buf, &policy); + if (err) + return err; + dev_warn(&dev->pdev->dev, "%s set_vport_context stub func\r\n", __func__); + return count; +} + +/* ETH SRIOV SYSFS */ +static ssize_t mac_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to set VF Mac Address\n"); +} + +static ssize_t mac_store(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + u8 mac[ETH_ALEN]; + int err; + + err = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); + if (err == 6) + goto set_mac; + + if (sysfs_streq(buf, "Random")) + eth_random_addr(mac); + else + return -EINVAL; + +set_mac: + err = crete_eswitch_set_vport_mac(dev->eswitch, g->vf + 1, mac); + return err ? err : count; +} + +static ssize_t vlan_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, "usage: write to set VF Vlan, %s", + " Qos, and optionally Vlan Protocol (default 802.1Q)\n"); +} + +static ssize_t vlan_store(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + char vproto_ext[5] = {'\0'}; + __be16 vlan_proto; + u16 vlan_id; + u8 qos; + int err; + + err = sscanf(buf, "%hu:%hhu:802.%4s", &vlan_id, &qos, vproto_ext); + if (err == 3) { + if ((strcmp(vproto_ext, "1AD") == 0) || + (strcmp(vproto_ext, "1ad") == 0)) + vlan_proto = htons(ETH_P_8021AD); + else if ((strcmp(vproto_ext, "1Q") == 0) || + (strcmp(vproto_ext, "1q") == 0)) + vlan_proto = htons(ETH_P_8021Q); + else + return -EINVAL; + } else { + err = sscanf(buf, "%hu:%hhu", &vlan_id, &qos); + if (err != 2) + return -EINVAL; + vlan_proto = htons(ETH_P_8021Q); + } + + err = crete_eswitch_set_vport_vlan(dev->eswitch, g->vf + 1, + vlan_id, qos, vlan_proto); + return err ? err : count; +} + +static const char *vlan_proto_str(u16 vlan, u8 qos, __be16 vlan_proto) +{ + if (!vlan && !qos) + return "N/A"; + + switch (vlan_proto) { + case htons(ETH_P_8021AD): return "802.1ad"; + case htons(ETH_P_8021Q): return "802.1Q"; + default: return "Invalid vlan protocol"; + } +} + +static ssize_t spoofcheck_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to enable|disable VF SpoofCheck\n" + ); +} + +static ssize_t spoofcheck_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, + size_t count) +{ + struct crete_core_dev *dev = g->dev; + bool settings; + int err; + + if (sysfs_streq(buf, "ON")) + settings = true; + else if (sysfs_streq(buf, "OFF")) + settings = false; + else + return -EINVAL; + + err = crete_eswitch_set_vport_spoofchk(dev->eswitch, g->vf + 1, settings); + return err ? err : count; +} + +static ssize_t trust_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to trust|untrust VF\n" + ); +} + +static ssize_t trust_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, + size_t count) +{ + struct crete_core_dev *dev = g->dev; + bool settings; + int err; + + if (sysfs_streq(buf, "ON")) + settings = true; + else if (sysfs_streq(buf, "OFF")) + settings = false; + else + return -EINVAL; + + err = crete_eswitch_set_vport_trust(dev->eswitch, g->vf + 1, settings); + return err ? err : count; +} + +static ssize_t link_state_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, "usage: write to set VF State\n"); +} + +static ssize_t link_state_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, + size_t count) +{ + struct crete_core_dev *dev = g->dev; + enum port_state_policy policy; + int err; + + err = strpolicy(buf, &policy); + if (err) + return err; + + err = crete_eswitch_set_vport_state(dev->eswitch, g->vf + 1, policy); + return err ? err : count; +} + +static ssize_t max_tx_rate_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to set VF max rate\n"); +} + +static ssize_t max_tx_rate_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + struct crete_vport *evport = crete_eswitch_get_vport(esw, g->vf + 1); + u32 max_tx_rate; + u32 min_tx_rate; + int err; + + mutex_lock(&esw->state_lock); + min_tx_rate = evport->qos.min_rate; + mutex_unlock(&esw->state_lock); + + err = kstrtou32(buf, 10, &max_tx_rate); + if (err) + return -EINVAL; + + err = crete_eswitch_set_vport_rate(dev->eswitch, g->vf + 1, + max_tx_rate, min_tx_rate); + return err ? err : count; +} + +static ssize_t group_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to set VF vport group\n", + CRETE_ESW_QOS_SYSFS_GROUP_MAX_ID); +} + +static ssize_t group_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + u32 group_id; + int err; + + err = kstrtou32(buf, 10, &group_id); + if (err) + return -EINVAL; + + if (group_id > CRETE_ESW_QOS_SYSFS_GROUP_MAX_ID) + return -EINVAL; + + err = crete_esw_qos_vport_update_sysfs_group(esw, g->vf + 1, group_id); + + return err ? err : count; +} + +static ssize_t min_tx_rate_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + char *buf) +{ + return sprintf(buf, + "usage: write to set VF min rate\n"); +} + +static ssize_t min_tx_rate_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, size_t count) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + struct crete_vport *evport = crete_eswitch_get_vport(esw, g->vf + 1); + u32 min_tx_rate; + u32 max_tx_rate; + int err; + + mutex_lock(&esw->state_lock); + max_tx_rate = evport->qos.max_rate; + mutex_unlock(&esw->state_lock); + + err = kstrtou32(buf, 10, &min_tx_rate); + if (err) + return -EINVAL; + + err = crete_eswitch_set_vport_rate(dev->eswitch, g->vf + 1, + max_tx_rate, min_tx_rate); + return err ? err : count; +} +#define _sprintf(p, buf, format, arg...) \ + ((PAGE_SIZE - (int)(p - buf)) <= 0 ? 0 : \ + scnprintf(p, PAGE_SIZE - (int)(p - buf), format, ## arg)) + +static ssize_t trunk_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + char *buf) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + struct crete_vport *evport = crete_eswitch_get_vport(esw, g->vf + 1); + u16 vlan_id = 0; + char *ret = buf; + + mutex_lock(&esw->state_lock); + if (!!bitmap_weight(evport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID)) { + ret += _sprintf(ret, buf, "Allowed 802.1Q VLANs:"); + for_each_set_bit(vlan_id, evport->info.vlan_trunk_8021q_bitmap, + VLAN_N_VID) + ret += _sprintf(ret, buf, " %d", vlan_id); + ret += _sprintf(ret, buf, "\n"); + } + mutex_unlock(&esw->state_lock); + + return (ssize_t)(ret - buf); +} + +static ssize_t trunk_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, + size_t count) +{ + struct crete_core_dev *dev = g->dev; + u16 start_vid, end_vid; + char op[5]; + int err; + + err = sscanf(buf, "%4s %hu %hu", op, &start_vid, &end_vid); + if (err != 3) + return -EINVAL; + + if (!strcmp(op, "add")) + err = crete_eswitch_add_vport_trunk_range(dev->eswitch, + g->vf + 1, + start_vid, end_vid); + else if (!strcmp(op, "rem")) + err = crete_eswitch_del_vport_trunk_range(dev->eswitch, + g->vf + 1, + start_vid, end_vid); + else + return -EINVAL; + + return err ? err : count; +} + +static ssize_t config_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + struct crete_vport *evport = crete_eswitch_get_vport(esw, g->vf + 1); + struct crete_vport_info *ivi; + char *p = buf; + + if (!esw && crete_core_is_pf(esw->dev)) + return -EPERM; + + if (IS_ERR(evport)) + return PTR_ERR(evport); + + mutex_lock(&esw->state_lock); + ivi = &evport->info; + p += _sprintf(p, buf, "VF : %d\n", g->vf); + p += _sprintf(p, buf, "MAC : %pM\n", ivi->mac); + p += _sprintf(p, buf, "VLAN : %d\n", ivi->vlan); + p += _sprintf(p, buf, "QoS : %d\n", ivi->qos); + p += _sprintf(p, buf, "VLAN Proto : %s\n", + vlan_proto_str(ivi->vlan, ivi->qos, ivi->vlan_proto)); + p += _sprintf(p, buf, "SpoofCheck : %s\n", ivi->spoofchk ? "ON" : "OFF"); + p += _sprintf(p, buf, "Trust : %s\n", ivi->trusted ? "ON" : "OFF"); + p += _sprintf(p, buf, "LinkState : %s", policy_str(ivi->link_state)); + + if (evport->qos.enabled) { + p += _sprintf(p, buf, "MinTxRate : %d\n", evport->qos.min_rate); + p += _sprintf(p, buf, "MaxTxRate : %d\n", evport->qos.max_rate); + if (evport->qos.group) + p += _sprintf(p, buf, "RateGroup : %d\n", + evport->qos.group->group_id); + else + p += _sprintf(p, buf, "RateGroup : 0\n"); + } else { + p += _sprintf(p, buf, "MinTxRate : 0\nMaxTxRate : 0\nRateGroup : 0\n"); + } + + p += _sprintf(p, buf, "VGT+ : %s\n", + !!bitmap_weight(ivi->vlan_trunk_8021q_bitmap, + VLAN_N_VID) ? "ON" : "OFF"); + p += _sprintf(p, buf, "RateGroup : %d\n", ivi->group); + mutex_unlock(&esw->state_lock); + + return (ssize_t)(p - buf); +} + +static ssize_t config_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, size_t count) +{ + return -EOPNOTSUPP; +} + +static ssize_t config_group_show(struct crete_esw_rate_group *g, + struct vf_group_attributes *oa, + char *buf) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + char *p = buf; + + if (!esw && crete_core_is_pf(esw->dev)) + return -EPERM; + + mutex_lock(&esw->state_lock); + p += _sprintf(p, buf, "Num VFs : %d\n", g->num_vports); + p += _sprintf(p, buf, "MaxRate : %d\n", g->max_rate); + p += _sprintf(p, buf, "MinRate : %d\n", g->min_rate); + p += _sprintf(p, buf, "BWShare(Indirect cfg) : %d\n", g->bw_share); + mutex_unlock(&esw->state_lock); + + return (ssize_t)(p - buf); +} + +static ssize_t config_group_store(struct crete_esw_rate_group *g, + struct vf_group_attributes *oa, + const char *buf, size_t count) +{ + return -EOPNOTSUPP; +} + +int +crete_eswitch_get_vf_meter_data(struct crete_eswitch *esw, int vport_num, + int data_type, int rx_tx, int xps, u64 *data) +{ + int err = 0; + struct crete_core_dev *dev = esw->dev; + + switch (data_type) { + case CRETE_RATE_LIMIT_DATA_RATE: + *data = 0; + break; + case CRETE_RATE_LIMIT_DATA_BURST: + *data = 0; + break; + case CRETE_RATE_LIMIT_DATA_PACKETS_DROPPED: + *data = 0; + break; + case CRETE_RATE_LIMIT_DATA_BYTES_DROPPED: + *data = 0; + break; + default: + err = -EINVAL; + } + dev_warn(&dev->pdev->dev, "%s stub. data_type:%d\n", __func__, data_type); + + return err; +} +int +crete_eswitch_set_vf_meter_data(struct crete_eswitch *esw, int vport_num, + int data_type, int rx_tx, int xps, u64 data) +{ + struct crete_core_dev *dev = esw->dev; + + dev_warn(&dev->pdev->dev, "%s stub data_type:%d\n", __func__, data_type); + return 0; + +} + +static ssize_t vf_meter_common_show(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, char *buf, + int data_type) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + u64 data; + int err; + + err = crete_eswitch_get_vf_meter_data(esw, g->vf + 1, data_type, + g->meter_type.rx_tx, + g->meter_type.xps, &data); + if (err) + return err; + + return sprintf(buf, "%lld\n", data); +} + +static ssize_t vf_meter_common_store(struct crete_sriov_vf_sysfs *g, + struct vf_attributes *oa, + const char *buf, size_t count, + int data_type) +{ + struct crete_core_dev *dev = g->dev; + struct crete_eswitch *esw = dev->eswitch; + s64 data; + int err; + + err = kstrtos64(buf, 10, &data); + if (err) + return err; + + if (data < 0) + return -EINVAL; + + err = crete_eswitch_set_vf_meter_data(esw, g->vf + 1, data_type, + g->meter_type.rx_tx, + g->meter_type.xps, data); + + return err ? err : count; +} + +static ssize_t rate_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + return vf_meter_common_show(g, oa, buf, CRETE_RATE_LIMIT_DATA_RATE); +} + +static ssize_t rate_store(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + const char *buf, size_t count) +{ + return vf_meter_common_store(g, oa, buf, count, CRETE_RATE_LIMIT_DATA_RATE); +} + +static ssize_t burst_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + return vf_meter_common_show(g, oa, buf, CRETE_RATE_LIMIT_DATA_BURST); +} + +static ssize_t burst_store(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + const char *buf, size_t count) +{ + return vf_meter_common_store(g, oa, buf, count, CRETE_RATE_LIMIT_DATA_BURST); +} + +static ssize_t bytes_dropped_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + return vf_meter_common_show(g, oa, buf, CRETE_RATE_LIMIT_DATA_BYTES_DROPPED); +} + +static ssize_t bytes_dropped_store(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + const char *buf, size_t count) +{ + return -EOPNOTSUPP; +} + +static ssize_t packets_dropped_show(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + char *buf) +{ + return vf_meter_common_show(g, oa, buf, CRETE_RATE_LIMIT_DATA_PACKETS_DROPPED); +} + +static ssize_t packets_dropped_store(struct crete_sriov_vf_sysfs *g, struct vf_attributes *oa, + const char *buf, size_t count) +{ + return -EOPNOTSUPP; +} + + +static ssize_t crete_num_vfs_store(struct device *device, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct pci_dev *pdev = container_of(device, struct pci_dev, dev); + int req_vfs; + int err; + + if (kstrtoint(buf, 0, &req_vfs) || req_vfs < 0 || + req_vfs > pci_sriov_get_totalvfs(pdev)) + return -EINVAL; + + err = crete_pci_sriov_configure(pdev, req_vfs); + if (err < 0) + return err; + + return count; +} + +static ssize_t crete_num_vfs_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev = container_of(device, struct pci_dev, dev); + struct crete_core_dev *dev = pci_get_drvdata(pdev); + struct crete_pf_info *pf = &dev->pf; + + + return sprintf(buf, "%d\n", pf->active_vfs); +} + +static DEVICE_ATTR_RW(crete_num_vfs); + +static const struct sysfs_ops vf_sysfs_ops = { + .show = vf_attr_show, + .store = vf_attr_store, +}; + +static const struct sysfs_ops vf_paging_ops = { + .show = vf_paging_attr_show, + .store = vf_paging_attr_store, +}; + +static const struct sysfs_ops vf_group_sysfs_ops = { + .show = vf_group_attr_show, + .store = vf_group_attr_store, +}; + +#define VF_RATE_GROUP_ATTR(_name) struct vf_group_attributes vf_group_attr_##_name = \ + __ATTR(_name, 0644, _name##_group_show, _name##_group_store) +#define VF_ATTR(_name) struct vf_attributes vf_attr_##_name = \ + __ATTR(_name, 0644, _name##_show, _name##_store) + +VF_ATTR(policy); +VF_ATTR(mac); +VF_ATTR(vlan); +VF_ATTR(link_state); +VF_ATTR(spoofcheck); +VF_ATTR(trust); +VF_ATTR(max_tx_rate); +VF_ATTR(min_tx_rate); +VF_ATTR(config); +VF_ATTR(trunk); +VF_ATTR(group); +VF_RATE_GROUP_ATTR(min_tx_rate); +VF_RATE_GROUP_ATTR(max_tx_rate); +VF_RATE_GROUP_ATTR(config); + +static struct attribute *vf_eth_attrs[] = { + &vf_attr_mac.attr, + &vf_attr_vlan.attr, + &vf_attr_link_state.attr, + &vf_attr_spoofcheck.attr, + &vf_attr_trust.attr, + &vf_attr_max_tx_rate.attr, + &vf_attr_min_tx_rate.attr, + &vf_attr_config.attr, + &vf_attr_trunk.attr, + &vf_attr_group.attr, + NULL +}; + +static struct attribute *vf_group_attrs[] = { + &vf_group_attr_max_tx_rate.attr, + &vf_group_attr_min_tx_rate.attr, + &vf_group_attr_config.attr, + NULL +}; + + +ATTRIBUTE_GROUPS(vf_group); + +static struct kobj_type vf_group = { + .sysfs_ops = &vf_group_sysfs_ops, + .default_groups = vf_group_groups +}; + +ATTRIBUTE_GROUPS(vf_eth); + +static struct kobj_type vf_type_eth = { + .sysfs_ops = &vf_sysfs_ops, + .default_groups = vf_eth_groups +}; + +VF_ATTR(rate); +VF_ATTR(burst); +VF_ATTR(bytes_dropped); +VF_ATTR(packets_dropped); + +static struct attribute *vf_meters_eth_attrs[] = { + &vf_attr_rate.attr, + &vf_attr_burst.attr, + &vf_attr_bytes_dropped.attr, + &vf_attr_packets_dropped.attr, + NULL +}; + + +ATTRIBUTE_GROUPS(vf_meters_eth); + +static struct kobj_type vf_meters_type_eth = { + .sysfs_ops = &vf_sysfs_ops, + .default_groups = vf_meters_eth_groups +}; + +static struct device_attribute *crete_class_attributes[] = { + &dev_attr_crete_num_vfs, +}; + +int crete_sriov_sysfs_init(struct crete_core_dev *dev) +{ + struct crete_pf_info *pf = &dev->pf; + struct device *device = &dev->pdev->dev; + int err; + int i; + + pf->config = kobject_create_and_add("sriov", &device->kobj); + if (!pf->config) + return -ENOMEM; + + + pf->groups_config = kobject_create_and_add("groups", + pf->config); + if (!pf->groups_config) { + err = -ENOMEM; + goto err_groups; + } + + for (i = 0; i < ARRAY_SIZE(crete_class_attributes); i++) { + err = device_create_file(device, crete_class_attributes[i]); + if (err) + goto err_attr; + } + + return 0; + +err_attr: + if (pf->groups_config) { + kobject_put(pf->groups_config); + pf->groups_config = NULL; + } + +err_groups: + kobject_put(pf->config); + pf->config = NULL; + return err; +} + +void crete_sriov_sysfs_cleanup(struct crete_core_dev *dev) +{ + struct crete_pf_info *pf = &dev->pf; + struct device *device = &dev->pdev->dev; + int i; + + for (i = 0; i < ARRAY_SIZE(crete_class_attributes); i++) + device_remove_file(device, crete_class_attributes[i]); + + kobject_put(pf->groups_config); + kobject_put(pf->config); + pf->config = NULL; +} + +int crete_create_vf_group_sysfs(struct crete_core_dev *dev, + u32 group_id, struct kobject *group_kobj) +{ + struct crete_pf_info *pf = &dev->pf; + int err; + + err = kobject_init_and_add(group_kobj, &vf_group, pf->groups_config, + "%d", group_id); + if (err) + return err; + + kobject_uevent(group_kobj, KOBJ_ADD); + return 0; +} + +void crete_destroy_vf_group_sysfs(struct crete_core_dev *dev, + struct kobject *group_kobj) +{ + kobject_put(group_kobj); +} + + +static void crete_destroy_vfs_sysfs_meters(struct crete_core_dev *dev, int num_vfs) +{ + struct crete_pf_info *pf = &dev->pf; + struct crete_sriov_vf_meters *meters; + struct crete_sriov_vf_sysfs *vf; + int i, j; + + for (i = 0; i < num_vfs; i++) { + vf = &pf->vf_sysfs[i]; + + meters = vf->meters; + if (!meters) + break; + + for (j = 0; j < 4; j++) + kobject_put(&meters->meters[j].kobj); + + kobject_put(meters->rx_kobj); + kobject_put(meters->tx_kobj); + kobject_put(meters->kobj); + + kfree(meters); + } +} + +static int crete_init_vfs_sysfs_init_meter(struct crete_sriov_vf_sysfs *vf, + struct crete_sriov_vf_meters *meters, + struct crete_sriov_vf_sysfs *meter, + int rx_tx, int xps) +{ + struct kobject *parent; + int err; + + if (rx_tx == CRETE_RATE_LIMIT_TX) + parent = meters->tx_kobj; + else + parent = meters->rx_kobj; + + err = kobject_init_and_add(&meter->kobj, &vf_meters_type_eth, parent, + (xps == CRETE_RATE_LIMIT_PPS) ? "pps" : "bps"); + if (err) + return err; + + meter->dev = vf->dev; + meter->vf = vf->vf; + meter->meter_type.rx_tx = rx_tx; + meter->meter_type.xps = xps; + + return 0; +} + +static int crete_create_vfs_sysfs_meters(struct crete_core_dev *dev, int num_vfs) +{ + struct crete_pf_info *pf = &dev->pf; + struct crete_sriov_vf_meters *meters; + struct crete_sriov_vf_sysfs *vf; + int err, i; + + for (i = 0; i < num_vfs; i++) { + vf = &pf->vf_sysfs[i]; + + meters = kzalloc(sizeof(*meters), GFP_KERNEL); + if (!meters) { + err = -ENOMEM; + goto err_vf_meters; + } + + meters->kobj = kobject_create_and_add("meters", &vf->kobj); + if (!meters->kobj) { + err = -EINVAL; + goto err_vf_meters; + } + + meters->rx_kobj = kobject_create_and_add("rx", meters->kobj); + if (!meters->rx_kobj) { + err = -EINVAL; + goto err_vf_meters; + } + + meters->tx_kobj = kobject_create_and_add("tx", meters->kobj); + if (!meters->tx_kobj) { + err = -EINVAL; + goto err_vf_meters; + } + + err = crete_init_vfs_sysfs_init_meter(vf, meters, + &meters->meters[0], + CRETE_RATE_LIMIT_RX, + CRETE_RATE_LIMIT_BPS); + if (err) + goto err_vf_meters; + + err = crete_init_vfs_sysfs_init_meter(vf, meters, + &meters->meters[1], + CRETE_RATE_LIMIT_RX, + CRETE_RATE_LIMIT_PPS); + if (err) + goto err_put_meter_0; + + err = crete_init_vfs_sysfs_init_meter(vf, meters, + &meters->meters[2], + CRETE_RATE_LIMIT_TX, + CRETE_RATE_LIMIT_BPS); + if (err) + goto err_put_meter_1; + + err = crete_init_vfs_sysfs_init_meter(vf, meters, + &meters->meters[3], + CRETE_RATE_LIMIT_TX, + CRETE_RATE_LIMIT_PPS); + if (err) + goto err_put_meter_2; + + vf->meters = meters; + } + + return 0; + +err_put_meter_2: + kobject_put(&meters->meters[2].kobj); +err_put_meter_1: + kobject_put(&meters->meters[1].kobj); +err_put_meter_0: + kobject_put(&meters->meters[0].kobj); +err_vf_meters: + kobject_put(meters->rx_kobj); + kobject_put(meters->tx_kobj); + kobject_put(meters->kobj); + + kfree(meters); + + crete_destroy_vfs_sysfs_meters(dev, num_vfs); + + return err; +} + + +int crete_create_vfs_sysfs(struct crete_core_dev *dev, int num_vfs) +{ + struct crete_pf_info *pf = &dev->pf; + struct crete_sriov_vf_sysfs *tmp; + int err; + int vf; + + pf->vf_sysfs = kcalloc(num_vfs, sizeof(*pf->vf_sysfs), GFP_KERNEL); + if (!pf->vf_sysfs) + return -ENOMEM; + + for (vf = 0; vf < num_vfs; vf++) { + tmp = &pf->vf_sysfs[vf]; + tmp->dev = dev; + tmp->vf = vf; + err = kobject_init_and_add(&tmp->kobj, &vf_type_eth, pf->config, + "%d", vf); + if (err) + goto err_vf; + + kobject_uevent(&tmp->kobj, KOBJ_ADD); + } + + err = crete_create_vfs_sysfs_meters(dev, num_vfs); + if (err) { + --vf; + goto err_vf; + } + + return 0; + +err_vf: + for (; vf >= 0; vf--) { + tmp = &pf->vf_sysfs[vf]; + kobject_put(&tmp->kobj); + } + + kfree(pf->vf_sysfs); + pf->vf_sysfs = NULL; + return err; +} + +void crete_destroy_vfs_sysfs(struct crete_core_dev *dev, int num_vfs) +{ + struct crete_pf_info *pf = &dev->pf; + struct crete_sriov_vf_sysfs *tmp; + int vf; + + if (!num_vfs || !pf || !pf->vf_sysfs) + return; + + crete_destroy_vfs_sysfs_meters(dev, num_vfs); + + for (vf = 0; vf < num_vfs; vf++) { + tmp = &pf->vf_sysfs[vf]; + kobject_put(&tmp->kobj); + } + + kfree(pf->vf_sysfs); + pf->vf_sysfs = NULL; +} + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov_sysfs.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov_sysfs.h new file mode 100644 index 0000000..74d0103 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_sriov_sysfs.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __CRETE_SRIOV_SYSFS_H +#define __CRETE_SRIOV_SYSFS_H + +enum { + CRETE_RATE_LIMIT_RX, + CRETE_RATE_LIMIT_TX, +}; + +enum crete_flow_meter_mode { + CRETE_RATE_LIMIT_BPS, + CRETE_RATE_LIMIT_PPS, +}; + +enum { + CRETE_RATE_LIMIT_DATA_RATE, + CRETE_RATE_LIMIT_DATA_BURST, + CRETE_RATE_LIMIT_DATA_PACKETS_DROPPED, + CRETE_RATE_LIMIT_DATA_BYTES_DROPPED, +}; + +#define CRETE_ESW_QOS_SYSFS_GROUP_MAX_ID 255 +#define CRETE_ESW_QOS_NON_SYSFS_GROUP (CRETE_ESW_QOS_SYSFS_GROUP_MAX_ID + 1) + +struct crete_sriov_vf_meter_type { + int rx_tx; + int xps; +}; + + +struct crete_sriov_vf_sysfs { + struct crete_core_dev *dev; + struct kobject kobj; + struct kobject page_kobj; + int vf; + union { + struct crete_sriov_vf_meters *meters; + struct crete_sriov_vf_meter_type meter_type; + }; +}; + +struct crete_sriov_vf_meters { + struct kobject *kobj; + struct kobject *rx_kobj; + struct kobject *tx_kobj; + struct crete_sriov_vf_sysfs meters[4]; +}; + +struct mlxdevm_rate_group { + struct list_head list; + char *name; + u64 tx_max; + u64 tx_share; +}; + + +struct crete_esw_rate_group { + struct crete_core_dev *dev; + struct mlxdevm_rate_group devm; + u32 tsar_ix; + u32 max_rate; + u32 min_rate; + u32 bw_share; + struct list_head list; + + /* sysfs group related fields */ + struct kobject kobj; + u32 group_id; + u32 num_vports; +}; + + +enum port_state_policy { + CRETE_POLICY_DOWN = 0, + CRETE_POLICY_UP = 1, + CRETE_POLICY_FOLLOW = 2, + CRETE_POLICY_INVALID = 0xffffffff +}; + +int crete_create_vfs_sysfs(struct crete_core_dev *dev, int num_vfs); +void crete_destroy_vfs_sysfs(struct crete_core_dev *dev, int num_vfs); + +int crete_create_vf_group_sysfs(struct crete_core_dev *dev, + u32 group_id, struct kobject *group_kobj); +void crete_destroy_vf_group_sysfs(struct crete_core_dev *dev, + struct kobject *group_kobj); + +int crete_sriov_sysfs_init(struct crete_core_dev *dev); +void crete_sriov_sysfs_cleanup(struct crete_core_dev *dev); + + +#endif /* __CRETE_SRIOV_SYSFS_H */ + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_stub.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_stub.c new file mode 100644 index 0000000..2c31d94 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_stub.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "crete.h" +#include "crete_stub.h" + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_stub.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_stub.h new file mode 100644 index 0000000..cb94fdf --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_stub.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __CRETE_STUB_H +#define __CRETE_STUB_H +#include +#include "crete.h" +/*tmp micro*/ +#define PCI_VENDOR_ID_CRETE 0x1f53 +#define PF_DEVICE_ID 0x1B20 +#define VF_DEVICE_ID 0x1B21 +#define PF_DEVICE_ID_SIM 0x9527 +#define VF_DEVICE_ID_SIM 0x9523 +#define PF_DEVICE_ID_NIC 0x3B20 +#define VF_DEVICE_ID_NIC 0x3B21 +#define PF_DEVICE_ID_CMCC 0x2C20 +#define VF_DEVICE_ID_CMCC 0x2C22 +#define PF_DEVICE_ID_FAKE 0x1C00 + +#endif /* __CRETE_STUB_H */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_txrx.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_txrx.c new file mode 100644 index 0000000..afa6a99 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_txrx.c @@ -0,0 +1,1859 @@ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include "crete.h" +#include "crete_rep.h" +#include "crete_txrx.h" +#include "crete_cmd_if.h" + +static unsigned int crete_netdev_features[] = { +// CRETE_NET_F_SOP_PADDING, CRETE_NET_F_EOP_PADDING, + CRETE_NET_F_AUTO_INTR_SUP, + CRETE_NET_F_INTR_MOD, CRETE_NET_F_TX_INORDER, + CRETE_NET_F_CQE_AGG, CRETE_NET_F_RX_MERGE +}; + +static unsigned int crete_offload_features[] = { + CRETE_NET_F_RX_VLAN_FILTER, CRETE_NET_F_RX_VLAN_STRIP, + CRETE_NET_F_RX_IPV4_CSUM, CRETE_NET_F_RX_UDP_CSUM, + CRETE_NET_F_RX_TCP_CSUM, CRETE_NET_F_RX_SCTP_CSUM, + CRETE_NET_F_RX_TCP_LRO, CRETE_NET_F_RX_RSS_HASH, + CRETE_NET_F_RX_TIMESTAMP, CRETE_NET_F_RX_METADATA, + CRETE_NET_F_TX_IPV4_CSUM, CRETE_NET_F_TX_TCP_CSUM, + CRETE_NET_F_TX_UDP_CSUM, CRETE_NET_F_TX_SCTP_CSUM, + CRETE_NET_F_TX_OUTER_IPV4_CSUM, CRETE_NET_F_TX_OUTER_UDP_CSUM, + CRETE_NET_F_TX_TCP_TSO, CRETE_NET_F_TX_IP_TNL_TSO, + CRETE_NET_F_TX_UDP_TNL_TSO, CRETE_NET_F_TX_VLAN_INSERT, + CRETE_NET_F_TX_QINQ_INSERT, CRETE_NET_F_TX_SEND_ON_TIMESTAMP, + CRETE_NET_F_TX_METADATA, CRETE_NET_F_VPORT_RX_FLOW_TABLE, + CRETE_NET_F_FDB_TABLE, CRETE_NET_F_FLOW_REDIR_TABLE, + CRETE_NET_F_L2_SWITCH_TABLE, CRETE_NET_F_VSWITCH_OFFLOAD +}; + +struct crete_core_dev *g_cdev; + +static void crete_db_write(struct device *dev, u16 prod, + u16 vqn, enum CRETE_DB_TYPE type, + struct crete_db *db) +{ + union crete_db_info dbval; + + crete_info(dev, + "crete write doorbell type %d prod %d vqn %d db 0x%lx\n", + type, prod, vqn, (unsigned long)db); + + dbval.db_info.type = type; + dbval.db_info.vqn = vqn; + dbval.db_info.index = prod; + + barrier(); + writel_relaxed(dbval.val, db->db_addr); + +} + +static void crete_set_rxring_params(struct crete_core_dev *cdev) +{ + u32 rx_size, rx_space; + + /* + * PAGE MODE + */ + if (cdev->netdev->mtu > 1500) { + /* + * rx space config page size + * rx size config to page size + */ + cdev->flags |= CRETE_PAGE_MODE; + rx_space = PAGE_SIZE; + rx_size = rx_space - ALIGN(max(NET_SKB_PAD, XDP_PACKET_HEADROOM), 8) - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + } else { + /* + * clean crete page mode flag + */ + cdev->flags &= ~CRETE_PAGE_MODE; + rx_size = SKB_DATA_ALIGN(cdev->netdev->mtu + ETH_HLEN + NET_IP_ALIGN + 8); + rx_space = rx_size + ALIGN(max(NET_SKB_PAD, XDP_PACKET_HEADROOM), 8) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + } + + cdev->rx_buf_use_size = rx_size; + cdev->rx_buf_size = rx_space; + cdev->rx_offset = CRETE_RX_OFFSET; + cdev->rx_dma_offset = CRETE_RX_DMA_OFFSET; + +} + +static int crete_free_rxbuf(struct crete_core_dev *cdev) +{ + int i, j; + struct pci_dev *pdev; + struct crete_rx_buf *rxbuf; + struct crete_rxring_info *rxring; + struct crete_rxcp_ring_info *rxcpring; + pdev = cdev->pdev; + + crete_info(&pdev->dev, "free rxring buffer\n"); + + for (i = 0; i < cdev->ring_size; i++) { + rxring = &cdev->rxring[i]; + rxcpring = rxring->cpring; + + rxring->rx_dbprod = 0; + rxring->rx_cons = 0; + rxring->rx_prod = 0; + memset(rxcpring->rxcq_base, 0, rxcpring->bd_len); + rxcpring->cp_cons = 0; + rxcpring->cp_prod = 0; + rxcpring->wrap_counter = 0; + + for (j = 0; j < rxring->rx_ring_size; j++) { + rxbuf = &rxring->rx_buf[j]; + if (refcount_read(&rxbuf->kref)) { + refcount_set(&rxbuf->kref, 0); + dma_unmap_single_attrs(&pdev->dev, + dma_unmap_addr(rxbuf, + mapping), + cdev->rx_buf_use_size, + DMA_FROM_DEVICE, + DMA_ATTR_WEAK_ORDERING); + if (cdev->flags & CRETE_PAGE_MODE) + __free_pages(rxbuf->page, 0); + else + skb_free_frag(rxbuf->data); + } + } + } + + return 0; +} + +static int crete_free_txbuf(struct crete_core_dev *cdev) +{ + int i, j; + struct pci_dev *pdev; + struct crete_tx_buf *txbuf; + struct crete_txring_info *txring; + struct crete_txcp_ring_info *txcpring; + u16 queuesize = cdev->cap.qpcap.max_queue_size; + struct sk_buff *skb; + + pdev = cdev->pdev; + crete_info(&pdev->dev, "free txring buffer\n"); + + for (i = 0; i < cdev->ring_size; i++) { + + txring = &cdev->txring[i]; + txring->tx_cons = 0; + txring->tx_dbprod = 0; + txring->tx_prod = 0; + atomic_set(&txring->ring_avail, queuesize); + txring->kick_pending = 0; + + txcpring = txring->cpring; + memset(txcpring->txcq_base, 0, txcpring->bd_len); + txcpring->cp_cons = 0; + txcpring->cp_prod = 0; + txcpring->wrap_counter = 0; + atomic_set(&txcpring->ring_avail, queuesize); + + for (j = 0; j < txring->tx_ring_size; j++) { + txbuf = &txring->tx_buf[j]; + if (refcount_read(&txbuf->kref)) { + skb = txbuf->skb; + refcount_set(&txbuf->kref, 0); + dma_unmap_single(&pdev->dev, + dma_unmap_addr(txbuf, mapping), + skb_headlen(skb), + DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + } + } + } + + return 0; +} + +static struct page *crete_alloc_rxring_page_data(struct crete_core_dev *cdev, + dma_addr_t *mapping, + gfp_t gfp) +{ + struct page *page; + struct pci_dev *pdev = cdev->pdev; + + page = alloc_page(gfp); + if (!page) + return NULL; + + *mapping = + dma_map_page_attrs(&pdev->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE, + DMA_ATTR_WEAK_ORDERING); + + if (dma_mapping_error(&pdev->dev, *mapping)) { + free_page((unsigned long)page); + page = NULL; + return NULL; + } + *mapping += cdev->rx_dma_offset; + + return page; +} + +static u8 *crete_alloc_rx_frag(struct crete_core_dev *cdev, + dma_addr_t *mapping, gfp_t gfp) +{ + u8 *data; + struct pci_dev *pdev = cdev->pdev; + + data = netdev_alloc_frag(cdev->rx_buf_size); + if (!data) + return NULL; + + *mapping = dma_map_single_attrs(&pdev->dev, data + cdev->rx_dma_offset, + cdev->rx_buf_use_size, DMA_FROM_DEVICE, + DMA_ATTR_WEAK_ORDERING); + + if (dma_mapping_error(&pdev->dev, *mapping)) { + skb_free_frag(data); + data = NULL; + return NULL; + } + + return data; +} + +int crete_alloc_rxring_data(struct crete_core_dev *cdev, u16 ringid, u16 prod, + gfp_t gfp) +{ + struct crete_rx_bd *rx_bd; + struct crete_rx_buf *rx_buf; + struct crete_rxring_info *rxr; + dma_addr_t mapping; + struct page *page; + u8 *data; + + rxr = &cdev->rxring[ringid]; + rx_bd = &rxr->rx_bd[prod]; + rx_buf = &rxr->rx_buf[prod]; + + /* + * Within the PAGEMODE + * alloc page memory + */ + if (cdev->flags & CRETE_PAGE_MODE) { + page = crete_alloc_rxring_page_data(cdev, &mapping, gfp); + if (!page) + return -ENOMEM; + + rx_buf->data = page_to_virt(page); + rx_buf->data_ptr = rx_buf->data + cdev->rx_offset; + rx_buf->mapping = mapping; + rx_buf->page = page; + + } else { /* frag mode */ + data = crete_alloc_rx_frag(cdev, &mapping, gfp); + if (!data) + return -ENOMEM; + + rx_buf->data = data; + rx_buf->data_ptr = data + cdev->rx_offset; + rx_buf->mapping = mapping; + + } + + refcount_set(&rx_buf->kref, 1); + CRETE_WRITE_64BITADDR(rx_bd, cpu_to_le64(mapping)); + rx_bd->buf_len = cpu_to_le16(cdev->rx_buf_use_size); + rx_bd->buf_id = prod; + + return 0; +} + +static int crete_init_rxring(struct crete_core_dev *cdev, int ringid) +{ + struct crete_rxring_info *rxr; + int i, ret; + u32 prod; + + rxr = &cdev->rxring[ringid]; + rxr->cpring = &cdev->rxcpring[ringid]; + + prod = READ_ONCE(rxr->rx_prod); + + for (i = 0; i < NAPI_POLL_WEIGHT; i++) { + ret = crete_alloc_rxring_data(cdev, ringid, prod, GFP_KERNEL); + if (ret) + return -EBUSY; + prod = CRETE_NEXTID(prod, 1, rxr->rx_ring_mask); + WRITE_ONCE(rxr->rx_prod, prod); + /* update production db index , the index not warp */ + rxr->rx_dbprod += 1; + prod = READ_ONCE(rxr->rx_prod); + } + + crete_info(&cdev->pdev->dev, "current rxring prod:%d\n", rxr->rx_prod); + return 0; +} + +static int crete_init_txring(struct crete_core_dev *cdev, int ringid) +{ + struct crete_txring_info *txr; + + txr = &cdev->txring[ringid]; + + txr->cpring = &cdev->txcpring[ringid]; + + return 0; +} + +static int crete_init_dev(struct crete_core_dev *cdev) +{ + int ret; + int i; + + for (i = 0; i < cdev->ring_size; i++) { + ret = crete_init_rxring(cdev, i); + if (ret) + return ret; + } + + for (i = 0; i < cdev->ring_size; i++) { + ret = crete_init_txring(cdev, i); + if (ret) + return ret; + } + return 0; +} + +static int crete_set_real_num_queues(struct crete_core_dev *cdev) +{ + int rc, qnum; + struct net_device *dev = cdev->netdev; + + qnum = cdev->ring_size; + rc = netif_set_real_num_tx_queues(dev, qnum); + if (rc) + return rc; + + rc = netif_set_real_num_rx_queues(dev, qnum); + if (rc) + return rc; + + return rc; +} + +int crete_poll_tx(struct napi_struct *napi, int budget); +int crete_poll_rx(struct napi_struct *napi, int budget); + +static void crete_add_napi(struct crete_core_dev *cdev) +{ + int i; + struct crete_napi *jnapi; + struct crete_napi *rx_jnapi; + struct crete_napi *tx_jnapi; + + jnapi = cdev->jnapi; + crete_info(&cdev->pdev->dev, "crete init napi\n"); + + for (i = 0; i < cdev->ring_size; i++) { + rx_jnapi = &jnapi[i * 2]; // rx ring is even number + tx_jnapi = &jnapi[i * 2 + 1]; // tx ring is odd number + +#ifdef NETIF_NAPI_ADD_NEWAPI + netif_napi_add(cdev->netdev, &rx_jnapi->napi, crete_poll_rx); +#else + netif_napi_add(cdev->netdev, &rx_jnapi->napi, crete_poll_rx, + 64); +#endif + +#ifdef NETIF_NAPI_ADD_NEWAPI + netif_napi_add(cdev->netdev, &tx_jnapi->napi, crete_poll_tx); +#else + netif_napi_add(cdev->netdev, &tx_jnapi->napi, crete_poll_tx, + 64); +#endif + } + +} + +static void crete_del_napi(struct crete_core_dev *cdev) +{ + int i; + struct crete_napi *jnapi; + + crete_info(&cdev->pdev->dev, "crete delete napi function\n"); + + for (i = 0; i < cdev->ring_size; i++) { + jnapi = &cdev->jnapi[2 * i]; + //__netif_napi_del(&jnapi->napi); + netif_napi_del(&jnapi->napi); + + jnapi = &cdev->jnapi[2 * i + 1]; + //__netif_napi_del(&jnapi->napi); + netif_napi_del(&jnapi->napi); + } + + synchronize_net(); +} + +static void crete_enable_napi(struct crete_core_dev *cdev) +{ + int i; + struct crete_napi *jnapi; + + crete_info(&cdev->pdev->dev, "crete enable napi function\n"); + + for (i = 0; i < cdev->ring_size; i++) { + jnapi = &cdev->jnapi[2 * i]; + napi_enable(&jnapi->napi); + jnapi = &cdev->jnapi[2 * i + 1]; + napi_enable(&jnapi->napi); + } + +} + +static void crete_disable_napi(struct crete_core_dev *cdev) +{ + int i; + struct crete_napi *jnapi; + + crete_info(&cdev->pdev->dev, "crete disable napi function\n"); + + for (i = 0; i < cdev->ring_size; i++) { + jnapi = &cdev->jnapi[2 * i]; + napi_disable(&jnapi->napi); + jnapi = &cdev->jnapi[2 * i + 1]; + napi_disable(&jnapi->napi); + } +} + +void crete_tx_disable(struct crete_core_dev *cdev) +{ + netif_carrier_off(cdev->netdev); + netif_tx_disable(cdev->netdev); +} + +void crete_tx_enable(struct crete_core_dev *cdev) +{ + netif_tx_wake_all_queues(cdev->netdev); + netif_carrier_on(cdev->netdev); +} + +int crete_poll_tx_clean(struct device *dev, + struct crete_txring_info *txr, u16 prod) +{ + struct crete_tx_buf *txbuf; + struct sk_buff *skb; + u16 txr_cons, bd_size, bd_nums, count = 0; + bool finack = false; + int i; + u64 tx_pkts = 0, tx_bytes = 0; + + txr_cons = READ_ONCE(txr->tx_cons); + txbuf = &txr->tx_buf[txr_cons]; + crete_info(dev, "clean tx get the tx cons:%u, prod:%u\n", txr_cons, + prod); + // so the txring and txcpring should be keep sequence; + pr_debug("clean tx get the ref val:%d\n", refcount_read(&txbuf->kref)); + /* + * first buffer can not be zero + * xmit first buffer need + */ + if (!refcount_read(&txbuf->kref)) { + crete_warn(dev, "the txr cons: %u, prod: %u\n", txr_cons, prod); + return 0; + } + + skb = txbuf->skb; + bd_size = txbuf->nr_bdnum; + bd_nums = txbuf->nr_bdnum; + pr_debug("get tx string %s\n", skb->data - NET_IP_ALIGN); + + dma_unmap_single(dev, dma_unmap_addr(txbuf, mapping), + skb_headlen(skb), DMA_TO_DEVICE); + refcount_set(&txbuf->kref, 0); + txbuf->skb = NULL; + txbuf->mapping = 0; + /*update txr cons id*/ + txr_cons = CRETE_NEXTID(txr_cons, bd_size, txr->tx_ring_mask); + count++; + tx_pkts = 1; + tx_bytes = skb->len; + /* clean up the fragments page */ + for (i = 0; (i < txbuf->nr_frags) && (finack == false); i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + txbuf = &txr->tx_buf[txr_cons]; + if (refcount_read(&txbuf->kref) == 0) { + crete_warn(dev, "xmit tx buffer refcounter zero\n"); + goto out; + } + dma_unmap_page(dev, + dma_unmap_addr(txbuf, mapping), + skb_frag_size(frag), DMA_TO_DEVICE); + txbuf->mapping = 0; + txbuf->skb = NULL; + bd_size = txbuf->nr_bdnum; + bd_nums += bd_size; + refcount_set(&txbuf->kref, 0); + finack = txr_cons == prod ? true : false; + /* update next cons id*/ + txr_cons = CRETE_NEXTID(txr_cons, bd_size, txr->tx_ring_mask); + count++; + } + +out: + dev_kfree_skb_any(skb); + /* consume one member,so need to push the tx_cons */ + /* upadte txring cons index */ + WRITE_ONCE(txr->tx_cons, txr_cons); + /* increase the txr ring avail size */ + atomic_add(bd_nums, &txr->ring_avail); + + u64_stats_update_begin(&txr->txq_stats->syncp); + txr->txq_stats->bytes += tx_bytes; + txr->txq_stats->packets += tx_pkts; + u64_stats_update_end(&txr->txq_stats->syncp); + + return 0; +} + +int crete_poll_tx(struct napi_struct *napi, int budget) +{ + struct crete_napi *jnapi; + struct crete_txring_info *txr; + struct crete_txcp_ring_info *txcpr; + struct crete_core_dev *cdev; + struct tx_cq_bd *txcqbd; + struct tx_cq_bd *txcqbd_1; + struct pci_dev *pdev; + int txpackets = 0; + int work_done; + int budget_1; + u16 cons; + int prod = -1; + int lastcons = -1; + + if (budget <= 0) + return 0; + + budget_1 = budget; + jnapi = container_of(napi, struct crete_napi, napi); + if (!jnapi) + return 0; + + cdev = jnapi->cdev; + pdev = cdev->pdev; + txr = jnapi->txring; + txcpr = jnapi->txcpring; + txcqbd = (struct tx_cq_bd *)jnapi->txcpring->txcq_base; + cons = READ_ONCE(txcpr->cp_cons); + txcqbd_1 = &txcqbd[cons]; + prefetch(txcqbd_1); + do { + pr_debug("current cons value:%u\n", cons); + pr_debug("tx cq bd wrap counter:%u, txcpr wrap counter:%u\n", + txcqbd_1->wrap_counter, txcpr->wrap_counter); + if (!CRETE_DESC_VALID(txcqbd_1, txcpr)) { + crete_err(&pdev->dev, "*******tx desc invalid******\n"); + break; + } + txpackets++; + prod = CRETE_DESC_BUFID(txcqbd_1); + crete_poll_tx_clean(&pdev->dev, txr, prod); + lastcons = cons; + cons = CRETE_NEXTID(cons, 1, txcpr->ring_mask); + /* wrap counter need to wrap when ring warpped */ + if (cons < lastcons || cons == 0) + txcpr->wrap_counter = 1 ^ txcpr->wrap_counter; + + txcqbd_1 = &txcqbd[cons]; + prefetch(txcqbd_1); + budget_1--; + + /* please notice this later will delete it + * break; just use for test + */ + } while (budget_1); + + txcpr->cp_cons = cons; + /* txr->tx_cons = (prod + 1) & txr->tx_ring_mask; */ + + /* increase the txr ring avail size */ + /* atomic_add(txpackets, &txr->ring_avail); */ + /* increase the txcpr ring avail size */ + atomic_add(txpackets, &txcpr->ring_avail); + work_done = budget - budget_1; + + smp_mb(); + /* if cons all budget then will need to return imedi */ + if (work_done >= budget) + goto out; + + /* trigger the tx doorbell to enable the int + * prod = READ_ONCE(txr->tx_prod); + */ + if (napi_complete_done(napi, work_done)) { + crete_info(&pdev->dev, "jmnd doorbell enable interrupt\n"); + /* crete_db_write(&pdev->dev, txr->tx_dbprod, txr->id, DB_TXCQ_ARM, cdev->db); */ + } + +out: + return work_done; +} + +static void crete_deliver_skb(struct crete_core_dev *cdev, + struct crete_napi *jnapi, struct sk_buff *skb) +{ + if (skb->dev != cdev->netdev) { + /* this packet belongs to a vf-rep */ + crete_vf_rep_rx(cdev, skb); + return; + } + napi_gro_receive(&jnapi->napi, skb); +} + +static void crete_reuse_rx_data(struct crete_rxring_info *rxr, u16 cons, + void *data) +{ + u16 prod; + struct crete_rx_buf *cons_rx_buf, *prod_rx_buf; + struct crete_rx_bd *cons_bd, *prod_bd; + + prod = READ_ONCE(rxr->rx_prod); + prod_rx_buf = &rxr->rx_buf[prod]; + cons_rx_buf = &rxr->rx_buf[cons]; + refcount_set(&cons_rx_buf->kref, 0); + refcount_set(&prod_rx_buf->kref, 1); + + if (data == NULL) + prod_rx_buf->data = cons_rx_buf->data; + else + prod_rx_buf->data = data; + + prod_rx_buf->data_ptr = cons_rx_buf->data_ptr; + prod_rx_buf->mapping = cons_rx_buf->mapping; + prod_rx_buf->page = cons_rx_buf->page; + + prod_bd = &rxr->rx_bd[prod]; + cons_bd = &rxr->rx_bd[cons]; + + prod_bd->addr_lo = cons_bd->addr_lo; + prod_bd->addr_hi = cons_bd->addr_hi; + prod_bd->buf_id = prod; + prod_bd->buf_len = cons_bd->buf_len; + rxr->rx_prod = CRETE_NEXTID(rxr->rx_prod, 1, rxr->rx_ring_mask); + rxr->rx_dbprod += 1; +} + +static int crete_rx_aggs_pages(struct crete_core_dev *cdev, + struct sk_buff *skb, struct crete_rxring_info *rxr, + struct crete_rxcp_ring_info *rxcpr, + u16 rx_cons, u16 cons, u16 len) +{ + int buflen, skblen, off, sumlen, length; + u8 *data_ptr, *data; + int i, k = 1; + dma_addr_t mapping; + struct page *page; + struct crete_rx_buf *rxbuf; + struct device *dev = &cdev->pdev->dev; + struct skb_shared_info *shinfo = skb_shinfo(skb); + + sumlen = len; + skblen = skb->len; + length = (rxr->rx_ring_size + cons - rx_cons + 1) & rxr->rx_ring_mask; + + for (i = rx_cons; length-- && skblen < sumlen; ) { + skb_frag_t *frag = &shinfo->frags[k++]; + /* + * The buffer length need to get the min with extra skb len + * and the rx buffer use size. + */ + buflen = min((u16)cdev->rx_buf_use_size, (u16)(sumlen - skblen)); + crete_info(dev, "crete rx aggs pages cons id %d frag id %d, buflen %d\n", + i, k-1, buflen); + rxbuf = &rxr->rx_buf[i]; + if (refcount_read(&rxbuf->kref) == 0) { + crete_info(dev, "rx buff refcounter zero error ret\n"); + return -ENOMEM; + } + + mapping = rxbuf->mapping; + /* mapping address need to be header address */ + mapping -= cdev->rx_dma_offset; + data_ptr = rxbuf->data_ptr; + data = rxbuf->data; + page = rxbuf->page; + /* + * about the receive multibd packages + * I think second bd not consider the IP ALIGN anymore. + */ + off = cdev->rx_dma_offset; + + /* realloc the rxring data , */ + if (crete_alloc_rxring_data(cdev, rxr->id, i, GFP_ATOMIC)) { + crete_reuse_rx_data(rxr, i, data); + return -ENOMEM; + } + + /* no matter alloc ring data failed or not ,need to reuse it */ + crete_reuse_rx_data(rxr, i, NULL); + dma_unmap_page_attrs(dev, mapping, PAGE_SIZE, DMA_FROM_DEVICE, + DMA_ATTR_WEAK_ORDERING); + + skb_frag_off_set(frag, off); + skb_frag_size_set(frag, buflen); + __skb_frag_set_page(frag, page); + shinfo->nr_frags += 1; + + /* + * Update the skb length + */ + skb->data_len += buflen; + skb->len += buflen; + skb->truesize += PAGE_SIZE; + + WRITE_ONCE(rxr->rx_cons, CRETE_NEXTID(rxr->rx_cons, 1, rxr->rx_ring_mask)); + i = READ_ONCE(rxr->rx_cons); + sumlen -= buflen; + } + + return 0; +} + + +static struct sk_buff *crete_rx_page_pkt(struct crete_napi *jnapi, + struct crete_rxring_info *rxr, + struct crete_rxcp_ring_info *rxcpr, + u16 cons, u16 len) +{ + u16 payload, rx_cons, buflen; + struct crete_core_dev *cdev = jnapi->cdev; + struct device *dev = &cdev->pdev->dev; + struct sk_buff *skb; + skb_frag_t *frag; + dma_addr_t mapping; + struct crete_rx_buf *rxbuf; + u8 *data_ptr, *data; + int off, ret, length; + struct page *page; + bool multibd = false; + + rx_cons = READ_ONCE(rxr->rx_cons); + length = (rxr->rx_ring_size + cons - rx_cons + 1) & rxr->rx_ring_mask; + /* + * If rxring rxcons exceed the rxcq cons , there is something wrong + * need to check with it + */ + if (length <= 0) + return NULL; + /* + * If hardware cons exceed the rx ring cons id, + * it means we enter into multi bd rx receive process. + * We need to check the rx buf use size anyway. + */ + buflen = len; + if (length > 1 && len > cdev->rx_buf_use_size) { + /* + * buf len used for first fragments + */ + buflen = cdev->rx_buf_use_size; + multibd = true; + } + crete_info(dev, "rx page mode buffer len %u\n", buflen); + rxbuf = &rxr->rx_buf[rx_cons]; + + if (refcount_read(&rxbuf->kref) == 0) { + crete_info(dev, "rx buff refcounter zero error ret\n"); + return NULL; + } + + mapping = rxbuf->mapping; + /* mapping address need to be header address */ + mapping -= cdev->rx_dma_offset; + data_ptr = rxbuf->data_ptr; + data = rxbuf->data; + page = rxbuf->page; + /* realloc the rxring data , */ + if (crete_alloc_rxring_data(cdev, rxr->id, rx_cons, GFP_ATOMIC)) { + crete_reuse_rx_data(rxr, rx_cons, data); + return NULL; + } + /* no matter alloc ring data failed or not ,need to reuse it */ + crete_reuse_rx_data(rxr, rx_cons, data); + dma_unmap_page_attrs(dev, mapping, PAGE_SIZE, DMA_FROM_DEVICE, + DMA_ATTR_WEAK_ORDERING); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, data_ptr - NET_IP_ALIGN, + len, true); + + /* linear get the head length */ + payload = eth_get_headlen(cdev->netdev, data_ptr, len); + + skb = napi_alloc_skb(&jnapi->napi, payload); + if (!skb) + return NULL; + + /* need to store the data offset with the page address */ + off = (void *)data_ptr - page_address(page); + /* page add to the first skfrag[0] */ + skb_add_rx_frag(skb, 0, page, off, buflen, PAGE_SIZE); + /* copy the linear data */ + memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN, + payload + NET_IP_ALIGN); + + frag = &skb_shinfo(skb)->frags[0]; + /* + * fragments need to sub the payload + * fragments offset need to be set to payload + */ + skb_frag_size_sub(frag, payload); + skb_frag_off_add(frag, payload); + /* non linear data len need to sub payload len */ + skb->data_len -= payload; + /* put the data */ + skb->tail += payload; + + WRITE_ONCE(rxr->rx_cons, CRETE_NEXTID(rxr->rx_cons, 1, rxr->rx_ring_mask)); + + /* + * when finish the normal buffer, + * if rx_cons exceed the rxbuffer cons, need to add these buffer + */ + if (multibd) + ret = crete_rx_aggs_pages(cdev, skb, rxr, + rxcpr, READ_ONCE(rxr->rx_cons), cons, len); + + if (ret) + return NULL; + + return skb; + +} + +static int crete_rx_normal_nonlinear(struct crete_core_dev *cdev, + struct sk_buff *skb, struct crete_rxring_info *rxr, + struct crete_rxcp_ring_info *rxcpr, + u16 rx_cons, u16 cons, u16 len) +{ + int buflen, skblen, off, sumlen, length; + u8 *data_ptr, *data; + int i, k = 0; + dma_addr_t mapping; + struct page *page; + struct crete_rx_buf *rxbuf; + struct device *dev = &cdev->pdev->dev; + struct skb_shared_info *shinfo = skb_shinfo(skb); + + length = (rxr->rx_ring_size + cons - rx_cons + 1) & rxr->rx_ring_mask; + sumlen = len; + skblen = skb->len; + for (i = rx_cons; length-- && skblen < sumlen; ) { + skb_frag_t *frag = &shinfo->frags[k++]; + /* + * The buffer length need to get the min with extra skb len + * and the rx buffer use size + */ + buflen = min((u16)(cdev->rx_buf_use_size), (u16)(sumlen - skblen)); + crete_info(dev, "crete rx aggs pages frag id %d, buflen %d\n", k-1, buflen); + rxbuf = &rxr->rx_buf[i]; + if (refcount_read(&rxbuf->kref) == 0) { + crete_info(dev, "rx buff refcounter zero error ret\n"); + return -ENOMEM; + } + + data_ptr = rxbuf->data_ptr; + data = rxbuf->data; + mapping = rxbuf->mapping; + rxbuf->data = NULL; + /* + * about the receive multibd packages + * I think second bd not consider the IP ALIGN anymore. + */ + off = cdev->rx_dma_offset; + + /* + * nonlinear data will forward to uplayer. + * so here need to realloc the ring data. + */ + if (crete_alloc_rxring_data(cdev, rxr->id, i, GFP_ATOMIC)) { + crete_reuse_rx_data(rxr, i, data); + return -ENOMEM; + } + + /* no matter alloc ring data failed or not ,need to reuse it */ + crete_reuse_rx_data(rxr, i, NULL); + + dma_sync_single_for_cpu(dev, mapping, cdev->rx_buf_use_size, + DMA_FROM_DEVICE); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, + data_ptr - NET_IP_ALIGN, buflen, true); + /* + * Get the data page info + */ + page = virt_to_page(data); + /* + * data dec page address plus cdev->rx_dma_offset + * We can get the actual data relate to the page offset + */ + off = (void *)data - (void *)page_address(page) + cdev->rx_dma_offset; + skb_frag_off_set(frag, off); + skb_frag_size_set(frag, buflen); + __skb_frag_set_page(frag, page); + shinfo->nr_frags += 1; + + /* + * Update the skb length + */ + skb->data_len += buflen; + skb->len += buflen; + skb->truesize += cdev->rx_buf_size; + /* + * update the rxring cons id + */ + WRITE_ONCE(rxr->rx_cons, CRETE_NEXTID(rxr->rx_cons, 1, rxr->rx_ring_mask)); + i = READ_ONCE(rxr->rx_cons); + sumlen -= buflen; + + } + + return 0; + +} + +static struct sk_buff *crete_rx_linear_pkt(struct crete_napi *jnapi, + struct crete_rxring_info *rxr, + struct crete_rxcp_ring_info *rxcpr, + u16 cons, u16 len) +{ + u8 *data_ptr; + void *data; + u16 rx_cons, buflen; + dma_addr_t mapping; + struct crete_core_dev *cdev; + struct pci_dev *pdev; + struct crete_rx_buf *rxbuf; + struct sk_buff *skb; + bool multibd = false; + int ret = 0, length; + + cdev = jnapi->cdev; + pdev = cdev->pdev; + rx_cons = READ_ONCE(rxr->rx_cons); + buflen = len; + length = (rxr->rx_ring_size + cons - rx_cons + 1) & rxr->rx_ring_mask; + /* + * If rxring rxcons exceed the rxcq cons , there is something wrong + * need to check with it + */ + if (length <= 0) + return NULL; + /* + * If hardware cons exceed the rx ring cons id, + * it means we enter into multi bd rx receive process. + * We need to check the rx buf use size anyway. + */ + if (length > 1 && len > cdev->rx_buf_use_size) { + /* + * buf len used for first fragments + */ + buflen = cdev->rx_buf_use_size; + multibd = true; + } + + rxbuf = &rxr->rx_buf[rx_cons]; + if (refcount_read(&rxbuf->kref) == 0) { + crete_info(&pdev->dev, "rx buff refcounter zero error ret\n"); + return NULL; + } + + data_ptr = rxbuf->data_ptr; + data = rxbuf->data; + mapping = rxbuf->mapping; + rxbuf->data = NULL; + skb = napi_alloc_skb(&jnapi->napi, buflen); + if (!skb) + return NULL; + + dma_sync_single_for_cpu(&pdev->dev, mapping, cdev->rx_buf_use_size, + DMA_FROM_DEVICE); + + /* copy the linear data */ + memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN, + buflen + NET_IP_ALIGN); + + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, + data_ptr - NET_IP_ALIGN, buflen, true); + skb_put(skb, buflen); + + /* linear data buffer reused */ + crete_reuse_rx_data(rxr, rx_cons, data); + + WRITE_ONCE(rxr->rx_cons, CRETE_NEXTID(rx_cons, 1, rxr->rx_ring_mask)); + /* + * when finish the normal buffer, + * if rx_cons exceed the rxbuffer cons, need to add these buffer + */ + if (multibd) + ret = crete_rx_normal_nonlinear(cdev, skb, rxr, + rxcpr, READ_ONCE(rxr->rx_cons), cons, len); + + if (ret) + return NULL; + + return skb; + +} + +static int crete_handle_rxchksum(struct net_device *netdev, + struct sk_buff *skb, + void *rxcqbd) +{ + struct crete_rxcq_32bd_low *rxcq_32low = + (struct crete_rxcq_32bd_low *)rxcqbd; + + if (unlikely(!(netdev->features & NETIF_F_RXCSUM))) + return 0; + /* + * current crete just support unnecessary partial + * check rxcq l3 cksum and l4 cksum value + */ + if ((rxcq_32low->l3_cksum_ok == 1) && + (rxcq_32low->l4_cksum_ok == 1)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + /* about the tunnel mode */ + if (rxcq_32low->tunnel_mode != 0 && + rxcq_32low->tunnel_mode != TUNNEL_ERR) { + skb->csum_level = 1; + skb->encapsulation = 1; + } + } + + return 0; +} + +static int crete_rx_post_handle(struct crete_core_dev *cdev, + struct sk_buff *skb, + void *rxcqbd) +{ + crete_handle_rxchksum(cdev->netdev, skb, rxcqbd); + + return 0; +} + +static struct sk_buff *crete_rx_receive(struct crete_napi *jnapi, + struct crete_rxring_info *rxr, + struct crete_rxcp_ring_info *rxcpr, u16 cons, + u16 len, u16 sfiinfo) +{ + struct sk_buff *skb; + struct net_device *dev = crete_get_vf_rep(jnapi->cdev, sfiinfo); + + if (!dev) + dev = jnapi->cdev->netdev; + /* exceed the 1500 size need to use the page mode */ + if (jnapi->cdev->flags & CRETE_PAGE_MODE) + skb = crete_rx_page_pkt(jnapi, rxr, rxcpr, cons, len); + else + skb = crete_rx_linear_pkt(jnapi, rxr, rxcpr, cons, len); + + skb->protocol = eth_type_trans(skb, dev); + + skb_record_rx_queue(skb, rxr->id); + + return skb; +} + +int crete_poll_rx(struct napi_struct *napi, int budget) +{ + struct sk_buff *skb = NULL; + struct crete_napi *jnapi; + struct crete_rxcq_32bd_low *rxcqbd; + struct crete_rxcq_32bd_hi *rxcqbd_h; + struct crete_rxring_info *rxr; + struct crete_rxcp_ring_info *rxcpr; + struct crete_core_dev *cdev; + struct pci_dev *pdev; + u16 rx_cons, rx_prod, len, sfiinfo; + int budget_1; + int work_done = 0; + u8 bdtype, bdsize; + int lastcons = -1; + u64 rx_pkts = 0, rx_bytes = 0, rx_kicks = 0; + + jnapi = container_of(napi, struct crete_napi, napi); + if (!jnapi) + return 0; + + cdev = jnapi->cdev; + pdev = cdev->pdev; + rxr = jnapi->rxring; + rxcpr = jnapi->rxcpring; + budget_1 = budget; + rx_cons = READ_ONCE(rxcpr->cp_cons); + rxcqbd = (struct crete_rxcq_32bd_low *) + ((u8 *) rxcpr->rxcq_base + rx_cons * CRETE_ENTRY_DFAULT_SIZE); + crete_info(&pdev->dev, + "rxcqbd value pkttype:%d bufid:%d pkt len:%d rxcqbd addr:0x%lx\n", + rxcqbd->pkt_type, rxcqbd->buf_id, rxcqbd->pkt_len, + (unsigned long)rxcqbd); + prefetch(rxcqbd); + do { + pr_debug + ("rx cpr cons:%u rxcqbd wrap count:%d rxcpr wrap count:%d\n", + rx_cons, rxcqbd->wrap_counter, rxcpr->wrap_counter); + + /* rxcpr->wrap_counter = rxcpr->wrap_counter ^ 1; */ + if (!CRETE_DESC_VALID(rxcqbd, rxcpr)) { + crete_err(&pdev->dev, "rx desc invalid\n"); + break; + } + /* rxcpr->wrap_counter = rxcpr->wrap_counter ^ 1; */ + bdtype = CRETE_DESC_TYPE(rxcqbd); + bdsize = CRETE_DESC_SIZE(rxcqbd); + if (bdsize == BD_SIZE64) { + rxcqbd_h = (struct crete_rxcq_32bd_hi *) + ((u8 *) rxcpr->rxcq_base + + ((rx_cons + + 2) & rxcpr->ring_mask) * + CRETE_ENTRY_DFAULT_SIZE); + prefetch(rxcqbd_h); + if (!CRETE_DESC_VALID(rxcqbd_h, rxcpr)) { + crete_err(&pdev->dev, + "32bd hi rx desc invalid\n"); + break; + } + } + rx_prod = CRETE_DESC_BUFID(rxcqbd); + len = CRETE_RX_PKT_LEN(rxcqbd); + sfiinfo = rxcqbd->src_port_id; + crete_info(&pdev->dev, "rx poll pkttype:%d rx_cons:%d len:%d\n", + bdsize, rx_cons, len); + + skb = crete_rx_receive(jnapi, rxr, rxcpr, rx_prod, len, sfiinfo); + if (skb) { + /* + * handle receive checksum status + */ + crete_rx_post_handle(jnapi->cdev, skb, rxcqbd); + crete_deliver_skb(jnapi->cdev, jnapi, skb); + work_done++; + rx_pkts++; + rx_bytes += len; + } + + lastcons = rx_cons; + rx_cons = + CRETE_NEXTID(rx_cons, CRETE_PKT_LENGTH(bdsize), + rxcpr->ring_mask); + /* wrap counter need to wrap when ring wrapped */ + if (rx_cons < lastcons || rx_cons == 0) + rxcpr->wrap_counter = rxcpr->wrap_counter ^ 1; + + /* here need to consider about the rxcq_base + * wrap then the memory not continues. + */ + rxcqbd = (struct crete_rxcq_32bd_low *) + ((u8 *) rxcpr->rxcq_base + + rx_cons * CRETE_ENTRY_DFAULT_SIZE); + + smp_rmb(); + prefetch(rxcqbd); + budget_1--; + /* break; */ + } while (budget_1); + + /* rxcpr->cp_cons = rx_cons; */ + WRITE_ONCE(rxcpr->cp_cons, rx_cons); + if (work_done >= budget) + goto out; + + if (napi_complete_done(napi, work_done)) { + crete_db_write(&pdev->dev, rxr->rx_dbprod, rxr->id, DB_RXRQ, + cdev->db); + rx_kicks++; + } + +out: + u64_stats_update_begin(&rxr->rxq_stats->syncp); + rxr->rxq_stats->packets += rx_pkts; + rxr->rxq_stats->bytes += rx_bytes; + rxr->rxq_stats->kicks += rx_kicks; + u64_stats_update_end(&rxr->rxq_stats->syncp); + return work_done; +} + +static irqreturn_t crete_inta(int irq, void *data) +{ + struct crete_napi *jnapi = data; + + napi_schedule(&jnapi->napi); + return IRQ_HANDLED; +} + +static int crete_request_irq(struct crete_core_dev *cdev) +{ + + int i, rc = 0, qp_num, max_irqs, qp_irqs, irqno; + unsigned long flags = 0; + struct crete_irq_info *irq_info; + struct crete_napi *jnapi; + + if (!(cdev->flags & CRETE_FLAG_HAS_MSIX)) { + crete_err(cdev->device, "no msix cap, return failed\n"); + return -EINVAL; + } + + qp_num = cdev->ring_size; + qp_irqs = qp_num << 1; + max_irqs = cdev->irq_num; + + if (max_irqs < qp_irqs) + return 0; + + for (i = 0; i < qp_irqs; i++) { + jnapi = &cdev->jnapi[i]; + irqno = (i & 0x1) ? jnapi->txring->vec : jnapi->rxring->vec; + irq_info = &cdev->irq_info[irqno]; + crete_info(cdev->device, "irqno =%d vector =%d i=%d add lyx\n", irqno, + irq_info->vector, i); + rc = request_irq(irq_info->vector, crete_inta, flags, + irq_info->name, jnapi); + if (rc) { + pr_warn("request msix irq failed\n"); + return -1; + } + } + + return rc; +} + +void crete_destroy_irq(struct crete_core_dev *cdev) +{ + int i, qp_irqs, irqno; + struct crete_irq_info *irq_info; + struct crete_napi *jnapi; + + if (!(cdev->flags & CRETE_FLAG_HAS_MSIX)) + return; + + qp_irqs = cdev->ring_size << 1; + + for (i = 0; i < qp_irqs; i++) { + jnapi = &cdev->jnapi[i]; + /* acquire the ring vector number */ + irqno = (i & 0x1) ? jnapi->txring->vec : jnapi->rxring->vec; + irq_info = &cdev->irq_info[irqno]; + pr_info("i =%d add lyx irqno=%d irq_info=%d irq_info->requested=%d\n", + i, irqno, irq_info->vector, irq_info->requested); + if (!irq_info->requested) + break; + free_irq(irq_info->vector, jnapi); + } + +} + +static int crete_dev_enable_int(struct crete_core_dev *cdev) +{ + int i; + struct crete_napi *jnapi; + struct crete_napi *rx_jnapi; + struct crete_napi *tx_jnapi; + + jnapi = cdev->jnapi; + for (i = 0; i < cdev->ring_size; i++) { + rx_jnapi = &jnapi[i * 2]; + tx_jnapi = &jnapi[i * 2 + 1]; + printk("index i%d write doorbell\n", i); + //trigger the rx dir doorbell + crete_db_write(&cdev->pdev->dev, rx_jnapi->rxring->rx_dbprod, + rx_jnapi->rxring->id, DB_RXRQ, cdev->db); + rx_jnapi->rxring->rxq_stats->kicks++; + //trigger the tx dir doorbell + crete_db_write(&cdev->pdev->dev, tx_jnapi->txring->tx_dbprod, + tx_jnapi->txring->id, DB_TXSQ, cdev->db); + tx_jnapi->txring->txq_stats->kicks++; + + } + + return 0; +} + +static int crete_dev_open(struct crete_core_dev *cdev) +{ + int ret, i; + + netif_carrier_off(cdev->netdev); + crete_set_rxring_params(cdev); + crete_add_napi(cdev); + ret = crete_request_irq(cdev); + if (ret) + return -ENOMEM; + + // init the ring info + ret = crete_init_dev(cdev); + if (ret) { + ret = -EBUSY; + goto err_init; + } + + /* + * set the netdevice queues + */ + crete_set_real_num_queues(cdev); + + /* + * enable the txrx queues + */ + for (i = 0; i < cdev->ring_size; i++) { + /* enable the rx queue */ + crete_enable_singlequeue(cdev, (i * 2)); + /* enable the tx queue */ + crete_enable_singlequeue(cdev, (1 + i * 2)); + } + + crete_enable_napi(cdev); + crete_tx_enable(cdev); + + //need to apply the new rx and tx doorbell to kick the net + crete_dev_enable_int(cdev); + synchronize_net(); + netif_tx_wake_all_queues(cdev->netdev); + set_bit(2, &cdev->state); + g_cdev = cdev; + + return 0; + +err_init: + crete_destroy_irq(cdev); + + return ret; +} + +int crete_open(struct net_device *dev) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *cdev = priv->coredev; + int ret; + + ret = crete_dev_open(cdev); + if (ret) + return ret; + + return 0; +} + +static int crete_dev_close(struct crete_core_dev *cdev) +{ + int i; + + clear_bit(2, &cdev->state); + /* + * make sure the napi poll complete + */ + synchronize_net(); + crete_tx_disable(cdev); + + /* + * disable the queue + */ + for (i = 0; i < cdev->ring_size; i++) { + /* disable rx queue */ + crete_disable_singlequeue(cdev, 2 * i); + /* disable tx queue */ + crete_disable_singlequeue(cdev, 2 * i + 1); + } + + /* + * reset the queue + */ + for (i = 0; i < cdev->ring_size; i++) { + /* reset rx queue */ + crete_reset_singlequeue(cdev, 2 * i); + /* reset tx queue */ + crete_reset_singlequeue(cdev, 2 * i + 1); + } + + crete_disable_napi(cdev); + crete_destroy_irq(cdev); + crete_del_napi(cdev); + + /* free rxbuf and txbuf */ + crete_free_rxbuf(cdev); + crete_free_txbuf(cdev); + + return 0; +} + +int crete_close(struct net_device *dev) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *cdev = priv->coredev; + + crete_dev_close(cdev); + + return 0; +} + +static int crete_change_mtu(struct net_device *dev, int new_mtu) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *cdev = priv->coredev; + + if (netif_running(dev)) + crete_dev_close(cdev); + + dev->mtu = new_mtu; + crete_set_rxring_params(cdev); + + if (netif_running(dev)) + return crete_dev_open(cdev); + + return 0; +} + +static int crete_txchksum(struct sk_buff *skb, void *txbd) +{ + struct crete_txbd *txbd_16B; + struct crete_32txbd *txbd_32B; + + txbd_16B = (struct crete_txbd *)txbd; + CRETE_SETBDSIZE(txbd_16B, BD_SIZE32); + + txbd_32B = (struct crete_32txbd *)txbd; + /* + * kernel outmost l3 checksum already config + * but the tso mode , need to reconfig it again + * outmost l4 checksum flag set + */ + txbd_32B->bd_l0.outmost_l3_cksum = 1; + txbd_32B->bd_l0.outmost_l4_cksum = 1; + + /* + * tunnel mode + */ + if (skb->encapsulation) { + txbd_32B->bd_l1.out2nd_l3_cksum = 1; + txbd_32B->bd_l1.out2nd_l4_cksum = 1; + } + + /* + * calc the offset length value + * outer_l3_offset = outmost L2 + vlan + * outer_l4_offset = outmost L2 + vlan L3_len + */ + txbd_32B->bd_l1.outer_l3_offset = skb_network_offset(skb); + txbd_32B->bd_l1.outer_l4_offset = skb_transport_offset(skb); + + if (skb->encapsulation) { + /* + * l3_offset = outer l2 + l3 + l4 + tunnel + * l4_offset = outer l2 + l3 + l4 + tunnel + inner l3 + */ + txbd_32B->bd_l1.l3_offset = skb_inner_network_offset(skb); + txbd_32B->bd_l1.l4_offset = skb_inner_transport_offset(skb); + } + + return 0; +} + +static int crete_tx_prepare_firsttxbd(struct sk_buff *skb, void *txbd) +{ + if (skb->ip_summed == CHECKSUM_PARTIAL) + crete_txchksum(skb, txbd); + + return 0; +} + +netdev_tx_t crete_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct crete_priv *priv = netdev_priv(dev); + struct crete_core_dev *cdev = priv->coredev; + struct crete_txbd *txbd = NULL; + struct crete_txbd *firsttxbd; + struct netdev_queue *txq; + int i; + dma_addr_t mapping; + u32 length, len, free_size, bdsize; + u16 prod, last_frag, sfiinfo; + struct pci_dev *pdev = cdev->pdev; + struct crete_txring_info *txr; + struct crete_txcp_ring_info *txcpr; + struct crete_tx_buf *tx_buf; + int cpring_avail; + u64 tx_kicks = 0; + + i = skb_get_queue_mapping(skb); + if (unlikely(i >= cdev->ring_size)) { + dev_kfree_skb_any(skb); + /* dev_core_stats_tx_dropped_inc(dev); */ + return NETDEV_TX_OK; + } + + txq = netdev_get_tx_queue(dev, i); + txr = &cdev->txring[i]; + txcpr = &cdev->txcpring[i]; + free_size = crete_tx_avail(txr); + cpring_avail = atomic_read(&txcpr->ring_avail); + pr_debug("current txcpr ring avail %d\n", cpring_avail); + + if (unlikely((free_size < skb_shinfo(skb)->nr_frags + CRETE_TX_FREE_SIZE_THD) + || (cpring_avail < CRETE_TX_CPR_SIZE_PTH))) { + netif_tx_stop_queue(txq); + return NETDEV_TX_BUSY; + } + + /* skb sum length */ + length = skb->len; + /* skb linear length */ + len = skb_headlen(skb); + /* get the skb scatter fragments */ + last_frag = skb_shinfo(skb)->nr_frags; + prod = READ_ONCE(txr->tx_prod); + firsttxbd = &txr->tx_bd[prod]; + /* + * default bdsize config to 16bytes + */ + CRETE_SETBDSIZE(firsttxbd, BD_SIZE16); + pr_debug("current prod index %u, txbd addr 0x%lx\n", prod, + (unsigned long)firsttxbd); + + /* + * prepare xmit first sq bd + * first skb with the linear mode + */ + crete_tx_prepare_firsttxbd(skb, firsttxbd); + + tx_buf = &txr->tx_buf[prod]; + if (refcount_read(&tx_buf->kref)) + goto tx_free; + + firsttxbd->buf_id = prod; + /* + * first buff length is linear and non linear length + */ + firsttxbd->buf_len = cpu_to_le16(length); + + /* + * dma mapping the linear data + */ + mapping = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(&pdev->dev, mapping))) + goto tx_free; + + dma_unmap_addr_set(tx_buf, mapping, mapping); + + CRETE_WRITE_64BITADDR(firsttxbd, cpu_to_le64(mapping)); + pr_debug("tx buf id:%u, buf len :0x%x, data mapping address 0x%llx\n", + firsttxbd->buf_id, firsttxbd->buf_len, mapping); + refcount_set(&tx_buf->kref, 1); + tx_buf->skb = skb; + tx_buf->nr_frags = last_frag; + + /* netdev_tx_sent_queue(txq, skb->len); */ + skb_tx_timestamp(skb); + bdsize = CRETE_PKT_LENGTH(CRETE_DESC_SIZE(firsttxbd)); + tx_buf->nr_bdnum = bdsize; + /* tx db prod always need to increase */ + prod = CRETE_NEXTID(prod, bdsize, txr->tx_ring_mask); + + /* + * get the sfiinfo from rep + */ + sfiinfo = crete_xmit_get_sfiinfo(skb); + /* + * check the sfiinfo is valid or not + */ + if (sfiinfo != CRETE_MAX_CFA_CODE) { + firsttxbd->dst_port_valid = 1; + firsttxbd->dst_port = sfiinfo; + } + /* txr ring avail num dec the bdnum */ + firsttxbd->bd_num = bdsize; + /* txring avail size calc */ + atomic_sub(bdsize, &txr->ring_avail); + /* + * doorbell index need use acumulation value + */ + txr->tx_dbprod += bdsize; + /* last txbd also need to config here*/ + txbd = firsttxbd; + /* SG mode */ + for (i = 0; i < last_frag; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + txbd = &txr->tx_bd[prod]; + CRETE_SETBDSIZE(txbd, BD_SIZE16); + bdsize = CRETE_PKT_LENGTH(CRETE_DESC_SIZE(txbd)); + tx_buf = &txr->tx_buf[prod]; + tx_buf->nr_bdnum = bdsize; + refcount_set(&tx_buf->kref, 1); + len = skb_frag_size(frag); + mapping = skb_frag_dma_map(&pdev->dev, frag, 0, len, + DMA_TO_DEVICE); + + dma_unmap_addr_set(tx_buf, mapping, mapping); + /* + * write the mapping address + */ + CRETE_WRITE_64BITADDR(txbd, cpu_to_le64(mapping)); + txbd->buf_len = len; + txbd->buf_id = prod; + /* update avail ring size */ + atomic_sub(bdsize, &txr->ring_avail); + /* + * bd number just first bd useful + */ + firsttxbd->bd_num += bdsize; + /* update doorbell index */ + txr->tx_dbprod += bdsize; + /* prod put next id */ + prod = CRETE_NEXTID(prod, bdsize, txr->tx_ring_mask); + + } + + /* update tx production */ + WRITE_ONCE(txr->tx_prod, prod); + /* update cpring driver avail ring size */ + atomic_sub(1, &txcpr->ring_avail); + + /* last bd set eop flag */ + if (txbd) + txbd->eop = 1; + + /* this barrier promis the tx prod have been writed */ + smp_mb(); + + /* write db to notify the net interface */ + if (!netdev_xmit_more() || netif_xmit_stopped(txq)) { + crete_db_write(&cdev->pdev->dev, txr->tx_dbprod, txr->id, + DB_TXSQ, cdev->db); + txr->kick_pending = 0; + tx_kicks ++; + } else + txr->kick_pending = 1; + + return NETDEV_TX_OK; + +tx_free: + dev_kfree_skb_any(skb); + + if (txr->kick_pending) { + crete_db_write(&cdev->pdev->dev, txr->tx_dbprod, txr->id, + DB_TXSQ, cdev->db); + tx_kicks ++; + } + /* dev_core_stats_tx_dropped_inc(dev); */ + u64_stats_update_begin(&txr->txq_stats->syncp); + txr->txq_stats->kicks += tx_kicks; + u64_stats_update_end(&txr->txq_stats->syncp); + return NETDEV_TX_OK; +} + + +#define CRETE_SET_FEATURE(features, feature, enable) \ + do { \ + if (enable) \ + *features |= feature; \ + else \ + *features &= ~feature; \ + } while (0) + + +typedef int (*crete_feature_handler)(struct net_device *netdev, bool enable); + +static int crete_handle_feature(struct net_device *netdev, + netdev_features_t *features, + netdev_features_t feature, + crete_feature_handler feature_handler) +{ + netdev_features_t changes = *features ^ netdev->features; + bool enable = !!(*features & feature); + int err; + + if (!(changes & feature)) + return 0; + + err = feature_handler(netdev, enable); + if (err) { + CRETE_SET_FEATURE(features, feature, !enable); + netdev_err(netdev, "%s feature %pNF failed, err %d\n", + enable ? "Enable" : "Disable", &feature, err); + return err; + } + + return 0; +} + +static int set_feature_lro(struct net_device *netdev, bool enable) +{ + /* TODO */ + /* + * crete_cmd_set_feature_lro: set_tcp_lro + */ + + return 0; +} + +static int set_feature_rss(struct net_device *netdev, bool enable) +{ + /* TODO */ + /* + * crete_cmd_set_feature_rss + */ + + return 0; +} + + +int crete_set_features(struct net_device *netdev, netdev_features_t features) +{ + netdev_features_t oper_features = features; + int err = 0; + +#define CRETE_HANDLE_FEATURE(feature, handler) \ + crete_handle_feature(netdev, &oper_features, feature, handler) + + err |= CRETE_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro); + err |= CRETE_HANDLE_FEATURE(NETIF_F_RXHASH, set_feature_rss); + + if (err) { + netdev->features = oper_features; + return -EINVAL; + } + + return 0; +} + +static netdev_features_t crete_fix_features(struct net_device *netdev, + netdev_features_t features) +{ + if (!netif_device_present(netdev)) + return features; + + if (!(features & NETIF_F_GRO)) + features &= ~NETIF_F_GRO_HW; + + if (features & NETIF_F_GRO_HW) + features &= ~NETIF_F_LRO; + + return features; +} + +netdev_features_t crete_features_check(struct sk_buff *skb, + struct net_device *netdev, + netdev_features_t features) +{ + return features; +} + +int crete_features_negotiate(struct crete_core_dev *cdev) +{ + int err; + int i; + netdev_features_t dev_netdev_feat_bits, driver_netdev_features; + netdev_features_t dev_offload_feat_bits, driver_offload_features; + + //1.get hw feat + err = crete_cmd_get_features(cdev, CRETE_NET_DEV_FEAT, &dev_netdev_feat_bits); + if (err) { + crete_err(cdev->device, "get netdev features failed\n"); + goto err_negotiate; + } + err = crete_cmd_get_features(cdev, CRETE_OFFLOAD_FEAT, &dev_offload_feat_bits); + if (err) { + crete_err(cdev->device, "get offload features failed\n"); + goto err_negotiate; + } + driver_netdev_features = 0; + for (i = 0; i < ARRAY_SIZE(crete_netdev_features); i++) { + unsigned int f = crete_netdev_features[i]; + + WARN_ON_ONCE(f >= 64); + driver_netdev_features |= (1ULL << f); + } + + driver_offload_features = 0; + for (i = 0; i < ARRAY_SIZE(crete_offload_features); i++) { + unsigned int f = crete_offload_features[i]; + + WARN_ON_ONCE(f >= 64); + driver_offload_features |= (1ULL << f); + } + + cdev->netdev_features = driver_netdev_features & dev_netdev_feat_bits; + cdev->offload_features = driver_offload_features & dev_offload_feat_bits; + + err = crete_cmd_set_features(cdev, CRETE_NET_DEV_FEAT, cdev->netdev_features); + if (err) { + crete_err(cdev->device, "set netdev features failed\n"); + goto err_negotiate; + } + + err = crete_cmd_set_features(cdev, CRETE_OFFLOAD_FEAT, cdev->offload_features); + if (err) { + crete_err(cdev->device, "set offload features failed\n"); + goto err_negotiate; + } + +err_negotiate: + return err; +} + +EXPORT_SYMBOL(crete_poll_rx); +EXPORT_SYMBOL(crete_poll_tx); +EXPORT_SYMBOL(crete_start_xmit); +EXPORT_SYMBOL(g_cdev); +const struct net_device_ops crete_netdev_ops = { + .ndo_open = crete_open, + .ndo_stop = crete_close, + .ndo_start_xmit = crete_start_xmit, + + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = crete_change_mac_addr, + + .ndo_set_rx_mode = crete_set_rx_mode, + + .ndo_get_vf_config = crete_get_vf_config, + .ndo_set_vf_mac = crete_set_vf_mac, + .ndo_set_vf_vlan = crete_set_vf_vlan, + .ndo_set_vf_rate = crete_set_vf_bw, + .ndo_set_vf_link_state = crete_set_vf_link_state, + .ndo_set_vf_spoofchk = crete_set_vf_spoofchk, + .ndo_set_vf_trust = crete_set_vf_trust, + .ndo_set_features = crete_set_features, + .ndo_fix_features = crete_fix_features, + .ndo_features_check = crete_features_check, + .ndo_change_mtu = crete_change_mtu +}; diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_txrx.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_txrx.h new file mode 100644 index 0000000..1a008c3 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete_txrx.h @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/****************************************************************************** + * crete_ring.c + * + * Jmnd crete driver + * + * Authors: Jmnd + * + */ +#ifndef __CRETE_IOQUEUE_H +#define __CRETE_IOQUEUE_H + +#define CRETE_RING_DEFAULT_DEEP 1024UL +#define CRETE_ENTRY_DFAULT_SIZE 16UL +#define CRETE_PKTTYPE0_LENGTH 1UL +#define CRETE_PKTTYPE1_LENGTH 2UL +#define CRETE_PKTTYPE2_LENGTH 3UL +#define CRETE_PKTTYPE3_LENGTH 4UL + +enum { + BD_SIZE16 = 0, + BD_SIZE32, + BD_SIZE48, + BD_SIZE64 +}; + +enum { + TUNNEL_NONE = 0x0, + TUNNEL_ONE = 0x2, + TUNNEL_TWO = 0x3, + TUNNEL_ERR = 0x1 +}; + +#define CRETE_PKT_LENGTH(bd_size) \ + (bd_size == BD_SIZE16 ? CRETE_PKTTYPE0_LENGTH : \ + (bd_size == BD_SIZE32 ? CRETE_PKTTYPE1_LENGTH : \ + (bd_size == BD_SIZE48 ? CRETE_PKTTYPE2_LENGTH : \ + (bd_size == BD_SIZE64 ? CRETE_PKTTYPE3_LENGTH : 0)))) + +#define CRETE_RX_OFFSET (NET_SKB_PAD + NET_IP_ALIGN) +#define CRETE_RX_DMA_OFFSET NET_SKB_PAD + +#define CRETE_TX_DIR 0 +#define CRETE_RX_DIR 1 +#define CRETE_TX_DIR_BITS (1 << 4) +#define CRETE_RX_DIR_BITS (1 << 3) + + +/* The feature bitmap for Crete netdev */ +#define CRETE_NET_F_SOP_PADDING 0 +#define CRETE_NET_F_EOP_PADDING 1 +#define CRETE_NET_F_AUTO_INTR_SUP 2 +#define CRETE_NET_F_INTR_MOD 3 +#define CRETE_NET_F_TX_INORDER 5 +#define CRETE_NET_F_CQE_AGG 7 +#define CRETE_NET_F_RX_MERGE 8 + +/* The feature bitmap for Crete offload */ +#define CRETE_NET_F_RX_VLAN_FILTER 0 +#define CRETE_NET_F_RX_VLAN_STRIP 1 +#define CRETE_NET_F_RX_IPV4_CSUM 2 +#define CRETE_NET_F_RX_UDP_CSUM 3 +#define CRETE_NET_F_RX_TCP_CSUM 4 +#define CRETE_NET_F_RX_SCTP_CSUM 5 +#define CRETE_NET_F_RX_TCP_LRO 6 +#define CRETE_NET_F_RX_RSS_HASH 7 +#define CRETE_NET_F_RX_TIMESTAMP 8 +#define CRETE_NET_F_RX_METADATA 9 + +#define CRETE_NET_F_TX_IPV4_CSUM 32 +#define CRETE_NET_F_TX_TCP_CSUM 33 +#define CRETE_NET_F_TX_UDP_CSUM 34 +#define CRETE_NET_F_TX_SCTP_CSUM 35 +#define CRETE_NET_F_TX_OUTER_IPV4_CSUM 36 +#define CRETE_NET_F_TX_OUTER_UDP_CSUM 37 +#define CRETE_NET_F_TX_TCP_TSO 38 +#define CRETE_NET_F_TX_IP_TNL_TSO 39 +#define CRETE_NET_F_TX_UDP_TNL_TSO 40 +#define CRETE_NET_F_TX_VLAN_INSERT 41 +#define CRETE_NET_F_TX_QINQ_INSERT 42 +#define CRETE_NET_F_TX_SEND_ON_TIMESTAMP 43 +#define CRETE_NET_F_TX_METADATA 44 + +#define CRETE_NET_F_VPORT_RX_FLOW_TABLE 59 +#define CRETE_NET_F_FDB_TABLE 60 +#define CRETE_NET_F_FLOW_REDIR_TABLE 61 +#define CRETE_NET_F_L2_SWITCH_TABLE 62 +#define CRETE_NET_F_VSWITCH_OFFLOAD 63 + +enum CRETE_DB_TYPE { + DB_RXRQ = 0, + DB_TXSQ, + DB_RXCQ_ARM, + DB_TXCQ_ARM +}; + +#define CRETE_RING_MEM_SIZE 4 +#define CRETE_TX_FREE_SIZE_THD 16 +#define CRETE_TX_CPR_SIZE_PTH 8 + +#define CRETE_SETBDSIZE(x, size) (x->bd_size = size) + +#define CRETE_NEXTID(x, val, mask) \ + ((x + val) & mask) + +#define CRETE_DESC_VALID(txcmp, txcpr) \ + (txcmp->wrap_counter == (1 ^ txcpr->wrap_counter)) + +#define CRETE_DESC_BUFID(txcmp) \ + (txcmp->buf_id) + +#define CRETE_DESC_TYPE(txcmp) \ + (txcmp->bd_type) + +#define CRETE_DESC_SIZE(txcmp) \ + (txcmp->bd_size) + +#define CRETE_DESC_BDLEN(txbd) \ + (CRETE_PKT_LENGTH(CRETE_DESC_SIZE(txbd))) + +#define CRETE_RX_PKT_LEN(bd) \ + (le16_to_cpu(bd->pkt_len)) + +#define CRETE_WRITE_64BITADDR(s, le64_val) \ + do { \ + s->addr_lo = le64_val & 0xFFFFFFFF; \ + s->addr_hi = (le64_val >> 32UL) & 0xFFFFFFFF; \ + }while(0) + +#define crete_err(__dev, format, ...) \ + dev_err(__dev, "%s:%d:(pid %d): " format, \ + __func__, __LINE__, current->pid, \ + ##__VA_ARGS__) + +#define crete_info(__dev, format, ...) \ + dev_info(__dev, "%s:%d:(pid %d): " format, \ + __func__, __LINE__, current->pid, \ + ##__VA_ARGS__) + +#define crete_warn(__dev, format, ...) \ + dev_warn(__dev, "%s:%d:(pid %d): " format, \ + __func__, __LINE__, current->pid, \ + ##__VA_ARGS__) + +/****begin define the io queue struct ****/ + +/** + * struct crete_rx_bd - crete rx rqe define + * @pkttype: pkttype 0 0:16bytes 1:2*16bytes 2:3*16bytes 3:4*16bytes + * @buf_id: the packet buffer id ,do not need to convert order sequence. + * @resv: resver bytes + * @buf_len: buffer length + * @addr_lo: address lower32 + * @addr_hi: address high32 + */ +struct crete_rx_bd { + u16 bd_size:3; + u16 rsv0:13; + u16 buf_id; + __le16 buf_len; + __le16 resv; + __le32 addr_lo; + __le32 addr_hi; +} __packed; + +/** + * struct crete_rxcq_32bd - crete rx rqe define + * @pkttype: pkttype 0 0:16bytes 1:2*16bytes 2:3*16bytes 3:4*16bytes + * @vlan_strip: the packet buffer id + * @rss_validate: resver bytes + * @outer_vlan_tpid: buffer length + * @addr_lo: address lower32 + * @addr_hi: address high32 + * Little Endian Only + */ +struct crete_rxcq_32bd_low { + /* dw0 */ + u16 bd_size:3; + u16 bd_type:2; + u16 rsv0:2; + u16 wrap_counter:1; + u16 pkt_err_type:3; + u16 l4_cksum_ok:1; + u16 l3_cksum_ok:1; + u16 l2_type:2; + u16 ptp_pkt:1; + u16 buf_id; + + /* dw1 */ + u32 pkt_len:17; + u32 l4_hdr_type:3; + u32 l3_hdr_type:3; + u32 outer_l3_type:1; + u32 ip_frag:1; + u32 tunnel_mode:2; + u32 l2_valid:1; + u32 outer_ip_ext_opts:1; + u32 tunnel_ip_ext_opts:1; + u32 tunnel_l3_type:1; + u32 ip_ext_opts:1; + + /* dw2 */ + u16 src_port_id:12; + u16 rsv1:4; + u16 pkt_type:4; + u16 rsv2:2; + u16 rss_level:2; + u16 rss_type:8; + + /* dw3 */ + __le32 rss_hash; + + /* dw4 */ + __le32 timestamp; + + /* dw5 */ + __le16 vlan_tci; + u16 strip_vlan_tpid:3; + u16 vlan_strip:1; + u16 rsv3:4; + u16 rx_drop_counter:8; + + /* dw6 */ + __le32 metadata0; + + /* dw7 */ + __le32 metadata1; +} __packed; + +/** + * struct crete_rxcq_32bd_hi - crete rx rqe define + * @rsv0: + * @wrap_counter: + * @rsv1: resver bytes + * @flow_tag0: buffer length + * @timestamps: address lower32 + * @addr_hi: address high32 + */ +struct crete_rxcq_32bd_hi { + /* dw 0 */ + u16 rsv0:7; + u16 wrap_counter:1; + u16 lro_seg_num:8; + __le16 lro_checksum; + + /* dw 1 */ + u16 rsv1:4; + u16 lro_tcp_psh:1; + u16 lro_abrt:3; + u16 lro_min_ttl:8; + __le16 lro_tcp_win; + + /* dw 2 */ + __le32 lro_ack_seq_num; + + /* dw 3 */ + u32 timestamp_type:2; + u32 rsv2:30; + + /* dw 4 */ + __le32 timestamp_low; + + /* dw 5 */ + __le32 timestamp_high; + + /* dw 6 */ + __le32 metadata2; + + /* dw 7 */ + __le32 metadata3; +} __packed; + +/** + * struct crete_rxcq_64bd - rx 64bytes bd + * @bd_l: low 32 bytes bd + * @bd_h: high 32 bytes bd + */ +struct crete_rxcq_64bd { + struct crete_rxcq_32bd_low bd_l; + struct crete_rxcq_32bd_hi bd_h; +} __packed; + +/** + * struct crete_txbd - 16bytes no offloads + * @pkt_type: + * @no_complete: + */ +struct crete_txbd { + /* dw 0 */ + u16 bd_size:3; + u16 rsv:2; + u16 eop:1; + u16 debug_trace:1; + u16 rsv0:1; + u16 bd_num:6; + u16 outmost_l3_cksum:1; + u16 outmost_l4_cksum:1; + u16 buf_id; + + /* dw 1 */ + u16 dst_port:12; + u16 rsv1:3; + u16 dst_port_valid:1; + __le16 buf_len; + + /* dw 2 */ + __le32 addr_lo; + + /* dw 3 */ + __le32 addr_hi; +} __packed; + +struct crete_txbd_l1 { + /* dw 0 */ + __le16 vlan_cli; + u16 vlan_insert:1; + u16 vlan_tpid:3; + u16 out3rd_l3_cksum:1; + u16 out3rd_l4_cksum:1; + u16 out2nd_l3_cksum:1; + u16 out2nd_l4_cksum:1; + u16 mac_timestamp_en:1; + u16 udp_tunnel_sport:1; + u16 rsv0:6; + + /* dw 1 */ + u8 outer_l4_offset; + u8 outer_l3_offset; + u8 l4_offset; + u8 l3_offset; + + /* dw 2 */ + u16 rsv1:15; + u16 tso_en:1; + u16 l4_tunnel_type:2; + u16 mss:14; + + /* dw 3 */ + __le32 metadata; +} __packed; + +struct crete_32txbd { + struct crete_txbd bd_l0; + struct crete_txbd_l1 bd_l1; +} __packed; + +struct crete_txbd_l2 { + /* dw 0 */ + u16 rsv0:15; + u16 meter_valid:1; + __le16 meter_len; + + /* dw 1 */ + __le16 meterid0; + __le16 meterid1; + + /* dw 2 */ + __le16 meterid2; + __le16 meterid3; + + /* dw 3 */ + __le16 meterid4; + __le16 meterid5; + +} __packed; + +struct crete_48txbd { + struct crete_txbd bd_l0; + struct crete_txbd_l1 bd_l1; + struct crete_txbd_l2 bd_l2; +} __packed; + +/** + * struct tx_cq_bd + * @pkt_type: + * @rsv0: + * @timestamp_high_flag: + */ +struct tx_cq_bd { + /* dw 0 */ + u16 bd_size:3; + u16 bd_type:2; + u16 rsv0:2; + u16 wrap_counter:1; + u16 rsv1:8; + __le16 buf_id; + + /* dw 1 */ + __le32 errors; + + /* dw 2 */ + __le32 rsv2; + + /* dw 3 */ + __le32 timestamps; +} __packed; + +union crete_db_info { + __le32 val; + struct { + __le16 index; + u16 vqn:11; + u16 debug_trace:1; + u16 type:4; + } db_info; +} __packed; + +/** + * struct crete_db - crete rx db define + * @val: doorbell register value, notice le mode + * @type: sq / rq / eq + * @vqn: qp index + * @index: sq/rq entry bd index + */ +struct crete_db { + void __iomem *db_addr; + spinlock_t lock; + union { + __le32 val; + struct { + u32 type:5; + u32 resv:3; + u32 vqn:8; + __le16 index:16; + } db_info; + }; +}; + +/****end define the io queue struct ****/ + +/** + * struct crete_rx_buf + * @page page + * @data:point to the rxbuf cpu address + * @mapping:device dma handle address + * kref: used for the + */ +struct crete_rx_buf { + refcount_t kref; + struct page *page; + void *data; + u8 *data_ptr; + dma_addr_t mapping; +// struct kref kref; +}; + +/** + * struct crete_tx_buf + * @skb: skb buffer address + * @mapping:device dma handle address + * @kref: ref counter + * @rx_prod: cons the rx production index + */ +struct crete_tx_buf { +// struct kref kref; + refcount_t kref; + struct sk_buff *skb; + dma_addr_t mapping; + void (*release)(struct kref *kref); + u16 rx_prod; + u16 nr_frags; + u16 nr_bdnum; +}; + +/** + * struct crete_rxring_mem + * all the qp memory info need the struct + * fly with bp memory + * @rx_bd: rx sq virtual memory address + * @rx_bd_map: rx bd dma handle + */ +struct crete_ring_mem { + void *ring_base[CRETE_RING_MEM_SIZE]; + dma_addr_t rx_bd_map[CRETE_RING_MEM_SIZE]; +}; + +struct crete_rxcp_ring_info { + void *rxcq_base; + void *priv; // used for crete_napi + dma_addr_t rxcq_mapping; + size_t bd_len; + u16 cp_prod; + u16 cp_cons; + u32 ring_size; + u32 ring_mask; + u8 wrap_counter:1; +}; + +struct crete_txcp_ring_info { + void *txcq_base; + void *priv; // used for crete_napi + dma_addr_t txcq_mapping; + size_t bd_len; + u16 cp_prod; + u16 cp_cons; + u32 ring_size; + u32 ring_mask; + atomic_t ring_avail; + u8 wrap_counter:1; +}; + +/** + * struct crete_rxring + * @rx_bd:rx ring descripion + * @db:ring doorbell + * @rx_buf: rxring buffer + */ +struct crete_rxring_info { + struct crete_rx_bd *rx_bd; + dma_addr_t rx_bd_mapping; + size_t bd_len; + struct crete_rx_buf *rx_buf; + struct crete_rxcp_ring_info *cpring; + void *priv; // used for crete_napi + refcount_t jref; + struct crete_db db; + struct crete_rxq_stats *rxq_stats; + u16 rx_dbprod; + u16 rx_prod; + u16 rx_cons; + u16 rx_ring_size; + u16 rx_ring_mask; + u8 queue_id; + u8 id; + u16 vec; +}; + +struct crete_txring_info { + struct crete_txbd *tx_bd; + dma_addr_t tx_bd_mapping; + size_t bd_len; + struct crete_db *db; + struct crete_tx_buf *tx_buf; + struct crete_txcp_ring_info *cpring; + void *priv; // used for crete_napi + //struct crete_db db; + struct crete_txq_stats *txq_stats; + u16 tx_prod; + u16 tx_dbprod; + u16 tx_cons; + u16 tx_ring_size; + u16 tx_ring_mask; + refcount_t jref; + u8 id; + u16 vec; + atomic_t ring_avail; + u8 kick_pending:1; + +}; + +struct crete_napi { + struct napi_struct napi; + struct crete_core_dev *cdev; + + union { + struct crete_rxring_info *rxring; + struct crete_txring_info *txring; + }; + + union { + struct crete_rxcp_ring_info *rxcpring; + struct crete_txcp_ring_info *txcpring; + }; + +}; + + +static inline u32 crete_tx_avail(struct crete_txring_info *txr) +{ + barrier(); +// return txr->tx_ring_size - ((txr->tx_prod - txr->tx_cons) & txr->tx_ring_mask); + return atomic_read(&txr->ring_avail); +} + +static inline u32 crete_tx_length(struct crete_txring_info *txr) +{ + barrier(); + return (txr->tx_ring_size - atomic_read(&txr->ring_avail)); +} + +extern struct crete_core_dev *g_cdev; +//extern int crete_cdev_cap_init(struct crete_core_dev *cdev); +extern netdev_tx_t crete_start_xmit(struct sk_buff *skb, + struct net_device *dev); +extern int crete_poll_tx(struct napi_struct *napi, int budget); +extern int crete_poll_rx(struct napi_struct *napi, int budget); +extern int crete_features_negotiate(struct crete_core_dev *cdev); +extern int crete_close(struct net_device *dev); +extern int crete_open(struct net_device *dev); + +/* + * static inline void crete_txbuf_release(struct kref *kref, struct device *dev) + * { + * struct crete_tx_buf *txbuf; + * struct + * txbuf = container_of(kref, struct crete_tx_buf, kref); + * if (!txbuf) + * return; + * dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping), + * skb_headlen(skb), DMA_TO_DEVICE); + * dev_kfree_skb_any(skb); + * } + */ + +#endif /* __CRETE_IOQUEUE_H */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/kcompat_std_defs.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/kcompat_std_defs.h new file mode 100644 index 0000000..a0509ea --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/kcompat_std_defs.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2023, Jaguar Micro. All rights reserved */ + +#ifndef _KCOMPAT_STD_DEFS_H_ +#define _KCOMPAT_STD_DEFS_H_ + +/* This file contains the definitions for what kernel features need backports + * for a given kernel. It targets only the standard stable kernel releases. + * It must check only LINUX_VERSION_CODE and assume the kernel is a standard + * release, and not a custom distribution. + * + * It must define HAVE_ and NEED_ for features. It must not + * implement any backports, instead leaving the implementation to the + * kcompat_impl.h header. + * + * If a feature can be easily implemented as a replacement macro or fully + * backported, use a NEED_ to indicate that the feature needs + * a backport. (If NEED_ is undefined, then no backport for that feature + * is needed). + * + * If a feature cannot be easily implemented in kcompat directly, but + * requires drivers to make specific changes such as stripping out an entire + * feature or modifying a function pointer prototype, use a HAVE_. + */ + +#ifndef LINUX_VERSION_CODE +#error "LINUX_VERSION_CODE is undefined" +#endif + +#ifndef KERNEL_VERSION +#error "KERNEL_VERSION is undefined" +#endif + + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 18, 0)) +#define CONFIG_DEVLINK_WITHOUT_FLASH +#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH +// #define NEED_ETH_HW_ADDR_SET +#endif /* 4,18,0 */ + + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) +#define NEED_ETH_HW_ADDR_SET +#endif /* 5.10.0 */ + + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 134)) +#define NEED_ETH_HW_ADDR_SET +#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH +#define HAVE_DEVLINK_REGISTER_SETS_DEV +#define NEED_DEVLINK_ALLOC_SETS_DEV +#endif /* 5.10.134 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)) +#define CONFIG_DEVLINK_CARRYOUT_OPTIMIZE +#endif /* 5.11.0 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)) +#define CONFIG_ETHTOOL_EXTEND_RINGPARAM +#endif /* 5.17.0 */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)) +#define NETIF_NAPI_ADD_NEWAPI +#endif /* 5.19.0 */ + +/*****************************************************************************/ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) +#else /* >=6.1.0 */ +#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH +#endif /* 6.1.0 */ + +/* + * about the anolis 5.10.134-14 kernel version + * auxliary define with return int value + */ +#ifdef SNIC_ANOLIS_VERSION14 +// #define NEED_ETH_HW_ADDR_SET +#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH +#define HAVE_DEVLINK_REGISTER_SETS_DEV +#define NEED_DEVLINK_ALLOC_SETS_DEV +#endif + +#ifdef BCLINUX2110U4 +#undef NEED_ETH_HW_ADDR_SET +#define CONFIG_ETHTOOL_EXTEND_RINGPARAM +#endif + +#ifdef SNIC_OPENEULER_VERSION136 +#define CONFIG_ETHTOOL_EXTEND_RINGPARAM +#endif + +#endif /* _KCOMPAT_STD_DEFS_H_ */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/rdma.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/rdma.h new file mode 100644 index 0000000..2468670 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/rdma.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * Copyright (c) 2023, Jaguarmicro Technologies, Inc. All rights reserved. + */ + +#ifndef JM_RDMA_H +#define JM_RDMA_H +#include +#ifndef USE_JM_AUX_BUS +#include +#else +#include "linux/auxiliary_bus.h" +#endif +#include + +struct jm_rdma_core; +struct jm_rdma_adev; + +/* + * struct device *(*get_device)(struct jm_rdma_core *rdma); + * Get struct device related with this auxiliary_device. + * For example: + * return &pci_dev.dev; + * + * void (*get_dev_info)(struct jm_rdma_core *rdma, u8 *feature, + * u8 *rev_id, u16 *dev_id); + * Get device's information. + * For example: + * *rev_id = pci_dev.revision; + * *dev_id = pci_dev.device; + * *vendor = pci_dev.vendor; + * + * void (*cmdq_notify)(struct jm_rdma_core *rdma, u32 event); + * Notify new command to the related command queue. + * For example: + * iowrite32(event, cmd_db_reg); //cmd_db_reg = reg_addr + 0xEFC0 + * + * int (*get_irqn)(struct jm_rdma_core *rdma, int index); + * Get the irq number with the index. + * For example: + * return pci_irq_vector(ae_dev->pdev, index); + * + * int (*store_bond_info)(struct jm_rdma_core *rdma, + * struct net_device *master, bool flag); + * Currently an empty function(return 0) is ok. + * + * void (*get_bar)(struct jm_rdma_core *rdma, void **base, void **eq_reg); + * Get BAR mapping bar address and eq address. + * For example: + * *base = reg_addr; // reg_addr = ioremap(base_base, 64 * 1024) + * *eq_reg = eq_db_reg; // eq_db_reg = reg_addr + 0xF000 + * + * void (*get_uar)(struct jm_rdma_core *rdma, phys_addr_t *base, u32 *len); + * Get UAR base and length. + * For example: + * *base = uar_base; //bar_base + 64 * 1024 + * *len = uar_size; // 64 * 1024 + * + * void (*get_vector)(struct jm_rdma_core *rdma, int num, int base); + * Get the base and number of rdma's interrupt vector. + * For example: + * *base = vector_base; + * *num = vector_num; + * + * void (*timer_db)(struct jm_rdma_core *rdma, u32 qpn, int flags); + * Trigger a time DB. + * Currently an empty function is ok. + * + * void (*reload)(struct jm_rdma_core *rdma); + * Reload rdma core driver. + * Currently an empty function is ok. + * + */ +struct jm_rdma_ops { + struct device *(*get_device)(struct jm_rdma_core *rdma); + void (*get_dev_info)(struct jm_rdma_core *rdma, u8 *feature, u8 *rev_id, + u16 *dev_id, u16 *vendor); + void (*cmdq_notify)(struct jm_rdma_core *rdma, u32 event); + int (*get_irqn)(struct jm_rdma_core *rdma, int index); + int (*store_bond_info)(struct jm_rdma_core *rdma, + struct net_device *master, bool flag); + void (*get_bar)(struct jm_rdma_core *rdma, void **base, void **eq_reg); + void (*get_uar)(struct jm_rdma_core *rdma, phys_addr_t *base, int *len); + void (*get_vector)(struct jm_rdma_core *rdma, int *num, int *base); + bool (*is_error)(struct jm_rdma_core *rdma); + void (*timer_db)(struct jm_rdma_core *rdma, u32 qpn, int flags); + void (*reload)(struct jm_rdma_core *rdma); +}; + +struct jm_rdma_core { + struct jm_rdma_ops *ops; + struct jm_rdma_adev **adev; + int adev_idx; +}; + +struct jm_rdma_adev { + struct auxiliary_device adev; + struct jm_rdma_core *rdma_core; + int idx; +}; + +enum { + JM_DEVICE_FEATURE_CMDQ_IS_PA = 1 << 0, + JM_DEVICE_FEATURE_ATOMIC_HCA = 1 << 1, +}; + + +#endif diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/scripts/check_aux_bus.sh b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/scripts/check_aux_bus.sh new file mode 100755 index 0000000..2aaf935 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/scripts/check_aux_bus.sh @@ -0,0 +1,239 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2023, Jaguar Micro. All rights reserved +# +# Helper script to detect if auxiliary bus support. This script +# +# returns 0 when: +# - CONFIG_AUXILIARY_BUS=y +# - auxiliary_bus.h was found +# +# Returning 0 means the driver build/install doesn't need OOT +# auxiliary bus +# +# returns 1 when: +# - CONFIG_AUXILIARY_BUS=n (or any value that's not "=y") +# - kernel configuration was incorrect +# - kernel configuration file was not found +# +# Returning 1 means something bad/unexpected happened and the +# driver build/install should treat this as a failure +# +# returns 2 when: +# - When OOT auxiliary is needed regardless if a previous OOT +# auxiliary was already. This is done because the driver +# always needs to build against auxiliary.o to avoid +# warnings/errors since auxiliary.o is built-in to the +# driver's makefile +# +# Returning 2 means the driver build/install needs OOT auxiliary +# bus +# +# returns 3 when: +# - A file and/or directory does not exist +# +# Returning 3 means something bad/unexpected happened and the +# driver build/install should treat this as a failure +# +# Note: when ksrc and build-kernel are both specified on the +# command line and build-kernel is not in the same location +# as ksrc, then ksrc takes precedence. For example: +# ./check_aux_bus --ksrc=/lib/modules/5.8.0/source --build-kernel=5.10.0 +# +# In this case the kernel config file won't be searched for and +# the script will only check to see if the in-tree/OOT auxiliary_bus.h +# file exists at ksrc. + +msg() +{ + if [ $verbose == 1 ]; then + echo -e $1 + fi +} + +exit_builtin_auxiliary_enabled() { exit 0; } +exit_kconfig_invalid() { exit 1; } +exit_need_oot_auxiliary() { exit 2; } +exit_not_found_failure() { exit 3; } + +find_aux_bus_inc() +{ + aux_bus_inc=$(find -L ${ksrc} -name "auxiliary_bus.h") + msg "auxiliary_bus.h location: ${aux_bus_inc}" +} + +LINUX_INC_DIR="include/linux" + +set_build_kernel() +{ + build_kernel=$(uname -r) +} + +find_kernel_source() +{ + # All the default places to look for kernel source + test_dirs=(/lib/modules/${build_kernel}/source \ + /lib/modules/${build_kernel}/build \ + /usr/src/linux-${build_kernel} \ + /usr/src/linux-$(echo ${build_kernel} | sed 's/-.*//') \ + /usr/src/kernel-headers-${build_kernel} \ + /usr/src/kernel-source-${build_kernel} \ + /usr/src/linux-$(echo ${build_kernel} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ + /usr/src/linux \ + /usr/src/kernels/${build_kernel} \ + /usr/src/kernels) + + # Save the first valid kernel source path + for dir in "${test_dirs[@]}"; do + if [ -d ${dir}/${LINUX_INC_DIR} ]; then + ksrc=${dir} + break + fi + done + + if [ -z ${ksrc} ]; then + echo "*** Kernel header files not in any of the expected locations." + echo "*** Install the appropriate kernel development package, e.g." + echo "kernel-devel, for building kernel modules and try again" + exit_not_found_failure + fi +} + +find_config_file() +{ + # only search for kernel .config file if build_kernel is pointing + # in the same tree as ksrc (see not about ksrc and build_kernel + # both set in the scripts header comment) + if [[ "$ksrc" != *"/lib/modules/${build_kernel}"* ]]; then + msg "ksrc=$ksrc not the same as location generated from" + msg "build_kernel=\"/lib/modules/${build_kernel}\", " + msg "not searching for kernel .config file" + else + kbuild_dir="/lib/modules/${build_kernel}/build" + + file_locations=(${kbuild_dir}/include/generated/autoconf.h \ + ${kbuild_dir}/include/linux/autoconf.h \ + /boot/bmlinux.autoconf.h) + + for file in "${file_locations[@]}"; do + if [ -f ${file} ]; then + kconfig=${file} + break + fi + done + + if [ -z ${kconfig} ]; then + msg "Kernel config file not found at any of the expected locations." + fi + fi +} + +get_config_auxiliary_bus() +{ + # CONFIG_AUXILIARY_BUS=0 corresponds to CONFIG_AUXILIARY_BUS=n + # CONFIG_AUXILIARY_BUS=1 corresponds to CONFIG_AUXILIARY_BUS=y + # CONFIG_AUXILIARY_BUS= corresponds to CONFIG_AUXILIARY_BUS not available in the kernel + CONFIG_AUXILIARY_BUS=$(grep CONFIG_AUXILIARY_BUS ${kconfig} | awk -F" " '{print $3}') + msg "CONFIG_AUXILIARY_BUS=${CONFIG_AUXILIARY_BUS}" +} + +ksrc="" +build_kernel="" +verbose=0 + +usage() +{ + script=$(basename $0) + echo -e "usage:" + echo -e "\t$script [options]" + echo -e "\n\toptions:" + echo -e "\t -v, --verbose" + echo -e "\t -h, --help" + echo -e "\n\turn script against specified kernel source" + echo -e "\t -k, --ksrc \"/lib/modules/5.12.0/source\"" + echo -e "\n\turn script with kernel version (kernel version used to" + echo -e "find kernel source programatically)" + echo -e "\t -b, --build-kernel \"5.8.0\"" +} + +options=$(getopt -o "k:b:vh" --long ksrc:,build-kernel:,verbose,help -- "$@") +eval set -- "$options" +while :; do + case $1 in + -k|--ksrc) ksrc=$2; shift;; + -b|--build-kernel) build_kernel=$2; shift;; + -v|--verbose) verbose=1 ;; + -h|--help) usage && exit 0;; + --) shift; break;; + esac + shift +done + +if [ $verbose == 1 ]; then + set -x +fi + +# both build_kernel and ksrc are unset so programatically determine build_kernel +if [ -z $build_kernel ] && [ -z $ksrc ]; then + set_build_kernel +fi + +# only programatically search for kernel source if ksrc not set on command line +if [ -z $ksrc ]; then + find_kernel_source +fi + +find_config_file + +if [ ! -z $kconfig ]; then + # if we found the kernel .config file then exit the script based on various + # conditions that depend on the CONFIG_AUXILIARY_BUS string being found + get_config_auxiliary_bus + + if [ -z "$CONFIG_AUXILIARY_BUS" ]; then + msg "CONFIG_AUXILIARY_BUS not found in ${kconfig}." + # CONFIG_AUXILIARY_BUS string was not found, so OOT auxiliary is needed + exit_need_oot_auxiliary + elif [ "$CONFIG_AUXILIARY_BUS" = "1" ]; then + msg "CONFIG_AUXILIARY_BUS=y in ${kconfig}." + # CONFIG_AUXILIARY_BUS=y, so OOT auxiliary is not needed + exit_builtin_auxiliary_enabled + else + msg "" + msg "kernel $build_kernel supports auxiliary bus, but CONFIG_AUXILIARY_BUS" + msg "is not set in ${kconfig}. Rebuild your kernel with" + msg "CONFIG_AUXILIARY_BUS=y" + msg "" + # CONFIG_AUXILIARY_BUS is not "=y", but the string was found, so report + # the failure so it can be used to fail build/install + exit_kconfig_invalid + fi +else + if [ ! -d ${ksrc}/${LINUX_INC_DIR} ] && [ ! -d ${ksrc}/source/${LINUX_INC_DIR} ]; then + echo "${ksrc}/${LINUX_INC_DIR} and ${ksrc}/source/${LINUX_INC_DIR}" + echo "do not exist" + exit_not_found_failure + fi + + # We didn't find a kernel .config file, so check to see if auxiliary_bus.h + # is found in the kernel source include directory + find_aux_bus_inc + + if [ -f "$aux_bus_inc" ]; then + # AUXILIARY_MODULE_PREFIX is defined only in out-of-tree auxiliary bus + if [ $(grep -c AUXILIARY_MODULE_PREFIX $aux_bus_inc) -eq 0 ]; then + msg "in-tree auxiliary_bus.h found at ${ksrc}/${LINUX_INC_DIR}" + # If auxiliary_bus.h is included at ${ksrc} and it isn't our OOT version, + #then don't build OOT auxiliary as part of the driver makefile + exit_builtin_auxiliary_enabled + else + msg "OOT auxiliary_bus.h found at ${ksrc}/${LINUX_INC_DIR}" + # If auxiliary bus is included at ${ksrc} and it is our OOT version, then + # build OOT auxiliary as part of the driver makefile + exit_need_oot_auxiliary + fi + else + msg "auxiliary_bus.h not found at ${ksrc}/${LINUX_INC_DIR}" + exit_need_oot_auxiliary + fi +fi diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/Makefile b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/Makefile new file mode 100644 index 0000000..4bf8cbd --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/Makefile @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +# ccflags-y += -DCONFIG_NOSIM_DEBUG +obj-m := crete_pnic.o +crete_pnic-objs := crete_nic_main.o \ + crete_nic_io.o \ + crete_nic.o \ + crete_nic_ethtool.o +KERNELDIR ?= /lib/modules/$(shell uname -r)/build/ + +################# +# Auxiliary Bus # +# ################# + +AUX_BUS_SYM := /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers + +ifeq ($(wildcard $(AUX_BUS_SYM)),) +$(info ${AUX_BUS_SYM} File does not exist) +else +KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers +endif + +KBUILD_EXTRA_SYMBOLS += $(PWD)/../crete-core/Module.symvers + +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + @\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic.c new file mode 100644 index 0000000..69224f4 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * JaguarMicro virtual dev driver for virtio dataplane offloading + * + * Copyright (C) 2022 JaguarMicro Corporation. + * + * Author: Angus Chen + * + */ +#include +#include "../crete-core/crete_cmd_if.h" +#include "crete_nic.h" + +void crete_vnic_priv_cleanup(struct crete_vnic_priv *priv) +{ + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev; + struct crete_net_common_cfg *netcfg = &priv->net_cfg; + + if (!priv->coredev) + return; + + pdev = core_dev->pdev; + dev_err(&pdev->dev, "enter crete_priv_cleanup\n"); + + kfree(netcfg->mc_list); + netcfg->mc_list = NULL; + + kfree(netcfg->uc_list); + netcfg->uc_list = NULL; + +// memset(priv, 0, sizeof(*priv)); + dev_err(&pdev->dev, "exit crete_priv_cleanup\n"); +} + +int crete_nic_set_device_type(struct crete_core_dev *core_dev, enum crete_dev_type op) +{ + + int ret; + struct pci_dev *pdev = core_dev->pdev; + u32 devtype = 0; + + ret = crete_set_dev_type(core_dev, op); + if (ret) { + dev_err(&pdev->dev, + "Failed to set device type %x, set cmd error\n", op); + return -EINVAL; + } + ret = crete_get_dev_type(core_dev, &devtype); + if (ret) { + dev_err(&pdev->dev, "set dev type failed\n"); + goto out; + } + + if (devtype != op) { + dev_err(&pdev->dev, + " dev type not right check failed. dev type %x\n", op); + goto out; + } + + return ret; +out: + return -EINVAL; +} + +u64 crete_net_get_supported_features(struct crete_core_dev *core_dev, + enum crete_feature_opcode op) +{ + + struct pci_dev *pdev = core_dev->pdev; + u64 dev_features; + u64 ret; + + ret = crete_cmd_get_features(core_dev, op, &dev_features); + if (ret) { + dev_err(&pdev->dev, "get device features is error\n"); + ret = -EINVAL; + } + core_dev->cap.hw_features = dev_features; + dev_info(&pdev->dev, "device supported features[0x%llx]\n", + core_dev->cap.hw_features); + return ret; +} + +u64 crete_net_get_max_supported_vqs(struct crete_core_dev *core_dev) +{ + int ret; + u16 max_queue_size; + u8 max_qp_num; + u8 ctrl_queue_size; + struct pci_dev *pdev = core_dev->pdev; + + ret = + crete_get_qp_cap(core_dev, &max_queue_size, &max_qp_num, + &ctrl_queue_size); + if (ret) { + dev_err(&pdev->dev, "%s is error\n", __func__); + return -EINVAL; + } + core_dev->cap.qpcap.ctrl_queue_size = ctrl_queue_size; + core_dev->cap.qpcap.max_qp_num = max_qp_num; + core_dev->cap.qpcap.max_queue_size = max_queue_size; + + dev_info(&pdev->dev, + "crete vqs: ctl_qlen[0x%x] ioqlen[0x%x] maxvqs[%d]\n", + ctrl_queue_size, max_queue_size, max_qp_num); + return 0; +} + +//todo: keyi cmd_if + +int crete_trim_rings(struct crete_core_dev *cdev) +{ + int cpunums = num_online_cpus(); + int maxqpnums = cdev->cap.qpcap.max_qp_num; + + if (maxqpnums > CRETE_VNIC_MAX_QUEUES) { + cdev->cap.qpcap.max_qp_num = CRETE_VNIC_MAX_QUEUES; + crete_err(cdev->device, "max qp greater than %d\n", + CRETE_VNIC_MAX_QUEUES); + } + cdev->ring_size = min(cpunums, maxqpnums); + if (!cdev->ring_size) { + crete_err(cdev->device, "ring size zero not right\n"); + return -1; + } + return 0; +} //todo: keyi cmd_if + +int crete_vnic_priv_init(struct crete_vnic_priv *priv, + struct net_device *netdev, + struct crete_core_dev *core_dev) +{ + int mem_size = (CRETE_MAX_UC_ADDRS - 1) * ETH_ALEN; + struct crete_net_common_cfg *netcfg = &priv->net_cfg; + int rc = 0; + + priv->coredev = core_dev; + priv->netdev = netdev; + + netcfg->uc_list = kmalloc(mem_size, GFP_KERNEL); + if (!netcfg->uc_list) { + rc = -ENOMEM; + goto err_uc_list_alloc; + } + netcfg->mc_list_size = CRETE_MAX_MC_ADDRS * ETH_ALEN; + netcfg->mc_list = kmalloc(netcfg->mc_list_size, GFP_KERNEL); + if (!netcfg->mc_list) { + rc = -ENOMEM; + goto err_mc_list_alloc; + } + + return 0; +err_mc_list_alloc: + kfree(netcfg->uc_list); + netcfg->uc_list = NULL; +err_uc_list_alloc: + return rc; +} //todo: keyi cmd_if + +struct net_device *crete_vnic_create_netdev(struct crete_core_dev *coredev) +{ + struct net_device *netdev; + unsigned int txqs, rxqs; + struct crete_vnic_priv *priv; + struct pci_dev *pdev = coredev->pdev; + int err; + + txqs = coredev->ring_size; + rxqs = coredev->ring_size; + /* crete netdevice with max qp number */ + netdev = alloc_etherdev_mqs(sizeof(struct crete_vnic_priv), txqs, rxqs); + if (!netdev) { + dev_err(&pdev->dev, "alloc_etherdev_mqs() failed\n"); + return NULL; + } + priv = netdev_priv(netdev); + coredev->netdev = netdev; + err = crete_vnic_priv_init(priv, netdev, coredev); + if (err) { + dev_err(&pdev->dev, "crete_vnic_priv_init failed\n"); + goto err_priv_init; + } + + netif_tx_disable(netdev); + return netdev; + +err_priv_init: + free_netdev(netdev); + return NULL; +} //todo: keyi cmd_if + +void crete_build_common_netdev(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + + netdev->watchdog_timeo = 5 * HZ; + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + SET_NETDEV_DEV(netdev, &pdev->dev); + strcpy(netdev->name, "eth%d"); +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic.h new file mode 100644 index 0000000..ff17e9a --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic.h @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * JaguarMicro virt device driver for virtio dataplane offloading + * + * Copyright (C) 2020 JaguarMicro Corporation. + */ + +#ifndef _CRETE_NIC_H_ +#define _CRETE_NIC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../crete-core/crete_cmd.h" +#include "../crete-core/crete_cmd_if.h" +/* Max 8 data queue pairs(16 queues) and one control vq for now. */ +#define CRETE_VNIC_MAX_QUEUES 17 +#define CRETE_VNIC_QUEUES_NOCTRL 16 + +#define CRETE_VNIC_QUEUE_ALIGNMENT PAGE_SIZE +/*attention pls ,it's the depth of queue*/ +#define CRETE_VNIC_QUEUE_SIZE_MAX 512 +#define CRETE_VNIC_QUEUE_SIZE_MIN 64 +#define CRETE_VNIC_MSI_CONFIG_OFF 0 +#define CRETE_VNIC_MSI_QUEUE_OFF 1 +#define CRETE_VNIC_PCI_MAX_RESOURCE 6 +#define VHOST_F_LOG_ALL 26 +#define VHOST_ACCESS_WO 0x2 +#define DEBUG + +#define VIRTIO_NET_CONFIG_OFFSET_MAC offsetof(struct virtio_net_config, mac) +#define VIRTIO_NET_CONFIG_OFFSET_MTU offsetof(struct virtio_net_config, mtu) + +/**********************************vnic add******************************************/ +#define CRETE_VNIC_MQ_MAX 17 + +#define CRETE_VNIC_AUX_DEV_NAME "crete_core.nic" +#define CRETE_NIC_DRV_NAME "crete_pnic" +/* FIXME: MTU in config. */ +#define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) +#define GOOD_COPY_LEN 128 + +#define VIRTNET_RX_PAD (NET_IP_ALIGN + NET_SKB_PAD) + +/* Amount of XDP headroom to prepend to packets for use by xdp_adjust_head */ +#define VIRTIO_XDP_HEADROOM 256 + +/* RX packet size EWMA. The average packet size is used to determine the packet + * buffer size when refilling RX rings. As the entire RX ring may be refilled + * at once, the weight is chosen so that the EWMA will be insensitive to short- + * term, transient changes in packet size. + */ +DECLARE_EWMA(pkt_len, 0, 64) +#define GUEST_OFFLOAD_GRO_HW_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \ + (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \ + (1ULL << VIRTIO_NET_F_GUEST_ECN) | \ + (1ULL << VIRTIO_NET_F_GUEST_UFO)) + +struct crete_vnic_stat_desc { + char desc[ETH_GSTRING_LEN]; + size_t offset; +}; + +struct crete_vnic_sq_stats { + struct u64_stats_sync syncp; + u64 packets; + u64 bytes; + u64 xdp_tx; + u64 xdp_tx_drops; + u64 kicks; +}; + +struct crete_vnic_rq_stats { + struct u64_stats_sync syncp; + u64 packets; + u64 bytes; + u64 drops; + u64 xdp_packets; + u64 xdp_tx; + u64 xdp_redirects; + u64 xdp_drops; + u64 kicks; +}; + +#define CRETE_VNIC_SQ_STAT(m) offsetof(struct crete_vnic_sq_stats, m) +#define CRETE_VNIC_RQ_STAT(m) offsetof(struct crete_vnic_rq_stats, m) + +struct send_queue { + /* Virtqueue associated with this send _queue */ + struct virtqueue *vq; + + /* TX: fragments + linear part + virtio header */ + struct scatterlist sg[MAX_SKB_FRAGS + 2]; + + /* Name of the send queue: output.$index */ + char name[40]; + + struct crete_vnic_sq_stats stats; + + struct napi_struct napi; +}; + +/* Internal representation of a receive virtqueue */ +struct receive_queue { + /* Virtqueue associated with this receive_queue */ + struct virtqueue *vq; + + struct napi_struct napi; + + struct bpf_prog __rcu *xdp_prog; + + struct crete_vnic_rq_stats stats; + + /* Chain pages by the private ptr. */ + struct page *pages; + + /* Average packet length for mergeable receive buffers. */ + struct ewma_pkt_len mrg_avg_pkt_len; + + /* Page frag for packet buffer allocation. */ + struct page_frag alloc_frag; + + /* RX: fragments + linear part + virtio header */ + struct scatterlist sg[MAX_SKB_FRAGS + 2]; + + /* Min single buffer size for mergeable buffers case. */ + unsigned int min_buf_len; + + /* Name of this receive queue: input.$index */ + char name[40]; +}; + +struct crete_vnic_msix_info { + struct virtqueue *vq; + int qid; + /* MSI-X vector (or none) */ + unsigned int msix_vector; + unsigned int irq; + bool ready; + char msix_name[256]; +}; + +struct crete_net_common_cfg { + u32 rx_mask; + u16 uc_filter_count; + u8 *uc_list; + u8 *mc_list; + int mc_list_size; + int mc_list_count; + __u16 vportid; + __u8 mac[ETH_ALEN]; + __u16 mtu; + __le32 speed; + /* + * 0x00 - half duplex + * 0x01 - full duplex + * Any other value stands for unknown. + */ + __u8 duplex; + /* maximum size of RSS key */ + __u8 rss_max_key_size; + /* maximum number of indirection table entries */ + __le16 rss_max_indirection_table_length; + /* bitmask of supported VIRTIO_NET_RSS_HASH_ types */ + __le32 supported_hash_types; + __le16 vlanid; +}; + +struct crete_vnic_priv { + struct virtio_device vdev; + struct crete_core_dev *coredev; + struct net_device *netdev; + struct send_queue *sq; + struct receive_queue *rq; + unsigned int status; + u16 max_queue_pairs; + u16 curr_queue_pairs; + bool big_packets; + bool mergeable_rx_bufs; + bool any_header_sg; + u8 hdr_len; + struct delayed_work refill; + bool refill_enabled; + spinlock_t refill_lock; + bool affinity_hint_set; + struct hlist_node node; + struct hlist_node node_dead; + unsigned long guest_offloads; + unsigned long guest_offloads_capable; + spinlock_t lock; + struct crete_vnic_msix_info msix_info[CRETE_VNIC_MQ_MAX]; + struct crete_net_common_cfg net_cfg; + struct crete_nb cnb; + struct work_struct set_rx_mode_work; + struct workqueue_struct *wq; +}; + +/*******************************************************************************/ +enum crete_net_status { + CRETE_NET_DEV_STARTUP, + CRETE_NET_DEV_FEATURE_OK, + CRETE_NET_DEV_DEV_OK, + CRETE_NET_DEV_STOPPED +}; + +#define CRETE_RX_SEQ 0 +#define CRETE_TX_SEQ 1 + +int crete_nic_set_hwstatus(struct crete_core_dev *core_dev, u8 status); +int crete_nic_set_device_type(struct crete_core_dev *core_dev, + enum crete_dev_type op); +int crete_trim_rings(struct crete_core_dev *core_dev); +struct net_device *crete_vnic_create_netdev(struct crete_core_dev *core_dev); +void crete_build_common_netdev(struct net_device *netdev); +void crete_vnic_destroy_netdev(struct net_device *netdev); +void crete_vnic_priv_cleanup(struct crete_vnic_priv *priv); +u64 crete_net_get_max_supported_vqs(struct crete_core_dev *core_dev); +u64 crete_net_get_supported_features(struct crete_core_dev *core_dev, + enum crete_feature_opcode op); +#endif /* _CRETE_NIC_H_ */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_ethtool.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_ethtool.c new file mode 100644 index 0000000..ec32b99 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_ethtool.c @@ -0,0 +1,516 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* A network driver using virtio. + * + * Copyright 2007 Rusty Russell IBM Corporation + */ +//#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crete_nic.h" +#include "crete_nic_io.h" +#include +#include "../crete-core/crete_fw_update.h" + +#define CRETE_VNIC_DRIVER_VERSION "crete-vnic-1.0" +/******************net tools****************************/ +static void crete_vnic_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + + strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); + + snprintf(info->fw_version, sizeof(info->fw_version), + "%d.%d.%d.%d", fw_ver_maj(core_dev), + fw_ver_min(core_dev), fw_ver_sub(core_dev), fw_ver_rev(core_dev)); + + strlcpy(info->version, CRETE_VNIC_DRIVER_VERSION, + sizeof(info->version)); + strlcpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info)); +} + +static u32 crete_vnic_get_link(struct net_device *netdev) +{ + //struct crete_vnic_priv *vnic_priv = netdev_priv(netdev); + //struct crete_core_dev *core_dev =vnic_priv->coredev; + /* If the link is not reported up to netdev, interrupts are disabled, + * and so the physical link state may have changed since we last + * looked. Set get_link_status to make sure that the true link + * state is interrogated, rather than pulling a cached and possibly + * stale link state from the driver. + */ + if (!netif_carrier_ok(netdev)) { + /*todo to vdev get link status */ + return 0; + } + return 1; +} + +/* + * about the anolis 5.10.134-14 kernel version + * auxliary define with return int value + */ +#if defined(SNIC_ANOLIS_VERSION14) || !defined(CONFIG_ETHTOOL_EXTEND_RINGPARAM) +static void crete_vnic_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + + ring->rx_max_pending = virtqueue_get_vring_size(vnic_priv->rq[0].vq); + ring->tx_max_pending = virtqueue_get_vring_size(vnic_priv->sq[0].vq); + ring->rx_pending = ring->rx_max_pending; + ring->tx_pending = ring->tx_max_pending; +} + +#else + +static void crete_vnic_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring, + struct kernel_ethtool_ringparam + *kernel_ring, + struct netlink_ext_ack *extack) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + + ring->rx_max_pending = virtqueue_get_vring_size(vnic_priv->rq[0].vq); + ring->tx_max_pending = virtqueue_get_vring_size(vnic_priv->sq[0].vq); + ring->rx_pending = ring->rx_max_pending; + ring->tx_pending = ring->tx_max_pending; +} + +#endif + +static void crete_vnic_get_channels(struct net_device *dev, + struct ethtool_channels *channels) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + + channels->combined_count = vnic_priv->curr_queue_pairs; + channels->max_combined = vnic_priv->max_queue_pairs; + channels->max_other = 0; + channels->rx_count = 0; + channels->tx_count = 0; + channels->other_count = 0; +} + +/* TODO: Eliminate OOO packets during switching */ +static int crete_vnic_set_channels(struct net_device *dev, + struct ethtool_channels *channels) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + u16 queue_pairs = channels->combined_count; + int err; + + /* We don't support separate rx/tx channels. + * We don't allow setting 'other' channels. + */ + if (channels->rx_count || channels->tx_count || channels->other_count) + return -EINVAL; + + if (queue_pairs > vnic_priv->max_queue_pairs || queue_pairs == 0) + return -EINVAL; + + err = __crete_vnic_set_queues(dev, queue_pairs); + if (err) + goto err; + + netif_set_real_num_tx_queues(dev, queue_pairs); + netif_set_real_num_rx_queues(dev, queue_pairs); + err: + return err; +} + +int crete_vnic_ethtool_flash_device(struct crete_vnic_priv *vnic_priv, + struct ethtool_flash *flash) +{ + struct crete_core_dev *cdev = vnic_priv->coredev; + struct net_device *dev = vnic_priv->netdev; + const struct firmware *fw; + int err; + + if (flash->region != ETHTOOL_FLASH_ALL_REGIONS) + return -EOPNOTSUPP; + + err = request_firmware_direct(&fw, flash->data, &dev->dev); + if (err) + return err; + + dev_hold(dev); + rtnl_unlock(); + + err = crete_firmware_flash(cdev, fw, NULL, CRETE_FWU_ETHTOOL); + release_firmware(fw); + + rtnl_lock(); + dev_put(dev); + return err; +} + +static int crete_vnic_flash_device(struct net_device *dev, + struct ethtool_flash *flash) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + + return crete_vnic_ethtool_flash_device(vnic_priv, flash); +} + +struct ptys2ethtool_config { + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised); +}; + +static +struct ptys2ethtool_config ptys2ethtool_table[CRETE_LINK_MODES_CAP_BIT]; + +#define CRETE_BUILD_PTYS2ETHTOOL_CONFIG(reg_, table, ...) \ + ({ \ + struct ptys2ethtool_config *cfg; \ + const unsigned int modes[] = { __VA_ARGS__ }; \ + unsigned int i, bit, idx; \ + cfg = &table[reg_]; \ + bitmap_zero(cfg->supported, \ + __ETHTOOL_LINK_MODE_MASK_NBITS); \ + bitmap_zero(cfg->advertised, \ + __ETHTOOL_LINK_MODE_MASK_NBITS); \ + for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \ + bit = modes[i] % 64; \ + idx = modes[i] / 64; \ + __set_bit(bit, &cfg->supported[idx]); \ + __set_bit(bit, &cfg->advertised[idx]); \ + } \ + }) + +void crete_build_ptys2ethtool_map(void) +{ + memset(ptys2ethtool_table, 0, sizeof(ptys2ethtool_table)); + CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_10GBASE_BIT, ptys2ethtool_table, + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT); + CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_25GBASE_BIT, ptys2ethtool_table, + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT); + CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_40GBASE_BIT, ptys2ethtool_table, + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT); + CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_50GBASE_BIT, ptys2ethtool_table, + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT); + CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_100GBASE_BIT, ptys2ethtool_table, + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT); + CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_200GBASE_BIT, ptys2ethtool_table, + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, + ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT, + ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT, + ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT); + CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_400GBASE_BIT, ptys2ethtool_table, + ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, + ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT, + ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT, + ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, + ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT, + ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT, + ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT); +} + +u16 crete_port_speed2linkmode(u32 speed) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(crete_link_speed); ++i) { + if (crete_link_speed[i] == speed) + return i; + } + return 0; +} + +int crete_ethtool_set_link_ksettings(struct crete_vnic_priv *vnic_priv, + const struct ethtool_link_ksettings *link_ksettings) +{ + struct crete_core_dev *cdev = vnic_priv->coredev; + const struct ethtool_link_settings *base = &link_ksettings->base; + struct net_device *dev = vnic_priv->netdev; + struct crete_speed_duplex sd_current = {0}; + u16 change_bit = 0; + u16 link_mode; + int ret; + + if (base->autoneg == AUTONEG_ENABLE) { + netdev_err(dev, "Autonegotiation is not supported!\n"); + return -EINVAL; + } + + if (base->duplex != DUPLEX_FULL) { + netdev_err(dev, "Only full duplex mode is supported!\n"); + return -EINVAL; + } + + link_mode = crete_port_speed2linkmode(base->speed); + if (link_mode >= CRETE_LINK_MODES_NUMBER || link_mode < CRETE_10GBASE) { + netdev_err(dev, "speed parameter is illeagl.\n"); + return -EINVAL; + } + + ret = crete_get_port_speed_duplex(cdev, &sd_current); + if (ret) { + netdev_err(dev, "Failed to get current speed and duplex mode!\n"); + return ret; + } + + if (sd_current.speed == link_mode && sd_current.duplex == base->duplex) { + netdev_info(dev, "Speed and duplex mode are already set to the requested values.\n"); + return 0; + } + + change_bit |= (sd_current.speed != link_mode) ? LINK_SPEED_OP_BIT : 0; + change_bit |= (sd_current.duplex != base->duplex) ? DUPLEX_MODE_OP_BIT : 0; + + if (!netif_running(dev)) { + netdev_err(dev, "Network interface is not running. Cannot change settings.\n"); + return -EINVAL; + } + + ret = crete_set_port_speed_duplex(cdev, link_mode, base->duplex, change_bit); + if (ret) { + netdev_err(dev, "Failed to set speed and duplex mode!\n"); + return ret; + } + + netdev_info(dev, "Speed set to %d Mbps, duplex mode set to full.\n", base->speed); + + return 0; +} + +static int crete_vnic_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *link_ksettings) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + + return crete_ethtool_set_link_ksettings(vnic_priv, link_ksettings); +} + +static void ptys2ethtool_adver_link(u32 eth_speed_cap, + u8 tx_pause, u8 rx_pause, struct ethtool_link_ksettings *link_ksettings) +{ + unsigned long speed_cap = eth_speed_cap; + unsigned long *advertising_modes = link_ksettings->link_modes.advertising; + int speed; + + for_each_set_bit(speed, &speed_cap, CRETE_LINK_MODES_CAP_BIT) + bitmap_or(advertising_modes, advertising_modes, + ptys2ethtool_table[speed].advertised, + __ETHTOOL_LINK_MODE_MASK_NBITS); + if (rx_pause) + ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause); + if (tx_pause ^ rx_pause) + ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause); +} + +static void ptys2ethtool_supported_link(u32 eth_speed_cap, + struct ethtool_link_ksettings *link_ksettings) +{ + unsigned long speed_cap = eth_speed_cap; + unsigned long *supported_modes = link_ksettings->link_modes.supported; + int speed; + + for_each_set_bit(speed, &speed_cap, CRETE_LINK_MODES_CAP_BIT) + bitmap_or(supported_modes, supported_modes, + ptys2ethtool_table[speed].supported, + __ETHTOOL_LINK_MODE_MASK_NBITS); + ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause); +} + +static int get_fec_supported_advertised(struct crete_core_dev *cdev, + struct ethtool_link_ksettings *link_ksettings) +{ + u16 active_fec; + u16 eth_fec_cap; + u8 fec; + int err; + unsigned long fec_cap; + + err = crete_get_fec_mode(cdev, &active_fec, ð_fec_cap); + if (err) + return err; + fec_cap = eth_fec_cap; + for_each_set_bit(fec, &fec_cap, ARRAY_SIZE(crete_fec_2_ethtool_bit)) + __set_bit(crete_fec_2_ethtool_bit[fec], link_ksettings->link_modes.supported); + + if (active_fec <= CRETE_FEC_LLRS) + __set_bit(crete_fec_2_ethtool_bit[active_fec], + link_ksettings->link_modes.advertising); + + return 0; +} + +static int crete_vnic_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *link_ksettings) +{ + struct crete_speed_duplex sd = {0}; + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *cdev = vnic_priv->coredev; + u8 rx_pause = 0; + u8 tx_pause = 0; + int ret = 0; + + link_ksettings->base.speed = SPEED_UNKNOWN; + link_ksettings->base.duplex = DUPLEX_UNKNOWN; + ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); + ethtool_link_ksettings_zero_link_mode(link_ksettings, supported); + + crete_get_pfc_enable(cdev, &rx_pause, &tx_pause); + + ret = crete_get_port_speed_duplex(cdev, &sd); + if (ret) { + netdev_err(dev, "Failed to get speed and duplex mode!\n"); + ret = 0; + } + if (sd.speed >= CRETE_10GBASE && sd.speed < CRETE_LINK_MODES_NUMBER) + link_ksettings->base.speed = crete_link_speed[sd.speed]; + + if (sd.duplex >= CRETE_HALF_DUPLEX && sd.duplex < CRETE_DUPLEX_MAX) + link_ksettings->base.duplex = crete_link_duplex[sd.duplex]; + + netdev_info(dev, "Speed Get speed[%d] speed_cap[0x%x].\n", sd.speed, sd.speed_cap); + ptys2ethtool_supported_link(sd.speed_cap, link_ksettings); + ptys2ethtool_adver_link(sd.speed_cap, tx_pause, rx_pause, link_ksettings); + link_ksettings->base.port = PORT_FIBRE; + + ret = get_fec_supported_advertised(cdev, link_ksettings); + if (ret) { + netdev_err(dev, "%s: FEC caps query failed: %d\n", + __func__, ret); + ret = 0; /* don't fail caps query because of FEC error */ + } + + ethtool_link_ksettings_add_link_mode(link_ksettings, supported, FIBRE); + ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, FIBRE); + + return ret; +} + +static int crete_vnic_set_fecparam(struct net_device *dev, + struct ethtool_fecparam *fecparam) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *cdev = vnic_priv->coredev; + + unsigned long fec_bitmap; + u16 fec_policy = 0; + + bitmap_from_arr32(&fec_bitmap, &fecparam->fec, sizeof(fecparam->fec) * BITS_PER_BYTE); + if (bitmap_weight(&fec_bitmap, ETHTOOL_FEC_LLRS_BIT + 1) > 1) + return -EOPNOTSUPP; + + switch (fecparam->fec) { + case ETHTOOL_FEC_OFF: + fec_policy = CRETE_FEC_OFF; + break; + case ETHTOOL_FEC_RS: + fec_policy = CRETE_FEC_RS; + break; + case ETHTOOL_FEC_BASER: + fec_policy = CRETE_FEC_BASER; + break; + default: + netdev_err(dev, "Unsupported FEC mode: %d\n", fecparam->fec); + return -EINVAL; + } + return crete_set_fec_mode(cdev, fec_policy); +} + +static u32 crete_fec_cap_to_ethtool_fec(u16 fec_cap) +{ + u32 ethtool_fec = 0; + + if (fec_cap & BIT(CRETE_FEC_OFF)) + ethtool_fec |= ETHTOOL_FEC_OFF; + + if (fec_cap & BIT(CRETE_FEC_AUTO)) + ethtool_fec |= ETHTOOL_FEC_AUTO; + + if (fec_cap & BIT(CRETE_FEC_RS)) + ethtool_fec |= ETHTOOL_FEC_RS; + + if (fec_cap & BIT(CRETE_FEC_BASER)) + ethtool_fec |= ETHTOOL_FEC_BASER; + + if (fec_cap & BIT(CRETE_FEC_LLRS)) + ethtool_fec |= ETHTOOL_FEC_LLRS; + + return ethtool_fec; +} + +static int crete_vnic_get_fecparam(struct net_device *dev, + struct ethtool_fecparam *fecparam) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *cdev = vnic_priv->coredev; + u16 fec_active; + u16 fec_cap; + int err; + + err = crete_get_fec_mode(cdev, &fec_active, &fec_cap); + if (err) + return err; + + fecparam->active_fec = crete_fec_2_ethtool[fec_active]; + + fecparam->fec = crete_fec_cap_to_ethtool_fec(fec_cap); + + return 0; +} + +static const struct ethtool_ops crete_vnic_ethtool_ops = { + .get_drvinfo = crete_vnic_get_drvinfo, + .get_link = crete_vnic_get_link, + .get_ringparam = crete_vnic_get_ringparam, + .get_strings = crete_vnic_get_strings, + .get_sset_count = crete_vnic_get_sset_count, + .get_ethtool_stats = crete_vnic_get_ethtool_stats, + .get_channels = crete_vnic_get_channels, + .set_channels = crete_vnic_set_channels, + .flash_device = crete_vnic_flash_device, + .get_link_ksettings = crete_vnic_get_link_ksettings, + .set_link_ksettings = crete_vnic_set_link_ksettings, + .get_fecparam = crete_vnic_get_fecparam, + .set_fecparam = crete_vnic_set_fecparam, +}; + +void crete_set_ethtool_ops(struct net_device *netdev) +{ + netdev->ethtool_ops = &crete_vnic_ethtool_ops; +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_ethtool.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_ethtool.h new file mode 100644 index 0000000..3c27f37 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_ethtool.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CRETE_NIC_ETHTOOL_H_ +#define _CRETE_NIC_ETHTOOL_H_ +void crete_set_ethtool_ops(struct net_device *netdev); +void crete_build_ptys2ethtool_map(void); +#endif /* _CRETE_NIC_ETHTOOL_H_*/ + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_io.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_io.c new file mode 100644 index 0000000..2b76563 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_io.c @@ -0,0 +1,1765 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* A network driver using virtio. + * + * Copyright 2007 Rusty Russell IBM Corporation + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crete_nic.h" + +#define CRETE_VNIC_XDP_HEADROOM 256 +#define MRG_CTX_HEADER_SHIFT 22 + +static const struct crete_vnic_stat_desc crete_vnic_sq_stats_desc[] = { + {"packets", CRETE_VNIC_SQ_STAT(packets)}, + {"bytes", CRETE_VNIC_SQ_STAT(bytes)}, + {"xdp_tx", CRETE_VNIC_SQ_STAT(xdp_tx)}, + {"xdp_tx_drops", CRETE_VNIC_SQ_STAT(xdp_tx_drops)}, + {"kicks", CRETE_VNIC_SQ_STAT(kicks)}, +}; + +static const struct crete_vnic_stat_desc crete_vnic_rq_stats_desc[] = { + {"packets", CRETE_VNIC_RQ_STAT(packets)}, + {"bytes", CRETE_VNIC_RQ_STAT(bytes)}, + {"drops", CRETE_VNIC_RQ_STAT(drops)}, + {"xdp_packets", CRETE_VNIC_RQ_STAT(xdp_packets)}, + {"xdp_tx", CRETE_VNIC_RQ_STAT(xdp_tx)}, + {"xdp_redirects", CRETE_VNIC_RQ_STAT(xdp_redirects)}, + {"xdp_drops", CRETE_VNIC_RQ_STAT(xdp_drops)}, + {"kicks", CRETE_VNIC_RQ_STAT(kicks)}, +}; + +static const char crete_vnic_phy_stat_desc[][ETH_GSTRING_LEN] = { + "rx_bytes_phy", + "rx_packets_phy", + "tx_bytes_phy", + "tx_packets_phy" +}; + +#define CRETE_VNIC_SQ_STATS_LEN ARRAY_SIZE(crete_vnic_sq_stats_desc) +#define CRETE_VNIC_RQ_STATS_LEN ARRAY_SIZE(crete_vnic_rq_stats_desc) + +#define CRETE_VNIC_PHY_STATS_LEN ARRAY_SIZE(crete_vnic_phy_stat_desc) + +struct padded_vnet_hdr { + struct virtio_net_hdr_mrg_rxbuf hdr; + /* + * hdr is in a separate sg buffer, and data sg buffer shares same page + * with this header sg. This padding makes next sg 16 byte aligned + * after the header. + */ + char padding[4]; +}; + +static int vq2rxq(struct virtqueue *vq) +{ + return vq->index / 2; +} + +static int vq2txq(struct virtqueue *vq) +{ + return (vq->index - 1) / 2; +} + +static unsigned int mergeable_ctx_to_headroom(void *mrg_ctx) +{ + return (unsigned long)mrg_ctx >> MRG_CTX_HEADER_SHIFT; +} + +static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx) +{ + return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1); +} + +static inline struct virtio_net_hdr_mrg_rxbuf *skb_to_crete_vnic_hdr(struct + sk_buff + *skb) +{ + return (struct virtio_net_hdr_mrg_rxbuf *)skb->cb; +} + +static void crete_vnic_give_pages(struct receive_queue *rq, struct page *page) +{ + struct page *end; + + /* Find end of list, sew whole thing into vnic_priv->rq.pages. */ + for (end = page; end->private; end = (struct page *)end->private) + end->private = (unsigned long)rq->pages; + rq->pages = page; +} + +/* Called from bottom half context */ +static struct sk_buff *crete_vnic_page_to_skb(struct crete_vnic_priv *vnic_priv, + struct receive_queue *rq, + struct page *page, + unsigned int offset, + unsigned int len, + unsigned int truesize, + bool hdr_valid, + unsigned int metasize) +{ + struct sk_buff *skb; + struct virtio_net_hdr_mrg_rxbuf *hdr; + unsigned int copy, hdr_len, hdr_padded_len; + char *p; + + p = page_address(page) + offset; + + /* copy small packet so we can reuse these pages for small data */ + skb = napi_alloc_skb(&rq->napi, GOOD_COPY_LEN); + if (unlikely(!skb)) + return NULL; + + hdr = skb_to_crete_vnic_hdr(skb); + + hdr_len = vnic_priv->hdr_len; + if (vnic_priv->mergeable_rx_bufs) + hdr_padded_len = sizeof(*hdr); + else + hdr_padded_len = sizeof(struct padded_vnet_hdr); + if (hdr_valid) + memcpy(hdr, p, hdr_len); + len -= hdr_len; + offset += hdr_padded_len; + p += hdr_padded_len; + + /* Copy all frame if it fits skb->head, otherwise + * we let virtio_net_hdr_to_skb() and GRO pull headers as needed. + */ + if (len <= skb_tailroom(skb)) + copy = len; + else + copy = ETH_HLEN + metasize; + skb_put_data(skb, p, copy); + + if (metasize) { + __skb_pull(skb, metasize); + skb_metadata_set(skb, metasize); + } + + len -= copy; + offset += copy; + + if (vnic_priv->mergeable_rx_bufs) { + if (len) + skb_add_rx_frag(skb, 0, page, offset, len, truesize); + else + put_page(page); + return skb; + } + + /* + * Verify that we can indeed put this data into a skb. + * This is here to handle cases when the device erroneously + * tries to receive more than is possible. This is usually + * the case of a broken device. + */ + if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) { + net_dbg_ratelimited("%s: too much data\n", skb->dev->name); + dev_kfree_skb(skb); + return NULL; + } + BUG_ON(offset >= PAGE_SIZE); + while (len) { + unsigned int frag_size = min((unsigned int)PAGE_SIZE - offset, len); + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, + frag_size, truesize); + len -= frag_size; + page = (struct page *)page->private; + offset = 0; + } + + if (page) + crete_vnic_give_pages(rq, page); + + return skb; +} + +/****************net rx************************************/ + +static void virtqueue_napi_schedule(struct napi_struct *napi, + struct virtqueue *vq) +{ + if (napi_schedule_prep(napi)) { + virtqueue_disable_cb(vq); + __napi_schedule(napi); + } +} + +static void virtqueue_napi_complete(struct napi_struct *napi, + struct virtqueue *vq, int processed) +{ + int opaque; + + opaque = virtqueue_enable_cb_prepare(vq); + if (napi_complete_done(napi, processed)) { + if (unlikely(virtqueue_poll(vq, opaque))) + virtqueue_napi_schedule(napi, vq); + } else { + virtqueue_disable_cb(vq); + } +} + +static void crete_vnic_napi_enable(struct virtqueue *vq, + struct napi_struct *napi) +{ + napi_enable(napi); + + /* If all buffers were filled by other side before we napi_enabled, we + * won't get another interrupt, so process any outstanding packets now. + * Call local_bh_enable after to trigger softIRQ processing. + */ + local_bh_disable(); + virtqueue_napi_schedule(napi, vq); + local_bh_enable(); +} + +static void crete_vnic_napi_tx_enable(struct crete_vnic_priv *vnic_priv, + struct virtqueue *vq, + struct napi_struct *napi) +{ + if (!napi->weight) + return; + + /* Tx napi touches cachelines on the cpu handling tx interrupts. Only + * enable the feature if this is likely affine with the transmit path. + */ + if (!vnic_priv->affinity_hint_set) { + napi->weight = 0; + return; + } + + return crete_vnic_napi_enable(vq, napi); +} + +static void crete_vnic_napi_tx_disable(struct napi_struct *napi) +{ + if (napi->weight) + napi_disable(napi); +} + +static unsigned int crete_vnic_get_headroom(struct crete_vnic_priv *vnic_priv) +{ + return 0; +} + +#define MRG_CTX_HEADER_SHIFT 22 +static void *crete_vnic_mergeable_len_to_ctx(unsigned int truesize, + unsigned int headroom) +{ + return (void *)(unsigned long)((headroom << MRG_CTX_HEADER_SHIFT) | + truesize); +} + +static unsigned int crete_vnic_get_mergeable_buf_len(struct receive_queue *rq, struct ewma_pkt_len + *avg_pkt_len, + unsigned int room) +{ + const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + unsigned int len; + + if (room) + return PAGE_SIZE - room; + + len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len), + rq->min_buf_len, PAGE_SIZE - hdr_len); + + return ALIGN(len, L1_CACHE_BYTES); +} + +static int crete_vnic_add_recvbuf_mergeable(struct crete_vnic_priv *vnic_priv, + struct receive_queue *rq, gfp_t gfp) +{ + struct page_frag *alloc_frag = &rq->alloc_frag; + unsigned int headroom = crete_vnic_get_headroom(vnic_priv); + unsigned int tailroom = headroom ? sizeof(struct skb_shared_info) : 0; + unsigned int room = SKB_DATA_ALIGN(headroom + tailroom); + char *buf; + void *ctx; + int err; + unsigned int len, hole; + + /* Extra tailroom is needed to satisfy XDP's assumption. This + * means rx frags coalescing won't work, but consider we've + * disabled GSO for XDP, it won't be a big issue. + */ + len = crete_vnic_get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len, room); + if (unlikely(!skb_page_frag_refill(len + room, alloc_frag, gfp))) + return -ENOMEM; + + buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; + buf += headroom; /* advance address leaving hole at front of pkt */ + get_page(alloc_frag->page); + alloc_frag->offset += len + room; + hole = alloc_frag->size - alloc_frag->offset; + if (hole < len + room) { + /* To avoid internal fragmentation, if there is very likely not + * enough space for another buffer, add the remaining space to + * the current buffer. + */ + len += hole; + alloc_frag->offset += hole; + } + + sg_init_one(rq->sg, buf, len); + ctx = crete_vnic_mergeable_len_to_ctx(len, headroom); + err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp); + if (err < 0) + put_page(virt_to_head_page(buf)); + + return err; +} + +static void crete_vnic_enable_delayed_refill(struct crete_vnic_priv *vnic_priv) +{ + spin_lock_bh(&vnic_priv->refill_lock); + vnic_priv->refill_enabled = true; + spin_unlock_bh(&vnic_priv->refill_lock); +} + +static void crete_vnic_disable_delayed_refill(struct crete_vnic_priv *vnic_priv) +{ + spin_lock_bh(&vnic_priv->refill_lock); + vnic_priv->refill_enabled = false; + spin_unlock_bh(&vnic_priv->refill_lock); +} + +static bool crete_vnic_try_fill_recv(struct crete_vnic_priv *vnic_priv, + struct receive_queue *rq, gfp_t gfp) +{ + int err; + bool oom; + + do { + err = crete_vnic_add_recvbuf_mergeable(vnic_priv, rq, gfp); + oom = err == -ENOMEM; + if (err) + break; + } while (rq->vq->num_free); + if (virtqueue_kick_prepare(rq->vq) && virtqueue_notify(rq->vq)) { + unsigned long flags; + + flags = u64_stats_update_begin_irqsave(&rq->stats.syncp); + rq->stats.kicks++; + u64_stats_update_end_irqrestore(&rq->stats.syncp, flags); + } + return !oom; +} + +void crete_vnic_alloc_recv_buf(struct work_struct *work) +{ + struct crete_vnic_priv *vnic_priv = + container_of(work, struct crete_vnic_priv, refill.work); + bool still_empty; + int i; + + for (i = 0; i < vnic_priv->curr_queue_pairs; i++) { + struct receive_queue *rq = &vnic_priv->rq[i]; + + napi_disable(&rq->napi); + still_empty = + !crete_vnic_try_fill_recv(vnic_priv, rq, GFP_KERNEL); + crete_vnic_napi_enable(rq->vq, &rq->napi); + + /* In theory, this can happen: if we don't get any buffers in + * we will *never* try to fill again. + */ + if (still_empty) + schedule_delayed_work(&vnic_priv->refill, HZ / 2); + } +} + +/***************rx end*****************************************/ + +/**********************tx xmit************************************/ + +static inline int crete_vnic_hdr_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr *hdr, + bool little_endian, + bool has_data_valid, int vlan_hlen) +{ + memset(hdr, 0, sizeof(*hdr)); /* no info leak */ + + if (skb_is_gso(skb)) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + + /* This is a hint as to how much should be linear. */ + hdr->hdr_len = __cpu_to_virtio16(little_endian, + skb_headlen(skb)); + hdr->gso_size = __cpu_to_virtio16(little_endian, + sinfo->gso_size); + if (sinfo->gso_type & SKB_GSO_TCPV4) + hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; + else + return -EINVAL; + if (sinfo->gso_type & SKB_GSO_TCP_ECN) + hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; + } else + hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + hdr->csum_start = __cpu_to_virtio16(little_endian, + skb_checksum_start_offset + (skb) + vlan_hlen); + hdr->csum_offset = + __cpu_to_virtio16(little_endian, skb->csum_offset); + } else if (has_data_valid && skb->ip_summed == CHECKSUM_UNNECESSARY) { + hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; + } + /* else everything is zero */ + return 0; +} + +static int crete_vnic_send_skb(struct send_queue *sq, struct sk_buff *skb) +{ + struct virtio_net_hdr_mrg_rxbuf *hdr; + const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; + struct crete_vnic_priv *vnic_priv = sq->vq->vdev->priv; + int num_sg; + unsigned int hdr_len = vnic_priv->hdr_len; + bool can_push; + + pr_debug("xmit %p %pM\n", skb, dest); + + can_push = vnic_priv->any_header_sg && + !((unsigned long)skb->data & (__alignof__(*hdr) - 1)) && + !skb_header_cloned(skb) && skb_headroom(skb) >= hdr_len; + /* Even if we can, don't push here yet as this would skew + * csum_start offset below. + */ + if (can_push) + hdr = (struct virtio_net_hdr_mrg_rxbuf *)(skb->data - hdr_len); + else + hdr = skb_to_crete_vnic_hdr(skb); + + if (crete_vnic_hdr_from_skb(skb, &hdr->hdr, + virtio_is_little_endian(&vnic_priv->vdev), + false, 0)) + return -EPROTO; + + if (vnic_priv->mergeable_rx_bufs) + hdr->num_buffers = 0; + + sg_init_table(sq->sg, skb_shinfo(skb)->nr_frags + (can_push ? 1 : 2)); + if (can_push) { + __skb_push(skb, hdr_len); + num_sg = skb_to_sgvec(skb, sq->sg, 0, skb->len); + if (unlikely(num_sg < 0)) + return num_sg; + /* Pull header back to avoid skew in tx bytes calculations. */ + __skb_pull(skb, hdr_len); + } else { + sg_set_buf(sq->sg, hdr, hdr_len); + num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len); + if (unlikely(num_sg < 0)) + return num_sg; + num_sg++; + } + return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC); +} + +static void crete_vnic_free_old_tx_skbs(struct send_queue *sq, bool in_napi) +{ + unsigned int len; + unsigned int packets = 0; + unsigned int bytes = 0; + void *ptr; + + while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) { + struct sk_buff *skb = ptr; + + pr_debug("Sent skb %p\n", skb); + bytes += skb->len; + napi_consume_skb(skb, in_napi); + packets++; + } + + /* Avoid overhead when no packets have been processed + * happens when called speculatively from start_xmit. + */ + if (!packets) + return; + + u64_stats_update_begin(&sq->stats.syncp); + sq->stats.bytes += bytes; + sq->stats.packets += packets; + u64_stats_update_end(&sq->stats.syncp); +} + +static netdev_tx_t crete_vnic_dev_queue_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + int qnum = skb_get_queue_mapping(skb); + struct send_queue *sq = &vnic_priv->sq[qnum]; + int err; + struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum); + bool kick = !netdev_xmit_more(); + bool use_napi = sq->napi.weight; + + /* Free up any pending old buffers before queueing new ones. */ + crete_vnic_free_old_tx_skbs(sq, false); + + if (use_napi && kick) + virtqueue_enable_cb_delayed(sq->vq); + + /* timestamp packet in software */ + skb_tx_timestamp(skb); + + /* Try to transmit */ + err = crete_vnic_send_skb(sq, skb); + + /* This should not happen! */ + if (unlikely(err)) { + dev->stats.tx_fifo_errors++; + if (net_ratelimit()) + dev_warn(&dev->dev, + "Unexpected TXQ (%d) queue failure: %d\n", + qnum, err); + dev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + /* Don't wait up for transmitted skbs to be freed. */ + if (!use_napi) { + skb_orphan(skb); + nf_reset_ct(skb); + } + + if (sq->vq->num_free < 2 + MAX_SKB_FRAGS) { + netif_stop_subqueue(dev, qnum); + if (!use_napi && unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { + /* More just got used, free them then recheck. */ + crete_vnic_free_old_tx_skbs(sq, false); + if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) { + netif_start_subqueue(dev, qnum); + virtqueue_disable_cb(sq->vq); + } + } + } + + if (kick || netif_xmit_stopped(txq)) { + if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) { + u64_stats_update_begin(&sq->stats.syncp); + sq->stats.kicks++; + u64_stats_update_end(&sq->stats.syncp); + } + } + + return NETDEV_TX_OK; +} + +/*************************tx end**************************************/ + +static int crete_vnic_open(struct net_device *dev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + int i; + + if (!vnic_priv) { + dev_err(core_dev->device, "vnic info is nuLL\n"); + return -ENOSPC; + } + + crete_vnic_enable_delayed_refill(vnic_priv); + + for (i = 0; i < core_dev->cap.qpcap.max_qp_num; i++) { + if (i < vnic_priv->curr_queue_pairs) + if (!crete_vnic_try_fill_recv + (vnic_priv, &vnic_priv->rq[i], GFP_KERNEL)) + schedule_delayed_work(&vnic_priv->refill, 0); + + crete_vnic_napi_enable(vnic_priv->rq[i].vq, + &vnic_priv->rq[i].napi); + crete_vnic_napi_tx_enable(vnic_priv, vnic_priv->sq[i].vq, + &vnic_priv->sq[i].napi); + } + + return 0; +} + +static int crete_vnic_close(struct net_device *dev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + int i; + int max_queue_pairs = core_dev->cap.qpcap.max_qp_num; + + /* Make sure NAPI doesn't schedule refill work */ + crete_vnic_disable_delayed_refill(vnic_priv); + /* Make sure refill_work doesn't re-enable napi! */ + cancel_delayed_work_sync(&vnic_priv->refill); + + for (i = 0; i < max_queue_pairs; i++) { + napi_disable(&vnic_priv->rq[i].napi); + crete_vnic_napi_tx_disable(&vnic_priv->sq[i].napi); + } + + return 0; +} + +//////////////////////////////cmd begin//////////////////////////////////////// +static int crete_vnic_set_guest_offloads(struct crete_vnic_priv *vnic_priv, + u64 offloads) +{ + u64 virtio64_offloads = 0; + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int err; + + virtio64_offloads = cpu_to_virtio64(&vnic_priv->vdev, offloads); + err = + crete_cmd_set_features(core_dev, CRETE_OFFLOAD_FEAT, + virtio64_offloads); + if (err) + dev_err(&pdev->dev, "set offload features failed %d\n", err); + + return err; +} + +static int crete_vnic_set_features(struct net_device *dev, + netdev_features_t features) +{ + + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + u64 offloads; + int err; + + if ((dev->features ^ features) & NETIF_F_GRO_HW) { + + if (features & NETIF_F_GRO_HW) + offloads = vnic_priv->guest_offloads_capable; + else + offloads = vnic_priv->guest_offloads_capable & + ~GUEST_OFFLOAD_GRO_HW_MASK; + + err = crete_vnic_set_guest_offloads(vnic_priv, offloads); + if (err) + return err; + vnic_priv->guest_offloads = offloads; + } + + return 0; +} + +static int crete_vnic_cmd_set_vport_vlan(struct crete_core_dev *core_dev, + int vport, u16 vlan, bool del) +{ + + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_rx_mode_in); + int out_len = CRETE_ST_SZ_BYTES(set_rx_mode_out); + void *in, *out, *vlan_list_in_base; + int vlan_range_num = 1; + int vlan_range_list_size = + vlan_range_num * CRETE_ST_SZ_BYTES(vlan_range); + + in_len += ALIGN_TO_DW(vlan_range_list_size); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + vlan_list_in_base = in + in_len - ALIGN_TO_DW(vlan_range_list_size); + + CRETE_SET(set_rx_mode_in, in, cmd_op, 1); + CRETE_SET(set_rx_mode_in, in, cmd_id, CRETE_CMD_SET_VPORT_RX_MODE); + CRETE_SET(set_rx_mode_in, in, vport_id, vport); + if (del) { + CRETE_SET(set_rx_mode_in, in, vlan_fliter, 0); + CRETE_SET(set_rx_mode_in, in, vlan_filter_mode, 0); + in_len -= ALIGN_TO_DW(vlan_range_list_size); + } else { + CRETE_SET(set_rx_mode_in, in, vlan_fliter, 1); + CRETE_SET(set_rx_mode_in, in, vlan_tpid, 1); + CRETE_SET(set_rx_mode_in, in, vlan_filter_mode, 2); + CRETE_SET(set_rx_mode_in, in, vlan_range_num, vlan_range_num); + CRETE_SET(vlan_range, vlan_list_in_base, start_vlan, vlan); + CRETE_SET(vlan_range, vlan_list_in_base, end_vlan, vlan); + } + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_rx_mode_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_rx_mode_out, out, err_type); + crete_err(&pdev->dev, + "crete set vport_vlan failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + kvfree(in); + kvfree(out); + dev_warn(&pdev->dev, "%s esw_vport_vlan ret:0x%x\n", __func__, ret); + return ret; +} + +static int crete_vnic_vlan_rx_add_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + struct crete_core_dev *core_dev = vnic_priv->coredev; + __virtio16 local_vid; + int ret, vportid; + struct pci_dev *pdev = core_dev->pdev; + + vportid = netcfg->vportid; + local_vid = cpu_to_virtio16(&vnic_priv->vdev, vid); + ret = + crete_vnic_cmd_set_vport_vlan(core_dev, vportid, local_vid, false); + if (ret) + dev_err(&pdev->dev, "set vlan id %d: is error\n", vid); + netcfg->vlanid = local_vid; + return ret; +} + +static int crete_vnic_vlan_rx_kill_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + __virtio16 local_vid; + int ret, vportid; + + vportid = netcfg->vportid; + local_vid = cpu_to_virtio16(&vnic_priv->vdev, vid); + ret = crete_vnic_cmd_set_vport_vlan(core_dev, vportid, local_vid, true); + if (ret) + dev_err(&pdev->dev, "delvlan id %d: is error\n", vid); + netcfg->vlanid = 0; + return ret; + +} + +static void crete_vnic_get_stats(struct net_device *dev, + struct rtnl_link_stats64 *tot) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + unsigned int start; + int i; + + for (i = 0; i < vnic_priv->max_queue_pairs; i++) { + u64 tpackets, tbytes, rpackets, rbytes, rdrops; + struct receive_queue *rq = &vnic_priv->rq[i]; + struct send_queue *sq = &vnic_priv->sq[i]; + + do { + start = u64_stats_fetch_begin_irq(&sq->stats.syncp); + tpackets = sq->stats.packets; + tbytes = sq->stats.bytes; + } while (u64_stats_fetch_retry_irq(&sq->stats.syncp, start)); + + do { + start = u64_stats_fetch_begin_irq(&rq->stats.syncp); + rpackets = rq->stats.packets; + rbytes = rq->stats.bytes; + rdrops = rq->stats.drops; + } while (u64_stats_fetch_retry_irq(&rq->stats.syncp, start)); + + tot->rx_packets += rpackets; + tot->tx_packets += tpackets; + tot->rx_bytes += rbytes; + tot->tx_bytes += tbytes; + tot->rx_dropped += rdrops; + } + + tot->tx_dropped = dev->stats.tx_dropped; + tot->tx_fifo_errors = dev->stats.tx_fifo_errors; + tot->rx_length_errors = dev->stats.rx_length_errors; + tot->rx_frame_errors = dev->stats.rx_frame_errors; +} + +static int crete_vnic_set_trust_vf(struct net_device *dev, int vf_id, bool trust_state) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + int ret = 0; + u16 vf_sfi = 0; + + ret = crete_get_dev_sfi(core_dev, CRETE_GET_SFI_VF, vf_id, &vf_sfi); + if (ret) { + pr_err("get vf %u sfi error info\n", vf_id); + return ret; + } + + ret = crete_set_trust_vf(core_dev, vf_sfi, trust_state); + return ret; +} + +static int crete_vnic_change_mtu(struct net_device *dev, int new_mtu) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + int ret = 0; + + if (CRETE_COREDEV_PF != core_dev->coredev_type) { + pr_warn("port %u is not pf, can not be set mtu\n", core_dev->sfi_id); + return 0; + } + + if (new_mtu > dev->max_mtu ) { + pr_err("set port mtu (%u) error , exceed max mtu\n", new_mtu); + return -EINVAL; + } + + ret = crete_set_port_mtu(core_dev, CRETE_SET_MTU_MACPORT, MAC_MTU(new_mtu)); + if (ret) { + pr_err("set port mtu error info\n"); + return ret; + } + + WRITE_ONCE(dev->mtu, new_mtu); + + return ret; +} + +static int crete_vnic_adminq_set_mac(struct net_device *dev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0; //status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_uc_mac_in); + int out_len = CRETE_ST_SZ_BYTES(set_uc_mac_out); + void *in, *out, *uc_mac_list_in_base; + int uc_mac_list_size = 0; + + uc_mac_list_size = + netcfg->uc_filter_count * CRETE_ST_SZ_BYTES(uc_mac_list); + + in_len += ALIGN_TO_DW(uc_mac_list_size); + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + uc_mac_list_in_base = in + in_len - ALIGN_TO_DW(uc_mac_list_size); + CRETE_SET(set_uc_mac_in, in, cmd_op, 0); + CRETE_SET(set_uc_mac_in, in, cmd_id, CRETE_CMD_SET_UC_MAC); + CRETE_SET(set_uc_mac_in, in, uc_list_num, netcfg->uc_filter_count); + memcpy(uc_mac_list_in_base, netcfg->uc_list, uc_mac_list_size); +/* + * ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + * if (ret < 0) + * goto err_out; + * status = CRETE_GET(set_uc_mac_out, out, status); + * if (status != SUCCESS) { + * err_type = CRETE_GET(set_uc_mac_out, out, err_type); + * crete_err(&pdev->dev, + * "crete set uc mac failed, err type:0x%x status:0x%x\n", + * err_type, status); + * ret = -EINVAL; + * } + */ +err_out: + kvfree(in); + kvfree(out); + crete_err(&pdev->dev, "%s return:%x\n", __func__, ret); + return ret; +} + +static int crete_vnic_cmd_set_mc_filter(struct net_device *netdev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(netdev); + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_rx_mode_new_in); + int out_len = CRETE_ST_SZ_BYTES(set_rx_mode_out); + void *in, *out, *mc_mac_list_in_base; + int vlan_range_list_size; + int mc_mac_list_size; + int vlan_range_num = 0; + int mc_list_num = netcfg->mc_list_count; + int mc_list_size = mc_list_num * ETH_ALEN; + + vlan_range_list_size = vlan_range_num * CRETE_ST_SZ_BYTES(vlan_range); + in_len += vlan_range_list_size; + + mc_mac_list_size = mc_list_num * CRETE_ST_SZ_BYTES(mc_mac_list); + in_len += ALIGN_TO_DW(mc_mac_list_size); + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + mc_mac_list_in_base = in + in_len - ALIGN_TO_DW(mc_mac_list_size); + + CRETE_SET(set_rx_mode_new_in, in, cmd_op, BIT(CRETE_RX_MODE_MC_MAC_LIST_ADD)); + CRETE_SET(set_rx_mode_new_in, in, cmd_id, CRETE_CMD_SET_VPORT_RX_MODE); + CRETE_SET(set_rx_mode_new_in, in, svport_id, core_dev->sfi_id); + CRETE_SET(set_rx_mode_new_in, in, dvport_id, core_dev->sfi_id); + + CRETE_SET(set_rx_mode_new_in, in, mc_list_num, netcfg->mc_list_count); + memcpy(mc_mac_list_in_base, netcfg->mc_list, mc_list_size); + + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_rx_mode_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_rx_mode_out, out, err_type); + crete_err(&pdev->dev, + "crete set mc filter failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + kvfree(in); + kvfree(out); + return ret; +} + +static int __maybe_unused crete_vnic_set_uc_filter(struct net_device *netdev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(netdev); + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + struct netdev_hw_addr *ha; + int off = 0; + + netif_addr_lock_bh(netdev); + if (netdev_uc_count(netdev) > (CRETE_MAX_UC_ADDRS - 1)) { + netcfg->rx_mask |= L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + } else { + netdev_for_each_uc_addr(ha, netdev) { + memcpy(netcfg->uc_list + off, ha->addr, ETH_ALEN); + off += ETH_ALEN; + netcfg->uc_filter_count++; + } + } + netif_addr_unlock_bh(netdev); + + return crete_vnic_adminq_set_mac(netdev); +} + +static int crete_vnic_cmd_set_rx_mask(struct net_device *netdev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(netdev); + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_rx_mode_new_in); + int out_len = CRETE_ST_SZ_BYTES(set_rx_mode_out); + void *in, *out; + + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + CRETE_SET(set_rx_mode_new_in, in, cmd_op, 1); + CRETE_SET(set_rx_mode_new_in, in, cmd_id, CRETE_CMD_SET_VPORT_RX_MODE); + CRETE_SET(set_rx_mode_new_in, in, svport_id, core_dev->sfi_id); + CRETE_SET(set_rx_mode_new_in, in, dvport_id, core_dev->sfi_id); + + if (netcfg->rx_mask & L2_SET_RX_MASK_REQ_MASK_BCAST) + CRETE_SET(set_rx_mode_new_in, in, broadcast, 1); + + if (netcfg->rx_mask & L2_SET_RX_MASK_REQ_MASK_ALL_MCAST) + CRETE_SET(set_rx_mode_new_in, in, all_mmulticast, 1); + + if (netcfg->rx_mask & L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS) + CRETE_SET(set_rx_mode_new_in, in, promiscuous, 1); + + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_rx_mode_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_rx_mode_out, out, err_type); + crete_err(&pdev->dev, + "crete set rx mask failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + kvfree(in); + kvfree(out); + return ret; +} + +void crete_vnic_do_set_rx_mode(struct crete_vnic_priv *vnic_priv) +{ + + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct net_device *netdev = vnic_priv->netdev; + int rc; + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + + if (netcfg->rx_mask & L2_SET_RX_MASK_REQ_MASK_MCAST) { + rc = crete_vnic_cmd_set_mc_filter(netdev); + if (rc) { + dev_err(&pdev->dev, + "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n", + rc); + netcfg->rx_mask &= ~L2_SET_RX_MASK_REQ_MASK_MCAST; + netcfg->rx_mask |= L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + netcfg->mc_list_count = 0; + } + } + /*promisc check */ + //if ((netcfg->rx_mask & L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS) && + //!crete_promisc_ok(core_dev)) + // priv->rx_mask &= ~L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + + rc = crete_vnic_cmd_set_rx_mask(netdev); + if (rc) + dev_err(&pdev->dev, "HWRM l2 rx mask failure rc: %d\n", rc); +} + +void crete_vnic_set_rx_mode_work(struct work_struct *work) +{ + struct crete_vnic_priv *vnic_priv = container_of(work, struct crete_vnic_priv, + set_rx_mode_work); + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct net_device *netdev = vnic_priv->netdev; + int rc; + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + + if (netcfg->rx_mask & L2_SET_RX_MASK_REQ_MASK_MCAST) { + rc = crete_vnic_cmd_set_mc_filter(netdev); + if (rc) { + dev_err(&pdev->dev, + "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n", + rc); + netcfg->rx_mask &= ~L2_SET_RX_MASK_REQ_MASK_MCAST; + netcfg->rx_mask |= L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + netcfg->mc_list_count = 0; + } + } + + rc = crete_vnic_cmd_set_rx_mask(netdev); + if (rc) + dev_err(&pdev->dev, "HWRM l2 rx mask failure rc: %d\n", rc); + +} +EXPORT_SYMBOL(crete_vnic_set_rx_mode_work); + +static bool __maybe_unused crete_vnic_uc_list_updated(struct net_device *dev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + struct netdev_hw_addr *ha; + int off = 0; + + if (netdev_uc_count(dev) != (netcfg->uc_filter_count)) + return true; + + netdev_for_each_uc_addr(ha, dev) { + if (!ether_addr_equal(ha->addr, netcfg->uc_list + off)) + return true; + off += ETH_ALEN; + } + return false; +} + +static bool __maybe_unused crete_vnic_mc_list_updated(struct net_device *dev, u32 *rx_mask) +{ + int mc_count = 0; + bool update = false; + int off = 0; + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct netdev_hw_addr *ha; + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + + netdev_for_each_mc_addr(ha, dev) { + if (mc_count >= CRETE_MAX_MC_ADDRS) { + *rx_mask |= L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + netcfg->mc_list_count = 0; + return false; + } + if (!ether_addr_equal(ha->addr, netcfg->mc_list + off)) { + memcpy(netcfg->mc_list + off, ha->addr, ETH_ALEN); + update = true; + } + off += ETH_ALEN; + mc_count++; + } + if (mc_count) + *rx_mask |= L2_SET_RX_MASK_REQ_MASK_MCAST; + + if (mc_count != netcfg->mc_list_count) { + netcfg->mc_list_count = mc_count; + update = true; + } + return update; +} + +static void crete_vnic_set_rx_mode(struct net_device *dev) +{ + + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + u32 mask; + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + bool mc_update; + + pr_debug("crete enter into rx mode set\n"); + mask = netcfg->rx_mask; + mask &= ~(L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS | + L2_SET_RX_MASK_REQ_MASK_MCAST | + L2_SET_RX_MASK_REQ_MASK_ALL_MCAST | + L2_SET_RX_MASK_REQ_MASK_BCAST); + + if (dev->flags & IFF_PROMISC) + mask |= L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + if (dev->flags & IFF_BROADCAST) + mask |= L2_SET_RX_MASK_REQ_MASK_BCAST; + if (dev->flags & IFF_ALLMULTI) { + mask |= L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + netcfg->mc_list_count = 0; + } +/* + * snic not support the MC MAC ADD AND DEL + */ +#if 0 + } else if (dev->flags & IFF_MULTICAST) { + mc_update = crete_vnic_mc_list_updated(dev, &mask); + } + bool uc_update = crete_vnic_uc_list_updated(dev); + if (uc_update) { + rc = crete_vnic_set_uc_filter(dev); + if (rc) + dev_err(&pdev->dev, + "HWRM l2 uc filter failure rc: %d\n", rc); + } +#endif + dev_dbg(&pdev->dev, + "update rxmode config new mask %x old cfg mask %x\n", + mask, netcfg->rx_mask); + //todo pf current not set vdev + if (mask != netcfg->rx_mask || mc_update) { + netcfg->rx_mask = mask; + queue_work(vnic_priv->wq, &vnic_priv->set_rx_mode_work); + } + +} + +static int crete_cmd_set_uc_mac_new(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_net_common_cfg *netcfg = &priv->net_cfg; + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0, status = 0, err_type; + int in_len = CRETE_ST_SZ_BYTES(set_rx_mode_new_in); + int out_len = CRETE_ST_SZ_BYTES(set_rx_mode_out); + void *in, *out, *uc_mac_list_in_base; + int uc_list_num = netcfg->uc_filter_count; + int uc_mac_list_size = uc_list_num * CRETE_ST_SZ_BYTES(uc_mac_list); + + in_len += ALIGN_TO_DW(uc_mac_list_size); + in = kvzalloc(in_len, GFP_KERNEL); + out = kvzalloc(out_len, GFP_KERNEL); + if (!out || !in) { + ret = -ENOMEM; + goto err_out; + } + + uc_mac_list_in_base = in + in_len - ALIGN_TO_DW(uc_mac_list_size); + CRETE_SET(set_rx_mode_new_in, in, cmd_op, BIT(CRETE_RX_MODE_UC_MAC_LIST_ADD)); + CRETE_SET(set_rx_mode_new_in, in, cmd_id, CRETE_CMD_SET_VPORT_RX_MODE); + + CRETE_SET(set_rx_mode_new_in, in, svport_id, core_dev->sfi_id); + CRETE_SET(set_rx_mode_new_in, in, dvport_id, core_dev->sfi_id); + + CRETE_SET(set_rx_mode_new_in, in, uc_list_num, netcfg->uc_filter_count); + memcpy(uc_mac_list_in_base, netcfg->uc_list, uc_mac_list_size); + + ret = crete_cmd_exec_polling(core_dev, in, in_len, out, out_len); + if (ret < 0) + goto err_out; + + status = CRETE_GET(set_rx_mode_out, out, status); + if (status != SUCCESS) { + err_type = CRETE_GET(set_rx_mode_out, out, err_type); + crete_err(&pdev->dev, + "crete set uc mac failed, err type:0x%x status:0x%x\n", + err_type, status); + ret = -EINVAL; + } +err_out: + if (in) { + kvfree(in); + in = NULL; + } + if (out) { + kvfree(out); + out = NULL; + } + crete_err(&pdev->dev, "%s return:%d\n", __func__, ret); + return ret; + +} + +int crete_vnic_set_mac_address(struct net_device *dev, void *p) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_net_common_cfg *netcfg = &vnic_priv->net_cfg; + int ret, i; + struct sockaddr *addr; + + addr = kmemdup(p, sizeof(*addr), GFP_KERNEL); + if (!addr) + return -ENOMEM; + + ret = eth_prepare_mac_addr_change(dev, addr); + if (ret) + goto out; + for (i = 0; i < ETH_ALEN; i++) + netcfg->uc_list[i] = addr->sa_data[ETH_ALEN - i - 1]; + + netcfg->uc_filter_count = 1; + ret = crete_cmd_set_uc_mac_new(dev); + if (ret) { + dev_warn(&pdev->dev, "Failed to set mac address ret %d\n", ret); + netcfg->uc_filter_count = 0; + goto out; + } + eth_commit_mac_addr_change(dev, p); +out: + kfree(addr); + return ret; +} + +/////////////////////////////cmd end///////////////////////////////////////// + +/************************interrupts ctx********************************/ +int crete_vnic_poll_tx(struct napi_struct *napi, int budget) +{ + struct send_queue *sq = container_of(napi, struct send_queue, napi); + struct crete_vnic_priv *vnic_priv = sq->vq->vdev->priv; + unsigned int index = vq2txq(sq->vq); + struct netdev_queue *txq; + int opaque; + bool done; + + txq = netdev_get_tx_queue(vnic_priv->netdev, index); + __netif_tx_lock(txq, raw_smp_processor_id()); + virtqueue_disable_cb(sq->vq); + crete_vnic_free_old_tx_skbs(sq, true); + + opaque = virtqueue_enable_cb_prepare(sq->vq); + done = napi_complete_done(napi, 0); + if (!done) + virtqueue_disable_cb(sq->vq); + + __netif_tx_unlock(txq); + + if (done) { + if (unlikely(virtqueue_poll(sq->vq, opaque))) { + if (napi_schedule_prep(napi)) { + __netif_tx_lock(txq, raw_smp_processor_id()); + virtqueue_disable_cb(sq->vq); + __netif_tx_unlock(txq); + __napi_schedule(napi); + } + } + } + + if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) + netif_tx_wake_queue(txq); + + return 0; +} + +void crete_vnic_xmit_done(struct virtqueue *vq) +{ + struct crete_vnic_priv *vnic_priv = vq->vdev->priv; + struct napi_struct *napi = &vnic_priv->sq[vq2txq(vq)].napi; + + /* Suppress further interrupts. */ + virtqueue_disable_cb(vq); + + if (napi->weight) + virtqueue_napi_schedule(napi, vq); + else + /* We were probably waiting for more output buffers. */ + netif_wake_subqueue(vnic_priv->netdev, vq2txq(vq)); +} + +static struct sk_buff *crete_vnic_receive_mergeable(struct net_device *dev, struct crete_vnic_priv + *vnic_priv, + struct receive_queue *rq, + void *buf, void *ctx, + unsigned int len, + struct crete_vnic_rq_stats + *stats) +{ + struct virtio_net_hdr_mrg_rxbuf *hdr = buf; + u16 num_buf = virtio16_to_cpu(&vnic_priv->vdev, hdr->num_buffers); + struct page *page = virt_to_head_page(buf); + int offset = buf - page_address(page); + struct sk_buff *head_skb, *curr_skb; + unsigned int truesize = mergeable_ctx_to_truesize(ctx); + unsigned int headroom = 0; + unsigned int metasize = 0; + + headroom = mergeable_ctx_to_headroom(ctx); + head_skb = NULL; + stats->bytes += len - vnic_priv->hdr_len; + if (unlikely(len > truesize)) { + pr_debug("%s: rx error: len %u exceeds truesize %lu\n", + dev->name, len, (unsigned long)ctx); + dev->stats.rx_length_errors++; + goto err_skb; + } + + head_skb = + crete_vnic_page_to_skb(vnic_priv, rq, page, offset, len, truesize, + true, metasize); + curr_skb = head_skb; + + if (unlikely(!curr_skb)) + goto err_skb; + while (--num_buf) { + int num_skb_frags; + + buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx); + if (unlikely(!buf)) { + pr_debug("%s: rx error: %d buffers out of %d missing\n", + dev->name, num_buf, + virtio16_to_cpu(&vnic_priv->vdev, + hdr->num_buffers)); + dev->stats.rx_length_errors++; + goto err_buf; + } + + stats->bytes += len; + page = virt_to_head_page(buf); + + truesize = mergeable_ctx_to_truesize(ctx); + if (unlikely(len > truesize)) { + pr_debug("%s: rx error: len %u exceeds truesize %lu\n", + dev->name, len, (unsigned long)ctx); + dev->stats.rx_length_errors++; + goto err_skb; + } + + num_skb_frags = skb_shinfo(curr_skb)->nr_frags; + if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { + struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC); + + if (unlikely(!nskb)) + goto err_skb; + if (curr_skb == head_skb) + skb_shinfo(curr_skb)->frag_list = nskb; + else + curr_skb->next = nskb; + curr_skb = nskb; + head_skb->truesize += nskb->truesize; + num_skb_frags = 0; + } + if (curr_skb != head_skb) { + head_skb->data_len += len; + head_skb->len += len; + head_skb->truesize += truesize; + } + offset = buf - page_address(page); + if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { + put_page(page); + skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1, + len, truesize); + } else { + skb_add_rx_frag(curr_skb, num_skb_frags, page, + offset, len, truesize); + } + } + + ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len); + return head_skb; +err_skb: + put_page(page); + while (num_buf-- > 1) { + buf = virtqueue_get_buf(rq->vq, &len); + if (unlikely(!buf)) { + pr_debug("%s: rx error: %d buffers missing\n", + dev->name, num_buf); + dev->stats.rx_length_errors++; + break; + } + stats->bytes += len; + page = virt_to_head_page(buf); + put_page(page); + } +err_buf: + stats->drops++; + dev_kfree_skb(head_skb); + return NULL; +} + +static void crete_vnic_receive_buf(struct crete_vnic_priv *vnic_priv, + struct receive_queue *rq, void *buf, + unsigned int len, void **ctx, + struct crete_vnic_rq_stats *stats) +{ + struct net_device *dev = vnic_priv->netdev; + struct sk_buff *skb; + struct virtio_net_hdr_mrg_rxbuf *hdr; + + if (unlikely(len < vnic_priv->hdr_len + ETH_HLEN)) { + pr_debug("%s: short packet %i\n", dev->name, len); + dev->stats.rx_length_errors++; + put_page(virt_to_head_page(buf)); + return; + } + + skb = crete_vnic_receive_mergeable(dev, vnic_priv, rq, buf, ctx, len, + stats); + if (unlikely(!skb)) + return; + + hdr = skb_to_crete_vnic_hdr(skb); + + if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + if (virtio_net_hdr_to_skb(skb, &hdr->hdr, + virtio_is_little_endian(&vnic_priv->vdev))) { + net_warn_ratelimited("%s: bad gso: type: %u, size: %u\n", + dev->name, hdr->hdr.gso_type, + hdr->hdr.gso_size); + goto frame_err; + } + + skb_record_rx_queue(skb, vq2rxq(rq->vq)); + skb->protocol = eth_type_trans(skb, dev); + pr_debug("Receiving skb proto 0x%04x len %i type %i\n", + ntohs(skb->protocol), skb->len, skb->pkt_type); + + napi_gro_receive(&rq->napi, skb); + return; + +frame_err: + dev->stats.rx_frame_errors++; + dev_kfree_skb(skb); +} + +static int crete_vnic_receive(struct receive_queue *rq, int budget) +{ + struct crete_vnic_priv *vnic_priv = rq->vq->vdev->priv; + struct crete_vnic_rq_stats stats = { }; + unsigned int len; + void *buf; + int i; + + if (!vnic_priv->big_packets || vnic_priv->mergeable_rx_bufs) { + void *ctx; + + while (stats.packets < budget && + (buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx))) { + crete_vnic_receive_buf(vnic_priv, rq, buf, len, ctx, + &stats); + stats.packets++; + } + } else { + while (stats.packets < budget && + (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { + crete_vnic_receive_buf(vnic_priv, rq, buf, len, NULL, + &stats); + stats.packets++; + } + } + + if (rq->vq->num_free > min_t(unsigned int, + (unsigned int)budget, virtqueue_get_vring_size(rq->vq)) / 2) { + if (!crete_vnic_try_fill_recv(vnic_priv, rq, GFP_ATOMIC)) { + spin_lock(&vnic_priv->refill_lock); + if (vnic_priv->refill_enabled) + schedule_delayed_work(&vnic_priv->refill, 0); + spin_unlock(&vnic_priv->refill_lock); + } + } + + u64_stats_update_begin(&rq->stats.syncp); + for (i = 0; i < CRETE_VNIC_RQ_STATS_LEN; i++) { + size_t offset = crete_vnic_rq_stats_desc[i].offset; + u64 *item; + + item = (u64 *) ((u8 *)&rq->stats + offset); + *item += *(u64 *) ((u8 *)&stats + offset); + } + u64_stats_update_end(&rq->stats.syncp); + + return stats.packets; +} + +static void crete_vnic_poll_cleantx(struct receive_queue *rq) +{ + struct crete_vnic_priv *vnic_priv = rq->vq->vdev->priv; + unsigned int index = vq2rxq(rq->vq); + struct send_queue *sq = &vnic_priv->sq[index]; + struct netdev_queue *txq = + netdev_get_tx_queue(vnic_priv->netdev, index); + + if (!sq->napi.weight) + return; + + if (__netif_tx_trylock(txq)) { + crete_vnic_free_old_tx_skbs(sq, true); + __netif_tx_unlock(txq); + } + + if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) + netif_tx_wake_queue(txq); +} + +int crete_vnic_poll(struct napi_struct *napi, int budget) +{ + struct receive_queue *rq = + container_of(napi, struct receive_queue, napi); + unsigned int received; + + crete_vnic_poll_cleantx(rq); + received = crete_vnic_receive(rq, budget); + /* Out of packets? */ + if (received < budget) + virtqueue_napi_complete(napi, rq->vq, received); + return received; +} + +void crete_vnic_recv_done(struct virtqueue *rvq) +{ + struct crete_vnic_priv *vnic_priv = rvq->vdev->priv; + struct receive_queue *rq = &vnic_priv->rq[vq2rxq(rvq)]; + + virtqueue_napi_schedule(&rq->napi, rvq); +} + +/************************interrupts ctx********************************/ + +void free_unused_bufs(struct crete_vnic_priv *vnic_priv) +{ +} + +static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask) +{ + struct page *p = rq->pages; + + if (p) { + rq->pages = (struct page *)p->private; + /* clear private here, it is used to chain pages */ + p->private = 0; + } else + p = alloc_page(gfp_mask); + return p; +} + +static void _free_receive_bufs(struct crete_vnic_priv *vnic_priv) +{ + int i; + + for (i = 0; i < vnic_priv->max_queue_pairs; i++) { + while (vnic_priv->rq[i].pages) + __free_pages(get_a_page(&vnic_priv->rq[i], GFP_KERNEL), + 0); + } +} + +void free_receive_bufs(struct crete_vnic_priv *vnic_priv) +{ + rtnl_lock(); + _free_receive_bufs(vnic_priv); + rtnl_unlock(); +} + +static const struct net_device_ops crete_vnic_netdev_ops = { + .ndo_open = crete_vnic_open, + .ndo_stop = crete_vnic_close, + .ndo_start_xmit = crete_vnic_dev_queue_xmit, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = crete_vnic_set_mac_address, + .ndo_set_rx_mode = crete_vnic_set_rx_mode, + .ndo_get_stats64 = crete_vnic_get_stats, + .ndo_vlan_rx_add_vid = crete_vnic_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = crete_vnic_vlan_rx_kill_vid, + .ndo_set_features = crete_vnic_set_features, + .ndo_set_vf_trust = crete_vnic_set_trust_vf, + .ndo_change_mtu = crete_vnic_change_mtu, +}; + +void crete_set_netdev_ops(struct net_device *netdev) +{ + netdev->netdev_ops = &crete_vnic_netdev_ops; +} + +void free_receive_page_frags(struct crete_vnic_priv *vnic_priv) +{ + int i; + + for (i = 0; i < vnic_priv->max_queue_pairs; i++) + if (vnic_priv->rq[i].alloc_frag.page) + put_page(vnic_priv->rq[i].alloc_frag.page); +} + +int __crete_vnic_set_queues(struct net_device *netdev, u16 queue_pairs) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int ret = 0; + + if (crete_set_qp_num(core_dev, queue_pairs) != 0) { + dev_warn(&pdev->dev, "Fail to set num of queue pairs to %d\n", + queue_pairs); + ret = -EINVAL; + } else { + priv->curr_queue_pairs = queue_pairs; + /* snic_open() will refill when device is going to up. */ + if (netdev->flags & IFF_UP) + schedule_delayed_work(&priv->refill, 0); + } + + return ret; +} + +int crete_vnic_set_queues(struct net_device *netdev, u16 queue_pairs) +{ + int err = 0; + + rtnl_lock(); + err = __crete_vnic_set_queues(netdev, queue_pairs); + rtnl_unlock(); + return err; +} + +void crete_vnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + char *p = (char *)data; + unsigned int i, j; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < vnic_priv->curr_queue_pairs; i++) { + for (j = 0; j < CRETE_VNIC_RQ_STATS_LEN; j++) { + snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_%s", + i, crete_vnic_rq_stats_desc[j].desc); + p += ETH_GSTRING_LEN; + } + } + + for (i = 0; i < vnic_priv->curr_queue_pairs; i++) { + for (j = 0; j < CRETE_VNIC_SQ_STATS_LEN; j++) { + snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_%s", + i, crete_vnic_sq_stats_desc[j].desc); + p += ETH_GSTRING_LEN; + } + } + + for (j = 0; j < CRETE_VNIC_PHY_STATS_LEN; j++) { + snprintf(p, ETH_GSTRING_LEN, "%s", crete_vnic_phy_stat_desc[j]); + p += ETH_GSTRING_LEN; + } + break; + } +} + +int crete_vnic_get_sset_count(struct net_device *dev, int sset) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + + switch (sset) { + case ETH_SS_STATS: + return vnic_priv->curr_queue_pairs * (CRETE_VNIC_RQ_STATS_LEN + + CRETE_VNIC_SQ_STATS_LEN) + CRETE_VNIC_PHY_STATS_LEN; + default: + return -EOPNOTSUPP; + } +} + +void crete_vnic_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(dev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + unsigned int idx = 0, start, i, j; + const u8 *stats_base; + size_t offset; + int ret = 0; + struct crete_port_statistics port_statistics; + + for (i = 0; i < vnic_priv->curr_queue_pairs; i++) { + struct receive_queue *rq = &vnic_priv->rq[i]; + + stats_base = (u8 *)&rq->stats; + do { + start = u64_stats_fetch_begin_irq(&rq->stats.syncp); + for (j = 0; j < CRETE_VNIC_RQ_STATS_LEN; j++) { + offset = crete_vnic_rq_stats_desc[j].offset; + data[idx + j] = *(u64 *) (stats_base + offset); + } + } while (u64_stats_fetch_retry_irq(&rq->stats.syncp, start)); + idx += CRETE_VNIC_RQ_STATS_LEN; + } + + for (i = 0; i < vnic_priv->curr_queue_pairs; i++) { + struct send_queue *sq = &vnic_priv->sq[i]; + + stats_base = (u8 *)&sq->stats; + do { + start = u64_stats_fetch_begin_irq(&sq->stats.syncp); + for (j = 0; j < CRETE_VNIC_SQ_STATS_LEN; j++) { + offset = crete_vnic_sq_stats_desc[j].offset; + data[idx + j] = *(u64 *) (stats_base + offset); + } + } while (u64_stats_fetch_retry_irq(&sq->stats.syncp, start)); + idx += CRETE_VNIC_SQ_STATS_LEN; + } + + ret = crete_get_vport_pkt_statistics(core_dev, CRETE_GET_PKT_STATIS_MAC, &port_statistics); + if (ret == 0) { + data[idx + 0] = port_statistics.rx_bytes; + data[idx + 1] = port_statistics.rx_pkts; + data[idx + 2] = port_statistics.tx_bytes; + data[idx + 3] = port_statistics.tx_pkts; + } +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_io.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_io.h new file mode 100644 index 0000000..dabcd84 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_io.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CRETE_NIC_IO_H_ +#define _CRETE_NIC_IO_H_ +void crete_set_netdev_ops(struct net_device *netdev); +void crete_set_ethtool_ops(struct net_device *netdev); +void free_unused_bufs(struct crete_vnic_priv *vnic_priv); +void free_receive_bufs(struct crete_vnic_priv *vnic_priv); +void free_receive_page_frags(struct crete_vnic_priv *vnic_priv); +int crete_vnic_set_queues(struct net_device *netdev, u16 queue_pairs); +int __crete_vnic_set_queues(struct net_device *netdev, u16 queue_pairs); +void crete_vnic_recv_done(struct virtqueue *rvq); +void crete_vnic_xmit_done(struct virtqueue *vq); +int crete_vnic_poll_tx(struct napi_struct *napi, int budget); +int crete_vnic_poll(struct napi_struct *napi, int budget); +void crete_vnic_alloc_recv_buf(struct work_struct *work); +void crete_vnic_get_strings(struct net_device *dev, u32 stringset, u8 *data); +int crete_vnic_get_sset_count(struct net_device *dev, int sset); +void crete_vnic_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data); +#endif /* _CRETE_NIC_IO_H_*/ + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_main.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_main.c new file mode 100644 index 0000000..6615e04 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-pnic/crete_nic_main.c @@ -0,0 +1,1341 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crete_nic.h" +#include "crete_nic_io.h" +#include "crete_nic_ethtool.h" + +static int napi_weight = NAPI_POLL_WEIGHT; +module_param(napi_weight, int, 0444); + +static bool csum = true, gso = true, napi_tx = true; +module_param(csum, bool, 0444); +module_param(gso, bool, 0444); +module_param(napi_tx, bool, 0644); + +#define CRETE_NIC_DRV_DESCRIPTION "JaguarMicro/CRETE NIC Device Driver" +#define CRETE_VNIC_DRV_NAME "crete_vnic" + +static const unsigned long crete_vnic_guest_offloads[] = { + VIRTIO_NET_F_GUEST_TSO4, + VIRTIO_NET_F_GUEST_TSO6, + VIRTIO_NET_F_GUEST_ECN, + VIRTIO_NET_F_GUEST_UFO, + VIRTIO_NET_F_GUEST_CSUM +}; + +#define CRETE_VNIC_FEATURES \ + VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, \ + VIRTIO_NET_F_MAC, \ + VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, \ + VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, \ + VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, \ + VIRTIO_NET_F_CTRL_VLAN, \ + VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \ + VIRTIO_NET_F_CTRL_MAC_ADDR, \ + VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ + VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_MRG_RXBUF + +static unsigned int crete_vnic_features[] = { + CRETE_VNIC_FEATURES, +}; + +#define CRETE_VIRTIO_DEVICE_ID 0x1C20 /* virtio net */ +#define CRETE_VIRTIO_VENDOR_ID 0x1f53 /* virtio net */ + +struct crete_vnic_wq_ent { + struct work_struct work; + struct crete_vnic_priv *vnic_priv; +}; + +static bool crete_vnic_get_link_state(struct crete_core_dev *core_dev, + struct crete_vnic_priv *vnic_priv) +{ + int ret; + bool linkstat = false; + + ret = crete_get_dev_linkattr(core_dev, &linkstat); + if (ret) + return false; + + return linkstat; +} + +static void update_carrier(struct work_struct *work) +{ + struct crete_vnic_wq_ent *wqent; + struct crete_vnic_priv *vnic_priv; + struct crete_core_dev *core_dev; + + wqent = container_of(work, struct crete_vnic_wq_ent, work); + vnic_priv = wqent->vnic_priv; + core_dev = vnic_priv->coredev; + + if (crete_vnic_get_link_state(core_dev, vnic_priv)) + netif_carrier_on(core_dev->netdev); + else + netif_carrier_off(core_dev->netdev); + + kfree(wqent); +} + +static int queue_link_work(struct crete_vnic_priv *vnic_priv) +{ + struct crete_vnic_wq_ent *wqent; + + wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC); + if (!wqent) + return -ENOMEM; + + wqent->vnic_priv = vnic_priv; + INIT_WORK(&wqent->work, update_carrier); + queue_work(vnic_priv->wq, &wqent->work); + return 0; +} + +static int crete_vnic_notify_handler(struct notifier_block *nb, + unsigned long ecode, void *data) +{ + struct crete_nb *cnb = container_of(nb, struct crete_nb, nb); + struct crete_vnic_priv *vnic_priv = + container_of(cnb, struct crete_vnic_priv, cnb); + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct crete_event_entry *cee = data; + uint8_t event_sub_type = cee->event_sub_type; + struct pci_dev *pdev = core_dev->pdev; + unsigned int status; + + //dev_dbg(&pdev->dev, "%s: event code %lu\n sub_tupe %d\n", __func__, + crete_info(&pdev->dev, "%s: event code %lu\n sub_tupe %d\n", __func__, + ecode, event_sub_type); + /* + * about the event type is port link change + */ + if (ecode == CRETE_EVENT_PORT_LINK_CHANGE) { + + status = event_sub_type; + /* + * if status exceed RIGHT LINK status + * or status not changed anymore. + * just return now. + */ + if (status >= CRETE_EVENT_PORT_LINK_ERR || + status == vnic_priv->status) + return NOTIFY_DONE; + + vnic_priv->status = status; + /* make sure other core will see it */ + smp_mb(); + + if (queue_link_work(vnic_priv)) + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static int crete_vnic_register_event_handler(struct net_device *netdev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_nb *cnb = &vnic_priv->cnb; + struct notifier_block *nb = &cnb->nb; + int err; + + if (!nb->notifier_call) { + nb->notifier_call = crete_vnic_notify_handler; + cnb->event_type = CRETE_EVENT_PORT_LINK_CHANGE; + err = crete_event_notifier_register(core_dev, cnb); + if (err) { + nb->notifier_call = NULL; + dev_err(&pdev->dev, + "failed to register pds event handler: %ps\n", + ERR_PTR(err)); + return -EINVAL; + } + dev_dbg(&pdev->dev, "crete event handler registered\n"); + } + + return 0; +} + +static void crete_vnic_unregister_event_handler(struct net_device *netdev) +{ + struct crete_vnic_priv *vnic_priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = vnic_priv->coredev; + struct crete_nb *cnb = &vnic_priv->cnb; + struct notifier_block *nb = &cnb->nb; + + if (nb->notifier_call) { + crete_event_notifier_unregister(core_dev, cnb); + nb->notifier_call = NULL; + } +} + +/* Converting between virtqueue no. and kernel tx/rx queue no. + * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq + */ + +static int txq2vq(int txq) +{ + return txq * 2 + 1; +} + +static int rxq2vq(int rxq) +{ + return rxq * 2; +} + +static inline void __vnic_set_bit(struct virtio_device *vdev, unsigned int fbit) +{ + /* Did you forget to fix assumptions on max features? */ + if (__builtin_constant_p(fbit)) + BUILD_BUG_ON(fbit >= 64); + else + BUG_ON(fbit >= 64); + + vdev->features |= BIT_ULL(fbit); +} + +/********************************virtio config ops*********************************************/ +static inline struct crete_vnic_priv *to_vnic_net_device(struct virtio_device + *vdev) +{ + return container_of(vdev, struct crete_vnic_priv, vdev); +} + +static inline struct crete_core_dev *to_vnic_core_device(struct virtio_device + *dev) +{ + struct crete_vnic_priv *cpriv; + + cpriv = to_vnic_net_device(dev); + return cpriv->coredev; +} + +static bool crete_vnic_kick_vq(struct virtqueue *vq) +{ + iowrite16(vq->index, (void __iomem *)vq->priv); + return true; +} + +static irqreturn_t crete_vnic_intr_handler(int irq, void *arg) +{ + struct crete_vnic_msix_info *info = arg; + + return vring_interrupt(irq, info->vq); +} + +static void __iomem *crete_vnic_signal_queue_init_notify(struct crete_core_dev *core_dev, + u16 index) +{ + return core_dev->db_base; +} + +static int crete_vnic_signal_queue_init_irq(struct crete_vnic_msix_info *info, + struct crete_core_dev *core_dev, + u16 index) +{ + struct device *dev = core_dev->device; + struct pci_dev *pdev = core_dev->pdev; + int vectorno, ret = 0; + struct crete_irq_info *irq_info; + + if (!info) { + crete_err(dev, "info is null\n"); + ret = -EINVAL; + goto err; + } + + vectorno = crete_req_msixirq(core_dev); + if (vectorno < 0) { + crete_err(dev, "request irq vector failed\n"); + ret = -ENXIO; + goto err; + } + + irq_info = &core_dev->irq_info[vectorno]; + info->msix_vector = vectorno; + info->irq = irq_info->vector; + snprintf(info->msix_name, 256, "crete-nic[%s]-%d", + pci_name(pdev), index); + ret = request_irq(irq_info->vector, crete_vnic_intr_handler, 0, + info->msix_name, info); + if (ret) { + crete_free_msixirq(core_dev, vectorno); + crete_err(dev, "enable irq failed\n"); + goto err; + + } + + irq_info->handler = crete_vnic_intr_handler; + irq_info->requested = 1; + //info->ready = 1; + +err: + return ret; +} + +static void crete_vnic_signal_queue_freeirq(int msix_vector, + struct crete_core_dev *core_dev, + struct crete_vnic_msix_info *info) +{ + struct crete_irq_info *irq_info; + + irq_info = &core_dev->irq_info[msix_vector]; + if (irq_info->requested == 0) + return; + irq_info->requested = 0; + free_irq(info->irq, info); + crete_free_msixirq(core_dev, msix_vector); + +} + +static int crete_vnic_signal_queue_create(struct crete_core_dev *core_dev, + struct virtqueue *vq, int qid, + int msix_vector) +{ + + struct crete_queue_context qc; + u64 desc_addr, driver_addr, device_addr; + int ret = 0; + int queue_size = core_dev->cap.qpcap.max_queue_size; + struct pci_dev *pdev = core_dev->pdev; + + desc_addr = virtqueue_get_desc_addr(vq); + driver_addr = virtqueue_get_avail_addr(vq); + device_addr = virtqueue_get_used_addr(vq); + + dev_info(&pdev->dev, + "qpid[%d] desc_addr[0x%llx] driver_addr[0x%llx] vector[%d]\n", + qid, desc_addr, driver_addr, msix_vector); + qc.qid = qid; + qc.queue_size = queue_size; + qc.cq_size = queue_size; + qc.queue_vec = msix_vector; + qc.queue_desc_base = desc_addr; + qc.queue_used_base = desc_addr; + //qc.queue_used_base = device_addr; + + ret = crete_cmd_create_signal_queue(core_dev, &qc); + if (ret < 0) { + crete_err(&pdev->dev, "crete create queue failed ret:%d\n", + ret); + ret = -EINVAL; + goto err; + } +err: + return ret; +} + +static void crete_vnic_driver_resetqueue(struct crete_core_dev *core_dev, + int qid) +{ + int ret; + + ret = crete_reset_singlequeue(core_dev, qid); + if (ret) { + crete_err(core_dev->device, "crete reset queue id:%d failed\n", + qid); + ret = -EINVAL; + } +} + +static void crete_vnic_reset_io_queue(struct crete_core_dev *core_dev, + int endqid) +{ + int i; + struct net_device *netdev = core_dev->netdev; + struct crete_vnic_priv *vnic_info = netdev_priv(netdev); + struct crete_vnic_msix_info *msix_info; + + for (i = endqid - 1; i >= 0; i--) { + msix_info = &vnic_info->msix_info[i]; + if (msix_info->irq) + crete_vnic_signal_queue_freeirq(msix_info->msix_vector, + core_dev, msix_info); + if (msix_info->ready) + crete_vnic_driver_resetqueue(core_dev, i); + msix_info->ready = 0; + msix_info->msix_vector = 0; + msix_info->irq = 0; + msix_info->vq = NULL; + } + +} + +static void crete_vnic_del_vqs(struct virtio_device *vdev) +{ + struct virtqueue *vq, *n; + + list_for_each_entry_safe(vq, n, &vdev->vqs, list) { + vring_del_virtqueue(vq); + } +} + +static struct virtqueue *crete_vnic_setup_vq(struct virtio_device *vdev, + unsigned int index, + void (*callback)(struct virtqueue *vq), + const char *name, bool ctx) +{ + struct crete_vnic_priv *vnic_info = to_vnic_net_device(vdev); + struct crete_core_dev *core_dev = to_vnic_core_device(vdev); + struct virtqueue *vq; + struct pci_dev *pdev = core_dev->pdev; + struct crete_vnic_msix_info *info; + int err; + int total_vqs = 2 * core_dev->cap.qpcap.max_qp_num; + u32 max_queue_size = core_dev->cap.qpcap.max_queue_size; + + if (!name) + return NULL; + if (index >= total_vqs || index >= CRETE_VNIC_MQ_MAX) + return ERR_PTR(-ENOENT); + /* Queue shouldn't already be set up. */ + + vq = vring_create_virtqueue(index, max_queue_size, PAGE_SIZE, vdev, + true, true, ctx, + crete_vnic_kick_vq, callback, name); + if (!vq) { + err = -ENOMEM; + goto error_new_virtqueue; + } + info = &vnic_info->msix_info[index]; + info->qid = index; + info->vq = vq; + vq->priv = + (void __force *)crete_vnic_signal_queue_init_notify(core_dev, + index); + if (!vq->priv) { + err = -ENOMEM; + goto error_new_virtqueue; + } + + if (callback) { + err = crete_vnic_signal_queue_init_irq(info, core_dev, index); + if (err) { + dev_err(&pdev->dev, + "crete_vnic_signal_queue_init_irq failed\n"); + err = -ENOMEM; + goto error_new_virtqueue; + } + } else { + info->irq = 0; + info->msix_vector = VIRTIO_MSI_NO_VECTOR; + info->ready = 0; + } + + err = + crete_vnic_signal_queue_create(core_dev, vq, index, + info->msix_vector); + if (err) { + dev_err(&pdev->dev, "create queue is error qid[%d]\n", index); + err = -ENOMEM; + goto error_new_virtqueue; + } + info->ready = 1; + err = crete_start_singlequeue(core_dev, index); + if (err) { + dev_err(&pdev->dev, "start queue [%d]is error\n", index); + err = -ENOMEM; + goto error_new_virtqueue; + } + + return vq; +error_new_virtqueue: + return ERR_PTR(err); +} + +static int crete_vnic_find_vqs(struct virtio_device *vdev, unsigned int nvqs, + struct virtqueue *vqs[], + vq_callback_t *callbacks[], + const char *const names[], + const bool *ctx, struct irq_affinity *desc) +{ + struct crete_core_dev *core_dev = to_vnic_core_device(vdev); + int i, err, queue_idx = 0; + + for (i = 0; i < nvqs; ++i) { + if (!names[i]) { + vqs[i] = NULL; + continue; + } + + vqs[i] = crete_vnic_setup_vq(vdev, queue_idx++, + callbacks[i], names[i], ctx ? + ctx[i] : false); + if (IS_ERR(vqs[i])) { + err = PTR_ERR(vqs[i]); + goto err_setup_vq; + } + } + return 0; +err_setup_vq: + crete_vnic_reset_io_queue(core_dev, i); + crete_vnic_del_vqs(vdev); + return err; +} + +static int crete_vnic_alloc_queues(struct crete_vnic_priv *vnic_info, + struct crete_core_dev *core_dev) +{ + struct net_device *netdev = core_dev->netdev; + int i, max_queue_pairs; + + max_queue_pairs = core_dev->cap.qpcap.max_qp_num; + vnic_info->sq = + kcalloc(max_queue_pairs, sizeof(*vnic_info->sq), GFP_KERNEL); + if (!vnic_info->sq) + goto err; + vnic_info->rq = + kcalloc(max_queue_pairs, sizeof(*vnic_info->rq), GFP_KERNEL); + if (!vnic_info->rq) + goto err_rq; + spin_lock_init(&vnic_info->refill_lock); + INIT_DELAYED_WORK(&vnic_info->refill, crete_vnic_alloc_recv_buf); + vnic_info->mergeable_rx_bufs = true; + for (i = 0; i < max_queue_pairs; i++) { + vnic_info->rq[i].pages = NULL; +#ifdef NETIF_NAPI_ADD_NEWAPI + netif_napi_add_weight(netdev, &vnic_info->rq[i].napi, crete_vnic_poll, + napi_weight); + netif_napi_add_tx_weight(netdev, &vnic_info->sq[i].napi, + crete_vnic_poll_tx, + napi_tx ? napi_weight : 0); +#else + netif_napi_add(netdev, &vnic_info->rq[i].napi, crete_vnic_poll, + napi_weight); + netif_tx_napi_add(netdev, &vnic_info->sq[i].napi, + crete_vnic_poll_tx, + napi_tx ? napi_weight : 0); +#endif + sg_init_table(vnic_info->rq[i].sg, + ARRAY_SIZE(vnic_info->rq[i].sg)); + ewma_pkt_len_init(&vnic_info->rq[i].mrg_avg_pkt_len); + sg_init_table(vnic_info->sq[i].sg, + ARRAY_SIZE(vnic_info->sq[i].sg)); + + u64_stats_init(&vnic_info->rq[i].stats.syncp); + u64_stats_init(&vnic_info->sq[i].stats.syncp); + } + + return 0; + +err_rq: + kfree(vnic_info->sq); +err: + return -ENOMEM; +} + +static void crete_vnic_free_queues(struct crete_vnic_priv *vnic_info, + struct crete_core_dev *core_dev) +{ + int i, max_queue_pairs; + + max_queue_pairs = core_dev->cap.qpcap.max_qp_num; + + for (i = 0; i < max_queue_pairs; i++) { + __netif_napi_del(&vnic_info->rq[i].napi); + __netif_napi_del(&vnic_info->sq[i].napi); + } + + /* We called __netif_napi_del(), + * we need to respect an RCU grace period before freeing vi->rq + */ + synchronize_net(); + + kfree(vnic_info->rq); + kfree(vnic_info->sq); +} + +static unsigned int crete_get_min_buf_len(struct virtqueue *vq) +{ + const unsigned int hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + unsigned int rq_size = virtqueue_get_vring_size(vq); + unsigned int packet_len = IP_MAX_MTU; + unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len; + unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size); + unsigned int ret; + + ret = + max(max(min_buf_len, hdr_len) - hdr_len, + (unsigned int)GOOD_PACKET_LEN); + return ret; +} + +static int crete_vnic_setup_vqs(struct crete_vnic_priv *vnic_info) +{ + vq_callback_t **callbacks; + struct virtqueue **vqs; + int ret = -ENOMEM; + int i, total_vqs; + const char **names; + bool *ctx; + struct crete_core_dev *core_dev = vnic_info->coredev; + + total_vqs = 2 * core_dev->cap.qpcap.max_qp_num; + vqs = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL); + if (!vqs) + goto err_vq; + callbacks = kmalloc_array(total_vqs, sizeof(*callbacks), GFP_KERNEL); + if (!callbacks) + goto err_callback; + names = kmalloc_array(total_vqs, sizeof(*names), GFP_KERNEL); + if (!names) + goto err_names; + if (!vnic_info->big_packets || vnic_info->mergeable_rx_bufs) { + ctx = kcalloc(total_vqs, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + goto err_ctx; + } else { + ctx = NULL; + } + + /* Parameters for control virtqueue, if any */ + + /* Allocate/initialize parameters for send/receive virtqueues */ + for (i = 0; i < core_dev->cap.qpcap.max_qp_num; i++) { + callbacks[rxq2vq(i)] = crete_vnic_recv_done; + callbacks[txq2vq(i)] = crete_vnic_xmit_done; + sprintf(vnic_info->rq[i].name, "vnic-input.%d", i); + sprintf(vnic_info->sq[i].name, "vnic-output.%d", i); + names[rxq2vq(i)] = vnic_info->rq[i].name; + names[txq2vq(i)] = vnic_info->sq[i].name; + if (ctx) + ctx[rxq2vq(i)] = true; + } + + ret = crete_vnic_find_vqs(&vnic_info->vdev, total_vqs, vqs, callbacks, + names, ctx, NULL); + if (ret) + goto err_find; + + for (i = 0; i < core_dev->cap.qpcap.max_qp_num; i++) { + vnic_info->rq[i].vq = vqs[rxq2vq(i)]; + vnic_info->rq[i].min_buf_len = crete_get_min_buf_len(vnic_info->rq[i].vq); + vnic_info->sq[i].vq = vqs[txq2vq(i)]; + } + +err_find: + kfree(ctx); +err_ctx: + kfree(names); +err_names: + kfree(callbacks); +err_callback: + kfree(vqs); +err_vq: + return ret; +} + +static int crete_vnic_request_rings(struct crete_core_dev *core_dev) +{ + + struct net_device *netdev = core_dev->netdev; + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct pci_dev *pdev = core_dev->pdev; + int ret = 0; + + ret = crete_vnic_alloc_queues(priv, core_dev); + if (ret) { + dev_err(&pdev->dev, "crete_vnic_alloc_queues failed\n"); + return -ENOMEM; + } + ret = crete_vnic_setup_vqs(priv); + if (ret) { + dev_err(&pdev->dev, "crete_vnic_setup_vqs failed\n"); + goto alloc_queues; + } + return 0; +alloc_queues: + crete_vnic_free_queues(priv, core_dev); + return ret; +} + +static void crete_vnic_distroy_rings(struct crete_core_dev *core_dev) +{ + + struct net_device *netdev = core_dev->netdev; + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct virtio_device *vdev = &priv->vdev; + + crete_vnic_del_vqs(vdev); + crete_vnic_free_queues(priv, core_dev); +} + +static void crete_nic_negotiate_driver_features(struct crete_core_dev *core_dev) +{ + u64 device_features; + u64 driver_features; + int i, feature_table_size; + + device_features = core_dev->cap.hw_features; + feature_table_size = ARRAY_SIZE(crete_vnic_features), + /* Figure out what features the driver supports. */ + driver_features = 0; + for (i = 0; i < feature_table_size; i++) { + unsigned int f = crete_vnic_features[i]; + + BUG_ON(f >= 64); + driver_features |= (1ULL << f); + } + + core_dev->cap.driver_features = driver_features & device_features; + + /* Transport features always preserved to pass to finalize_features. */ + for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) + if (device_features & (1ULL << i)) + core_dev->cap.driver_features |= BIT_ULL(i); + +} + +static inline bool crete_vnic_has_feature(struct crete_core_dev *core_dev, + unsigned int fbit) +{ + bool ret = false; + + ret = !!(core_dev->cap.driver_features & BIT_ULL(fbit)); + return ret; +} + +static int crete_build_vnic_netdev_features(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int i; + + netdev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE; + netdev->features = NETIF_F_HIGHDMA; + crete_build_ptys2ethtool_map(); + crete_set_netdev_ops(netdev); + crete_set_ethtool_ops(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); + + /* Do we support "hardware" checksums? */ + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_CSUM)) { + /* This opens up the world of extra features. */ + netdev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG; + if (csum) + netdev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; + + /* Individual feature bits: what can host handle? */ + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_HOST_TSO4)) + netdev->hw_features |= NETIF_F_TSO; + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_HOST_TSO6)) + netdev->hw_features |= NETIF_F_TSO6; + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_HOST_ECN)) + netdev->hw_features |= NETIF_F_TSO_ECN; + + netdev->features |= NETIF_F_GSO_ROBUST; + + if (gso) + netdev->features |= + netdev->hw_features & NETIF_F_ALL_TSO; + /* (!csum && gso) case will be fixed by register_netdev() */ + } + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_GUEST_CSUM)) + netdev->features |= NETIF_F_RXCSUM; + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_GUEST_TSO4) || + crete_vnic_has_feature(core_dev, VIRTIO_NET_F_GUEST_TSO6)) + netdev->features |= NETIF_F_GRO_HW; + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) + netdev->hw_features |= NETIF_F_GRO_HW; + netdev->vlan_features = netdev->features; + + for (i = 0; i < ARRAY_SIZE(crete_vnic_guest_offloads); i++) + if (crete_vnic_has_feature + (core_dev, crete_vnic_guest_offloads[i])) + set_bit(crete_vnic_guest_offloads[i], + &priv->guest_offloads); + priv->guest_offloads_capable = priv->guest_offloads; + return 0; +} + +static int crete_vnic_init_mac_addr(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_net_common_cfg *netcfg = &priv->net_cfg; + struct crete_core_dev *core_dev = priv->coredev; + + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_MAC)) + memcpy(netdev->dev_addr, netcfg->mac, ETH_ALEN); + else + eth_hw_addr_random(netdev); + + return 0; +} + +int crete_vnic_set_mac_address(struct net_device *dev, void *p); +static int crete_vnic_init_mac_addr_new(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct sockaddr addr; + int err = 0; + + memset(&addr, 0, sizeof(struct sockaddr)); + /* init get the mac default address */ + err = crete_get_dev_macattr(core_dev, &addr); + if (err) { + dev_err(&pdev->dev, "vnic get default mac address faile\n"); + return -1; + } + + /* config the default mac */ + err = crete_vnic_set_mac_address(netdev, (void *)(&addr)); + if (err) { + dev_err(&pdev->dev, "vnic get default mac address faile\n"); + return -1; + } + + return 0; +} + +static int crete_vnic_init_mtu(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_net_common_cfg *netcfg = &priv->net_cfg; + int vnic_mtu = 1500; + int err = 0; + + /* MTU range: 68 - 65535 */ + + netdev->min_mtu = ETH_MIN_MTU; + netdev->max_mtu = ETH_MAX_MTU; + if (crete_vnic_has_feature(core_dev, VIRTIO_NET_F_MTU)) { + vnic_mtu = netcfg->mtu; + if (vnic_mtu < netdev->min_mtu) { + /* Should never trigger: MTU was previously validated + * in virtnet_validate. + */ + dev_err(&pdev->dev, + "device MTU appears to have changed it is now %d < %d", + vnic_mtu, netdev->min_mtu); + err = -EINVAL; + return err; + } + + netdev->mtu = vnic_mtu; + netdev->max_mtu = ETH_MAX_MTU; + } else { + + netdev->mtu = 1500; + netdev->max_mtu = ETH_MAX_MTU; + } + + err = crete_set_port_mtu(core_dev, CRETE_SET_MTU_MACPORT, MAC_MTU(netdev->mtu)); + if (err) { + dev_err(&pdev->dev,"init port mtu (%u) error info\n", netdev->mtu); + return err; + } + return 0; +} + +static int crete_vnic_init_mru(struct net_device *netdev) +{ + + return 0; +} + +#define NEW_MAC_ADDRESS "\x56\x48\x4d\x47\x00\x00" +#define NEW_MAC_ADDRESS1 "\x56\x48\x4d\x47\x00\x01" +int crete_vport_get_net_comm_cfg(struct crete_core_dev *cdev, + struct crete_net_common_cfg *netcfg) +{ + //int ret = 0; +//todo :get form vdev + static int mac_index = 0; + netcfg->vportid = 0; + netcfg->speed = 0x01; + netcfg->duplex = 0x01; + netcfg->mtu = 1500; + netcfg->vlanid = 0xffff; + memcpy(netcfg->mac, NEW_MAC_ADDRESS, ETH_ALEN); + if( mac_index) + memcpy(netcfg->mac, NEW_MAC_ADDRESS1, ETH_ALEN); + mac_index ++ ; + crete_info(cdev->device, + "vportid[%d] speed[0x%x] duplex[0x%x] mtu[%d] vlanid[%d] mac[%pM]\n", + netcfg->vportid, netcfg->speed, netcfg->duplex, + netcfg->mtu, netcfg->vlanid, netcfg->mac); + + return 0; +} + +static int crete_vnic_init_net_cfg(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_net_common_cfg *netcfg = &priv->net_cfg; + int ret = 0; + + ret = crete_vport_get_net_comm_cfg(core_dev, netcfg); + if (ret) { + dev_err(&pdev->dev, "get net cfg erro ret %d\n", ret); + goto err; + } + ret = crete_vnic_init_mac_addr_new(netdev); + if (ret) { + dev_err(&pdev->dev, "Unable to initialize mac address. Use the ramdom mac\n"); + crete_vnic_init_mac_addr(netdev); + } + ret = crete_vnic_init_mtu(netdev); + if (ret) { + dev_err(&pdev->dev, "Unable to initialize mtu.\n"); + goto err; + } + ret = crete_vnic_init_mru(netdev); + if (ret) { + dev_err(&pdev->dev, "Unable to initialize mru.\n"); + goto err; + } + +err: + return ret; +} + +static void crete_virtio_release_dev(struct device *_d) +{ + struct virtio_device *vdev = + container_of(_d, struct virtio_device, dev); + struct crete_vnic_priv *priv = + container_of(vdev, struct crete_vnic_priv, vdev); + struct crete_core_dev *core_dev = priv->coredev; + + dev_info(core_dev->device, "release virtio device\n"); +} + +static int crete_vnic_set_priv(struct net_device *netdev) +{ + struct crete_vnic_priv *priv = netdev_priv(netdev); + struct crete_core_dev *core_dev = priv->coredev; + struct pci_dev *pdev = core_dev->pdev; + int maxqueue = 2 * core_dev->cap.qpcap.max_qp_num; + struct virtio_device *vdev = &priv->vdev; + int ret = 0; + int i; + + vdev->priv = priv; + vdev->dev.parent = &pdev->dev; + vdev->dev.release = crete_virtio_release_dev; + priv->curr_queue_pairs = core_dev->ring_size; + priv->max_queue_pairs = core_dev->cap.qpcap.max_qp_num; + //crete_vnic_priv->vdev.config = &crete_vnic_config_ops; + + //INIT_LIST_HEAD(&crete_vnic_priv->vvdev->featuresirtqueues); + spin_lock_init(&priv->lock); + + vdev->id.vendor = CRETE_VIRTIO_VENDOR_ID; + vdev->id.device = CRETE_VIRTIO_DEVICE_ID; + vdev->features = core_dev->cap.driver_features; + + spin_lock_init(&vdev->config_lock); + vdev->config_enabled = false; + vdev->config_change_pending = false; + INIT_LIST_HEAD(&vdev->vqs); + spin_lock_init(&vdev->vqs_list_lock); + + for (i = 0; i < maxqueue; i++) { + priv->msix_info[i].irq = 0; + priv->msix_info[i].msix_vector = VIRTIO_MSI_NO_VECTOR; + priv->msix_info[i].ready = 0; + priv->msix_info[i].vq = NULL; + } + + ret = crete_cmd_set_features(core_dev, CRETE_VIRTIO_NET_DEV_FEAT, + vdev->features); + if (ret) { + dev_err(&pdev->dev, "crete set features 0x%llx failed\n", + vdev->features); + goto err; + } + + ret = crete_set_status(core_dev, CRETE_NET_DEV_STATUS, + CRETE_NET_DEV_FEATURE_OK); + if (ret) { + dev_err(&pdev->dev, "crete cmd set status %u failed\n", + CRETE_NET_DEV_FEATURE_OK); + goto err; + } + + priv->big_packets = true; + priv->mergeable_rx_bufs = true; + priv->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + priv->any_header_sg = true; + netif_set_real_num_tx_queues(netdev, priv->curr_queue_pairs); + netif_set_real_num_rx_queues(netdev, priv->curr_queue_pairs); + return ret; +err: + return ret; +} + +int crete_vnic_trim_rings(struct crete_core_dev *cdev) +{ + int cpunums = num_online_cpus(); + int maxqpnums = cdev->cap.qpcap.max_qp_num; + + if (maxqpnums > CRETE_VNIC_MAX_QUEUES) { + cdev->cap.qpcap.max_qp_num = CRETE_VNIC_MAX_QUEUES; + crete_err(cdev->device, "max qp greater than %d\n", + CRETE_VNIC_MAX_QUEUES); + } + cdev->ring_size = min(cpunums, maxqpnums); + if (!cdev->ring_size) { + crete_err(cdev->device, "ring size zero not right\n"); + return -1; + } + return 0; +} +void crete_vnic_set_rx_mode_work(struct work_struct *work); + +static int crete_vnic_net_init(struct crete_core_dev *core_dev) +{ + struct pci_dev *pdev = core_dev->pdev; + struct device *dev = &pdev->dev; + struct crete_vnic_priv *priv; + struct net_device *netdev; + int err; + + /* reserve the ring size */ + err = crete_vnic_trim_rings(core_dev); + if (err) + return err; + + netdev = crete_vnic_create_netdev(core_dev); + if (!netdev) { + dev_err(dev, "crete_create_netdev failed\n"); + return -ENOMEM; + } + + priv = netdev_priv(netdev); + crete_build_common_netdev(netdev); + err = crete_build_vnic_netdev_features(netdev); + if (err) { + dev_err(dev, "build netdev features failed, %d\n", err); + goto err_crete_create_netdev; + } + + err = crete_get_func_caps(core_dev); + if (err < 0) { + dev_err(dev, "init func err\n"); + goto err_crete_create_netdev; + } + + err = crete_vnic_set_priv(netdev); + if (err) { + dev_err(dev, "Unable to initialize prive.\n"); + goto err_crete_create_netdev; + } + + err = crete_vnic_init_net_cfg(netdev); + if (err) { + dev_err(dev, "Unable to initialize mac address.\n"); + goto err_init_set_priv; + } + + err = crete_vnic_request_rings(core_dev); + if (err) { + dev_err(dev, "Reserve rings failed\n"); + goto err_init_set_priv; + } + priv->wq = create_singlethread_workqueue("crete_nic_wq"); + if (!priv->wq) { + dev_err(dev, "Reserve workqueue faild\n"); + err = -ENOMEM; + goto err_init_set_priv; + } + /* init rx mode work */ + INIT_WORK(&priv->set_rx_mode_work, crete_vnic_set_rx_mode_work); + + err = crete_vnic_register_event_handler(netdev); + if (err) { + dev_err(dev, "register evnet faild\n"); + crete_vnic_unregister_event_handler(netdev); + goto err_init_set_priv; + } + return 0; +//err_request_rings: +// crete_vnic_distroy_rings(core_dev); +err_init_set_priv: +err_crete_create_netdev: + priv = netdev_priv(netdev); + crete_vnic_priv_cleanup(priv); + return err; +} + +int crete_vnic_net_del(struct crete_core_dev *core_dev) +{ + struct net_device *netdev = core_dev->netdev; + struct crete_vnic_priv *priv; + struct workqueue_struct *wq; + + priv = netdev_priv(netdev); + wq = priv->wq; + crete_vnic_unregister_event_handler(netdev); + destroy_workqueue(wq); + crete_vnic_distroy_rings(core_dev); + crete_vnic_priv_cleanup(priv); + priv->wq = NULL; + return 0; +} + +static int crete_vnic_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct crete_aux_dev *cadev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = cadev->core_dev; + struct pci_dev *pdev = core_dev->pdev; + struct device *dev = &pdev->dev; + enum crete_feature_opcode op = CRETE_VIRTIO_NET_DEV_FEAT; + enum crete_dev_type crete_pci_type = CRETE_VNET_DEV; + struct crete_vnic_priv *priv = NULL; + int ret; + + ret = crete_nic_set_device_type(core_dev, crete_pci_type); + if (ret) { + dev_err(dev, "Failed to set device type pnic\n"); + return -EINVAL; + } + + ret = crete_set_status(core_dev, CRETE_NET_DEV_STATUS, + CRETE_NET_DEV_STARTUP); + if (ret) { + dev_err(dev, "crete cmd set status %u failed\n", + CRETE_NET_DEV_STARTUP); + return -EINVAL; + } + /* get core dev cap init */ + ret = crete_net_get_max_supported_vqs(core_dev); + if (ret) { + dev_err(dev, "crete core dev get qpcap failed\n"); + return -EINVAL; + } + + ret = crete_net_get_supported_features(core_dev, op); + if (ret) { + dev_err(dev, "crete core dev get features failed\n"); + return -EINVAL; + } + crete_nic_negotiate_driver_features(core_dev); + ret = crete_vnic_net_init(core_dev); + if (ret) { + dev_err(dev, "Failed to init net dev management\n"); + goto err_return; + } + ret = register_netdev(core_dev->netdev); + if (ret) { + dev_err(dev, "register_netdev failed, %d\n", ret); + goto err_net_init; + } + + priv = netdev_priv(core_dev->netdev); + /* config the netdev queue pairs */ + ret = crete_vnic_set_queues(core_dev->netdev, priv->curr_queue_pairs); + if (ret) { + dev_err(dev, "crete vnic set queues %d failed\n", priv->curr_queue_pairs); + goto err_net_registert; + } + + netif_carrier_off(core_dev->netdev); + ret = + crete_set_status(core_dev, CRETE_NET_DEV_STATUS, + CRETE_NET_DEV_DEV_OK); + if (ret) { + dev_err(dev, "Failed to set device CRETE_NET_DEV_DEV_OK\n"); + goto err_net_registert; + } + +#if 0 + /* carrier off reporting is important to ethtool even BEFORE open */ + if (crete_vnic_get_link_state(core_dev)) + netif_carrier_on(core_dev->netdev); + else + netif_carrier_off(core_dev->netdev); +#endif + + dev_set_drvdata(&adev->dev, core_dev); + //crete_vnic_debugfs_add_dev(cvm); + //crete_vnic_debugfs_add_hcap(cvm); + return 0; +err_net_registert: + unregister_netdev(core_dev->netdev); +err_net_init: + crete_vnic_net_del(core_dev); +err_return: + return ret; +} + +static void crete_vnic_reset_device(struct crete_core_dev *core_dev) +{ + + int ret; + enum crete_net_status op = CRETE_NET_DEV_STARTUP; + int max_queue = core_dev->cap.qpcap.max_qp_num * 2; + + crete_vnic_reset_io_queue(core_dev, max_queue); + ret = crete_set_status(core_dev, CRETE_NET_DEV_STATUS, op); + if (ret) { + crete_err(core_dev->device, "crete cmd set status %u failed\n", + op); + WARN_ON(1); + } + +} + +static void crete_remove_vq_common(struct crete_core_dev *core_dev) +{ + struct net_device *netdev = core_dev->netdev; + struct crete_vnic_priv *priv = netdev_priv(netdev); + + crete_vnic_reset_device(core_dev); + /* Free unused buffers in both send and recv, if any. */ + free_unused_bufs(priv); //todo + + free_receive_bufs(priv); //todo + + free_receive_page_frags(priv); //todo + crete_vnic_net_del(core_dev); + free_netdev(netdev); + core_dev->netdev = NULL; +} + +/* + * about the anolis 5.10.134-14 kernel version + * auxliary define with return int value + */ +#ifdef SNIC_ANOLIS_VERSION14 +static int crete_vnic_remove(struct auxiliary_device *adev) +{ + struct crete_aux_dev *cadev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = cadev->core_dev; + struct pci_dev *pdev = core_dev->pdev; + struct device *dev = &pdev->dev; + struct crete_vnic_priv *priv = netdev_priv(core_dev->netdev); + + cancel_work_sync(&priv->set_rx_mode_work); + unregister_netdev(core_dev->netdev); + crete_remove_vq_common(core_dev); + dev_set_drvdata(&adev->dev, NULL); + dev_info(dev, "crete vnic remove\n"); + return 0; + +} + +#else + +static void crete_vnic_remove(struct auxiliary_device *adev) +{ + struct crete_aux_dev *cadev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = cadev->core_dev; + struct pci_dev *pdev = core_dev->pdev; + struct device *dev = &pdev->dev; + struct crete_vnic_priv *priv = netdev_priv(core_dev->netdev); + + cancel_work_sync(&priv->set_rx_mode_work); + unregister_netdev(core_dev->netdev); + crete_remove_vq_common(core_dev); + dev_set_drvdata(&adev->dev, NULL); + dev_info(dev, "crete vnic remove\n"); +} + +#endif + +static const struct auxiliary_device_id crete_vnic_id_table[] = { + {.name = CRETE_VNIC_AUX_DEV_NAME,}, + {}, +}; + +static struct auxiliary_driver crete_vnic_driver = { + .name = CRETE_VNIC_DRV_NAME, + .probe = crete_vnic_probe, + .remove = crete_vnic_remove, + .id_table = crete_vnic_id_table, +}; + +static void __exit crete_vnic_cleanup(void) +{ + auxiliary_driver_unregister(&crete_vnic_driver); + +// crete_vnet_debugfs_destroy(); +} + +module_exit(crete_vnic_cleanup); + +static int __init crete_vnic_init(void) +{ + int err; + +// crete_nic_debugfs_create(); + err = auxiliary_driver_register(&crete_vnic_driver); + if (err) { + pr_err("%s: aux driver register failed: %pe\n", + CRETE_NIC_DRV_NAME, ERR_PTR(err)); + //crete_nic_debugfs_destroy(); + } + + return err; +} + +module_init(crete_vnic_init); + +MODULE_DESCRIPTION(CRETE_NIC_DRV_DESCRIPTION); +MODULE_AUTHOR("jaguarmicro.com"); +MODULE_LICENSE("GPL"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/Makefile b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/Makefile new file mode 100644 index 0000000..68b0651 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/Makefile @@ -0,0 +1,166 @@ +# SPDX-License-Identifier: GPL-2.0-only + +# When the make command line has the goal 'all' or no goal specified (i.e. +# when compiling the driver) a sub-make of the kernel's Makefile includes +# the kernel configuration (include/config/auto.conf), but if any other +# goal is specified (e.g. install) the kernel configuration does not get +# included. Set a variable and export it to track over sub-makes. +ifeq ($(MAKELEVEL),0) + ifeq ($(filter-out all, $(MAKECMDGOALS)),) + export KERNEL_CONFIG_INCLUDED=1 + endif +endif + +# Explicitly set shell to bash, to avoid issues on distros with a different +# default shell. Looking at you, Ubuntu. +SHELL=/bin/bash + +COMMON_MK ?= $(wildcard $(src)/common.mk) +ifeq (${COMMON_MK},) + override src = . + COMMON_MK = $(wildcard $(src)/common.mk) +endif +ifeq (${COMMON_MK},) + $(error Cannot find common.mk build rules) +else + include ${COMMON_MK} +endif + +# SIOV support is only supported if the kernel has features for controlling +# PASID support. Do not even try to build SIOV support if the kernel lacks +# the necessary infrastructure. +ifeq ($(call is_kcompat_defined,HAVE_PASID_SUPPORT),1) +ifeq ($(call is_kcompat_defined,HAVE_IOMMU_DEV_FEAT_AUX),1) +export ENABLE_SIOV_SUPPORT := 1 +endif +endif + +# LM support is only enabled if the kernel has features for LM v1 protocol. +# If the kernel lacks the necessary infrastructure, LM support will be disabled. +ifeq ($(call is_kcompat_defined,HAVE_LMV1_SUPPORT),1) +export ENABLE_LM_SUPPORT := 1 +endif + +ifneq ($(KERNELRELEASE),) +# kbuild part of makefile +# +ccflags-y += -I$(src) +subdir-ccflags-y += -I$(src) + +obj-m += crete_vdpa.o + +crete_vdpa-y := crete_vdpa_main.o \ + crete_vdpa_dev.o \ + + +else # ifneq($(KERNELRELEASE),) +# normal makefile + +DRIVER := crete_vdpa +EXTRA_CFLAGS += -std=gnu11 + +# ice does not support building on kernels older than 3.10.0 +$(call minimum_kver_check,3,10,0) + +# Command to update initramfs or display a warning message +ifeq (${cmd_initrd},) +define cmd_initramfs +@echo "Unable to update initramfs. You may need to do this manually." +endef +else +define cmd_initramfs +@echo "Updating initramfs..." +$(call cmd_initrd) +endef +endif + +all: + +$(call kernelbuild,modules) + #@gzip -c ../${DRIVER}.${MANSECTION} > ${DRIVER}.${MANSECTION}.gz +ifneq ($(wildcard lttng),) + $(MAKE) -C lttng +endif + +clean: + +$(call kernelbuild,clean) + @-rm -rf *.${MANSECTION}.gz *.ko +ifneq ($(wildcard lttng),) + $(MAKE) -C lttng clean +endif + +# Install kernel module files. This target is called by the RPM specfile when +# generating binary RPMs, and is not expected to modify files outside of the +# build root. Thus, it must not update initramfs, or run depmod. +modules_install: all + +$(call kernelbuild,modules_install) +#$(MAKE) auxiliary_install + +# Install kernel module files without auxiliary. This target is called by the +# RPM specfile when generating binary RPMs, and is not expected to modify +# files outside of the build root. Thus, it must not update initramfs, or run depmod. +modules_install_no_aux: + @+$(call kernelbuild,modules_install) + +mandocs_install: all + install -D -m 644 ${DRIVER}.${MANSECTION}.gz ${INSTALL_MOD_PATH}/${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz + +# After installing all the files, perform necessary work to ensure the system +# will use the new modules. This includes running depmod to update module +# dependencies and updating the initramfs image in case the module is loaded +# during early boot. +install: modules_install + $(call cmd_depmod) + $(call cmd_initramfs) + +# Remove installed module files. This target is called by the RPM specfile when +# generating binary RPMs, and is not expected to modify files outside of the +# build root. Thus, it must not update the initramfs image or run depmod. +modules_uninstall: + rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko + #$(MAKE) auxiliary_uninstall + +mandocs_uninstall: + rm -f ${INSTALL_MOD_PATH}/${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz 2>/dev/null + +# After uninstalling all the files, perform necessary work to restore the +# system back to using the default kernel modules. This includes running depmod +# to update module dependencies and updating the initramfs image. +uninstall: modules_uninstall + $(call cmd_depmod) + $(call cmd_initramfs) + +#auxiliary_info: +# @../scripts/check_aux_bus --verbose --ksrc="${KSRC}" --build-kernel="${BUILD_KERNEL}" + +#auxiliary_install: +# ${auxiliary_post_install} + +#auxiliary_uninstall: +# ${auxiliary_post_uninstall} + +#ifeq (${NEED_AUX_BUS},1) +#all: auxiliary_info +#endif + +help: + @echo 'Building external (out-of-tree) modules:' + @echo ' all - default target, build the module(s) and manpage' + @echo ' clean - remove generated files' + @echo ' modules_install - install the module(s) only' + @echo ' install - install the module(s) and manpage, and update initramfs' + @echo ' modules_uninstall - uninstall the module(s) only' + @echo ' uninstall - uninstall the module(s) and manpage, and update initramfs' + @echo '' + @echo 'Command-line options:' + @echo ' KSRC= - Path to kernel source (defaults to running kernel)' + @echo ' LINUX_VERSION= - Debug tool to force kernel LINUX_VERSION_CODE for' + @echo ' external module(s). *** Use at your own risk! ***' + @echo ' INSTALL_MOD_PATH= - Prefix added to default module(s) installation path' + @echo ' (/lib/modules/$$(KERNELRELEASE)/)' + @echo ' INSTALL_MOD_DIR= - Install module(s) in subdirectory other than default' + @echo ' (.../updates/drivers/net/ethernet/jm/${DRIVER}/)' + @echo '' + +.PHONY: all clean modules_install install modules_uninstall uninstall help + +endif # ifneq($(KERNELRELEASE),) diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_anos.sh b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_anos.sh new file mode 100755 index 0000000..dda52c6 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_anos.sh @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +#!/bin/bash +# common build rules useful for out-of-tree Linux driver builds +# +make clean + +make EXTRA_CFLAGS="-DHAVE_VDPA_JMND_OPS" + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_euler.sh b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_euler.sh new file mode 100755 index 0000000..041b071 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_euler.sh @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +#!/bin/bash +# common build rules useful for out-of-tree Linux driver builds +# +make clean + +make EXTRA_CFLAGS="-DHAVE_VDPA_EULER_OPS" + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/common.mk b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/common.mk new file mode 100644 index 0000000..b96aed1 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/common.mk @@ -0,0 +1,454 @@ +# SPDX-License-Identifier: GPL-2.0-only + +# +# common Makefile rules useful for out-of-tree Linux driver builds +# +# Usage: include common.mk +# +# After including, you probably want to add a minimum_kver_check call +# +# Required Variables: +# DRIVER +# -- Set to the lowercase driver name + +##################### +# Helpful functions # +##################### + +SHELL := $(shell which bash) +src ?= $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +readlink = $(shell readlink -f ${1}) + +# helper functions for converting kernel version to version codes +get_kver = $(or $(word ${2},$(subst ., ,${1})),0) +get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \ + [ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \ + [ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \ + printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) ) + +################ +# depmod Macro # +################ + +cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \ + $(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \ + -a ${KVER} + +##################### +# Environment tests # +##################### + +DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]") + +ifeq (,${BUILD_KERNEL}) +BUILD_KERNEL=$(shell uname -r) +endif + +# Kernel Search Path +# All the places we look for kernel source +KSP := /lib/modules/${BUILD_KERNEL}/source \ + /lib/modules/${BUILD_KERNEL}/build \ + /usr/src/linux-${BUILD_KERNEL} \ + /usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \ + /usr/src/kernel-headers-${BUILD_KERNEL} \ + /usr/src/kernel-source-${BUILD_KERNEL} \ + /usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ + /usr/src/linux \ + /usr/src/kernels/${BUILD_KERNEL} \ + /usr/src/kernels + +# prune the list down to only values that exist and have an include/linux +# sub-directory. We can't use include/config because some older kernels don't +# have this. +test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir}) +KSP := $(foreach dir, ${KSP}, ${test_dir}) + +# we will use this first valid entry in the search path +ifeq (,${KSRC}) + KSRC := $(firstword ${KSP}) +endif + +ifeq (,${KSRC}) + $(warning *** Kernel header files not in any of the expected locations.) + $(warning *** Install the appropriate kernel development package, e.g.) + $(error kernel-devel, for building kernel modules and try again) +else +ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC}) + KOBJ := /lib/modules/${BUILD_KERNEL}/build +else + KOBJ := ${KSRC} +endif +endif + +SCRIPT_PATH := ${KSRC}/scripts +info_signed_modules = + +ifeq (,${SCRIPT_PATH}) + info_signed_modules += echo "*** Could not find sign-file script. Cannot sign driver." ; +else + SIGN_FILE_EXISTS := $(or $(and $(wildcard $(SCRIPT_PATH)/sign-file),1),) + PRIV_KEY_EXISTS := $(or $(and $(wildcard jm-linux-key.key),1),) + PUB_KEY_EXISTS := $(or $(and $(wildcard jm-linux-key.crt),1),) +ifneq ($(and $(SIGN_FILE_EXISTS),$(PRIV_KEY_EXISTS),$(PUB_KEY_EXISTS)),) + info_signed_modules += \ + echo "*** Is sign-file present: ${SIGN_FILE_EXISTS}" ; \ + echo "*** Is private key present: ${PRIV_KEY_EXISTS}" ; \ + echo "*** Is public key present: ${PUB_KEY_EXISTS}" ; + info_signed_modules += echo "*** All files are present, signing driver." ; + sign_driver = $(shell ${SCRIPT_PATH}/sign-file sha256 jm-linux-key.key \ + intel-linux-key.crt ${DRIVER}.ko) +else + info_signed_modules += echo "*** Files are missing, cannot sign driver." ; + sign_driver = +endif +endif + +# Version file Search Path +VSP := ${KOBJ}/include/generated/utsrelease.h \ + ${KOBJ}/include/linux/utsrelease.h \ + ${KOBJ}/include/linux/version.h \ + ${KOBJ}/include/generated/uapi/linux/version.h \ + /boot/vmlinuz.version.h + +# Config file Search Path +CSP := ${KOBJ}/include/generated/autoconf.h \ + ${KOBJ}/include/linux/autoconf.h \ + /boot/vmlinuz.autoconf.h + +# System.map Search Path (for depmod) +MSP := ${KSRC}/System.map \ + /usr/lib/debug/boot/System.map-${BUILD_KERNEL} \ + /boot/System.map-${BUILD_KERNEL} + +# prune the lists down to only files that exist +test_file = $(shell [ -f ${1} ] && echo ${1}) +VSP := $(foreach file, ${VSP}, $(call test_file,${file})) +CSP := $(foreach file, ${CSP}, $(call test_file,${file})) +MSP := $(foreach file, ${MSP}, $(call test_file,${file})) + + +# and use the first valid entry in the Search Paths +ifeq (,${VERSION_FILE}) + VERSION_FILE := $(firstword ${VSP}) +endif + +ifeq (,${CONFIG_FILE}) + CONFIG_FILE := $(firstword ${CSP}) +endif + +ifeq (,${SYSTEM_MAP_FILE}) + SYSTEM_MAP_FILE := $(firstword ${MSP}) +endif + +ifeq (,$(wildcard ${VERSION_FILE})) + $(error Linux kernel source not configured - missing version header file) +endif + +ifeq (,$(wildcard ${CONFIG_FILE})) + $(error Linux kernel source not configured - missing autoconf.h) +endif + +ifeq (,$(wildcard ${SYSTEM_MAP_FILE})) + $(warning Missing System.map file - depmod will not check for missing symbols during module installation) +endif + +ifneq ($(words $(subst :, ,$(CURDIR))), 1) + $(error Sources directory '$(CURDIR)' cannot contain spaces nor colons. Rename directory or move sources to another path) +endif + +######################## +# Extract config value # +######################## + +get_config_value = $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\ + grep -m 1 ${1} | awk '{ print $$3 }') + +################ +# dracut Macro # +################ + +cmd_initrd := $(shell \ + if [[ ${KOBJ} != /lib/modules/${BUILD_KERNEL}/* ]]; then \ + echo ""; \ + elif which dracut > /dev/null 2>&1 ; then \ + echo "dracut --force --kver ${BUILD_KERNEL}"; \ + elif which update-initramfs > /dev/null 2>&1 ; then \ + echo "update-initramfs -u -k ${BUILD_KERNEL}"; \ + fi ) + +######################## +# Check module signing # +######################## + +CONFIG_MODULE_SIG_ALL := $(call get_config_value,CONFIG_MODULE_SIG_ALL) +CONFIG_MODULE_SIG_FORCE := $(call get_config_value,CONFIG_MODULE_SIG_FORCE) +CONFIG_MODULE_SIG_KEY := $(call get_config_value,CONFIG_MODULE_SIG_KEY) + +SIG_KEY_SP := ${KOBJ}/${CONFIG_MODULE_SIG_KEY} \ + ${KOBJ}/certs/signing_key.pem + +SIG_KEY_FILE := $(firstword $(foreach file, ${SIG_KEY_SP}, $(call test_file,${file}))) + +# print a warning if the kernel configuration attempts to sign modules but +# the signing key can't be found. +ifneq (${SIG_KEY_FILE},) +warn_signed_modules := : ; +else +warn_signed_modules := +ifeq (${CONFIG_MODULE_SIG_ALL},1) +warn_signed_modules += \ + echo "*** The target kernel has CONFIG_MODULE_SIG_ALL enabled, but" ; \ + echo "*** the signing key cannot be found. Module signing has been" ; \ + echo "*** disabled for this build." ; +endif # CONFIG_MODULE_SIG_ALL=y +ifeq (${CONFIG_MODULE_SIG_FORCE},1) + warn_signed_modules += \ + echo "warning: The target kernel has CONFIG_MODULE_SIG_FORCE enabled," ; \ + echo "warning: but the signing key cannot be found. The module must" ; \ + echo "warning: be signed manually using 'scripts/sign-file'." ; +endif # CONFIG_MODULE_SIG_FORCE +DISABLE_MODULE_SIGNING := Yes +endif + +####################### +# Linux Version Setup # +####################### + +# The following command line parameter is intended for development of KCOMPAT +# against upstream kernels such as net-next which have broken or non-updated +# version codes in their Makefile. They are intended for debugging and +# development purpose only so that we can easily test new KCOMPAT early. If you +# don't know what this means, you do not need to set this flag. There is no +# arcane magic here. + +# Convert LINUX_VERSION into LINUX_VERSION_CODE +ifneq (${LINUX_VERSION},) + LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3)) +endif + +# Honor LINUX_VERSION_CODE +ifneq (${LINUX_VERSION_CODE},) + $(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.) + KVER_CODE := ${LINUX_VERSION_CODE} + EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE} +endif + +# Determine SLE_KERNEL_REVISION for SuSE SLE >= 11 (needed by kcompat) +# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string +# appended to the stable kernel version on which their kernel is based with +# additional versioning information (up to 3 numbers), a possible abbreviated +# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default +# or CONFIG_LOCALVERSION=-999.gdeadbee-default +# SLE >= 15SP3 added additional information about version and service pack +# to their kernel version e.g CONFIG_LOCALVERSION=-150300.59.43.1-default +# +# SLE_LOCALVERSION_CODE is also exported to support legacy kcompat.h +# definitions. +ifeq (1,$(call get_config_value,CONFIG_SUSE_KERNEL)) + +ifneq (10,$(call get_config_value,CONFIG_SLE_VERSION)) + + CONFIG_LOCALVERSION := $(call get_config_value,CONFIG_LOCALVERSION) + LOCALVERSION := $(shell echo ${CONFIG_LOCALVERSION} | \ + cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//') + LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1) +ifeq ($(shell test ${LOCALVER_A} -gt 65535; echo $$?),0) + LOCAL_VER_MAJOR := $(shell echo ${LOCALVER_A:0:3}) + LOCAL_VER_MINOR := $(shell echo ${LOCALVER_A:3:3}) + LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2) + LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3) + LOCALVER_D := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f4) + SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_B} \* 65536 + \ + 0${LOCALVER_C} \* 256 + 0${LOCALVER_D}) + EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE} + EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_B} +else + LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2) + LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3) + SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \ + 0${LOCALVER_B} \* 256 + 0${LOCALVER_C}) + EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE} + EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_A} +endif +endif +endif + +EXTRA_CFLAGS += ${CFLAGS_EXTRA} + +# get the kernel version - we use this to find the correct install path +KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \ + awk '{ print $$3 }' | sed 's/\"//g') + +# assume source symlink is the same as build, otherwise adjust KOBJ +ifneq (,$(wildcard /lib/modules/${KVER}/build)) + ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build)) + KOBJ=/lib/modules/${KVER}/build + endif +endif + +ifeq (${KVER_CODE},) + KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\ + grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g') +endif + +# minimum_kver_check +# +# helper function to provide uniform output for different drivers to abort the +# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)". +define _minimum_kver_check +ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?")) + $$(warning *** Aborting the build.) + $$(error This driver is not supported on kernel versions older than ${1}.${2}.${3}) +endif +endef +minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3})) + +############################# +# kcompat definitions setup # +############################# + +# In most cases, kcompat flags can be checked within the driver source files +# using simple CPP checks. However, it may be necessary to check for a flag +# value within the Makefile for some specific edge cases. For example, if an +# entire feature ought to be excluded on some kernels due to missing +# functionality. +# +# To support this, kcompat_defs.h is preprocessed and converted into a word list +# that can be checked to determine whether a given kcompat feature flag will +# be defined for this kernel. +# +# KCOMPAT_DEFINITIONS holds the set of all macros which are defined. Note +# this does include a large number of standard/builtin definitions. +# +# Use is_kcompat_defined as a $(call) function to check whether a given flag +# is defined or undefined. For example: +# +# ifeq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1) +# +# ifneq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1) +# +# The is_kcompat_defined function returns 1 if the macro name is defined, +# and the empty string otherwise. +# +# There is no mechanism to extract the value of the kcompat definition. +# Supporting this would be non-trivial as Make does not have a map variable +# type. +# +# Note that only the new layout is supported. Legacy definitions in +# kcompat.h are not supported. If you need to check one of these, please +# refactor it into the new layout. + +# call script that populates defines automatically +# +# since is_kcompat_defined() is a macro, it's "computed" before any target +# recipe, kcompat_generated_defs.h is needed prior to that, so needs to be +# generated also via $(shell) call, which makes error handling ugly +$(if $(shell \ + $(if $(findstring 1,${V}),,QUIET_COMPAT=1) \ + KSRC=${KSRC} OUT=${src}/kcompat_generated_defs.h CONFFILE=${CONFIG_FILE} \ + bash ${src}/kcompat-generator.sh && echo ok), , $(error kcompat-generator.sh failed)) + +KCOMPAT_DEFINITIONS := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM \ + -I${KOBJ}/include \ + -I${KOBJ}/include/generated/uapi \ + ${src}/kcompat_defs.h | awk '{ print $$2 }') + +is_kcompat_defined = $(if $(filter ${1},${KCOMPAT_DEFINITIONS}),1,) + +################ +# Manual Pages # +################ + +MANSECTION = 7 + +ifeq (,${MANDIR}) + # find the best place to install the man page + MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g') + ifneq (,${MANPATH}) + # test based on inclusion in MANPATH + test_dir = $(findstring ${dir}, ${MANPATH}) + else + # no MANPATH, test based on directory existence + test_dir = $(shell [ -e ${dir} ] && echo ${dir}) + endif + # our preferred install path + # should /usr/local/man be in here ? + MANDIR := /usr/share/man /usr/man + MANDIR := $(foreach dir, ${MANDIR}, ${test_dir}) + MANDIR := $(firstword ${MANDIR}) +endif +ifeq (,${MANDIR}) + # fallback to /usr/man + MANDIR := /usr/man +endif + +#################### +# CCFLAGS variable # +#################### + +# set correct CCFLAGS variable for kernels older than 2.6.24 +ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?)) +CCFLAGS_VAR := EXTRA_CFLAGS +else +CCFLAGS_VAR := ccflags-y +endif + +################# +# KBUILD_OUTPUT # +################# + +# Only set KBUILD_OUTPUT if the real paths of KOBJ and KSRC differ +ifneq ($(call readlink,${KSRC}),$(call readlink,${KOBJ})) +export KBUILD_OUTPUT ?= ${KOBJ} +endif + +############################ +# Module Install Directory # +############################ + +# Default to using updates/drivers/net/ethernet/jm/ path, since depmod since +# v3.1 defaults to checking updates folder first, and only checking kernels/ +# and extra afterwards. We use updates instead of kernel/* due to desire to +# prevent over-writing built-in modules files. +export INSTALL_MOD_DIR ?= updates/drivers/net/ethernet/jm/${DRIVER} + + +###################### +# Kernel Build Macro # +###################### + +# kernel build function +# ${1} is the kernel build target +# ${2} may contain any extra rules to pass directly to the sub-make process +# +# This function is expected to be executed by +# @+$(call kernelbuild,,) +# from within a Makefile recipe. +# +# The following variables are expected to be defined for its use: +# GCC_I_SYS -- if set it will enable use of gcc-i-sys.sh wrapper to use -isystem +# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS +# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable +# KSRC -- the location of the kernel source tree to build against +# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER +# W -- if set, enables the W= kernel warnings options +# C -- if set, enables the C= kernel sparse build options +# +# + +KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers +KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers +KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.symvers +#export KBUILD_EXTRA_SYMBOLS + +kernelbuild = $(call warn_signed_modules) \ + ${MAKE} $(if ${GCC_I_SYS},CC="${GCC_I_SYS}") \ + ${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \ + -C "${KSRC}" \ + CONFIG_${DRIVER_UPPERCASE}=m \ + $(if ${DISABLE_MODULE_SIGNING},CONFIG_MODULE_SIG=n) \ + $(if ${DISABLE_MODULE_SIGNING},CONFIG_MODULE_SIG_ALL=) \ + M="${CURDIR}" \ + $(if ${W},W="${W}") \ + $(if ${C},C="${C}") \ + ${2} ${1} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_dev.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_dev.c new file mode 100644 index 0000000..b435842 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_dev.c @@ -0,0 +1,2411 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * JaguarMicro virtual dev driver for virtio dataplane offloading + * + * Copyright (C) 2022 JaguarMicro Corporation. + * + * Author: Angus Chen + * + */ +#include +#include +#include +#include +#include +#include +#include "crete_vdpa_dev.h" +#include "../crete-core/crete_cmd_if.h" +#include + +#define JMND_PCI_DEV_TYPE_MASK 0x0010 + +static int batch_vq_state = 1; +module_param(batch_vq_state, int, 0444); +MODULE_PARM_DESC(batch_vq_state, "Batched get vq state 1 -Enable; 0 - Disable"); + +static int crete_queue_size = 512; +module_param(crete_queue_size, int, 0444); +MODULE_PARM_DESC(crete_queue_size, "512 default; 1024 - max"); + +static bool vf_irq = true; +module_param(vf_irq, bool, 0444); +MODULE_PARM_DESC(vf_irq, "enable the interupt for vf 1 - Auto; 0 - Disable interupt"); + +static bool vf_packed = false; +module_param(vf_packed, bool, 0444); +MODULE_PARM_DESC(vf_packed, "1 - packe; 0 - split"); + + +static struct virtio_device_id id_table_net[] = { + {VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID}, + {0}, +}; + +static struct virtio_device_id id_table_blk[] = { + {VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID}, + {0}, +}; + +static u32 get_dev_type(struct pci_dev *pdev) +{ + u32 dev_type; + + /* This drirver drives both modern virtio devices and transitional + * devices in modern mode. + * vDPA requires feature bit VIRTIO_F_ACCESS_PLATFORM, + * so legacy devices and transitional devices in legacy + * mode will not work for vDPA, this driver will not + * drive devices with legacy interface. + */ + + if (pdev->device < 0x1040) + dev_type = pdev->subsystem_device; + else + dev_type = pdev->device - 0x1040; + + if ( pdev->device & JMND_PCI_DEV_TYPE_MASK) + dev_type = VIRTIO_ID_BLOCK; + else + dev_type = VIRTIO_ID_NET; + + return dev_type; +} + +u32 crete_init_config_size(struct crete_vdpa *hw) +{ + u32 config_size; + + switch (hw->dev_type) { + case VIRTIO_ID_NET: + config_size = sizeof(struct virtio_net_config); + break; + case VIRTIO_ID_BLOCK: + config_size = sizeof(struct virtio_blk_config); + break; + default: + config_size = 0; + pr_err("VIRTIO ID %u not supported\n", hw->dev_type); + } + return config_size; +} + + +int crete_vdpa_driver_resetqueue(struct vdpa_device *vdpa_dev, + int startqueue, int endqueue); + +struct crete_adapter *vd_to_adapter(struct crete_vdpa *hw) +{ + return container_of(hw, struct crete_adapter, vd); +} + +struct crete_core_dev *vd_to_coredev(struct crete_vdpa *hw) +{ + struct crete_adapter *adapter = vd_to_adapter(hw); + struct crete_core_dev *core_dev = adapter->cdev; + return core_dev; +} + +static struct crete_adapter *vdpa_to_adapter(struct vdpa_device *vdpa_dev) +{ + return container_of(vdpa_dev, struct crete_adapter, vdpa); +} + +static struct crete_vdpa *vdpa_to_vd(struct vdpa_device *vdpa_dev) +{ + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + + return &adapter->vd; +} + +static u64 __maybe_unused crete_vdpa_get_log_base(struct crete_vdpa *vd) +{ + u64 log_base; + log_base = ((u64)vd->mig_log.log_base_h << 32) | vd->mig_log.log_base_l; + return log_base; +} + +static u64 __maybe_unused crete_vdpa_get_log_size(struct crete_vdpa *vd) +{ + u64 log_size; + log_size = ((u64)vd->mig_log.iova_size_h << 32) | vd->mig_log.iova_size_l; + return log_size; +} + + +static int __maybe_unused crete_vdpa_notify_handler(struct notifier_block *nb, + unsigned long ecode, void *data) +{ + struct crete_nb *cnb = container_of(nb, struct crete_nb, nb); + struct crete_vdpa *vd = container_of(cnb, struct crete_vdpa, cnb); + struct crete_adapter *adapter = vd_to_adapter(vd); + struct crete_core_dev *cdev = adapter->cdev; + struct crete_event_entry *cee = data; + uint8_t event_sub_type = cee->event_sub_type; + int ret; + struct device *dev = &cdev->pdev->dev; + + dev_dbg(dev, "%s: event code %lu\n sub_tupe %d\n", __func__, + ecode, event_sub_type); + if (ecode == CRETE_EVENT_PORT_LINK_CHANGE) { + switch (event_sub_type) { + case CRETE_EVENT_VNET_LINK_CHANGE: + case CRETE_EVENT_VNET_RESET: + if (vd->config_cb.callback) + vd->config_cb.callback(vd->config_cb.private); + ret = NOTIFY_OK; + break; + default: + return NOTIFY_DONE; + } + return ret; + } + return 0; +} + +static int crete_vdpa_register_event_handler(struct crete_vdpa *vd) +{ +#if 0 + struct crete_adapter *adapter = vd_to_adapter(vd); + struct crete_core_dev *cdev = adapter->cdev; + struct crete_nb *cnb = &vd->cnb; + struct notifier_block *nb = &cnb->nb; + int err; + struct device *dev = &cdev->pdev->dev; + + if (!nb->notifier_call) { + nb->notifier_call = crete_vdpa_notify_handler; + cnb->event_type = CRETE_EVENT_VNET_LINK_CHANGE; + err = crete_event_notifier_register(cdev, cnb); + if (err) { + nb->notifier_call = NULL; + dev_err(dev, + "failed to register pds event handler: %ps\n", + ERR_PTR(err)); + return -EINVAL; + } + dev_dbg(dev, "crete event handler registered\n"); + } +#endif + return 0; +} + +static void crete_vdpa_unregister_event_handler(struct crete_vdpa *vd) +{ +#if 0 + struct crete_adapter *adapter = vd_to_adapter(vd); + struct crete_core_dev *cdev = adapter->cdev; + struct crete_nb *cnb = &vd->cnb; + struct notifier_block *nb = &cnb->nb; + + if (nb->notifier_call) { + crete_event_notifier_unregister(cdev, cnb); + nb->notifier_call = NULL; + } +#endif +} + +int crete_vdpa_set_hwstatus(struct crete_core_dev *core_dev, u8 status, + struct device *dev) +{ + int ret; + u8 dev_status = 0; + + ret = crete_set_status(core_dev, CRETE_NET_DEV_STATUS, status); + if (ret) { + crete_err(dev, "crete cmd set status %u failed\n", status); + return ret; + } + + ret = crete_get_status(core_dev, CRETE_NET_DEV_STATUS, &dev_status); + if (ret) + crete_err(dev, "crete cmd get status failed\n"); + + return ret; +} + +static int __maybe_unused crete_vdpa_add_status(struct crete_vdpa *hw, u8 status) +{ + u8 hw_status; + int ret = 0; + struct crete_core_dev *cdev = vd_to_coredev(hw); + + if (status & VIRTIO_CONFIG_S_DRIVER_OK) { + hw_status = CRETE_NET_DEV_DEV_OK; + return crete_vdpa_set_hwstatus(cdev, hw_status, + &cdev->pdev->dev); + } + + return ret; +} + +void crete_reset_netdev(struct crete_vdpa *hw) +{ + struct crete_adapter *adp = vd_to_adapter(hw); + + hw->config_cb.callback = NULL; + hw->config_cb.private = NULL; + crete_reset_dev(adp->cdev, CRETE_RESET_NET_DEV); +} + +u64 crete_vdpa_get_features(struct crete_vdpa *hw) +{ + struct crete_vnet_hw_cap *hcap = hw->hcap; + + return hcap->hw_features; +} + +void crete_notify_queue(struct crete_vdpa *hw, u16 qid) +{ + iowrite16(qid, hw->vring[qid].notify_addr); +} + +static void crete_reset_vring(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + int i; + + crete_vdpa_driver_resetqueue(vdpa_dev, 0, vd->num_queues); + + for (i = 0; i < vd->num_queues; i++) { + vd->vring[i].ready = 0; + vd->vring[i].last_avail_idx = 0; + vd->vring[i].desc = 0; + vd->vring[i].avail = 0; + vd->vring[i].used = 0; + vd->vring[i].irq = VIRTIO_MSI_NO_VECTOR; + vd->vring[i].irqvec = 0xFFFF; + vd->vring[i].cb.callback = NULL; + vd->vring[i].cb.private = NULL; + } + +} + +static irqreturn_t crete_vdpa_intr_handler(int irq, void *arg) +{ + struct vring_info *vring = arg; + + if (vring->cb.callback) + return vring->cb.callback(vring->cb.private); + + return IRQ_HANDLED; +} + +static void crete_driver_freeirq_on(struct vdpa_device *vdpa_dev, int qid) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct vring_info *vfinfo = vd->vring; + struct crete_irq_info *irq_info; + + irq_info = &cdev->irq_info[vfinfo[qid].irqvec]; + if (vfinfo[qid].irq == VIRTIO_MSI_NO_VECTOR) + return; + + irq_info->requested = 0; + free_irq(vfinfo[qid].irq, &vfinfo[qid]); + crete_free_msixirq(cdev, vfinfo[qid].irqvec); + vfinfo[qid].irqvec = 0; + vfinfo[qid].irq = VIRTIO_MSI_NO_VECTOR; +} + +static void crete_driver_freeirq(struct vdpa_device *vdpa_dev, int queuenum) +{ + int i; + + for (i = 0; i < queuenum; i++) + crete_driver_freeirq_on(vdpa_dev, i); +} + +int crete_driver_initirq(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct vring_info *vfinfo = vd->vring; + struct device *dev = &cdev->pdev->dev; + int i, vectorno, ret = 0; + int queuenum = vd->qp_nums << 1; + struct pci_dev *pdev = cdev->pdev; + struct crete_irq_info *irq_info; + + /* ctrlq could't request the msix */ + for (i = 0; i < queuenum; i++) { + vectorno = crete_req_msixirq(cdev); + if (vectorno < 0) { + crete_err(dev, "request irq vector failed\n"); + ret = -ENXIO; + goto err1; + } + snprintf(vd->vring[i].msix_name, 256, "crete-vdpa[%s]-%d", + pci_name(pdev), i); + + irq_info = &cdev->irq_info[vectorno]; + snprintf(irq_info->name, 256, "crete-vdpa[%s]-%d", + pci_name(pdev), i); + ret = + request_irq(irq_info->vector, crete_vdpa_intr_handler, 0, + vd->vring[i].msix_name, &vfinfo[i]); + if (ret) { + crete_free_msixirq(cdev, vectorno); + crete_err(dev, "enable irq failed\n"); + goto err1; + + } + vfinfo[i].irqvec = vectorno; + vfinfo[i].irq = irq_info->vector; + irq_info->handler = crete_vdpa_intr_handler; + irq_info->requested = 1; + } + crete_info(dev, "crete vdpa init irq, queues %d\n", queuenum); +err1: + if (ret) { + /* irq request failed */ + crete_driver_freeirq(vdpa_dev, i); + } + return ret; +} + +int crete_driver_init_ctl_irq(struct vdpa_device *vdpa_dev, bool *ctrl_irq) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct vring_info *vfinfo = vd->vring; + struct device *dev = &cdev->pdev->dev; + int i, irqvec, irq, ret = 0; + int queuenum = vd->num_queues; + int io_vector = 0; + struct crete_vdpa_mgmtdev *vdpa_mgmt_dev; + struct crete_vnet_hw_cap *hcap; + + if (!adapter->priv) { + *ctrl_irq = false; + crete_info(dev, "crete is not vdpa device\n"); + return 0; + } + vdpa_mgmt_dev = adapter->priv; + hcap = &vdpa_mgmt_dev->hcap; + if (!hcap->have_ctl) { + *ctrl_irq = false; + crete_info(dev, "crete is not have ctl\n"); + return 0; + } + for (i = 0; i < vd->num_queues; ++i) { + if (vd->vring[i].cb.callback) + ++io_vector; + } + if (io_vector == queuenum) { + *ctrl_irq = false; + crete_info(dev, "crete is not have ctl irq\n"); + return 0; + } else if (io_vector != queuenum + 1) { + *ctrl_irq = false; + crete_err(dev, "crete is not support current vdpa devie\n"); + return -EINVAL; + } + + *ctrl_irq = true; + irqvec = crete_req_msixirq(cdev); + if (irqvec < 0) { + crete_err(dev, "request irq vector failed\n"); + ret = -ENXIO; + return ret; + } + i = queuenum; + snprintf(vd->vring[i].msix_name, 256, "crete-ctrl[%s]-%d\n", + pci_name(cdev->pdev), i); + + /* init vringinfo irq num */ + irq = cdev->irq_info[irqvec].vector; + ret = devm_request_irq(dev, irq, + crete_vdpa_intr_handler, + 0, vd->vring[i].msix_name, &vfinfo[i]); + if (ret) { + crete_free_msixirq(cdev, irqvec); + crete_err(dev, "enable irq failed\n"); + goto err1; + } + /* vring info irq vector */ + vfinfo[i].irqvec = irqvec; + /* vring info irq num */ + vfinfo[i].irq = irq; + return 0; +err1: + return ret; +} + +static int crete_driver_creteqp(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct vring_info *vfinfo = vd->vring; + int queuenum = vd->qp_nums << 1; + struct crete_queue_context qc; + int i, ret = 0; + + for (i = 0; i < queuenum; i++) { + /* if vring not ready just failed \n */ + if (!vfinfo[i].ready) { + crete_info(&cdev->pdev->dev, "qpid %d is no ready\n", i); + //break; + } + qc.qid = i; + qc.queue_size = vd->queue_size; + qc.cq_size = vd->queue_size; + qc.queue_vec = vfinfo[i].irqvec; + if (vd->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { + qc.queue_desc_base = vfinfo[i].desc; + qc.queue_used_base = vfinfo[i].desc; + } else { + qc.queue_desc_base = vfinfo[i].desc; + qc.queue_used_base = vfinfo[i].used; + } + ret = crete_cmd_create_signal_queue(cdev, &qc); + if (ret < 0) { + crete_err(cdev->device, "crete create queue failed ret:%d\n", ret); + ret = -EINVAL; + goto err; + } + } +err: + return ret; +} + +static int crete_driver_crete_ctrlq(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct vring_info *vfinfo = vd->vring; + struct device *dev = &cdev->pdev->dev; + int queuenum = vd->qp_nums << 1; + struct crete_vdpa_mgmtdev *vdpa_mgmt_dev; + struct crete_vnet_hw_cap *hcap; + struct crete_queue_context qc; + int ret = 0; + + if (!adapter->priv) { + crete_info(dev, "crete is not vdpa device\n"); + return 0; + } + vdpa_mgmt_dev = adapter->priv; + hcap = &vdpa_mgmt_dev->hcap; + if (!hcap->have_ctl) { + crete_info(dev, "crete is not have ctl\n"); + return 0; + } + + qc.qid = queuenum; + qc.queue_size = vfinfo[queuenum].size; + qc.queue_vec = 0xffff; + qc.cq_size = vfinfo[queuenum].size; + if (vd->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { + qc.queue_desc_base = vfinfo[queuenum].desc; + qc.queue_used_base = vfinfo[queuenum].desc; + } else { + qc.queue_desc_base = vfinfo[queuenum].desc; + qc.queue_used_base = vfinfo[queuenum].used; + } + + ret = crete_cmd_create_signal_queue(cdev, &qc); + if (ret < 0) { + crete_err(dev, "crete create queue failed ret: %d\n", ret); + return ret; + } + return ret; +} + +static int crete_set_vq_state(struct crete_vdpa *hw, u16 qid, u16 last_used) +{ + struct crete_core_dev *cdev = vd_to_coredev(hw); + struct device *dev = &cdev->pdev->dev; + int ret; + ret = crete_set_vq_mig_state(cdev, CRETE_MIG_DEV_VIRTIO, qid, last_used); + if (ret < 0) { + crete_err(dev, "set mig vq state error. qid %d last used %d err %d\n", + qid, last_used, ret); + /* FIXME: what value should be returned */ + return ret; + } + return 0; +} + +static int crete_driver_startqueue(struct vdpa_device *vdpa_dev, + int startqueue, int endqueue) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct device *dev = &cdev->pdev->dev; + struct vring_info *vfinfo = vd->vring; + int i, ret = 0; + + for (i = startqueue; i < endqueue; i++) { + if (!vfinfo[i].ready) + crete_err(dev, " start queue %d no ready\n", i); + + /* set the last avail index */ + if (vd->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) + crete_set_vq_state(vd, i, vd->vring_lm_cfg[i].last_avail_idx); + else + if (vd->vring_lm_cfg[i].last_avail_idx > 0) + crete_set_vq_state(vd, i, vd->vring_lm_cfg[i].last_avail_idx); + + /* enable queue. don't enable queue until set vq state */ + ret = crete_start_singlequeue(cdev, i); + if (ret) { + crete_err(dev, "crete start queue id:%d failed\n", i); + ret = -EINVAL; + break; + } + } + + return ret; +} + +int crete_vdpa_driver_resetqueue(struct vdpa_device *vdpa_dev, + int startqueue, int endqueue) +{ + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct device *dev = &cdev->pdev->dev; + int i, ret = 0; + + for (i = startqueue; i < endqueue; i++) { + ret = crete_reset_singlequeue(cdev, i); + if (ret) { + crete_err(dev, "crete reset queue id:%d failed\n", i); + ret = -EINVAL; + break; + } + } + + return ret; +} + +static void crete_driver_reset_ctrlq(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + int startqueue = vd->qp_nums << 1; + + crete_vdpa_driver_resetqueue(vdpa_dev, startqueue, vd->num_queues); +} + +static void crete_driver_reset_ioqp(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + int endqueue = vd->qp_nums << 1; + + crete_vdpa_driver_resetqueue(vdpa_dev, 0, endqueue); +} + +static void crete_vdap_unmask_irq(struct vdpa_device *vdpa_dev) +{ + int i; + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + int qnum = vd->qp_nums << 1; + for (i = 0; i < qnum; i++) { + vd->vring[i].irq = VIRTIO_MSI_NO_VECTOR; + vd->vring[i].irqvec = 0xFFFF; + } +} + +int crete_driver_setup(struct vdpa_device *vdpa_dev) +{ + + int ret = 0; + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct device *dev = &cdev->pdev->dev; + bool ctrl_have_irq; + int queuenum = vd->qp_nums << 1; + + ctrl_have_irq = false; + + if (vd->host_polling) { + /* disable interupt */ + crete_event_exit(&cdev->hw); + crete_exit_irq(cdev); + /* reset irq value on the vring */ + crete_vdap_unmask_irq(vdpa_dev); + crete_info(dev, "crete vdpa unmask the irq\n"); + } else { + /* step 1: request vring irq resource */ + ret = crete_driver_initirq(vdpa_dev); + if (ret) { + crete_err(dev, "crete driver init irq failed\n"); + goto err; + } + } + + /* step 2: create qp failed */ + ret = crete_driver_creteqp(vdpa_dev); + if (ret) { + crete_err(dev, "crete driver create qp failed\n"); + goto err_ctrl_irq; + } + ret = crete_driver_crete_ctrlq(vdpa_dev); + if (ret) { + crete_err(dev, "crete driver create ctrl queue failed\n"); + goto err_creteqp; + } + /* step 3: */ + ret = crete_driver_startqueue(vdpa_dev, 0, vd->num_queues); + if (ret) { + crete_err(dev, "crete start queue failed\n"); + goto err_crete_ctrlq; + } + crete_info(dev, "crete vdpa driver setup\n"); + return 0; + +err_crete_ctrlq: + crete_driver_reset_ctrlq(vdpa_dev); +err_creteqp: + crete_driver_reset_ioqp(vdpa_dev); +err_ctrl_irq: + if (ctrl_have_irq) + crete_driver_freeirq_on(vdpa_dev, queuenum); + + crete_driver_freeirq(vdpa_dev, queuenum); +#ifndef JMND_DISABLE_MSIX +err: +#endif + return ret; +} + +int crete_driver_down(struct vdpa_device *vdpa_dev) +{ + int ret = 0; + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + /* TODO: free the irq, except ctrlq */ + crete_driver_freeirq(vdpa_dev, vd->num_queues); + + return ret; +} + +static int __maybe_unused crete_driver_postinit(struct vdpa_device *vdpa_dev) +{ + int ret = 0; + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct device *dev = &cdev->pdev->dev; + + /* set features */ + ret = + crete_cmd_set_features(cdev, CRETE_VIRTIO_NET_DEV_FEAT, + vd->driver_features); + if (ret) { + crete_err(dev, "crete set features 0x%llx failed\n", + vd->driver_features); + goto out; + } + + /* set feature ok status */ + ret = crete_vdpa_set_hwstatus(cdev, CRETE_NET_DEV_FEATURE_OK, dev); + if (ret) + crete_err(dev, "crete set status feature ok failed\n"); + +out: + return ret; +} + +static u64 crete_vdpa_get_device_features(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_vnet_hw_cap *hcap = vd->hcap; + + return hcap->hw_features; +} + +static int crete_vdpa_set_log_state(struct crete_vdpa *vd, u8 state) +{ + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dev = &cdev->pdev->dev; + int ret; + ret = crete_set_mig_log_state(cdev, CRETE_MIG_DEV_VIRTIO, state); + if (ret < 0) { + crete_err(dev, "set mig log state error. state %d err %d\n", state, ret); + /* FIXME: what value should be returned */ + return ret; + } + + return 0; +} + +static void crete_vdpa_disable_logging(struct crete_vdpa *vd) +{ + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dev = &cdev->pdev->dev; + + vd->lm_ctrl = CORSICA_LM_DISABLE; + crete_vdpa_set_log_state(vd, CORSICA_LM_DISABLE); + crete_info(dev, "crete vdpa disable dirty logging\n"); +} + +static void crete_vdpa_enable_logging(struct crete_vdpa *vd) +{ + crete_vdpa_set_log_state(vd, CORSICA_LM_ENABLE); +} + +static int crete_vdpa_stop_mig(struct crete_vdpa *vd) +{ + return crete_vdpa_set_log_state(vd, CORSICA_LM_STOP_DEV); +} + +static int crete_vdpa_set_driver_features(struct vdpa_device *vdpa_dev, + u64 features) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *core_dev = adapter->cdev; + struct device *dev = &core_dev->pdev->dev; + int ret; + + if (!(features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)) && features) { + crete_err(dev, "VIRTIO_F_ACCESS_PLATFORM is not negotiated\n"); + return -EINVAL; + } + + ret = + crete_cmd_set_features(core_dev, CRETE_VIRTIO_NET_DEV_FEAT, features); + if (ret) { + crete_err(dev, "crete set features 0x%llx failed ret %d\n", features, ret); + return ret; + } + + if (features & (1 << VHOST_F_LOG_ALL) + && (vd->lm_ctrl == CORSICA_LM_ENABLE)) { + crete_info(dev, "enable log log_base= 0x%x%08x,log_size=0x%x%08x\n", + vd->mig_log.log_base_h, vd->mig_log.log_base_l, vd->mig_log.iova_size_h, vd->mig_log.iova_size_l); + crete_vdpa_enable_logging(vd); + } else if (!(features & (1 << VHOST_F_LOG_ALL)) && + (vd->lm_ctrl == CORSICA_LM_STOP_DEV)) { + crete_info(dev, "disable log now lm ctrl= %d\n", vd->lm_ctrl); + crete_vdpa_disable_logging(vd); + } + vd->driver_features = features; + crete_info(dev, "vdpa set features 0x%llx\n", features); + return 0; +} + +#ifdef HAVE_VDPA_OPS_DEVICE_FEAT +static u64 crete_vdpa_get_driver_features(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + return vd->driver_features; +} +#endif + + +static u8 crete_vdpa_get_status(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd; + struct crete_core_dev *cdev; + + vd = vdpa_to_vd(vdpa_dev); + cdev = vd_to_coredev(vd); + + dev_info(&cdev->pdev->dev, "vdpa get dev status: %d\n", vd->status); + return vd->status; +} + +static int crete_vdpa_reset(struct vdpa_device *vdpa_dev, int state) +{ + struct crete_adapter *adapter; + struct crete_vdpa *vd; + u8 status_old; + struct crete_core_dev *cdev; + int ret; + + vd = vdpa_to_vd(vdpa_dev); + adapter = vdpa_to_adapter(vdpa_dev); + status_old = vd->status; + cdev = adapter->cdev; + + /* if within the non initial status */ + if (status_old == 0) + return 0; + + if (status_old & VIRTIO_CONFIG_S_DRIVER_OK) { + crete_driver_down(vdpa_dev); + crete_exit_irq(cdev); + crete_reset_vring(vdpa_dev); + crete_reset_netdev(vd); + ret = crete_vdpa_set_hwstatus(adapter->cdev, + CRETE_NET_DEV_STARTUP, cdev->device); + if (ret) { + dev_err(cdev->device, + "%s set CRETE_NET_DEV_STARTUP failed\n", __func__); + return -EINVAL; + } + } + vd->announce_count = 0; + vd->status = state; + /* reset net device status as LINKUP */ + adapter->config.status = VIRTIO_NET_S_LINK_UP; + dev_info(cdev->device, "vdap reset stauts %d old %d\n", state, status_old); + return 0; +} + +static void crete_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status) +{ + struct crete_adapter *adapter; + struct crete_core_dev *cdev; + struct crete_vdpa *vd; + struct virtio_net_config *config; + u8 status_old, jnet_st; + int ret = 0; + bool need = false; + vd = vdpa_to_vd(vdpa_dev); + adapter = vdpa_to_adapter(vdpa_dev); + cdev = adapter->cdev; + status_old = vd->status; + config = &adapter->config; + + if (status_old == status) + return; + + if (status == 0 || ((status_old & VIRTIO_CONFIG_S_DRIVER_OK) && + !(status & VIRTIO_CONFIG_S_DRIVER_OK))) { + crete_vdpa_reset(vdpa_dev, 0); + vd->status = status; + return; + } + + if ((status & VIRTIO_CONFIG_S_ACKNOWLEDGE) && + !(status_old & VIRTIO_CONFIG_S_ACKNOWLEDGE)) { + jnet_st = CRETE_NET_DEV_STARTUP; + need = true; + } + + if ((status & VIRTIO_CONFIG_S_FEATURES_OK) && + !(status_old & VIRTIO_CONFIG_S_FEATURES_OK)) { + jnet_st = CRETE_NET_DEV_FEATURE_OK; + crete_init_msix(cdev); + need = true; + } + + if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && + !(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) { + ret = crete_driver_setup(vdpa_dev); + if (ret) { + dev_err(cdev->device, "driver setup error\n"); + goto fw_reset; + } + jnet_st = CRETE_NET_DEV_DEV_OK; + need = true; + if ( (vd->driver_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) && + ((config->status & VIRTIO_NET_S_ANNOUNCE) != VIRTIO_NET_S_ANNOUNCE)) { + config->status |= VIRTIO_NET_S_ANNOUNCE; + dev_info(cdev->device, "crete vdpa set config status has VIRTIO_NET_S_ANNOUNCE\n"); + } + } + + if (need) { + ret = crete_set_status(cdev, CRETE_NET_DEV_STATUS, jnet_st); + if (ret) { + crete_err(cdev->device, "crete cmd set status %u failed\n", status); + goto fw_reset; + } + } + + vd->status = status; + if (jnet_st == CRETE_NET_DEV_DEV_OK) { + /* The config_cb.call can't be setted until SET DRIVER_OK be returned */ + vd->announce_count = 5; + dev_info(cdev->device, "set config announce status %d\n", config->status); + } + dev_info(cdev->device, "vdpa set status: %d jnet %d need %d\n", status, jnet_st, need); + return; +fw_reset: + vd->status = status_old | VIRTIO_CONFIG_S_FAILED; + /* todo nodify fw send reset evnet to virtio*/ +} + +static u16 crete_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + return vd->queue_size; +} + +#ifdef HAVE_VDPA_OPS_NUM_MIN +static u16 crete_vdpa_get_vq_num_min(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + return vd->queue_size; +} +#endif + +static int crete_vdpa_iotlb_invalidate(struct vdpa_device *vdpa) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_iotlb_map *iter, *_iter; + struct page *page; + unsigned long pfn, pinned; + + if(!vd->domain) { + return -1; + } + spin_lock(&vd->iommu_lock); + list_for_each_entry_safe(iter, _iter, &vd->mig_log.list,link) { + if(vd->mig_log.nmaps == 0 || iter->size == 0) + break; + pinned = PFN_DOWN(iter->size); + for (pfn = PFN_DOWN(iter->addr); + pinned > 0; pfn++, pinned--) { + page = pfn_to_page(pfn); + if (iter->perm & VHOST_ACCESS_WO) + set_page_dirty_lock(page); + unpin_user_page(page); + } + atomic64_sub(PFN_DOWN(iter->size), &vd->mm->pinned_vm); + iommu_unmap(vd->domain,iter->start,iter->size); + list_del(&iter->link); + kfree(iter); + vd->mig_log.nmaps--; + } + spin_unlock(&vd->iommu_lock); + return 0; +} + +static void crete_vdpa_unbind_mm(struct vdpa_device *vdpa) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_core_dev *cdev = vd_to_coredev(vd); + + if (!vd->mm) { + crete_info(&cdev->pdev->dev, "crete vdpa mm alread be unbind\n"); + return; + } + crete_vdpa_iotlb_invalidate(vdpa); + mmdrop(vd->mm); + vd->mm = NULL; + + crete_info(&cdev->pdev->dev, "crete vdpa mm be unbind n"); + return ; +} + +static void crete_avail_idx_to_vq_state(struct crete_vdpa *vd, u16 avail_index, struct vdpa_vq_state *state) +{ + if (vd->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { + state->packed.last_avail_idx = avail_index & 0x7fff; + state->packed.last_avail_counter = !!!(avail_index & 0x8000); + state->packed.last_used_counter = state->packed.last_avail_counter; + state->packed.last_used_idx = state->packed.last_avail_idx; + } else { + state->split.avail_index = avail_index; + } +} + +static u16 crete_vq_state_to_avail_idx(struct crete_vdpa *vd, const struct vdpa_vq_state *state) +{ + u16 avail_index; + if (vd->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { + avail_index = state->packed.last_avail_idx; + avail_index |= (!((uint16_t)state->packed.last_avail_counter)) << 15; + } else + avail_index = state->split.avail_index; + + return avail_index; +} + +static u16 crete_get_vq_state(struct crete_vdpa *vd, u16 qid) +{ + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dev = &cdev->pdev->dev; + u16 last_used; + int ret; + + ret = crete_get_vq_mig_state(cdev, CRETE_MIG_DEV_VIRTIO, qid, &last_used); + if (ret < 0) { + crete_err(dev, "get mig vq state error. qid %d err %d\n", qid, ret); + /* FIXME: what value should be returned */ + return 0; + } + return last_used; +} + +static int crete_get_vq_state_batch(struct crete_vdpa *vd, u16 start_qid, u16 qnum) +{ + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dev = &cdev->pdev->dev; + u16 last_used_set[16], qid; + int ret, i; + + ret = crete_get_vq_mig_state_batch(cdev, CRETE_MIG_DEV_VIRTIO, start_qid, qnum, last_used_set); + if (ret < 0) { + crete_err(dev, "get mig vq state batch error. start qid %d qnum %d err %d\n", + start_qid, qnum, ret); + /* FIXME: what value should be returned */ + return ret; + } + + /* save the last avail index */ + for (i = 0, qid = start_qid; i < qnum; i++, qid++) { + vd->vring_lm_cfg[qid].last_avail_idx = last_used_set[i]; + vd->vring_lm_cfg[qid].can_used = 1; + crete_info(dev, "crete vdpa save batch the last avail index qid %d value 0x%x", + qid, last_used_set[i]); + } + + return 0; +} + +static int crete_vdpa_get_vq_state_single(struct vdpa_device *vdpa_dev, u16 qid, + struct vdpa_vq_state *state) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct device *dev = &cdev->pdev->dev; + u16 avail_index; + + avail_index = crete_get_vq_state(vd, qid); + crete_avail_idx_to_vq_state(vd, avail_index, state); + /* save the avail index and set `can_used` */ + vd->vring_lm_cfg[qid].last_avail_idx = avail_index; + vd->vring_lm_cfg[qid].can_used = 0; + + if (vd->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) + crete_info(dev, + "get vq state packed qid = %u, last avail idx=%u counter %d " + "last used idx %d counter %d " + "ctrl %d avail index %u\n", + qid, state->packed.last_avail_idx, + state->packed.last_avail_counter, + state->packed.last_used_idx, state->packed.last_used_counter, + vd->lm_ctrl, avail_index); + else + crete_info(dev, + "get vq state split qid = %u, last_avail_idx=%u " + "ctrl %d avail index %d\n", + qid, state->split.avail_index, vd->lm_ctrl, avail_index); + return 0; +} + +static int crete_vdpa_get_vq_state_batch(struct vdpa_device *vdpa_dev, u16 start_qid, + u16 qnum, struct vdpa_vq_state *state) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + int ret; + ret = crete_get_vq_state_batch(vd, start_qid, qnum); + if (ret == 0) { + /* TODO: first check the flag `can_used` */ + crete_avail_idx_to_vq_state(vd, vd->vring_lm_cfg[start_qid].last_avail_idx, state); + vd->vring_lm_cfg[start_qid].can_used = 0; + } + + return ret; +} + +static int crete_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid, + struct vdpa_vq_state *state) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + struct device *dev = &cdev->pdev->dev; + int ret; + /* gabage,qemu use this to stop the device */ + if (qid == 0 && (vd->lm_ctrl & CORSICA_LM_ENABLE)) { + vd->lm_ctrl = CORSICA_LM_STOP_DEV; + + /* STOP Migration Device */ + ret = crete_vdpa_stop_mig(vd); + if (ret != 0) { + /* TODO: can't stop device. need stop migration */ + crete_err(dev, "crete vdpa migration stop failed. ret %d\n", ret); + } else + crete_info(dev, "crete vdpa migration stop\n"); + } + + if ((qid == vd->num_queues - 1) && + (vd->lm_ctrl & CORSICA_LM_STOP_DEV)) { + /** disable the log dirty tracking **/ + crete_vdpa_disable_logging(vd); + crete_vdpa_unbind_mm(vdpa_dev); + vd->mig_log.log_base_h = 0; + vd->mig_log.log_base_l = 0; + vd->mig_log.iova_size_h = 0; + vd->mig_log.iova_size_l = 0; + vd->mig_log.nmaps = 0; + crete_info(dev, "crete vdpa dirty log diable\n"); + } + + if (vd->vring_lm_cfg[qid].can_used) { + crete_avail_idx_to_vq_state(vd, vd->vring_lm_cfg[qid].last_avail_idx, state); + /* unset the flag `can_used` */ + vd->vring_lm_cfg[qid].can_used = 0; + return 0; + } + + if ((qid == vd->num_queues - 1) || (batch_vq_state == 0)) { + /* get the vq state single */ + return crete_vdpa_get_vq_state_single(vdpa_dev, qid, state); + } else { + /* get the vq state batch */ + return crete_vdpa_get_vq_state_batch(vdpa_dev, qid, + min(vd->num_queues - qid, 16), state); + } +} + +static int crete_vdpa_set_vq_state(struct vdpa_device *vdpa_dev, u16 qid, + const struct vdpa_vq_state *state) +{ + u16 avail_index; + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dev = &cdev->pdev->dev; + + avail_index = crete_vq_state_to_avail_idx(vd, state); + + vd->vring_lm_cfg[qid].last_avail_idx = avail_index; + if (vd->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { + crete_info(dev, + "set vq state packed qid = %u, last avail idx %u counter %d " + "last used idx %d counter %d " + "ctrl %d avail index %u\n", + qid, state->packed.last_avail_idx, + state->packed.last_avail_counter, + state->packed.last_used_idx, state->packed.last_used_counter, + vd->lm_ctrl, avail_index); + } else { + if (avail_index == 0) + goto ret; + + crete_info(dev, + "set vq state split qid = %u, last_avail_idx=%u " + "ctrl %d avail index %d\n", + qid, state->split.avail_index, vd->lm_ctrl, avail_index); + } +ret: + return 0; +} + +static void crete_vdpa_set_vq_cb(struct vdpa_device *vdpa_dev, u16 qid, + struct vdpa_callback *cb) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + + vd->vring[qid].cb = *cb; + if (qid == 0) { + if ((cb->callback == NULL) || (vf_irq == 0)) { + vd->host_polling = true; + crete_info(&cdev->pdev->dev, "crete vdpa disable irq\n"); + } else { + vd->host_polling = false; + crete_info(&cdev->pdev->dev, "crete vdpa enable irq\n"); + } + } +} + +static void crete_vdpa_set_vq_ready(struct vdpa_device *vdpa_dev, + u16 qid, bool ready) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + vd->vring[qid].ready = ready; +} + +static bool crete_vdpa_get_vq_ready(struct vdpa_device *vdpa_dev, u16 qid) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + return vd->vring[qid].ready; +} + +static void crete_vdpa_set_vq_num(struct vdpa_device *vdpa_dev, u16 qid, + u32 num) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + //struct crete_core_dev *cdev = vd_to_coredev(vd); + + vd->vring[qid].size = num; + //crete_info(&cdev->pdev->dev, "crete vdpa set vq num qid %d num %d\n", qid, num); +} + +static int crete_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid, + u64 desc_area, u64 driver_area, + u64 device_area) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + + vd->vring[qid].desc = desc_area; + vd->vring[qid].avail = driver_area; + vd->vring[qid].used = device_area; + + dev_info(&cdev->pdev->dev, "vdpa set vq address qid: %d desc: 0x%llx avail: 0x%llx used: 0x%llx\n", + qid, desc_area, driver_area, device_area); + return 0; +} + +static void crete_vdpa_kick_vq(struct vdpa_device *vdpa_dev, u16 qid) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + + crete_notify_queue(vd, qid); + + dev_info(&cdev->pdev->dev, "vdpa kick vq: %d\n", qid); +} + +static u32 crete_vdpa_get_generation(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + return vd->generation; +} + +static u32 crete_vdpa_get_device_id(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + return vd->dev_type; +} + +static u32 crete_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev) +{ + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct pci_dev *pdev = adapter->cdev->pdev; + + return pdev->subsystem_vendor; +} + +static u32 crete_vdpa_get_vq_align(struct vdpa_device *vdpa_dev) +{ + return CORSICA_QUEUE_ALIGNMENT; +} + +#ifdef HAVE_VDPA_OPS_GET_CONFIG_SIZE +static size_t crete_vdpa_get_config_size(struct vdpa_device *vdpa_dev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + return vd->config_size; +} +#endif + +static void crete_vdpa_announce(struct vdpa_device *vdpa_dev, struct virtio_net_config *config) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + + if (config->status & VIRTIO_NET_S_ANNOUNCE) { + if (vd->announce_count > 0) { + vd->announce_count--; + if (vd->announce_count == 0) { + config->status &= ~VIRTIO_NET_S_ANNOUNCE; + crete_info(cdev->device, "crete vdpa unmask announce status %d\n", + config->status); + } + /* set the bit of ANNOUNCE */ + if ((vd->config_cb.callback) && + (vd->driver_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))) { + vd->config_cb.callback(vd->config_cb.private); + crete_info(cdev->device, "send config callback status %d\n", + config->status); + } + } + } +} + +static void crete_vdpa_get_config(struct vdpa_device *vdpa_dev, + unsigned int offset, + void *buf, unsigned int len) +{ + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct virtio_net_config *config = &adapter->config; + struct crete_core_dev *cdev = adapter->cdev; + + if (offset + len <= sizeof(struct virtio_net_config)) { + memcpy(buf, (u8 *)&adapter->config + offset, len); + crete_info(&cdev->pdev->dev, "crete vdpa get config mtu %d " + "status %d speed %d queue pairs %d\n", + config->mtu, config->status, config->speed, + config->max_virtqueue_pairs); + } + + switch (offset) + { + case VIRTIO_NET_CONFIG_OFFSET_MAC: + crete_info(&cdev->pdev->dev, "get config mac %pM len %d\n", config->mac, len); + break; + case VIRTIO_NET_CONFIG_OFFSET_MTU: + crete_info(&cdev->pdev->dev, "get config mtu %d len %d\n", config->mtu, len); + break; + case VIRTIO_NET_CONFIG_OFFSET_STATUS: + crete_info(&cdev->pdev->dev, "get config status %d len %d\n", config->status, len); + crete_vdpa_announce(vdpa_dev, config); + break; + default: + crete_info(&cdev->pdev->dev, "get config unknown offset %u len %d\n", offset, len); + break; + } +} + +static void crete_vdpa_set_config(struct vdpa_device *vdpa_dev, + unsigned int offset, const void *buf, + unsigned int len) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct virtio_net_config *config = &adapter->config; + struct crete_core_dev *cdev = adapter->cdev; + const u8 *p; + + p = buf; + WARN_ON(offset + len > vd->config_size); + crete_info(&cdev->pdev->dev, + "set config old mac=%pM mtu=%d offset %d len %d\n", + config->mac, config->mtu, offset, len); + + memcpy((u8 *)config + offset, buf, len); + switch (offset) { + case VIRTIO_NET_CONFIG_OFFSET_MAC: + pr_info("send cmd mac addr update %02x:%02x:%02x:%02x:%02x:%02x\n", + p[0], p[1], p[2], p[3], p[4], p[5]); + break; + case VIRTIO_NET_CONFIG_OFFSET_MTU: + pr_info("send cmd mtu addr update mut %d\n", config->mtu); + break; + default: + crete_info(&cdev->pdev->dev, "set confg unknown offset %d len %d\n", offset, len); + break; + } + crete_info(&cdev->pdev->dev, "crete vdpa set_config mtu %d " + "status %d speed %d queue pairs %d\n", + config->mtu, config->status, config->speed, + config->max_virtqueue_pairs); + +} + +static void crete_vdpa_set_config_cb(struct vdpa_device *vdpa_dev, + struct vdpa_callback *cb) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + //struct virtio_net_config *config = &adapter->config; + struct crete_core_dev *cdev = adapter->cdev; + + vd->config_cb.callback = cb->callback; + vd->config_cb.private = cb->private; + + crete_info(&cdev->pdev->dev, "set config callback\n"); + + /* + * In the qemu, can't update the DRIVER_OK to dev->status + * until this function returned. + * So, we need start a timer worker to send callback. + */ + if (vd->announce_count > 0) { + vd->announce_count--; + /* TODO: start a timer worker */ + if ((vd->config_cb.callback) && + (vd->driver_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))) { + vd->config_cb.callback(vd->config_cb.private); + crete_info(&cdev->pdev->dev, "send config callback\n"); + } + } +} + +static int crete_vdpa_get_vq_irq(struct vdpa_device *vdpa_dev, u16 qid) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct crete_core_dev *cdev = adapter->cdev; + int irq = vd->vring[qid].irq; + if (irq == VIRTIO_MSI_NO_VECTOR) { + crete_err(&cdev->pdev->dev, "get vq irq. qid %d error NO_VECTOR\n", qid); + return -EINVAL; + } + + crete_info(&cdev->pdev->dev, "get vq irq. qid %d irq %u", qid, irq); + return irq; +} + +bool is_ctrl_vq_idx(struct vdpa_device *vdpa_dev, u16 idx) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + + if (vd->num_queues == idx) + return true; + return false; + +} + +static struct vdpa_notification_area crete_get_vq_notification( + struct vdpa_device *vdpa_dev, u16 idx) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa_dev); + struct vdpa_notification_area area; + + area.addr = vd->vring[idx].notify_pa; + area.size = PAGE_SIZE; + return area; +} + +#ifdef HAVE_VDPA_EULER_OPS +static int perm_to_iommu_flags(u32 perm) +{ + int flags = 0; + + switch (perm) { + case VHOST_ACCESS_WO: + flags |= IOMMU_WRITE; + break; + case VHOST_ACCESS_RO: + flags |= IOMMU_READ; + break; + case VHOST_ACCESS_RW: + flags |= (IOMMU_WRITE | IOMMU_READ); + break; + default: + WARN(1, "invalidate vhost IOTLB permission\n"); + break; + } + + return flags | IOMMU_CACHE; +} + +static int crete_vdpa_iotlb_update(struct vdpa_device *vdpa, unsigned int asid, + u64 iova, u64 size, + u64 pa, u32 perm, void *opaque) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa); + struct crete_core_dev *cdev = adapter->cdev; + + int ret = 0; + int flags = perm_to_iommu_flags(perm); + struct crete_iotlb_map *map; + + if(!vd->domain){ + dev_err(&cdev->pdev->dev,"crete vdpa domain is null\n"); + return -EIO; + } + if (size <= 0) + return -EFAULT; + map = kmalloc(sizeof(*map), GFP_ATOMIC); + if (!map) + return -ENOMEM; + + map->start = iova; + map->size = size; + map->last = iova + size - 1; + map->addr = pa; + map->perm = perm; + map->opaque = opaque; + + INIT_LIST_HEAD(&map->link); + spin_lock(&vd->iommu_lock); + vd->mig_log.nmaps++; + list_add_tail(&map->link, &vd->mig_log.list); + ret = iommu_map(vd->domain, iova, pa, size, flags); + spin_unlock(&vd->iommu_lock); + return ret; +} + +static int crete_vdpa_dma_unmap(struct vdpa_device *vdev, unsigned int asid, + u64 iova, u64 size) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + + if(!vd->domain){ + dev_err(&cdev->pdev->dev,"crete vdpa domain is null\n"); + return -EIO; + } + + spin_lock(&vd->iommu_lock); + iommu_unmap(vd->domain, iova, size); + spin_unlock(&vd->iommu_lock); + return 0; +} + +static int crete_vdpa_dma_map_log_base(struct vdpa_device *vdpa, u64 log_size, u64 iova) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa); + struct crete_core_dev *cdev = adapter->cdev; + + struct page **page_list; + unsigned long list_size = PAGE_SIZE / sizeof(struct page *); + unsigned int gup_flags = FOLL_LONGTERM; + unsigned long npages, cur_base, map_pfn, last_pfn = 0; + unsigned long lock_limit, sz2pin, nchunks, i; + u64 start, log_base; + long pinned; + int ret = 0; + u32 perm; + + start = iova; + perm = VHOST_ACCESS_RW; + /* Limit the use of memory for bookkeeping */ + page_list = (struct page **) __get_free_page(GFP_KERNEL); + if (!page_list) + return -ENOMEM; + + if (perm & VHOST_ACCESS_WO) + gup_flags |= FOLL_WRITE; + + npages = PFN_UP(log_size + (iova & ~PAGE_MASK)); + if (!npages) { + ret = -EINVAL; + goto free; + } + if(!vd->mm){ + ret = -EIO; + goto free; + } + mmap_read_lock(vd->mm); + + lock_limit = PFN_DOWN(rlimit(RLIMIT_MEMLOCK)); + if (npages + atomic64_read(&vd->mm->pinned_vm) > lock_limit) { + ret = -ENOMEM; + goto unlock; + } + + log_base = crete_vdpa_get_log_base(vd); + log_base &= PAGE_MASK; + iova &= PAGE_MASK; + nchunks = 0; + + crete_info(&cdev->pdev->dev, "crete vdpa dma map pages %ld log base 0x%llx size 0x%llx iova 0x%llx\n", + npages, log_base, log_size, iova); + while (npages) { + sz2pin = min_t(unsigned long, npages, list_size); + pinned = pin_user_pages(log_base, sz2pin, + gup_flags, page_list, NULL); + if (sz2pin != pinned) { + if (pinned < 0) { + ret = pinned; + } else { + unpin_user_pages(page_list, pinned); + ret = -ENOMEM; + } + goto out; + } + nchunks++; + + if (!last_pfn) + map_pfn = page_to_pfn(page_list[0]); + + for (i = 0; i < pinned; i++) { + unsigned long this_pfn = page_to_pfn(page_list[i]); + u64 csize; + if (last_pfn && (this_pfn != last_pfn + 1)) { + /* Pin a contiguous chunk of memory */ + csize = PFN_PHYS(last_pfn - map_pfn + 1); + ret = crete_vdpa_iotlb_update(vdpa, 0, iova, csize, + PFN_PHYS(map_pfn), + perm, NULL); + if (ret) { + /* + * Unpin the pages that are left unmapped + * from this point on in the current + * page_list. The remaining outstanding + * ones which may stride across several + * chunks will be covered in the common + * error path subsequently. + */ + unpin_user_pages(&page_list[i], + pinned - i); + crete_err(&cdev->pdev->dev, "crete vpa update iotlb error. " + "iova 0x%llx csize 0x%llx npages %ld\n", + iova, csize, npages); + goto out; + } + + map_pfn = this_pfn; + iova += csize; + nchunks = 0; + } + + last_pfn = this_pfn; + } + + cur_base += PFN_PHYS(pinned); + npages -= pinned; + } + + /* Pin the rest chunk */ + ret = crete_vdpa_iotlb_update(vdpa,0, iova, PFN_PHYS(last_pfn - map_pfn + 1), + PFN_PHYS(map_pfn), perm, NULL); +out: + if (ret) { + if (nchunks) { + unsigned long pfn; + + /* + * Unpin the outstanding pages which are yet to be + * mapped but haven't due to vdpa_map() or + * pin_user_pages() failure. + * + * Mapped pages are accounted in vdpa_map(), hence + * the corresponding unpinning will be handled by + * vdpa_unmap(). + */ + WARN_ON(!last_pfn); + for (pfn = map_pfn; pfn <= last_pfn; pfn++) + unpin_user_page(pfn_to_page(pfn)); + } + crete_vdpa_dma_unmap(vdpa,0, start, log_size); + } +unlock: + mmap_read_unlock(vd->mm); +free: + free_page((unsigned long)page_list); + return ret; +} +#endif + +#ifdef HAVE_VDPA_JMND_OPS +static int crete_jmnd_set_log_base(struct vdpa_device *vdpa, u64 log_base, u64 log_size) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa); + struct crete_core_dev *cdev = adapter->cdev; + int ret; + + /* TODO: need disable log first? */ + //crete_info(pdev->dev,"disable log \n"); + //crete_info(pdev->,"enable log log_base = %llu\n",log_base); + vd->mig_log.log_base_l = log_base & 0xFFFFFFFF; + vd->mig_log.log_base_h = log_base >> 32; + vd->mig_log.iova_addr_l = 0; + vd->mig_log.iova_addr_h = 0; + + log_size = log_size << 18; /* by 32K * 8 */ + vd->mig_log.iova_size_l = log_size & 0xFFFFFFFF; + vd->mig_log.iova_size_h = log_size >> 32; + vd->lm_ctrl = CORSICA_LM_ENABLE; + ret = crete_set_mig_log_base(cdev, CRETE_MIG_DEV_VIRTIO, 1, + vd->mig_log.log_base_l, vd->mig_log.log_base_h, + vd->mig_log.iova_addr_l, vd->mig_log.iova_addr_h, + vd->mig_log.iova_size_l, vd->mig_log.iova_size_h); + if (ret < 0) { + crete_err(&cdev->pdev->dev, "set log base errro. ret %d log base 0x%llx log size 0x%llx\n", + ret, log_base, log_size); + } + return ret; +} +#endif + +#ifdef HAVE_VDPA_EULER_OPS +static void crete_vdpa_bind_mm(struct vdpa_device *vdpa) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa); + struct crete_core_dev *cdev = adapter->cdev; + if (vd->mm) { + crete_warn(&cdev->pdev->dev, "crete vdpa mm already been bond\n"); + return; + } + vd->mm = current->mm; + mmgrab(vd->mm); + crete_warn(&cdev->pdev->dev, "crete vdpa mm been bond\n"); +} + +static int crete_vdpa_set_mig_log(struct vdpa_device *vdpa, u64 log_size, u64 iova_base) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa); + struct crete_core_dev *cdev = adapter->cdev; + int ret; + + if((vd->mig_log.log_base_l == 0 && vd->mig_log.log_base_h ==0) || + (vd->mig_log.iova_size_l == 0 && vd->mig_log.iova_size_h == 0)) { + return 0; + } + + /* log base and log size all be assigned a value */ + vd->lm_ctrl = CORSICA_LM_ENABLE; + ret = crete_vdpa_dma_map_log_base(vdpa, log_size, iova_base); + if (ret) { + crete_err(&cdev->pdev->dev, "crete vdpa log base dma map error. ret %d \n", ret); + return ret; + } + ret = crete_set_mig_log_base(cdev, CRETE_MIG_DEV_VIRTIO, 1, + vd->mig_log.log_base_l, vd->mig_log.log_base_h, + vd->mig_log.iova_addr_l, vd->mig_log.iova_addr_h, + vd->mig_log.iova_size_l, vd->mig_log.iova_size_h); + if (ret < 0) { + crete_err(&cdev->pdev->dev, "set log base errro. ret %d log base 0x%llx log size 0x%llx\n", + ret, crete_vdpa_get_log_base(vd), crete_vdpa_get_log_size(vd)); + } + return ret; +} + +static int crete_eular_set_log_base(struct vdpa_device *vdpa, uint64_t log_base) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa); + struct crete_core_dev *cdev = adapter->cdev; + + /* check bind mm first */ + crete_vdpa_bind_mm(vdpa); + vd->mig_log.log_base_l = log_base & 0xFFFFFFFF; + vd->mig_log.log_base_h = log_base >> 32; + vd->mig_log.iova_addr_l = 0; + vd->mig_log.iova_addr_h = 0; + + crete_info(&cdev->pdev->dev, "set log base 0x%llx\n", log_base); + return 0; +} + +static int crete_eular_set_log_size(struct vdpa_device *vdpa, uint64_t log_size) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_adapter *adapter = vdpa_to_adapter(vdpa); + struct crete_core_dev *cdev = adapter->cdev; + u64 iova_size, iova_base, iova_off; + + iova_off = ((u64)vd->mig_log.iova_size_h << 32) | vd->mig_log.iova_size_l; + iova_base = CRETE_LOG_BASE_IOVA + (PFN_UP(iova_off) << PAGE_SHIFT); + iova_size = log_size << 15; /* by 32K */ + vd->mig_log.iova_size_l = iova_size & 0xFFFFFFFF; + vd->mig_log.iova_size_h = iova_size >> 32; + + crete_info(&cdev->pdev->dev, "set log size 0x%llx iova size 0x%llx iova_base 0x%llx iova_off 0x%llx\n", + log_size, iova_size, iova_base, iova_off); + return crete_vdpa_set_mig_log(vdpa, log_size, iova_base); +} + +int crete_vdpa_suspend(struct vdpa_device *vdev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dev = &cdev->pdev->dev; + + crete_info(dev, "crete vdpa suspend\n"); + return 0; +} + +int crete_vdpa_resume(struct vdpa_device *vdev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dev = &cdev->pdev->dev; + + crete_info(dev, "crete vdpa resume\n"); + return 0; +} + +static int crete_vdpa_dma_map(struct vdpa_device *vdev, unsigned int asid, + u64 iova, u64 size, + u64 pa, u32 perm, void *opaque) +{ + int ret = 0; + int flags = perm_to_iommu_flags(perm); + struct crete_vdpa *vd = vdpa_to_vd(vdev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + + if(!vd->domain){ + dev_err(&cdev->pdev->dev,"crete vdpa domain is null\n"); + return -EIO; + } + spin_lock(&vd->iommu_lock); + ret = iommu_map(vd->domain, iova, pa, size, flags); + spin_unlock(&vd->iommu_lock); + + return ret; +} + +static uint32_t crete_vdpa_get_dev_buffer_size(struct vdpa_device *vdpa) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_core_dev *cdev = vd_to_coredev(vd); + crete_info(&cdev->pdev->dev, "get dev buffer size %d\n", vd->config_size); + return vd->config_size; +} + +static int crete_vdpa_get_dev_buffer(struct vdpa_device *vdpa, unsigned int offset, + void __user *dest, unsigned int len) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_core_dev *cdev = vd_to_coredev(vd); + u8 *buf; + + buf = kvzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + crete_vdpa_get_config(vdpa, offset, buf, len); + + if (copy_to_user(dest, buf, len)) { + kvfree(buf); + crete_err(&cdev->pdev->dev, "crete vdpa get dev buffer failed\n"); + return -EFAULT; + } + + kvfree(buf); + crete_info(&cdev->pdev->dev, "crete vdpa get dev buffer completely.\n"); + return 0; +} + +static int crete_vdpa_set_dev_buffer(struct vdpa_device *vdpa, unsigned int offset, + const void __user *src, unsigned int len) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_core_dev *cdev = vd_to_coredev(vd); + u8 *buf; + + buf = vmemdup_user(src, len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + crete_vdpa_set_config(vdpa, offset, buf, len); + kvfree(buf); + crete_info(&cdev->pdev->dev, "crete vdpa set dev buffer offset %d len %d\n", offset, len); + return 0; +} + +static int crete_vdpa_set_mig_state(struct vdpa_device *vdpa, u8 state) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_core_dev *cdev = vd_to_coredev(vd); + crete_info(&cdev->pdev->dev, "set mig state %d\n", state); + return 0; +} + +static int crete_vdpa_log_sync(struct vdpa_device *vdpa) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdpa); + struct crete_core_dev *cdev = vd_to_coredev(vd); + crete_info(&cdev->pdev->dev, "crete vdpa log sync\n"); + return 0; +} +#endif + +struct vdpa_config_ops crete_vdpa_ops = { +#ifdef HAVE_VDPA_OPS_DEVICE_FEAT + .get_device_features = crete_vdpa_get_device_features, + .set_driver_features = crete_vdpa_set_driver_features, + .get_driver_features = crete_vdpa_get_driver_features, +#else + .get_features = crete_vdpa_get_device_features, + .set_features = crete_vdpa_set_driver_features, +#endif + .get_status = crete_vdpa_get_status, + .set_status = crete_vdpa_set_status, +#ifdef HAVE_VDPA_OPS_RESET + .reset = crete_vdpa_reset, +#endif + .get_vq_num_max = crete_vdpa_get_vq_num_max, +#ifdef HAVE_VDPA_OPS_NUM_MIN + .get_vq_num_min = crete_vdpa_get_vq_num_min, +#endif + .get_vq_state = crete_vdpa_get_vq_state, + .set_vq_state = crete_vdpa_set_vq_state, + .set_vq_cb = crete_vdpa_set_vq_cb, + .set_vq_ready = crete_vdpa_set_vq_ready, + .get_vq_ready = crete_vdpa_get_vq_ready, + .set_vq_num = crete_vdpa_set_vq_num, + .set_vq_address = crete_vdpa_set_vq_address, + .get_vq_irq = crete_vdpa_get_vq_irq, + .kick_vq = crete_vdpa_kick_vq, + .get_generation = crete_vdpa_get_generation, + .get_device_id = crete_vdpa_get_device_id, + .get_vendor_id = crete_vdpa_get_vendor_id, + .get_vq_align = crete_vdpa_get_vq_align, + +#ifdef HAVE_VDPA_OPS_GET_CONFIG_SIZE + .get_config_size = crete_vdpa_get_config_size, +#endif + .get_config = crete_vdpa_get_config, + .set_config = crete_vdpa_set_config, + .set_config_cb = crete_vdpa_set_config_cb, + .get_vq_notification = crete_get_vq_notification, +#ifdef HAVE_VDPA_JMND_OPS + /* set log base & size on one functon */ + .set_log_base = crete_jmnd_set_log_base, +#endif + +#ifdef HAVE_VDPA_EULER_OPS + .set_log_base = crete_eular_set_log_base, + .set_log_size = crete_eular_set_log_size, + + .suspend = crete_vdpa_suspend, + .resume = crete_vdpa_resume, + + .dma_map = crete_vdpa_dma_map, + .dma_unmap = crete_vdpa_dma_unmap, + + .get_dev_buffer_size = crete_vdpa_get_dev_buffer_size, + .get_dev_buffer = crete_vdpa_get_dev_buffer, + .set_dev_buffer = crete_vdpa_set_dev_buffer, + .set_mig_state = crete_vdpa_set_mig_state, + .log_sync = crete_vdpa_log_sync, +#endif +}; + +#ifdef HAVE_VDPA_EULER_OPS +static int crete_vdpa_resv_iommu_region(struct iommu_domain *domain, struct device *dma_dev, + struct vhost_iotlb *resv_iotlb) +{ + struct list_head dev_resv_regions; + phys_addr_t resv_msi_base = 0; + struct iommu_resv_region *region; + int ret = 0; + bool with_sw_msi = false; + bool with_hw_msi = false; + + INIT_LIST_HEAD(&dev_resv_regions); + iommu_get_resv_regions(dma_dev, &dev_resv_regions); + + list_for_each_entry(region, &dev_resv_regions, list) { + ret = vhost_iotlb_add_range_ctx(resv_iotlb, region->start, + region->start + region->length - 1, + 0, 0, NULL); + if (ret) { + vhost_iotlb_reset(resv_iotlb); + break; + } + + if (region->type == IOMMU_RESV_MSI) + with_hw_msi = true; + + if (region->type == IOMMU_RESV_SW_MSI) { + resv_msi_base = region->start; + with_sw_msi = true; + } + + } + + if (!ret && !with_hw_msi && with_sw_msi) + ret = iommu_get_msi_cookie(domain, resv_msi_base); + + iommu_put_resv_regions(dma_dev, &dev_resv_regions); + + return ret; +} + +static int crete_vdpa_alloc_domain(struct vdpa_device *vdev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dma_dev = vdpa_get_dma_dev(vdev); + struct bus_type *bus; + int ret; + + /* Device want to do DMA by itself */ + bus = dma_dev->bus; + if (!bus) + return -EFAULT; + + if (!iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY)) + return -ENOTSUPP; + + vd->domain = iommu_domain_alloc(bus); + if (!vd->domain) + return -EIO; + + ret = iommu_attach_device(vd->domain, dma_dev); + if (ret) + goto err_alloc_domain; + + + ret = crete_vdpa_resv_iommu_region(vd->domain, dma_dev, &vd->resv_iotlb); + if (ret) + goto err_attach_device; + + dev_info(&cdev->pdev->dev, "crete vdpa alloc domain successfully\n"); + return 0; +err_attach_device: + iommu_detach_device(vd->domain, dma_dev); +err_alloc_domain: + iommu_domain_free(vd->domain); + vd->domain = NULL; + dev_err(&cdev->pdev->dev, "crete vdpa alloc domain failed\n"); + return ret; +} + +static void crete_vdpa_free_domain(struct vdpa_device *vdev) +{ + struct crete_vdpa *vd = vdpa_to_vd(vdev); + struct crete_core_dev *cdev = vd_to_coredev(vd); + struct device *dma_dev = vdpa_get_dma_dev(vdev); + + if (vd->domain) { + iommu_detach_device(vd->domain, dma_dev); + iommu_domain_free(vd->domain); + } + + vd->domain = NULL; + dev_info(&cdev->pdev->dev, "crete vdpa free domain\n"); +} +#endif + +static int crete_vdpa_get_mac(struct crete_core_dev *cdev, struct device *dev, u8* mac) +{ + int ret; + ret = crete_get_vf_mac(cdev, mac); + if (ret) { + crete_info(dev, "crete vdpa get vf mac error. %d", ret); + } else { + crete_info(dev, "crete vdpa get vf mac %pM\n", mac); + } + + return ret; +} + +int crete_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, + const struct vdpa_dev_set_config *config) +{ + struct crete_vdpa_mgmtdev *crete_mgmt_dev; + struct crete_adapter *adapter; + struct pci_dev *pdev; + struct device *dev; + struct crete_core_dev *core_dev; + struct crete_vnet_hw_cap *hcap; + struct crete_vdpa *cvd; + struct crete_hw *hw; + u8 addr[ETH_ALEN]; + int ret, i; + + crete_mgmt_dev = container_of(mdev, struct crete_vdpa_mgmtdev, mdev); + core_dev = crete_mgmt_dev->cdev; + pdev = core_dev->pdev; + dev = &pdev->dev; + + crete_info(dev, "crete vdpa dev add\n"); + if (crete_mgmt_dev->adapter) { + crete_warn(dev, "cant't add vdpa dev name %s\n", name); + return -EOPNOTSUPP; + } + + hcap = &crete_mgmt_dev->hcap; + hw = &core_dev->hw; + + if (!(hcap->hw_features & BIT_ULL(VIRTIO_F_VERSION_1) && + hcap->hw_features & BIT_ULL(VIRTIO_F_ACCESS_PLATFORM))) { + dev_warn(dev, + "Must provision minimum features 0x%llx for this device", + BIT_ULL(VIRTIO_F_VERSION_1) | + BIT_ULL(VIRTIO_F_ACCESS_PLATFORM)); + return -EOPNOTSUPP; + } + + if (hcap->have_ctl) + hcap->vdpa_max_vqs = 2 * hcap->max_vqpnum + 1; + else + hcap->vdpa_max_vqs = 2; + + +#ifndef HAVE_VDPA_ALLOC_LACK_GROUP + adapter = vdpa_alloc_device(struct crete_adapter, vdpa, + dev, &crete_vdpa_ops, 1, 1, name, false); +#else + #ifndef HAVE_VDPA_ALLOC_LACK_NAME + adapter = vdpa_alloc_device(struct crete_adapter, vdpa, + dev, &crete_vdpa_ops, NULL, false); + #else + adapter = vdpa_alloc_device(struct crete_adapter, vdpa, + dev, &crete_vdpa_ops, hcap->vdpa_max_vqs); + #endif +#endif + if (IS_ERR(adapter)) { + dev_err(dev, "Failed to allocate vDPA structure"); + return PTR_ERR(adapter); + } + memset(&adapter->config, 0, sizeof(struct virtio_net_config)); + crete_mgmt_dev->adapter = adapter; + cvd = &adapter->vd; + cvd->hcap = hcap; + cvd->dev_type = get_dev_type(pdev); + cvd->config_size = crete_init_config_size(cvd); + + cvd->status = 0; + cvd->num_queues = hcap->vdpa_max_vqs; + cvd->qp_nums = cvd->num_queues / 2; + cvd->queue_size = hcap->io_qlen; + cvd->mig_log.nmaps = 0; + cvd->mig_log.iova_size_h = 0; + cvd->mig_log.iova_size_l = 0; + INIT_LIST_HEAD(&cvd->mig_log.list); + + adapter->vdpa.dma_dev = &pdev->dev; + +#ifdef HAVE_VDPA_MGMTDEV_OPS + adapter->vdpa.mdev = mdev; +#endif + + adapter->config.max_virtqueue_pairs = hcap->max_vqpnum; + adapter->config.mtu = 1500; + adapter->config.status = 1; + +#if defined(HAVE_VDPA_MGMTDEV_OPS) + if (config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR)) { + memcpy(adapter->config.mac, config->net.mac, ETH_ALEN); + dev_info(dev, "crete vdpa set mac %pM\n", adapter->config.mac); + } else { + //eth_random_addr(addr); + crete_vdpa_get_mac(core_dev, dev, addr); + memcpy(adapter->config.mac, addr, ETH_ALEN); + } + + if (config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP)) { + dev_info(dev, "crete vdpa set vQP %d\n", config->net.max_vq_pairs); + } +#else + eth_random_addr(addr); + memcpy(adapter->config.mac, addr, ETH_ALEN); +#endif + + adapter->cdev = core_dev; + adapter->priv = crete_mgmt_dev; + + + dev_info(dev, "[%s] [%d] vf_packed %d vf_irq %d queue size %d vdpa_max_vqs =%d\n", + __func__, __LINE__, vf_packed, vf_irq, crete_queue_size, hcap->vdpa_max_vqs); + if (hcap->vdpa_max_vqs > CORSICA_MAX_QUEUES) { + dev_err(dev, + "[%s] [%d] hcap->vdpa_max_vqs > hcap->vdpa_max_vqs", + __func__, __LINE__); + hcap->vdpa_max_vqs = hcap->vdpa_max_vqs; + + } + for (i = 0; i < hcap->vdpa_max_vqs; i++) { + if (cvd == NULL) { + dev_err(dev, "cvd is null\n"); + ret = -66; + goto err; + } + + cvd->vring[i].irq = VIRTIO_MSI_NO_VECTOR; + + if (i == 2 * hcap->max_vqpnum) { + cvd->vring[i].notify_addr = + core_dev->db_base + 0x1000; + cvd->vring[i].notify_pa = + core_dev->bar_addr + ((hw->jnd.offset) << 12) + 0x1000; + continue; + } + cvd->vring[i].notify_addr = core_dev->db_base; + cvd->vring[i].notify_pa = + core_dev->bar_addr + ((hw->jnd.offset) << 12); + } + dev_info(dev, "crete core dev doorbell base address:0x%pK\n", + core_dev->db_base); + + ret = crete_vdpa_register_event_handler(cvd); + if (ret) { + dev_err(dev, "Failed to register for crete events: %pe\n", + ERR_PTR(ret)); + goto err; + } + +#if defined(HAVE_VDPA_MGMTDEV_OPS) + ret = _vdpa_register_device(&adapter->vdpa, cvd->num_queues); +#else + ret = vdpa_register_device(&adapter->vdpa); +#endif + if (ret) { + dev_err(dev, "Failed to register to vDPA bus %d", ret); + goto err_event; + } + + /* the msix was enabled on the crete core, so when add a vdpa device, need free it */ + crete_event_exit(hw); + crete_exit_irq(core_dev); + //pci_set_drvdata(pdev, crete_mgmt_dev); //core driver is used + +#ifdef HAVE_VDPA_EULER_OPS + /* alloc domina */ + vhost_iotlb_init(&cvd->resv_iotlb, 0, 0); + ret = crete_vdpa_alloc_domain(&adapter->vdpa); + if (ret) { + crete_err(dev, "crete vdpa alloc domain failed %d", ret); + goto err_event; + } +#endif + return 0; +err_event: + crete_vdpa_unregister_event_handler(cvd); +err: + put_device(&adapter->vdpa.dev); + return ret; +} + +void crete_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev) +{ + struct crete_vdpa_mgmtdev *crete_mgmt_dev; + struct crete_adapter *adapter; + + crete_info(mdev->device, "crete vdpa del dev\n"); + crete_mgmt_dev = container_of(mdev, struct crete_vdpa_mgmtdev, mdev); + adapter = crete_mgmt_dev->adapter; + crete_vdpa_unregister_event_handler(&adapter->vd); +#ifdef HAVE_VDPA_EULER_OPS + /* unbind the mm, MUST befor the free domain */ + crete_vdpa_unbind_mm(dev); + crete_vdpa_free_domain(dev); +#endif + +#ifndef HAVE_VDPA_MGMTDEV_OPS + vdpa_unregister_device(dev); + /* TODO: need release adapter */ +#else + _vdpa_unregister_device(dev); +#endif + crete_mgmt_dev->adapter = NULL; +} + +static u64 crete_get_max_supported_vqs(struct crete_vdpa_mgmtdev + *crete_mgmt_dev) +{ + int ret; + u16 qsize; + u8 maxqpnum; + u8 ctrlqsize; + struct crete_core_dev *core_dev = crete_mgmt_dev->cdev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_vnet_hw_cap *hcap = &crete_mgmt_dev->hcap; + + ret = crete_get_qp_cap(core_dev, &qsize, &maxqpnum, &ctrlqsize); + if (ret) { + dev_err(&pdev->dev, "%s is error\n", __func__); + return -EINVAL; + } + +// hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_NET_F_CTRL_VQ)); + hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_NET_F_CTRL_RX)); + hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_NET_F_CTRL_VLAN)); +// hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_NET_F_GUEST_ANNOUNCE)); + hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)); +// hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_NET_F_MQ)); + /* openEular SP1 don't supprot the PACKED */ + if (!vf_packed) + hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_F_RING_PACKED)); + /* + * To supported the openEular qemu, + * using this bit set the size of bitmap chunk. + */ + hcap->hw_features = hcap->hw_features & (~ BIT_ULL(VIRTIO_NET_F_SPEED_DUPLEX)); + + if (hcap->hw_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) { + hcap->have_ctl = true; + hcap->ctl_qlen = crete_queue_size; + } else { + hcap->have_ctl = false; + hcap->ctl_qlen = 0; + } + hcap->max_vqpnum = maxqpnum; + hcap->io_qlen = crete_queue_size; /* don't use the cap value, use the default */ + dev_info(&pdev->dev, + "crete vqs: ctl_qlen[0x%x] ioqlen[0x%x] maxvqs[%d]\n", + hcap->ctl_qlen, hcap->io_qlen, hcap->max_vqpnum); + return ret; +} + +static u64 crete_get_supported_features(struct crete_vdpa_mgmtdev + *crete_mgmt_dev) +{ + struct crete_core_dev *core_dev = crete_mgmt_dev->cdev; + struct pci_dev *pdev = core_dev->pdev; + struct crete_vnet_hw_cap *hcap = &crete_mgmt_dev->hcap; + u64 dev_features; + u64 ret; + + ret = + crete_cmd_get_features(core_dev, CRETE_VIRTIO_NET_DEV_FEAT, + &dev_features); + if (ret) { + dev_err(&pdev->dev, "get device features is error\n"); + ret = -EINVAL; + } + hcap->hw_features = dev_features; + dev_info(&pdev->dev, "device supported features[0x%llx] [0x%llx]\n", + hcap->hw_features, dev_features); + return ret; +} + +static const struct vdpa_mgmtdev_ops crete_vdpa_mgmt_dev_ops = { + .dev_add = crete_vdpa_dev_add, + .dev_del = crete_vdpa_dev_del +}; + +int crete_vdpa_get_mgmt_info(struct crete_vdpa_mgmtdev *cvm) +{ + int ret; + u32 dev_type; + struct crete_core_dev *core_dev = cvm->cdev; + struct pci_dev *pdev = core_dev->pdev; + + ret = crete_get_supported_features(cvm); + if (ret < 0) { + ret = -EOPNOTSUPP; + goto err; + } + ret = crete_get_max_supported_vqs(cvm); + if (ret < 0) { + ret = -EOPNOTSUPP; + goto err; + } + + dev_type = get_dev_type(pdev); + switch (dev_type) { + case VIRTIO_ID_NET: + cvm->mdev.id_table = id_table_net; + break; + case VIRTIO_ID_BLOCK: + cvm->mdev.id_table = id_table_blk; + break; + default: + dev_err(&pdev->dev, "VIRTIO ID %u not supported\n", dev_type); + ret = -EOPNOTSUPP; + goto err; + } + + if (cvm->hcap.have_ctl) + cvm->mdev.max_supported_vqs = 2 * cvm->hcap.max_vqpnum + 1; + else + cvm->mdev.max_supported_vqs = 2; + + cvm->mdev.config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR); + cvm->mdev.config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP); + cvm->mdev.supported_features = cvm->hcap.hw_features; + cvm->mdev.ops = &crete_vdpa_mgmt_dev_ops; + cvm->mdev.device = &pdev->dev; + return 0; +err: + return ret; +} + +int crete_vdpa_set_device_type(struct crete_core_dev *core_dev) +{ + + int ret; + struct pci_dev *pdev = core_dev->pdev; + u32 devtype = 0; + + ret = crete_set_dev_type(core_dev, CRETE_VNET_DEV); + if (ret) { + dev_err(&pdev->dev, + "Failed to set device type VNET, set cmd error\n"); + return -EINVAL; + } + ret = crete_get_dev_type(core_dev, &devtype); + if (ret) { + dev_err(&pdev->dev, "set dev type failed\n"); + goto out; + } + + if (devtype != CRETE_VNET_DEV) { + dev_err(&pdev->dev, " dev type not right check failed\n"); + goto out; + } + + return ret; +out: + return -EINVAL; +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_dev.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_dev.h new file mode 100644 index 0000000..cbe89df --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_dev.h @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * JaguarMicro virt device driver for virtio dataplane offloading + * + * Copyright (C) 2020 JaguarMicro Corporation. + * + * Author: Angus Chen + * + */ + +#ifndef _CRETE_VDPA_DEV_H_ +#define _CRETE_VDPA_DEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../crete-core/crete_cmd.h" +#include "kcompat_generated_defs.h" +/* Max 8 data queue pairs(16 queues) and one control vq for now. */ +#define CORSICA_MAX_QUEUES 65 +#define CORSICA_MAX_QUEUES_NOCTRL 64 + +#define CORSICA_QUEUE_ALIGNMENT PAGE_SIZE +/*attention pls ,it's the depth of queue*/ +#define CORSICA_QUEUE_SIZE_MAX 1024 +#define CORSICA_QUEUE_SIZE_MIN 64 +#define CORSICA_MSI_CONFIG_OFF 0 +#define CORSICA_MSI_QUEUE_OFF 1 +#define CORSICA_PCI_MAX_RESOURCE 6 +#define VHOST_F_LOG_ALL 26 +#define VHOST_ACCESS_WO 0x2 +#define DEBUG + + + +#define CORSICA_ERR(pdev, fmt, ...) dev_err(&pdev->dev, fmt, ##__VA_ARGS__) +#define CORSICA_DBG(pdev, fmt, ...) dev_dbg(&pdev->dev, fmt, ##__VA_ARGS__) +#define CORSICA_INFO(pdev, fmt, ...) dev_info(&pdev->dev, fmt, ##__VA_ARGS__) + +#define CORSICA_DEV_CONFIG_OFFSIZE 0x40 +#define CORSICA_LOG_BASE_L 0x2 +#define CORSICA_LOG_BASE_H 0x6 +#define CORSICA_32_BIT_MASK 0xffffffff +#define CORSICA_LOG_BASE 0x100000000000 +#define CORSICA_LM_DISABLE 0x0 +#define CORSICA_LM_ENABLE 0x1 +#define CORSICA_LM_STOP_DEV 0x2 +#define CORSICA_LM_ENABLE_VF 0x4 +#define CORSICA_LM_ENABLE_PF 0x8 +#define CORSICA_DEV_STOPED 0x4 + +#define VIRTIO_NET_CONFIG_OFFSET_MAC offsetof(struct virtio_net_config, mac) +#define VIRTIO_NET_CONFIG_OFFSET_MTU offsetof(struct virtio_net_config, mtu) +#define VIRTIO_NET_CONFIG_OFFSET_STATUS offsetof(struct virtio_net_config, status) +#define CONFIG_ENABLE_TLP 0 + +#define CRETE_LOG_BASE_IOVA 0x100000000000 +/*************************support bclinux********************************/ + +#ifndef HAVE_VDPA_MGMTDEV_OPS +struct vdpa_dev_set_config { + struct { + u8 mac[ETH_ALEN]; + u16 mtu; + u16 max_vq_pairs; + } net; + u64 mask; +}; + +struct vdpa_mgmtdev_ops; + +struct vdpa_mgmt_dev { + struct device *device; + const struct vdpa_mgmtdev_ops *ops; + struct virtio_device_id *id_table; + u64 config_attr_mask; + struct list_head list; + u64 supported_features; + u32 max_supported_vqs; +}; + + +struct vdpa_mgmtdev_ops { + int (*dev_add)(struct vdpa_mgmt_dev *mdev, const char *name, + const struct vdpa_dev_set_config *config); + void (*dev_del)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev); +}; + +#endif + + +enum crete_net_status { + CRETE_NET_DEV_STARTUP, + CRETE_NET_DEV_FEATURE_OK, + CRETE_NET_DEV_DEV_OK, + CRETE_NET_DEV_STOPPED +}; + +#define CRETE_RX_SEQ 0 +#define CRETE_TX_SEQ 1 + +struct crete_mig_log { + u32 log_base_l; + u32 log_base_h; + /* TODO: need use array to store multiple iova */ + u32 iova_addr_l; + u32 iova_addr_h; + u32 iova_size_l; + u32 iova_size_h; + struct list_head list; + unsigned int limit; + unsigned int nmaps; +} __packed; + +struct virtio_vdpa_config { + union { + struct virtio_net_config v_net_config; + struct virtio_blk_config v_blk_config; + u8 config_offset[CORSICA_DEV_CONFIG_OFFSIZE]; + }; +}; + +struct crete_vdpa_config { + struct virtio_vdpa_config vdpa_config; + u16 lm_ctrl; + u16 reserved; + u32 log_base_l; + u32 log_base_h; + struct crete_mig_log mig_log; + u8 log_mask; + u8 reserved1; +} __packed; + +struct crete_vring_lm_cfg { + u16 last_avail_idx; + u16 can_used; /* indircat the `last_avail_idx already been getted */ +}; + +struct crete_lm_cfg { + struct crete_vdpa_config vdpa_lm_cfg; + struct crete_vring_lm_cfg vring_lm_cfg[CORSICA_MAX_QUEUES]; +}; + +#define crete_private_to_vd(adapter) \ + (&((struct crete_adapter *)adapter)->vd) + +struct vring_info { + u64 desc; + u64 avail; + u64 used; + u16 size; + u16 last_avail_idx; + bool ready; + void __iomem *notify_addr; + phys_addr_t notify_pa; + u32 irq; + u32 irqvec; + struct vdpa_callback cb; + char msix_name[256]; +}; + +struct crete_iotlb_map { + struct list_head link; + u64 start; + u64 last; + u64 size; + u64 addr; + u32 perm; + u32 flags_padding; + u64 __subtree_last; + void *opaque; +}; + +struct crete_vdpa { + struct crete_vnet_hw_cap *hcap; //vdpa device hw capability +/*********vdpa* soft capability*******/ + u8 status; + u32 generation; + u16 qp_nums; + u16 num_queues; + u16 queue_size; + u64 driver_features; + u32 dev_type; +/************vdap queue***************************/ + struct vring_info vring[CORSICA_MAX_QUEUES]; + char config_msix_name[256]; + struct vdpa_callback config_cb; + unsigned int config_irq; + u32 config_size; + u16 lm_ctrl; + u16 announce_count; + struct crete_mig_log mig_log; + bool have_hw_ctrl; + bool have_soft_ctrl; + bool have_ctrl_irq; + bool host_polling; + __le16 ctl_qlen; + u8 __iomem *lm_cfg; + struct crete_vring_lm_cfg vring_lm_cfg[CORSICA_MAX_QUEUES]; + struct crete_nb cnb; + spinlock_t iommu_lock; + struct iommu_domain *domain; + struct vhost_iotlb resv_iotlb; + struct mm_struct *mm; +}; + + +struct crete_adapter { + struct vdpa_device vdpa; + struct virtio_net_config config; + struct crete_core_dev *cdev; + struct crete_vdpa vd; + struct crete_vdpa_mgmtdev *priv; +}; + +struct crete_vnet_hw_cap { + __le64 hw_features; + __le16 max_vqpnum; + __le16 io_qlen; + __le16 ctl_qlen; + bool have_ctl; + __le16 vdpa_max_vqs; +}; + +struct crete_vdpa_mgmtdev { + struct vdpa_mgmt_dev mdev; + struct crete_adapter *adapter; + struct crete_core_dev *cdev; + struct crete_vnet_hw_cap hcap; +}; + +int crete_vdpa_set_hwstatus(struct crete_core_dev *core_dev, u8 status, + struct device *dev); +int crete_vdpa_get_mgmt_info(struct crete_vdpa_mgmtdev *cvm); + +int crete_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, + const struct vdpa_dev_set_config *config); + +void crete_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev); +int crete_vdpa_set_device_type(struct crete_core_dev *core_dev); +#endif /* _CRETE_VDPA_DEV_H_ */ + + + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_main.c b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_main.c new file mode 100644 index 0000000..814f3c2 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/crete_vdpa_main.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Jaguar Micro. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "crete_vdpa_dev.h" +#define CRETE_VDPA_DRV_DESCRIPTION "JaguarMicro/CRETE VDPA VF Device Driver" +#define CRETE_VDPA_AUX_DEV_NAME "crete_core.vnet" +#define CRETE_VDPA_DRV_NAME "crete_vnet" + +static int crete_vdpa_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct crete_aux_dev *cadev = + container_of(adev, struct crete_aux_dev, adev); + struct crete_core_dev *core_dev = cadev->core_dev; + struct pci_dev *pdev = core_dev->pdev; + struct device *dev = &pdev->dev; + struct crete_vdpa_mgmtdev *cvm; + int ret; +#if defined(HAVE_VDPA_MGMTDEV_OPS) +#else + struct vdpa_dev_set_config vdsc; +#endif + + ret = crete_vdpa_set_device_type(core_dev); + if (ret) { + dev_err(dev, + "Failed to alloc memory for the vDPA management device\n"); + return -EINVAL; + } + + ret = crete_vdpa_set_hwstatus(core_dev, CRETE_NET_DEV_STARTUP, dev); + if (ret) { + dev_err(dev, "set net dev status failed\n"); + return -EINVAL; + } + cvm = kzalloc(sizeof(struct crete_vdpa_mgmtdev), GFP_KERNEL); + if (!cvm) + return -ENOMEM; + cvm->cdev = core_dev; + ret = crete_vdpa_get_mgmt_info(cvm); + if (ret) { + dev_err(dev, "Failed to set vDPA management\n"); + goto err; + } + dev_set_drvdata(&adev->dev, cvm); + +#if defined(HAVE_VDPA_MGMTDEV_OPS) + ret = vdpa_mgmtdev_register(&cvm->mdev); + if (ret) { + dev_err(dev, + "Failed to initialize the management interfaces\n"); + goto err; + } +#else + memset(&vdsc, 0, sizeof(struct vdpa_dev_set_config)); + ret = crete_vdpa_dev_add(&cvm->mdev, "NULL", &vdsc); + if (ret) { + dev_err(dev, + "Failed to add vdpa device ret:%d\n",ret); + goto err_add; + } +#endif + + //crete_vdpa_debugfs_add_dev(cvm); + //crete_vdpa_debugfs_add_hcap(cvm); + return 0; +err_add: + dev_set_drvdata(&adev->dev, NULL); +err: + kfree(cvm); + return ret; +} + +static void crete_vdpa_remove(struct auxiliary_device *adev) +{ + struct crete_vdpa_mgmtdev *crete_mgmt_dev; + struct device *dev = &adev->dev; + struct crete_adapter *adapter; + struct vdpa_device *vdpa_dev; + + crete_mgmt_dev = dev_get_drvdata(&adev->dev); + + dev_info(dev, "crete vdpa remove\n"); +#if defined(HAVE_VDPA_MGMTDEV_OPS) + vdpa_mgmtdev_unregister(&crete_mgmt_dev->mdev); +#else + adapter = crete_mgmt_dev->adapter; + vdpa_dev = &adapter->vdpa; + crete_vdpa_dev_del(&crete_mgmt_dev->mdev, vdpa_dev); + crete_mgmt_dev->adapter = NULL; +// crete_vdpa_debugfs_del_vdpadev(crete_mgmt_dev); + kfree(crete_mgmt_dev); + dev_set_drvdata(&adev->dev, NULL); +#endif + +} + +static const struct auxiliary_device_id crete_vdpa_id_table[] = { + {.name = CRETE_VDPA_AUX_DEV_NAME,}, + {}, +}; + +static struct auxiliary_driver crete_vdpa_driver = { + .name = CRETE_VDPA_DRV_NAME, + .probe = crete_vdpa_probe, + .remove = crete_vdpa_remove, + .id_table = crete_vdpa_id_table, +}; + +static void __exit crete_vdpa_cleanup(void) +{ + auxiliary_driver_unregister(&crete_vdpa_driver); + +// crete_vnet_debugfs_destroy(); +} + +module_exit(crete_vdpa_cleanup); + +static int __init crete_vdpa_init(void) +{ + int err; + +// crete_vnet_debugfs_create(); + err = auxiliary_driver_register(&crete_vdpa_driver); + if (err) { + pr_err("%s: aux driver register failed: %pe\n", + CRETE_VDPA_DRV_NAME, ERR_PTR(err)); + //crete_vnet_debugfs_destroy(); + } + + return err; +} + +module_init(crete_vdpa_init); + +MODULE_DESCRIPTION(CRETE_VDPA_DRV_DESCRIPTION); +MODULE_AUTHOR("jaguarmicro.com"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("3.1.1"); diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat-generator.sh b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat-generator.sh new file mode 100644 index 0000000..66bf514 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat-generator.sh @@ -0,0 +1,173 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only + +set -Eeuo pipefail + +# This file generates HAVE_ and NEED_ defines for current kernel +# (or KSRC if provided). +# +# It does so by 'gen' function calls (see body of 'gen-devlink' for examples). +# 'gen' could look for various kinds of declarations in provided kernel headers, +# eg look for an enum in one of files specified and check if given enumeration +# (single value) is present. See 'Documentation' or comment above the 'gen' fun +# in the kcompat-lib.sh. + +# Why using bash/awk instead of an old/legacy approach? +# +# The aim is to replicate all the defines provided by human developers +# in the past. Additional bonus is the fact, that we no longer need to care +# about backports done by OS vendors (RHEL, SLES, ORACLE, UBUNTU, more to come). +# We will even work (compile) with only part of backports provided. +# +# To enable smooth transition, especially in time of late fixes, "old" method +# of providing flags should still work as usual. + +# End of intro. +# Find info about coding style/rules at the end of file. +# Most of the implementation is in kcompat-lib.sh, here are actual 'gen' calls. + +export LC_ALL=C +SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" +ORIG_CWD="$(pwd)" +trap 'rc=$?; echo >&2 "$(realpath "$ORIG_CWD/${BASH_SOURCE[0]}"):$LINENO: failed with rc: $rc"' ERR + +# shellcheck source=kcompat-lib.sh +source "$SCRIPT_DIR"/kcompat-lib.sh + +# DO NOT break gen calls below (via \), to make our compat code more grep-able, +# keep them also grouped, first by feature (like DEVLINK), then by .h filename +# finally, keep them sorted within a group (sort by flag name) + +# handy line of DOC copy-pasted form kcompat-lib.sh: +# gen DEFINE if (KIND [METHOD of]) NAME [(matches|lacks) PATTERN|absent] in + + +function gen-vdpa() { + vh='include/linux/vdpa.h' + vm='include/linux/virtio_pci_modern.h' + if [ -f $vm ];then + gen HAVE_VIRTIO_PCI_MODERN if struct virtio_pci_modern_device in $vm + fi + #gen HAVE_VDPA_OPS_RESET_INFO if method reset of vdpa_config_ops matches lacks status in "$vh" + gen HAVE_VDPA_RESET_LACK_INFO if method reset of vdpa_config_ops lacks state in "$vh" + gen HAVE_VDPA_OPS_RESET if method reset of vdpa_config_ops in "$vh" + gen HAVE_VDPA_ALLOC_LACK_GROUP if fun __vdpa_alloc_device lacks ngroups in "$vh" + gen HAVE_VDPA_ALLOC_LACK_NAME if fun __vdpa_alloc_device lacks name in "$vh" + gen HAVE_VDPA_VQ_STATE_LACK_PACKED if struct vdpa_vq_state lacks packed in "$vh" + gen HAVE_VDPA_MGMTDEV_OPS if struct vdpa_mgmtdev_ops in "$vh" + gen HAVE_VDPA_DEV_SET_CONFIG if struct vdpa_dev_set_config in "$vh" + gen HAVE_VDPA_OPS_DEVICE_FEAT if method get_device_features of vdpa_config_ops in "$vh" + gen HAVE_VDPA_OPS_GET_CONFIG_SIZE if method get_config_size of vdpa_config_ops in "$vh" + gen HAVE_VDPA_OPS_LOG_BASE if method set_log_base of vdpa_config_ops in "$vh" + gen HAVE_VDPA_OPS_NUM_MIN if method get_vq_num_min of vdpa_config_ops in "$vh" +} + +function gen-aux() { + ah='include/linux/auxiliary_bus.h' + mh='include/linux/mod_devicetable.h' + if config_has CONFIG_AUXILIARY_BUS; then + gen HAVE_AUXILIARY_DRIVER_INT_REMOVE if method remove of auxiliary_driver matches 'int' in "$ah" + fi + + # generate HAVE_AUXILIARY_DEVICE_ID only for cases when it's disabled in .config + if ! config_has CONFIG_AUXILIARY_BUS; then + gen HAVE_AUXILIARY_DEVICE_ID if struct auxiliary_device_id in "$mh" + fi +} + + +function gen-pci() { + pcih='include/linux/pci.h' + gen HAVE_PCI_MSIX_ALLOC_IRQ_AT if fun pci_msix_alloc_irq_at in "$pcih" + gen HAVE_PCI_MSIX_CAN_ALLOC_DYN if fun pci_msix_can_alloc_dyn in "$pcih" + gen HAVE_PCI_MSIX_FREE_IRQ if fun pci_msix_free_irq in "$pcih" + gen HAVE_PER_VF_MSIX_SYSFS if method sriov_set_msix_vec_count of pci_driver in "$pcih" + gen HAVE_STRUCT_PCI_DEV_PTM_ENABLED if struct pci_dev matches ptm_enabled in "$pcih" + gen NEED_PCIE_FLR if fun pcie_flr absent in "$pcih" + gen NEED_PCIE_FLR_RETVAL if fun pcie_flr lacks 'int pcie_flr' in "$pcih" + gen NEED_PCIE_PTM_ENABLED if fun pcie_ptm_enabled absent in "$pcih" + gen NEED_PCI_ENABLE_PTM if fun pci_enable_ptm absent in "$pcih" +} + + +# all the generations, extracted from main() to keep normal code and various +# prep separated +function gen-all() { + # code above is covered by unit_tests/test_gold.sh + if [ -n "${JUST_UNIT_TESTING-}" ]; then + return + fi + gen-aux + gen-vdpa + gen-pci +} + +function main() { + # check if caller (like our makefile) wants to redirect output to file + if [ -n "${OUT-}" ]; then + + # in case OUT exists, we don't want to overwrite it, instead + # write to a temporary copy. + if [ -s "${OUT}" ]; then + TMP_OUT="$(mktemp "${OUT}.XXX")" + trap "rm -f '${TMP_OUT}'" EXIT + + REAL_OUT="${OUT}" + OUT="${TMP_OUT}" + fi + + exec > "$OUT" + # all stdout goes to OUT since now + echo "/* Autogenerated for KSRC=${KSRC-} via $(basename "$0") */" + fi + if [ -d "${KSRC-}" ]; then + cd "${KSRC}" + fi + + # check if KSRC was ok/if we are in proper place to look for headers + if [ -z "$(filter-out-bad-files include/linux/kernel.h)" ]; then + echo >&2 "seems that there are no kernel includes placed in KSRC=${KSRC} + pwd=$(pwd); ls -l:" + ls -l >&2 + exit 8 + fi + + # we need some flags from .config or (autoconf.h), required + if [ ! -f "${CONFFILE-}" ]; then + echo >&2 ".config should be passed as env CONFFILE + (and it's not set or not a file)" + exit 9 + fi + + echo "#ifndef _KCOMPAT_GENERATED_DEFS_H_" + echo "#define _KCOMPAT_GENERATED_DEFS_H_" + gen-all + echo "#endif /* _KCOMPAT_GENERATED_DEFS_H_ */" + + if [ -n "${OUT-}" ]; then + cd "$ORIG_CWD" + + # Compare and see if anything changed. This avoids updating + # mtime of the file. + if [ -n "${REAL_OUT-}" ]; then + if cmp --silent "${REAL_OUT}" "${TMP_OUT}"; then + # exit now, skipping print of the output since + # there were no changes. the trap should + # cleanup TMP_OUT + exit 0 + fi + + mv -f "${TMP_OUT}" "${REAL_OUT}" + OUT="${REAL_OUT}" + fi + + # dump output, will be visible in CI + if [ -n "${JUST_UNIT_TESTING-}${QUIET_COMPAT-}" ]; then + return + fi + cat -n "$OUT" >&2 + fi +} + +main + diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat-lib.sh b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat-lib.sh new file mode 100644 index 0000000..57d1b7d --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat-lib.sh @@ -0,0 +1,310 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only + +# to be sourced + +# General shell helpers + +# exit with non-zero exit code; if there is only one param: +# exit with msg $1 and exit code from last command (or 99 if = 0) +# otherwise, exit with $1 and use remaining arguments as msg +function die() { + rc=$? + if [ $# -gt 1 ]; then + rc="$1" + shift + fi + [ "$rc" -ne 0 ] || rc=99 + echo >&2 "$@" + exit $rc +} + +# filter out paths that are not files +# input $@, output via echo; +# note: pass `-` for stdin +# note: outputs nothing if all input files are "bad" (eg. not existing), but it +# is left for caller to decide if this is an erorr condition; +# note: whitespaces are considered "bad" as part of filename, it's an error. +function filter-out-bad-files() { + if [[ $# = 1 && "$1" = '-' ]]; then + echo - + return 0 + fi + if [ $# = 0 ]; then + die 10 "no files passed, use '-' when reading from pipe (|)" + fi + local any=0 diagmsgs=/dev/stderr re=$'[\t \n]' + [ -n "${QUIET_COMPAT-}" ] && diagmsgs=/dev/null + for x in "$@"; do + if [ -e "$x" ]; then + if [[ "$x" =~ $re ]]; then + die 11 "err: filename contains whitespaces: $x." + fi + echo "$x" + any=1 + else + echo >&"$diagmsgs" filtering "$x" out + fi + done + if [ $any = 0 ]; then + echo >&"$diagmsgs" 'all files (for given query) filtered out' + fi +} + +# Basics of regexp explained, as a reference for mostly-C programmers: +# (bash) "regexp-$VAR-regexp" - bash' VARs are placed into "QUOTED" strings +# /\);?$/ - match end of function declaration, $ is end of string +# ^[ \t]* - (heuristic), anything but comment, eg to exclude function docs +# /STH/, /END/ - (awk), print all lines sice STH matched, up to END, inclusive + +# "Whitespace only" +WB='[ \t\n]' + +# Helpers below print the thing that is looked for, for further grep'ping/etc. +# That simplifies process of excluding comments or spares us state machine impl. +# +# We take advantage of current/common linux codebase formatting here. +# +# Functions in this section require input file/s passed as args +# (usually one, but more could be supplied in case of renames in kernel), +# '-' could be used as an (only) file argument to read from stdin/pipe. + +# wrapper over find-something-decl() functions below, to avoid repetition +# pass $what as $1, $end as $2, and $files to look in as rest of args +function find-decl() { + test $# -ge 3 # ensure that there are at least 3 params + local what end files + what="$1" + end="$2" + shift 2 + files="$(filter-out-bad-files "$@")" || die + if [ -z "$files" ]; then + return 0 + fi + # shellcheck disable=SC2086 + awk " + /^$WB*\*/ {next} + $what, $end + " $files +} + +# yield $1 function declaration (signature), don't pass return type in $1 +# looks only in files specified ($2, $3...) +function find-fun-decl() { + test $# -ge 2 + local what end + what="/$WB*([(]\*)?$1$WB*($|[()])/" + end='/\);?$/' + shift + find-decl "$what" "$end" "$@" +} + +# yield $1 enum declaration (type/body) +function find-enum-decl() { + test $# -ge 2 + local what end + what="/^$WB*enum$WB+$1"' \{$/' + end='/\};$/' + shift + find-decl "$what" "$end" "$@" +} + +# yield $1 struct declaration (type/body) +function find-struct-decl() { + test $# -ge 2 + local what end + what="/^$WB*struct$WB+$1"' \{$/' + end='/^\};$/' # that's (^) different from enum-decl + shift + find-decl "$what" "$end" "$@" +} + +# yield first line of $1 macro definition +function find-macro-decl() { + test $# -ge 2 + local what end + # only unindented defines, only whole-word match + what="/^#define$WB+$1"'([ \t\(]|$)/' + end=1 # only first line; use find-macro-implementation-decl for full body + shift + find-decl "$what" "$end" "$@" +} + +# yield full macro implementation +function find-macro-implementation-decl() { + test $# -ge 2 + local what end + # only unindented defines, only whole-word match + what="/^#define$WB+$1"'([ \t\(]|$)/' + # full implementation, until a line not ending in a backslash. + # Does not handle macros with comments embedded within the definition. + end='/[^\\]$/' + shift + find-decl "$what" "$end" "$@" +} + +# yield first line of $1 typedef definition (simple typedefs only) +# this probably won't handle typedef struct { \n int foo;\n}; +function find-typedef-decl() { + test $# -ge 2 + local what end + what="/^typedef .* $1"';$/' + end=1 + shift + find-decl "$what" "$end" "$@" +} + +# gen() - DSL-like function to wrap around all the other +# +# syntax: +# gen DEFINE if (KIND [METHOD of]) NAME [(matches|lacks) PATTERN|absent] in + +# where: +# DEFINE is HAVE_ or NEED_ #define to print; +# `if` is there to just read it easier and made syntax easier to check; +# +# NAME is the name for what we are looking for; +# +# KIND specifies what kind of declaration/definition we are looking for, +# could be: fun, enum, struct, method, macro, typedef, +# 'implementation of macro' +# for KIND=method, we are looking for function ptr named METHOD in struct +# named NAME (two optional args are then necessary (METHOD & of)); +# +# for KIND='implementation of macro' we are looking for the full +# implementation of the macro, not just its first line. This is usually +# combined with "matches" or "lacks". +# +# next [optional] args could be used: +# matches PATTERN - use to grep for the PATTERN within definition +# (eg, for ext_ack param) +# lacks - use to add #define only if there is no match of the PATTERN, +# *but* the NAME is *found* +# absent - the NAME that we grep for must be not found +# (ie: function not exisiting) +# +# without this optional params, behavior is the same as with +# `matches .` - use to grep just for existence of NAME; +# +# `in` is there to ease syntax, similar to `if` before. +# +# is just space-separate list of files to look in, +# single (-) for stdin. +# +# PATTERN is an awk pattern, will be wrapped by two slashes (/) +function gen() { + test $# -ge 6 || die 20 "too few arguments, $# given, at least 6 needed" + local define if_kw kind name in_kw # mandatory + local of_kw method_name operator pattern # optional + local src_line="${BASH_SOURCE[0]}:${BASH_LINENO[0]}" + define="$1" + if_kw="$2" + kind="$3" + local orig_args_cnt=$# + shift 3 + [ "$if_kw" != if ] && die 21 "$src_line: 'if' keyword expected, '$if_kw' given" + case "$kind" in + fun|enum|struct|macro|typedef) + name="$1" + shift + ;; + method) + test $# -ge 5 || die 22 "$src_line: too few arguments, $orig_args_cnt given, at least 8 needed" + method_name="$1" + of_kw="$2" + name="$3" + shift 3 + [ "$of_kw" != of ] && die 23 "$src_line: 'of' keyword expected, '$of_kw' given" + ;; + implementation) + test $# -ge 5 || die 28 "$src_line: too few arguments, $orig_args_cnt given, at least 8 needed" + of_kw="$1" + kind="$2" + name="$3" + shift 3 + [ "$of_kw" != of ] && die 29 "$src_line: 'of' keyword expected, '$of_kw' given" + [ "$kind" != macro ] && die 30 "$src_line: implementation only supports 'macro', '$kind' given" + kind=macro-implementation + ;; + *) die 24 "$src_line: unknown KIND ($kind) to look for" ;; + esac + operator="$1" + case "$operator" in + absent) + pattern='.' + in_kw="$2" + shift 2 + ;; + matches|lacks) + pattern="$2" + in_kw="$3" + shift 3 + ;; + in) + operator=matches + pattern='.' + in_kw=in + shift + ;; + *) die 25 "$src_line: unknown OPERATOR ($operator) to look for" ;; + esac + [ "$in_kw" != in ] && die 26 "$src_line: 'in' keyword expected, '$in_kw' given" + test $# -ge 1 || die 27 "$src_line: too few arguments, at least one filename expected" + + local first_decl= + if [ "$kind" = method ]; then + first_decl="$(find-struct-decl "$name" "$@")" || exit 40 + # prepare params for next lookup phase + set -- - # overwrite $@ to be single dash (-) + name="$method_name" + kind=fun + elif [[ $# = 1 && "$1" = '-' ]]; then + # avoid losing stdin provided to gen() due to redirection (<<<) + first_decl="$(cat -)" + fi + + # lookup the NAME + local body + body="$(find-$kind-decl "$name" "$@" <<< "$first_decl")" || exit 41 + awk -v define="$define" -v pattern="$pattern" -v "$operator"=1 ' + BEGIN { + # prepend "identifier boundary" to pattern, also append + # it, but only for patterns not ending with such already + # + # eg: "foo" -> "\bfoo\b" + # "struct foo *" -> "\bstruct foo *" + + # Note that mawk does not support "\b", so we have our + # own approximation, NI + NI = "[^A-Za-z0-9_]" # "Not an Indentifier" + + if (!match(pattern, NI "$")) + pattern = pattern "(" NI "|$)" + pattern = "(^|" NI ")" pattern + } + /./ { not_empty = 1 } + $0 ~ pattern { found = 1 } + END { + if (lacks && !found && not_empty || matches && found || absent && !found) + print "#define", define + } + ' <<< "$body" +} + +# tell if given flag is enabled in .config +# return 0 if given flag is enabled, 1 otherwise +# inputs: +# $1 - flag to check (whole word, without _MODULE suffix) +# env flag $CONFFILE +# +# there are two "config" formats supported, to ease up integrators lifes +# .config (without leading #~ prefix): +#~ # CONFIG_ACPI_EC_DEBUGFS is not set +#~ CONFIG_ACPI_AC=y +#~ CONFIG_ACPI_VIDEO=m +# and autoconf.h, which would be: +#~ #define CONFIG_ACPI_AC 1 +#~ #define CONFIG_ACPI_VIDEO_MODULE 1 +function config_has() { + grep -qE "^(#define )?$1((_MODULE)? 1|=m|=y)$" "$CONFFILE" +} diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_defs.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_defs.h new file mode 100644 index 0000000..f2528f6 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_defs.h @@ -0,0 +1,34 @@ + +#ifndef _KCOMPAT_DEFS_H_ +#define _KCOMPAT_DEFS_H_ + +#ifndef LINUX_VERSION_CODE +#include +#else +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif +#endif /* LINUX_VERSION_CODE */ + +#ifndef UTS_RELEASE +#include +#endif + +/* + * Include the definitions file for HAVE/NEED flags for the standard upstream + * kernels. + * + * Then, based on the distribution we detect, load the distribution specific + * definitions file that customizes the definitions for the target + * distribution. + */ +#include "kcompat_std_defs.h" + + +#ifdef RHEL_RELEASE_CODE +#include "kcompat_rhel_defs.h" +#endif + +#include "kcompat_generated_defs.h" + +#endif /* _KCOMPAT_DEFS_H_ */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_generated_defs.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_generated_defs.h new file mode 100644 index 0000000..67efc56 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_generated_defs.h @@ -0,0 +1,14 @@ +/* Autogenerated for KSRC=/lib/modules/5.10.0-136.12.oe2203sp1/source via kcompat-generator.sh */ +#ifndef _KCOMPAT_GENERATED_DEFS_H_ +#define _KCOMPAT_GENERATED_DEFS_H_ +#define HAVE_AUXILIARY_DEVICE_ID +#define HAVE_VIRTIO_PCI_MODERN +#define HAVE_VDPA_OPS_RESET +#define HAVE_VDPA_MGMTDEV_OPS +#define HAVE_VDPA_DEV_SET_CONFIG +#define HAVE_VDPA_OPS_DEVICE_FEAT +#define HAVE_VDPA_OPS_GET_CONFIG_SIZE +#define HAVE_VDPA_OPS_LOG_BASE +#define HAVE_STRUCT_PCI_DEV_PTM_ENABLED +#define NEED_PCIE_PTM_ENABLED +#endif /* _KCOMPAT_GENERATED_DEFS_H_ */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_rhel_defs.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_rhel_defs.h new file mode 100644 index 0000000..330abbb --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_rhel_defs.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _KCOMPAT_RHEL_DEFS_H_ +#define _KCOMPAT_RHEL_DEFS_H_ + +/* This is the RedHat Enterprise Linux distribution specific definitions file. + * It defines what features need backports for a given version of the RHEL + * kernel. + * + * It checks the RHEL_RELEASE_CODE and RHEL_RELEASE_VERSION macros to decide + * what support the target kernel has. + * + * It assumes that kcompat_std_defs.h has already been processed, and will + * #define or #undef any flags that have changed based on backports done by + * RHEL. + */ + +#if !RHEL_RELEASE_CODE +#error "RHEL_RELEASE_CODE is 0 or undefined" +#endif + +#ifndef RHEL_RELEASE_VERSION +#error "RHEL_RELEASE_VERSION is undefined" +#endif + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3)) +#define NEED_NETDEV_TXQ_BQL_PREFETCH +#else /* >= 7.3 */ +#endif /* 7.3 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,4)) +#define NEED_BUILD_BUG_ON +#else /* >= 7.4 */ +#define HAVE_RHEL7_EXTENDED_OFFLOAD_STATS +#define HAVE_INCLUDE_BITFIELD +#endif /* 7.4 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,5)) +#else /* >= 7.5 */ +#define HAVE_TCF_EXTS_TO_LIST +#define HAVE_FLOW_DISSECTOR_KEY_IP +#endif /* 7.5 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,6)) +#undef HAVE_XDP_BUFF_RXQ +#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS +#else /* >= 7.6 */ +#undef NEED_JIFFIES_64_TIME_IS_MACROS +#undef NEED_TC_CLS_CAN_OFFLOAD_AND_CHAIN0 +#undef NEED_TC_SETUP_QDISC_MQPRIO +#endif /* 7.6 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,7)) +#else /* >= 7.7 */ +#define HAVE_DEVLINK_PORT_ATTRS_SET_PORT_FLAVOUR +#define HAVE_ETHTOOL_NEW_100G_BITS +#undef NEED_NETDEV_TX_SENT_QUEUE +#undef NEED_IN_TASK +#define HAVE_FLOW_DISSECTOR_KEY_ENC_IP +#endif /* 7.7 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0)) +#else /* >= 8.0 */ +#undef HAVE_TCF_EXTS_TO_LIST +#undef HAVE_ETHTOOL_NEW_100G_BITS +#define HAVE_NDO_OFFLOAD_STATS +#undef HAVE_RHEL7_EXTENDED_OFFLOAD_STATS +#define HAVE_TCF_EXTS_FOR_EACH_ACTION +/* 7.7 undefs it due to a backport in 7.7+, but 8.0 needs it still */ +#define NEED_NETDEV_TX_SENT_QUEUE +#endif /* 8.0 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,1)) +#define NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE +#define NEED_FLOW_MATCH +#else /* >= 8.1 */ +#define HAVE_ETHTOOL_NEW_100G_BITS +#undef NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE +#undef NEED_FLOW_MATCH +#undef NEED_NETDEV_TX_SENT_QUEUE +#undef NEED_INDIRECT_CALL_WRAPPER_MACROS +#define HAVE_INDIRECT_CALL_WRAPPER_HEADER +#define HAVE_GRETAP_TYPE +#define HAVE_GENEVE_TYPE +#define HAVE_VXLAN_TYPE +#define HAVE_LINKMODE +#endif /* 8.1 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,2)) +#else /* >= 8.2 */ +#undef NEED_DEVLINK_FLASH_UPDATE_STATUS_NOTIFY +#undef NEED_SKB_FRAG_OFF +#undef NEED_SKB_FRAG_OFF_ADD +#undef NEED_FLOW_INDR_BLOCK_CB_REGISTER +#define HAVE_FLOW_INDR_BLOCK_LOCK +#define HAVE_DEVLINK_PORT_ATTRS_SET_SWITCH_ID +#define HAVE_NETDEV_SB_DEV +#endif /* 8.2 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,3)) +#else /* >= 8.3 */ +#undef NEED_CPU_LATENCY_QOS_RENAME +#undef NEED_DEVLINK_REGION_CREATE_OPS +#define HAVE_RT_IRQ_SCHED_FIX +#endif /* 8.3 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,4)) +#else /* >= 8.4 */ +#undef NEED_DEVLINK_PORT_ATTRS_SET_STRUCT +#undef NEED_DEVLINK_FLASH_UPDATE_TIMEOUT_NOTIFY +#undef HAVE_XDP_QUERY_PROG +#define HAVE_AF_XDP_ZC_SUPPORT +#define HAVE_MEM_TYPE_XSK_BUFF_POOL +#define HAVE_NDO_XSK_WAKEUP +#define XSK_UMEM_RETURNS_XDP_DESC +#undef NEED_XSK_UMEM_GET_RX_FRAME_SIZE +#define HAVE_ETHTOOL_COALESCE_PARAMS_SUPPORT +#define HAVE_PTP_FIND_PIN_UNLOCKED +#endif /* 8.4 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,5)) +#else /* >= 8.5 */ +#undef HAVE_NAPI_BUSY_LOOP +#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS +#undef NEED_XSK_BUFF_DMA_SYNC_FOR_CPU +#define NO_XDP_QUERY_XSK_UMEM +#undef NEED_XSK_BUFF_POOL_RENAME +#define HAVE_NETDEV_BPF_XSK_POOL +#define HAVE_AF_XDP_NETDEV_UMEM +#define HAVE_DEVLINK_OPS_CREATE_DEL +#endif /* 8.5 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,7)) +#else /* >= 8.7 */ +#undef NEED_DEVLINK_ALLOC_SETS_DEV +#define HAVE_DEVLINK_SET_STATE_3_PARAM +#endif /* 8.7 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9,0)) +#else /* >= 9.0 */ +#define HAVE_XDP_BUFF_RXQ +#endif /* 9.0 */ + +/*****************************************************************************/ +#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9,1)) +#else /* >= 9.1 */ +#undef HAVE_PASID_SUPPORT +#endif /* 9.1 */ + +/*****************************************************************************/ +#endif /* _KCOMPAT_RHEL_DEFS_H_ */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_std_defs.h b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_std_defs.h new file mode 100644 index 0000000..281766f --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/kcompat_std_defs.h @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _KCOMPAT_STD_DEFS_H_ +#define _KCOMPAT_STD_DEFS_H_ + +/* This file contains the definitions for what kernel features need backports + * for a given kernel. It targets only the standard stable kernel releases. + * It must check only LINUX_VERSION_CODE and assume the kernel is a standard + * release, and not a custom distribution. + * + * It must define HAVE_ and NEED_ for features. It must not + * implement any backports, instead leaving the implementation to the + * kcompat_impl.h header. + * + * If a feature can be easily implemented as a replacement macro or fully + * backported, use a NEED_ to indicate that the feature needs + * a backport. (If NEED_ is undefined, then no backport for that feature + * is needed). + * + * If a feature cannot be easily implemented in kcompat directly, but + * requires drivers to make specific changes such as stripping out an entire + * feature or modifying a function pointer prototype, use a HAVE_. + */ + +#ifndef LINUX_VERSION_CODE +#error "LINUX_VERSION_CODE is undefined" +#endif + +#ifndef KERNEL_VERSION +#error "KERNEL_VERSION is undefined" +#endif + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)) +#else /* >= 4,8,0 */ +#define HAVE_TCF_EXTS_TO_LIST +#define HAVE_PCI_ALLOC_IRQ +#endif /* 4,8,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)) +#define NEED_JIFFIES_64_TIME_IS_MACROS +#else /* >= 4,9,0 */ +#define HAVE_KTHREAD_DELAYED_API +#define HAVE_NDO_OFFLOAD_STATS +#define HAVE_INCLUDE_BITFIELD +#endif /* 4,9,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,62)) +#define NEED_IN_TASK +#else /* >= 4,9,62 */ +#endif /* 4,9,62 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0)) +#else /* >= 4,12,0 */ +#define HAVE_NAPI_BUSY_LOOP +#endif /* 4,12,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0)) +#else /* >= 4,13,0 */ +#define HAVE_FLOW_DISSECTOR_KEY_IP +#endif /* 4,13,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) +#define NEED_TC_SETUP_QDISC_MQPRIO +#define NEED_NETDEV_XDP_STRUCT +#else /* >= 4,15,0 */ +#define HAVE_TC_CB_AND_SETUP_QDISC_MQPRIO +#define HAVE_NDO_BPF +#endif /* 4,15,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0)) +#define NEED_TC_CLS_CAN_OFFLOAD_AND_CHAIN0 +#else /* >= 4,16,0 */ +#define HAVE_XDP_BUFF_RXQ +#define HAVE_XDP_RXQ_INFO_REG_3_PARAMS +#endif /* 4,16,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,17,0)) +#define NEED_CONVERT_ART_NS_TO_TSC +#else /* >= 4,17,0 */ +#endif /* 4,17,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0)) +#define NEED_MACVLAN_ACCEL_PRIV +#define NEED_MACVLAN_RELEASE_L2FW_OFFLOAD +#define NEED_MACVLAN_SUPPORTS_DEST_FILTER +#else /* >= 4,18,0 */ +#define HAVE_DEVLINK_PORT_ATTRS_SET_PORT_FLAVOUR +#endif /* 4,18,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)) +#define NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE +#else /* >= 4,19,0 */ +#undef HAVE_TCF_EXTS_TO_LIST +#define HAVE_TCF_EXTS_FOR_EACH_ACTION +#define HAVE_TC_ETF_QOPT_OFFLOAD +#define HAVE_FLOW_DISSECTOR_KEY_ENC_IP +#endif /* 4,19,0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)) +#define NEED_NETDEV_TX_SENT_QUEUE +#else /* >= 4.20.0 */ +#define HAVE_VXLAN_TYPE +#define HAVE_LINKMODE +#endif /* 4.20.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)) +#define NEED_INDIRECT_CALL_WRAPPER_MACROS +#else /* >= 5.0.0 */ +#define HAVE_GRETAP_TYPE +#define HAVE_GENEVE_TYPE +#define HAVE_INDIRECT_CALL_WRAPPER_HEADER +#endif /* 5.0.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)) +#define NEED_FLOW_MATCH +#else /* >= 5.1.0 */ +#define HAVE_ETHTOOL_200G_BITS +#define HAVE_ETHTOOL_NEW_100G_BITS +#endif /* 5.1.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)) +#else /* >= 5.2.0 */ +#define HAVE_DEVLINK_PORT_ATTRS_SET_SWITCH_ID +#endif /* 5.2.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0)) +#define NEED_DEVLINK_FLASH_UPDATE_STATUS_NOTIFY +#else /* >= 5.3.0 */ +#endif /* 5.3.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)) +#define NEED_SKB_FRAG_OFF_ADD +#define NEED_SKB_FRAG_OFF +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,14,241) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) +#undef NEED_SKB_FRAG_OFF +#endif /* > 4.14.241 && < 4.15.0 */ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,19,200) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)) +#undef NEED_SKB_FRAG_OFF +#endif /* > 4.19.200 && < 4.20.0 */ + +#define NEED_FLOW_INDR_BLOCK_CB_REGISTER +#else /* >= 5.4.0 */ +#define HAVE_FLOW_INDR_BLOCK_LOCK +#define HAVE_XSK_UNALIGNED_CHUNK_PLACEMENT +#endif /* 5.4.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0)) +#define NEED_DEVLINK_REGION_CREATE_OPS +#define NEED_CPU_LATENCY_QOS_RENAME +#else /* >= 5.7.0 */ +#define HAVE_PTP_FIND_PIN_UNLOCKED +#endif /* 5.7.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)) +#define NEED_XSK_UMEM_GET_RX_FRAME_SIZE +#else /* >= 5.8.0 */ +#undef HAVE_XSK_UNALIGNED_CHUNK_PLACEMENT +#define HAVE_RT_IRQ_SCHED_FIX +#endif /* 5.8.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0)) +#define NEED_DEVLINK_PORT_ATTRS_SET_STRUCT +#define HAVE_XDP_QUERY_PROG +#define NEED_INDIRECT_CALL_3_AND_4 +#else /* >= 5.9.0 */ +#define HAVE_TASKLET_SETUP +#endif /* 5.9.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)) +#define NEED_DEVLINK_FLASH_UPDATE_TIMEOUT_NOTIFY +#define NEED_XSK_BUFF_DMA_SYNC_FOR_CPU +#define NEED_XSK_BUFF_POOL_RENAME +#else /* >= 5.10.0 */ +#define HAVE_UDP_TUNNEL_NIC_SHARED +#define HAVE_NETDEV_BPF_XSK_POOL +#endif /* 5.10.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0)) +#else /* >= 5.11.0 */ +#define HAVE_XSK_BATCHED_DESCRIPTOR_INTERFACES +#define HAVE_PASID_SUPPORT +#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS +#define HAVE_XSK_TX_PEEK_RELEASE_DESC_BATCH_3_PARAMS +#endif /* 5.11.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)) +#define NEED_EXPORT_INDIRECT_CALLABLE +#else /* >= 5.12.0 */ +#define HAVE_DEVLINK_OPS_CREATE_DEL +#endif /* 5.12.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0)) +/* HAVE_KOBJ_IN_MDEV_PARENT_OPS_CREATE + * + * create api changed as part of the commit c2ef2f50ad0c( vfio/mdev: Remove + * kobj from mdev_parent_ops->create()) + * + * if flag is defined use the old API else new API + */ +#define HAVE_KOBJ_IN_MDEV_PARENT_OPS_CREATE +#define HAVE_DEV_IN_MDEV_API +#else /* >= 5.13.0 */ +#define HAVE_XPS_MAP_TYPE +#endif /* 5.13.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,14,0)) +#else /* >= 5.14.0 */ +#define HAVE_TTY_WRITE_ROOM_UINT +#endif /* 5.14.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0)) +#define NEED_DEVLINK_ALLOC_SETS_DEV +#else /* >= 5.15.0 */ +#define HAVE_DEVICE_IN_MDEV_PARENT_OPS +#define NEED_PCI_IOV_VF_ID +#define HAVE_DEVLINK_SET_STATE_3_PARAM +#endif /* 5.15.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,16,0)) +#else /* >= 5.16.0 */ +#undef HAVE_PASID_SUPPORT +#define HAVE_XSK_BATCHED_RX_ALLOC +#endif /* 5.16.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)) +#else /* >=5.18.0*/ +#undef NEED_PCI_IOV_VF_ID +#define HAVE_GTP_SUPPORT +#undef HAVE_XSK_TX_PEEK_RELEASE_DESC_BATCH_3_PARAMS +#endif /* 5.18.0 */ + +/*****************************************************************************/ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0)) +#else /* >=6.1.0 */ +#define HAVE_FLOW_DISSECTOR_KEY_L2TPV3 +#define HAVE_TTY_TERMIOS_CONST_STRUCT +#endif /* 6.1.0 */ + +#endif /* _KCOMPAT_STD_DEFS_H_ */ diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/check_aux_bus b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/check_aux_bus new file mode 100755 index 0000000..9b14ea2 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/check_aux_bus @@ -0,0 +1,235 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (C) 2021 - 2023 Intel Corporation +# +# Helper script to detect if auxiliary bus support. This script +# +# returns 0 when: +# - CONFIG_AUXILIARY_BUS=y +# - auxiliary_bus.h was found +# +# Returning 0 means the driver build/install doesn't need OOT +# auxiliary bus +# +# returns 1 when: +# - CONFIG_AUXILIARY_BUS=n (or any value that's not "=y") +# - kernel configuration was incorrect +# - kernel configuration file was not found +# +# Returning 1 means something bad/unexpected happened and the +# driver build/install should treat this as a failure +# +# returns 2 when: +# - When OOT auxiliary is needed regardless if a previous OOT +# auxiliary was already. This is done because the driver +# always needs to build against auxiliary.o to avoid +# warnings/errors since auxiliary.o is built-in to the +# driver's makefile +# +# Returning 2 means the driver build/install needs OOT auxiliary +# bus +# +# returns 3 when: +# - A file and/or directory does not exist +# +# Returning 3 means something bad/unexpected happened and the +# driver build/install should treat this as a failure +# +# Note: when ksrc and build-kernel are both specified on the +# command line and build-kernel is not in the same location +# as ksrc, then ksrc takes precedence. For example: +# ./check_aux_bus --ksrc=/lib/modules/5.8.0/source --build-kernel=5.10.0 +# +# In this case the kernel config file won't be searched for and +# the script will only check to see if the in-tree/OOT auxiliary_bus.h +# file exists at ksrc. + +msg() +{ + if [ $verbose == 1 ]; then + echo -e $1 + fi +} + +exit_builtin_auxiliary_enabled() { exit 0; } +exit_kconfig_invalid() { exit 1; } +exit_need_oot_auxiliary() { exit 2; } +exit_not_found_failure() { exit 3; } + +find_aux_bus_inc() +{ + aux_bus_inc=$(find -L ${ksrc} -name "auxiliary_bus.h") + msg "auxiliary_bus.h location: ${aux_bus_inc}" +} + +LINUX_INCLUDE_DIR="include/linux" + +set_build_kernel() +{ + build_kernel=$(uname -r) +} + +find_kernel_source() +{ + # All the default places to look for kernel source + test_dirs=(/lib/modules/${build_kernel}/source \ + /lib/modules/${build_kernel}/build \ + /usr/src/linux-${build_kernel} \ + /usr/src/linux-$(echo ${build_kernel} | sed 's/-.*//') \ + /usr/src/kernel-headers-${build_kernel} \ + /usr/src/kernel-source-${build_kernel} \ + /usr/src/linux-$(echo ${build_kernel} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ + /usr/src/linux \ + /usr/src/kernels/${build_kernel} \ + /usr/src/kernels) + + # Save the first valid kernel source path + for dir in "${test_dirs[@]}"; do + if [ -d ${dir}/${LINUX_INCLUDE_DIR} ]; then + ksrc=${dir} + break + fi + done + + if [ -z ${ksrc} ]; then + echo "*** Kernel header files not in any of the expected locations." + echo "*** Install the appropriate kernel development package, e.g." + echo "kernel-devel, for building kernel modules and try again" + exit_not_found_failure + fi +} + +find_config_file() +{ + # only search for kernel .config file if build_kernel is pointing + # in the same tree as ksrc (see not about ksrc and build_kernel + # both set in the scripts header comment) + if [[ "$ksrc" != *"/lib/modules/${build_kernel}"* ]]; then + msg "ksrc=$ksrc not the same as location generated from build_kernel=\"/lib/modules/${build_kernel}\", not searching for kernel .config file" + else + kbuild_dir="/lib/modules/${build_kernel}/build" + + file_locations=(${kbuild_dir}/include/generated/autoconf.h \ + ${kbuild_dir}/include/linux/autoconf.h \ + /boot/bmlinux.autoconf.h) + + for file in "${file_locations[@]}"; do + if [ -f ${file} ]; then + kconfig=${file} + break + fi + done + + if [ -z ${kconfig} ]; then + msg "Kernel config file not found at any of the expected locations." + fi + fi +} + +get_config_auxiliary_bus() +{ + # CONFIG_AUXILIARY_BUS=0 corresponds to CONFIG_AUXILIARY_BUS=n + # CONFIG_AUXILIARY_BUS=1 corresponds to CONFIG_AUXILIARY_BUS=y + # CONFIG_AUXILIARY_BUS= corresponds to CONFIG_AUXILIARY_BUS not available in the kernel + CONFIG_AUXILIARY_BUS=$(grep CONFIG_AUXILIARY_BUS ${kconfig} | awk -F" " '{print $3}') + msg "CONFIG_AUXILIARY_BUS=${CONFIG_AUXILIARY_BUS}" +} + +ksrc="" +build_kernel="" +verbose=0 + +usage() +{ + script=$(basename $0) + echo -e "usage:" + echo -e "\t$script [options]" + echo -e "\n\toptions:" + echo -e "\t -v, --verbose" + echo -e "\t -h, --help" + echo -e "\n\t run script against specified kernel source" + echo -e "\t -k, --ksrc \"/lib/modules/5.12.0/source\"" + echo -e "\n\t run script with kernel version (kernel version used to find kernel source programatically)" + echo -e "\t -b, --build-kernel \"5.8.0\"" +} + +options=$(getopt -o "k:b:vh" --long ksrc:,build-kernel:,verbose,help -- "$@") +eval set -- "$options" +while :; do + case $1 in + -k|--ksrc) ksrc=$2; shift;; + -b|--build-kernel) build_kernel=$2; shift;; + -v|--verbose) verbose=1 ;; + -h|--help) usage && exit 0;; + --) shift; break;; + esac + shift +done + +if [ $verbose == 1 ]; then + set -x +fi + +# both build_kernel and ksrc are unset so programatically determine build_kernel +if [ -z $build_kernel ] && [ -z $ksrc ]; then + set_build_kernel +fi + +# only programatically search for kernel source if ksrc not set on command line +if [ -z $ksrc ]; then + find_kernel_source +fi + +find_config_file + +if [ ! -z $kconfig ]; then + # if we found the kernel .config file then exit the script based on various + # conditions that depend on the CONFIG_AUXILIARY_BUS string being found + get_config_auxiliary_bus + + if [ -z "$CONFIG_AUXILIARY_BUS" ]; then + msg "CONFIG_AUXILIARY_BUS not found in ${kconfig}." + # CONFIG_AUXILIARY_BUS string was not found, so OOT auxiliary is needed + exit_need_oot_auxiliary + elif [ "$CONFIG_AUXILIARY_BUS" = "1" ]; then + msg "CONFIG_AUXILIARY_BUS=y in ${kconfig}." + # CONFIG_AUXILIARY_BUS=y, so OOT auxiliary is not needed + exit_builtin_auxiliary_enabled + else + msg "" + msg "kernel $build_kernel supports auxiliary bus, but CONFIG_AUXILIARY_BUS" + msg "is not set in ${kconfig}. Rebuild your kernel with" + msg "CONFIG_AUXILIARY_BUS=y" + msg "" + # CONFIG_AUXILIARY_BUS is not "=y", but the string was found, so report + # the failure so it can be used to fail build/install + exit_kconfig_invalid + fi +else + if [ ! -d ${ksrc}/${LINUX_INCLUDE_DIR} ] && [ ! -d ${ksrc}/source/${LINUX_INCLUDE_DIR} ]; then + echo "${ksrc}/${LINUX_INCLUDE_DIR} and ${ksrc}/source/${LINUX_INCLUDE_DIR} do not exist" + exit_not_found_failure + fi + + # We didn't find a kernel .config file, so check to see if auxiliary_bus.h + # is found in the kernel source include directory + find_aux_bus_inc + + if [ -f "$aux_bus_inc" ]; then + # AUXILIARY_MODULE_PREFIX is defined only in out-of-tree auxiliary bus + if [ $(grep -c AUXILIARY_MODULE_PREFIX $aux_bus_inc) -eq 0 ]; then + msg "in-tree auxiliary_bus.h found at ${ksrc}/${LINUX_INCLUDE_DIR}" + # If auxiliary_bus.h is included at ${ksrc} and it isn't our OOT version, then + # don't build OOT auxiliary as part of the driver makefile + exit_builtin_auxiliary_enabled + else + msg "OOT auxiliary_bus.h found at ${ksrc}/${LINUX_INCLUDE_DIR}" + # If auxiliary bus is included at ${ksrc} and it is our OOT version, then + # build OOT auxiliary as part of the driver makefile + exit_need_oot_auxiliary + fi + else + msg "auxiliary_bus.h not found at ${ksrc}/${LINUX_INCLUDE_DIR}" + exit_need_oot_auxiliary + fi +fi diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_arfs b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_arfs new file mode 100755 index 0000000..c7f7a07 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_arfs @@ -0,0 +1,86 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (C) 2020 - 2023 Intel Corporation +# +# Attempt a basic setup of adaptive receive flow steering +# also known as aRFS. aRFS will automatically at runtime +# use ntuple rules to direct receive traffic to the same +# rx queue (matched by queue number) as was used for the +# application that was transmitting. Most useful for +# TCP workloads and latency sensitive TCP connections. +# +# typical usage is (as root): +# set_arfs -s flow_entries eth1 +# +# to get help: +# set_arfs + +usage() +{ + echo + echo "Usage: $0 [-s flow_entries] ..." + echo " Options: " + echo " -s number of socket flow entries" + echo " Examples:" + echo " $0 eth1 eth2 # eth1 and eth2 use default flow_entries" + echo " $0 -s flow_entries eth1 # eth1 use specified flow_entries" + echo + exit 1 +} + +# offer some help +if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + usage + exit 1 +fi + +# if -s and a value specified, then use them. +if [ "$1" == "-s" ]; then + FLOW_ENTRIES=$2 + shift + shift +fi + +# append the interfaces listed to the string with spaces +while [ "$#" -ne "0" ] ; do + IFACES+=" $1" + shift +done + +# for now the user must specify interfaces +if [ -z "$IFACES" ]; then + usage + exit 1 +fi + +# provide a default flow num value, typically 2048 per queue +# is useful, but if there are many queues then maybe a smaller +# value per-queue is good enough. +if [ -z "$FLOW_ENTRIES" ]; then + FLOW_ENTRIES=32768 +fi + +set_arfs() +{ + echo $FLOW_ENTRIES > /proc/sys/net/core/rps_sock_flow_entries + echo -n "done: " + grep -H . /proc/sys/net/core/rps_sock_flow_entries + for IFACE in $IFACES; do + QDIR="/sys/class/net/$IFACE/queues" + QUEUES=`ls -1 -d $QDIR/rx-*` + QUEUES_COUNT=`ls -1 -d $QDIR/rx-* | wc -l` + sockTrack=$((FLOW_ENTRIES / QUEUES_COUNT)) + if [ -z `ls $QDIR/rx-0/rps_flow_cnt` ]; then + echo "ERROR: aRFS is not supported on $IFACE" + exit 2 + fi + n=0 + for i in $QUEUES; do + echo $sockTrack > $i/rps_flow_cnt + echo -n "Queue $((n++)) done: " + grep -H . $i/rps_flow_cnt + done + done +} + +set_arfs diff --git a/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_irq_affinity b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_irq_affinity new file mode 100755 index 0000000..8f33d81 --- /dev/null +++ b/LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_irq_affinity @@ -0,0 +1,336 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (C) 2015 - 2023 Intel Corporation +# +# Affinitize interrupts to cores +# +# typical usage is (as root): +# set_irq_affinity -x local eth1 +# set_irq_affinity -s eth1 +# +# to get help: +# set_irq_affinity + +usage() +{ + echo + echo "Usage: option -s to show current settings only" + echo "Usage: $0 [-x|-X] [all|local|remote []|one |custom|] ..." + echo " Options: " + echo " -s Shows current affinity settings" + echo " -x Configure XPS as well as smp_affinity" + echo " -X Disable XPS but set smp_affinity" + echo " [all] is the default value" + echo " [remote []] can be followed by a specific node number" + echo " Examples:" + echo " $0 -s eth1 # Show settings on eth1" + + echo " $0 all eth1 eth2 # eth1 and eth2 to all cores" + echo " $0 one 2 eth1 # eth1 to core 2 only" + echo " $0 local eth1 # eth1 to local cores only" + echo " $0 remote eth1 # eth1 to remote cores only" + echo " $0 custom eth1 # prompt for eth1 interface" + echo " $0 0-7,16-23 eth0 # eth1 to cores 0-7 and 16-23" + echo + exit 1 +} + +usageX() +{ + echo "options -x and -X cannot both be specified, pick one" + exit 1 +} + +if [ "$1" == "-x" ]; then + XPS_ENA=1 + shift +fi + +if [ "$1" == "-s" ]; then + SHOW=1 + echo Show affinity settings + shift +fi + +if [ "$1" == "-X" ]; then + if [ -n "$XPS_ENA" ]; then + usageX + fi + XPS_DIS=2 + shift +fi + +if [ "$1" == -x ]; then + usageX +fi + +if [ -n "$XPS_ENA" ] && [ -n "$XPS_DIS" ]; then + usageX +fi + +if [ -z "$XPS_ENA" ]; then + XPS_ENA=$XPS_DIS +fi + +SED=`which sed` +if [[ ! -x $SED ]]; then + echo " $0: ERROR: sed not found in path, this script requires sed" + exit 1 +fi + +num='^[0-9]+$' + +# search helpers +NOZEROCOMMA="s/^[0,]*//" +# Vars +AFF=$1 +shift + +case "$AFF" in + remote) [[ $1 =~ $num ]] && rnode=$1 && shift ;; + one) [[ $1 =~ $num ]] && cnt=$1 && shift ;; + all) ;; + local) ;; + custom) ;; + [0-9]*) ;; + -h|--help) usage ;; + "") usage ;; + *) IFACES=$AFF && AFF=all ;; # Backwards compat mode +esac + +# append the interfaces listed to the string with spaces +while [ "$#" -ne "0" ] ; do + IFACES+=" $1" + shift +done + +# for now the user must specify interfaces +if [ -z "$IFACES" ]; then + usage + exit 2 +fi + +notfound() +{ + echo $MYIFACE: not found + exit 15 +} + +# check the interfaces exist +for MYIFACE in $IFACES; do + grep -q $MYIFACE /proc/net/dev || notfound +done + +# support functions + +build_mask() +{ + VEC=$core + if [ $VEC -ge 32 ] + then + MASK_FILL="" + MASK_ZERO="00000000" + let "IDX = $VEC / 32" + for ((i=1; i<=$IDX;i++)) + do + MASK_FILL="${MASK_FILL},${MASK_ZERO}" + done + + let "VEC -= 32 * $IDX" + MASK_TMP=$((1<<$VEC)) + MASK=$(printf "%X%s" $MASK_TMP $MASK_FILL) + else + MASK_TMP=$((1<<$VEC)) + MASK=$(printf "%X" $MASK_TMP) + fi +} + +show_affinity() +{ + # returns the MASK variable + build_mask + + SMP_I=`sed -E "${NOZEROCOMMA}" /proc/irq/$IRQ/smp_affinity` + HINT=`sed -E "${NOZEROCOMMA}" /proc/irq/$IRQ/affinity_hint` + printf "ACTUAL %s %d %s <- /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $SMP_I + printf "HINT %s %d %s <- /proc/irq/$IRQ/affinity_hint\n" $IFACE $core $HINT + IRQ_CHECK=`grep '[-,]' /proc/irq/$IRQ/smp_affinity_list` + if [ ! -z $IRQ_CHECK ]; then + printf " WARNING -- SMP_AFFINITY is assigned to multiple cores $IRQ_CHECK\n" + fi + if [ "$SMP_I" != "$HINT" ]; then + printf " WARNING -- SMP_AFFINITY VALUE does not match AFFINITY_HINT \n" + fi + printf "NODE %s %d %s <- /proc/irq/$IRQ/node\n" $IFACE $core `cat /proc/irq/$IRQ/node` + printf "LIST %s %d [%s] <- /proc/irq/$IRQ/smp_affinity_list\n" $IFACE $core `cat /proc/irq/$IRQ/smp_affinity_list` + printf "XPS %s %d %s <- /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus` $IFACE $((n-1)) + if [ -z `ls /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_rxqs` ]; then + echo "WARNING: xps rxqs not supported on $IFACE" + else + printf "XPSRXQs %s %d %s <- /sys/class/net/%s/queues/tx-%d/xps_rxqs\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_rxqs` $IFACE $((n-1)) + fi + printf "TX_MAX %s %d %s <- /sys/class/net/%s/queues/tx-%d/tx_maxrate\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/tx_maxrate` $IFACE $((n-1)) + printf "BQLIMIT %s %d %s <- /sys/class/net/%s/queues/tx-%d/byte_queue_limits/limit\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/byte_queue_limits/limit` $IFACE $((n-1)) + printf "BQL_MAX %s %d %s <- /sys/class/net/%s/queues/tx-%d/byte_queue_limits/limit_max\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/byte_queue_limits/limit_max` $IFACE $((n-1)) + printf "BQL_MIN %s %d %s <- /sys/class/net/%s/queues/tx-%d/byte_queue_limits/limit_min\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/byte_queue_limits/limit_min` $IFACE $((n-1)) + if [ -z `ls /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_flow_cnt` ]; then + echo "WARNING: aRFS is not supported on $IFACE" + else + printf "RPSFCNT %s %d %s <- /sys/class/net/%s/queues/rx-%d/rps_flow_cnt\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_flow_cnt` $IFACE $((n-1)) + fi + if [ -z `ls /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_cpus` ]; then + echo "WARNING: rps_cpus is not available on $IFACE" + else + printf "RPSCPU %s %d %s <- /sys/class/net/%s/queues/rx-%d/rps_cpus\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_cpus` $IFACE $((n-1)) + fi + echo +} + +set_affinity() +{ + # returns the MASK variable + build_mask + + printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity + printf "%s %d %s -> /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $MASK + SMP_I=`sed -E "${NOZEROCOMMA}" /proc/irq/$IRQ/smp_affinity` + if [ "$SMP_I" != "$MASK" ]; then + printf " ACTUAL\t%s %d %s <- /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $SMP_I + printf " WARNING -- SMP_AFFINITY setting failed\n" + fi + case "$XPS_ENA" in + 1) + printf "%s %d %s -> /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core $MASK $IFACE $((n-1)) + printf "%s" $MASK > /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus + ;; + 2) + MASK=0 + printf "%s %d %s -> /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core $MASK $IFACE $((n-1)) + printf "%s" $MASK > /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus + ;; + *) + esac +} + +# Allow usage of , or - +# +parse_range () { + RANGE=${@//,/ } + RANGE=${RANGE//-/..} + LIST="" + for r in $RANGE; do + # eval lets us use vars in {#..#} range + [[ $r =~ '..' ]] && r="$(eval echo {$r})" + LIST+=" $r" + done + echo $LIST +} + +# Affinitize interrupts +# +doaff() +{ + CORES=$(parse_range $CORES) + ncores=$(echo $CORES | wc -w) + n=1 + + # this script only supports interrupt vectors in pairs, + # modification would be required to support a single Tx or Rx queue + # per interrupt vector + + queues="${IFACE}-.*TxRx" + + irqs=$(grep "$queues" /proc/interrupts | cut -f1 -d:) + [ -z "$irqs" ] && irqs=$(grep $IFACE /proc/interrupts | cut -f1 -d:) + [ -z "$irqs" ] && irqs=$(for i in `ls -1 /sys/class/net/${IFACE}/device/msi_irqs | sort -n` ;do grep -w $i: /proc/interrupts | egrep -v 'fdir|async|misc|ctrl' | cut -f 1 -d :; done) + [ -z "$irqs" ] && echo "Error: Could not find interrupts for $IFACE" + + if [ "$SHOW" == "1" ] ; then + echo "TYPE IFACE CORE MASK -> FILE" + echo "============================" + else + echo "IFACE CORE MASK -> FILE" + echo "=======================" + fi + + for IRQ in $irqs; do + [ "$n" -gt "$ncores" ] && n=1 + j=1 + # much faster than calling cut for each + for i in $CORES; do + [ $((j++)) -ge $n ] && break + done + core=$i + if [ "$SHOW" == "1" ] ; then + show_affinity + else + set_affinity + fi + ((n++)) + done +} + +# these next 2 lines would allow script to auto-determine interfaces +#[ -z "$IFACES" ] && IFACES=$(ls /sys/class/net) +#[ -z "$IFACES" ] && echo "Error: No interfaces up" && exit 1 + +# echo IFACES is $IFACES + +CORES=$( +# +# to get help: +# set_xps_rxqs + +iface=$1 + +if [ -z "$iface" ]; then + echo "Usage: $0 " + exit 1 +fi + +CHECK () { + "$@" + if [ $? -ne 0 ]; then + echo "Error in command ${1}, execution aborted, but some changes may have already been made!" >&2 + exit 1 + fi +} + +CPUMASK () { + cpu=$1 + if [ $cpu -ge 32 ]; then + mask_fill="" + mask_zero="00000000" + let "pow = $cpu / 32" + for ((i=1; i<=pow; i++)); do + mask_fill="${mask_fill},${mask_zero}" + done + + let "cpu -= 32 * $pow" + mask_tmp=$((1 << cpu)) + mask=$(printf "%X%s" $mask_tmp $mask_fill) + else + mask_tmp=$((1 << cpu)) + mask=$(printf "%X" $mask_tmp) + fi + echo $mask +} + +for i in /sys/class/net/$iface/queues/tx-*/xps_rxqs; do + j=$(echo $i | cut -d'/' -f7 | cut -d'-' -f2) + mask=$(CPUMASK $j) + echo ${mask} > $i + CHECK echo ${mask} > $i +done diff --git a/LingYaoSNIC/README.md b/LingYaoSNIC/README.md new file mode 100644 index 0000000..11c27fb --- /dev/null +++ b/LingYaoSNIC/README.md @@ -0,0 +1 @@ +中移自研“灵耀”智能网卡驱动固件 \ No newline at end of file diff --git a/LingYaoSNIC/ZTE/README.md b/LingYaoSNIC/ZTE/README.md new file mode 100644 index 0000000..762f8a3 --- /dev/null +++ b/LingYaoSNIC/ZTE/README.md @@ -0,0 +1 @@ +适配对接中移网络云中兴虚拟层版本 \ No newline at end of file diff --git a/LingYaoSNIC/ZTE/firmware/imu_flash_snic_cqaca_1.7.6.img b/LingYaoSNIC/ZTE/firmware/imu_flash_snic_cqaca_1.7.6.img new file mode 100644 index 0000000..752f4c2 Binary files /dev/null and b/LingYaoSNIC/ZTE/firmware/imu_flash_snic_cqaca_1.7.6.img differ diff --git a/LingYaoSNIC/ZTE/firmware/md5.txt b/LingYaoSNIC/ZTE/firmware/md5.txt new file mode 100644 index 0000000..9b9a9f0 --- /dev/null +++ b/LingYaoSNIC/ZTE/firmware/md5.txt @@ -0,0 +1,3 @@ +890073cae9c0fae3edf42938e3dfd010 imu_flash_snic_cqaca.img +3c1d9cbab63b4aae0f406c706a307681 scp_flash_cqaca_n2_2.0g_cmn_1.65g.img + diff --git a/LingYaoSNIC/ZTE/firmware/scp_flash_cqaca_n2_2.0g_cmn_1.65g_1.7.6.img b/LingYaoSNIC/ZTE/firmware/scp_flash_cqaca_n2_2.0g_cmn_1.65g_1.7.6.img new file mode 100644 index 0000000..43417f3 Binary files /dev/null and b/LingYaoSNIC/ZTE/firmware/scp_flash_cqaca_n2_2.0g_cmn_1.65g_1.7.6.img differ diff --git a/LingYaoSNIC/ZTE/kernel/crete-kernel-modules-1.9.7-1.an8.x86_64.rpm b/LingYaoSNIC/ZTE/kernel/crete-kernel-modules-1.9.7-1.an8.x86_64.rpm new file mode 100644 index 0000000..efbe68a Binary files /dev/null and b/LingYaoSNIC/ZTE/kernel/crete-kernel-modules-1.9.7-1.an8.x86_64.rpm differ diff --git a/LingYaoSNIC/ZTE/kernel/md5.txt b/LingYaoSNIC/ZTE/kernel/md5.txt new file mode 100644 index 0000000..e733327 --- /dev/null +++ b/LingYaoSNIC/ZTE/kernel/md5.txt @@ -0,0 +1 @@ +e745351e037e0267cb90c5378dc573c4 crete-kernel-modules-1.9.7-1.an8.x86_64.rpm