diff --git a/0095-Upstream-hinic3-DPDK-driver.patch b/0095-Upstream-hinic3-DPDK-driver.patch new file mode 100644 index 0000000000000000000000000000000000000000..b11b34377e8b04486995c9bd49da0b9d7216ff85 --- /dev/null +++ b/0095-Upstream-hinic3-DPDK-driver.patch @@ -0,0 +1,48172 @@ +From be4735fe620dfa94e84d2bf87eeb2f6d83b4038b Mon Sep 17 00:00:00 2001 +From: kaiyuan001 +Date: Mon, 7 Jul 2025 19:54:22 +0800 +Subject: [PATCH] Upstream-hinic3-DPDK-driver + +--- + .../hinic3/cfg/ovs_dpu_virt/agent_config.ini | 49 + + drivers/net/hinic3/include/dpak_cfg.h | 95 + + drivers/net/hinic3/meson.build | 180 ++ + .../hinic3/scripts/dpak_ovs_completion_ovs.sh | 716 ++++++++ + .../src/common/hinic3_cfg/ovs_dpu_virt.c | 37 + + .../hinic3/src/common/hinic3_ds/hinic3_ds.c | 143 ++ + .../hinic3/src/common/hinic3_ds/hinic3_ds.h | 37 + + .../src/common/hinic3_hash/hinic3_hash.c | 94 + + .../src/common/hinic3_hash/hinic3_hash.h | 23 + + .../src/common/hinic3_hmap/hinic3_hmap.c | 186 ++ + .../src/common/hinic3_hmap/hinic3_hmap.h | 58 + + .../hinic3/src/common/hinic3_log/hinic3_log.c | 528 ++++++ + .../hinic3/src/common/hinic3_log/hinic3_log.h | 112 ++ + .../common/hinic3_mpool_mgmt/hinic3_mpool.c | 371 ++++ + .../common/hinic3_mpool_mgmt/hinic3_mpool.h | 52 + + .../src/common/hinic3_mutex/hinic3_mutex.c | 210 +++ + .../common/hinic3_packets/hinic3_packets.c | 20 + + .../common/hinic3_packets/hinic3_packets.h | 18 + + .../src/common/hinic3_smap/hinic3_shash.c | 156 ++ + .../src/common/hinic3_smap/hinic3_shash.h | 30 + + .../src/common/hinic3_smap/hinic3_smap.c | 159 ++ + .../src/common/hinic3_smap/hinic3_smap.h | 30 + + .../hinic3_string_util/hinic3_string_format.c | 404 +++++ + .../hinic3_string_util/hinic3_string_format.h | 25 + + .../hinic3_string_util/hinic3_string_util.c | 71 + + .../hinic3_string_util/hinic3_string_util.h | 19 + + .../src/common/hinic3_thread/hinic3_thread.c | 112 ++ + .../src/common/hinic3_thread/hinic3_thread.h | 28 + + .../hinic3_check_thread_health_state.c | 174 ++ + .../hinic3_check_thread_health_state.h | 42 + + .../common/hinic3_utils/hinic3_dpdk_adapter.h | 285 +++ + .../src/common/hinic3_utils/hinic3_drv.h | 120 ++ + .../common/hinic3_utils/hinic3_error_stats.c | 187 ++ + .../common/hinic3_utils/hinic3_error_stats.h | 185 ++ + .../common/hinic3_utils/hinic3_eth_packets.h | 114 ++ + .../common/hinic3_utils/hinic3_file_util.c | 293 ++++ + .../common/hinic3_utils/hinic3_file_util.h | 19 + + .../hinic3_utils/hinic3_flow_agent_enum.h | 93 + + .../hinic3_utils/hinic3_flow_agent_public.h | 336 ++++ + .../hinic3_utils/hinic3_hugepage_meminfo.c | 472 +++++ + .../hinic3_utils/hinic3_hugepage_meminfo.h | 75 + + .../src/common/hinic3_utils/hinic3_list.h | 72 + + .../src/common/hinic3_utils/hinic3_map.h | 44 + + .../src/common/hinic3_utils/hinic3_meminfo.c | 107 ++ + .../src/common/hinic3_utils/hinic3_meminfo.h | 34 + + .../src/common/hinic3_utils/hinic3_message.h | 605 +++++++ + .../src/common/hinic3_utils/hinic3_mutex.h | 57 + + .../src/common/hinic3_utils/hinic3_nlattr.h | 205 +++ + .../src/common/hinic3_utils/hinic3_option.h | 18 + + .../common/hinic3_utils/hinic3_ovs_adapter.h | 0 + .../hinic3_utils/hinic3_packets_types.h | 383 ++++ + .../src/common/hinic3_utils/hinic3_provider.h | 265 +++ + .../common/hinic3_utils/hinic3_set_userdata.c | 67 + + .../common/hinic3_utils/hinic3_set_userdata.h | 26 + + .../src/common/hinic3_utils/hinic3_timeval.h | 27 + + .../src/common/hinic3_utils/hinic3_tlv_key.h | 154 ++ + .../src/common/hinic3_utils/hinic3_types.h | 29 + + .../common/hinic3_utils/hinic3_ui_string.h | 410 +++++ + .../common/hinic3_utils/hinic3_unaligned.h | 16 + + .../src/common/hinic3_utils/hinic3_util.c | 515 ++++++ + .../src/common/hinic3_utils/hinic3_util.h | 220 +++ + .../src/common/hinic3_uuid/hinic3_uuid.c | 89 + + .../src/common/hinic3_uuid/hinic3_uuid.h | 29 + + .../hinic3_capture/hinic3_capture_command.c | 437 +++++ + .../hinic3_capture/hinic3_capture_command.h | 13 + + .../src/hinic3_capture/hinic3_capture_core.c | 140 ++ + .../src/hinic3_capture/hinic3_capture_core.h | 19 + + .../hinic3_capture/hinic3_capture_filter.c | 1188 +++++++++++++ + .../hinic3_capture/hinic3_capture_filter.h | 185 ++ + .../src/hinic3_capture/hinic3_capture_hooks.c | 58 + + .../src/hinic3_capture/hinic3_capture_hooks.h | 9 + + .../src/hinic3_capture/hinic3_capture_main.c | 178 ++ + .../src/hinic3_capture/hinic3_capture_main.h | 13 + + .../src/hinic3_capture/hinic3_capture_save.c | 266 +++ + .../src/hinic3_capture/hinic3_capture_save.h | 11 + + .../src/hinic3_capture/hinic3_capture_utils.c | 1303 ++++++++++++++ + .../src/hinic3_capture/hinic3_capture_utils.h | 281 +++ + .../client/hinic3_command_client.c | 278 +++ + .../src/hinic3_cmds/comm/hinic3_agent_cmd.c | 74 + + .../src/hinic3_cmds/comm/hinic3_agent_cmd.h | 19 + + .../comm/hinic3_agent_cmd_format.c | 527 ++++++ + .../comm/hinic3_agent_cmd_format.h | 50 + + .../hinic3_cmds/comm/hinic3_agent_cmd_time.c | 40 + + .../hinic3_cmds/comm/hinic3_agent_cmd_time.h | 88 + + .../hinic3_cmds/comm/hinic3_agent_flow_cmd.c | 92 + + .../hinic3_cmds/comm/hinic3_agent_flow_cmd.h | 80 + + .../comm/hinic3_agent_flow_cmd_api.c | 268 +++ + .../comm/hinic3_agent_flow_cmd_dump.c | 554 ++++++ + .../comm/hinic3_agent_flow_cmd_dump.h | 152 ++ + .../comm/hinic3_agent_flow_cmd_dump_file.c | 302 ++++ + .../comm/hinic3_agent_flow_cmd_speed.c | 472 +++++ + .../hinic3_cmds/comm/hinic3_cmd_error_stats.c | 151 ++ + .../hinic3_cmds/comm/hinic3_cmd_error_stats.h | 19 + + .../src/hinic3_cmds/comm/hinic3_cmd_exec.c | 82 + + .../src/hinic3_cmds/comm/hinic3_cmd_exec.h | 15 + + .../src/hinic3_cmds/comm/hinic3_cmd_forward.c | 210 +++ + .../src/hinic3_cmds/comm/hinic3_cmd_forward.h | 9 + + .../src/hinic3_cmds/comm/hinic3_cmd_meminfo.c | 124 ++ + .../src/hinic3_cmds/comm/hinic3_cmd_meminfo.h | 16 + + .../src/hinic3_cmds/comm/hinic3_cmd_version.c | 28 + + .../src/hinic3_cmds/comm/hinic3_cmd_version.h | 11 + + .../src/hinic3_cmds/comm/hinic3_dfx_port.c | 114 ++ + .../src/hinic3_cmds/comm/hinic3_dfx_port.h | 55 + + .../comm/hinic3_dfx_port_bond_slave.c | 238 +++ + .../comm/hinic3_dfx_port_flush_dump.c | 502 ++++++ + .../comm/hinic3_dfx_port_upcall_queue.c | 582 ++++++ + .../src/hinic3_cmds/comm/hinic3_trace_flow.c | 395 +++++ + .../src/hinic3_cmds/comm/hinic3_trace_flow.h | 79 + + .../src/hinic3_cmds/comm/hinic3_vf_dfx.c | 363 ++++ + .../src/hinic3_cmds/comm/hinic3_vf_dfx.h | 76 + + .../comm/hinic3_vf_dfx_multi_qos.c | 1121 ++++++++++++ + .../src/hinic3_cmds/server/hinic3_command.c | 625 +++++++ + .../src/hinic3_cmds/server/hinic3_command.h | 49 + + .../hinic3_driver_public.h | 152 ++ + .../hinic3_driver_adapter/hinic3_iface_flow.c | 552 ++++++ + .../hinic3_driver_adapter/hinic3_iface_flow.h | 112 ++ + .../hinic3_iface_flow_api_record.c | 122 ++ + .../hinic3_iface_flow_api_record.h | 82 + + .../hinic3_iface_global.c | 1560 +++++++++++++++++ + .../hinic3_iface_global.h | 156 ++ + .../hinic3_iface_global_api_record.c | 86 + + .../hinic3_iface_global_api_record.h | 14 + + .../hinic3_driver_adapter/hinic3_iface_port.c | 910 ++++++++++ + .../hinic3_driver_adapter/hinic3_iface_port.h | 121 ++ + .../hinic3_iface_port_api_record.c | 92 + + .../hinic3_iface_port_api_record.h | 60 + + .../hinic3_iface_port_util.c | 529 ++++++ + .../hinic3_iface_port_util.h | 23 + + .../hiovs/hiovs_acl_api.h | 21 + + .../hinic3_driver_adapter/hiovs/hiovs_api.h | 1170 +++++++++++++ + .../comm/hinic3_age_delete_flow_public.c | 22 + + .../comm/hinic3_age_delete_flow_public.h | 17 + + .../hinic3_flow_agent_sync_stats_public.h | 29 + + .../comm/hinic3_flow_dump_public.c | 142 ++ + .../comm/hinic3_flow_dump_public.h | 102 ++ + .../comm/hinic3_offload_action_public.c | 299 ++++ + .../comm/hinic3_offload_action_public.h | 24 + + .../comm/hinic3_offload_flow_port.c | 125 ++ + .../comm/hinic3_offload_flow_port.h | 12 + + .../comm/hinic3_offload_flow_public.c | 45 + + .../comm/hinic3_offload_flow_public.h | 204 +++ + .../comm/hinic3_packet_key_public.h | 284 +++ + .../hinic3_emc_dump/hinic3_flow_dump_action.c | 616 +++++++ + .../hinic3_emc_dump/hinic3_flow_dump_action.h | 18 + + .../hinic3_emc_dump/hinic3_flow_dump_item.c | 363 ++++ + .../hinic3_emc_dump/hinic3_flow_dump_item.h | 18 + + .../hinic3_flow_dump_item_key.c | 174 ++ + .../hinic3_flow_dump_item_key.h | 39 + + .../hinic3_emc_dump/hinic3_flow_emc_dump.c | 154 ++ + .../hinic3_emc_dump/hinic3_flow_emc_dump.h | 7 + + .../hinic3_age_delete_flow.c | 142 ++ + .../hinic3_age_delete_flow.h | 14 + + .../hinic3_flow_dump/hinic3_flow_api.c | 153 ++ + .../hinic3_flow_dump/hinic3_flow_dump.c | 338 ++++ + .../hinic3_flow_dump/hinic3_flow_dump.h | 19 + + .../hinic3_flow_format/hinic3_flow_format.c | 549 ++++++ + .../hinic3_flow_format/hinic3_flow_format.h | 26 + + .../hinic3_flow_mirror/hinic3_flow_mirror.c | 306 ++++ + .../hinic3_flow_mirror/hinic3_flow_mirror.h | 72 + + .../hinic3_flow_mirror/hinic3_flow_session.c | 569 ++++++ + .../hinic3_flow_mirror/hinic3_flow_session.h | 102 ++ + .../hinic3_flow_offload/hinic3_dump_flow.c | 71 + + .../hinic3_flow_offload/hinic3_dump_flow.h | 23 + + .../hinic3_offload_action.c | 128 ++ + .../hinic3_offload_action.h | 14 + + .../hinic3_flow_offload/hinic3_offload_flow.c | 587 +++++++ + .../hinic3_flow_offload/hinic3_offload_flow.h | 17 + + .../hinic3_flow_agent_sync_stats.c | 192 ++ + .../hinic3_flow_agent_sync_stats.h | 11 + + .../hinic3_flow_query/hinic3_key_query.c | 737 ++++++++ + .../hinic3_flow_query/hinic3_key_query.h | 29 + + .../hinic3_flow_query/hinic3_query_flow.c | 65 + + .../hinic3_flow_query/hinic3_query_flow.h | 13 + + .../hinic3_flows/hinic3_vxlan/hinic3_vxlan.c | 68 + + .../hinic3_flows/hinic3_vxlan/hinic3_vxlan.h | 16 + + .../hinic3_vxlan/hinic3_vxlan_dump.c | 256 +++ + .../hinic3_vxlan/hinic3_vxlan_dump.h | 11 + + .../src/hinic3_init/comm/hinic3_agent.c | 335 ++++ + .../src/hinic3_init/comm/hinic3_agent.h | 57 + + .../src/hinic3_init/comm/hinic3_flow_agent.c | 659 +++++++ + .../src/hinic3_init/comm/hinic3_flow_agent.h | 48 + + .../hinic3/src/hinic3_init/comm/hinic3_init.c | 294 ++++ + .../hinic3/src/hinic3_init/comm/hinic3_init.h | 35 + + .../comm/hinic3_parse_agent_config.c | 649 +++++++ + .../comm/hinic3_parse_agent_config.h | 238 +++ + .../src/hinic3_ports/comm/hinic3_port_util.c | 202 +++ + .../src/hinic3_ports/comm/hinic3_port_util.h | 44 + + .../hinic3_bond/hinic3_bond_controller.c | 930 ++++++++++ + .../hinic3_bond/hinic3_bond_controller.h | 91 + + .../hinic3_bond/hinic3_bond_statistics.c | 135 ++ + .../hinic3_bond/hinic3_bond_statistics.h | 19 + + .../hinic3_ports/hinic3_queue/hinic3_queue.c | 128 ++ + .../hinic3_ports/hinic3_queue/hinic3_queue.h | 52 + + .../hinic3_queue/hinic3_standard_queue.c | 21 + + .../hinic3_queue/hinic3_standard_queue.h | 36 + + .../hinic3_queue/hinic3_virtual_queue.c | 300 ++++ + .../hinic3_queue/hinic3_virtual_queue.h | 72 + + .../hinic3_ports/hinic3_vdev/hinic3_vdev.c | 1111 ++++++++++++ + .../hinic3_ports/hinic3_vdev/hinic3_vdev.h | 13 + + .../hinic3_ports/hinic3_vf/hinic3_eth_util.c | 174 ++ + .../hinic3_ports/hinic3_vf/hinic3_eth_util.h | 27 + + .../hinic3_vf/hinic3_function_statistics.c | 144 ++ + .../hinic3_vf/hinic3_function_statistics.h | 20 + + .../hinic3_vf/hinic3_vf_controller.c | 1325 ++++++++++++++ + .../hinic3_vf/hinic3_vf_controller.h | 196 +++ + .../hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c | 643 +++++++ + .../hinic3_ports/hinic3_vf/hinic3_vf_mgmt.h | 113 ++ + .../hinic3_vf/hinic3_vf_mgmt_baremetal.c | 72 + + .../hinic3_vf/hinic3_vf_mgmt_baremetal.h | 10 + + .../hinic3_vf/hinic3_vf_mgmt_virtual.c | 61 + + .../hinic3_vf/hinic3_vf_mgmt_virtual.h | 11 + + .../comm/hinic3_vf_port_qos_public.c | 331 ++++ + .../comm/hinic3_vf_port_qos_public.h | 79 + + .../hinic3/src/hinic3_qos/meter/hinic3_qos.c | 26 + + .../hinic3/src/hinic3_qos/meter/hinic3_qos.h | 13 + + .../hinic3_qos/multilevel_qos/hinic3_mtr.c | 1555 ++++++++++++++++ + .../hinic3_qos/multilevel_qos/hinic3_mtr.h | 100 ++ + .../multilevel_qos/hinic3_mtr_policy.c | 165 ++ + .../multilevel_qos/hinic3_mtr_policy.h | 36 + + .../multilevel_qos/hinic3_mtr_profile.c | 181 ++ + .../multilevel_qos/hinic3_mtr_profile.h | 35 + + .../hinic3_ufid_map/hinic3_mpool_rte_flow.c | 105 ++ + .../hinic3_ufid_map/hinic3_mpool_rte_flow.h | 31 + + .../src/hinic3_ufid_map/hinic3_ufid_hmap.c | 118 ++ + .../src/hinic3_ufid_map/hinic3_ufid_hmap.h | 32 + + .../hinic3_ufid_map_rte_flow.c | 466 +++++ + .../hinic3_ufid_map_rte_flow.h | 122 ++ + drivers/net/meson.build | 1 + + 228 files changed, 46336 insertions(+) + create mode 100644 drivers/net/hinic3/cfg/ovs_dpu_virt/agent_config.ini + create mode 100644 drivers/net/hinic3/include/dpak_cfg.h + create mode 100644 drivers/net/hinic3/meson.build + create mode 100644 drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh + create mode 100644 drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_eth_packets.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_enum.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_public.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_list.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_message.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_option.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_ovs_adapter.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_provider.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_tlv_key.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_types.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_ui_string.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_unaligned.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h + create mode 100644 drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.c + create mode 100644 drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.h + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.h + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.h + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.h + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.h + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.h + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c + create mode 100644 drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_api.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c + create mode 100644 drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.c + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.c + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_acl_api.h + create mode 100644 drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_agent_sync_stats_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/comm/hinic3_packet_key_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.h + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.h + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.h + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.h + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c + create mode 100644 drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.h + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.c + create mode 100644 drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.h + create mode 100644 drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c + create mode 100644 drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.h + create mode 100644 drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c + create mode 100644 drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.h + create mode 100644 drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c + create mode 100644 drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.h + create mode 100644 drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c + create mode 100644 drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.h + create mode 100644 drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.c + create mode 100644 drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.h + create mode 100644 drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h + create mode 100644 drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c + create mode 100644 drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h + create mode 100644 drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h + +diff --git a/drivers/net/hinic3/cfg/ovs_dpu_virt/agent_config.ini b/drivers/net/hinic3/cfg/ovs_dpu_virt/agent_config.ini +new file mode 100644 +index 0000000..526bdfa +--- /dev/null ++++ b/drivers/net/hinic3/cfg/ovs_dpu_virt/agent_config.ini +@@ -0,0 +1,49 @@ ++; Global Configuration. ++[hwoff_agent] ++; offload_thread_num: Number of flow table offloading threads. The value range is {1, 2, 4}. ++offload_thread_num=2 ++; max_flow_num: Maximum number of hardware flow tables, in million (M). The value range is {1, 2}, if run time mode is 1, support 4 also. ++max_flow_num=2 ++; forward_cpu_mask: Core binding configuration for flow table offloading threads, e.g. "*, *". ++forward_cpu_mask=8, 9 ++; control_cpu_mask: Core binding configuration for control threads, e.g. "*, *". ++control_cpu_mask=10 ++; pf_pci_addr: NIC PCI address. The defalut value is "". ++pf_pci_addr="" ++; disk_usage: Maximum drive space usage of a file directory, in MB. The value range is [10, 10240]. ++disk_usage=1024 ++; hugepage_meminfo_statistic: Enable or disable hugepage memory statistics. The value can be either enable or disable. ++hugepage_meminfo_statistic=enable ++; packet_forward_mode: Packet forwarding mode. The value range is {0, 1}. 0: high bandwidth mode, 1: low latency mode. ++packet_forward_mode=0 ++; run_time_mode: DPAK runtime modes in different scenarios. The value range is {0, 1}. ++run_time_mode=1 ++; bond_hash_policy: efficient bond hash policy selection. The value range is {0, 1}. 0: efficient hash policy, 1: standard hash policy, default 0. ++bond_hash_policy=0 ++; pcap_cpu: CPU configuration for the packet capture threads. The value range is [0, 23]. ++pcap_cpu=0 ++ ++; Port Configuration. ++[hwoff_port] ++; bond_rx_depth: RX queue depth of the bond port. The value range is [256, 8192]. ++bond_rx_depth=2048 ++; bond_tx_depth: TX queue depth of the bond port. The value range is [256, 8192]. ++bond_tx_depth=2048 ++; vport_rx_depth: RX queue depth of the VF and PF ports. The value range is [256, 8192]. ++vport_rx_depth=512 ++; vport_tx_depth: TX queue depth of the VF and PF ports. The value range is [256, 8192]. ++vport_tx_depth=512 ++; mbuf_size: The dataroom size of mempool used by the hiovs3 driver. ++mbuf_size=2176 ++; virtual_queue_multiplex: Configure the virtual upcall queue and set the multiple. The value range is [0, 16], and setting [0, 1] will disable virtual queue mode. ++virtual_queue_multiplex=0 ++ ++; Flow Configuration. ++[hwoff_flow] ++; flow_max_idle: Hardware flow table aging time. The value range is [30000, 500000]. ++flow_max_idle=200000 ++ ++; QoS Configuration. ++[hwoff_QoS] ++; Types of multi-level QoS settings. The value rannge is {port_pps, port_bps, vm_pps, vm_bps, net_pps, net_bps}.Just support in run_time_mode = 1. ++qos_level=port_bps,port_pps,vm_bps,vm_pps,net_bps,net_pps +diff --git a/drivers/net/hinic3/include/dpak_cfg.h b/drivers/net/hinic3/include/dpak_cfg.h +new file mode 100644 +index 0000000..c2c7d49 +--- /dev/null ++++ b/drivers/net/hinic3/include/dpak_cfg.h +@@ -0,0 +1,95 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#ifndef DPAK_CFG_H ++#define DPAK_CFG_H ++ ++#include ++#include ++#include "hinic3_log.h" ++#include "hiovs_api.h" ++#define HINIC3_CPU_MASK_NUM 4 ++#define HINIC3_PCI_MAX_LEN 40 ++#define QOS_LEVEL_MAX_LENGTH 50 ++#define HINIC3_FLOW_MAX_IDLE_DEFAULT 200000 ++ ++/* 三种状态 默认下发 默认不下发 选择性下发 */ ++enum tcp_ct_action_switch { ++ DEFAULT_PUT, ++ DEFAULT_NOT_PUT, ++ SELECT_PUT, ++}; ++ ++enum hinic3_work_mode { ++ SMART_NIC_MODE, ++ DPU_MODE, ++}; ++ ++enum hinic3_forward_mode { ++ OVS_KEY_EXTRACT_MODE_9TUPLE = 0, /**< 9 tuples: localtag, dmac, smac, ethtype, sip, dip, protol, sport, dport */ ++ OVS_KEY_EXTRACT_MODE_4TUPLE = 1, /**< 4 tuples: localtag, dmac, smac, ethtype */ ++ OVS_KEY_EXTRACT_MODE_6_9TUPLE = 2, /**< 6 tuples: localtag, sip, dip, protol, sport, dport */ ++ OVS_KEY_EXTRACT_MODE_MAX = 3, ++ OVS_KEY_EXTRACT_EXTEND_MODE_6TUPLE = 4, /**< 6 tuples: localtag, dmac, dip, ethtype, vlan_id, input_port */ ++ OVS_KEY_EXTRACT_EXTEND_MODE_11TUPLE = 5, /**< 11 tuples: 9 tuples, vlan_id, input_port */ ++ OVS_KEY_EXTRACT_EXTEND_MODE_7TUPLE = 6, /** < 9 tuples vni, eth_type, src_ip, dst_ip, protocol, sport, dport */ ++}; ++ ++enum hinic3_query_bdf_type { ++ QUERY_BDF_TYPE_REAL, /**< query real bdf type. */ ++ QUERY_BDF_TYPE_FAKE, /**< query fake bdf type. */ ++}; ++ ++struct hinic3_cpu_mask { ++ uint32_t cpu_mask[HINIC3_CPU_MASK_NUM]; ++ uint32_t cpu_mask_invalid_num; ++}; ++ ++enum hinic3_bond_hash_policy { ++ EFFICIENT_HASH, ++ STANDARD_HASH, ++}; ++ ++struct hinic3_init_arg { ++ bool add_port_when_init; ++ bool is_dpu; ++ enum tcp_ct_action_switch status_packet_upcall; ++ uint32_t support_virtio_queue; ++ uint32_t bond_rx_depth; ++ uint32_t bond_tx_depth; ++ uint32_t vport_rx_depth; ++ uint32_t vport_tx_depth; ++ enum hinic3_forward_mode forward_mode; ++ enum hiovs_work_mode hiovs_mode; ++ uint32_t offload_thread_num; ++ uint32_t max_flow_num; ++ uint32_t max_flow_num_limit; ++ struct hinic3_cpu_mask forward_cpu_mask; ++ struct hinic3_cpu_mask control_cpu_mask; ++ char pf_pci_addr[HINIC3_PCI_MAX_LEN]; ++ uint32_t max_queue_num; ++ uint32_t max_queue_num_limit; ++ uint32_t upcall_queue_num; ++ uint32_t mbuf_size; ++ uint32_t flow_max_idle; ++ uint64_t vdpa_virtio_feature; ++ uint32_t disk_usage; ++ uint32_t packet_forward_mode; ++ bool enable_hugepage_meminfo_statistic; ++ uint32_t virtual_queue_multiplex; ++ uint32_t run_time_mode; ++ enum hinic3_bond_hash_policy bond_hash_policy; ++ uint32_t pcap_cpu; ++ enum hinic3_query_bdf_type query_bdf_type; ++ bool support_port_hot_plug; ++ bool support_vf_port; ++ bool support_pf_port; ++ char qos_level[QOS_LEVEL_MAX_LENGTH]; ++ bool is_virtio_queue_depth_set; ++ uint16_t virtio_queue_depth; ++}; ++ ++const char *hinic3_log_prefix_get(void); ++struct hinic3_init_arg *hinic3_get_fixed_config(); ++ ++#endif +diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build +new file mode 100644 +index 0000000..af07938 +--- /dev/null ++++ b/drivers/net/hinic3/meson.build +@@ -0,0 +1,180 @@ ++# SPDX-License-Identifier: BSD-3-Clause ++# Copyright(c) 2025 Huawei Technologies Co., Ltd ++ ++sources = files( ++ 'src/hinic3_capture/hinic3_capture_save.c', ++ 'src/hinic3_capture/hinic3_capture_hooks.c', ++ 'src/hinic3_capture/hinic3_capture_utils.c', ++ 'src/hinic3_capture/hinic3_capture_filter.c', ++ 'src/hinic3_capture/hinic3_capture_main.c', ++ 'src/hinic3_capture/hinic3_capture_command.c', ++ 'src/hinic3_capture/hinic3_capture_core.c', ++ 'src/hinic3_ports/comm/hinic3_port_util.c', ++ 'src/hinic3_ports/hinic3_queue/hinic3_queue.c', ++ 'src/hinic3_ports/hinic3_queue/hinic3_standard_queue.c', ++ 'src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.c', ++ 'src/hinic3_ports/hinic3_vf/hinic3_eth_util.c', ++ 'src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.c', ++ 'src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c', ++ 'src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c', ++ 'src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.c', ++ 'src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c', ++ 'src/hinic3_ports/hinic3_vdev/hinic3_vdev.c', ++ 'src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c', ++ 'src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c', ++ 'src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.c', ++ 'src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c', ++ 'src/hinic3_qos/multilevel_qos/hinic3_mtr.c', ++ 'src/hinic3_qos/comm/hinic3_vf_port_qos_public.c', ++ 'src/hinic3_qos/meter/hinic3_qos.c', ++ 'src/hinic3_ufid_map/hinic3_ufid_hmap.c', ++ 'src/hinic3_ufid_map/hinic3_mpool_rte_flow.c', ++ 'src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c', ++ 'src/hinic3_init/comm/hinic3_init.c', ++ 'src/hinic3_init/comm/hinic3_agent.c', ++ 'src/hinic3_init/comm/hinic3_flow_agent.c', ++ 'src/hinic3_init/comm/hinic3_parse_agent_config.c', ++ 'src/hinic3_driver_adapter/hinic3_iface_flow_api_record.c', ++ 'src/hinic3_driver_adapter/hinic3_iface_flow.c', ++ 'src/hinic3_driver_adapter/hinic3_iface_port.c', ++ 'src/hinic3_driver_adapter/hinic3_iface_global.c', ++ 'src/hinic3_driver_adapter/hinic3_iface_port_util.c', ++ 'src/hinic3_driver_adapter/hinic3_iface_global_api_record.c', ++ 'src/hinic3_driver_adapter/hinic3_iface_port_api_record.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_cmd_format.c', ++ 'src/hinic3_cmds/comm/hinic3_cmd_forward.c', ++ 'src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c', ++ 'src/hinic3_cmds/comm/hinic3_dfx_port.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_cmd.c', ++ 'src/hinic3_cmds/comm/hinic3_cmd_exec.c', ++ 'src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c', ++ 'src/hinic3_cmds/comm/hinic3_vf_dfx.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_flow_cmd.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_flow_cmd_api.c', ++ 'src/hinic3_cmds/comm/hinic3_trace_flow.c', ++ 'src/hinic3_cmds/comm/hinic3_cmd_meminfo.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c', ++ 'src/hinic3_cmds/comm/hinic3_cmd_version.c', ++ 'src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_cmd_time.c', ++ 'src/hinic3_cmds/comm/hinic3_cmd_error_stats.c', ++ 'src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c', ++ 'src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c', ++ 'src/hinic3_cmds/server/hinic3_command.c', ++ 'src/common/hinic3_log/hinic3_log.c', ++ 'src/common/hinic3_hash/hinic3_hash.c', ++ 'src/common/hinic3_cfg/ovs_dpu_virt.c', ++ 'src/common/hinic3_mutex/hinic3_mutex.c', ++ 'src/common/hinic3_hmap/hinic3_hmap.c', ++ 'src/common/hinic3_ds/hinic3_ds.c', ++ 'src/common/hinic3_uuid/hinic3_uuid.c', ++ 'src/common/hinic3_string_util/hinic3_string_format.c', ++ 'src/common/hinic3_string_util/hinic3_string_util.c', ++ 'src/common/hinic3_packets/hinic3_packets.c', ++ 'src/common/hinic3_mpool_mgmt/hinic3_mpool.c', ++ 'src/common/hinic3_utils/hinic3_meminfo.c', ++ 'src/common/hinic3_utils/hinic3_check_thread_health_state.c', ++ 'src/common/hinic3_utils/hinic3_set_userdata.c', ++ 'src/common/hinic3_utils/hinic3_file_util.c', ++ 'src/common/hinic3_utils/hinic3_hugepage_meminfo.c', ++ 'src/common/hinic3_utils/hinic3_error_stats.c', ++ 'src/common/hinic3_utils/hinic3_util.c', ++ 'src/common/hinic3_thread/hinic3_thread.c', ++ 'src/common/hinic3_smap/hinic3_shash.c', ++ 'src/common/hinic3_smap/hinic3_smap.c', ++ 'src/hinic3_flows/comm/hinic3_offload_action_public.c', ++ 'src/hinic3_flows/comm/hinic3_age_delete_flow_public.c', ++ 'src/hinic3_flows/comm/hinic3_flow_dump_public.c', ++ 'src/hinic3_flows/comm/hinic3_offload_flow_public.c', ++ 'src/hinic3_flows/comm/hinic3_offload_flow_port.c', ++ 'src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c', ++ 'src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c', ++ 'src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c', ++ 'src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c', ++ 'src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c', ++ 'src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c', ++ 'src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c', ++ 'src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c', ++ 'src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c', ++ 'src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c', ++ 'src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c', ++ 'src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c', ++ 'src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c', ++ 'src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c', ++ 'src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c', ++ 'src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.c', ++ 'src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c', ++ 'src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c', ++) ++ ++includes += include_directories( ++ 'include', ++ 'src/', ++ 'src/hinic3_capture', ++ 'src/hinic3_ports', ++ 'src/hinic3_ports/comm', ++ 'src/hinic3_ports/hinic3_queue', ++ 'src/hinic3_ports/hinic3_vf', ++ 'src/hinic3_ports/hinic3_vdev', ++ 'src/hinic3_ports/hinic3_bond', ++ 'src/hinic3_qos', ++ 'src/hinic3_qos/multilevel_qos', ++ 'src/hinic3_qos/comm', ++ 'src/hinic3_qos/meter', ++ 'src/hinic3_ufid_map', ++ 'src/hinic3_init', ++ 'src/hinic3_init/comm', ++ 'src/hinic3_driver_adapter', ++ 'src/hinic3_driver_adapter/hiovs', ++ 'src/hinic3_cmds', ++ 'src/hinic3_cmds/client', ++ 'src/hinic3_cmds/comm', ++ 'src/hinic3_cmds/server', ++ 'src/common', ++ 'src/common/hinic3_log', ++ 'src/common/hinic3_hash', ++ 'src/common/hinic3_cfg', ++ 'src/common/hinic3_mutex', ++ 'src/common/hinic3_hmap', ++ 'src/common/hinic3_ds', ++ 'src/common/hinic3_uuid', ++ 'src/common/hinic3_string_util', ++ 'src/common/hinic3_packets', ++ 'src/common/hinic3_mpool_mgmt', ++ 'src/common/hinic3_utils', ++ 'src/common/hinic3_thread', ++ 'src/common/hinic3_smap', ++ 'src/hinic3_flows', ++ 'src/hinic3_flows/comm', ++ 'src/hinic3_flows/hinic3_flow_mirror', ++ 'src/hinic3_flows/hinic3_flow_offload', ++ 'src/hinic3_flows/hinic3_flow_dump', ++ 'src/hinic3_flows/hinic3_flow_delete', ++ 'src/hinic3_flows/hinic3_flow_format', ++ 'src/hinic3_flows/hinic3_emc_dump', ++ 'src/hinic3_flows/hinic3_vxlan', ++ 'src/hinic3_flows/hinic3_flow_query', ++) ++deps += ['cfgfile', 'eal', 'kvargs', 'mempool', 'pci', 'bus_pci', 'bus_vdev', 'ring', 'mbuf', 'timer', 'ethdev'] ++ ++# eal is standard dependency once built ++if dpdk_conf.has('RTE_LIB_EAL') ++ deps += ['eal'] ++endif ++ ++shared_deps = [] ++static_deps = [] ++foreach d:deps ++ if not is_variable('shared_rte_' + d) ++ error('Missing internal dependency "@0@" for @name@ [@2@]' ++ .format(d, name, 'lib/' + name)) ++ endif ++ shared_deps += [get_variable('shared_rte_' + d)] ++ static_deps += [get_variable('static_rte_' + d)] ++endforeach ++ ++executable('dpak_ovs_ctl', ++ 'src/hinic3_cmds/client/hinic3_command_client.c', ++ include_directories: includes, ++) +diff --git a/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +new file mode 100644 +index 0000000..4eb0f1a +--- /dev/null ++++ b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +@@ -0,0 +1,716 @@ ++#!/bin/bash ++ ++# SPDX-License-Identifier: BSD-3-Clause ++# Copyright(c) 2022 Huawei Technologies Co., Ltd ++ ++config_file="/etc/dpak/net/agent_config.ini" ++ ++TOP_LEVEL_OPTS=( ++ hwoff/show-forward-mode ++ hwoff/set-forward-mode ++ hwoff/show-global-api ++ hwoff/dump-hinic3-flows ++ hwoff/dump-upcall-queue-info ++ hwoff/dump-bond-slave-info ++ hwoff/show-port-api ++ hwoff/show-adapter-version ++ hwoff/show-log-list ++ hwoff/show-security-src-mac-info ++ hwoff/set-log-level ++ hwoff/show-port-qos ++ hwoff/show-offload-flow-num ++ hwoff/dump-ports ++ hwoff/dump-ports-queue-info ++ hwoff/show-mpool-stats ++ hwoff/dump-trace ++ hwoff/dump-ufid-map-hw ++ hwoff/show-function-flavor ++ hwoff/show-meminfo ++ hwoff/show-hugepage-meminfo ++ hwoff/dump-qos ++ hwoff/enable-capture-probe ++ hwoff/flush-ports ++ hwoff/show-port-security-filter ++ hwoff/disable-capture-probe ++ hwoff/show-qos-speed ++ list-commands ++ hwoff/capture-probe ++ hwoff/show-error-stats ++ hwoff/show-function-stats ++ hwoff/trace-flow ++ hwoff/show-thread-stats ++ hwoff/flow-escape-mode ++ hwoff/dump-ufid-map-sw ++ hwoff/dump-qos-loss ++ hwoff/ufid-map-error-stats ++ hwoff/exec-cmd ++ hinic3-agent-version ++ hwoff/flow-offload-speed-stat ++ hwoff/show-flow-api ++ hwoff/show-hmap-flow-num ++ hwoff/show-security-eth-type-info ++ hwoff/query-offloaded-flow ++ hwoff/del-flow-by-ufid ++ hwoff/dump-meter ++ hwoff/dump-flow-qos-loss ++ -h ++ -v ++) ++ ++RUN_TIME_MODE_OPTS=( ++ hwoff/dump-port-qos-loss ++ hwoff/show-meter ++ hwoff/show-policy ++ hwoff/show-profile ++ hwoff/show-port-qos-speed ++ hwoff/dump-net-qos ++ hwoff/dump-net-qos-loss ++ hwoff/dump-qos-stats ++ hwoff/dump-port-qos-stats ++ hwoff/dump-net-qos-stats ++ hwoff/show-sample-session ++) ++ ++_get_top_level_options() { ++ local cur opts ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ COMPREPLY=( $(compgen -W "${TOP_LEVEL_OPTS[*]}" -- ${cur}) ) ++} ++ ++_get_run_time_mode_options() { ++ local cur opts ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ COMPREPLY=( $(compgen -W "${TOP_LEVEL_OPTS[*]} ${RUN_TIME_MODE_OPTS[*]}" -- ${cur}) ) ++} ++ ++_complete_show_global_api() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ prev2="${COMP_WORDS[COMP_CWORD-2]}" ++ ++ local api_opts=( ++ hovs_global_cfg_set ++ hovs_global_cfg_get ++ hovs_global_statistics_get ++ hovs_global_statistics_flush ++ hovs_open_log ++ hovs_set_log_level ++ hovs_mml_lib ++ hovs_global_pcie_list_query ++ ) ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "api clear all -h" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "api" ]]; then ++ COMPREPLY=( $(compgen -W "${api_opts[*]}" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 4 && ${prev2} == "api" && " ${api_opts[*]} " == *" ${prev} "* ]]; then ++ COMPREPLY=( $(compgen -W "clear" -- ${cur}) ) ++ fi ++} ++ ++_complete_dump_hinic3_flows() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "ufid check stop -h -f -n -b" -- ${cur}) ) ++ fi ++} ++ ++_complete_show_port_api() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ prev2="${COMP_WORDS[COMP_CWORD-2]}" ++ ++ local api_opts=( ++ hovs_port_mgmt_add ++ hovs_port_mgmt_del ++ hovs_port_mgmt_get ++ hovs_port_mgmt_set ++ hovs_port_mgmt_setup_upcall_queue ++ hovs_port_mgmt_release_upcall_queue ++ hovs_bond_mgmt_create ++ hovs_bond_mgmt_delete ++ hovs_bond_mgmt_get ++ hovs_bond_mgmt_set ++ hovs_bond_mgmt_clear ++ hovs_bond_slave_info_get ++ hovs_etheraddr_get ++ hovs_mtu_set ++ hovs_carrier_get ++ hovs_carrier_resets_get ++ hovs_port_statistics_get ++ hovs_port_statistics_flush ++ hovs_features_get ++ hovs_bum_get ++ hovs_bum_set ++ hovs_bum_remove ++ hovs_bum_clear ++ hovs_qos_ingress_limit_set ++ hovs_qos_ingress_limit_get ++ hovs_qos_egress_limit_set ++ hovs_qos_egress_limit_get ++ hovs_qos_drop_thresh_set ++ hovs_qos_drop_thresh_get ++ hovs_port_mgmt_get_capability ++ hovs_port_mgmt_get_upcall_info ++ hovs_qos_statistics_get_batch ++ hovs_qos_statistics_get_all_batch ++ hovs_qos_statistics_clear_batch ++ hovs_hqos_statistics_get_all_batch ++ hovs_hqos_statistics_clear_batch ++ hovs_port_mgmt_add_dynamic ++ hovs_qos_vm_limit_set ++ hovs_qos_vm_limit_get ++ hovs_qos_flow_limit_set ++ hovs_qos_flow_limit_get ++ hovs_qos_vport_limit_set ++ hovs_qos_vport_limit_get ++ hovs_qos_vm_srtcm_limit_set ++ hovs_qos_vm_srtcm_limit_get ++ hovs_qos_net_limit_set ++ hovs_qos_net_limit_get ++ hovs_bond_slave_statistics_get ++ hovs_port_mgmt_set_usage_state ++ hovs_port_mgmt_get_usage_state ++ hovs_upcall_mtu_set ++ ) ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "api clear all -h" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "api" ]]; then ++ COMPREPLY=( $(compgen -W "${api_opts[*]}" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 4 && ${prev2} == "api" && " ${api_opts[*]} " == *" ${prev} "* ]]; then ++ COMPREPLY=( $(compgen -W "clear" -- ${cur}) ) ++ fi ++} ++ ++_complete_set_log_level() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ prev2="${COMP_WORDS[COMP_CWORD-2]}" ++ local module_name=( ++ hinic3-agent ++ hinic3-vport ++ hinic3-bond ++ hinic3-flow ++ hinic3-bum ++ hinic3-qos ++ hinic3-packet ++ hinic3-driver-vport ++ hinic3-driver-bond ++ hinic3-driver-flow ++ hinic3-driver-bum ++ hinic3-driver-qos ++ hinic3-driver-chip ++ hinic3-driver-packet ++ hinic3-offload-policy ++ ) ++ ++ local level=( ++ disabled ++ emergency ++ alert ++ critical ++ error ++ warning ++ notice ++ info ++ debug ++ ) ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "-m -l -h --help" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "-m" ]]; then ++ COMPREPLY=( $(compgen -W "${module_name[*]}" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "-l" ]]; then ++ COMPREPLY=( $(compgen -W "${level[*]}" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 4 && ${prev2} == "-m" && " ${module_name[*]} " == *" ${prev} "* ]]; then ++ COMPREPLY=( $(compgen -W "-l" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 4 && ${prev2} == "-l" && " ${level[*]} " == *" ${prev} "* ]]; then ++ COMPREPLY=( $(compgen -W "-m" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 5 && ${prev} == "-m" ]]; then ++ COMPREPLY=( $(compgen -W "${module_name[*]}" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 5 && ${prev} == "-l" ]]; then ++ COMPREPLY=( $(compgen -W "${level[*]}" -- ${cur}) ) ++ fi ++} ++ ++ ++_complete_dump_ports() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "global -h" -- ${cur}) ) ++ fi ++} ++ ++_complete_dump_trace() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "-f -h" -- ${cur}) ) ++ fi ++} ++ ++_complete_flush_ports() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "global -h" -- ${cur}) ) ++ fi ++} ++ ++_complete_flow_escape_mode() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "enable disable show -h" -- ${cur}) ) ++ fi ++} ++ ++_complete_flow_offload_speed_stat_opts() ++{ ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ local opts=( ++ -t ++ -i ++ ) ++ ++ for ((i = 1; i < COMP_CWORD; i++)); do ++ word="${COMP_WORDS[i]}" ++ opts=("${opts[@]/$word}") ++ done ++ ++ COMPREPLY=( $(compgen -W "${opts[*]}" -- ${cur}) ) ++} ++_complete_flow_offload_speed_stat() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "start restart show stop -h" -- ${cur}) ) ++ elif [[ ${COMP_WORDS[2]} == "start" ]]; then ++ _complete_flow_offload_speed_stat_opts ++ elif [[ ${COMP_WORDS[2]} == "restart" ]]; then ++ _complete_flow_offload_speed_stat_opts ++ fi ++} ++ ++_complete_show_flow_api() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ prev2="${COMP_WORDS[COMP_CWORD-2]}" ++ ++ local api_opts=( ++ hovs_flow_mgmt_put ++ hovs_flow_mgmt_get_by_key ++ hovs_flow_mgmt_get_by_ufid ++ hovs_flow_mgmt_del_by_ufid ++ hovs_flow_mgmt_del_by_batch ++ hovs_flow_mgmt_flush ++ hovs_flow_mgmt_dump_start ++ hovs_flow_mgmt_dump_next ++ hovs_flow_mgmt_dump_done ++ hovs_flow_mgmt_get_maxflows ++ hovs_flow_mgmt_get_capability ++ hovs_flow_mgmt_set_forward_mode ++ hovs_flow_mgmt_get_forward_mode ++ hovs_statistics_flow_get_by_ufid ++ hovs_statistics_flow_flush_by_ufid ++ hinic3_rte_flow_create ++ hinic3_rte_flow_query ++ hinic3_rte_flow_delete ++ hinic3_rte_flow_flush_all ++ hinic3_rte_flow_destroy_by_batch ++ hinic3_rte_flow_dump_start ++ hinic3_rte_flow_dump_next ++ hinic3_rte_flow_dump_end ++ hovs_flow_mgmt_get_block_table_size ++ hovs_flow_mgmt_update ++ hovs_flow_mgmt_set_block_version ++ hovs_flow_mgmt_get_block_version ++ ) ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "api clear all -h" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "api" ]]; then ++ COMPREPLY=( $(compgen -W "${api_opts[*]}" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 4 && ${prev2} == "api" && " ${api_opts[*]} " == *" ${prev} "* ]]; then ++ COMPREPLY=( $(compgen -W "clear" -- ${cur}) ) ++ fi ++} ++ ++_complete_exec_cmd_dump() ++{ ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ local opts=" ++ -h ++ -t ++ -x ++ " ++ local t_opts=" ++ 0 ++ 2 ++ 3 ++ 4 ++ 16 ++ 17 ++ 18 ++ 19 ++ 20 ++ 22 ++ 23 ++ 24 ++ " ++ for ((i = 1; i < COMP_CWORD; i++)); do ++ word="${COMP_WORDS[i]}" ++ opts=("${opts[@]/$word}") ++ done ++ ++ if [[ "${prev}" == "-t" ]]; then ++ COMPREPLY=( $(compgen -W "${t_opts}" -- ${cur}) ) ++ else ++ COMPREPLY=( $(compgen -W "${opts[*]}" -- ${cur}) ) ++ fi ++} ++ ++_complete_exec_cmd_nic_queue() ++{ ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ local opts=" ++ -h ++ -i ++ -d ++ -t ++ -q ++ -w ++ " ++ local d_opts=" ++ 0 ++ 1 ++ " ++ local t_opts=" ++ 0 ++ 1 ++ 2 ++ " ++ for ((i = 1; i < COMP_CWORD; i++)); do ++ word="${COMP_WORDS[i]}" ++ opts=("${opts[@]/$word}") ++ done ++ ++ if [[ "${prev}" == "-d" ]]; then ++ COMPREPLY=( $(compgen -W "${d_opts}" -- ${cur}) ) ++ elif [[ "${prev}" == "-t" ]]; then ++ COMPREPLY=( $(compgen -W "${t_opts}" -- ${cur}) ) ++ else ++ COMPREPLY=( $(compgen -W "${opts[*]}" -- ${cur}) ) ++ fi ++} ++ ++_complete_exec_cmd_hpd() ++{ ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ local opts=" ++ -h ++ -v ++ -m ++ -t ++ -i ++ -x ++ " ++ local m_opts=" ++ 0 ++ 1 ++ " ++ local t_opts=" ++ 0 ++ 1 ++ 2 ++ " ++ for ((i = 1; i < COMP_CWORD; i++)); do ++ word="${COMP_WORDS[i]}" ++ opts=("${opts[@]/$word}") ++ done ++ ++ if [[ "${prev}" == "-m" ]]; then ++ COMPREPLY=( $(compgen -W "${m_opts}" -- ${cur}) ) ++ elif [[ "${prev}" == "-t" ]]; then ++ COMPREPLY=( $(compgen -W "${t_opts}" -- ${cur}) ) ++ else ++ COMPREPLY=( $(compgen -W "${opts[*]}" -- ${cur}) ) ++ fi ++} ++ ++_complete_exec_cmd() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "-h -v dump xstats nic_queue hpd" -- ${cur}) ) ++ elif [[ ${COMP_WORDS[2]} == "dump" ]]; then ++ _complete_exec_cmd_dump ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "xstats" ]]; then ++ COMPREPLY=( $(compgen -W "-h -i" -- ${cur}) ) ++ elif [[ ${COMP_WORDS[2]} == "nic_queue" ]]; then ++ _complete_exec_cmd_nic_queue ++ elif [[ ${COMP_WORDS[2]} == "hpd" ]]; then ++ _complete_exec_cmd_hpd ++ fi ++} ++ ++_complete_capture_probe_start() ++{ ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ local opts=" ++ -w ++ -sip ++ -dip ++ -host ++ -smac ++ -dmac ++ -eth_type ++ -ip_proto ++ -vxlan_inner ++ -vlan ++ -sport ++ -dport ++ -vxlan_vni ++ -P ++ -c ++ -thread ++ " ++ local ip_proto_opts=" ++ TCP ++ UDP ++ ICMP ++ SCTP ++ ICMPV6 ++ " ++ local p_opts=" ++ in ++ out ++ inout ++ " ++ for ((i = 1; i < COMP_CWORD; i++)); do ++ word="${COMP_WORDS[i]}" ++ opts=("${opts[@]/$word}") ++ done ++ ++ if [[ "${prev}" == "-ip_proto" ]]; then ++ COMPREPLY=( $(compgen -W "${ip_proto_opts}" -- ${cur}) ) ++ elif [[ "${prev}" == "-P" ]]; then ++ COMPREPLY=( $(compgen -W "${p_opts}" -- ${cur}) ) ++ else ++ COMPREPLY=( $(compgen -W "${opts[*]}" -- ${cur}) ) ++ fi ++} ++ ++_complete_capture_probe() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "start show stop help" -- ${cur}) ) ++ elif [[ ${COMP_WORDS[2]} == "start" ]]; then ++ _complete_capture_probe_start ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "stop" ]]; then ++ COMPREPLY=( $(compgen -W "-pcap_id" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "show" ]]; then ++ COMPREPLY=( $(compgen -W "all -pcap_id" -- ${cur}) ) ++ fi ++} ++ ++_complete_set_pkt_forward_mod() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "low_latency high_throughput" -- ${cur}) ) ++ fi ++} ++ ++_complete_trace_flow() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "-proto -sip -dip -sport -dport" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "-proto" ]]; then ++ COMPREPLY=( $(compgen -W "tcp udp" -- ${cur}) ) ++ fi ++} ++ ++_complete_dump_ufid_map_hw() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "-n -h all" -- ${cur}) ) ++ fi ++} ++ ++_complete_set_offload_switch() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "enable disable -h" -- ${cur}) ) ++ fi ++} ++ ++_complete_set_policy_info() { ++ local cur prev ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ local set_policy_opts=" ++ permission-enable ++ user-permission-default ++ permission-update-interval ++ permission-credit ++ delay-mode ++ delay-duration ++ delay-packet-pps ++ delay-packet-nums ++ garbage-clean-interval ++ max-garbage-life ++ user-idle-time ++ limit-offload-flow-nums ++ clean-window-enable ++ flow-clean-pps ++ window-update-interval ++ -h ++ " ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "${set_policy_opts}" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "permission-enable" ]]; then ++ COMPREPLY=( $(compgen -W "off on" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "delay-mode" ]]; then ++ COMPREPLY=( $(compgen -W "delay-packet-count delay-packet-pps no-offload-delay" -- ${cur}) ) ++ elif [[ ${COMP_CWORD} -eq 3 && ${prev} == "clean-window-enable" ]]; then ++ COMPREPLY=( $(compgen -W "off on" -- ${cur}) ) ++ fi ++} ++ ++_complete_dump_ufid_map_sw() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "all -n -h" -- ${cur}) ) ++ fi ++} ++ ++_complete_add_del_rapid_proto() { ++ local cur ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ ++ if [[ ${COMP_CWORD} -eq 2 ]]; then ++ COMPREPLY=( $(compgen -W "tcp udp icmp icmpv6 -h" -- ${cur}) ) ++ fi ++} ++ ++_dpak_ovs_ctl() { ++ local cur prev ++ local run_time_mode ++ run_time_mode=$(grep -E '^run_time_mode=' "$config_file" | awk -F= '{print $2+0}') ++ COMPREPLY=() ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[1]}" ++ ++ if [[ ${COMP_CWORD} -eq 1 ]]; then ++ if [[ $run_time_mode -eq 1 ]]; then ++ _get_run_time_mode_options ++ return 0 ++ fi ++ _get_top_level_options ++ return 0 ++ fi ++ ++ case "${prev}" in ++ hwoff/show-global-api) ++ _complete_show_global_api ++ return 0 ++ ;; ++ hwoff/dump-hinic3-flows) ++ _complete_dump_hinic3_flows ++ return 0 ++ ;; ++ hwoff/show-port-api) ++ _complete_show_port_api ++ return 0 ++ ;; ++ hwoff/set-log-level) ++ _complete_set_log_level ++ return 0 ++ ;; ++ hwoff/dump-ports) ++ _complete_dump_ports ++ return 0 ++ ;; ++ hwoff/dump-trace) ++ _complete_dump_trace ++ return 0 ++ ;; ++ hwoff/dump-ufid-map-hw) ++ _complete_dump_ufid_map_hw ++ return 0 ++ ;; ++ hwoff/flush-ports) ++ _complete_flush_ports ++ return 0 ++ ;; ++ hwoff/flow-escape-mode) ++ _complete_flow_escape_mode ++ return 0 ++ ;; ++ hwoff/dump-ufid-map-sw) ++ _complete_dump_ufid-map-sw ++ return 0 ++ ;; ++ hwoff/flow-offload-speed-stat) ++ _complete_flow_offload_speed_stat ++ return 0 ++ ;; ++ hwoff/show-flow-api) ++ _complete_show_flow_api ++ return 0 ++ ;; ++ hwoff/exec-cmd) ++ _complete_exec_cmd ++ return 0 ++ ;; ++ hwoff/capture-probe) ++ _complete_capture_probe ++ return 0 ++ ;; ++ hwoff/set-forward-mode) ++ _complete_set_pkt_forward_mod ++ return 0 ++ ;; ++ hwoff/trace-flow) ++ _complete_trace_flow ++ return 0 ++ ;; ++ *) ++ return 0 ++ ;; ++ esac ++} ++ ++complete -F _dpak_ovs_ctl dpak-ovs-ctl +diff --git a/drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c b/drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c +new file mode 100644 +index 0000000..d77b928 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c +@@ -0,0 +1,37 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include "dpak_cfg.h" ++ ++#define LOG_PREFIX_LENGTH 32 ++ ++const char g_log_prefix[LOG_PREFIX_LENGTH] = "dpak"; ++ ++struct hinic3_init_arg g_init_arg = { ++ .add_port_when_init = false, ++ .is_dpu = true, ++ .forward_mode = OVS_KEY_EXTRACT_EXTEND_MODE_7TUPLE, ++ .hiovs_mode = HIOVS_WORK_MODE_ZERO_VM_PT, ++ .vdpa_virtio_feature = 0, ++ .status_packet_upcall = SELECT_PUT, ++ .support_virtio_queue = 4096, ++ .max_flow_num_limit = 4, ++ .max_queue_num_limit = 64, ++ .query_bdf_type = QUERY_BDF_TYPE_REAL, ++ .support_port_hot_plug = false, ++ .support_vf_port = true, ++ .support_pf_port = true, ++}; ++ ++const char *hinic3_log_prefix_get(void) ++{ ++ return g_log_prefix; ++} ++ ++struct hinic3_init_arg *hinic3_get_fixed_config() ++{ ++ return &g_init_arg; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c +new file mode 100644 +index 0000000..bfdb82d +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c +@@ -0,0 +1,143 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_ds.h" ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_log.h" ++#include "hinic3_meminfo.h" ++ ++void hinic3_ds_destroy(struct ds *ds) ++{ ++ if (ds->string != NULL) { ++ hinic3_free(ds->string); ++ ds->string = NULL; ++ } ++} ++ ++char* hinic3_ds_cstr(struct ds *ds) ++{ ++ if (ds == NULL) { ++ return "\0"; ++ } ++ return ds->string == NULL ? "\0" : ds->string; ++} ++ ++static int hinic3_ds_reserve(struct ds *ds, size_t size) ++{ ++ if (size > ds->allocated) { ++ char *new_str = (char *)hinic3_calloc(1, size, HINIC3_COMMON_RESOURCE); ++ if (new_str == NULL) { ++ return -1; ++ } ++ ++ memcpy(new_str, ds->string, ds->length); ++ if (ds->string != NULL) { ++ hinic3_free(ds->string); ++ } ++ ++ ds->allocated = size; ++ ds->string = new_str; ++ } ++ return 0; ++} ++ ++void hinic3_ds_put_cstr(struct ds *ds, const char *s) ++{ ++ hinic3_ds_put_format(ds, "%s", s); ++} ++ ++void hinic3_ds_put_format_valist(struct ds *ds, const char *format, va_list args) ++{ ++ int writed = -1; ++ int ret; ++ size_t size = ds->allocated; ++ if (size == 0) { ++ size = HINIC3_INIT_DS_SIZE; ++ } ++ ++ while (writed < 0) { ++ if (size > HINIC3_MAX_DS_SIZE) { ++ char head[HINIC3_LOG_HEAD_LEN + 1] = {0}; ++ memcpy(head, ds->string, ds->length); ++ HINIC3_LOG(ERR, AGENT, "ds too long, prefix: %s, size:%d vs %d", head, (int)size, HINIC3_MAX_DS_SIZE); ++ return; ++ } ++ ++ ret = hinic3_ds_reserve(ds, size); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "ds reserve failed, ret is %d", ret); ++ return; ++ } ++ ++ size <<= 1; ++ ++ int left = ds->allocated - ds->length; ++ va_list args_tmp; ++ va_copy(args_tmp, args); ++ ++ writed = vsnprintf(&ds->string[ds->length], left, format, args_tmp); ++ if (writed < left) { ++ ds->length += writed; ++ } else { ++ writed = -1; ++ } ++ ++ va_end(args_tmp); ++ } ++} ++ ++void hinic3_ds_put_format(struct ds *ds, const char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ hinic3_ds_put_format_valist(ds, format, args); ++ va_end(args); ++} ++ ++void hinic3_ds_put_format_prefix(struct ds *ds, uint8_t indent_num, const char *prefix, const char *format, ...) ++{ ++ va_list args; ++ ++ for (uint8_t i = 0; i < indent_num; i++) { ++ hinic3_ds_put_format(ds, "%s", " "); ++ } ++ hinic3_ds_put_format(ds, "%s", prefix); ++ ++ va_start(args, format); ++ hinic3_ds_put_format_valist(ds, format, args); ++ va_end(args); ++} ++ ++void hinic3_ds_clear(struct ds *ds) ++{ ++ ds->length = 0; ++} ++ ++char *hinic3_ds_put_uninit(struct ds *ds, size_t n) ++{ ++ int ret; ++ ret = hinic3_ds_reserve(ds, ds->length + n); ++ if (ret != 0) { ++ return NULL; ++ } ++ ++ ds->length += n; ++ ds->string[ds->length - 1] = '\0'; ++ return &ds->string[ds->length - n]; ++} ++ ++void hinic3_ds_put_buffer(struct ds *ds, const char *s, size_t n) ++{ ++ memcpy(hinic3_ds_put_uninit(ds, n), s, n); ++} ++ ++void hinic3_ds_concat(struct ds *dst_ds, struct ds *src_ds) ++{ ++ hinic3_ds_put_buffer(dst_ds, src_ds->string, src_ds->length); ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h +new file mode 100644 +index 0000000..c73810e +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h +@@ -0,0 +1,37 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_DS_H_ ++#define _HINIC3_DS_H_ ++#include ++#include ++#include ++#include "hinic3_meminfo.h" ++ ++#define HINIC3_MAX_DS_SIZE (1 << 20) // max print string size 1M ++#define HINIC3_LOG_HEAD_LEN 30 ++#define HINIC3_INIT_DS_SIZE 128 ++ ++struct ds { ++ char *string; ++ size_t length; ++ size_t allocated; ++}; ++ ++#define DS_EMPTY_INITIALIZER { NULL, 0, 0 } ++ ++void hinic3_ds_put_cstr(struct ds *ds, const char *s); ++void hinic3_ds_put_format_valist(struct ds *ds, const char *format, va_list args); ++void hinic3_ds_put_format(struct ds *ds, const char *format, ...); ++/* 带缩进和前缀的格式化函数,indent_num为行首缩进数, prefix为前缀字符串 */ ++void hinic3_ds_put_format_prefix(struct ds *ds, uint8_t indent_num, const char *prefix, const char *format, ...); ++void hinic3_ds_destroy(struct ds *ds); ++char *hinic3_ds_cstr(struct ds *ds); ++ ++void hinic3_ds_clear(struct ds *ds); ++char *hinic3_ds_put_uninit(struct ds *ds, size_t n); ++void hinic3_ds_put_buffer(struct ds *ds, const char *s, size_t n); ++void hinic3_ds_concat(struct ds *dst_ds, struct ds *src_ds); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.c b/drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.c +new file mode 100644 +index 0000000..3c12934 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.c +@@ -0,0 +1,94 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_hash.h" ++ ++#define HINIC3_HALF_BYTE_SIZE 4 ++#define HINIC3_BYTE_SIZE 8 ++#define HINIC3_SHORT_SIZE 16 ++#define HINIC3_THREE_BYTE_SIZE 24 ++#define HINIC3_WORD_SIZE 32 ++ ++uint32_t hinic3_hash_add(uint32_t hash, uint32_t data) ++{ ++ return __crc32cw(hash, data); ++} ++ ++uint32_t hinic3_hash_add64(uint32_t hash, uint64_t data) ++{ ++ return __crc32cd(hash, data); ++} ++ ++static inline uint32_t hinic3_hash_finish(uint32_t hash, uint64_t final) ++{ ++ uint32_t hash_num = __crc32cd(hash, final) * 0x805204f3; ++ return hash_num ^ (hash_num >> HINIC3_SHORT_SIZE); ++} ++ ++static inline uint32_t get_unaligned_u32(const uint32_t *p_) ++{ ++ enum array_index {HOST_ID_LOW_BIT = 0, HOST_ID_HIGH_BIT = 1, NET_ID_LOW_BIT = 2, NET_ID_HIGH_BIT = 3}; ++ const uint8_t *p = (const uint8_t *)p_; ++ return ntohl((p[HOST_ID_LOW_BIT] << HINIC3_THREE_BYTE_SIZE) | (p[HOST_ID_HIGH_BIT] << HINIC3_SHORT_SIZE) | ++ (p[NET_ID_LOW_BIT] << HINIC3_BYTE_SIZE) | p[NET_ID_HIGH_BIT]); ++} ++ ++uint32_t hinic3_hash_bytes(const void *point, size_t n, uint32_t basis) ++{ ++ if (point == NULL) { ++ return hinic3_hash_finish(basis, 0); ++ } ++ const uint32_t *p = point; ++ uint32_t n_32b = (uint32_t)n; ++ uint32_t iter_n = n_32b; ++ uint32_t hash; ++ ++ hash = basis; ++ while (iter_n >= HINIC3_HALF_BYTE_SIZE) { ++ hash = hinic3_hash_add(hash, get_unaligned_u32(p)); ++ iter_n -= HINIC3_HALF_BYTE_SIZE; ++ p += 1; ++ } ++ ++ if (iter_n > 0) { ++ uint32_t tmp = 0; ++ ++ memcpy(&tmp, p, iter_n); ++ hash = hinic3_hash_add(hash, tmp); ++ } ++ ++ return hinic3_hash_finish(hash, n_32b); ++} ++ ++uint32_t hinic3_hash_string(const char *s, uint32_t basis) ++{ ++ return hinic3_hash_bytes(s, strlen(s), basis); ++} ++ ++uint32_t hinic3_hash_2words(uint32_t x, uint32_t y) ++{ ++ return hinic3_hash_finish(hinic3_hash_add(hinic3_hash_add(x, 0), y), HINIC3_BYTE_SIZE); ++} ++ ++ ++uint32_t hinic3_hash_int(uint32_t x, uint32_t basis) ++{ ++ return hinic3_hash_2words(x, basis); ++} ++ ++uint32_t hinic3_hash_uint64_basis(const uint64_t x, const uint32_t basis) ++{ ++ return hinic3_hash_finish(hinic3_hash_add64(basis, x), HINIC3_BYTE_SIZE); ++} ++ ++uint32_t hinic3_hash_uint64(const uint64_t x) ++{ ++ return hinic3_hash_uint64_basis(x, 0); ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.h b/drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.h +new file mode 100644 +index 0000000..3fe7062 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_hash/hinic3_hash.h +@@ -0,0 +1,23 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_HASH_H_ ++#define _HINIC3_HASH_H_ ++ ++#include ++#include ++#include ++#include ++ ++uint32_t hinic3_hash_add(uint32_t hash, uint32_t data); ++uint32_t hinic3_hash_add64(uint32_t hash, uint64_t data); ++uint32_t hinic3_hash_bytes(const void *point, size_t n, uint32_t basis); ++uint32_t hinic3_hash_string(const char *s, uint32_t basis); ++ ++uint32_t hinic3_hash_2words(uint32_t x, uint32_t y); ++uint32_t hinic3_hash_int(uint32_t x, uint32_t basis); ++uint32_t hinic3_hash_uint64_basis(const uint64_t x, const uint32_t basis); ++uint32_t hinic3_hash_uint64(const uint64_t x); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c +new file mode 100644 +index 0000000..2f7c9e1 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c +@@ -0,0 +1,186 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_hash.h" ++#include "hinic3_util.h" ++#include "hinic3_log.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_hmap.h" ++ ++void hinic3_hmap_init(struct hmap *hmap) ++{ ++ hmap->buckets = &hmap->one; ++ hmap->one = NULL; ++ hmap->mask = 0; ++ hmap->n = 0; ++} ++ ++void hinic3_hmap_destroy(struct hmap *hmap) ++{ ++ if (hmap != NULL && hmap->buckets != &hmap->one) { ++ hinic3_free(hmap->buckets); ++ hmap->buckets = NULL; ++ } ++} ++ ++bool hinic3_hmap_is_empty(const struct hmap *hmap) ++{ ++ return hmap->n == 0; ++} ++ ++size_t hinic3_hmap_count(const struct hmap *hmap) ++{ ++ return hmap->n; ++} ++ ++void hinic3_hmap_clear(struct hmap *hmap) ++{ ++ size_t size; ++ if (hmap->n > 0) { ++ hmap->n = 0; ++ size = (hmap->mask + 1) * sizeof(*hmap->buckets); ++ memset(hmap->buckets, 0, size); ++ } ++} ++ ++static inline struct hmap_node* hinic3_hmap_next_(const struct hmap *hmap, size_t start) ++{ ++ struct hmap_node *node = NULL; ++ size_t i; ++ ++ for (i = start; i <= hmap->mask; i++) { ++ node = hmap->buckets[i]; ++ if (node != NULL) { ++ return node; ++ } ++ } ++ ++ return NULL; ++} ++ ++struct hmap_node* hinic3_hmap_first(const struct hmap *hmap) ++{ ++ return hinic3_hmap_next_(hmap, 0); ++} ++ ++struct hmap_node* hinic3_hmap_next(const struct hmap *hmap, const struct hmap_node *node) ++{ ++ return (node->next ? node->next : hinic3_hmap_next_(hmap, (node->hash & hmap->mask) + 1)); ++} ++ ++void hinic3_hmap_moved(struct hmap *hmap) ++{ ++ if (!hmap->mask) { ++ hmap->buckets = &hmap->one; ++ } ++} ++ ++void hinic3_hmap_swap(struct hmap *a, struct hmap *b) ++{ ++ struct hmap tmp = *a; ++ *a = *b; ++ *b = tmp; ++ hinic3_hmap_moved(a); ++ hinic3_hmap_moved(b); ++} ++ ++static inline void hinic3_hmap_insert_fast(struct hmap *hmap, struct hmap_node *node, size_t hash) ++{ ++ struct hmap_node **bucket = &hmap->buckets[hash & hmap->mask]; ++ node->hash = hash; ++ node->next = *bucket; ++ *bucket = node; ++ hmap->n++; ++} ++ ++static void hinic3_resize(struct hmap *hmap, size_t new_mask, const char *where, enum hinic3_module module_id) ++{ ++ struct hmap tmp; ++ size_t i; ++ ++ hinic3_hmap_init(&tmp); ++ if (new_mask) { ++ tmp.buckets = hinic3_xmalloc(sizeof (*tmp.buckets) * (new_mask + 1), module_id); ++ if (tmp.buckets == NULL) { ++ HINIC3_LOG(ERR, AGENT, "malloc failed when resize."); ++ goto err; ++ } ++ tmp.mask = new_mask; ++ for (i = 0; i <= tmp.mask; i++) { ++ tmp.buckets[i] = NULL; ++ } ++ } ++ ++ for (i = 0; i <= hmap->mask; i++) { ++ struct hmap_node *node, *next; ++ for (node = hmap->buckets[i]; node; node = next) { ++ next = node->next; ++ hinic3_hmap_insert_fast(&tmp, node, node->hash); ++ } ++ } ++ hinic3_hmap_swap(hmap, &tmp); ++err: ++ hinic3_hmap_destroy(&tmp); ++} ++ ++static size_t hinic3_calc_mask(size_t capacity) ++{ ++ size_t mask = capacity / 0x2; ++ mask |= mask >> 0x1; ++ mask |= mask >> 0x2; ++ mask |= mask >> 0x4; ++ mask |= mask >> 0x8; ++ mask |= mask >> 0x10; ++ mask |= mask >> 0x20; ++ ++ mask |= (mask & 0x1) << 0x1; ++ ++ return mask; ++} ++ ++void hinic3_hmap_expand_at(struct hmap *hmap, const char *where, enum hinic3_module module_id) ++{ ++ size_t new_mask = hinic3_calc_mask(hmap->n); ++ if (new_mask > hmap->mask) { ++ hinic3_resize(hmap, new_mask, where, module_id); ++ } ++} ++ ++void hinic3_hmap_insert_at(struct hmap *hmap, struct hmap_node *node, size_t hash, ++ const char *where, enum hinic3_module module_id) ++{ ++ hinic3_hmap_insert_fast(hmap, node, hash); ++ if (hmap->n / 0x2 > hmap->mask) { ++ hinic3_hmap_expand_at(hmap, where, module_id); ++ } ++} ++ ++void hinic3_hmap_remove(struct hmap *hmap, struct hmap_node *node) ++{ ++ struct hmap_node **bucket = &hmap->buckets[node->hash & hmap->mask]; ++ while (*bucket != node) { ++ bucket = &(*bucket)->next; ++ } ++ *bucket = node->next; ++ hmap->n--; ++} ++ ++static inline struct hmap_node* hinic3_hmap_next_with_hash_(struct hmap_node *node, size_t hash) ++{ ++ while (node != NULL && node->hash != hash) { ++ node = node->next; ++ } ++ ++ return node; ++} ++ ++struct hmap_node* hinic3_hmap_first_with_hash(const struct hmap *hmap, size_t hash) ++{ ++ return hinic3_hmap_next_with_hash_(hmap->buckets[hash & hmap->mask], hash); ++} ++ ++struct hmap_node* hinic3_hmap_next_with_hash(const struct hmap_node *node) ++{ ++ return hinic3_hmap_next_with_hash_(node->next, node->hash); ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.h b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.h +new file mode 100644 +index 0000000..6675734 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.h +@@ -0,0 +1,58 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_HMAP_H_ ++#define _HINIC3_HMAP_H_ ++ ++#include ++#include ++#include "hinic3_map.h" /* 为了保持与ovs原生接口兼容,使用原生ovs软件hmap的数据结构定义 */ ++#include "hinic3_util.h" ++ ++#define HINIC3_HMAP_FOR_EACH(NODE, MEMBER, HMAP) \ ++ HINIC3_HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, (void) 0) ++ ++#define HINIC3_HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, ...) \ ++ for (HINIC3_CONTAINER_INIT(NODE, hinic3_hmap_first(HMAP), MEMBER); \ ++ ((NODE) != HINIC3_OBJECT_CONTAINING(NULL, (NODE), MEMBER)) \ ++ || (((NODE) = NULL), false); \ ++ HINIC3_CONTAINER_ASSIGN(NODE, hinic3_hmap_next(HMAP, &(NODE)->MEMBER), MEMBER)) ++ ++#define HINIC3_HMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HMAP) \ ++ for (HINIC3_CONTAINER_INIT(NODE, hinic3_hmap_first_with_hash(HMAP, HASH), MEMBER); \ ++ (NODE != HINIC3_OBJECT_CONTAINING(NULL, (NODE), MEMBER)) \ ++ || (((NODE) = NULL), false); \ ++ HINIC3_CONTAINER_ASSIGN(NODE, hinic3_hmap_next_with_hash(&(NODE)->MEMBER), MEMBER)) ++ ++#define HINIC3_HMAP_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HMAP) \ ++ HINIC3_HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, (void) 0) ++ ++#define HINIC3_HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, ...) \ ++ for (HINIC3_CONTAINER_INIT(NODE, hinic3_hmap_first(HMAP), MEMBER); \ ++ ((NODE != HINIC3_OBJECT_CONTAINING(NULL, (NODE), MEMBER)) \ ++ || ((NODE = NULL), false) \ ++ ? HINIC3_CONTAINER_INIT(NEXT, hinic3_hmap_next(HMAP, &(NODE)->MEMBER), MEMBER), 1 : 0); \ ++ (NODE) = (NEXT)) ++ ++void hinic3_hmap_clear(struct hmap *hamp); ++void hinic3_hmap_init(struct hmap *); ++void hinic3_hmap_destroy(struct hmap *); ++bool hinic3_hmap_is_empty(const struct hmap *hmap); ++size_t hinic3_hmap_count(const struct hmap *hmap); ++struct hmap_node* hinic3_hmap_first(const struct hmap *hmap); ++struct hmap_node* hinic3_hmap_next(const struct hmap *hmap, const struct hmap_node *node); ++void hinic3_hmap_insert_at(struct hmap *, struct hmap_node *, size_t hash, const char *where, ++ enum hinic3_module module_id); ++void hinic3_hmap_remove(struct hmap *, struct hmap_node *); ++void hinic3_hmap_swap(struct hmap *a, struct hmap *b); ++void hinic3_hmap_moved(struct hmap *hmap); ++struct hmap_node* hinic3_hmap_first_with_hash(const struct hmap *hmap, size_t hash); ++struct hmap_node* hinic3_hmap_next_with_hash(const struct hmap_node *node); ++ ++static inline void hinic3_hmap_insert(struct hmap *hmap, ++ struct hmap_node *node, size_t hash, enum hinic3_module module_id) ++{ ++ hinic3_hmap_insert_at(hmap, node, hash, HINIC3_SOURCE_LOCATOR, module_id); ++} ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c +new file mode 100644 +index 0000000..8a08d5d +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c +@@ -0,0 +1,528 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_log.h" ++ ++#include ++#include ++#include "hinic3_util.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_command.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_parse_agent_config.h" ++#include "rte_log.h" ++ ++#define SET_LOG_HELP_ARG_NUM 2 ++#define SET_LOG_MODULE_ARG_NUM 5 ++#define HINIC3_LOG_MSG_TOKENS (60 * 1000) ++#define HINIC3_LOG_RATE_TOKENS 60 ++#define HINIC3_LOG_BURST_TOKENS 1000 ++#define TOKEN_BUCKET_INIT(RATE, BURST) { RATE, BURST, 0, LLONG_MIN } ++#define SHOW_MAX_NAME_ONE_LINE 4 ++#define HINIC3_MODULE_NAME_MAX_LEN 30 ++#define ARGC_ADD_DOUBLE 2 ++ ++#define HINIC3_SAT_MUL(X, Y) \ ++ ((Y) == 0 ? 0 \ ++ : (X) <= UINT_MAX / (Y) ? (unsigned int) (X) * (unsigned int) (Y) \ ++ : UINT_MAX) ++ ++#define HINIC3_LOG_RATE_LIMIT_INIT(RATE, BURST) \ ++ { \ ++ TOKEN_BUCKET_INIT(RATE, HINIC3_SAT_MUL(BURST, HINIC3_LOG_MSG_TOKENS)), \ ++ 0, /* first_dropped */ \ ++ 0, /* last_dropped */ \ ++ 0, /* n_dropped */ \ ++ HINIC3_MUTEX_INITIALIZER /* mutex */ \ ++ } ++ ++enum hinic3_log_level { ++ HINIC3_LOG_ALERT_LEVEL = 1, ++ HINIC3_LOG_CRITICAL_LEVEL, ++ HINIC3_LOG_ERR_LEVEL, ++ HINIC3_LOG_WARNING_LEVEL, ++ HINIC3_LOG_NOTICE_LEVEL, ++ HINIC3_LOG_INFO_LEVEL, ++ HINIC3_LOG_DEBUG_LEVEL, ++ HINIC3_LOG_MAX_LEVEL, ++}; ++ ++static struct hinic3_log_module g_hinic3_log_module_list[] = { ++ {"hinic3-agent", HINIC3_LOG_TYPE_UP, HINIC3_LOG_AGENT, RTE_LOG_INFO}, ++ {"hinic3-vport", HINIC3_LOG_TYPE_UP, HINIC3_LOG_VPORT, RTE_LOG_INFO}, ++ {"hinic3-bond", HINIC3_LOG_TYPE_UP, HINIC3_LOG_BOND, RTE_LOG_INFO}, ++ {"hinic3-flow", HINIC3_LOG_TYPE_UP, HINIC3_LOG_FLOW, RTE_LOG_INFO}, ++ {"hinic3-bum", HINIC3_LOG_TYPE_UP, HINIC3_LOG_BUM, RTE_LOG_INFO}, ++ {"hinic3-qos", HINIC3_LOG_TYPE_UP, HINIC3_LOG_QOS, RTE_LOG_INFO}, ++ {"hinic3-packet", HINIC3_LOG_TYPE_UP, HINIC3_LOG_PACKET, RTE_LOG_INFO}, ++ {"hinic3-driver-vport", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_VPORT, RTE_LOG_INFO}, ++ {"hinic3-driver-bond", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_BOND, RTE_LOG_INFO}, ++ {"hinic3-driver-flow", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_FLOW, RTE_LOG_INFO}, ++ {"hinic3-driver-bum", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_BUM, RTE_LOG_INFO}, ++ {"hinic3-driver-qos", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_QOS, RTE_LOG_INFO}, ++ {"hinic3-driver-chip", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_CHIP, RTE_LOG_INFO}, ++ {"hinic3-driver-packet", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_PACKET, RTE_LOG_INFO}, ++ {"hinic3-offload-policy", HINIC3_LOG_TYPE_UP, HINIC3_LOG_POLICY, RTE_LOG_INFO} ++}; ++ ++static struct hinic3_log_level_map g_hinic3_log_level_map[] = { ++ {0, 0, "disabled"}, ++ {RTE_LOG_EMERG, HINIC3_LOG_ALERT_LEVEL, "emergency"}, ++ {RTE_LOG_ALERT, HINIC3_LOG_ALERT_LEVEL, "alert"}, ++ {RTE_LOG_CRIT, HINIC3_LOG_CRITICAL_LEVEL, "critical"}, ++ {RTE_LOG_ERR, HINIC3_LOG_ERR_LEVEL, "error"}, ++ {RTE_LOG_WARNING, HINIC3_LOG_WARNING_LEVEL, "warning"}, ++ {RTE_LOG_NOTICE, HINIC3_LOG_NOTICE_LEVEL, "notice"}, ++ {RTE_LOG_INFO, HINIC3_LOG_INFO_LEVEL, "info"}, ++ {RTE_LOG_DEBUG, HINIC3_LOG_DEBUG_LEVEL, "debug"}, ++}; ++ ++static int g_hinic3_log_module_dpdk_id[HINIC3_LOG_MAX]; ++static int g_hinic3_driver_log_module_dpdk_id[HINIC3_DRIVER_LOG_MAX]; ++struct set_log_level_input_key g_set_log_level_input_key = { 0 }; ++ ++int hinic3_log_init(void) ++{ ++ size_t i; ++ int ret; ++ int log_id; ++ struct hinic3_log_module *module = NULL; ++ ++ for (i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); i++) { ++ module = &g_hinic3_log_module_list[i]; ++ if (module->type == HINIC3_LOG_TYPE_DRIVER) { ++ continue; ++ } ++ log_id = rte_log_register(module->name); ++ if (log_id < 0) { ++ return -1; ++ } ++ ++ if (module->type == HINIC3_LOG_TYPE_UP) { ++ g_hinic3_log_module_dpdk_id[module->index] = log_id; ++ } ++ ++ /* set default level */ ++ ret = rte_log_set_level(log_id, module->def_level); ++ if (ret < 0) { ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++int hinic3_driver_log_init(void) ++{ ++ size_t i; ++ int ret; ++ int log_id; ++ int driver_level; ++ struct hinic3_log_module *module = NULL; ++ ++ for (i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); i++) { ++ module = &g_hinic3_log_module_list[i]; ++ if (module->type == HINIC3_LOG_TYPE_UP) { ++ continue; ++ } ++ log_id = rte_log_register(module->name); ++ if (log_id < 0) { ++ return -1; ++ } ++ ++ if (module->type == HINIC3_LOG_TYPE_DRIVER) { ++ g_hinic3_driver_log_module_dpdk_id[module->index] = log_id; ++ } ++ ++ /* set default level */ ++ ret = rte_log_set_level(log_id, module->def_level); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ ret = hinic3_global_open_log(module->index, 1); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "open driver log fail, module is %s, ret is %d", module->name, ret); ++ return -1; ++ } ++ ++ driver_level = g_hinic3_log_level_map[module->def_level].hinic3_level; ++ ret = hinic3_global_set_log_level(module->index, driver_level); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "set driver log level fail, module is %s, ret is %d", module->name, ret); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++int hinic3_set_module_log_level(struct set_log_level_input_key *g_input_key) ++{ ++ char *module = g_input_key->module_name; ++ int level = g_input_key->log_level; ++ ++ size_t i; ++ int ret; ++ int driver_level; ++ int module_dpdk_id; ++ struct hinic3_log_module *module_ins = NULL; ++ ++ if (module == NULL) { ++ return -1; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); ++i) { ++ if (strcmp(module, g_hinic3_log_module_list[i].name) == 0) { ++ module_ins = &g_hinic3_log_module_list[i]; ++ break; ++ } ++ } ++ ++ if (module_ins == NULL) { ++ HINIC3_LOG(ERR, AGENT, "invalid log module."); ++ return -1; ++ } ++ ++ if (level > RTE_LOG_DEBUG) { ++ HINIC3_LOG(ERR, AGENT, "invalid log level is %d", level); ++ return -1; ++ } ++ ++ if (module_ins->type == HINIC3_LOG_TYPE_UP) { ++ module_dpdk_id = g_hinic3_log_module_dpdk_id[module_ins->index]; ++ } else { ++ module_dpdk_id = g_hinic3_driver_log_module_dpdk_id[module_ins->index]; ++ } ++ ++ ret = rte_log_set_level(module_dpdk_id, level); ++ if (ret < 0) { ++ HINIC3_LOG(ERR, AGENT, "set level failed ,ret is %d", ret); ++ return -1; ++ } ++ ++ if (module_ins->type == HINIC3_LOG_TYPE_UP) { ++ module_ins->def_level = level; ++ return 0; ++ } ++ ++ driver_level = g_hinic3_log_level_map[level].hinic3_level; ++ ret = hinic3_global_set_log_level(module_ins->index, driver_level); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "set driver log level fail, module is %s, ret is %d", module_ins->name, ret); ++ return -1; ++ } ++ module_ins->def_level = level; ++ HINIC3_LOG(INFO, AGENT, "set log level, module is %s, level is %d\n", module_ins->name, level); ++ return 0; ++} ++ ++uint32_t hinic3_get_log_module_dpdk_id(enum hinic3_log_module_index module_idx) ++{ ++ uint32_t result = 0; ++ ++ if (module_idx < HINIC3_LOG_MAX) { ++ result = g_hinic3_log_module_dpdk_id[module_idx]; ++ } ++ ++ return result; ++} ++ ++const char *hinic3_get_log_module_prefix(void) ++{ ++ return hinic3_log_prefix_get(); ++} ++static struct hinic3_log_module *hinic3_get_log_module_name(const char *module_name) ++{ ++ struct hinic3_log_module *module = NULL; ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); ++i) { ++ if (strcmp(g_hinic3_log_module_list[i].name, module_name) == 0) { ++ module = &g_hinic3_log_module_list[i]; ++ break; ++ } ++ } ++ return module; ++} ++ ++static int hinic3_get_log_level_from_name(const char *level_name) ++{ ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_log_level_map); ++i) { ++ if (strcmp(level_name, g_hinic3_log_level_map[i].level_name) == 0) { ++ return g_hinic3_log_level_map[i].dpdk_level; ++ } ++ } ++ return -1; ++} ++ ++static int hinic3_set_log_level_help_info(struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%2sUsage: dpak-ovs-ctl hwoff/set-log-level { -m -l | " ++ "{ -h | --help } }\n\n", HINIC3_UI_INDENT_SPACE); ++ ++ hinic3_ds_put_format(ds, "%2sOptions list:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4s-m Module name\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4s-l Log level\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4s-h, --help Display the help information\n\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%2sSupported modules:", HINIC3_UI_INDENT_SPACE); ++ ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); ++i) { ++ if (i % SHOW_MAX_NAME_ONE_LINE == 0) { ++ hinic3_ds_put_format(ds, "\n"); ++ hinic3_ds_put_format(ds, "%4s", HINIC3_UI_INDENT_SPACE); ++ } ++ hinic3_ds_put_format(ds, "%-36s", g_hinic3_log_module_list[i].name); ++ } ++ hinic3_ds_put_format(ds, "\n\n"); ++ hinic3_ds_put_format(ds, "%2sSupported levels:", HINIC3_UI_INDENT_SPACE); ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_log_level_map); ++i) { ++ if (i % SHOW_MAX_NAME_ONE_LINE == 0) { ++ hinic3_ds_put_format(ds, "\n"); ++ hinic3_ds_put_format(ds, "%4s", HINIC3_UI_INDENT_SPACE); ++ } ++ hinic3_ds_put_format(ds, "%-36s", g_hinic3_log_level_map[i].level_name); ++ } ++ hinic3_ds_put_format(ds, "\n"); ++ return 0; ++} ++ ++static void hinic3_show_log_list(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[], ++ void *aux) ++{ ++ size_t i; ++ uint32_t level; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ for (i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); i++) { ++ level = g_hinic3_log_module_list[i].def_level; ++ char module_name[HINIC3_MODULE_NAME_MAX_LEN] = {0}; ++ int ret = snprintf(module_name, sizeof(module_name), "%s:", g_hinic3_log_module_list[i].name); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "snprintf_s for module_name failed."); ++ return; ++ } ++ hinic3_ds_put_format(&ds, "%2s%-25s%s\n", HINIC3_UI_INDENT_SPACE, module_name, ++ g_hinic3_log_level_map[level].level_name); ++ } ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} ++ ++static int hinic3_key_module_name_parse(char *value, struct ds *ds) ++{ ++ struct hinic3_log_module *module = NULL; ++ module = hinic3_get_log_module_name(value); ++ if (!module) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Unknown module name: %s.\n", value); ++ return -1; ++ } ++ g_set_log_level_input_key.module_name = value; ++ return 0; ++} ++ ++static int hinic3_key_log_level_parse(char *value, struct ds *ds) ++{ ++ int log_level; ++ log_level = hinic3_get_log_level_from_name(value); ++ if (log_level == -1) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid log level: %s.\n", value); ++ return -1; ++ } ++ g_set_log_level_input_key.log_level = log_level; ++ return 0; ++} ++static struct set_log_level_sub_key_parser g_input_key_parser[] = { ++ {"-m", sizeof("-m"), hinic3_key_module_name_parse}, ++ {"-l", sizeof("-l"), hinic3_key_log_level_parse}, ++}; ++static int hinic3_set_log_level_sub_key_parse(struct unixctl_conn *conn, const char *key_name, ++ char *value, struct ds *ds) ++{ ++ size_t i = 0; ++ int ret = 0; ++ set_log_level_sub_key_parse_func func = NULL; ++ for (i = 0; i < ARRAY_SIZE(g_input_key_parser); i++) { ++ struct set_log_level_sub_key_parser *item = &g_input_key_parser[i]; ++ if (strcmp(key_name, item->key_name) == 0) { ++ func = item->func; ++ break; ++ } ++ } ++ ++ if (!func) { ++ hinic3_ds_put_format(ds, "%sIllegal parameter %s, input -h for help.\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ ret = func(value, ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "Parse %s failed!\n", key_name); ++ return -1; ++ } ++ return ret; ++} ++ ++static int hinic3_set_log_level_input_key_parse(struct unixctl_conn *conn, int argc, const char *argv[], struct ds *ds) ++{ ++ int ret; ++ int work_argc = argc; ++ if (work_argc != SET_LOG_MODULE_ARG_NUM) { ++ HINIC3_LOG(ERR, AGENT, "arameters num error.\n"); ++ hinic3_ds_put_format(ds, "%sIllegal parameter, input -h for help.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ int i = 1; ++ const char **work_argv = argv; ++ ++ while (i < work_argc) { ++ ret = hinic3_set_log_level_sub_key_parse(conn, (char *)work_argv[i], (char *)work_argv[i + 1], ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "key_parse error\n"); ++ return -1; ++ } ++ i += ARGC_ADD_DOUBLE; ++ } ++ ++ return 0; ++} ++ ++static void hinic3_set_log_level(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ if ((argc == SET_LOG_HELP_ARG_NUM && (strcmp("-h", ++ argv[SET_LOG_HELP_ARG_NUM - 1 ]) == 0 || strcmp("--help", argv[SET_LOG_HELP_ARG_NUM - 1]) == 0))) { ++ hinic3_set_log_level_help_info(&ds); ++ } else { ++ ret = hinic3_set_log_level_input_key_parse(conn, argc, argv, &ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "key parse failed\n"); ++ goto err_out; ++ } ++ ret = hinic3_set_module_log_level(&g_set_log_level_input_key); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Failed to set log level for module: %s.\n.", ++ argv[2]); ++ goto err_out; ++ } ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_INFO "Successfully set log level to %s for module %s.\n", ++ argv[4], argv[2]); ++ } ++ ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++ ++err_out: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++} ++ ++void unixctl_hinic3_cmd_log_register(void) ++{ ++ hinic3_command_register("hwoff/show-log-list", "", 0, 0, hinic3_show_log_list, NULL); ++ hinic3_command_register("hwoff/set-log-level", "{ -m -l | { -h | --help } }", ++ 1, SET_LOG_MODULE_ARG_NUM, hinic3_set_log_level, NULL); ++} ++ ++static inline unsigned int hinic3_sat_mul(unsigned int x, unsigned int y) ++{ ++ return HINIC3_SAT_MUL(x, y); ++} ++ ++static inline unsigned int hinic3_sat_add(unsigned int x, unsigned int y) ++{ ++ return x + y >= x ? x + y : UINT_MAX; ++} ++ ++static bool token_bucket_withdraw(struct token_bucket *tb, unsigned int n) ++{ ++ if (tb->tokens < n) { ++ long long int now = hinic3_time_msec(); ++ if (now > tb->last_fill) { ++ unsigned long long int elapsed_ull ++ = (unsigned long long int) now - tb->last_fill; ++ unsigned int elapsed = MIN(UINT_MAX, elapsed_ull); ++ unsigned int add = hinic3_sat_mul(tb->rate, elapsed); ++ unsigned int tokens = hinic3_sat_add(tb->tokens, add); ++ tb->tokens = MIN(tokens, tb->burst); ++ tb->last_fill = now; ++ } ++ ++ if (tb->tokens < n) { ++ return false; ++ } ++ } ++ ++ tb->tokens -= n; ++ return true; ++} ++ ++bool hinic3_log_is_enabled(uint32_t level, uint32_t logtype) ++{ ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); ++i) { ++ if (logtype == g_hinic3_log_module_list[i].index) { ++ return level >= g_hinic3_log_module_list[i].type; ++ } ++ } ++ return false; ++} ++ ++static bool hinic3_log_should_drop(uint32_t level, uint32_t logtype, struct vlog_rate_limit *rl) ++{ ++ if (!hinic3_log_is_enabled(level, logtype)) { ++ return true; ++ } ++ ++ hinic3_pthread_mutex_lock(&rl->mutex); ++ if (!token_bucket_withdraw(&rl->token_bucket, HINIC3_LOG_MSG_TOKENS)) { ++ long long int now = hinic3_time_sec(); ++ if (!rl->n_dropped) { ++ rl->first_dropped = now; ++ } ++ rl->last_dropped = now; ++ rl->n_dropped++; ++ hinic3_pthread_mutex_unlock(&rl->mutex); ++ return true; ++ } ++ ++ if (!rl->n_dropped) { ++ hinic3_pthread_mutex_unlock(&rl->mutex); ++ } else { ++ long long int now = hinic3_time_sec(); ++ unsigned int n_dropped = rl->n_dropped; ++ long long int first_dropped_elapsed = now - rl->first_dropped; ++ long long int last_dropped_elapsed = now - rl->last_dropped; ++ uint32_t dpdk_log_type = hinic3_get_log_module_dpdk_id(logtype); ++ rl->n_dropped = 0; ++ hinic3_pthread_mutex_unlock(&rl->mutex); ++ ++ rte_log(level, dpdk_log_type, ++ "[%s] Hinic3 dropped %u log messages in last %lld seconds (most recently, " ++ "%lld seconds ago) due to excessive rate", ++ hinic3_get_log_module_prefix(), n_dropped, first_dropped_elapsed, last_dropped_elapsed); ++ } ++ ++ return false; ++} ++ ++int hinic3_log_limit(uint32_t level, uint32_t logtype, const char *format, ...) ++{ ++ int ret = 0; ++ static struct vlog_rate_limit rl = HINIC3_LOG_RATE_LIMIT_INIT(HINIC3_LOG_RATE_TOKENS, HINIC3_LOG_BURST_TOKENS); ++ if (!hinic3_log_should_drop(level, logtype, &rl)) { ++ uint32_t dpdk_log_type = hinic3_get_log_module_dpdk_id(logtype); ++ va_list ap; ++ va_start(ap, format); ++ ++ ret = rte_vlog(level, dpdk_log_type, format, ap); ++ va_end(ap); ++ } ++ ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h +new file mode 100644 +index 0000000..b24b707 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h +@@ -0,0 +1,112 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_LOG_H ++#define HINIC3_LOG_H ++ ++#include ++#include "hinic3_mutex.h" ++#include "rte_log.h" ++#include "hinic3_ds.h" ++ ++#define HINIC3_MAX_LOG_NAME 16 ++ ++#define HINIC3_DEFAULT_MAJOR_VERSION_STRING "(null)" ++#define HINIC3_DEFAULT_SUB_VERSION_STRING "(null)" ++ ++#ifdef BUILD_MAJOR_VERSION ++#define HINIC3_BUILD_MAJOR_VERSION BUILD_MAJOR_VERSION ++#else ++#define HINIC3_BUILD_MAJOR_VERSION HINIC3_DEFAULT_MAJOR_VERSION_STRING ++#endif ++ ++#ifdef BUILD_SUB_VERSION ++#define HINIC3_BUILD_SUB_VERSION BUILD_SUB_VERSION ++#else ++#define HINIC3_BUILD_SUB_VERSION HINIC3_DEFAULT_SUB_VERSION_STRING ++#endif ++ ++enum hinic3_log_module_index { ++ HINIC3_LOG_AGENT = 0, ++ HINIC3_LOG_VPORT, ++ HINIC3_LOG_BOND, ++ HINIC3_LOG_FLOW, ++ HINIC3_LOG_BUM, ++ HINIC3_LOG_QOS, ++ HINIC3_LOG_PACKET, ++ HINIC3_LOG_POLICY, ++ HINIC3_LOG_MAX, ++}; ++ ++enum hinic3_driver_log_module_index { ++ HINIC3_DRIVER_LOG_VPORT = 1, ++ HINIC3_DRIVER_LOG_BOND, ++ HINIC3_DRIVER_LOG_FLOW, ++ HINIC3_DRIVER_LOG_BUM, ++ HINIC3_DRIVER_LOG_QOS, ++ HINIC3_DRIVER_LOG_CHIP, ++ HINIC3_DRIVER_LOG_PACKET, ++ HINIC3_DRIVER_LOG_MAX, ++}; ++ ++enum hinic3_log_type_e { ++ HINIC3_LOG_TYPE_UP, ++ HINIC3_LOG_TYPE_DRIVER, ++}; ++ ++struct set_log_level_input_key { ++ char *module_name; ++ int log_level; ++}; ++ ++typedef int (*set_log_level_sub_key_parse_func)(char *value, struct ds *ds); ++ ++struct set_log_level_sub_key_parser { ++ const char *key_name; ++ size_t key_len; ++ set_log_level_sub_key_parse_func func; ++}; ++ ++struct hinic3_log_module { ++ char *name; ++ int type; ++ int index; ++ int def_level; ++}; ++ ++struct token_bucket { ++ unsigned int rate; ++ unsigned int burst; ++ unsigned int tokens; ++ long long int last_fill; ++}; ++ ++struct vlog_rate_limit { ++ struct token_bucket token_bucket; ++ long long int first_dropped; ++ long long int last_dropped; ++ unsigned int n_dropped; ++ struct hinic3_mutex mutex; ++}; ++ ++struct hinic3_log_level_map { ++ int dpdk_level; ++ int hinic3_level; ++ char level_name[HINIC3_MAX_LOG_NAME]; ++}; ++ ++int hinic3_log_init(void); ++int hinic3_driver_log_init(void); ++/* level 0 will close the module log */ ++int hinic3_set_module_log_level(struct set_log_level_input_key *g_input_key); ++uint32_t hinic3_get_log_module_dpdk_id(enum hinic3_log_module_index module_idx); ++const char *hinic3_get_log_module_prefix(void); ++void unixctl_hinic3_cmd_log_register(void); ++long long int hinic3_time_msec(void); ++int hinic3_log_limit(uint32_t level, uint32_t logtype, const char *format, ...); ++ ++#define HINIC3_LOG(l, t, format, ...) \ ++ hinic3_log_limit(RTE_LOG_ ## l, HINIC3_LOG_ ## t, "[%s]" # t ": " format, \ ++ hinic3_get_log_module_prefix(), ## __VA_ARGS__) ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c +new file mode 100644 +index 0000000..eda2279 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c +@@ -0,0 +1,371 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ds.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_mpool.h" ++ ++static uint32_t dpak_mp_align_up(uint32_t size) ++{ ++ /* Aligin to sizeof uint64_t */ ++ return (size + sizeof(uint64_t) - 1) & (~(sizeof(uint64_t) - 1)); ++} ++ ++static inline int dpak_mp_lock(struct dpak_mempool *mp) ++{ ++ return pthread_mutex_lock(&mp->lock); ++} ++ ++static inline int dpak_mp_unlock(struct dpak_mempool *mp) ++{ ++ return pthread_mutex_unlock(&mp->lock); ++} ++ ++/* 头删除 */ ++static void dpak_mp_list_delete(struct dpak_mp_chunk **head, struct dpak_mp_chunk *ck) ++{ ++ if (HINIC3_UNLIKELY((*head == NULL) || (ck == NULL))) { ++ return; ++ } ++ *head = ck->next; ++} ++ ++/* 头插入 */ ++static inline void dpak_mp_list_insert(struct dpak_mp_chunk **head, struct dpak_mp_chunk *ck) ++{ ++ if (HINIC3_UNLIKELY(ck == NULL)) { ++ return; ++ } ++ ck->next = *head; ++ *head = ck; ++} ++ ++static int dpak_mp_insert_blocks(struct dpak_mempool *mp, uint32_t need_size, uint32_t ele_count, ++ enum hinic3_module module_id) ++{ ++ struct dpak_mp_block *blk_head = (struct dpak_mp_block *)hinic3_calloc(1, sizeof(struct dpak_mp_block), module_id); ++ if (blk_head == NULL) { ++ return -1; ++ } ++ ++ if ((ele_count == 0) || (need_size == 0)) { ++ HINIC3_LOG(ERR, FLOW, "block alloc size is invalid"); ++ hinic3_free(blk_head); ++ return -1; ++ } ++ ++ blk_head->virt_start = (char *)hinic3_calloc(ele_count, need_size, module_id); ++ if (blk_head->virt_start == NULL) { ++ hinic3_free(blk_head); ++ return -1; ++ } ++ ++ blk_head->next = mp->blk_list; ++ mp->blk_list = blk_head; ++ mp->ele_total_count += ele_count; ++ mp->block_num += 1; ++ blk_head->free_count = ele_count; ++ blk_head->alloc_count = 0; ++ ++ for (uint32_t i = 0; i < ele_count; i++) { ++ struct dpak_mp_chunk *tmp = (struct dpak_mp_chunk *)(blk_head->virt_start + need_size * i); ++ dpak_mp_list_insert(&blk_head->free_list, tmp); ++ } ++ return 0; ++} ++ ++static int dpak_mempool_create(struct dpak_mempool *mp, uint32_t ele_size, uint32_t ele_count, ++ enum hinic3_module module_id) ++{ ++ int ret; ++ ++ if (ele_size == 0) { ++ HINIC3_LOG(ERR, FLOW, "Memory pool size can not be %u, mempool create failed", ele_size); ++ return -1; ++ } ++ ++ uint32_t need_size = dpak_mp_align_up(ele_size + MP_CK_HEADER_LEN); ++ ret = dpak_mp_insert_blocks(mp, need_size, ele_count, module_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "init block failed"); ++ return ret; ++ } ++ ++ mp->ele_size = ele_size; ++ mp->ele_need_size = need_size; ++ mp->per_block_ele_count = ele_count; ++ ret = pthread_mutex_init(&mp->lock, NULL); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "init lock failed. errno is %d", ret); ++ return ret; ++ } ++ mp->is_valid = true; ++ return 0; ++} ++ ++static void *dpak_mp_alloc_mem_from_block(struct dpak_mp_block *blk, uint64_t size) ++{ ++ struct dpak_mp_chunk *allocated = NULL; ++ char *alloc = NULL; ++ ++ allocated = blk->free_list; ++ if (HINIC3_UNLIKELY(allocated == NULL)) { ++ return NULL; ++ } ++ ++ dpak_mp_list_delete(&blk->free_list, allocated); ++ blk->free_count--; ++ blk->alloc_count++; ++ alloc = (char *)allocated + MP_CK_HEADER_LEN; ++ return alloc; ++} ++ ++static void *dpak_mp_alloc_mem_from_blocks(struct dpak_mempool *mp, uint32_t need_size, enum hinic3_module module_id) ++{ ++ struct dpak_mp_block *blk = mp->blk_list; ++ void *alloc = NULL; ++ ++ while (blk != NULL) { ++ if (blk->free_count == 0) { ++ blk = blk->next; ++ continue; ++ } ++ ++ alloc = dpak_mp_alloc_mem_from_block(blk, need_size); ++ if (HINIC3_LIKELY(alloc != NULL)) { ++ mp->ele_used_count++; ++ return alloc; ++ } ++ blk = blk->next; ++ } ++ ++ HINIC3_LOG(WARNING, FLOW, "mempool of ele_size %u no enough memory, start alloc new block", need_size); ++ (void)dpak_mp_insert_blocks(mp, need_size, mp->per_block_ele_count, module_id); ++ return NULL; ++} ++ ++static struct dpak_mp_block *dpak_mp_find_block(struct dpak_mempool *mp, void *p) ++{ ++ struct dpak_mp_block *blk = mp->blk_list; ++ uint32_t need_size = mp->ele_need_size; ++ ++ while (blk != NULL) { ++ if ((blk->virt_start <= (char *)p) && ((blk->virt_start + mp->per_block_ele_count * need_size) > (char *)p)) { ++ break; ++ } ++ blk = blk->next; ++ } ++ ++ return blk; ++} ++ ++static void dpak_mp_free_blk_heads(struct dpak_mp_block *blk) ++{ ++ struct dpak_mp_block *blk_head = blk; ++ struct dpak_mp_block *blk_cur_node = NULL; ++ ++ while (blk_head != NULL) { ++ blk_cur_node = blk_head; ++ blk_head = blk_head->next; ++ hinic3_free(blk_cur_node->virt_start); ++ hinic3_free(blk_cur_node); ++ blk_cur_node = NULL; ++ } ++} ++ ++int dpak_mempool_flush(struct dpak_mempool *mp) ++{ ++ int ret; ++ ++ if (mp == NULL) { ++ HINIC3_LOG(ERR, FLOW, "mempool is null."); ++ return -1; ++ } ++ ++ uint32_t need_size = mp->ele_need_size; ++ uint32_t ele_count = mp->per_block_ele_count; ++ struct dpak_mp_block *blk = mp->blk_list; ++ struct dpak_mp_chunk *mp_chunk_start = NULL; ++ ++ ret = dpak_mp_lock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp flush locked failed. errno is %d", ret); ++ return -1; ++ } ++ ++ while (blk != NULL) { ++ blk->free_list = NULL; ++ memset(blk->virt_start, 0, need_size * ele_count); ++ for (uint32_t i = 0; i < ele_count; i++) { ++ mp_chunk_start = (struct dpak_mp_chunk *)(blk->virt_start + need_size * i); ++ dpak_mp_list_insert(&blk->free_list, mp_chunk_start); ++ } ++ blk->free_count = ele_count; ++ blk->alloc_count = 0; ++ blk = blk->next; ++ } ++ mp->ele_used_count = 0; ++ ++ ret = dpak_mp_unlock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp flush unlocked failed. errno is %d", ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void dpak_mempool_destroy(struct dpak_mempool *mp) ++{ ++ int ret; ++ if (mp == NULL) { ++ HINIC3_LOG(ERR, FLOW, "destory mpool is null"); ++ return; ++ } ++ ++ ret = dpak_mp_lock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp locked failed. errno is %d", ret); ++ return; ++ } ++ dpak_mp_free_blk_heads(mp->blk_list); ++ ret = dpak_mp_unlock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp unlocked failed. errno is %d", ret); ++ return; ++ } ++ ret = pthread_mutex_destroy(&mp->lock); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp lock destroy failed. errno is %d", ret); ++ return; ++ } ++ hinic3_free(mp); ++} ++ ++void *dpak_mempool_alloc(struct dpak_mempool *mp, enum hinic3_module module_id) ++{ ++ int ret; ++ void *alloc = NULL; ++ if (HINIC3_UNLIKELY((mp == NULL) || (mp->blk_list == NULL) || (mp->block_num == 0))) { ++ HINIC3_LOG(ERR, FLOW, "mempool is null"); ++ return NULL; ++ } ++ ++ ret = dpak_mp_lock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp lock failed. errno is %d", ret); ++ return NULL; ++ } ++ alloc = dpak_mp_alloc_mem_from_blocks(mp, mp->ele_need_size, module_id); ++ if (HINIC3_UNLIKELY(alloc == NULL)) { ++ /* 此处为支持block可动态扩张,如果一个block里边没有可用内存,则再申请一个 */ ++ alloc = dpak_mp_alloc_mem_from_blocks(mp, mp->ele_need_size, module_id); ++ } ++ ret = dpak_mp_unlock(mp); ++ if (ret != 0) { ++ dpak_mempool_free(mp, alloc); ++ HINIC3_LOG(ERR, FLOW, "mp unlock failed. errno is %d", ret); ++ return NULL; ++ } ++ return alloc; ++} ++ ++struct dpak_mempool *hinic3_create_single_mpool(const char *pool_name, uint32_t ele_size, uint32_t ele_num, ++ enum hinic3_module module_id) ++{ ++ if (pool_name == NULL) { ++ HINIC3_LOG(ERR, FLOW, "pool_name is NULL."); ++ return NULL; ++ } ++ struct dpak_mempool *pool = (struct dpak_mempool *)hinic3_calloc(1, sizeof(struct dpak_mempool), module_id); ++ if (pool == NULL) { ++ HINIC3_LOG(ERR, FLOW, "alloc mpool failed."); ++ return NULL; ++ } ++ ++ int ret = snprintf(pool->pool_name, sizeof(pool->pool_name), "%s", pool_name); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, FLOW, "snprintf_s %s for mpool name failed.", pool_name); ++ hinic3_free(pool); ++ return NULL; ++ } ++ ++ ret = dpak_mempool_create(pool, ele_size, ele_num, module_id); ++ if (ret != 0) { ++ dpak_mempool_destroy(pool); ++ return NULL; ++ } ++ return pool; ++} ++ ++void dpak_mempool_free(struct dpak_mempool *mp, void *ptr) ++{ ++ int ret; ++ if ((mp == NULL) || (ptr == NULL)) { ++ HINIC3_LOG(ERR, FLOW, "mpool is null or ptr is null"); ++ return; ++ } ++ ++ struct dpak_mp_block *blk = NULL; ++ struct dpak_mp_chunk *ck = NULL; ++ ++ ret = dpak_mp_lock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp lock failed. errno is %d", ret); ++ return; ++ } ++ blk = dpak_mp_find_block(mp, ptr); ++ if (HINIC3_UNLIKELY(blk == NULL)) { ++ HINIC3_LOG(WARNING, FLOW, "find block faied for free element"); ++ ret = dpak_mp_unlock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp unlock failed. errno is %d", ret); ++ } ++ return; ++ } ++ ++ ck = (struct dpak_mp_chunk *)((char *)ptr - MP_CK_HEADER_LEN); ++ dpak_mp_list_insert(&blk->free_list, ck); ++ blk->free_count++; ++ blk->alloc_count--; ++ mp->ele_used_count--; ++ ret = dpak_mp_unlock(mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "mp unlock failed. errno is %d", ret); ++ return; ++ } ++} ++ ++void hinic3_show_one_mpool(const struct dpak_mempool *mpool, struct ds *ds, bool is_end) ++{ ++ if ((mpool == NULL) || (mpool->is_valid != true) || ds == NULL) { ++ return; ++ } ++ ++ uint32_t need_size = mpool->ele_need_size; ++ hinic3_ds_put_format(ds, "%2smempool %s:\n", HINIC3_UI_INDENT_SPACE, mpool->pool_name); ++ hinic3_ds_put_format(ds, "%4selt-size(Byte): %u\n", HINIC3_UI_INDENT_SPACE, mpool->ele_size); ++ hinic3_ds_put_format(ds, "%4stotal-obj-size(Byte): %u\n", HINIC3_UI_INDENT_SPACE, need_size); ++ hinic3_ds_put_format(ds, "%4sblock-count: %u\n", HINIC3_UI_INDENT_SPACE, mpool->block_num); ++ hinic3_ds_put_format(ds, "%4sper-block-ele-num: %u\n", HINIC3_UI_INDENT_SPACE, mpool->per_block_ele_count); ++ hinic3_ds_put_format(ds, "%4sused-ele-count: %u \n", HINIC3_UI_INDENT_SPACE, mpool->ele_used_count); ++ hinic3_ds_put_format(ds, "%4stotal-ele-count: %u\n", HINIC3_UI_INDENT_SPACE, mpool->ele_total_count); ++ hinic3_ds_put_format(ds, "%4sTotal Memory(KByte): %u\n", HINIC3_UI_INDENT_SPACE, ++ mpool->ele_total_count * need_size / HINIC3_KB_TO_BYTE); ++ hinic3_ds_put_format(ds, "%4sUsed Memory(KByte): %u\n", HINIC3_UI_INDENT_SPACE, ++ mpool->ele_used_count * need_size / HINIC3_KB_TO_BYTE); ++ float mem_usage = mpool->ele_total_count == 0 ? ++ (float)0 : ++ (((float)mpool->ele_used_count) / ((float)mpool->ele_total_count) * HINIC3_PERCENTAGE); ++ hinic3_ds_put_format(ds, "%4sMemory usage(%%): %.2f\n", HINIC3_UI_INDENT_SPACE, mem_usage); ++ ++ if (!is_end) { ++ hinic3_ds_put_format(ds, "%s\n", HINIC3_UI_INDENT_SPACE); ++ } ++ return; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h +new file mode 100644 +index 0000000..ad40415 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_MPOOL_H ++#define HINIC3_MPOOL_H ++ ++#include ++#include "hinic3_mutex.h" ++#include "hinic3_ds.h" ++#include "hinic3_meminfo.h" ++ ++#define HINIC3_POOL_NAME_MAX_LEN 32 ++#define MP_CK_HEADER_LEN sizeof(struct dpak_mp_chunk) ++#define HINIC3_KB_TO_BYTE 1024 ++#define HINIC3_PERCENTAGE 100 ++ ++struct dpak_mp_chunk { ++ struct dpak_mp_chunk *next; ++}; ++ ++struct dpak_mp_block { ++ struct dpak_mp_chunk *free_list; ++ struct dpak_mp_block *next; ++ ++ /* The memory pool block's start virtual address */ ++ char *virt_start; ++ uint32_t free_count; ++ uint32_t alloc_count; ++}; ++ ++struct dpak_mempool { ++ char pool_name[HINIC3_POOL_NAME_MAX_LEN]; ++ uint32_t ele_size; ++ uint32_t ele_need_size; ++ uint32_t per_block_ele_count; ++ uint32_t ele_total_count; ++ uint32_t ele_used_count; ++ uint32_t block_num; ++ struct dpak_mp_block *blk_list; ++ pthread_mutex_t lock; ++ bool is_valid; ++}; ++ ++int dpak_mempool_flush(struct dpak_mempool *mp); ++void dpak_mempool_free(struct dpak_mempool *mp, void *ptr); ++void dpak_mempool_destroy(struct dpak_mempool *mp); ++struct dpak_mempool *hinic3_create_single_mpool(const char *pool_name, uint32_t ele_size, uint32_t ele_num, ++ enum hinic3_module module_id); ++void *dpak_mempool_alloc(struct dpak_mempool *mp, enum hinic3_module module_id); ++void hinic3_show_one_mpool(const struct dpak_mempool *mpool, struct ds *ds, bool is_end); ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c b/drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c +new file mode 100644 +index 0000000..ae5972d +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c +@@ -0,0 +1,210 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_mutex.h" ++ ++int hinic3_rwlock_init(struct hinic3_rwlock *lock) ++{ ++ int ret = pthread_rwlock_init(&lock->lock, NULL); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 rwlock init failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_rwlock_destroy(struct hinic3_rwlock *lock) ++{ ++ int ret = pthread_rwlock_destroy(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 rwlock destroy failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_rwlock_write_priority_init(struct hinic3_rwlock *lock) ++{ ++ int ret; ++ pthread_rwlockattr_t attr; ++ ret = pthread_rwlockattr_init(&attr); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "pthread rwlock init failed, ret is %d\n", ret); ++ return ret; ++ } ++ ret = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "pthread rwlock setkind failed, ret is %d\n", ret); ++ return ret; ++ } ++ ret = pthread_rwlock_init(&lock->lock, &attr); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 rwlock init failed"); ++ } ++ return ret; ++} ++ ++int hinic3_rwlock_rdlock(struct hinic3_rwlock *lock) ++{ ++ int ret = pthread_rwlock_rdlock(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 rwlock rdlock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_rwlock_rdunlock(struct hinic3_rwlock *lock) ++{ ++ int ret = pthread_rwlock_unlock(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 rdlock rdunlock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_rwlock_wrlock(struct hinic3_rwlock *lock) ++{ ++ int ret = pthread_rwlock_wrlock(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 rdlock wrlock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_rwlock_wrunlock(struct hinic3_rwlock *lock) ++{ ++ int ret = pthread_rwlock_unlock(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 rdlock wrUNlock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_rwlock_tryrdlock(struct hinic3_rwlock *lock) ++{ ++ return pthread_rwlock_tryrdlock(&lock->lock); ++} ++ ++int hinic3_mutex_cond_wait(pthread_cond_t *cond, const struct hinic3_mutex *mutex_) ++{ ++ struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); ++ int ret = pthread_cond_wait(cond, &mutex->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 cond wait failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_pthread_mutex_init(const struct hinic3_mutex *mutex_) ++{ ++ struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); ++ int ret = pthread_mutex_init(&mutex->lock, NULL); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 mutex init failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_pthread_mutex_lock(const struct hinic3_mutex *mutex_) ++{ ++ struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); ++ int ret = pthread_mutex_lock(&mutex->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 mutex lock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_pthread_mutex_unlock(const struct hinic3_mutex *mutex_) ++{ ++ struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); ++ int ret = pthread_mutex_unlock(&mutex->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 mutex unlock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_pthread_mutex_destroy(const struct hinic3_mutex *mutex_) ++{ ++ struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); ++ int ret = pthread_mutex_destroy(&mutex->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 mutex destroy failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++static bool hinic3_thread_once_start_(struct hinic3_thread_once *once) ++{ ++ if (hinic3_pthread_mutex_lock(&once->mutex) == 0) { ++ if (!once->done) { ++ (void)hinic3_pthread_mutex_unlock(&once->mutex); ++ return true; ++ } ++ (void)hinic3_pthread_mutex_unlock(&once->mutex); ++ } ++ return false; ++} ++ ++bool hinic3_thread_once_start(struct hinic3_thread_once *once) ++{ ++ return !once ->done && hinic3_thread_once_start_(once); ++} ++ ++void hinic3_thread_once_done(struct hinic3_thread_once *once) ++{ ++ if (hinic3_pthread_mutex_lock(&once->mutex) == 0) { ++ once->done = true; ++ (void)hinic3_pthread_mutex_unlock(&once->mutex); ++ } ++} ++ ++int hinic3_spinlock_init(struct hinic3_spinlock *lock, int pshared) ++{ ++ int ret = pthread_spin_init(&lock->lock, pshared); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 spinlock init failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_spinlock_destroy(struct hinic3_spinlock *lock) ++{ ++ int ret = pthread_spin_destroy(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 spinlock destroy failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_spinlock_lock(struct hinic3_spinlock *lock) ++{ ++ int ret = pthread_spin_lock(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 spinlock lock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_spinlock_trylock(struct hinic3_spinlock *lock) ++{ ++ int ret = pthread_spin_trylock(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 spinlock trylock failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_spinlock_unlock(struct hinic3_spinlock *lock) ++{ ++ int ret = pthread_spin_unlock(&lock->lock); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 spinlock unlock failed, ret is %d\n", ret); ++ } ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.c b/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.c +new file mode 100644 +index 0000000..4ca291f +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.c +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include "hinic3_eth_packets.h" ++#include "hinic3_log.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ds.h" ++#include "hinic3_packets.h" ++ ++void hinic3_ipv6_format_addr(const struct in6_addr *addr, struct ds *s) ++{ ++ char buf[INET6_ADDRSTRLEN]; ++ if (inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN) == NULL) { ++ HINIC3_LOG(ERR, AGENT, "inet ntop failed."); ++ } ++ hinic3_ds_put_format(s, "%s", buf); ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h b/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h +new file mode 100644 +index 0000000..0351ee9 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef __HINIC3_PACKETS_H__ ++#define __HINIC3_PACKETS_H__ ++ ++#include "hinic3_packets_types.h" ++#include "hinic3_meminfo.h" ++ ++void hinic3_ipv6_format_addr(const struct in6_addr *addr, struct ds *s); ++ ++static inline uint16_t hinic3_vlan_tci_to_vid(hinic3_be16 vlan_tci) ++{ ++ return (ntohs(vlan_tci) & VLAN_VID_MASK); ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c +new file mode 100644 +index 0000000..7716604 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c +@@ -0,0 +1,156 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include "hinic3_hash.h" ++#include "hinic3_string_util.h" ++#include "hinic3_util.h" ++#include "hinic3_hmap.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_shash.h" ++ ++static struct shash_node *hinic3_shash_find__(const struct shash*, ++ const char *name, size_t name_len, size_t hash); ++ ++static size_t hinic3_hash_name(const char *name) ++{ ++ return hinic3_hash_string(name, 0); ++} ++ ++void hinic3_shash_init(struct shash *sh) ++{ ++ hinic3_hmap_init(&sh->map); ++} ++ ++void hinic3_shash_clear(struct shash *sh) ++{ ++ struct shash_node *node, *next; ++ ++ HINIC3_SHASH_FOR_EACH_SAFE (node, next, sh) { ++ hinic3_hmap_remove(&sh->map, &node->node); ++ hinic3_free(node->name); ++ hinic3_free(node); ++ } ++} ++ ++void hinic3_shash_destroy(struct shash *sh) ++{ ++ if (sh) { ++ hinic3_shash_clear(sh); ++ hinic3_hmap_destroy(&sh->map); ++ } ++} ++ ++void hinic3_shash_destroy_free_data(struct shash *sh) ++{ ++ if (sh) { ++ hinic3_shash_clear_free_data(sh); ++ hinic3_hmap_destroy(&sh->map); ++ } ++} ++ ++void hinic3_shash_clear_free_data(struct shash *sh) ++{ ++ struct shash_node *node, *next; ++ ++ HINIC3_SHASH_FOR_EACH_SAFE (node, next, sh) { ++ hinic3_hmap_remove(&sh->map, &node->node); ++ hinic3_free(node->data); ++ hinic3_free(node->name); ++ hinic3_free(node); ++ } ++} ++ ++static struct shash_node* hinic3_shash_add_nocopy__(struct shash *sh, char *name, ++ void *data, size_t hash, enum hinic3_module module_id) ++{ ++ struct shash_node *node = NULL; ++ ++ node = hinic3_xmalloc(sizeof *node, module_id); ++ if (node == NULL) { ++ return NULL; ++ } ++ ++ node->name = name; ++ node->data = data; ++ ++ hinic3_hmap_insert(&sh->map, &node->node, hash, module_id); ++ ++ return node; ++} ++ ++struct shash_node* hinic3_shash_add_nocopy(struct shash *sh, char *name, void *data, enum hinic3_module module_id) ++{ ++ return hinic3_shash_add_nocopy__(sh, name, data, hinic3_hash_name(name), module_id); ++} ++ ++struct shash_node* hinic3_shash_add(struct shash *sh, const char *name, void *data, enum hinic3_module module_id) ++{ ++ return hinic3_shash_add_nocopy(sh, hinic3_xstrdup(name, module_id), data, module_id); ++} ++ ++bool hinic3_shash_add_once(struct shash *sh, const char *name, const void *data, enum hinic3_module module_id) ++{ ++ if (!hinic3_shash_find(sh, name)) { ++ hinic3_shash_add(sh, name, (void*)data, module_id); ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++char* hinic3_shash_steal(struct shash *sh, struct shash_node *node) ++{ ++ char *name = node->name; ++ ++ hinic3_hmap_remove(&sh->map, &node->node); ++ hinic3_free(node); ++ ++ return name; ++} ++ ++void hinic3_shash_delete(struct shash *sh, struct shash_node *node) ++{ ++ hinic3_free(hinic3_shash_steal(sh, node)); ++} ++ ++static struct shash_node* hinic3_shash_find__(const struct shash *sh, const char *name, ++ size_t name_len, size_t hash) ++{ ++ struct shash_node *node = NULL; ++ ++ HINIC3_HMAP_FOR_EACH_WITH_HASH (node, node, hash, &sh->map) { ++ if (!strncmp(node->name, name, name_len) && !node->name[name_len]) { ++ return node; ++ } ++ } ++ ++ return NULL; ++} ++ ++struct shash_node* hinic3_shash_find(const struct shash *sh, const char *name) ++{ ++ return hinic3_shash_find__(sh, name, strlen(name), hinic3_hash_name(name)); ++} ++ ++void* hinic3_shash_find_data(const struct shash *sh, const char *name) ++{ ++ struct shash_node *node = hinic3_shash_find(sh, name); ++ return node ? node->data : NULL; ++} ++ ++void* hinic3_shash_find_and_delete(struct shash *sh, const char *name) ++{ ++ struct shash_node *node = hinic3_shash_find(sh, name); ++ if (node) { ++ void *data = node->data; ++ hinic3_shash_delete(sh, node); ++ return data; ++ } else { ++ return NULL; ++ } ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h +new file mode 100644 +index 0000000..8fce7f8 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_SHASH_H ++#define HINIC3_SHASH_H ++ ++#include ++#include ++#include ++#include ++#include "hinic3_hmap.h" ++ ++#define HINIC3_SHASH_FOR_EACH(SHASH_NODE, SHASH) \ ++ HINIC3_HMAP_FOR_EACH_INIT (SHASH_NODE, node, &(SHASH)->map) ++ ++#define HINIC3_SHASH_FOR_EACH_SAFE(SHASH_NODE, NEXT, SHASH) \ ++ HINIC3_HMAP_FOR_EACH_SAFE_INIT ( \ ++ SHASH_NODE, NEXT, node, &(SHASH)->map) ++ ++void hinic3_shash_init(struct shash *shash); ++void hinic3_shash_destroy(struct shash *shash); ++void hinic3_shash_destroy_free_data(struct shash *sh); ++void* hinic3_shash_find_data(const struct shash *shash, const char *name); ++struct shash_node* hinic3_shash_find(const struct shash *sh, const char *name); ++bool hinic3_shash_add_once(struct shash *shash, const char *name, const void *data, enum hinic3_module module_id); ++char* hinic3_shash_steal(struct shash *sh, struct shash_node *node); ++void hinic3_shash_clear_free_data(struct shash *sh); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c +new file mode 100644 +index 0000000..fc62fde +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c +@@ -0,0 +1,159 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include "hinic3_hash.h" ++#include "hinic3_string_util.h" ++#include "hinic3_util.h" ++#include "hinic3_log.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_smap.h" ++ ++static struct smap_node *hinic3_smap_add__(struct smap *, char *, void *, ++ size_t hash, enum hinic3_module module_id); ++static struct smap_node *hinic3_smap_find__(const struct smap *, const char *key, ++ size_t key_len, size_t hash); ++ ++void hinic3_smap_init(struct smap *smap) ++{ ++ hinic3_hmap_init(&smap->map); ++} ++ ++void hinic3_smap_destroy(struct smap *smap) ++{ ++ if (smap) { ++ hinic3_smap_clear(smap); ++ hinic3_hmap_destroy(&smap->map); ++ } ++} ++ ++struct smap_node *hinic3_smap_add(struct smap *smap, const char *key, const char *value, enum hinic3_module module_id) ++{ ++ size_t key_len = strlen(key); ++ ++ return hinic3_smap_add__(smap, hinic3_xmemdup0(key, key_len, module_id), hinic3_xstrdup(value, module_id), ++ hinic3_hash_bytes(key, key_len, 0), module_id); ++} ++ ++struct smap_node *hinic3_smap_get_node(const struct smap *smap, const char *key) ++{ ++ size_t key_len = strlen(key); ++ return hinic3_smap_find__(smap, key, key_len, hinic3_hash_bytes(key, key_len, 0)); ++} ++ ++void hinic3_smap_remove_node(struct smap *smap, struct smap_node *node) ++{ ++ hinic3_hmap_remove(&smap->map, &node->node); ++ hinic3_free(node->key); ++ hinic3_free(node->value); ++ hinic3_free(node); ++} ++ ++void hinic3_smap_clear(struct smap *smap) ++{ ++ struct smap_node *node, *next; ++ ++ HINIC3_SMAP_FOR_EACH_SAFE(node, next, smap) { ++ hinic3_smap_remove_node(smap, node); ++ } ++} ++ ++const char* hinic3_smap_get_def(const struct smap *smap, const char *key, const char *def) ++{ ++ struct smap_node *node = hinic3_smap_get_node(smap, key); ++ return node ? node->value : def; ++} ++ ++const char* hinic3_smap_get(const struct smap *smap, const char *key) ++{ ++ return hinic3_smap_get_def(smap, key, NULL); ++} ++ ++size_t hinic3_smap_count(const struct smap *smap) ++{ ++ return hinic3_hmap_count(&smap->map); ++} ++ ++void hinic3_smap_clone(struct smap *dst, const struct smap *src, enum hinic3_module module_id) ++{ ++ const struct smap_node *node; ++ ++ hinic3_smap_init(dst); ++ HINIC3_SMAP_FOR_EACH(node, src) { ++ hinic3_smap_add__(dst, hinic3_xstrdup(node->key, module_id), hinic3_xstrdup(node->value, module_id), ++ node->node.hash, module_id); ++ } ++} ++ ++bool hinic3_smap_equal(const struct smap *smap1, const struct smap *smap2) ++{ ++ const struct smap_node *node; ++ ++ if (hinic3_smap_count(smap1) != hinic3_smap_count(smap2)) { ++ return false; ++ } ++ ++ HINIC3_SMAP_FOR_EACH(node, smap1) { ++ const char *value2 = hinic3_smap_get(smap2, node->key); ++ if (!value2 || strcmp(node->value, value2)) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static struct smap_node *hinic3_smap_add__(struct smap *smap, char *key, void *value, size_t hash, ++ enum hinic3_module module_id) ++{ ++ struct smap_node *node = hinic3_xmalloc(sizeof *node, module_id); ++ if (node == NULL) { ++ HINIC3_LOG(ERR, AGENT, "malloc failed when smap add node."); ++ return NULL; ++ } ++ node->key = key; ++ node->value = value; ++ ++ hinic3_hmap_insert(&smap->map, &node->node, hash, module_id); ++ return node; ++} ++ ++static void hinic3_smap_add_format_varg(struct smap *smap, const char *key, const char *format, va_list args, ++ enum hinic3_module module_id) ++{ ++ char *value; ++ size_t key_len; ++ ++ value = hinic3_xvasprintf(format, args, module_id); ++ key_len = strlen(key); ++ hinic3_smap_add__(smap, hinic3_xmemdup0(key, key_len, module_id), value, hinic3_hash_bytes(key, key_len, 0), ++ module_id); ++} ++ ++static struct smap_node* hinic3_smap_find__(const struct smap *smap, const char *key, ++ size_t key_len, size_t hash) ++{ ++ struct smap_node *node; ++ ++ HINIC3_HMAP_FOR_EACH_WITH_HASH (node, node, hash, &smap->map) { ++ if (!strncmp(node->key, key, key_len) && !node->key[key_len]) { ++ return node; ++ } ++ } ++ ++ return NULL; ++} ++ ++void hinic3_smap_add_format(enum hinic3_module module_id, struct smap *smap, const char *key, const char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ ++ hinic3_smap_add_format_varg(smap, key, format, args, module_id); ++ ++ va_end(args); ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.h b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.h +new file mode 100644 +index 0000000..2603ab2 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_SMAP_H_ ++#define _HINIC3_SMAP_H_ ++ ++#include ++#include ++#include ++#include ++#include "hinic3_map.h" ++#include "hinic3_hmap.h" ++ ++#define HINIC3_SMAP_FOR_EACH(SMAP_NODE, SMAP) \ ++ HINIC3_HMAP_FOR_EACH_INIT (SMAP_NODE, node, &(SMAP)->map) ++ ++#define HINIC3_SMAP_FOR_EACH_SAFE(SMAP_NODE, NEXT, SMAP) \ ++ HINIC3_HMAP_FOR_EACH_SAFE_INIT ( SMAP_NODE, NEXT, node, &(SMAP)->map) ++ ++void hinic3_smap_init(struct smap *smap); ++void hinic3_smap_destroy(struct smap *smap); ++struct smap_node *hinic3_smap_add(struct smap *smap, const char *key, const char *value, enum hinic3_module module_id); ++bool hinic3_smap_equal(const struct smap *smap1, const struct smap *smap2); ++void hinic3_smap_clone(struct smap *dst, const struct smap *src, enum hinic3_module module_id); ++const char *hinic3_smap_get(const struct smap *smap, const char *key); ++size_t hinic3_smap_count(const struct smap *smap); ++void hinic3_smap_clear(struct smap *smap); ++void hinic3_smap_add_format(enum hinic3_module module_id, struct smap *smap, const char *key, const char *format, ...); ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c +new file mode 100644 +index 0000000..d4283ff +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c +@@ -0,0 +1,404 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_capture_filter.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_string_format.h" ++ ++#define INPUT_KEY_NUM 26 ++#define ARGC_ADD_DOUBLE 2 ++#define HINIC3_INPUT_ITEM_MAX_NUM 6 ++#define PCAP_MAX_PORT_ID 65535 ++#define QUERY_CMD_MIN_PARAM 1 ++#define QUERY_CMD_MAX_PARAM 30 ++#define HINIC3_ICMP_FLOW_MASK 8 ++#define PCAP_FLAG_KEY_VLAN_ID (1LLU << 13) ++#define PCAP_FLAG_KEY_PORT_ID (1LLU << 14) ++#define PCAP_FLAG_KEY_INNER_TYPE (1LLU << 15) ++#define PCAP_FLAG_KEY_IS_VXLAN (1LLU << 16) ++ ++typedef struct rte_flow_item *(*pattern_func)(struct input_key *); ++rte_be16_t g_set_inner_type = 0; ++int hinic3_key_sip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_SIP) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_HOST) != 0) { ++ hinic3_ds_put_format(ds, "%sAlready config \"-host\", cann't config \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ key_name); ++ return -1; ++ } ++ ++ ret = pcap_ip_mask_parse(value, &cap_key->sip, &cap_key->sip_masklen, &cap_key->ip_type); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->flags |= PCAP_FLAG_KEY_SIP; ++ return 0; ++} ++ ++int hinic3_key_dip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_DIP) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_HOST) != 0) { ++ hinic3_ds_put_format(ds, "%sAlready config \"-host\", cann't config \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ key_name); ++ return -1; ++ } ++ ++ ret = pcap_ip_mask_parse(value, &cap_key->dip, &cap_key->dip_masklen, &cap_key->ip_type); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->flags |= PCAP_FLAG_KEY_DIP; ++ return 0; ++} ++ ++int hinic3_key_smac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ struct eth_address addr = { 0 }; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_SMAC) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ ret = parse_mac(value, &addr); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ memcpy(cap_key->smac, &addr, RTE_ETHER_ADDR_LEN); ++ ++ cap_key->flags |= PCAP_FLAG_KEY_SMAC; ++ return 0; ++} ++ ++int hinic3_key_dmac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ struct eth_address addr = { 0 }; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_DMAC) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ ret = parse_mac(value, &addr); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ memcpy(cap_key->dmac, &addr, RTE_ETHER_ADDR_LEN); ++ ++ cap_key->flags |= PCAP_FLAG_KEY_DMAC; ++ return 0; ++} ++ ++int hinic3_key_eth_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ uint32_t tmp_value; ++ char *endPtr = NULL; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_ETH_TYPE) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ ret = check_valid_eth_type(value); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ tmp_value = strtoul(value, &endPtr, STR_TO_HEX_BASE); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ cap_key->eth_type = (uint16_t)htons((uint16_t)tmp_value); ++ ++ if (cap_key->eth_type == htons(ETH_TYPE_IP)) { ++ g_set_inner_type = htons(ETH_TYPE_IP); ++ } else if (cap_key->eth_type == htons(ETH_TYPE_IPV6)) { ++ g_set_inner_type = htons(ETH_TYPE_IPV6); ++ } ++ ++ cap_key->flags |= PCAP_FLAG_KEY_ETH_TYPE; ++ return 0; ++} ++ ++int hinic3_key_ip_proto_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_IP_PROTO) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ ret = parse_l4_proto(value, &cap_key->ip_proto); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->flags |= PCAP_FLAG_KEY_IP_PROTO; ++ return 0; ++} ++ ++int hinic3_key_sport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint32_t sport_value; ++ char *endPtr = NULL; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_SPORT) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ sport_value = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (sport_value > UINT16_MAX) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->sport = (uint16_t)htons((uint16_t)sport_value); ++ cap_key->flags |= PCAP_FLAG_KEY_SPORT; ++ return 0; ++} ++ ++int hinic3_key_dport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint32_t dport_value; ++ char *endPtr = NULL; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_DPORT) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ dport_value = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (dport_value > UINT16_MAX) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->dport = (uint16_t)htons((uint16_t)dport_value); ++ cap_key->flags |= PCAP_FLAG_KEY_DPORT; ++ return 0; ++} ++ ++int hinic3_key_vlan_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint32_t vlan_value; ++ char *endPtr = NULL; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_VLAN) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\".\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ vlan_value = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ return -1; ++ } ++ if (vlan_value > PCAP_MAX_VLAN) { ++ hinic3_ds_put_format(ds, "%sParameter value %s for %s is out of range.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, ++ key_name); ++ return -1; ++ } ++ ++ cap_key->vlan_id = (uint16_t)vlan_value; ++ cap_key->flags |= PCAP_FLAG_KEY_VLAN; ++ return 0; ++} ++ ++int hinic3_key_vni_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint32_t vni_value; ++ char *endPtr = NULL; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_VXLAN_VNI) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ vni_value = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (vni_value > PCAP_MAX_VNI) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->vxlan_vni = vni_value; ++ cap_key->flags |= PCAP_FLAG_KEY_VXLAN_VNI; ++ return 0; ++} ++ ++rte_be16_t hinic3_get_inter_type(void) ++{ ++ return g_set_inner_type; ++} ++ ++int hinic3_key_port_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint32_t port_id; ++ char *endPtr = NULL; ++ if ((cap_key->flags & PCAP_FLAG_KEY_PORT_ID) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ port_id = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ HINIC3_LOG(ERR, FLOW, "port_id is invalid!\n"); ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (port_id > PCAP_MAX_PORT_ID) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->port_id = port_id; ++ cap_key->flags |= PCAP_FLAG_KEY_PORT_ID; ++ return 0; ++} ++ ++int hinic3_key_icmp_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint8_t icmp_type; ++ char *endPtr = NULL; ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ icmp_type = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (icmp_type > UINT8_MAX) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ cap_key->icmp_type = icmp_type; ++ return 0; ++} ++ ++int hinic3_key_icmp_code_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint8_t icmp_code; ++ char *endPtr = NULL; ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ icmp_code = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (icmp_code > UINT8_MAX) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ cap_key->icmp_code = icmp_code; ++ return 0; ++} ++ ++int hinic3_key_icmp_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ uint16_t icmp_id; ++ char *endPtr = NULL; ++ ++ if (!is_valid_digit(value)) { ++ hinic3_ds_put_format(ds, "%sInvalid value %s for parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, value, key_name); ++ return -1; ++ } ++ ++ icmp_id = strtoul(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (icmp_id > UINT16_MAX) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ cap_key->icmp_id = (uint16_t)htons((uint16_t)icmp_id); ++ cap_key->icmp_id = htons(icmp_id); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h +new file mode 100644 +index 0000000..ab75cfe +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h +@@ -0,0 +1,25 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_STRING_FORMAT_H_ ++#define _HINIC3_STRING_FORMAT_H_ ++ ++#include "hinic3_capture_utils.h" ++ ++int hinic3_key_sip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_dip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_smac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_dmac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_eth_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_ip_proto_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_sport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_dport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_vlan_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_vni_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_port_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_icmp_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_icmp_code_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_icmp_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++rte_be16_t hinic3_get_inter_type(void); ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.c b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.c +new file mode 100644 +index 0000000..33474f0 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.c +@@ -0,0 +1,71 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_util.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_string_util.h" ++ ++#define LEFT_SHIFTING_FOUR 4 ++ ++int hinic3_hexit_value(unsigned char c) ++{ ++ static const signed char tbl[UCHAR_MAX + 1] = { ++#define SHT(x) \ ++ ( (x) >= '0' && (x) <= '9' ? (x) - '0' \ ++ : (x) >= 'a' && (x) <= 'f' ? (x) - 'a' + 0xa \ ++ : (x) >= 'A' && (x) <= 'F' ? (x) - 'A' + 0xa \ ++ : -1) ++#define SHT0(x) SHT(x), SHT((x) + 1), SHT((x) + 2), SHT((x) + 3) ++#define SHT1(x) SHT0(x), SHT0((x) + 4), SHT0((x) + 8), SHT0((x) + 12) ++#define SHT2(x) SHT1(x), SHT1((x) + 16), SHT1((x) + 32), SHT1((x) + 48) ++ SHT2(0), SHT2(64), SHT2(128), SHT2(192) ++ }; ++ ++ return tbl[c]; ++} ++ ++uintmax_t hinic3_hexits_value(const char *s, size_t n, bool *ok) ++{ ++ uintmax_t val = 0; ++ for (size_t index = 0; index < n; index++) { ++ int hexit = hinic3_hexit_value(s[index]); ++ if (hexit < 0) { ++ *ok = false; ++ return UINTMAX_MAX; ++ } ++ val = (val << LEFT_SHIFTING_FOUR) + hexit; ++ } ++ *ok = true; ++ return val; ++} ++ ++int hinic3_parse_hw_ufid_from_string(const char *str, uint64_t *ufid) ++{ ++ const char *s = str; ++ bool ok = false; ++ ++ if (strlen(s) < HINIC3_HW_UUID_LEN) { ++ return -1; ++ } ++ ++ *ufid = hinic3_hexits_value(s, HINIC3_HW_UFID_STR_LEN, &ok) << HINIC3_HW_UFID_SHFIT; ++ if (!ok || s[HINIC3_HW_UFID_STR_LEN] != '-') { ++ return -1; ++ } ++ ++ *ufid += hinic3_hexits_value(s + HINIC3_HW_UFID_STR_LEN + 1, HINIC3_HW_UFID_STR_LEN, &ok); ++ if (!ok) { ++ return -1; ++ } ++ ++ if (s[HINIC3_HW_UUID_LEN] != '\0') { ++ return -1; ++ } ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.h b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.h +new file mode 100644 +index 0000000..5425e18 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_util.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_STRING_UTIL_H_ ++#define _HINIC3_STRING_UTIL_H_ ++#include ++#include ++#include ++ ++#define HINIC3_HW_UUID_LEN 17 ++#define HINIC3_HW_UFID_STR_LEN 8 ++#define HINIC3_HW_UFID_SHFIT 32 ++ ++int hinic3_hexit_value(unsigned char c); ++uintmax_t hinic3_hexits_value(const char *s, size_t n, bool *ok); ++int hinic3_parse_hw_ufid_from_string(const char *str, uint64_t *ufid); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.c b/drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.c +new file mode 100644 +index 0000000..a6423f3 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.c +@@ -0,0 +1,112 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_meminfo.h" ++#include "hinic3_thread.h" ++#define MIN_STACK_SIZE (512 * 1024) ++#define MAX_THREAD_NAME_LENGTH 16 ++ ++struct hinic3_thread_aux { ++ void *(*start)(void *); ++ void *arg; ++ char name[MAX_THREAD_NAME_LENGTH]; ++}; ++ ++static void set_min_stack_size(pthread_attr_t *attr, size_t min_stacksize) ++{ ++ size_t stacksize; ++ int error; ++ ++ error = pthread_attr_getstacksize(attr, &stacksize); ++ if (error != 0) { ++ HINIC3_LOG(ERR, AGENT, "pthread_attr_getstacksize failed"); ++ return; ++ } ++ ++ if (stacksize < min_stacksize) { ++ error = pthread_attr_setstacksize(attr, min_stacksize); ++ if (error != 0) { ++ HINIC3_LOG(ERR, AGENT, "pthread_attr_setstacksize failed"); ++ return; ++ } ++ } ++} ++ ++static void *hinic3_set_thread_name(void *aux_) ++{ ++ struct hinic3_thread_aux aux; ++ ++ aux = *(struct hinic3_thread_aux *)aux_; ++ hinic3_free(aux_); ++ ++ if (pthread_setname_np(pthread_self(), aux.name) != 0) { ++ HINIC3_LOG(ERR, AGENT, "thread set name failed. errno is %d", errno); ++ } ++ return aux.start(aux.arg); ++} ++ ++int hinic3_thread_create(pthread_t *thread, const char *name, void *(*start)(void *), void *arg, ++ enum hinic3_module module_id) ++{ ++ int ret; ++ pthread_attr_t attr; ++ struct hinic3_thread_aux *aux = NULL; ++ size_t len; ++ ++ aux = hinic3_malloc(sizeof(struct hinic3_thread_aux), module_id); ++ if (aux == NULL) { ++ return -1; ++ } ++ aux->start = start; ++ aux->arg = arg; ++ ++ len = strnlen(name, sizeof(aux->name) - 1); ++ memcpy(aux->name, name, len); ++ (aux->name)[len] = '\0'; ++ /* on Linux pthread_attr_init/pthread_attr_destroy always succeed */ ++ (void)pthread_attr_init(&attr); ++ set_min_stack_size(&attr, MIN_STACK_SIZE); ++ ret = pthread_create(thread, &attr, hinic3_set_thread_name, aux); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "pthread_create failed. errno is %d", ret); ++ (void)pthread_attr_destroy(&attr); ++ return -1; ++ } ++ (void)pthread_attr_destroy(&attr); ++ return 0; ++} ++ ++int hinic3_thread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr) ++{ ++ int ret = pthread_cond_init(cond, attr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "pthread cond init failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_thread_cond_destroy(pthread_cond_t *cond) ++{ ++ int ret = pthread_cond_destroy(cond); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 cond destroy failed, ret is %d\n", ret); ++ } ++ return ret; ++} ++ ++int hinic3_thread_cond_signal(pthread_cond_t *cond) ++{ ++ int ret = pthread_cond_signal(cond); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 cond signal failed, ret is %d\n", ret); ++ } ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.h b/drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.h +new file mode 100644 +index 0000000..d674c6f +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_thread/hinic3_thread.h +@@ -0,0 +1,28 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_THREAD_H ++#define HINIC3_THREAD_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_log.h" ++#include "hinic3_meminfo.h" ++ ++enum hinic3_thread_status { ++ HINIC3_THREAD_NORMAL_STATUS, ++ HINIC3_THREAD_EXIT_STATUS, ++}; ++ ++int hinic3_thread_create(pthread_t *thread, const char *name, void *(*start)(void *), void *arg, ++ enum hinic3_module module_id); ++int hinic3_thread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr); ++int hinic3_thread_cond_destroy(pthread_cond_t *cond); ++int hinic3_thread_cond_signal(pthread_cond_t *cond); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c +new file mode 100644 +index 0000000..675d708 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c +@@ -0,0 +1,174 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_thread.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_ds.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_check_thread_health_state.h" ++ ++#define HINIC3_MAX_THREAD_NUMS (CONST_THREAD_NUM + HINIC3_OFFLOAD_THREAD_NUM_MAX) ++#define HINIC3_CHECK_THREAD_INTER_TIME 60 ++#define HINIC3_HPD_THREAD_INTER_TIME 200000 ++#define HINIC3_THREAD_NAME_MAX_LEN 50 ++ ++struct check_thread { ++ int thread_health; ++ pthread_t thread; ++ uint32_t thread_exit; ++ uint32_t signal[HINIC3_MAX_THREAD_NUMS]; ++ int thread_status[HINIC3_MAX_THREAD_NUMS]; ++}; ++ ++struct hinic3_hpd_mgr { ++ pthread_t thread; ++ uint32_t thread_exit; ++}; ++ ++static struct check_thread g_check_thread = { 0 }; ++static struct hinic3_hpd_mgr g_hpd_mgr = { 0 }; ++static struct hinic3_thread_name g_thread_name[HINIC3_MAX_THREAD_NUMS] = { ++ {CAPTURE_THREAD, "hinic3-capture-t"}, ++ {LISTEN_THREAD, "hinic3-listen-th"}, ++ {PCAP_SAVE_THREAD, "hinic3-pcap-save"}, ++ {HPD_THREAD, "hinic3-hpd-th"}, ++ {OFFLOAD_THREAD_ONE, "hinic3-offload-0"}, ++ {OFFLOAD_THREAD_TWO, "hinic3-offload-1"}, ++ {OFFLOAD_THREAD_THREE, "hinic3-offload-2"}, ++ {OFFLOAD_THREAD_FOUR, "hinic3-offload-3"}, ++}; ++ ++static void hinic3_signal_increase(uint32_t thread_index) ++{ ++ if (thread_index >= HINIC3_MAX_THREAD_NUMS) { ++ HINIC3_LOG(ERR, FLOW, "HINIC3 CHECK THREAD: exceeded the number of check thread"); ++ return; ++ } ++ g_check_thread.signal[thread_index]++; ++} ++ ++static void *hinic3_check_thread_main(void *arg) ++{ ++ uint32_t prev_signal[HINIC3_MAX_THREAD_NUMS] = {0}; ++ uint32_t offload_thread_num = hinic3_offload_thread_num_get(); ++ uint32_t check_thread_num = CONST_THREAD_NUM + offload_thread_num; ++ bool is_check_hpd_thread = hinic3_support_port_hot_plug(); ++ ++ while (g_check_thread.thread_exit == HINIC3_THREAD_NORMAL_STATUS) { ++ sleep(HINIC3_CHECK_THREAD_INTER_TIME); ++ g_check_thread.thread_health = 0; ++ memset(g_check_thread.thread_status, 0, sizeof(g_check_thread.thread_status)); ++ for (uint32_t thread_num = 0; thread_num < check_thread_num; thread_num++) { ++ if (strcmp(g_thread_name[thread_num].thread_name, "hinic3-hpd-th") == 0 && !is_check_hpd_thread) { ++ continue; ++ } ++ if (g_check_thread.signal[thread_num] == prev_signal[thread_num]) { ++ g_check_thread.thread_health = -(thread_num + 1); ++ g_check_thread.thread_status[thread_num] = -1; ++ /* Marks different thread exception states, ++ -(thread_num + 1) represents (thread_num + 1) thread exception */ ++ HINIC3_LOG(ERR, FLOW, "check thread error, %s thread is abnormal!", ++ g_thread_name[thread_num].thread_name); ++ } ++ prev_signal[thread_num] = g_check_thread.signal[thread_num]; ++ } ++ } ++ return NULL; ++} ++ ++static void hinic3_thread_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ uint32_t offload_thread_num = hinic3_offload_thread_num_get(); ++ uint32_t check_thread_num = CONST_THREAD_NUM + offload_thread_num; ++ ++ for (uint32_t index = 0; index < check_thread_num; index++) { ++ char thread_name[HINIC3_THREAD_NAME_MAX_LEN] = {0}; ++ int ret = snprintf(thread_name, sizeof(thread_name), ++ "%s:", g_thread_name[index].thread_name); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "snprintf_s for thread_name failed."); ++ return; ++ } ++ if (g_check_thread.thread_status[index] == -1) { ++ hinic3_ds_put_format(&ds, "%2s%s%6s%5sunhealthy\n", HINIC3_UI_INDENT_SPACE, thread_name, ++ HINIC3_UI_INDENT_SPACE, HINIC3_UI_INDENT_SPACE); ++ } else { ++ hinic3_ds_put_format(&ds, "%2s%s%6s%5shealthy\n", HINIC3_UI_INDENT_SPACE, thread_name, ++ HINIC3_UI_INDENT_SPACE, HINIC3_UI_INDENT_SPACE); ++ } ++ } ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} ++ ++void unixctl_thread_status_dfx_init(void) ++{ ++ hinic3_command_register("hwoff/show-thread-stats", "", 0, 0, hinic3_thread_stats_show, NULL); ++} ++ ++long long hinic3_thread_signal_increase(long long start, uint32_t index, uint32_t signal_increase_inter) ++{ ++ long long end = hinic3_time_msec(); ++ if ((end - start) / SEC_TO_MSEC_BASE >= signal_increase_inter) { ++ hinic3_signal_increase(index); ++ start = end; ++ } ++ ++ return start; ++} ++ ++int hinic3_check_thread_health_state(void) ++{ ++ return g_check_thread.thread_health; ++} ++ ++static void *hinic3_check_hpd_main(void *arg) ++{ ++ enum check_thread_item_type check_thread = HPD_THREAD; ++ long long start = hinic3_time_msec(); ++ ++ while (g_hpd_mgr.thread_exit == HINIC3_THREAD_NORMAL_STATUS) { ++ start = hinic3_thread_signal_increase(start, check_thread, HINIC3_HPD_THREAD_SIGNAL_INCREASE_INTER); ++ usleep(HINIC3_HPD_THREAD_INTER_TIME); ++ (void)hinic3_global_rte_eth_rx_burst(0, (uint16_t)HINIC3_PTHREAD_HOTPLUG_CTX_CALL, NULL, 0); ++ } ++ return NULL; ++} ++ ++int hinic3_polling_thread_init(void) ++{ ++ int ret; ++ ret = hinic3_thread_create(&g_check_thread.thread, "hinic3_check_th", hinic3_check_thread_main, NULL, HINIC3_INIT); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 check thread create fail."); ++ return -1; ++ } ++ ++ hinic3_set_ctrl_thread_cpu_affinity(&g_check_thread.thread); ++ if (hinic3_support_port_hot_plug()) { ++ ret = hinic3_thread_create(&g_hpd_mgr.thread, "hinic3_hpd_th", hinic3_check_hpd_main, NULL, HINIC3_INIT); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 hpd thread create fail."); ++ return -1; ++ } ++ hinic3_set_ctrl_thread_cpu_affinity(&g_hpd_mgr.thread); ++ } ++ ++ return 0; ++} ++ ++void hinic3_polling_thread_uninit(void) ++{ ++ g_check_thread.thread_exit = HINIC3_THREAD_EXIT_STATUS; ++ if (hinic3_support_port_hot_plug()) { ++ g_hpd_mgr.thread_exit = HINIC3_THREAD_EXIT_STATUS; ++ } ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h +new file mode 100644 +index 0000000..241719f +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h +@@ -0,0 +1,42 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CHECK_THREAD_HEALTH_STATE_H ++#define HINIC3_CHECK_THREAD_HEALTH_STATE_H ++ ++#include ++#include ++#include ++#include "hinic3_command.h" ++ ++#define CONST_THREAD_NUM 4 ++#define HINIC3_OFFLOAD_THREAD_NUM_MAX 4 ++#define HINIC3_PCAP_SAVE_THREAD_SIGNAL_INCREASE_INTER 5 ++#define HINIC3_CAPTURE_THREAD_SIGNAL_INCREASE_INTER 5 ++#define HINIC3_LISTEN_THREAD_SIGNAL_INCREASE_INTER 5 ++#define HINIC3_HPD_THREAD_SIGNAL_INCREASE_INTER 5 ++#define HINIC3LOAD_THREAD_SIGNAL_INCREASE_INTER 5 ++enum check_thread_item_type { ++ CAPTURE_THREAD, ++ LISTEN_THREAD, ++ PCAP_SAVE_THREAD, ++ HPD_THREAD, ++ OFFLOAD_THREAD_ONE, ++ OFFLOAD_THREAD_TWO, ++ OFFLOAD_THREAD_THREE, ++ OFFLOAD_THREAD_FOUR, ++}; ++ ++struct hinic3_thread_name { ++ enum check_thread_item_type thread_id; ++ char *thread_name; ++}; ++ ++int hinic3_check_thread_health_state(void); ++int hinic3_polling_thread_init(void); ++void hinic3_polling_thread_uninit(void); ++long long hinic3_thread_signal_increase(long long start, uint32_t index, uint32_t signal_increase_inter); ++void unixctl_thread_status_dfx_init(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h +new file mode 100644 +index 0000000..20833ae +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h +@@ -0,0 +1,285 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_DPDK_ADAPTER_H ++#define _HINIC3_DPDK_ADAPTER_H ++ ++#include ++ ++#include ++#include "rte_dev.h" ++#include "rte_bus_vdev.h" ++#include "rte_flow_driver.h" ++#include "rte_devargs.h" ++#include "rte_ethdev.h" ++#include "ethdev_driver.h" ++#include "rte_bus_pci.h" ++#include "rte_mtr_driver.h" ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_flow_agent_enum.h" ++#include "bus_pci_driver.h" ++#include "malloc_elem.h" ++#include "hinic3_meminfo.h" ++ ++#define GET_RTE_MBUF_INDEX 9 ++ ++void *hinic3_calloc(size_t num, size_t size, enum hinic3_module module_id); ++ ++ ++ ++static inline void rte_flow_ops_set_validate(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ flow_ops->validate = arg; ++} ++ ++static inline void rte_flow_ops_set_create(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ flow_ops->create = arg; ++} ++ ++static inline void rte_flow_ops_set_destroy(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ flow_ops->destroy = arg; ++} ++ ++static inline void rte_flow_ops_set_flush(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ flow_ops->flush = arg; ++} ++ ++static inline void rte_flow_ops_set_query(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ flow_ops->query = arg; ++} ++ ++static inline void rte_flow_ops_set_dev_dump(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ flow_ops->dev_dump = arg; ++} ++ ++static inline size_t rte_mbuf_struct_size(void) ++{ ++ return sizeof(struct rte_mbuf); ++} ++ ++static inline void* rte_mbuf_get_udata64_ptr(struct rte_mbuf *mbuf) ++{ ++ return &mbuf->dynfield1[1]; ++} ++ ++static inline void* rte_mbuf_get_ptr(struct rte_mbuf *mbuf, int index) ++{ ++ if (index >= 0 && index < GET_RTE_MBUF_INDEX) { ++ return &mbuf->dynfield1[index]; ++ } ++ return NULL; ++} ++ ++static inline void* rte_pktmbuf_get_data(struct rte_mbuf *mbuf) ++{ ++ return rte_pktmbuf_mtod(mbuf, void*); ++} ++ ++static inline uint32_t rte_pktmbuf_get_data_len(struct rte_mbuf *mbuf) ++{ ++ return rte_pktmbuf_data_len(mbuf); ++} ++ ++static inline uint32_t rte_pktmbuf_get_pkt_len(struct rte_mbuf *mbuf) ++{ ++ return rte_pktmbuf_pkt_len(mbuf); ++} ++ ++static inline uint64_t rte_mbuf_get_ol_flags(struct rte_mbuf *mbuf) ++{ ++ return mbuf->ol_flags; ++} ++ ++static inline uint16_t rte_mbuf_get_vlan_tci(struct rte_mbuf *mbuf) ++{ ++ return mbuf->vlan_tci; ++} ++ ++static inline uint32_t rte_mbuf_get_hash_rss(struct rte_mbuf *mbuf) ++{ ++ return mbuf->hash.rss; ++} ++ ++static inline void rte_mbuf_set_ol_flags(struct rte_mbuf *mbuf, uint64_t flag) ++{ ++ mbuf->ol_flags = flag; ++} ++ ++static inline void rte_mbuf_set_port_id(struct rte_mbuf *mbuf, uint16_t port) ++{ ++ mbuf->port = port; ++} ++ ++ ++static inline void rte_pci_driver_set_name(struct rte_pci_driver *driver, const char *name) ++{ ++ driver->driver.name = name; ++} ++ ++static inline void rte_pci_driver_set_id_table(struct rte_pci_driver *driver, const struct rte_pci_id *pci_id) ++{ ++ driver->id_table = pci_id; ++} ++ ++static inline void rte_pci_driver_set_drv_flags(struct rte_pci_driver *driver, uint32_t drv_flags) ++{ ++ driver->drv_flags = drv_flags; ++} ++ ++static inline void rte_pci_driver_set_probe(struct rte_pci_driver *driver, void *arg) ++{ ++ driver->probe = (rte_pci_probe_t*)arg; ++} ++ ++static inline void rte_pci_driver_set_remove(struct rte_pci_driver *driver, void *arg) ++{ ++ driver->remove = (rte_pci_remove_t*)arg; ++} ++ ++static inline struct rte_pci_device* rte_pci_device_get_next(struct rte_pci_device *pci_dev) ++{ ++ return TAILQ_NEXT(pci_dev, next); ++} ++ ++static inline struct rte_pci_addr* rte_pci_device_get_addr_ptr(struct rte_pci_device *device) ++{ ++ return &device->addr; ++} ++ ++static inline struct rte_pci_id* rte_pci_device_get_id_ptr(struct rte_pci_device *device) ++{ ++ return &device->id; ++} ++ ++static inline struct rte_mem_resource* rte_pci_device_get_mem_resource(struct rte_pci_device *device) ++{ ++ return device->mem_resource; ++} ++ ++static inline struct rte_device* rte_pci_device_get_device_ptr(struct rte_pci_device *device) ++{ ++ return &device->device; ++} ++ ++static inline char* rte_pci_device_get_name(struct rte_pci_device *device) ++{ ++ return device->name; ++} ++ ++static inline struct rte_device* rte_vdev_device_get_device_ptr(struct rte_vdev_device *dev) ++{ ++ return &dev->device; ++} ++ ++static inline struct rte_vdev_driver* rte_vdev_driver_allocate(void) ++{ ++ return (struct rte_vdev_driver*)hinic3_calloc(1, sizeof(struct rte_vdev_driver), HINIC3_PORTS); ++} ++ ++static inline void rte_vdev_driver_free(struct rte_vdev_driver *driver) ++{ ++ hinic3_free(driver); ++} ++ ++static inline void rte_vdev_driver_set_probe(struct rte_vdev_driver *driver, void *arg) ++{ ++ driver->probe = (rte_vdev_probe_t*)arg; ++} ++ ++static inline void rte_vdev_driver_set_remove(struct rte_vdev_driver *driver, void *arg) ++{ ++ driver->remove = (rte_vdev_remove_t*)arg; ++} ++ ++static inline void rte_vdev_driver_set_name(struct rte_vdev_driver *driver, const char *name) ++{ ++ driver->driver.name = name; ++} ++ ++static inline void rte_vdev_driver_set_alias(struct rte_vdev_driver *driver, const char *alias) ++{ ++ driver->driver.alias = alias; ++} ++ ++static inline void rte_flow_ops_tunnel_decap_set(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ flow_ops->tunnel_decap_set = arg; ++} ++ ++static inline void rte_eth_mtr_ops_create(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->create = arg; ++} ++ ++static inline void rte_eth_mtr_ops_destroy(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->destroy = arg; ++} ++ ++static inline void rte_eth_mtr_ops_meter_profile_add(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->meter_profile_add = arg; ++} ++ ++static inline void rte_eth_mtr_ops_meter_profile_delete(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->meter_profile_delete = arg; ++} ++ ++static inline void rte_eth_mtr_ops_meter_profile_update(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->meter_profile_update = arg; ++} ++ ++static inline void rte_eth_mtr_ops_meter_policy_add(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->meter_policy_add = arg; ++} ++ ++static inline void rte_eth_mtr_ops_meter_policy_delete(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->meter_policy_delete = arg; ++} ++ ++static inline void rte_eth_mtr_ops_meter_stats_read(struct rte_mtr_ops *mtr_ops, void *arg) ++{ ++ mtr_ops->stats_read = arg; ++} ++ ++static inline struct rte_mtr_ops *rte_mtr_ops_allocate(void) ++{ ++ return hinic3_calloc(1, sizeof(struct rte_mtr_ops), HINIC3_QOS); ++} ++ ++static inline void rte_eth_dev_ops_mtr_get(struct eth_dev_ops *edev_ops, void *arg) ++{ ++ edev_ops->mtr_ops_get = arg; ++} ++ ++static inline void rte_eth_dev_ops_set_mac_addr(struct eth_dev_ops *edev_ops, void *arg) ++{ ++ edev_ops->mac_addr_set = arg; ++} ++ ++static inline void rte_flow_ops_flow_dump_start(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ return; ++} ++ ++static inline void rte_flow_ops_flow_dump_next(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ return; ++} ++ ++static inline void rte_flow_ops_flow_dump_done(struct rte_flow_ops *flow_ops, void *arg) ++{ ++ return; ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h +new file mode 100644 +index 0000000..49aa554 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h +@@ -0,0 +1,120 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_DRV_H__ ++#define HINIC3_DRV_H__ ++ ++#include ++#include "hiovs_api.h" ++ ++#define HINIC3_DRV_FUNC_NO_PTR (-1) ++#define HINIC3_DRV_ADD_FUNC(class, name) {#name, (void**)&(class).name} ++#define HINIC3_FUNC_PTR_OR_ERR_RET(func, retval) do { \ ++ if ((func) == NULL) \ ++ return retval; \ ++} while (0) ++ ++ ++struct hinic3_drv_ops_map { ++ char *name; ++ void **func; ++}; ++ ++struct hinic3_drv_ops { ++ int (*hovs_port_mgmt_add)(uint16_t *port_id, void *pci_addr); ++ int (*hovs_port_mgmt_add_dynamic)(uint16_t *port_id, const struct nlattr *args, uint32_t args_len); ++ void (*hovs_port_mgmt_del)(uint16_t port_id); ++ int (*hovs_port_mgmt_get)(uint16_t port_id, struct nlattr *args, uint32_t *args_len); ++ int (*hovs_port_mgmt_set)(uint16_t port_id, const struct nlattr *args, uint32_t args_len, struct nlattr *unset_args, ++ uint32_t *unset_args_len); ++ int (*hovs_port_mgmt_get_capability)(struct hovs_port_capability *cap); ++ int (*hovs_port_mgmt_get_upcall_info)(struct hovs_port_upcall_info *info); ++ int (*hovs_port_mgmt_setup_upcall_queue)(uint16_t port_id, uint16_t queue_id, unsigned int socket_id, void *mp); ++ int (*hovs_port_mgmt_release_upcall_queue)(uint16_t port_id, uint16_t queue_id); ++ int (*hovs_bond_mgmt_create)(uint8_t mode, const char *name, uint16_t *bond_port_id); ++ void (*hovs_bond_mgmt_delete)(uint16_t bond_port_id); ++ int (*hovs_bond_mgmt_get)(uint16_t bond_port_id, struct nlattr *args, uint32_t *args_len); ++ int (*hovs_etheraddr_get)(uint16_t port_id, struct hovs_eth_addr *mac); ++ int (*hovs_etheraddr_set)(uint16_t port_id, const struct hovs_eth_addr mac); ++ int (*hovs_mtu_set)(uint16_t port_id, int mtu); ++ int (*hovs_port_statistics_get)(uint16_t port_id, struct hovs_port_stats *stats); ++ int (*hovs_port_statistics_flush)(uint16_t port_id); ++ int (*hovs_bum_get)(uint16_t port_id, struct nlattr *args, uint32_t *args_len); ++ int (*hovs_bum_set)(uint16_t port_id, const struct nlattr *args, uint32_t args_len, struct nlattr *unset_args, ++ uint32_t *unset_args_len); ++ int (*hovs_bum_remove)(uint16_t port_id, const struct nlattr *args, uint32_t args_len); ++ int (*hovs_bum_clear)(uint16_t port_id); ++ int (*hovs_flow_mgmt_get_forward_mode)(uint8_t *forward_mode); ++ int (*hovs_flow_mgmt_set_forward_mode)(uint8_t forward_mode); ++ int (*hovs_flow_mgmt_put)(const struct hovs_dpif_flow *put, const struct nlattr *args, size_t args_len); ++ int (*hovs_flow_mgmt_get_by_key)(const struct nlattr *key, size_t key_len, struct hovs_dpif_flow_for_get *get); ++ int (*hovs_flow_mgmt_get_by_ufid)(uint64_t ufid, struct hovs_dpif_flow_for_get *get); ++ int (*hovs_flow_mgmt_del_by_key)(const struct nlattr *key, size_t key_len); ++ int (*hovs_flow_mgmt_del_by_ufid)(uint64_t ufid); ++ int (*hovs_flow_mgmt_del_by_batch)(const uint64_t *ufids, struct hovs_dpif_flow_for_get **flows, const size_t cnt); ++ int (*hovs_flow_mgmt_flush)(void); ++ int (*hovs_flow_mgmt_dump_start)(void **state); ++ int (*hovs_flow_mgmt_dump_next)(void *state, struct hovs_dpif_flow_for_get *dump); ++ int (*hovs_flow_mgmt_dump_done)(void *state); ++ int (*hovs_flow_mgmt_get_maxflows)(uint32_t *max_flows); ++ int (*hovs_flow_mgmt_get_capability)(struct hovs_flow_capability *cap); ++ int (*hovs_statistics_flow_get_by_ufid)(const uint64_t *ufid, const size_t cnt, struct hovs_flow_stats *stats); ++ int (*hovs_statistics_flow_flush_by_ufid)(uint64_t ufid); ++ hovs_flow_callback_t (*hovs_flow_callback_register)(hovs_flow_callback_t cb); ++ int (*hovs_global_cfg_set)(const struct nlattr *args, size_t args_len, struct nlattr *unset_args, ++ size_t *unset_args_len); ++ int (*hovs_global_cfg_get)(struct nlattr *args, size_t *args_len); ++ int (*hovs_global_statistics_get)(struct hovs_global_stats *stats); ++ int (*hovs_global_statistics_flush)(void); ++ int (*hovs_mml_lib)(const char *buf_in, uint32_t in_size, char *buf_out, uint32_t *out_len, ++ uint32_t max_buf_out_len); ++ int32_t (*hovs_lib_init)(void *arg); ++ int (*hovs_lib_deinit)(void *arg); ++ int (*hovs_open_log)(uint32_t module_type, uint32_t enable); ++ int (*hovs_set_log_level)(uint32_t module_type, uint32_t log_level); ++ int (*hovs_qos_statistics_get_batch)(uint16_t type, uint16_t *ids, struct hovs_qos_stats_batch *stats, size_t cnt); ++ int (*hovs_qos_statistics_get_all_batch)(uint16_t type, uint16_t *ids, struct hovs_qos_stats_batch_all *stats, ++ size_t cnt); ++ int (*hovs_qos_statistics_clear_batch)(uint16_t type, uint16_t *ids, size_t cnt); ++ int (*hovs_hqos_statistics_get_all_batch)(uint16_t type, uint16_t *ids, struct hovs_hqos_stats_batch_all *stats, ++ size_t cnt); ++ int (*hovs_hqos_statistics_clear_batch)(uint16_t type, uint16_t dir, uint16_t *ids, size_t cnt); ++ int (*hovs_qos_vm_limit_set)(uint16_t group_id, uint16_t dir, uint16_t type, uint64_t max_rate, uint64_t max_burst, ++ uint64_t min_rate, uint64_t min_burst); ++ int (*hovs_qos_flow_limit_set)(uint16_t qos_id, uint64_t max_rate, uint64_t max_burst, ++ uint64_t min_rate, uint64_t min_burst); ++ int (*hovs_qos_vm_limit_get)(uint16_t group_id, uint16_t dir, uint16_t type, uint64_t *max_rate, ++ uint64_t *max_burst, uint64_t *min_rate, uint64_t *min_burst); ++ int (*hovs_qos_flow_limit_get)(uint16_t qos_id, uint64_t *max_rate, uint64_t *max_burst, ++ uint64_t *min_rate, uint64_t *min_burst); ++ int (*hovs_qos_vport_limit_set)(uint16_t port_id, uint16_t dir, uint16_t type, ++ uint64_t max_rate, uint64_t max_burst, uint64_t min_rate, uint64_t min_burst); ++ int (*hovs_qos_vport_limit_get)(uint16_t port_id, uint16_t dir, uint16_t type, ++ uint64_t *max_rate, uint64_t *max_burst, uint64_t *min_rate, uint64_t *min_burst); ++ int (*hovs_qos_net_limit_set)(uint16_t host_id, uint16_t dir, uint16_t type, ++ uint64_t max_rate, uint64_t max_burst); ++ int (*hovs_qos_net_limit_get)(uint16_t host_id, uint16_t dir, uint16_t type, ++ uint64_t *max_rate, uint64_t *max_burst); ++ uint16_t (*hovs_rte_tx_burst)(uint16_t dpdk_port_id, uint16_t dpdk_queue_id, void **tx_pkts, uint16_t nb_pkts); ++ uint16_t (*hovs_rte_rx_burst)(uint16_t dpdk_port_id, uint16_t dpdk_queue_id, void **rx_pkts, uint16_t nb_pkts); ++ int (*hovs_global_pcie_list_query)(uint8_t front_back, uint8_t bdf_type, struct hovs_phy_dev_info *dev); ++ int (*hovs_qos_vm_srtcm_limit_set)(uint16_t group_id, uint16_t dir, uint16_t type, uint64_t min_rate, ++ uint64_t min_burst, uint64_t exs_burst); ++ int (*hovs_qos_vm_srtcm_limit_get)(uint16_t group_id, uint16_t dir, uint16_t type, uint64_t *min_rate, ++ uint64_t *min_burst, uint64_t *exs_burst); ++ int (*hovs_bond_slave_statistics_get)(uint16_t port_id, struct hovs_bond_slave_stats *stats); ++ int (*hovs_port_mgmt_set_upcall_priority)(uint16_t port_id, struct hovs_high_priority_protocol_cfg cfgs[], ++ uint32_t config_num, uint8_t upcall_queue_num); ++ int (*hovs_port_mgmt_get_usage_state)(uint16_t port_id, uint32_t *device_status); ++ int (*hovs_port_mgmt_set_usage_state)(uint16_t port_id, uint16_t status); ++ int (*hovs_upcall_mtu_set)(uint8_t type, int mtu); ++ ++ int (*hovs_flow_mgmt_get_block_table_size)(uint32_t *block_num); ++ int (*hovs_flow_mgmt_update)(const struct hovs_dpif_flow *modify, const struct nlattr *args, size_t args_len); ++ void (*hovs_flow_mgmt_set_block_version)(uint32_t block_num, uint16_t block_id[], ++ uint16_t block_version[], int result[]); ++ int (*hovs_flow_mgmt_get_block_version)(uint32_t block_num, uint16_t block_id[], uint16_t block_version[]); ++}; ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.c +new file mode 100644 +index 0000000..a475482 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.c +@@ -0,0 +1,187 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_error_stats.h" ++#include ++#include ++#define HINIC3_ERRSTAT_ERROR_STRING "error" ++#define HINIC3_ERRSTAT_WARNING_STRING "warning" ++static uint64_t g_hinic3_agent_error_stats[HINIC3_ERRSTAT_END] = { 0 }; ++ ++struct hinic3_error_stats_info { ++ enum hinic3_module module; ++ const char *string; ++}; ++ ++static struct hinic3_error_stats_info g_error_stats_info[] = { ++ [HINIC3_ERRSTAT_COMMON_ERRSTAT_INPUT_NULL] = {HINIC3_COMMON_RESOURCE, "errstat_self_input_is_null"}, ++ [HINIC3_ERRSTAT_COMMON_ERRSTAT_TYPE_OUTOFBOUND] = {HINIC3_COMMON_RESOURCE, "errstat_self_type_out_of_bound"}, ++ [HINIC3_ERRSTAT_COMMON_ERRSTAT_TYPE_NO_INFO] = {HINIC3_COMMON_RESOURCE, "errstat_self_type_no_info"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_CHECK_FAIL] = {HINIC3_CT_OFFLOAD, "error_ct_check_fail"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_NOT_READY] = {HINIC3_CT_OFFLOAD, "warning_ct_not_ready"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_CLEAN_ID_NOT_FOUND] = {HINIC3_CT_OFFLOAD, "error_clean_id_not_found"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_CHECK_CONN_FAILED] = {HINIC3_CT_OFFLOAD, "error_ct_check_conn_failed"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_GET_INFO_ID_NOT_FOUND] = {HINIC3_CT_OFFLOAD, "error_get_info_id_not_found"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_CHECK_ALG_CTRL] = {HINIC3_CT_OFFLOAD, "error_check_alg_ctrl"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_RECIRCLED_NOT_TCP] = {HINIC3_CT_OFFLOAD, "error_recircled_non_tcp"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_GET_EXIST_CONN_NOT_FOUND] = {HINIC3_CT_OFFLOAD, "error_get_exist_conn_not_found"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_NOT_CONNECT] = {HINIC3_CT_OFFLOAD, "warning_ct_not_connect"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_SEARCH_ERR] = {HINIC3_CT_OFFLOAD, "error_ct_search_fail"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_NOT_NAT] = {HINIC3_CT_OFFLOAD, "warning_ct_not_nat"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_REVERT_CONN_NULL] = {HINIC3_CT_OFFLOAD, "error_ct_revert_conn_is_null"}, ++ [HINIC3_FLOW_AGENT_ERROR_CT_REVERT_CONN_NOT_NAT] = {HINIC3_CT_OFFLOAD, "error_ct_revert_conn_is_not_nat"}, ++ [HINIC3_FLOW_AGENT_ERROR_GLOBAL_CFG_SET] = {HINIC3_DRIVER_ADAPTER, "error_global_cfg_set_emc_sample__error"}, ++ [HINIC3_VPORT_HOVS_RTE_RX_BURST_NULL] = {HINIC3_DRIVER_ADAPTER, "error_vport_hovs_rte_rx_burst_null"}, ++ [HINIC3_VPORT_HOVS_RTE_TX_BURST_NULL] = {HINIC3_DRIVER_ADAPTER, "error_vport_hovs_rte_tx_burst_null"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_PROCESS_FLOW_KEY] = {HINIC3_FLOWS, "error_emc_offload_process_flow_key_fail"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_REPEATED] = ++ {HINIC3_FLOWS, "error_emc_offload_check_offload_repeated"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_EXIST_GAP] = ++ {HINIC3_FLOWS, "warning_emc_offload_check_offload_exit_gap"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_ONGOING] = ++ {HINIC3_FLOWS, "error_emc_offload_check_offload_ongoing"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_INSERT_RTE_FLOW_IN_HMAP] = {HINIC3_FLOWS, "error_emc_offload_insert_into_hmap_fail"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_PARSE_FLOW_ACTION] = {HINIC3_FLOWS, "error_emc_offload_parse_flow_action_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CALL_HARDWARE_FUNC] = {HINIC3_FLOWS, "error_emc_offload_call_hardware_func_error"}, ++ [HINIC3_FLOW_AGENT_WARNING_OFFLOAD_CALLBACK] = {HINIC3_FLOWS, "warning_flow_offload_callback"}, ++ [HINIC3_FLOW_AGENT_ERROR_DEL_RTE_FLOW_IN_HMAP] = {HINIC3_FLOWS, "error_emc_destroy_flow_in_hmap_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DEL_HARD_FLOW] = {HINIC3_FLOWS, "error_emc_destroy_hard_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_EMC_FLOW_OFFLOAD] = {HINIC3_FLOWS, "error_emc_offload_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_EMC_FLOW_ALLOC] = {HINIC3_FLOWS, "error_emc_offload_flow_alloc_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_NO_INIT] = {HINIC3_FLOWS, "error_emc_offload_agent_no_init_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DEL_FLOW_IN_SESSION] = {HINIC3_FLOWS, "error_emc_destroy_mirror_session_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_EMC_HARD_FLOW_FLUSH] = {HINIC3_FLOWS, "error_emc_flush_hard_flow_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_EMC_MPOOL_FLUSH] = {HINIC3_FLOWS, "error_emc_flush_mpool_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_MIRROR_SESSION_FLUSH] = {HINIC3_FLOWS, "error_emc_flush_mirror_session_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_FLOW_NOT_OFFLOADED] = {HINIC3_FLOWS, "error_emc_flow_not_offload"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_START] = {HINIC3_FLOWS, "error_emc_dump_start_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_START_HARD] = {HINIC3_FLOWS, "error_emc_dump_start_hard_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_DONE] = {HINIC3_FLOWS, "error_emc_dump_done_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_DONE_HARD] = {HINIC3_FLOWS, "error_emc_dump_done_hard_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_NEXT] = {HINIC3_FLOWS, "error_emc_dump_next_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_NEXT_MEM] = {HINIC3_FLOWS, "error_emc_dump_next_mem_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_CALLBACK_FLOW_PUT_INFO] = ++ {HINIC3_FLOWS, "error_callback_emc_offload_process_flow_put_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_CALLBACK_MODIFY_FLOW_PUT] = ++ {HINIC3_FLOWS, "error_callback_emc_modify_process_flow_put_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_CALLBACK_SET_UFID_IN_RTE_FLOW] = ++ {HINIC3_FLOWS, "error_callback_emc_offload__set_ufid_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION] = {HINIC3_FLOWS, "error_sample_action_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_PORT_ID] = {HINIC3_FLOWS, "error_sample_port_id_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION_SET] = {HINIC3_FLOWS, "error_sample_set_action_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_VXLAN_ENCAP] = {HINIC3_FLOWS, "error_sample_vxlan_encap_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_UDP_ITEM] = {HINIC3_FLOWS, "error_sample_udp_item_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_VXLAN_ITEM] = {HINIC3_FLOWS, "error_sample_vxlan_item_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV6_ITEM] = {HINIC3_FLOWS, "error_sample_ipv6_item_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_ETH_ITEM] = {HINIC3_FLOWS, "error_sample_eth_item_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_VLAN_ITEM] = {HINIC3_FLOWS, "error_sample_vlan_item_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV4_ITEM] = {HINIC3_FLOWS, "error_sample_ipv4_item_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SAMPLE_NVGRE_ITEM] = {HINIC3_FLOWS, "error_sample_gre_item_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SESSION_FULLED] = {HINIC3_FLOWS, "error_session_fulled"}, ++ [HINIC3_FLOW_AGENT_ERROR_SESSION_UNUSED] = {HINIC3_FLOWS, "error_session_unused"}, ++ [HINIC3_FLOW_AGENT_ERROR_SESSION_RATIO] = {HINIC3_FLOWS, "error_session_ratio_out_of_range"}, ++ [HINIC3_FLOW_AGENT_ERROR_GET_HW_STATS_BY_UFID] = {HINIC3_FLOWS, "error_get_hw_stats_by_ufid"}, ++ [HINIC3_FLOW_AGENT_ERROR_MANY_OUTPUT] = {HINIC3_FLOWS, "warning_many_output"}, ++ [HINIC3_FLOW_AGENT_ERROR_INPUT_NOT_HIOVS] = {HINIC3_FLOWS, "error_input_port_not_hiovs"}, ++ [HINIC3_FLOW_AGENT_ERROR_FLOW_NO_VXLAN_ACTION_OFFSET] = {HINIC3_FLOWS, "error_no_vxlan_action_offset"}, ++ [HINIC3_FLOW_AGENT_ERROR_WRONG_CREATE_FLOW_TYPE] = {HINIC3_FLOWS, "error_flow_offload_type_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_WRONG_FLUSH_FLOW_TYPE] = {HINIC3_FLOWS, "error_flow_flush_type_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_UFID_MAP_MPOOL_FLUSH] = {HINIC3_FLOWS, "error_ufid_map_flush_mpool_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_GET_TIME_STAMP] = {HINIC3_FLOWS, "error_get_time_stamp_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_FLOW_FLUSH_ALL_INPUT_NULL] = {HINIC3_FLOWS, "error_flow_flush_input_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_INPUT_CHECK_PTHREAD] = {HINIC3_FLOWS, "error_flow_dump_input_thread_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUMP_INPUT_CHECK_TYPE] = {HINIC3_FLOWS, "error_flow_dump_input_type_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_DEV_DUMP_NULL] = {HINIC3_FLOWS, "error_eth_flow_dev_dump_error"}, ++ [HINIC3_FLOW_ERROR_NO_EXIST_FLOW] = {HINIC3_FLOWS, "error_modify_no_exist_flow"}, ++ [HINIC3_FLOW_ERROR_FLOW_NOT_READY] = {HINIC3_FLOWS, "error_modify_flow_not_ready"}, ++ [HINIC3_FLOW_ERROR_FLOW_BLOCK_ERR] = {HINIC3_FLOWS, "error_flow_block_out_of_range"}, ++ [HINIC3_FLOW_AGENT_ERROR_IGNORE_CT_FOR_PUSH] = {HINIC3_OVS_FLOW, "warning_ignore_ct_for_push"}, ++ [HINIC3_FLOW_OVS_ERROR_FLOW_RECIRC_BY_PACKET] = {HINIC3_OVS_FLOW, "error_flow_recirc_by_packet_error"}, ++ [HINIC3_FLOW_OVS_ERROR_FLOW_GENERATE_BY_PACKET] = {HINIC3_OVS_FLOW, "error_flow_generate_by_packet_error"}, ++ [HINIC3_FLOW_OVS_ERROR_OFFLOAD_BY_PACKET] = {HINIC3_OVS_FLOW, "error_offload_by_packet_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_FORWARD_ENGINE_NOT_READY] = {HINIC3_INIT, "error_forward_engine_not_ready"}, ++ [HINIC3_FLOW_AGENT_STATS_OFFLOAD_DELAY] = {HINIC3_POLICY, "warning_check_offload_delay"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_LIMITS] = {HINIC3_POLICY, "warning_check_reach_hw_limits"}, ++ [HINIC3_FLOW_AGENT_ERROR_NO_CONN_TABLE] = {HINIC3_POLICY, "warning_check_no_conn_table"}, ++ [HINIC3_FLOW_AGENT_ERROR_NOT_USER_PERMISSION] = {HINIC3_POLICY, "warning_check_user_permission_fail"}, ++ [HINIC3_FLOW_AGENT_ERROR_DUPLICATE_OFFLOAD] = {HINIC3_POLICY, "warning_check_duplicated_policy_table"}, ++ [HINIC3_FLOW_AGENT_ERROR_POLICY_ILLEGAL_INPUT] = {HINIC3_POLICY, "error_check_illegal_input"}, ++ [HINIC3_FLOW_AGENT_ERROR_POLICY_ILLEGAL_OFFLOAD_TIME] = {HINIC3_POLICY, "error_check_illegal_offload_time"}, ++ [HINIC3_FLOW_OVS_POLICY_CHECK_NO_OFFLOAD] = {HINIC3_POLICY, "warning_check_no_offload"}, ++ [HINIC3_FLOW_OVS_ERROR_POLICY_REACH_USER_LIMITS] = {HINIC3_POLICY, "warning_check_reach_user_limit"}, ++ [HINIC3_FLOW_OVS_POLICY_INTERNAL_ERROR] = {HINIC3_POLICY, "error_check_internal_error"}, ++ [HINIC3_FLOW_AGENT_POLICY_LOW_SPEED_FLOW_DEL] = {HINIC3_POLICY, "warning_low_speed_flow_delete"}, ++ [HINIC3_FLOW_AGENT_POLICY_LOW_SPEED_ERROR] = {HINIC3_POLICY, "warning_low_speed_flow_block"}, ++ [HINIC3_FLOW_OVS_POLICY_HASH_TABLE_DEL_FAIL] = {HINIC3_POLICY, "error_del_hash_table_fail"}, ++ [HINIC3_FLOW_AGENT_ERROR_POLICY_CALLBACK_ILLEGAL_INPUT] = {HINIC3_POLICY, "error_callback_illegal_input"}, ++ [HINIC3_FLOW_AGENT_ERROR_OFFLOAD_DISABLE] = {HINIC3_PORTS, "warning_offload_disable"}, ++ [HINIC3_VPORT_VIRTUAL_QUEUE_RECV_PKTS_DISTRIBUTE_DROP] = ++ {HINIC3_PORTS, "error_virtual_queue_recv_pkts_distribute_drop"}, ++ [HINIC3_VPORT_RX_QUEUE_INVALID] = {HINIC3_PORTS, "error_standard_queue_valid_rxq_invalid"}, ++ [HINIC3_VPORT_VIRTUAL_RX_QUEUE_INVALID] = {HINIC3_PORTS, "error_virtual_queue_valid_rxq_invalid"}, ++ [HINIC3_VPORT_TX_QUEUE_INVALID] = {HINIC3_PORTS, "error_standard_queue_valid_txq_invalid"}, ++ [HINIC3_VPORT_DEV_PRIVATE_DATA_NULL] = {HINIC3_PORTS, "error_vport_dev_private_data_null"}, ++ [HINIC3_FLOW_AGENT_ERROR_FLOW_QUERY_INPUT_NULL] = {HINIC3_PORTS, "error_flow_query_input_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_FLOW_CREATE_INPUT_NULL] = {HINIC3_PORTS, "error_flow_offload_input_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_FLOW_DEL_INPUT_NULL] = {HINIC3_PORTS, "error_flow_destroy_input_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_FLOW_GET_PORT_ID] = {HINIC3_PORTS, "error_flow_get_port_id_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_UPCALL_PRIORITY] = {HINIC3_PORTS, "error_upcall_priority_error"}, ++ [HINIC3_FLOW_AGENT_ERROR_SET_MULTI_QOS] = {HINIC3_QOS, "error_set_multi_qos_error"}, ++ [HINIC3_FLOW_OVS_ERROR_FLOW_NO_OUTPUT_PORT] = {HINIC3_PACKET_PARSE, "error_ovs_flow_no_output_port"}, ++ [HINIC3_FLOW_OVS_ERROR_FLOW_MUTIL_OUTPUT_PORT] = {HINIC3_PACKET_PARSE, "error_ovs_flow_mutil_output_port"}, ++ [HINIC3_FLOW_OVS_ERROR_OFFLOAD_FULLKEY_VPORT_FAIL] = {HINIC3_PACKET_PARSE, "error_ovs_offload_fullkey_vport_fail"}, ++ [HINIC3_FLOW_OVS_ERROR_OFFLOAD_PARSE_HDR_FAIL] = {HINIC3_PACKET_PARSE, "error_ovs_offload_parse_hdr_fail"}, ++ [HINIC3_PACKET_ERROR_MBUF_GET_FIAL] = {HINIC3_PACKET_PARSE, "error_mbuf_get_failed"}, ++ [HINIC3_PACKET_ERROR_PARSE_ACTION] = {HINIC3_PACKET_PARSE, "error_action_parse_failed"}, ++ [HINIC3_PACKET_ERROR_PARSE_PKT_EXTRACT] = {HINIC3_PACKET_PARSE, "error_extract_failed"}, ++ [HINIC3_PACKET_ERROR_PARSE_PKT_INFO] = {HINIC3_PACKET_PARSE, "error_info_get_failed"}, ++ [HINIC3_PACKET_ERROR_PARSE_HDR_PARSE] = {HINIC3_PACKET_PARSE, "error_hdr_parse_failed"}, ++ [HINIC3_FLOW_AGENT_ERROR_IP_FRAGMENT] = {HINIC3_PACKET_PARSE, "error_ip_fragment"}, ++ [HINIC3_FLOW_AGENT_ERROR_IPV6_ICMP_NOT_ECHO] = {HINIC3_PACKET_PARSE, "error_ipv6_not_echo"}, ++ [HINIC3_FLOW_AGENT_ERROR_BROADCAST_PKT] = {HINIC3_PACKET_PARSE, "warning_broadcast_pkt"}, ++ [HINIC3_FLOW_AGENT_ERROR_NO_PKT_INFO] = {HINIC3_PACKET_PARSE, "error_no_pkt_info"}, ++ [HINIC3_FLOW_AGENT_ERROR_EXTRACT_PKT] = {HINIC3_PACKET_PARSE, "warning_extract_pkt"}, ++ [HINIC3_FLOW_AGENT_ERROR_TRANS_KEY] = {HINIC3_PACKET_PARSE, "error_transfer_key"}, ++ [HINIC3_FLOW_AGENT_ERROR_PROC_OFFLOAD_PKTS_FAILED] = {HINIC3_PACKET_PARSE, "error_proc_offload_pkts_failed"}, ++}; ++ ++void hinic3_add_error_stats(enum hinic3_errstat_type index, uint32_t count) ++{ ++ if (index >= HINIC3_ERRSTAT_END || index <= HINIC3_ERRSTAT_START) { ++ g_hinic3_agent_error_stats[HINIC3_ERRSTAT_COMMON_ERRSTAT_TYPE_OUTOFBOUND]++; ++ return; ++ } ++ g_hinic3_agent_error_stats[index] += count; ++} ++ ++static inline enum hinic3_errstat_level hinic3_errstat_get_level_by_string(const char* string) ++{ ++ if (strncmp(HINIC3_ERRSTAT_ERROR_STRING, string, strlen(HINIC3_ERRSTAT_ERROR_STRING)) == 0) { ++ return HINIC3_ERRSTAT_LEVEL_ERROR; ++ } else { ++ return HINIC3_ERRSTAT_LEVEL_WARNING; ++ } ++} ++ ++int hinic3_get_error_stats(enum hinic3_errstat_type index, struct hinic3_error_stats* stats) ++{ ++ if (stats == NULL) { ++ g_hinic3_agent_error_stats[HINIC3_ERRSTAT_COMMON_ERRSTAT_INPUT_NULL]++; ++ return -1; ++ } ++ if (index >= HINIC3_ERRSTAT_END || index <= HINIC3_ERRSTAT_START) { ++ g_hinic3_agent_error_stats[HINIC3_ERRSTAT_COMMON_ERRSTAT_TYPE_OUTOFBOUND]++; ++ return -1; ++ } ++ ++ stats->string = g_error_stats_info[index].string; ++ stats->module = g_error_stats_info[index].module; ++ if (stats->string == NULL || stats->module >= HINIC3_MODULE_MAX || stats->module < 0) { ++ g_hinic3_agent_error_stats[HINIC3_ERRSTAT_COMMON_ERRSTAT_TYPE_NO_INFO]++; ++ return -1; ++ } ++ stats->level = hinic3_errstat_get_level_by_string(stats->string); ++ stats->count = g_hinic3_agent_error_stats[index]; ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.h +new file mode 100644 +index 0000000..9f39a5b +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_error_stats.h +@@ -0,0 +1,185 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_ERROR_STATS_H ++#define HINIC3_ERROR_STATS_H ++#include ++#include "hinic3_flow_agent_enum.h" ++/** 错误类型名 命名格式 ++ * HINIC3_ERSTAT_FLOW_WARNING_BRAODCAST_PKT ++ * |--- 前缀 ---|模块|错误类型|-- 错误信息--| ++ * 模块名简称 ++ * [HINIC3_COMMON_RESOURCE] COMMON:通用工具模块 ++ * [HINIC3_CAPTURE] CAPTURE:抓包模块 ++ * [HINIC3_COMMAND] COMMAND:命令行模块 ++ * [HINIC3_CT_OFFLOAD] CT:ct卸载模块 ++ * [HINIC3_DRIVER_ADAPTER] DRIVER:驱动适配模块 ++ * [HINIC3_FLOWS] FLOWS:流表模块 ++ * [HINIC3_OVS_FLOW] OVSOFF: OVS流表卸载模块 ++ * [HINIC3_INIT] INIT:初始化模块 ++ * [HINIC3_POLICY] POLICY:卸载策略模块 ++ * [HINIC3_PORTS] PORTS:端口模块 ++ * [HINIC3_QOS] QOS:qos模块 ++ * [HINIC3_SECURITY_FILTER] FILTER:安全过滤模块 ++ * [HINIC3_UFID_MAP] UFID:ufid管理 ++ * [HINIC3_OVS_MEMPOOL] - ++ * [HINIC3_OVS_UFID_MEMPOOL] - ++ * [HINIC3_OVS_UFID_MAP] OVSUFID:OVS ufid管理 ++ * [HINIC3_PACKET_PARSE] PACKET:OVS 解包模块 ++ * [HINIC3_OVS_SMAC] - ++ * [HINIC3_OVS_HINIC3_PRIVATE] - ++ * [HIOVS_MEM] - ++*/ ++enum hinic3_errstat_type { ++ HINIC3_ERRSTAT_START, ++ // 通用工具模块 ++ HINIC3_ERRSTAT_COMMON_ERRSTAT_TYPE_OUTOFBOUND, ++ HINIC3_ERRSTAT_COMMON_ERRSTAT_TYPE_NO_INFO, ++ HINIC3_ERRSTAT_COMMON_ERRSTAT_INPUT_NULL, ++ // CT 卸载模块 ++ HINIC3_FLOW_AGENT_ERROR_CT_CHECK_FAIL, ++ HINIC3_FLOW_AGENT_ERROR_CT_NOT_READY, ++ HINIC3_FLOW_AGENT_ERROR_CT_CLEAN_ID_NOT_FOUND, ++ HINIC3_FLOW_AGENT_ERROR_CT_CHECK_CONN_FAILED, ++ HINIC3_FLOW_AGENT_ERROR_CT_GET_INFO_ID_NOT_FOUND, ++ HINIC3_FLOW_AGENT_ERROR_CT_CHECK_ALG_CTRL, ++ HINIC3_FLOW_AGENT_ERROR_CT_RECIRCLED_NOT_TCP, ++ HINIC3_FLOW_AGENT_ERROR_CT_GET_EXIST_CONN_NOT_FOUND, ++ HINIC3_FLOW_AGENT_ERROR_CT_NOT_CONNECT, ++ HINIC3_FLOW_AGENT_ERROR_CT_SEARCH_ERR, ++ HINIC3_FLOW_AGENT_ERROR_CT_NOT_NAT, ++ HINIC3_FLOW_AGENT_ERROR_CT_REVERT_CONN_NULL, ++ HINIC3_FLOW_AGENT_ERROR_CT_REVERT_CONN_NOT_NAT, ++ // driver adapter模块 ++ HINIC3_FLOW_AGENT_ERROR_GLOBAL_CFG_SET, ++ HINIC3_VPORT_HOVS_RTE_RX_BURST_NULL, ++ HINIC3_VPORT_HOVS_RTE_TX_BURST_NULL, ++ // 流表模块 ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_PROCESS_FLOW_KEY, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_REPEATED, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_EXIST_GAP, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_ONGOING, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_INSERT_RTE_FLOW_IN_HMAP, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_PARSE_FLOW_ACTION, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CALL_HARDWARE_FUNC, ++ HINIC3_FLOW_AGENT_WARNING_OFFLOAD_CALLBACK, ++ HINIC3_FLOW_AGENT_ERROR_DEL_RTE_FLOW_IN_HMAP, ++ HINIC3_FLOW_AGENT_ERROR_DEL_HARD_FLOW, ++ HINIC3_FLOW_AGENT_ERROR_EMC_FLOW_OFFLOAD, ++ HINIC3_FLOW_AGENT_ERROR_EMC_FLOW_ALLOC, ++ HINIC3_FLOW_AGENT_ERROR_NO_INIT, ++ HINIC3_FLOW_AGENT_ERROR_DEL_FLOW_IN_SESSION, ++ HINIC3_FLOW_AGENT_ERROR_EMC_HARD_FLOW_FLUSH, ++ HINIC3_FLOW_AGENT_ERROR_EMC_MPOOL_FLUSH, ++ HINIC3_FLOW_AGENT_ERROR_MIRROR_SESSION_FLUSH, ++ HINIC3_FLOW_AGENT_ERROR_FLOW_NOT_OFFLOADED, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_START, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_START_HARD, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_DONE, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_DONE_HARD, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_NEXT, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_NEXT_MEM, ++ HINIC3_FLOW_AGENT_ERROR_CALLBACK_FLOW_PUT_INFO, ++ HINIC3_FLOW_AGENT_ERROR_CALLBACK_MODIFY_FLOW_PUT, ++ HINIC3_FLOW_AGENT_ERROR_CALLBACK_SET_UFID_IN_RTE_FLOW, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_PORT_ID, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION_SET, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_VXLAN_ENCAP, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_UDP_ITEM, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_VXLAN_ITEM, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV6_ITEM, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_ETH_ITEM, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_VLAN_ITEM, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV4_ITEM, ++ HINIC3_FLOW_AGENT_ERROR_SAMPLE_NVGRE_ITEM, ++ HINIC3_FLOW_AGENT_ERROR_SESSION_FULLED, ++ HINIC3_FLOW_AGENT_ERROR_SESSION_UNUSED, ++ HINIC3_FLOW_AGENT_ERROR_SESSION_RATIO, ++ HINIC3_FLOW_AGENT_ERROR_GET_HW_STATS_BY_UFID, ++ HINIC3_FLOW_AGENT_ERROR_MANY_OUTPUT, ++ HINIC3_FLOW_AGENT_ERROR_INPUT_NOT_HIOVS, ++ HINIC3_FLOW_AGENT_ERROR_FLOW_NO_VXLAN_ACTION_OFFSET, ++ HINIC3_FLOW_AGENT_ERROR_WRONG_CREATE_FLOW_TYPE, ++ HINIC3_FLOW_AGENT_ERROR_WRONG_FLUSH_FLOW_TYPE, ++ HINIC3_FLOW_AGENT_ERROR_UFID_MAP_MPOOL_FLUSH, ++ HINIC3_FLOW_AGENT_ERROR_GET_TIME_STAMP, ++ HINIC3_FLOW_AGENT_ERROR_FLOW_FLUSH_ALL_INPUT_NULL, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_INPUT_CHECK_PTHREAD, ++ HINIC3_FLOW_AGENT_ERROR_DUMP_INPUT_CHECK_TYPE, ++ HINIC3_FLOW_AGENT_ERROR_DEV_DUMP_NULL, ++ HINIC3_FLOW_ERROR_NO_EXIST_FLOW, ++ HINIC3_FLOW_ERROR_FLOW_NOT_READY, ++ HINIC3_FLOW_ERROR_FLOW_BLOCK_ERR, ++ // OVSOFF ++ HINIC3_FLOW_AGENT_ERROR_IGNORE_CT_FOR_PUSH, ++ HINIC3_FLOW_OVS_ERROR_FLOW_RECIRC_BY_PACKET, ++ HINIC3_FLOW_OVS_ERROR_FLOW_GENERATE_BY_PACKET, ++ HINIC3_FLOW_OVS_ERROR_OFFLOAD_BY_PACKET, ++ // 初始化模块 ++ HINIC3_FLOW_AGENT_ERROR_FORWARD_ENGINE_NOT_READY, ++ // 卸载策略模块 ++ HINIC3_FLOW_AGENT_STATS_OFFLOAD_DELAY, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_LIMITS, ++ HINIC3_FLOW_AGENT_ERROR_NO_CONN_TABLE, ++ HINIC3_FLOW_AGENT_ERROR_NOT_USER_PERMISSION, ++ HINIC3_FLOW_AGENT_ERROR_DUPLICATE_OFFLOAD, ++ HINIC3_FLOW_AGENT_ERROR_POLICY_ILLEGAL_INPUT, ++ HINIC3_FLOW_AGENT_ERROR_POLICY_ILLEGAL_OFFLOAD_TIME, ++ HINIC3_FLOW_OVS_POLICY_CHECK_NO_OFFLOAD, ++ HINIC3_FLOW_OVS_ERROR_POLICY_REACH_USER_LIMITS, ++ HINIC3_FLOW_OVS_POLICY_INTERNAL_ERROR, ++ HINIC3_FLOW_AGENT_POLICY_LOW_SPEED_FLOW_DEL, ++ HINIC3_FLOW_AGENT_POLICY_LOW_SPEED_ERROR, ++ HINIC3_FLOW_OVS_POLICY_HASH_TABLE_DEL_FAIL, ++ HINIC3_FLOW_AGENT_ERROR_POLICY_CALLBACK_ILLEGAL_INPUT, ++ // 端口模块 ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_DISABLE, ++ HINIC3_VPORT_VIRTUAL_QUEUE_RECV_PKTS_DISTRIBUTE_DROP, ++ HINIC3_VPORT_RX_QUEUE_INVALID, ++ HINIC3_VPORT_VIRTUAL_RX_QUEUE_INVALID, ++ HINIC3_VPORT_TX_QUEUE_INVALID, ++ HINIC3_VPORT_DEV_PRIVATE_DATA_NULL, ++ HINIC3_FLOW_AGENT_ERROR_FLOW_QUERY_INPUT_NULL, ++ HINIC3_FLOW_AGENT_ERROR_FLOW_CREATE_INPUT_NULL, ++ HINIC3_FLOW_AGENT_ERROR_FLOW_DEL_INPUT_NULL, ++ HINIC3_FLOW_AGENT_ERROR_FLOW_GET_PORT_ID, ++ HINIC3_FLOW_AGENT_ERROR_UPCALL_PRIORITY, ++ // qos模块 ++ HINIC3_FLOW_AGENT_ERROR_SET_MULTI_QOS, ++ // ovs 解包模块 ++ HINIC3_FLOW_OVS_ERROR_FLOW_NO_OUTPUT_PORT, ++ HINIC3_FLOW_OVS_ERROR_FLOW_MUTIL_OUTPUT_PORT, ++ HINIC3_FLOW_OVS_ERROR_OFFLOAD_FULLKEY_VPORT_FAIL, ++ HINIC3_FLOW_OVS_ERROR_OFFLOAD_PARSE_HDR_FAIL, ++ HINIC3_PACKET_ERROR_MBUF_GET_FIAL, ++ HINIC3_PACKET_ERROR_PARSE_ACTION, ++ HINIC3_PACKET_ERROR_PARSE_PKT_EXTRACT, ++ HINIC3_PACKET_ERROR_PARSE_PKT_INFO, ++ HINIC3_PACKET_ERROR_PARSE_HDR_PARSE, ++ HINIC3_FLOW_AGENT_ERROR_IP_FRAGMENT, ++ HINIC3_FLOW_AGENT_ERROR_IPV6_ICMP_NOT_ECHO, ++ HINIC3_FLOW_AGENT_ERROR_BROADCAST_PKT, ++ HINIC3_FLOW_AGENT_ERROR_NO_PKT_INFO, ++ HINIC3_FLOW_AGENT_ERROR_EXTRACT_PKT, ++ HINIC3_FLOW_AGENT_ERROR_TRANS_KEY, ++ HINIC3_FLOW_AGENT_ERROR_PROC_OFFLOAD_PKTS_FAILED, ++ HINIC3_ERRSTAT_END ++}; ++ ++enum hinic3_errstat_level { ++ HINIC3_ERRSTAT_LEVEL_ERROR, ++ HINIC3_ERRSTAT_LEVEL_WARNING ++}; ++ ++struct hinic3_error_stats { ++ enum hinic3_module module; ++ enum hinic3_errstat_level level; ++ uint64_t count; ++ const char *string; ++}; ++ ++void hinic3_add_error_stats(enum hinic3_errstat_type index, uint32_t count); ++int hinic3_get_error_stats(enum hinic3_errstat_type index, struct hinic3_error_stats* stats); ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_eth_packets.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_eth_packets.h +new file mode 100644 +index 0000000..a25a536 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_eth_packets.h +@@ -0,0 +1,114 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_PACKETS_H ++#define HINIC3_PACKETS_H ++ ++#include ++#include ++#include "hinic3_types.h" ++ ++#define IP_ARGS(ip) \ ++ ntohl(ip) >> 24, \ ++ (ntohl(ip) >> 16) & 0xff, \ ++ (ntohl(ip) >> 8) & 0xff, \ ++ ntohl(ip) & 0xff ++ ++#define ETH_TYPE_IP 0x0800 ++#define ETH_TYPE_ARP 0x0806 ++#define ETH_TYPE_VLAN_8021Q 0x8100 ++#define ETH_TYPE_VLAN ETH_TYPE_VLAN_8021Q ++#define ETH_TYPE_VLAN_8021AD 0x88a8 ++#define ETH_TYPE_IPV6 0x86dd ++#define ETH_TYPE_RARP 0x8035 ++ ++#define ETH_ADDR_LEN 6 ++ ++#define ETH_ADDR_FMT \ ++ "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8 ++ ++#define ETH_ADDR_ARGS(EA) \ ++ ((EA).ea)[0], ((EA).ea)[1], ((EA).ea)[2], ((EA).ea)[3], ((EA).ea)[4], ((EA).ea)[5] ++ ++#define IP_FMT "%"PRIu32".%"PRIu32".%"PRIu32".%"PRIu32 ++ ++#define ETH_HEADER_LEN 14 ++ ++struct eth_addr { ++ union { ++ uint8_t ea[6]; ++ uint16_t be16[3]; ++ }; ++}; ++ ++struct eth_header { ++ struct eth_addr eth_dst; ++ struct eth_addr eth_src; ++ uint16_t eth_type; ++}; ++ ++#define VLAN_HEADER_LEN 4 ++struct vlan_header { ++ uint16_t vlan_tci; /* Lowest 12 bits are VLAN ID. */ ++ uint16_t vlan_next_type; ++}; ++ ++#define IP_DONT_FRAGMENT 0x4000 /* Don't fragment. */ ++#define IP_MORE_FRAGMENTS 0x2000 /* More fragments. */ ++#define IP_FRAG_OFF_MASK 0x1fff /* Fragment offset. */ ++#define IP_IS_FRAGMENT(ip_frag_off) \ ++ ((ip_frag_off) & htons(IP_MORE_FRAGMENTS | IP_FRAG_OFF_MASK)) ++ ++#define IP_IHL(ip_ihl_ver) ((ip_ihl_ver) & 15) ++ ++struct ip_header { ++ uint8_t ip_ihl_ver; ++ uint8_t ip_tos; ++ uint16_t ip_tot_len; ++ uint16_t ip_id; ++ uint16_t ip_frag_off; ++ uint8_t ip_ttl; ++ uint8_t ip_proto; ++ uint16_t ip_csum; ++ hinic3_16aligned_be32 ip_src; ++ hinic3_16aligned_be32 ip_dst; ++}; ++ ++#define UDP_HEADER_LEN 8 ++struct udp_header { ++ uint16_t udp_src; ++ uint16_t udp_dst; ++ uint16_t udp_len; ++ uint16_t udp_csum; ++}; ++ ++#define TCP_HEADER_LEN 20 ++struct tcp_header { ++ uint16_t tcp_src; ++ uint16_t tcp_dst; ++ hinic3_16aligned_be32 tcp_seq; ++ hinic3_16aligned_be32 tcp_ack; ++ uint16_t tcp_ctl; ++ uint16_t tcp_winsz; ++ uint16_t tcp_csum; ++ uint16_t tcp_urg; ++}; ++ ++static inline bool eth_type_vlan(uint16_t eth_type) ++{ ++ return eth_type == htons(ETH_TYPE_VLAN_8021Q) || ++ eth_type == htons(ETH_TYPE_VLAN_8021AD); ++} ++ ++static inline bool eth_addr_is_zero(const struct eth_addr a) ++{ ++ return !(a.be16[0] | a.be16[0x1] | a.be16[0x2]); ++} ++ ++static inline bool eth_addr_is_multicast(const struct eth_addr a) ++{ ++ return a.ea[0] & 1; ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c +new file mode 100644 +index 0000000..2cefeaa +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c +@@ -0,0 +1,293 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_file_util.h" ++ ++#define HINIC3_FILE_USAGE_CMD_LEN 256 ++#define HINIC3_FILE_OUTER_DIRECTORY_PATH "/var/log/dpak/" ++#define HINIC3_FILE_DIRECTORY_PATH "/var/log/dpak/dpak_ovs_data/" ++#define HINIC3_FILE_USER "dpak_maint" ++#define HINIC3_FILE_GROUP "dpak_ovs" ++#define HINIC3_FILE_USAGE_RESULT_LEN 64 ++#define HINIC3_FILE_INNER_PRIVILEGE 0750 ++#define HINIC3_FILE_SIZE_KB 1024 ++#define HINIC3_FILE_SIZE_MB (HINIC3_FILE_SIZE_KB * HINIC3_FILE_SIZE_KB) ++ ++static int hinic3_get_absolute_file_path(const char *file_name, char *absolute_path, int len) ++{ ++ int ret; ++ ++ if (strchr(file_name, '/') != NULL) { ++ HINIC3_LOG(ERR, AGENT, "wrong file name (%s).", file_name); ++ return -1; ++ } ++ ++ ret = snprintf(absolute_path, len, "%s%s", HINIC3_FILE_DIRECTORY_PATH, file_name); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "get absolute path fail.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static bool hinic3_check_directory_existence(char *path) ++{ ++ struct stat info; ++ ++ // 检查路径是否存在 ++ if (access(path, F_OK) != 0) { ++ return false; ++ } ++ ++ // 获取文件状态 ++ if (stat(path, &info) != 0) { ++ return false; ++ } ++ ++ // 检查是否目录 ++ return (info.st_mode & S_IFDIR) ? true : false; ++} ++ ++static int hinic3_mkdir(char *path) ++{ ++ char dir_path[PATH_MAX]; ++ struct passwd *user = NULL; ++ struct group *grp = NULL; ++ int ret; ++ ++ ret = snprintf(dir_path, PATH_MAX, "%s", path); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "get file directory fail, path: %s.\n", path); ++ return -1; ++ } ++ ++ if (mkdir(dir_path, HINIC3_FILE_INNER_PRIVILEGE) && errno != EEXIST) { ++ HINIC3_LOG(ERR, AGENT, "create file directory fail, path: %s.\n", path); ++ return -1; ++ } ++ ++ user = getpwnam(HINIC3_FILE_USER); ++ if (user == NULL) { ++ HINIC3_LOG(ERR, AGENT, "get file directory user fail, path: %s", path); ++ return 0; ++ } ++ grp = getgrnam(HINIC3_FILE_GROUP); ++ if (grp == NULL) { ++ HINIC3_LOG(ERR, AGENT, "get file directory group fail, path: %s", path); ++ return 0; ++ } ++ ++ if (hinic3_check_masked_to_exact_switch() == false) { ++ if (chown(path, -1, grp->gr_gid) == -1) { ++ HINIC3_LOG(ERR, AGENT, "change file directory group fail, path: %s", path); ++ return 0; ++ } ++ } else { ++ if (chown(path, user->pw_uid, grp->gr_gid) == -1) { ++ HINIC3_LOG(ERR, AGENT, "change file directory user and group fail, path: %s", path); ++ return 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static int hinic3_check_directory(char *path) ++{ ++ if (hinic3_check_directory_existence(path) == true) { ++ return 1; ++ } else if (hinic3_check_directory_existence(HINIC3_FILE_OUTER_DIRECTORY_PATH) == false) { ++ HINIC3_LOG(INFO, AGENT, "directory not exist, path: %s.\n", ++ HINIC3_FILE_OUTER_DIRECTORY_PATH); ++ return -1; ++ } ++ ++ if (hinic3_mkdir(path) != 0) { ++ HINIC3_LOG(ERR, AGENT, "create file directory fail, path: %s.\n", path); ++ return -1; ++ } ++ return 0; ++} ++ ++uint64_t hinic3_get_default_file_directory_size(bool *is_obtained) ++{ ++ char cmd[HINIC3_FILE_USAGE_CMD_LEN]; ++ char result[HINIC3_FILE_USAGE_RESULT_LEN] = {0}; ++ char *endptr = NULL; ++ FILE *file = NULL; ++ uint64_t real_size = 0; ++ int ret; ++ ++ ret = snprintf(cmd, HINIC3_FILE_USAGE_CMD_LEN, "du -BM %s | cut -f1", HINIC3_FILE_DIRECTORY_PATH); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "get directory path fail, path: %s.\n", HINIC3_FILE_DIRECTORY_PATH); ++ *is_obtained = false; ++ return 0; ++ } ++ ++ file = popen(cmd, "r"); ++ if (file == NULL) { ++ HINIC3_LOG(ERR, AGENT, "open directory size fail, path: %s.\n", HINIC3_FILE_DIRECTORY_PATH); ++ *is_obtained = false; ++ return 0; ++ } ++ ++ while (fgets(result, HINIC3_FILE_USAGE_RESULT_LEN, file) != NULL) { ++ real_size = strtoul(result, &endptr, STR_TO_DEC_NUM); ++ if (endptr == NULL || *endptr != 'M') { ++ HINIC3_LOG(ERR, AGENT, "convert directory size fail, path: %s.\n", HINIC3_FILE_DIRECTORY_PATH); ++ pclose(file); ++ *is_obtained = false; ++ return 0; ++ } ++ ++ pclose(file); ++ *is_obtained = true; ++ return real_size; ++ } ++ ++ pclose(file); ++ HINIC3_LOG(ERR, AGENT, "get directory size fail.\n"); ++ *is_obtained = false; ++ return 0; ++} ++ ++static bool hinic3_is_directory_reach_limit(void) ++{ ++ uint64_t real_size = 0; ++ uint32_t directory_size_max = hinic3_disk_usage_get(); ++ int ret; ++ bool is_obtained = false; ++ ++ ret = hinic3_check_directory(HINIC3_FILE_DIRECTORY_PATH); ++ if (ret < 0) { ++ HINIC3_LOG(ERR, AGENT, "check directory fail, path: %s.", HINIC3_FILE_DIRECTORY_PATH); ++ return true; ++ } ++ ++ real_size = hinic3_get_default_file_directory_size(&is_obtained); ++ if (is_obtained == false) { ++ HINIC3_LOG(ERR, AGENT, "get directory real size fail, path: %s.", HINIC3_FILE_DIRECTORY_PATH); ++ return true; ++ } else if (real_size >= directory_size_max) { ++ HINIC3_LOG(ERR, AGENT, "directory %s size %" PRIu64 "MB reachs or exceeds the limit %uMB.\n", ++ HINIC3_FILE_DIRECTORY_PATH, real_size, directory_size_max); ++ return true; ++ } ++ ++ return false; ++} ++ ++int hinic3_agent_chown_output_file_path(const char *resolve_path) ++{ ++ struct group *grp = getgrnam(HINIC3_OVS_GROUP_NAME); ++ if (grp != NULL) { ++ gid_t group_id = grp->gr_gid; ++ if (chown(resolve_path, -1, group_id) == -1) { ++ HINIC3_LOG(ERR, AGENT, "chown fail, errno: %d", errno); ++ return -1; ++ } ++ } else { ++ HINIC3_LOG(ERR, AGENT, "getgrnam %s fail", HINIC3_OVS_GROUP_NAME); ++ return -1; ++ } ++ return 0; ++} ++ ++int hinic3_check_output_file_directory(const char *filename, char *absolute_path, unsigned int path_len, struct ds *ds) ++{ ++ int ret; ++ uint64_t dir_size; ++ bool is_obtained = false; ++ ++ if (filename == NULL || absolute_path == NULL || ds == NULL || path_len == 0 || path_len > PATH_MAX) { ++ HINIC3_LOG(ERR, AGENT, "input param is invalid.\n"); ++ return -1; ++ } ++ ++ ret = hinic3_get_absolute_file_path(filename, absolute_path, path_len); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_GET_ABSOLUTE_PATH_FAIL_STRING, HINIC3_UI_LEADING_SIGN_ERROR, filename); ++ return -1; ++ } ++ ++ if (hinic3_is_directory_reach_limit()) { ++ dir_size = hinic3_get_default_file_directory_size(&is_obtained); ++ if (is_obtained == false) { ++ hinic3_ds_put_format(ds, "%sGet directory real size fail, path: %s.\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_FILE_DIRECTORY_PATH); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_NO_SPACE_STRING, HINIC3_UI_LEADING_SIGN_FAILURE, filename); ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_DIRECTORY_SIZE_REACH_LIMIT_STRING, HINIC3_UI_INDENT_SPACE, ++ hinic3_get_default_directory(), dir_size, hinic3_disk_usage_get()); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++const char *hinic3_get_default_directory(void) ++{ ++ return HINIC3_FILE_DIRECTORY_PATH; ++} ++ ++uint64_t hinic3_get_partition_free_space_size(void) ++{ ++ struct statvfs stat; ++ uint64_t available_space; ++ int ret; ++ ++ ret = hinic3_check_directory(HINIC3_FILE_DIRECTORY_PATH); ++ if (ret < 0) { ++ HINIC3_LOG(ERR, AGENT, "check directory fail, path: %s.", HINIC3_FILE_DIRECTORY_PATH); ++ return 0; ++ } ++ ++ if (statvfs(HINIC3_FILE_DIRECTORY_PATH, &stat) != 0) { ++ HINIC3_LOG(ERR, AGENT, "get partition free space size fail, errno: %s, path: %s.\n", strerror(errno), ++ HINIC3_FILE_DIRECTORY_PATH); ++ return 0; ++ } ++ ++ available_space = stat.f_frsize * stat.f_bavail; ++ ++ return (uint64_t)ceil(available_space / HINIC3_FILE_SIZE_MB); ++} ++ ++int hinic3_check_file_realpath(const char *absolute_path, char *resolve_path, struct ds *ds) ++{ ++ char *result = realpath(absolute_path, resolve_path); ++ ++ if (result == NULL) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_PATH_CREATE_STRING, HINIC3_UI_LEADING_SIGN_INFO, resolve_path); ++ } else { ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_PATH_APPEND_STRING, HINIC3_UI_LEADING_SIGN_INFO, resolve_path); ++ } ++ ++ if ((strlen(resolve_path) == 0) || (strlen(resolve_path) >= PATH_MAX)) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_PATH_TIPS_STRING, HINIC3_UI_LEADING_SIGN_ERROR, resolve_path); ++ return -1; ++ } ++ ++ if (strcmp(resolve_path, absolute_path) != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_FILE_NOT_ABSOLUTE_PATH_STRING); ++ return -1; ++ } ++ ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h +new file mode 100644 +index 0000000..70313bf +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FILE_USAGE_H ++#define HINIC3_FILE_USAGE_H ++ ++#include ++#include ++#include "hinic3_ds.h" ++ ++const char *hinic3_get_default_directory(void); ++int hinic3_check_output_file_directory(const char *filename, char *absolute_path, unsigned int path_len, struct ds *ds); ++int hinic3_agent_chown_output_file_path(const char *resolve_path); ++uint64_t hinic3_get_default_file_directory_size(bool *is_obtained); ++uint64_t hinic3_get_partition_free_space_size(void); ++int hinic3_check_file_realpath(const char *absolute_path, char *resolve_path, struct ds *ds); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_enum.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_enum.h +new file mode 100644 +index 0000000..fcad0a4 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_enum.h +@@ -0,0 +1,93 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FLOW_AGNET_ENUM_H ++#define HINIC3_FLOW_AGNET_ENUM_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++enum { ++ VXLAN_STATUS_NONE = 0, ++ VXLAN_STATUS_ENCAP, ++ VXLAN_STATUS_DECAP ++}; ++ ++enum { ++ VLAN_STATUS_NONE = 0, ++ VLAN_STATUS_PUSH ++}; ++ ++enum hinic3_flow_engine_bit_type { ++ HINIC3_ENG_CAP_F_BATCH_DEL, ++ HINIC3_ENG_CAP_F_OFFLOAD_RAW_IP, ++ HINIC3_ENG_CAP_F_OFFLOAD_ETHERNET, ++ HINIC3_ENG_CAP_F_STATS_SYNC_PULL, ++ HINIC3_ENG_CAP_F_OFFLOAD_ICMP, ++ HINIC3_ENG_CAP_F_OFFLOAD_IPV6, ++ HINIC3_ENG_CAP_F_OFFLOAD_ICMPV6, ++ HINIC3_ENG_CAP_F_OFFLOAD_3TUPLE, ++ HINIC3_ENG_CAP_F_ASYNC_FLUSH, ++ HINIC3_ENG_CAP_F_MAX ++}; ++ ++enum { ++ /* 0, not offload any flow */ ++ HINIC3_ESCAPE_MODE_NO_OFFLOAD, ++ /* 1, not offload ipv6 flow */ ++ HINIC3_ESCAPE_MODE_NO_IPV6_OFFLOAD, ++ /* 2, offload all flows */ ++ HINIC3_ESCAPE_MODE_ALL_OFFLOAD, ++ HINIC3_ESCAPE_MODE_MAX ++}; ++ ++enum offload_flow_status { ++ HINIC3_FLOW_OFFLOAD_FAILED, ++ HINIC3_FLOW_OFFLOAD_SUCCESS, ++ HINIC3_FLOW_OFFLOAD_DOING, ++}; ++ ++ ++enum hinic3_offload_mode_status { ++ HINIC3_FLOW_OFFLOAD_ENABLE, ++ HINIC3_FLOW_OFFLOAD_DISABLE, ++}; ++ ++enum hinic3_module { ++ HINIC3_COMMON_RESOURCE, ++ HINIC3_CAPTURE, ++ HINIC3_COMMAND, ++ HINIC3_CT_OFFLOAD, ++ HINIC3_DRIVER_ADAPTER, ++ HINIC3_FLOWS, ++ HINIC3_OVS_FLOW, ++ HINIC3_INIT, ++ HINIC3_POLICY, ++ HINIC3_PORTS, ++ HINIC3_QOS, ++ HINIC3_SECURITY_FILTER, ++ HINIC3_UFID_MAP, ++ HINIC3_OVS_MEMPOOL, ++ HINIC3_OVS_UFID_MEMPOOL, ++ HINIC3_OVS_UFID_MAP, ++ HINIC3_PACKET_PARSE, ++ HINIC3_OVS_SMAC, ++ HINIC3_OVS_HINIC3_PRIVATE, ++ HIOVS_MEM, ++ HINIC3_MODULE_MAX ++}; ++ ++#define HINIC3_MODULE_NAME_MAX 30 ++ ++struct hinic3_module_name { ++ enum hinic3_module module_id; ++ char module_name[HINIC3_MODULE_NAME_MAX]; ++}; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_public.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_public.h +new file mode 100644 +index 0000000..25e1533 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_flow_agent_public.h +@@ -0,0 +1,336 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FLOW_AGNET_PUBLIC_H ++#define HINIC3_FLOW_AGNET_PUBLIC_H ++ ++#include "rte_flow.h" ++#include "rte_config.h" ++#include "rte_spinlock.h" ++#include "hinic3_list.h" ++#include "dpak_cfg.h" ++#include ++#include "hinic3_packet_key_public.h" ++#include "hinic3_thread.h" ++#include "hinic3_mutex.h" ++#include "hinic3_map.h" ++#include "hinic3_trace_flow.h" ++#include "hinic3_flow_agent_enum.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_RX_THREAD_MAX 16 ++#define HINIC3_FLOW_STATS_BLOCK_SIZE 128 ++#define HINIC3_THREAD_NAME_MAX 16 ++#define HINIC3_COMMAND_QUEUES_NUM_MAX HINIC3_RX_THREAD_MAX ++#define HINIC3_NETDEV_CLASS_NUM 16 ++#define HINIC3_MAX_ENTRY_PER_STATS_DUMP 1000 ++#define HINIC3_MAX_ENTRY_PER_BATCH_DEL 128 ++#define HINIC3_ESCAPE_MODE_OFFSET 0U ++#define HINIC3_FORWARD_MODE_OFFSET 3U ++#define HINIC3_MODE_VERSION_OFFSET 6U ++ ++#define HINIC3_THREAD_RX_BURST_MAX 256 ++#define HINIC3_MAX_OFFLOAD_CORE_CNT 16 ++#define HINIC3_MAX_PMD_CORE_CNT 32 ++#define HINIC3_MAX_DPDK_CORE_CNT 32 ++#define HINIC3_CORE_MASK_LEN_MAX 256 ++ ++#define MAX_PKT_BURST 32 ++#define BUFSIZE_SHORT 1024 ++#define PKT_MAX_ASSOCIATED_FLOWS 16 ++#define HINIC3_MSG_MAX_BUF 512 ++#define HINIC3_MAX_LCORE_COUNT 128 ++#define HINIC3_MAX_UNIXCTL_MAX_LEN 1024 ++ ++#define HINIC3_BYTE_BITS 8 ++#define HINIC3_SHORT_BITS 16 ++ ++#define HINIC3_RAW_ACTION_NUM 10 ++ ++#define HINIC3_LOW_EIGHT_BIT_MASK 0xFF ++#define HINIC3_MID_EIGHT_BIT_MASK 0XFF00 ++#define HINIC3_HIGH_EIGHT_BIT_MASK 0XFF0000 ++#define HINIC3_BIT_MID_MOVE_INDEX 8 ++#define HINIC3_BIT_HIGH_MOVE_INDEX 16 ++#define HINIC3_TCP_PROTO 6 ++#define HINIC3_UDP_PROTO 17 ++#define HINIC3_VNI_ARR_LOW 0 ++#define HINIC3_VNI_ARR_MID 1 ++#define HINIC3_VNI_ARR_HIGH 2 ++#define HINIC3_VNI_ARR_SIZE 3 ++ ++typedef union { ++ uint32_t u32[4]; ++ struct { ++#ifdef WORDS_BIGENDIAN ++ uint64_t hi, lo; ++#else ++ uint64_t lo, hi; ++#endif ++ } u64; ++} hinic3_u128; ++ ++struct rte_flow { ++ /* rte_flow mega ufid. */ ++ hinic3_u128 mega_ufid; ++ /* hardware flow ufid. */ ++ uint64_t hw_ufid; ++ /* Number of packets matched in last query. */ ++ uint64_t sw_packets; ++ /* Number of bytes matched in last query. */ ++ uint64_t sw_bytes; ++ /* Number of packets matched in up-to-date query. */ ++ uint64_t hw_packets; ++ /* Number of bytes matched in up-to-date query. */ ++ uint64_t hw_bytes; ++ bool is_deleted; ++ void* flow_data; ++ rte_spinlock_t lock; ++ ++ uint32_t hash; ++ ++ uint8_t session_id; ++ uint16_t port_id; ++ uint32_t flow_hash; ++ struct hinic3_conntrack_full_key key; ++ struct { ++ uint32_t is_acl : 1; ++ uint32_t is_mega : 1; ++ uint32_t is_offload : 1; ++ uint32_t is_sample : 2; ++ uint32_t is_mem_used : 1; ++ uint32_t live_time : 13; ++ uint32_t is_dp_hash : 1; ++ uint32_t is_aged : 1; ++ uint32_t is_dumb : 1; ++ uint32_t is_qos : 1; ++ uint32_t qos_index : 2; ++ uint32_t reserved : 7; ++ } flags; ++}; ++ ++struct hinic3_flow_capability { ++ uint32_t vendor_id; ++ uint32_t supported_dev_types; ++ uint32_t supported_actions; ++ uint8_t key_format_type; ++ uint8_t cleanup_max_level; ++ uint16_t flags; ++ uint32_t max_flow_size; ++ uint32_t rx_thread_num; ++ uint32_t cmd_queue_base; ++ uint32_t cmd_queue_num; ++}; ++ ++struct hinic3_flow_stats { ++ /* Number of packets matched. */ ++ uint64_t packet_count; ++ /* Number of bytes matched. */ ++ uint64_t byte_count; ++ /* Number of packets dropped for CT failure. */ ++ uint64_t ct_loss_pkts; ++ /* Remain life time of flow, unit : ms */ ++ uint32_t live_time; ++ /* Total life time of flow, unit : ms */ ++ uint32_t age_time; ++ uint16_t tcp_flags; ++ uint8_t block[HINIC3_FLOW_STATS_BLOCK_SIZE]; ++}; ++ ++struct hinic3_offload_thread_data { ++ pthread_t thread; ++ uint32_t thread_id; ++ uint32_t exit; ++ struct hinic3_dp_extend_info *dp_info; ++ char name[HINIC3_THREAD_NAME_MAX]; ++ uint32_t cur_buk_idx; ++ uint32_t min_buk_idx; ++ uint32_t max_buk_idx; ++}; ++ ++struct hinic3_forward_engine_info { ++ uint32_t port_id; ++ uint32_t cmd_queue_base; ++ uint32_t cmd_queue_num; ++ struct rte_mempool *cmd_mbuf_pool; ++}; ++ ++ ++struct hinic3_dp_extend_info { ++ /* Private data of flow agent */ ++ void *hw_offload; ++ /* offload thread */ ++ struct hinic3_offload_thread_data *offload_threads; ++ /* offload thread operations */ ++ struct hinic3_rx_thread_ops *offload_thread_ops; ++ /* Information of forward engine */ ++ struct hinic3_forward_engine_info forward_engine; ++ /* Core info in env */ ++ uint32_t offload_num_in_env; ++ uint32_t offload_thread_core[HINIC3_CPU_MASK_NUM]; ++ uint32_t control_num_in_env; ++ uint32_t control_thread_core[HINIC3_CPU_MASK_NUM]; ++}; ++ ++struct hinic3_rx_thread_ops { ++ void (*rx_put_ack)(uint32_t thread_id, struct hinic3_dp_extend_info *dp_info); ++ void (*rx_age_notice)(uint32_t thread_id, const struct hinic3_dp_extend_info *dp_info); ++ void (*del_sw_flow)(uint32_t thread_id, const struct hinic3_dp_extend_info *dp_info); ++ int (*sync_stats)(uint32_t thread_id, struct hinic3_dp_extend_info *dp_info); ++}; ++ ++struct hinic3_netdev_class_info { ++ uint64_t id; ++ char *name; ++}; ++struct hinic3_forward_engine { ++ /* Information from forward engine */ ++ struct hinic3_flow_capability cap; ++ ++ /* Information Derived from above */ ++ struct { ++ uint32_t use_hw_ifindex : 1; ++ uint32_t reserved : 31; ++ }; ++ /* lock to protect current_flow_size */ ++ rte_spinlock_t lock; ++ rte_atomic32_t current_flow_size; ++ int netdev_class_num; ++ struct hinic3_netdev_class_info supported_netdev_class[HINIC3_NETDEV_CLASS_NUM]; ++}; ++ ++struct hinic3_sw_flow { ++ hinic3_u128 mega_ufid; ++ int actions_size; ++ uint8_t actions[BUFSIZE_SHORT]; ++ struct rte_flow_action raw_action[HINIC3_RAW_ACTION_NUM]; ++ bool action_recorded; ++}; ++ ++struct hinic3_pkt_info { ++ struct { ++ uint16_t offload : 2; ++ uint16_t vxlan : 2; ++ uint16_t ct_establish : 1; ++ uint16_t ct_tracked : 1; ++ uint16_t snat : 1; ++ uint16_t dnat : 1; ++ uint16_t orig_tuple : 1; ++ uint16_t first_ct_notrack : 1; ++ uint16_t last_ct_notrack : 1; ++ /* Outer vlan of transmited packet is pushed by OVS actions */ ++ uint16_t pushed_outer_vlan : 1; ++ /* Inner vlan of transmited packet is pushed by OVS actions */ ++ uint16_t pushed_inner_vlan : 1; ++ uint16_t snat_before_ct : 1; ++ uint16_t dnat_before_ct : 1; ++ uint16_t nat_done_by_ct : 1; ++ /* Flag of cvlan in QinQ is recorded */ ++ uint16_t cvlan : 1; ++ uint16_t vxlan_poped : 1; ++ /* if already fail, we will not process this packet in the left circles, because some action was not recorded */ ++ uint16_t already_fail : 1; ++ } status; ++ ++ struct { ++ uint16_t ct_action_exist : 1; ++ uint16_t encap_action_exist : 1; ++ } cur_round_status; ++ /* push vlan for receiving packet by OVS actions */ ++ uint16_t push_vlan_id; ++ /* Inner vlan of received packet is popped by OVS actions */ ++ uint16_t popped_inner_vlan; ++ /* Inner vlan of double vlan in QinQ */ ++ uint16_t inner_cvlan; ++ uint16_t input_port; ++ uint32_t input_port_type; ++ uint16_t first_ct_zone; ++ uint16_t last_ct_zone; ++ uint8_t flows_num; ++ uint32_t hw_conn_id; ++ uint32_t vxlan_vni; ++ ++ /* Above area will be cleared when init */ ++ uint8_t is_used : 1; ++ uint8_t is_recircle : 1; ++ uint8_t padings : 6; ++ struct hinic3_sw_flow associated_flows[PKT_MAX_ASSOCIATED_FLOWS]; ++}; ++ ++struct hinic3_pmd_status { ++ /* This sequence will add in every PMD receive round */ ++ uint32_t rx_seq; ++ struct hinic3_pkt_info pkt_info_bufs[MAX_PKT_BURST]; ++}; ++ ++struct hinic3_offload_buf_s { ++ uint8_t key_buf[HINIC3_MSG_MAX_BUF]; ++ uint8_t actions_buf[HINIC3_MSG_MAX_BUF]; ++ uint8_t final_actions_buf[HINIC3_MSG_MAX_BUF]; ++ uint8_t args_buf[HINIC3_MSG_MAX_BUF]; ++}; ++ ++struct hinic3_rarp_mac_s { ++ uint8_t mac[ETH_ALEN]; ++ long long int last_proc_time; ++ struct hinic3_list node; ++}; ++ ++struct hinic3_pkt_key_cache_s { ++ int count; ++ struct hinic3_conntrack_full_key full_key_list[MAX_PKT_BURST]; ++}; ++ ++struct hinic3_virtio_queue { ++ uint32_t total_count; ++ uint32_t used_now; ++}; ++ ++struct hinic3_flow_agent_db { ++ /* Forward engine capability description */ ++ struct hinic3_forward_engine forward_engine; ++ rte_spinlock_t operate_disable_lock; ++ /* change offload disable status operate count */ ++ uint16_t operate_disable; ++ uint16_t escape_mode; ++ /* How long can offload entry live */ ++ uint32_t live_time; ++ uint16_t pmd_status_num; ++ struct hinic3_pmd_status *pmd_status; ++ struct hinic3_offload_buf_s offload_buf_list[HINIC3_MAX_LCORE_COUNT]; ++ struct hinic3_list pmd_rarp_list[HINIC3_MAX_LCORE_COUNT]; ++ /* The time when next hardware stats syncing is to do */ ++ long long next_hw_stats_sync[HINIC3_COMMAND_QUEUES_NUM_MAX]; ++ struct hinic3_trace_flow trace_flow_info; ++ struct hinic3_virtio_queue queue_num; ++ uint32_t max_block_num; ++ uint16_t vxlan_dst_port; ++}; ++ ++struct hinic3_stats_dump_context { ++ void *dp_info; ++ /* current num of hardware flow */ ++ uint32_t num_entries; ++ /* total num of hardware flow */ ++ uint32_t total_hw_num; ++ /* per thread limits num of hardware flow */ ++ uint32_t total_num_limit; ++ /* sync start time */ ++ long long start_time; ++ /* per dump private info */ ++ void *priv_data[HINIC3_MAX_ENTRY_PER_STATS_DUMP]; ++ /* per dump ufid list */ ++ uint64_t ufids[HINIC3_MAX_ENTRY_PER_STATS_DUMP]; ++ /* per dump statistics info */ ++ struct hinic3_flow_stats stats[HINIC3_MAX_ENTRY_PER_STATS_DUMP]; ++}; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c +new file mode 100644 +index 0000000..55346db +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c +@@ -0,0 +1,472 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_hugepage_meminfo.h" ++#include "hinic3_dpdk_adapter.h" ++ ++static struct hinic3_hugepage_mem_statistics g_hugepage_mem_statistics = {0}; ++static struct hinic3_module_name g_module_name[] = { ++ {HINIC3_COMMON_RESOURCE, "hinic3-common-resource"}, ++ {HINIC3_CAPTURE, "hinic3-capture"}, ++ {HINIC3_COMMAND, "hinic3-command"}, ++ {HINIC3_CT_OFFLOAD, "hinic3-ct-offload"}, ++ {HINIC3_DRIVER_ADAPTER, "hinic3-driver-adapter"}, ++ {HINIC3_FLOWS, "hinic3-flows"}, ++ {HINIC3_OVS_FLOW, "hinic3-ovs-flows"}, ++ {HINIC3_INIT, "hinic3-init"}, ++ {HINIC3_POLICY, "hinic3-policy"}, ++ {HINIC3_PORTS, "hinic3-ports"}, ++ {HINIC3_QOS, "hinic3-qos"}, ++ {HINIC3_SECURITY_FILTER, "hinic3-security-filter"}, ++ {HINIC3_UFID_MAP, "hinic3-ufid-map"}, ++ {HINIC3_OVS_MEMPOOL, "hinic3-ovs-mempool"}, ++ {HINIC3_OVS_UFID_MEMPOOL, "hinic3-ovs-ufid-mempool"}, ++ {HINIC3_OVS_UFID_MAP, "hinic3-ovs-ufid-map"}, ++ {HINIC3_PACKET_PARSE, "hinic3-packet-parse"}, ++ {HINIC3_OVS_SMAC, "hinic3-ovs-smac"}, ++ {HINIC3_OVS_HINIC3_PRIVATE, "hinic3-ovs-private-data"}, ++ {HIOVS_MEM, "hiovs-mem"}, ++ {HINIC3_MODULE_MAX, "unknown module"}, ++}; ++ ++struct hinic3_hugepage_mem_statistics *hinic3_get_hugepage_meminfo(void) ++{ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return NULL; ++ } ++ return &g_hugepage_mem_statistics; ++} ++ ++const char *hinic3_get_module_name_from_module_id(enum hinic3_module module_id) ++{ ++ if (module_id >= 0 && module_id < HINIC3_MODULE_MAX) { ++ return g_module_name[module_id].module_name; ++ } ++ return g_module_name[HINIC3_MODULE_MAX].module_name; ++} ++ ++int hinic3_hugepage_meminfo_init(void) ++{ ++ int ret = 0; ++ // 初始化存储结构 ++ ret = hinic3_rwlock_init(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "heap meminfo rwlock init failed"); ++ goto heap_rwlock_failed; ++ } ++ ++ ret = hinic3_rwlock_init(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "memzone meminfo rwlock init failed"); ++ goto memzone_rwlock_failed; ++ } ++ ++ for (int i = HINIC3_COMMON_RESOURCE; i < HINIC3_MODULE_MAX; i++) { ++ g_hugepage_mem_statistics.heap_meminfo.allocated_size[i] = 0; ++ g_hugepage_mem_statistics.memzone_meminfo.allocated_size[i] = 0; ++ } ++ ++ ret = hinic3_pthread_mutex_init(&g_hugepage_mem_statistics.memzone_list.mutex); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "memzone list mutex init failed"); ++ goto memzone_mutex_failed; ++ } ++ ++ ret = hinic3_pthread_mutex_init(&g_hugepage_mem_statistics.mempool_list.mutex); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "mempool list mutex init failed"); ++ goto mempool_mutex_failed; ++ } ++ ++ hinic3_list_init(&g_hugepage_mem_statistics.memzone_list.list_head); ++ hinic3_list_init(&g_hugepage_mem_statistics.mempool_list.list_head); ++ return 0; ++ ++mempool_mutex_failed: ++ hinic3_pthread_mutex_destroy(&g_hugepage_mem_statistics.memzone_list.mutex); ++memzone_mutex_failed: ++ hinic3_rwlock_destroy(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++memzone_rwlock_failed: ++ hinic3_rwlock_destroy(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++heap_rwlock_failed: ++ return -1; ++} ++ ++void hinic3_hugepage_meminfo_uninit(void) ++{ ++ struct hinic3_rte_memzone_ele *iter = NULL; ++ struct hinic3_rte_memzone_ele *next = NULL; ++ struct hinic3_rte_mempool_ele *iter_pool = NULL; ++ struct hinic3_rte_mempool_ele *next_pool = NULL; ++ ++ LIST_FOR_EACH_SAFE(iter_pool, next_pool, node, &g_hugepage_mem_statistics.mempool_list.list_head) ++ { ++ hinic3_pthread_mutex_lock(&g_hugepage_mem_statistics.mempool_list.mutex); ++ hinic3_list_remove(&iter_pool->node); ++ hinic3_pthread_mutex_unlock(&g_hugepage_mem_statistics.mempool_list.mutex); ++ hinic3_rte_mempool_free(iter_pool->mempool); ++ iter_pool->mempool = NULL; ++ hinic3_free(iter_pool); ++ } ++ hinic3_pthread_mutex_destroy(&g_hugepage_mem_statistics.mempool_list.mutex); ++ ++ LIST_FOR_EACH_SAFE(iter, next, node, &g_hugepage_mem_statistics.memzone_list.list_head) ++ { ++ hinic3_pthread_mutex_lock(&g_hugepage_mem_statistics.memzone_list.mutex); ++ hinic3_list_remove(&iter->node); ++ hinic3_pthread_mutex_unlock(&g_hugepage_mem_statistics.memzone_list.mutex); ++ hinic3_rte_memzone_free(iter->memzone); ++ iter->memzone = NULL; ++ hinic3_free(iter); ++ } ++ hinic3_pthread_mutex_destroy(&g_hugepage_mem_statistics.memzone_list.mutex); ++ ++ hinic3_rwlock_destroy(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++ hinic3_rwlock_destroy(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++} ++ ++int hinic3_record_hugepage_meminfo(void *addr, enum hinic3_module module_id) ++{ ++ void *elem = addr - MALLOC_ELEM_HEADER_LEN; ++ size_t elem_size = ((struct malloc_elem *)elem)->size; ++ if (elem_size < MALLOC_ELEM_TRAILER_LEN + sizeof(struct hinic3_module_id)) { ++ HINIC3_LOG(ERR, AGENT, "failed to record hugepage meminfo"); ++ return -EINVAL; ++ } ++ struct hinic3_module_id *module_info = (struct hinic3_module_id *)(elem + ++ elem_size - MALLOC_ELEM_TRAILER_LEN - sizeof(struct hinic3_module_id)); ++ ++ module_info->module_id = module_id; ++ hinic3_rwlock_wrlock(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++ g_hugepage_mem_statistics.heap_meminfo.allocated_size[module_id] += elem_size; ++ hinic3_rwlock_wrunlock(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++ return 0; ++} ++ ++void *hinic3_rte_malloc(enum hinic3_module module_id, size_t size, unsigned align) ++{ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return rte_malloc(g_module_name[module_id].module_name, size, align); ++ } ++ ++ int ret; ++ void *ptr = rte_malloc(g_module_name[module_id].module_name, size + sizeof(struct hinic3_module_id), align); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, ++ "failed to allocate %" PRIu64 " bytes, module_name: %s", size, g_module_name[module_id].module_name); ++ return NULL; ++ } ++ ++ ret = hinic3_record_hugepage_meminfo(ptr, module_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc hugepage meminfo"); ++ hinic3_rte_free(ptr); ++ return NULL; ++ } ++ return ptr; ++} ++ ++void *hinic3_rte_zmalloc(enum hinic3_module module_id, size_t size, unsigned align) ++{ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return rte_zmalloc(g_module_name[module_id].module_name, size, align); ++ } ++ ++ int ret; ++ void *ptr = rte_zmalloc(g_module_name[module_id].module_name, size + sizeof(struct hinic3_module_id), align); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, ++ "failed to allocate %" PRIu64 " bytes, module_name: %s", size, g_module_name[module_id].module_name); ++ return NULL; ++ } ++ ++ ret = hinic3_record_hugepage_meminfo(ptr, module_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc hugepage meminfo"); ++ hinic3_rte_free(ptr); ++ return NULL; ++ } ++ return ptr; ++} ++ ++void *hinic3_rte_malloc_socket(enum hinic3_module module_id, size_t size, unsigned int align, int socket_arg) ++{ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return rte_malloc_socket(g_module_name[module_id].module_name, size, align, socket_arg); ++ } ++ ++ int ret; ++ void *ptr = rte_malloc_socket(g_module_name[module_id].module_name, ++ size + sizeof(struct hinic3_module_id), align, socket_arg); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, ++ "failed to allocate %" PRIu64 " bytes, module_name: %s", size, g_module_name[module_id].module_name); ++ return NULL; ++ } ++ ++ ret = hinic3_record_hugepage_meminfo(ptr, module_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc hugepage meminfo"); ++ hinic3_rte_free(ptr); ++ return NULL; ++ } ++ return ptr; ++} ++ ++void *hinic3_rte_zmalloc_socket(enum hinic3_module module_id, size_t size, unsigned align, int socket) ++{ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return rte_zmalloc_socket(g_module_name[module_id].module_name, size, align, socket); ++ } ++ ++ int ret; ++ void *ptr = rte_zmalloc_socket(g_module_name[module_id].module_name, ++ size + sizeof(struct hinic3_module_id), align, socket); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, ++ "failed to allocate %" PRIu64 " bytes, module_name: %s", size, g_module_name[module_id].module_name); ++ return NULL; ++ } ++ ++ ret = hinic3_record_hugepage_meminfo(ptr, module_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc hugepage meminfo"); ++ hinic3_rte_free(ptr); ++ return NULL; ++ } ++ return ptr; ++} ++ ++void hinic3_rte_free(void *addr) ++{ ++ if (addr == NULL) { ++ return; ++ } ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ rte_free(addr); ++ return; ++ } ++ ++ void *elem = addr - MALLOC_ELEM_HEADER_LEN; ++ size_t elem_size = ((struct malloc_elem *)elem)->size; ++ if (elem_size < MALLOC_ELEM_TRAILER_LEN + sizeof(struct hinic3_module_id)) { ++ HINIC3_LOG(ERR, AGENT, "failed to free memory, input wrong addr"); ++ return; ++ } ++ struct hinic3_module_id *module_info = (struct hinic3_module_id *)(elem + ++ elem_size - MALLOC_ELEM_TRAILER_LEN - sizeof(struct hinic3_module_id)); ++ if (module_info->module_id >= HINIC3_MODULE_MAX) { ++ HINIC3_LOG(ERR, AGENT, "failed to free memory, parse module_id error"); ++ return; ++ } ++ ++ hinic3_rwlock_wrlock(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++ if (g_hugepage_mem_statistics.heap_meminfo.allocated_size[module_info->module_id] < elem_size) { ++ HINIC3_LOG(ERR, AGENT, "failed to free memory, elem size error"); ++ hinic3_rwlock_wrunlock(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++ return; ++ } ++ g_hugepage_mem_statistics.heap_meminfo.allocated_size[module_info->module_id] -= elem_size; ++ hinic3_rwlock_wrunlock(&g_hugepage_mem_statistics.heap_meminfo.rwlock); ++ rte_free(addr); ++ return; ++} ++ ++int hinic3_record_memzone_info(const struct rte_memzone *mz, const char *name, size_t len, enum hinic3_module module_id) ++{ ++ struct hinic3_rte_memzone_ele *ptr = NULL; ++ ptr = (struct hinic3_rte_memzone_ele *)hinic3_malloc(sizeof(struct hinic3_rte_memzone_ele), HINIC3_COMMON_RESOURCE); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to record memzone"); ++ return -ENOMEM; ++ } ++ ptr->memzone = mz; ++ ptr->module_id = module_id; ++ ptr->allocated_size = len; ++ strcpy(ptr->name, name); ++ hinic3_list_init(&ptr->node); ++ hinic3_pthread_mutex_lock(&g_hugepage_mem_statistics.memzone_list.mutex); ++ hinic3_list_insert(&g_hugepage_mem_statistics.memzone_list.list_head, &ptr->node); ++ hinic3_pthread_mutex_unlock(&g_hugepage_mem_statistics.memzone_list.mutex); ++ hinic3_rwlock_wrlock(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++ g_hugepage_mem_statistics.memzone_meminfo.allocated_size[module_id] += len; ++ hinic3_rwlock_wrunlock(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++ return 0; ++} ++ ++const struct rte_memzone *hinic3_rte_memzone_reserve(const char *name, ++ size_t len, int socket_id, unsigned flags, enum hinic3_module module_id) ++{ ++ int ret; ++ const struct rte_memzone *mz = rte_memzone_reserve(name, len, socket_id, flags); ++ if (mz == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %" PRIu64 " bytes, module_name: %s", len, name); ++ return NULL; ++ } ++ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return mz; ++ } ++ ++ ret = hinic3_record_memzone_info(mz, name, len, module_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc memzone, record error"); ++ rte_memzone_free(mz); ++ return NULL; ++ } ++ return mz; ++} ++ ++const struct rte_memzone *hinic3_rte_memzone_reserve_aligned( ++ const char *name, size_t len, int socket_id, unsigned flags, unsigned align, enum hinic3_module module_id) ++{ ++ int ret; ++ const struct rte_memzone *mz = rte_memzone_reserve_aligned(name, len, socket_id, flags, align); ++ if (mz == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %" PRIu64 " bytes, module_name: %s", len, name); ++ return NULL; ++ } ++ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return mz; ++ } ++ ++ ret = hinic3_record_memzone_info(mz, name, len, module_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc memzone, record error"); ++ rte_memzone_free(mz); ++ return NULL; ++ } ++ return mz; ++} ++ ++int hinic3_rte_memzone_free(const struct rte_memzone *mz) ++{ ++ if (mz == NULL) { ++ return -EINVAL; ++ } ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return rte_memzone_free(mz); ++ } ++ ++ struct hinic3_rte_memzone_ele *iter = NULL; ++ struct hinic3_rte_memzone_ele *next = NULL; ++ LIST_FOR_EACH_SAFE(iter, next, node, &g_hugepage_mem_statistics.memzone_list.list_head) ++ { ++ if (iter->memzone == mz) { ++ hinic3_rwlock_wrlock(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++ if (g_hugepage_mem_statistics.memzone_meminfo.allocated_size[iter->module_id] < iter->allocated_size) { ++ HINIC3_LOG(ERR, AGENT, "failed to free memzone, memzone size error"); ++ hinic3_rwlock_wrunlock(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++ return -EINVAL; ++ } ++ g_hugepage_mem_statistics.memzone_meminfo.allocated_size[iter->module_id] -= iter->allocated_size; ++ hinic3_rwlock_wrunlock(&g_hugepage_mem_statistics.memzone_meminfo.rwlock); ++ ++ hinic3_pthread_mutex_lock(&g_hugepage_mem_statistics.memzone_list.mutex); ++ hinic3_list_remove(&iter->node); ++ hinic3_pthread_mutex_unlock(&g_hugepage_mem_statistics.memzone_list.mutex); ++ ++ rte_memzone_free(mz); ++ iter->memzone = NULL; ++ hinic3_free(iter); ++ return 0; ++ } ++ } ++ return -EINVAL; ++} ++ ++int hinic3_record_mempool_info(struct rte_mempool *mp, const char *name, unsigned private_data_size) ++{ ++ struct hinic3_rte_mempool_ele *ptr = NULL; ++ uint32_t unit_size = mp->elt_size + mp->header_size + mp->trailer_size; ++ ++ ptr = (struct hinic3_rte_mempool_ele *)hinic3_malloc(sizeof(struct hinic3_rte_mempool_ele), HINIC3_COMMON_RESOURCE); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to record mempool"); ++ return -ENOMEM; ++ } ++ ptr->mempool = mp; ++ ptr->allocated_size = unit_size * mp->size + mp->mz->len + private_data_size; ++ strcpy(ptr->name, name); ++ hinic3_list_init(&ptr->node); ++ hinic3_pthread_mutex_lock(&g_hugepage_mem_statistics.mempool_list.mutex); ++ hinic3_list_insert(&g_hugepage_mem_statistics.mempool_list.list_head, &ptr->node); ++ hinic3_pthread_mutex_unlock(&g_hugepage_mem_statistics.mempool_list.mutex); ++ return 0; ++} ++ ++struct rte_mempool *hinic3_rte_pktmbuf_pool_create( ++ const char *name, unsigned n, unsigned cache_size, uint16_t priv_size, uint16_t data_room_size, int socket_id) ++{ ++ int ret; ++ struct rte_mempool *mp = rte_pktmbuf_pool_create(name, n, cache_size, priv_size, data_room_size, socket_id); ++ if (mp == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %" PRIu64 " bytes, module_name: %s", n, name); ++ return NULL; ++ } ++ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return mp; ++ } ++ ++ ret = hinic3_record_mempool_info(mp, name, 0); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc mempool, record error"); ++ rte_mempool_free(mp); ++ return NULL; ++ } ++ return mp; ++} ++ ++struct rte_mempool *hinic3_rte_mempool_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, ++ unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_cb_t *obj_init, ++ void *obj_init_arg, int socket_id, unsigned flags) ++{ ++ int ret; ++ struct rte_mempool *mp = rte_mempool_create(name, n, elt_size, cache_size, ++ private_data_size, mp_init, mp_init_arg, obj_init, obj_init_arg, socket_id, flags); ++ if (mp == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %" PRIu64 " bytes, module_name: %s", n, name); ++ return NULL; ++ } ++ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ return mp; ++ } ++ ++ ret = hinic3_record_mempool_info(mp, name, private_data_size); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to alloc mempool, record error"); ++ rte_mempool_free(mp); ++ return NULL; ++ } ++ return mp; ++} ++ ++void hinic3_rte_mempool_free(struct rte_mempool *mp) ++{ ++ if (hinic3_get_enable_hugepage_meminfo_statistic() == false) { ++ rte_mempool_free(mp); ++ return; ++ } ++ ++ struct hinic3_rte_mempool_ele *iter = NULL; ++ struct hinic3_rte_mempool_ele *next = NULL; ++ LIST_FOR_EACH_SAFE(iter, next, node, &g_hugepage_mem_statistics.mempool_list.list_head) ++ { ++ if (iter->mempool == mp) { ++ hinic3_pthread_mutex_lock(&g_hugepage_mem_statistics.mempool_list.mutex); ++ hinic3_list_remove(&iter->node); ++ hinic3_pthread_mutex_unlock(&g_hugepage_mem_statistics.mempool_list.mutex); ++ rte_mempool_free(mp); ++ iter->mempool = NULL; ++ hinic3_free(iter); ++ return; ++ } ++ } ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.h +new file mode 100644 +index 0000000..f3ca141 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.h +@@ -0,0 +1,75 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_HUGEPAGE_MEMINFO_H ++#define HINIC3_HUGEPAGE_MEMINFO_H ++ ++#include "hinic3_list.h" ++#include "rte_malloc.h" ++#include "rte_mempool.h" ++#include "rte_mbuf.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_meminfo.h" ++ ++#define HINIC3_MODULE_NAME_MAX 30 ++ ++struct hinic3_module_hugepage_meminfo { ++ struct hinic3_rwlock rwlock; ++ size_t allocated_size[HINIC3_MODULE_MAX]; ++}; ++ ++struct hinic3_rte_memzone_ele { ++ struct hinic3_list node; ++ const struct rte_memzone *memzone; ++ char name[RTE_MEMZONE_NAMESIZE]; ++ enum hinic3_module module_id; ++ size_t allocated_size; ++}; ++ ++struct hinic3_rte_mempool_ele { ++ struct hinic3_list node; ++ struct rte_mempool *mempool; ++ char name[RTE_MEMZONE_NAMESIZE]; ++ size_t allocated_size; ++}; ++ ++struct hinic3_rte_meminfo_list { ++ struct hinic3_mutex mutex; ++ struct hinic3_list list_head; ++}; ++ ++struct hinic3_hugepage_mem_statistics { ++ struct hinic3_module_hugepage_meminfo heap_meminfo; ++ struct hinic3_module_hugepage_meminfo memzone_meminfo; ++ struct hinic3_rte_meminfo_list memzone_list; ++ struct hinic3_rte_meminfo_list mempool_list; ++}; ++ ++const char *hinic3_get_module_name_from_module_id(enum hinic3_module module_id); ++int hinic3_hugepage_meminfo_init(void); ++void hinic3_hugepage_meminfo_uninit(void); ++struct hinic3_hugepage_mem_statistics *hinic3_get_hugepage_meminfo(void); ++// heap部分 ++void *hinic3_rte_malloc(enum hinic3_module module_id, size_t size, unsigned align); ++void *hinic3_rte_zmalloc(enum hinic3_module module_id, size_t size, unsigned align); ++void *hinic3_rte_malloc_socket(enum hinic3_module module_id, size_t size, unsigned int align, int socket_arg); ++void *hinic3_rte_zmalloc_socket(enum hinic3_module module_id, size_t size, unsigned align, int socket); ++void hinic3_rte_free(void *addr); ++ ++// memzone部分 ++const struct rte_memzone *hinic3_rte_memzone_reserve( ++ const char *name, size_t len, int socket_id, unsigned flags, enum hinic3_module module_id); ++const struct rte_memzone *hinic3_rte_memzone_reserve_aligned( ++ const char *name, size_t len, int socket_id, unsigned flags, unsigned align, enum hinic3_module module_id); ++int hinic3_rte_memzone_free(const struct rte_memzone *mz); ++ ++// mempool部分 ++struct rte_mempool *hinic3_rte_pktmbuf_pool_create(const char *name, unsigned n, ++ unsigned cache_size, uint16_t priv_size, uint16_t data_room_size, int socket_id); ++struct rte_mempool *hinic3_rte_mempool_create(const char *name, unsigned n, unsigned elt_size, ++ unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, ++ rte_mempool_obj_cb_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags); ++void hinic3_rte_mempool_free(struct rte_mempool *mp); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_list.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_list.h +new file mode 100644 +index 0000000..756c4ec +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_list.h +@@ -0,0 +1,72 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. ++ * Description: ++ */ ++ ++#ifndef HINIC3_LIST_H ++#define HINIC3_LIST_H ++ ++#include ++#include ++#include ++#include "hinic3_util.h" ++#include "hinic3_util.h" ++ ++struct hinic3_list { ++ struct hinic3_list *prev; /* Previous list element. */ ++ struct hinic3_list *next; /* Next list element. */ ++}; ++ ++static inline void hinic3_list_init(struct hinic3_list *list); ++static inline void hinic3_list_insert(struct hinic3_list *before, struct hinic3_list *elem); ++static inline struct hinic3_list *hinic3_list_remove(struct hinic3_list *elem); ++static inline size_t hinic3_list_size(const struct hinic3_list *list); ++static inline bool hinic3_list_is_empty(const struct hinic3_list *list); ++ ++#define LIST_FOR_EACH(ITER, MEMBER, LIST) \ ++ for (HINIC3_CONTAINER_INIT(ITER, (LIST)->next, MEMBER); \ ++ &(ITER)->MEMBER != (LIST); \ ++ HINIC3_CONTAINER_ASSIGN(ITER, (ITER)->MEMBER.next, MEMBER)) ++ ++#define LIST_FOR_EACH_SAFE(ITER, NEXT, MEMBER, LIST) \ ++ for (HINIC3_CONTAINER_INIT(ITER, (LIST)->next, MEMBER); \ ++ (&(ITER)->MEMBER != (LIST) ? HINIC3_CONTAINER_INIT(NEXT, (ITER)->MEMBER.next, MEMBER), 1 : 0); \ ++ (ITER) = (NEXT)) ++ ++static inline void hinic3_list_init(struct hinic3_list *list) ++{ ++ list->next = list->prev = list; ++} ++ ++static inline void hinic3_list_insert(struct hinic3_list *before, struct hinic3_list *elem) ++{ ++ elem->prev = before->prev; ++ elem->next = before; ++ before->prev->next = elem; ++ before->prev = elem; ++} ++ ++static inline struct hinic3_list* hinic3_list_remove(struct hinic3_list *elem) ++{ ++ elem->prev->next = elem->next; ++ elem->next->prev = elem->prev; ++ return elem->next; ++} ++ ++static inline size_t hinic3_list_size(const struct hinic3_list *list) ++{ ++ const struct hinic3_list *e; ++ size_t cnt = 0; ++ ++ for (e = list->next; e != list; e = e->next) { ++ cnt++; ++ } ++ return cnt; ++} ++ ++static inline bool hinic3_list_is_empty(const struct hinic3_list *list) ++{ ++ return list->next == list; ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h +new file mode 100644 +index 0000000..b260759 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h +@@ -0,0 +1,44 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_MAP_H ++#define HINIC3_MAP_H ++ ++#include ++#include ++ ++struct hmap_node { ++ size_t hash; /* Hash value. */ ++ struct hmap_node *next; /* Next in linked list. */ ++}; ++ ++struct hmap { ++ struct hmap_node **buckets; /* Must point to 'one' iff 'mask' == 0. */ ++ struct hmap_node *one; ++ size_t mask; ++ size_t n; ++}; ++ ++struct smap { ++ struct hmap map; /* Contains "struct smap_node"s. */ ++}; ++ ++struct smap_node { ++ struct hmap_node node; /* In struct smap's 'map' hmap. */ ++ char *key; ++ char *value; ++}; ++ ++struct shash_node { ++ struct hmap_node node; ++ char *name; ++ void *data; ++}; ++ ++struct shash { ++ struct hmap map; ++}; ++ ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.c +new file mode 100644 +index 0000000..9fc827d +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.c +@@ -0,0 +1,107 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include "hinic3_log.h" ++#include "hinic3_meminfo.h" ++ ++#define HINIC3_CALLOC_DEFAULT_NUM 1 ++#define HINIC3_ALLOC_SIZE_MAX (1 << 30) ++ ++static struct hinic3_mem_statistics g_mem_statistics = { 0 }; ++ ++static void hinic3_mark_mem_header(void *ptr, enum hinic3_module module_id) ++{ ++ (*(struct hinic3_module_id *)ptr).module_id = module_id; ++} ++ ++static void hinic3_record_meminfo(size_t allocated_size, enum hinic3_module module_id) ++{ ++ struct hinic3_module_meminfo *module_meminfo = &g_mem_statistics.module_meminfo[module_id]; ++ ++ hinic3_rwlock_wrlock(&module_meminfo->rwlock); ++ module_meminfo->allocated_size += allocated_size; ++ hinic3_rwlock_wrunlock(&module_meminfo->rwlock); ++ return; ++} ++ ++void hinic3_meminfo_init(void) ++{ ++ for (int i = 0; i < HINIC3_MODULE_MAX; i++) { ++ (void)hinic3_rwlock_init(&g_mem_statistics.module_meminfo[i].rwlock); ++ } ++} ++ ++void hinic3_meminfo_uninit(void) ++{ ++ for (int i = 0; i < HINIC3_MODULE_MAX; i++) { ++ (void)hinic3_rwlock_destroy(&g_mem_statistics.module_meminfo[i].rwlock); ++ } ++} ++ ++void *hinic3_malloc(size_t size, enum hinic3_module module_id) ++{ ++ void *ptr = NULL; ++ ++ if (size > HINIC3_ALLOC_SIZE_MAX) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %zu bytes, exceeded 1 GB, module_id: %d", size, module_id); ++ return NULL; ++ } ++ ++ ptr = malloc(sizeof(struct hinic3_module_id) + size); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %zu bytes, module_id: %d", size, module_id); ++ return NULL; ++ } ++ hinic3_mark_mem_header(ptr, module_id); ++ hinic3_record_meminfo(malloc_usable_size(ptr), module_id); ++ ++ return (void *)((struct hinic3_module_id *)ptr + 1); ++} ++ ++void *hinic3_calloc(size_t num, size_t size, enum hinic3_module module_id) ++{ ++ void *ptr = NULL; ++ size_t total_size = num * size; ++ ++ if (total_size > HINIC3_ALLOC_SIZE_MAX) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %" PRIu64 " bytes, exceeded 1 GB, module_id: %d", size, module_id); ++ return NULL; ++ } ++ ++ ptr = calloc(HINIC3_CALLOC_DEFAULT_NUM, sizeof(struct hinic3_module_id) + total_size); ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, "failed to allocate %" PRIu64 " bytes, module_id: %d", size, module_id); ++ return NULL; ++ } ++ hinic3_mark_mem_header(ptr, module_id); ++ hinic3_record_meminfo(malloc_usable_size(ptr), module_id); ++ ++ return (void *)((struct hinic3_module_id *)ptr + 1); ++} ++ ++void hinic3_free(void *ptr) ++{ ++ if (ptr == NULL) { ++ return; ++ } ++ ++ void *original_ptr = (void *)((struct hinic3_module_id *)ptr - 1); ++ size_t allocated_size = malloc_usable_size(original_ptr); ++ enum hinic3_module module_id = (*(struct hinic3_module_id *)original_ptr).module_id; ++ ++ hinic3_rwlock_wrlock(&g_mem_statistics.module_meminfo[module_id].rwlock); ++ g_mem_statistics.module_meminfo[module_id].allocated_size -= allocated_size; ++ hinic3_rwlock_wrunlock(&g_mem_statistics.module_meminfo[module_id].rwlock); ++ ++ free(original_ptr); ++ return; ++} ++ ++struct hinic3_mem_statistics *hinic3_get_meminfo(void) ++{ ++ return &g_mem_statistics; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.h +new file mode 100644 +index 0000000..d5ddda1 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_meminfo.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_MEMINFO_H ++#define HINIC3_MEMINFO_H ++ ++#include ++#include ++#include "hinic3_mutex.h" ++#include "hinic3_flow_agent_enum.h" ++ ++struct hinic3_module_id { ++ enum hinic3_module module_id; ++} __attribute__((__aligned__(8))); ++ ++struct hinic3_module_meminfo { ++ struct hinic3_rwlock rwlock; ++ size_t allocated_size; ++}; ++ ++struct hinic3_mem_statistics { ++ struct hinic3_module_meminfo module_meminfo[HINIC3_MODULE_MAX]; ++}; ++ ++void hinic3_meminfo_init(void); ++void hinic3_meminfo_uninit(void); ++void *hinic3_malloc(size_t size, enum hinic3_module module_id); ++void *hinic3_calloc(size_t num, size_t size, enum hinic3_module module_id); ++void hinic3_free(void *ptr); ++ ++struct hinic3_mem_statistics *hinic3_get_meminfo(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_message.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_message.h +new file mode 100644 +index 0000000..811da81 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_message.h +@@ -0,0 +1,605 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++ ++#ifndef HINIC3_MESSAGE_H ++#define HINIC3_MESSAGE_H ++ ++#include "rte_pci.h" ++#include "hinic3_packets_types.h" ++#include "hinic3_init.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_ETP_DISABLE (0) ++#define HINIC3_ETP_ENABLE (1) ++#define HINIC3_ETP_RESET (2) ++#define HINIC3_TIME_STR_LEN (64) ++ ++#define HINIC3_ETP_ID_SIZE (16) ++ ++enum hinic3_key_format { ++ HINIC3_KEY_FMT_VNI_5TUPLE, ++ HINIC3_KEY_FMT_VLAN_VXLAN_HASH_5TUPLE, ++ HINIC3_KEY_FMT_PORT_VLAN_VXLAN_5TUPLE, ++ HINIC3_KEY_FMT_MASKED_7TUPLE ++}; ++ ++enum hinic3_global_cfg_time_sync_type { ++ HINIC3_PCAP_ETP_CFG_TIME_SYNC, ++ HINIC3_GLOBAL_CFG_TIME_SYNC_MAX, ++}; ++ ++enum hinic3_flow_key_type { ++ HINIC3_FLOW_KEY_IN_PORT, ++ HINIC3_FLOW_KEY_VNI, ++ HINIC3_FLOW_KEY_OUTER_VID, ++ HINIC3_FLOW_KEY_INNER_VID, ++ HINIC3_FLOW_KEY_DL_TYPE, ++ HINIC3_FLOW_KEY_SRC_IP, ++ HINIC3_FLOW_KEY_DST_IP, ++ HINIC3_FLOW_KEY_PROTOCOL, ++ HINIC3_FLOW_KEY_SRC_PORT, ++ HINIC3_FLOW_KEY_DST_PORT, ++ HINIC3_FLOW_KEY_SRC_MAC, ++ HINIC3_FLOW_KEY_DST_MAC, ++ HINIC3_FLOW_KEY_SRC_IPV6, ++ HINIC3_FLOW_KEY_DST_IPV6, ++ HINIC3_FLOW_KEY_ETH_TYPE, ++ HINIC3_FLOW_KEY_CONTROL_FLAG, ++ HINIC3_FLOW_KEY_DP_HASH, ++ HINIC3_FLOW_KEY_RECIRC_ID, ++ HINIC3_FLOW_KEY_TYPE_MAX, ++}; ++ ++enum hinic3_ct_tcp_state_type { ++ HINIC3_TCP_STATE_TYPE_CLOSED, ++ HINIC3_TCP_STATE_TYPE_LISTEN, ++ HINIC3_TCP_STATE_TYPE_SYN_SENT, ++ HINIC3_TCP_STATE_TYPE_SYN_RECV, ++ HINIC3_TCP_STATE_TYPE_ESTABLISHED, ++ HINIC3_TCP_STATE_TYPE_CLOSE_WAIT, ++ HINIC3_TCP_STATE_TYPE_FIN_WAIT_1, ++ HINIC3_TCP_STATE_TYPE_CLOSING, ++ HINIC3_TCP_STATE_TYPE_LAST_ACK, ++ HINIC3_TCP_STATE_TYPE_FIN_WAIT_2, ++ HINIC3_TCP_STATE_TYPE_TIME_WAIT ++}; ++ ++/* discard struct, use hinic3_flow_act_vxlan_gpe_header instead */ ++struct hinic3_flow_act_vxlan_header { ++ uint8_t dmac[HINIC3_ETH_ADDR_LEN]; /* Destination MAC address */ ++ uint8_t smac[HINIC3_ETH_ADDR_LEN]; /* Source MAC address */ ++ uint32_t sip; /* Source IP address, network order */ ++ uint32_t dip; /* Destination IP address, network order */ ++ uint16_t sport; /* Source port, network order */ ++ uint16_t vid; /* Virtual lan identifier, network order */ ++ uint32_t vni; /* Virtual network identifier, network order */ ++}; ++ ++struct hinic3_flow_act_vxlan_gpe_header { ++ uint8_t dmac[ETH_ALEN]; /**< Destination MAC address */ ++ uint8_t smac[ETH_ALEN]; /**< Source MAC address */ ++ ++ uint16_t rsvd; /**< rsvd */ ++ uint16_t vlan_id; /**< Virtual lan identifier, network order */ ++ ++ uint8_t ip_version; /**< ip_version: 0-ipv4, 1-ipv6 */ ++ uint8_t dscp; ++ uint16_t rsvd0; /**< rsvd */ ++ ++ uint32_t sip[4]; /**< Source IP address, network order */ ++ uint32_t dip[4]; /**< Destination IP address, network order */ ++ ++ uint16_t sport; /**< Source port, network order */ ++ uint16_t dport; /**< Destination port, network order */ ++ ++ struct { ++ uint32_t flag : 8; /**< vxlan header flags */ ++ uint32_t rsvd1 : 24; /**< vxlan header rsvd, network order */ ++ uint32_t vni : 24; /**< Virtual network identifier, network order */ ++ uint32_t rsvd2 : 8; /**< vxlan header rsvd */ ++ } vxlan; ++ ++ uint32_t rsvd3[8]; /**< rsvd 32B */ ++}; ++ ++struct hinic3_flow_act_block_version { ++ uint16_t block_id; ++ uint16_t block_version; ++}; ++ ++enum hinic3_flow_action_type { ++ HINIC3_FLOW_ACT_CT, ++ HINIC3_FLOW_ACT_VXL_PUSH, ++ HINIC3_FLOW_ACT_VXL_POP, ++ HINIC3_FLOW_ACT_VLAN_PUSH, ++ HINIC3_FLOW_ACT_VLAN_POP, ++ HINIC3_FLOW_ACT_SET_SMAC, ++ HINIC3_FLOW_ACT_SET_DMAC, ++ HINIC3_FLOW_ACT_SET_SIP, ++ HINIC3_FLOW_ACT_SET_DIP, ++ HINIC3_FLOW_ACT_SET_SPORT, ++ HINIC3_FLOW_ACT_SET_DPORT, ++ HINIC3_FLOW_ACT_SET_PRIORITY, ++ HINIC3_FLOW_ACT_OUTPUT, ++ HINIC3_FLOW_ACT_VXL_GPE_PUSH, ++ HINIC3_FLOW_ACT_SET_SIPV6, ++ HINIC3_FLOW_ACT_SET_DIPV6, ++ HINIC3_FLOW_ACT_SET_VXLAN_GROUP_ID, ++ HINIC3_FLOW_ACT_ECMP, ++ HINIC3_FLOW_ACT_DROP, ++ HINIC3_FLOW_ACT_MIRROR, ++ HINIC3_FLOW_ACT_CRYPTO, ++ HINIC3_FLOW_ACT_COUNT, ++ HINIC3_FLOW_ACT_DEC_TTL, ++ HINIC3_FLOW_ACT_UPCALL, ++ HINIC3_FLOW_ACT_DP_HASH, ++ HINIC3_FLOW_ACT_RECIRC_ID, ++ HINIC3_FLOW_ACT_BLOCK_VERSION, ++ HINIC3_FLOW_ACT_QOS, ++ HINIC3_FLOW_ACT_TYPE_MAX, ++}; ++ ++enum FLOW_PUT_RESULT { ++ SUCCES = 0, ++ FAIL, ++ TIMEOUT, ++}; ++ ++enum hinic3_pkt_user_data_mac_type { ++ HINIC3_USER_DATA_MAC_UNICAST, ++ HINIC3_USER_DATA_MAC_BROADCAST, ++ HINIC3_USER_DATA_MAC_MULTICAST ++}; ++ ++enum hinic3_pkt_user_data_l3_type { ++ HINIC3_USER_DATA_L3_UNKNOWN, ++ HINIC3_USER_DATA_L3_IPV4, ++ HINIC3_USER_DATA_L3_IPV6, ++ HINIC3_USER_DATA_L3_ARP ++}; ++ ++enum hinic3_pkt_user_data_l4_type { ++ HINIC3_USER_DATA_L4_UNKNOWN, ++ HINIC3_USER_DATA_L4_UDP = 4, ++ HINIC3_USER_DATA_L4_TCP ++}; ++ ++enum hinic3_pkt_user_data_traffic_type { ++ HINIC3_TRAFFIC_FROM_HOST_DEFAULT, /* Traffic from host to NIC. NIC should process it with its normal pipeline */ ++ HINIC3_TRAFFIC_FROM_HOST_FALLBACK, /* Traffic from host to NIC. NIC should send packet to destination port */ ++ HINIC3_TRAFFIC_FROM_NIC_DEFAULT, /* Traffic from NIC to host. Means NIC can not offload the packet type */ ++ HINIC3_TRAFFIC_FROM_NIC_MISS_UPCALL, /* Traffic from NIC to host. NIC forward cache missing, shoud be offload */ ++ HINIC3_TRAFFIC_COMMAND, /* Command traffic */ ++ HINIC3_TRAFFIC_FROM_HOST_PACKET_OUT /* Traffic from host to NIC. For etp_packet_out_cmd_parse */ ++}; ++ ++ ++enum hinic3_flow_arg_type { ++ HINIC3_FLOW_ARG_SW_UFID, ++ HINIC3_FLOW_ARG_CT_UFID, ++ HINIC3_FLOW_ARG_LIVE_TIME, ++ HINIC3_FLOW_ARG_PUT_RESULT, ++ HINIC3_FLOW_ARG_AGE, ++ HINIC3_FLOW_ARG_REVERSE_UFID, ++ HINIC3_FLOW_ARG_LOCAL_VXLAN, ++ HINIC3_FLOW_ARG_FLUSH_RESULT, ++ HINIC3_FLOW_PRIV_ARG_PMD_ID, ++ HINIC3_FLOW_ARG_OVS_CONN, /* ct offload used, ovs_conn */ ++ HINIC3_FLOW_ARG_CT_DIRECT, /* ct offload used, flow direction(reply or init) */ ++ HINIC3_FLOW_PRIV_POLICY_FLAG, ++ HINIC3_FLOW_ARG_NO_CT_UFID, ++ HINIC3_FLOW_ARG_SW_UFID_CNT, ++ HINIC3_FLOW_ARG_TIME, ++ HINIC3_FLOW_ARG_FLOW_HASH, ++ HINIC3_FLOW_ARG_DP_HASH, ++ HINIC3_FLOW_ARG_MODIFY, ++ HINIC3_FLOW_ARG_TYPE_MAX, ++}; ++ ++struct hinic3_pkt_user_data { ++ uint32_t vport_id : 16; /* Host order */ ++ uint32_t traffic_type : 6; /* See hinic3_pkt_user_data_traffic_type */ ++ uint32_t slave_port_id : 2; ++ uint32_t l4_type : 3; /* See hinic3_pkt_user_data_l4_type */ ++ uint32_t l3_type_cos : 3; /* Reuse for both RX/TX,Rx:See hinic3_pkt_user_data_l3_type,TX: cos */ ++ uint32_t mac_type : 2; /* See hinic3_pkt_user_data_mac_type */ ++}; ++ ++enum hinic3_vlan_mode_type { ++ HINIC3_VLAN_MODE_ACCESS, ++ HINIC3_VLAN_MODE_TRUNK, ++}; ++ ++enum hinic3_port_arg_type { ++ HINIC3_PORT_ARG_VLAN_OL, ++ HINIC3_PORT_ARG_VLAN_TAG, ++ HINIC3_PORT_ARG_VLAN_MODE, ++ HINIC3_PORT_ARG_VNI, ++ HINIC3_PORT_ARG_DPDK_PORT_ID, ++ HINIC3_PORT_ARG_FAULT_STATS, ++ HINIC3_PORT_ARG_FAULT_FLUSH, ++ HINIC3_PORT_ARG_PORT_QUEUE_MAP, ++ HINIC3_PORT_ARG_GRO_ENABLE, ++ HINIC3_PORT_ARG_IPV6_GRO_ENABLE, ++ HINIC3_PORT_ARG_PORT_UPCALL_QUEUE_MAP, ++ HINIC3_PORT_ARG_BUCKET_ID, ++ HINIC3_PORT_ARG_MAX_QUEUE_NUM, ++ HINIC3_PORT_ARG_MIGRATE_TUNNEL_INFO, ++ HINIC3_PORT_ARG_MIGRATE_STATE, ++ HINIC3_PORT_ARG_PCI_ADDR, ++ HINIC3_PORT_ARG_BLOCK_START, ++ HINIC3_PORT_ARG_BLOCK_SIZE, ++ HINIC3_PORT_ARG_UPCALL_QUEUE_NUM, ++ HINIC3_PORT_ARG_UPCALL_REUSE, ++ HINIC3_PORT_ARG_INTR_EN, ++ HINIC3_PORT_ARG_FAKE_BDF, ++ HINIC3_PORT_ARG_LOCAL_LRO_EN, ++ HINIC3_PORT_ARG_IPV4_IP, ++ HINIC3_PORT_ARG_DEVICE_FEATURE, ++ HINIC3_PORT_ARG_QUEUE_SIZE, ++ HINIC3_PORT_ARG_TYPE_MAX, ++}; ++ ++enum migrate_vtep_state { ++ MIGRATE_JUMP_PRECONFIG_STATE = 0, ++ MIGRATE_JUMP_ACTIVE_STATE = 1, ++ MIGRATE_JUMP_FLIP_STATE = 2, ++ MIGRATE_JUMP_CLEAR_STATE = 3, ++}; ++ ++enum migrate_tap_dir { ++ MIGRATE_JUMP_TAP_SRC = 0, /* src port flag */ ++ MIGRATE_JUMP_TAP_DST = 1, /* dst port flag */ ++}; ++ ++#define TAP_NAME_LEN 32 ++struct migrate_tunnel_info { ++ uint8_t src_mac[HINIC3_ETH_ADDR_LEN]; ++ uint8_t dst_mac[HINIC3_ETH_ADDR_LEN]; ++ hinic3_be32 ip_src; ++ hinic3_be32 ip_dst; ++ hinic3_be16 src_port; /* udp sport id */ ++ hinic3_be32 vx_vni; ++ hinic3_be16 vport_id; /* bond vport id */ ++ char tap_name[TAP_NAME_LEN]; ++ hinic3_be32 global_src_vni; ++ hinic3_be32 global_dst_vni; ++}; ++ ++struct migrate_state_dir { ++ enum migrate_vtep_state vtep_state; ++ enum migrate_tap_dir dir; ++}; ++ ++/* start define bond args */ ++enum bond_mode_type { ++ MODE_ACTIVE_BACKUP = 1, ++ MODE_BALANCE_XOR = 2, ++ MODE_8023AD = 4, ++}; ++ ++enum bond_hash_policy_type { ++ HASH_POLICY_L2 = 0, /* layer 2 */ ++ HASH_POLICY_L23, /* layer 2 + 3 */ ++ HASH_POLICY_L34, /* layer 3 + 4 */ ++ HASH_POLICY_L2_SMAC, /* layer 2 + smac */ ++ HASH_POLICY_L3_SIP, /* layer 3 + sip */ ++}; ++ ++enum bond_lacp_status_type { ++ STATUS_ACTIVE_NEGOTIATED, ++ STATUS_DISABLED, ++}; ++ ++enum bond_slave_status_type { ++ STATUS_UP, ++ STATUS_DOWN, ++}; ++ ++enum bond_slave_duplex_type { ++ SLAVE_DUPLEX_HALF, ++ SLAVE_DUPLEX_FULL, ++}; ++ ++enum bond_slave_statistics_type { ++ STATISTICS_RX_PKTS, ++ STATISTICS_RX_BYTES, ++ STATISTICS_RX_DROPPED, ++ STATISTICS_RX_ERRORS, ++ STATISTICS_TX_PKTS, ++ STATISTICS_TX_BYTES, ++ STATISTICS_TX_DROPPED, ++ STATISTICS_TX_ERRORS, ++ SLAVE_STATISTICS_RX_PDUS, ++ SLAVE_STATISTICS_TX_PDUS, ++ STATISTICS_RX_8023AD_DROPPED, ++ STATISTICS_TX_8023AD_DROPPED, ++ STATISTICS_UNKNOWN_PKT_8023AD_DROPPED, ++ STATISTICS_TYPE_MAX, ++}; ++ ++enum bond_slave_lacp_info_select_type { ++ SELECT_SELECTED, ++ SELECT_UNSELECTED, ++ SELECT_STANDBY, ++}; ++ ++enum bond_slave_lacp_info_lacp_time_type { ++ LACP_TIME_SLOW, ++ LACP_TIME_FAST, ++}; ++ ++enum bond_slave_lacp_info_type { ++ LACP_INFO_AGG_PORD_ID, ++ LACP_INFO_SELECT, ++ LACP_INFO_LACP_TIME, ++ LACP_INFO_ACTOR_SYS_ID, ++ LACP_INFO_ACTOR_PORT_PRIORITY, ++ LACP_INFO_ACTOR_PORT_NUM, ++ LACP_INFO_ACTOR_KEY, ++ LACP_INFO_ACTOR_SYS_PRIORITY, ++ LACP_INFO_ACTOR_STATE, ++ LACP_INFO_PARTNER_SYS_ID, ++ LACP_INFO_PARTNER_PORT_PRIORITY, ++ LACP_INFO_PARTNER_PORT_NUM, ++ LACP_INFO_PARTNER_KEY, ++ LACP_INFO_PARTNER_SYS_PRIORITY, ++ LACP_INFO_PARTNER_STATE, ++ LACP_INFO_TYPE_MAX, ++}; ++ ++enum hinic3_bond_arg_type { ++ HINIC3_BOND_ARG_UPLINK_PCI_ID, ++ HINIC3_BOND_ARG_LACP_DEACTIVE_SLAVES, ++ HINIC3_BOND_ARG_BOND_MODE, ++ HINIC3_BOND_ARG_XMIT_HASH_POLICY, ++ HINIC3_BOND_ARG_SLAVES, ++ HINIC3_BOND_ARG_ACTIVE_SLAVE, ++ HINIC3_BOND_ARG_UPDELAY, ++ HINIC3_BOND_ARG_DOWNDELAY, ++ HINIC3_BOND_ARG_LACP_STATUS, ++ HINIC3_BOND_ARG_ACTIVE_MAC, ++ HINIC3_BOND_ARG_SLAVE_NAME, ++ HINIC3_BOND_ARG_SLAVE_STATUS, ++ HINIC3_BOND_ARG_SLAVE_SPEED, /* Mbps */ ++ HINIC3_BOND_ARG_SLAVE_DUPLEX, ++ HINIC3_BOND_ARG_SLAVE_MAC_ADDRESS, ++ HINIC3_BOND_ARG_SLAVE_MTU, ++ HINIC3_BOND_ARG_SLAVE_STATISTICS, ++ HINIC3_BOND_ARG_SLAVE_LACP_INFO, ++ HINIC3_BOND_ARG_SLAVE_MAY_ENABLE, ++ HINIC3_BOND_ARG_LACP_RATE, ++ HINIC3_BOND_ARG_TYPE_MAX, ++}; ++ ++enum hinic3_global_action_solve_type { ++ GLOBAL_CFG_ACTION_DROP, ++ GLOBAL_CFG_ACTION_UPCALL, ++}; ++ ++enum hinic3_global_thread_mode { ++ GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN = 0, ++ GLOBAL_CFG_THREAD_MODE_INTERRUPT, ++}; ++ ++enum hinic3_global_pmd_mode { ++ GLOBAL_CFG_PMD_MODE_STOP = 0, ++ GLOBAL_CFG_PMD_MODE_START = 1, ++}; ++ ++enum hinic3_gobal_vlan_ethtype { ++ GLOBAL_VLAN_ETHTYPE_8021Q = 0, ++}; ++ ++enum hinic3_gobal_action_check { ++ GLOBAL_ACTION_CHECK_OFF = 0, ++ GLOBAL_ACTION_CHECK_ON = 1, ++}; ++ ++enum hinic3_global_cfg_arg_type { ++ HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE, ++ HINIC3_GLOBAL_CFG_ARG_RSS_VF_NUM, ++ HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP, ++ HINIC3_GLOBAL_CFG_ARG_PCI_VENDOR_ID, ++ HINIC3_GLOBAL_CFG_ARG_PCI_DEVICE_ID, ++ HINIC3_GLOBAL_CFG_ARG_PCI_SUB_VENDOR_ID, ++ HINIC3_GLOBAL_CFG_ARG_PCI_SUB_DEVICE_ID, ++ HINIC3_GLOBAL_CFG_ARG_FM_CTL, /* default 0:limitless */ ++ HINIC3_GLOBAL_CFG_ARG_INVALID_TCP_ACTION, /* default drop */ ++ HINIC3_GLOBAL_CFG_ARG_IP_FRAG_ACTION, /* default upcall */ ++ HINIC3_GLOBAL_CFG_ARG_THREAD_MODE, /* default GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN */ ++ HINIC3_GLOBAL_CFG_ARG_FLOW_AGE_TIME, /* GLOBAL_CFG_FLOW_AGE_TIME */ ++ HINIC3_GLOBAL_CFG_ARG_PTHREAD_FDS, ++ HINIC3_GLOBAL_CFG_ARG_IPFRAG_UPCALL_RATELIMIT, ++ HINIC3_GLOBAL_CFG_ARG_VF_INFO, ++ HINIC3_GLOBAL_CFG_ARG_VF_ENABLE, ++ HINIC3_GLOBAL_CFG_ARG_PMD_MODE, ++ HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE, ++ HINIC3_GLOBAL_GET_PCAP_PROBE_STATS, ++ HINIC3_GLOBAL_CFG_ARG_ETP, ++ HINIC3_GLOBAL_GET_ETP_STATS, ++ HINIC3_GLOBAL_CFG_ARG_PHY_DEV_INFO, ++ HINIC3_GLOBAL_CFG_ARG_ACTION_CHECKING, ++ HINIC3_GLOBAL_CFG_ARG_QUEUE_POOL_SIZE, ++ HINIC3_GLOBAL_CFG_ARG_VXLAN_CHECK_UPCALL, ++ HINIC3_GLOBAL_CFG_ARG_PREMAC, ++ HINIC3_GLOBAL_CFG_ARG_VXLAN_FLAGS, ++ HINIC3_GLOBAL_CFG_ARG_ETP_XTRACE, ++ HINIC3_GLOBAL_CFG_ARG_MIRROR_GLOBAL, ++ HINIC3_GLOBAL_CFG_ARG_MIRROR_SESSION_SET, ++ HINIC3_GLOBAL_CFG_ARG_MIRROR_SESSION_DEL, ++ HINIC3_GLOBAL_CFG_ARG_MIRROR_VTEP_SET, ++ HINIC3_GLOBAL_CFG_ARG_MIRROR_VTEP_DEL, ++ HINIC3_GLOBAL_CFG_ARG_MC_OFFLOAD_ENABLE, ++ HINIC3_GLOBAL_CFG_UNAGE_FLAG, ++ HINIC3_GLOBAL_CFG_VXLAN_DPORT, ++ HINIC3_GLOBAL_CFG_ARG_LATENCY_MOD, ++ HINIC3_GLOBAL_CFG_ARG_BOND_HASH_POLICY_CFG, ++ HINIC3_GLOBAL_CFG_ARG_TYPE_MAX, ++}; ++ ++enum hinic3_bum_ether_type_check { ++ ETHER_TYPE_CHECK_TRUE, ++ ETHER_TYPE_CHECK_FALSE, ++}; ++ ++/* Security filter supported attributes */ ++enum hinic3_security_arg_type { ++ HINIC3_SECURITY_ARG_SRC_MAC, ++ HINIC3_SECURITY_ARG_BRD_RATELIMIT, ++ HINIC3_SECURITY_ARG_ETHER_TYPE_CHECK, ++ HINIC3_SECURITY_ARG_EXTRA_ETH_TYPE, ++ HINIC3_SECURITY_ARG_SRC_IPMAC, ++ HINIC3_SECURITY_ARG_FLOW_MISS_RATELIMIT, ++ HINIC3_SECURITY_ARG_IPSET, ++ HINIC3_SECURITY_ARG_TYPE_MAX, ++}; ++ ++/* QoS supported attributes */ ++enum hinic3_qos_arg_type { ++ HINIC3_QOS_QUEUE_ARG_PRIORITY, ++ HINIC3_QOS_QUEUE_ARG_MIN_RATE, ++ HINIC3_QOS_QUEUE_ARG_MAX_RATE, ++ HINIC3_QOS_QUEUE_ARG_BURST, ++ HINIC3_QOS_QUEUE_ARG_WEIGHT, ++ HINIC3_QOS_ARG_TYPE_MAX, ++}; ++ ++enum hinic3_pthread_fd { ++ HINIC3_PTHREAD_AGING = 0x10, ++ HINIC3_PTHREAD_ACK = 0x11, ++ HINIC3_PTHREAD_HOTPLUG_CTX_CALL = 0x12, ++ HINIC3_PTHREAD_MAX, ++}; ++ ++enum hinic3_api_return_val { ++ HINIC3_API_OK = 0, ++ HIOVS_OK = 0, ++ HINIC3_PORT_API_ERROR_BASE = 0x10, ++ HINIC3_FLOW_API_ERROR_BASE = 0x20, ++ HINIC3_FLOW_API_KEY_ERROR = HINIC3_FLOW_API_ERROR_BASE, ++ HINIC3_FLOW_API_ACTION_ERROR = 0x21, ++ HINIC3_FLOW_API_FLUSH_ERROR = 0x22, ++ HINIC3_FLOW_API_CBPARM_ERROR = 0x23, ++ HINIC3_FLOW_API_FULL_ERROR = 0x24, ++ HINIC3_FLOW_API_SEND_ERROR = 0x25, ++ HINIC3_FLOW_API_OTHER_ERROR = 0x26, ++ HINIC3_FLOW_API_ERROR_END = 0x27, ++ HINIC3_CALLBACK_API_ERROR_BASE = 0x30, ++ HINIC3_BUM_API_ERROR_BASE = 0x40, ++ HINIC3_QOS_API_ERROR_BASE = 0x50, ++ HINIC3_GLOBAL_API_ERROR_BASE = 0x60, ++ HINIC3_API_ERROR_END = 0x61, ++ HIOVS_ERROR = -1, ++ HIOVS_EEXEC = -2, ++ HIOVS_EEMPTY = -4, ++}; ++ ++struct hinic3_port_capability { ++ uint32_t supported_upcall_qnum; ++ uint32_t rsvd; ++}; ++ ++#define HINIC3_UPCALL_INFO_RESERVE_SIZE (2) ++struct hinic3_port_upcall_info { ++ uint32_t total_upcall_qnum; ++ uint32_t left_upcall_qnum; ++ uint32_t rsvd[HINIC3_UPCALL_INFO_RESERVE_SIZE]; ++}; ++ ++struct hinic3_pcap_probe_stats { ++ uint64_t pkts_drop_cnt; ++ uint64_t pkts_pcap_cnt; ++}; ++ ++/* Used for offload port */ ++struct hinic3_pcap_probe_user_data { ++ uint32_t vport_id : 16; /* pcap_probe_vport_id */ ++ uint32_t rule_idx : 8; /* pcap_probe_rule_idx */ ++ uint32_t resv1 : 8; ++ uint32_t org_pkt_len : 16; ++ uint32_t resv2 : 16; ++}; ++ ++struct hinic3_pcap_probe_rule_q_map { ++ uint8_t rule_idx; ++ uint8_t hinic3_dpdk_port_id; ++ uint16_t queue_id; ++}; ++ ++struct hinic3_pcap_probe_ctl_t { ++ uint8_t rule_idx; ++ uint8_t enable : 4; ++ uint8_t first_last_rule : 4; ++ uint16_t hinic3_port_id; ++}; ++ ++struct hinic3_pcap_probe_cfg_mask_t { ++ uint32_t all_pass : 1; ++ uint32_t vxlan_inner : 1; ++ uint32_t host : 1; ++ uint32_t direct_rx : 1; ++ uint32_t direct_tx : 1; ++ uint32_t proto_en : 1; ++ uint32_t cnt_en : 1; ++ uint32_t vni_en : 1; ++ uint32_t dport_en : 1; ++ uint32_t sport_en : 1; ++ uint32_t vlan_en : 1; ++ uint32_t eth_type_en : 1; ++ uint32_t dmac_en : 1; ++ uint32_t smac_en : 1; ++ uint32_t dip_en : 1; ++ uint32_t sip_en : 1; ++ uint32_t dscp_en : 1; ++ uint32_t ipv6_en : 1; /* 0: ipv4/not care, 1: ipv6 */ ++ uint32_t resv : 2; ++ uint32_t hinic3_private_pfid : 4; ++ uint32_t hinic3_private_qid : 8; ++}; ++ ++struct hinic3_pcap_probe_rule_cfg_info { ++ uint32_t vport_id : 16; ++ uint32_t cap_id : 8; ++ uint32_t dscp : 8; ++ uint32_t sip; ++ uint32_t dip; ++ uint32_t host_ip; ++ uint8_t smac[ETH_ADDR_LEN]; ++ uint8_t dmac[ETH_ADDR_LEN]; ++ uint32_t vlan_id : 16; ++ uint32_t eth_type : 16; ++ uint32_t vni : 24; ++ uint32_t ip_proto : 8; ++ uint32_t dport : 16; ++ uint32_t sport : 16; ++ uint32_t sip_mask; ++ uint32_t dip_mask; ++ uint32_t host_mask; ++ uint32_t pcap_cfg_cnt_h; ++ uint32_t pcap_cfg_cnt_l; ++}; ++ ++struct hinic3_pcap_probe_rule_ipv6_cfg_info { ++ struct in6_addr sip6; ++ struct in6_addr dip6; ++ struct in6_addr hip6; ++}; ++ ++struct hinic3_pcap_probe_filter_t { ++ struct hinic3_pcap_probe_ctl_t pcap_ctl; ++ struct hinic3_pcap_probe_cfg_mask_t cap_mask; ++ struct hinic3_pcap_probe_rule_cfg_info rule_cfg; ++ struct hinic3_pcap_probe_rule_ipv6_cfg_info rule_ipv6_cfg; ++}; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HINIC3_MESSAGE_H */ +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h +new file mode 100644 +index 0000000..39946ef +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h +@@ -0,0 +1,57 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_MUTEX_H ++#define HINIC3_MUTEX_H ++#include ++#include "rte_rwlock.h" ++ ++#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP ++#define HINIC3_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, "" } ++#else ++#define HINIC3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, "" } ++#endif ++ ++struct hinic3_mutex { ++ pthread_mutex_t lock; ++ const char *where; ++}; ++ ++struct hinic3_thread_once { ++ bool done; ++ struct hinic3_mutex mutex; ++}; ++ ++struct hinic3_rwlock { ++ pthread_rwlock_t lock; ++}; ++ ++struct hinic3_spin_rwlock { ++ rte_rwlock_t lock; ++}; ++struct hinic3_spinlock { ++ pthread_spinlock_t lock; ++}; ++ ++int hinic3_rwlock_init(struct hinic3_rwlock *lock); ++int hinic3_rwlock_destroy(struct hinic3_rwlock *lock); ++int hinic3_rwlock_write_priority_init(struct hinic3_rwlock *lock); ++int hinic3_rwlock_rdlock(struct hinic3_rwlock *lock); ++int hinic3_rwlock_rdunlock(struct hinic3_rwlock *lock); ++int hinic3_rwlock_wrlock(struct hinic3_rwlock *lock); ++int hinic3_rwlock_wrunlock(struct hinic3_rwlock *lock); ++int hinic3_rwlock_tryrdlock(struct hinic3_rwlock *lock); ++int hinic3_mutex_cond_wait(pthread_cond_t *cond, const struct hinic3_mutex *mutex_); ++int hinic3_pthread_mutex_init(const struct hinic3_mutex *mutex_); ++int hinic3_pthread_mutex_lock(const struct hinic3_mutex *mutex_); ++int hinic3_pthread_mutex_unlock(const struct hinic3_mutex *mutex_); ++int hinic3_pthread_mutex_destroy(const struct hinic3_mutex *mutex_); ++bool hinic3_thread_once_start(struct hinic3_thread_once *once); ++void hinic3_thread_once_done(struct hinic3_thread_once *once); ++int hinic3_spinlock_init(struct hinic3_spinlock *lock, int pshared); ++int hinic3_spinlock_destroy(struct hinic3_spinlock *lock); ++int hinic3_spinlock_lock(struct hinic3_spinlock *lock); ++int hinic3_spinlock_trylock(struct hinic3_spinlock *lock); ++int hinic3_spinlock_unlock(struct hinic3_spinlock *lock); ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h +new file mode 100644 +index 0000000..6263e64 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h +@@ -0,0 +1,205 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_NLATTR_H ++#define HINIC3_NLATTR_H ++ ++#include ++#include ++#include "hinic3_util.h" ++ ++#define HINIC3_NLA_ALIGN_SIZE 4 ++ ++struct hinic3_nlattr_obj { ++ uint16_t nla_len; ++ uint16_t nla_type; ++}; ++ ++typedef struct hinic3_nlattr_obj *hinic3_nlattr_itr; ++ ++struct hinic3_nlattr { ++ /* the buf begin ptr */ ++ void *data; ++ /* the buf length */ ++ size_t total_len; ++ size_t used_len; ++ /* first unused obj ptr */ ++ hinic3_nlattr_itr nla_itr; ++}; ++ ++static inline size_t hinic3_nlattr_size_align(size_t size) ++{ ++ return (size + HINIC3_NLA_ALIGN_SIZE - 1) & ~(HINIC3_NLA_ALIGN_SIZE - 1); ++} ++ ++#define HINIC3_NLA_HDRLEN (hinic3_nlattr_size_align(sizeof(struct hinic3_nlattr_obj))) ++ ++static inline hinic3_nlattr_itr hinic3_nlattr_itr_next(const hinic3_nlattr_itr nla) ++{ ++ return (hinic3_nlattr_itr)((uint8_t *)nla + hinic3_nlattr_size_align(nla->nla_len)); ++} ++ ++#define HINIC3_NLATTR_FOR_EACH(ITER, ATTRS) \ ++ for ((ITER) = ((ATTRS)->data); (ITER) != ((ATTRS)->nla_itr); \ ++ (ITER) = hinic3_nlattr_itr_next(ITER)) ++ ++static inline void hinic3_nlattr_init(struct hinic3_nlattr *nla, void *buf, size_t buf_len) ++{ ++ if (buf) { ++ nla->data = buf; ++ nla->used_len = 0; ++ nla->total_len = buf_len; ++ nla->nla_itr = (hinic3_nlattr_itr)buf; ++ return; ++ } ++ memset(nla, 0, sizeof(struct hinic3_nlattr)); ++} ++ ++static inline void hinic3_nlattr_reset_itr(struct hinic3_nlattr *nla, size_t real_len) ++{ ++ if (nla) { ++ nla->used_len = real_len; ++ nla->nla_itr = (hinic3_nlattr_itr)((uint8_t *)nla->data + nla->used_len); ++ } ++} ++ ++static inline void *hinic3_nlattr_put_unspec_uninit(struct hinic3_nlattr *nla, uint16_t type, size_t size) ++{ ++ hinic3_nlattr_itr nla_itr = nla->nla_itr; ++ void *data_store_ptr = NULL; ++ size_t initial_size = HINIC3_NLA_HDRLEN + size; ++ size_t aligned_size = hinic3_nlattr_size_align(initial_size); ++ if (HINIC3_LIKELY((nla->total_len - nla->used_len) >= aligned_size)) { ++ nla_itr->nla_len = initial_size; ++ nla_itr->nla_type = type; ++ data_store_ptr = nla_itr + 1; ++ nla->nla_itr = (hinic3_nlattr_itr)((uint8_t *)nla_itr + aligned_size); ++ nla->used_len += aligned_size; ++ } ++ return data_store_ptr; ++} ++ ++static inline uint16_t hinic3_nlattr_get_itr_type(const hinic3_nlattr_itr nla) ++{ ++ return nla->nla_type; ++} ++ ++static inline size_t hinic3_nlattr_get_itr_size(const hinic3_nlattr_itr nla) ++{ ++ return nla->nla_len - HINIC3_NLA_HDRLEN; ++} ++ ++static inline const void *hinic3_nlattr_get_itr_data(const hinic3_nlattr_itr nla) ++{ ++ return nla + 1; ++} ++ ++static inline const void *hinic3_nlattr_get_itr_unspec(const hinic3_nlattr_itr nla, size_t size) ++{ ++ return nla + 1; ++} ++ ++static inline const char *hinic3_nlattr_get_itr_string(const hinic3_nlattr_itr nla) ++{ ++ return (const char *)(nla + 1); ++} ++ ++static inline uint64_t hinic3_nlattr_get_itr_u64(const hinic3_nlattr_itr nla) ++{ ++ uint64_t *data_ptr = (uint64_t *)(nla + 1); ++ return *data_ptr; ++} ++ ++static inline uint32_t hinic3_nlattr_get_itr_u32(const hinic3_nlattr_itr nla) ++{ ++ uint32_t *data_ptr = (uint32_t *)(nla + 1); ++ return *data_ptr; ++} ++ ++static inline uint16_t hinic3_nlattr_get_itr_u16(const hinic3_nlattr_itr nla) ++{ ++ uint16_t *data_ptr = (uint16_t *)(nla + 1); ++ return *data_ptr; ++} ++ ++static inline uint8_t hinic3_nlattr_get_itr_u8(const hinic3_nlattr_itr nla) ++{ ++ uint8_t *data_ptr = (uint8_t *)(nla + 1); ++ return *data_ptr; ++} ++ ++static inline bool hinic3_nlattr_get_itr_flag(const hinic3_nlattr_itr nla) ++{ ++ return true; ++} ++ ++static inline int hinic3_nlattr_put_unspec(struct hinic3_nlattr *nla, uint16_t type, const void *data, size_t size) ++{ ++ void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, size); ++ if (store_buf == NULL) { ++ return -1; ++ } ++ ++ if (data == NULL) { ++ return 0; ++ } ++ ++ memcpy(store_buf, data, size); ++ return 0; ++} ++ ++static inline int hinic3_nlattr_put_u64(struct hinic3_nlattr *nla, uint16_t type, uint64_t value) ++{ ++ void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, sizeof(uint64_t)); ++ if (store_buf == NULL) { ++ return -1; ++ } ++ *(uint64_t*)store_buf = value; ++ ++ return 0; ++} ++ ++static inline int hinic3_nlattr_put_u32(struct hinic3_nlattr *nla, uint16_t type, uint32_t value) ++{ ++ void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, sizeof(uint32_t)); ++ if (store_buf == NULL) { ++ return -1; ++ } ++ *(uint32_t*)store_buf = value; ++ ++ return 0; ++} ++ ++static inline int hinic3_nlattr_put_u16(struct hinic3_nlattr *nla, uint16_t type, uint16_t value) ++{ ++ void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, sizeof(uint16_t)); ++ if (store_buf == NULL) { ++ return -1; ++ } ++ *(uint16_t*)store_buf = value; ++ ++ return 0; ++} ++ ++static inline int hinic3_nlattr_put_u8(struct hinic3_nlattr *nla, uint16_t type, uint8_t value) ++{ ++ void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, sizeof(uint8_t)); ++ if (store_buf == NULL) { ++ return -1; ++ } ++ *(uint8_t*)store_buf = value; ++ ++ return 0; ++} ++ ++static inline int hinic3_nlattr_put_flag(struct hinic3_nlattr *nla, uint16_t type) ++{ ++ void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, 0); ++ if (store_buf == NULL) { ++ return -1; ++ } ++ ++ return 0; ++} ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_option.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_option.h +new file mode 100644 +index 0000000..ed4baf4 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_option.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef __HINIC3_OPTION_H__ ++#define __HINIC3_OPTION_H__ ++#define NO_ARGUMENT 0 ++#define REQUIRED_ARGUMENT 1 ++#define OPTIONAL_ARGUMENT 2 ++ ++struct hinic3_opt { ++ const char* name; ++ int has_arg; ++ int *flag; ++ int val; ++}; ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_ovs_adapter.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_ovs_adapter.h +new file mode 100644 +index 0000000..e69de29 +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h +new file mode 100644 +index 0000000..aec6355 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h +@@ -0,0 +1,383 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_PACKETS_TYPES_H ++#define HINIC3_PACKETS_TYPES_H ++ ++#include ++#include ++#include ++#include "hinic3_eth_packets.h" ++#include "rte_mbuf.h" ++#include "hinic3_types.h" ++ ++#ifndef ETH_ALEN ++#define ETH_ALEN 6 ++#endif ++ ++#ifndef IPV6_ALEN ++#define IPV6_ALEN 16 ++#endif ++ ++#define PKT_MAX_BURST 32 ++ ++#define HINIC3_ETH_HEADER_LEN 14 ++#define HINIC3_ETH_TYPE_LEN 2 ++#define HINIC3_VLAN_HEADER_LEN 4 ++#define HINIC3_ETH_ADDR_LEN 6 ++#define HINIC3_IPV6_ADDR_LEN 16 ++#define HINIC3_IPV4_ADDR_LEN 4 ++#define HINIC3_ARP_ETH_HEADER_LEN 28 ++#define HINIC3_IP_HEADER_LEN 20 ++#define HINIC3_IPV6_FLOW_TABLE_LEN 3 ++#define HINIC3_IPV6_HEADER_LEN 40 ++#define HINIC3_TCP_HEADER_LEN 20 ++#define HINIC3_UDP_HEADER_LEN 8 ++#define HINIC3_ICMP6_HEADER_LEN 4 ++#define HINIC3_ICMP6_MESSAGE_LEN 4 ++#define HINIC3_ICMP_HEADER_LEN 8 ++#define HINIC3_IGMP_HEADER_LEN 8 ++#define HINIC3_SCTP_HEADER_LEN 12 ++#define HINIC3_ETH_PAYLOAD_MIN 46 ++#define HINIC3_ETH_TOTAL_MIN (HINIC3_ETH_HEADER_LEN + HINIC3_ETH_PAYLOAD_MIN) ++#define HINIC3_ARP_PACKET_SIZE (2 + HINIC3_ETH_HEADER_LEN + HINIC3_VLAN_HEADER_LEN + \ ++ HINIC3_ARP_ETH_HEADER_LEN) ++#define HINIC3_VLAN_ETH_HEADER_LEN (HINIC3_ETH_HEADER_LEN + HINIC3_VLAN_HEADER_LEN) ++#define HINIC3_ETH_TYPE_MIN 0x600 ++ ++#define VLAN_CFI 0x1000 ++#define VLAN_CFI_SHIFT 12 ++ ++#define VLAN_VID_MASK 0x0fff ++#define VLAN_PCP_MASK 0xe000 ++#define VLAN_PCP_SHIFT 13 ++ ++#define ND_OPT_SOURCE_LINKADDR 1 ++#define ND_OPT_TARGET_LINKADDR 2 ++ ++#define ND_ROUTER_SOLICIT 133 ++#define ND_ROUTER_ADVERT 134 ++#define ND_NEIGHBOR_SOLICIT 135 ++#define ND_NEIGHBOR_ADVERT 136 ++#define ND_REDIRECT 137 ++ ++#define HINIC3_PACKET_CONTEXT_SIZE 64 ++ ++#define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */ ++#define ELB_VXLAN_FLAGS 0x48000000 /* elbtrans vxlan flags. */ ++#define EGF_VXLAN_FLAGS 0x88000000 /* egf vxlan flags. */ ++#define ELB_L7_VXLAN_FLAGS 0x0a000000 /* elbv3 L7 vxlan flags. */ ++#define DEFAULT_VXLAN_PORT 4789 ++ ++/* The IPv6 flow label is in the lower 20 bits of the first 32-bit word. */ ++#define IPV6_LABEL_MASK 0x000fffff ++#define DEFAULT_IP_IHL_VER 0x45 ++ ++#define HINIC3_INET_ADDRSTRLEN 16 ++#define HINIC3_INET6_ADDRSTRLEN 46 ++ ++enum hinic3_ip_type { ++ HINIC3_IP_ADDR_V4 = 0, ++ HINIC3_IP_ADDR_V6 ++}; ++ ++struct eth_address { ++ union { ++ uint8_t ea[HINIC3_ETH_ADDR_LEN]; ++ hinic3_be16 be16[HINIC3_ETH_ADDR_LEN / 2]; /* hinic3_be16 has 2 bytes */ ++ }; ++}; ++ ++typedef hinic3_be32 in4_addr_t; ++ ++typedef struct { ++ uint8_t addr[HINIC3_IPV6_ADDR_LEN]; ++} in6_addr_t; ++ ++struct hinic3_ip_addr_header { ++ bool is_ipv6; ++ union { ++ in4_addr_t ipv4; ++ in6_addr_t ipv6; ++ } u; ++}; ++ ++struct hinic3_eth_header { ++ struct eth_address dst; ++ struct eth_address src; ++ hinic3_be16 eth_type; ++}; ++ ++struct hinic3_vlan_header { ++ hinic3_be16 vlan_next_type; ++ hinic3_be16 vlan_tci; ++}; ++ ++struct hinic3_vlan_eth_header { ++ struct eth_address dst; ++ struct eth_address src; ++ hinic3_be16 eth_type; ++ hinic3_be16 vlan_tci; ++ hinic3_be16 vlan_next_type; ++}; ++ ++struct hinic3_arp_eth_header { ++ /* arp header members. */ ++ hinic3_be16 ar_hrd; /* Hardware type. */ ++ hinic3_be16 ar_pro; /* Protocol type. */ ++ uint8_t ar_hln; /* Hardware address length. */ ++ uint8_t ar_pln; /* Protocol address length. */ ++ hinic3_be16 ar_op; /* Opcode. */ ++ ++ /* arp body members. */ ++ struct eth_address ar_sha; /* src mac address. */ ++ hinic3_16aligned_be32 ar_spa; /* src ip address. */ ++ struct eth_address ar_tha; /* dst mac address. */ ++ hinic3_16aligned_be32 ar_tpa; /* dst ip address. */ ++}; ++ ++struct hinic3_ip_header { ++ uint8_t ip_ihl_ver; ++ uint8_t ip_tos; ++ hinic3_be16 ip_tot_len; ++ hinic3_be16 ip_id; ++ hinic3_be16 ip_frag_off; ++ uint8_t ip_ttl; ++ uint8_t ip_proto; ++ hinic3_be16 ip_csum; ++ in4_addr_t ip_src; ++ in4_addr_t ip_dst; ++}; ++ ++/* NextHeader field of IPv6 packet header */ ++#define HINIC3_NEXTHDR_HOP 0 /* Hop-by-hop option header. */ ++#define HINIC3_NEXTHDR_TCP 6 /* TCP segment. */ ++#define HINIC3_NEXTHDR_UDP 17 /* UDP message. */ ++#define HINIC3_NEXTHDR_IPV6 41 /* IPv6 in IPv6 */ ++#define HINIC3_NEXTHDR_ROUTING 43 /* Routing header. */ ++#define HINIC3_NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */ ++#define HINIC3_NEXTHDR_GRE 47 /* GRE header. */ ++#define HINIC3_NEXTHDR_ESP 50 /* Encapsulating security payload. */ ++#define HINIC3_NEXTHDR_AUTH 51 /* Authentication header. */ ++#define HINIC3_NEXTHDR_ICMP 58 /* ICMP for IPv6. */ ++#define HINIC3_NEXTHDR_NONE 59 /* No next header */ ++#define HINIC3_NEXTHDR_DEST 60 /* Destination options header. */ ++#define HINIC3_NEXTHDR_SCTP 132 /* SCTP message. */ ++#define HINIC3_NEXTHDR_MOBILITY 135 /* Mobility header. */ ++#define HINIC3_NEXTHDR_MAX 255 ++#define HINIC3_IP6F_OFF_MASK 0xfff8 ++ ++#define HINIC3_IP6_HEADER_LEN 40 ++struct hinic3_ip6_header { ++ uint8_t version : 4, ++ priority : 4; ++ uint8_t flow_lbl[HINIC3_IPV6_FLOW_TABLE_LEN]; ++ hinic3_be16 payload_len; ++ uint8_t nexthdr; ++ uint8_t hop_limit; ++ in6_addr_t saddr; ++ in6_addr_t daddr; ++}; ++ ++#define HINIC3_IP6_HEADER_LEN 40 ++struct hinic3_ipv6_opt_hdr { ++ uint8_t nexthdr; ++ uint8_t hdrlen; ++ /* TLV encoded option data follows. */ ++} __attribute__((packed)); ++ ++struct hinic3_ip6_frag { ++ uint8_t ip6f_nxt; ++ uint8_t ip6f_reserved; ++ hinic3_be16 ip6f_offlg; ++ hinic3_be32 ip6f_ident; ++}; ++ ++struct hinic3_ip6_rthdr { ++ uint8_t ip6r_nxt; ++ uint8_t ip6r_len; ++ uint8_t ip6r_type; ++ uint8_t ip6r_segleft; ++}; ++ ++struct hinic3_16aligned_ip6_frag { ++ uint8_t ip6f_nxt; ++ uint8_t ip6f_reserved; ++ hinic3_be16 ip6f_offlg; ++ hinic3_16aligned_be32 ip6f_ident; ++}; ++ ++struct hinic3_icmp6_header { ++ uint8_t icmp6_type; ++ uint8_t icmp6_code; ++ hinic3_be16 icmp6_cksum; ++}; ++ ++struct hinic3_udp_header { ++ hinic3_be16 udp_src; ++ hinic3_be16 udp_dst; ++ hinic3_be16 udp_len; ++ hinic3_be16 udp_csum; ++}; ++ ++struct hinic3_tcp_header { ++ hinic3_be16 tcp_src; ++ hinic3_be16 tcp_dst; ++ hinic3_16aligned_be32 tcp_seq; ++ hinic3_16aligned_be32 tcp_ack; ++ hinic3_be16 tcp_ctl; ++ hinic3_be16 tcp_winsz; ++ hinic3_be16 tcp_csum; ++ hinic3_be16 tcp_urg; ++}; ++ ++struct hinic3_icmp_header { ++ uint8_t icmp_type; ++ uint8_t icmp_code; ++ hinic3_be16 icmp_csum; ++ union { ++ struct { ++ hinic3_be16 id; ++ hinic3_be16 seq; ++ } echo; ++ struct { ++ hinic3_be16 empty; ++ hinic3_be16 mtu; ++ } frag; ++ hinic3_16aligned_be32 gateway; ++ } icmp_fields; ++}; ++ ++struct hinic3_sctp_header { ++ hinic3_be16 sctp_src; ++ hinic3_be16 sctp_dst; ++ hinic3_be32 sctp_vtag; ++ hinic3_be32 sctp_csum; ++}; ++ ++/* MPLS related definitions */ ++#define HINIC3_MPLS_TTL_MASK 0x000000ff ++#define HINIC3_MPLS_TTL_SHIFT 0 ++ ++#define HINIC3_MPLS_BOS_MASK 0x00000100 ++#define HINIC3_MPLS_BOS_SHIFT 8 ++ ++#define HINIC3_MPLS_TC_MASK 0x00000e00 ++#define HINIC3_MPLS_TC_SHIFT 9 ++ ++#define HINIC3_MPLS_LABEL_MASK 0xfffff000 ++#define HINIC3_MPLS_LABEL_SHIFT 12 ++ ++#define HINIC3_MPLS_HLEN 4 ++#define HINIC3_PACKET_PADDING_INFO_LEN 64 ++ ++struct hinic3_mpls_hdr { ++ hinic3_16aligned_be32 mpls_lse; ++}; ++ ++/* VXLAN protocol header */ ++struct hinic3_vxlanhdr { ++ hinic3_16aligned_be32 vx_flags; ++ hinic3_16aligned_be32 vx_vni; ++}; ++ ++struct hinic3_flow_tnl { ++ hinic3_be32 ip_dst; ++ hinic3_be32 ip_src; ++ in6_addr_t ipv6_dst; ++ in6_addr_t ipv6_src; ++ hinic3_be64 tun_id; ++}; ++ ++struct hinic3_packet_metadata { ++ uint32_t pkt_hash; ++ uint32_t pkt_mark; ++ struct hinic3_flow_tnl tunnel; ++ ++ uint16_t ct_state; ++ uint16_t ct_zone; /* Needed by offload engine */ ++ uint32_t in_port; ++ void *pkt_ctx; /* for user to store private process context. */ ++ uint32_t entity_id; /* Entity id for QoS. */ ++}; ++ ++struct padding_info { ++ /** ++ * If RTE_MBUF_F_TX_TCP_CKSUM or RTE_MBUF_F_TX_UDP_CKSUM is set in mbuf->ol_flags, ++ * and csum_start is not 0, We need to offload csum calculation. ++ */ ++ uint16_t csum_start; /* Position to start checksumming from */ ++ uint16_t csum_offset; /* Offset after that to place checksum */ ++ /** ++ * In eGF: ++ * Save the packet's original vlan when packet enter the ecmp/route/arp component. ++ * The Qos module uses this original vlan and packet's SIP to limit the flow rate. ++ */ ++ uint16_t org_vlan; ++ /** ++ * In order to save the inner l2 offset of vxlan/gre packet ++ */ ++ uint32_t ipv6_hash; ++ uint8_t frag_cnt; ++}; ++ ++struct hinic3_packet { ++#ifdef HAVE_OVS_DPDK ++ struct rte_mbuf mbuf; ++#endif ++ /* basic packet info */ ++ hinic3_be16 dl_type; ++ uint16_t l3_ofs; /* l3 header offset, or UINT16_MAX. */ ++ uint16_t l4_ofs; /* l4 header offset, or UINT16_MAX. */ ++ uint16_t inner_l2_ofs; /* inner l2 offset, or UINT16_MAX. */ ++ uint16_t inner_l3_ofs; /* inner l3 header offset, or UINT16_MAX. */ ++ uint16_t inner_l4_ofs; /* inner l4 header offset, or UINT16_MAX. */ ++ uint8_t l2_pad_size; /* l2 padding size. */ ++ uint16_t l2_5_ofs; /* for MPLS, or UINT16_MAX. */ ++ uint32_t mac_offset; /* Record MAC offset of original packet when GSO */ ++ ++ /* packet memtadata info */ ++ union { ++ struct hinic3_packet_metadata md; ++ uint64_t data[HINIC3_PACKET_CONTEXT_SIZE / 8]; /* 8 means eight bytes for uint64_t */ ++ }; ++ ++ struct hinic3_packet *next; ++ union { ++ struct padding_info padding; ++ uint8_t reserved[HINIC3_PACKET_PADDING_INFO_LEN]; ++ }; ++}; ++ ++struct hinic3_packet_batch { ++ int count; ++ struct hinic3_packet *packets[PKT_MAX_BURST]; ++ bool drop_packets; ++}; ++ ++#define HINIC3_ND_OPT_LEN 8 ++struct hinic3_nd_opt { ++ uint8_t nd_opt_type; /* Values defined in icmp6.h */ ++ uint8_t nd_opt_len; /* in units of 8 octets (the size of this struct) */ ++ struct eth_address nd_opt_mac; /* Ethernet address in the case of SLL or TLL options */ ++}; ++ ++/* Fragment bits, used for IPv4 and IPv6, always zero for non-IP flows. */ ++#define FLOW_NW_FRAG_ANY (1 << 0) /* Set for any IP frag. */ ++#define FLOW_NW_FRAG_LATER (1 << 1) /* Set for IP frag with nonzero offset. */ ++#define FLOW_NW_FRAG_MASK (FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER) ++#define IPV6_MAX_EXT_HDRS 8 ++#define IPV6_EXT_HDR_MIN_LEN 8 ++ ++/* as l3_len in dpdk is 9bit(511), thus here we define IPV6_EXT_HDR_MAX_TOTAL_LEN ++ as 471(511-sizeof(struct ipv6_hdr)) */ ++#define IPV6_EXT_HDR_MAX_TOTAL_LEN 471 ++ ++static inline uint32_t tcp_offset(hinic3_be16 tcp_ctl) ++{ ++ const unsigned int bit_move_num = 12; ++ return ntohs(tcp_ctl) >> bit_move_num; ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_provider.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_provider.h +new file mode 100644 +index 0000000..63021b7 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_provider.h +@@ -0,0 +1,265 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_PROVIDER_H ++#define HINIC3_PROVIDER_H ++ ++#include ++#include "rte_config.h" ++#include "rte_mbuf.h" ++#include "rte_pci.h" ++#include "hinic3_message.h" ++#include "hinic3_driver_public.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++/* ++ * PKT_RX_HW_OFFLOAD_INFO is used to indicate if mbuf->udata64 ++ * contains valid information. ++ * Be careful: Flow agent and IFE used the same mbuf->udata64. ++ */ ++#define MAX_NAME_LEN 32 ++#define HINIC3_RX_THREAD_MAX 16 ++#define HINIC3_FLOW_STATS_BLOCK_SIZE 128 ++ ++struct hinic3_netdev_stats { ++ uint64_t rx_packets; ++ uint64_t tx_packets; ++ uint64_t rx_bytes; ++ uint64_t tx_bytes; ++ uint64_t rx_errors; ++ uint64_t tx_errors; ++ uint64_t rx_dropped; ++ uint64_t tx_dropped; ++ uint64_t multicast; ++ uint64_t collisions; ++ ++ uint64_t rx_length_errors; ++ uint64_t rx_over_errors; ++ uint64_t rx_crc_errors; ++ uint64_t rx_frame_errors; ++ uint64_t rx_fifo_errors; ++ uint64_t rx_missed_errors; ++ ++ uint64_t tx_aborted_errors; ++ uint64_t tx_carrier_errors; ++ uint64_t tx_fifo_errors; ++ uint64_t tx_heartbeat_errors; ++ uint64_t tx_window_errors; ++ ++ uint64_t rx_packets_split[0x7]; ++ uint64_t tx_packets_split[0x7]; ++ ++ uint64_t tx_multicast_packets; ++ ++ uint64_t rx_broadcast_packets; ++ uint64_t tx_broadcast_packets; ++ ++ uint64_t rx_errors_size[0x4]; ++}; ++ ++struct hinic3_port_stats_ { ++ struct hinic3_netdev_stats ovs_port_stats; ++ uint64_t timestamp; ++ ++ /* Hinic ucode counter */ ++ uint32_t tx_bond_mode_err_dropped; ++ uint32_t tx_bond_noport_dropped; ++ uint32_t tx_bcmc_limit_dropped; ++ uint32_t tx_bum_smac_dropped; ++ uint32_t tx_bum_sipsmac_dropped; ++ uint32_t tx_bum_ethtype_dropped; ++ uint32_t rx_wqe_fail_dropped; ++ uint32_t rx_qos_dropped; ++ uint32_t rx_mtu_dropped; ++ uint32_t rx_vport_invalid_dropped; ++ uint32_t ct_dropped; /* tx_drop:vport type is function; else rx_drop */ ++ uint32_t upcall_wqe_fail_dropped; ++ ++ uint64_t upcall_pkt_num_vport; ++ uint64_t tx_uc_bytes; /* only valid when vport type is function */ ++ uint64_t tx_uc_pkts; ++ uint64_t tx_bc_bytes; /* only valid when vport type is function */ ++ uint64_t tx_bc_pkts; ++ uint64_t tx_mc_bytes; /* only valid when vport type is function */ ++ uint64_t tx_mc_pkts; ++ uint64_t rx_uc_bytes; /* only valid when vport type is function */ ++ uint64_t rx_uc_pkts; ++ uint64_t rx_bc_bytes; /* only valid when vport type is function */ ++ uint64_t rx_bc_pkts; ++ uint64_t rx_mc_bytes; /* only valid when vport type is function */ ++ uint64_t rx_mc_pkts; ++ ++ uint32_t upcall_no_sge_dropped; /* upcall pre-drop without sge */ ++ uint32_t rss_q_invalid_dropped; /* rss queue invalid drop, only valid for vport */ ++ uint32_t rq_bp_dropped; /* only valid when vport type is function */ ++ uint32_t lacp_rx_nowqe_dropped; /* only valid when vport type is bond */ ++ uint32_t rsvd[6]; ++}; ++typedef struct hinic3_port_stats_ hinic3_port_stats; ++ ++enum hinic3_provider_type { ++ HINIC3_PROVIDER_NONE = 0, ++ HINIC3_PROVIDER_IFE, /* Integrated Forwarding Engine */ ++ HINIC3_PROVIDER_HINIC, /* Hi1822 NIC */ ++}; ++ ++typedef enum tag_hinic3_global_api { ++ HINIC3_GLOBAL_CFG_SET = 0, ++ HINIC3_GLOBAL_CFG_GET, ++ HINIC3_GLOBAL_STATISTICS_GET, ++ HINIC3_GLOBAL_STATISTICS_FLUSH, ++ HINIC3_GLOBAL_OPEN_LOG, ++ HINIC3_GLOBAL_SET_LOG_LEVEL, ++ HINIC3_GLOBAL_CMD_EXEC, ++ HINIC3_GLOBAL_PCIE_LIST_QUERY, ++ HINIC3_GLOBAL_API_MAX ++} hinic3_global_api; ++ ++typedef enum tag_hinic3_port_api { ++ HINIC3_PORT_MGMT_ADD = 0, ++ HINIC3_PORT_MGMT_DEL, ++ HINIC3_PORT_MGMT_GET, ++ HINIC3_PORT_MGMT_SET, ++ HINIC3_PORT_QUEUE_SET, ++ HINIC3_PORT_QUEUE_RELEASE, ++ HINIC3_BOND_MGMT_CREATE, ++ HINIC3_BOND_MGMT_DELETE, ++ HINIC3_BOND_MGMT_GET, ++ HINIC3_BOND_MGMT_SET, ++ HINIC3_BOND_MGMT_CLEAR, ++ HINIC3_BOND_SLAVE_INFO_GET, ++ HINIC3_ETHERADDR_GET, ++ HINIC3_MTU_SET, ++ HINIC3_CARRIER_GET, ++ HINIC3_CARRIER_RESETS_GET, ++ HINIC3_PORT_STATISTICS_GET, ++ HINIC3_PORT_STATISTICS_FLUSH, ++ HINIC3_FEATURES_GET, ++ HINIC3_SECURITY_GET, ++ HINIC3_SECURITY_SET, ++ HINIC3_SECURITY_REMOVE, ++ HINIC3_SECURITY_CLEAR, ++ HINIC3_QOS_INGRESS_LIMIT_SET, ++ HINIC3_QOS_INGRESS_LIMIT_GET, ++ HINIC3_QOS_EGRESS_LIMIT_SET, ++ HINIC3_QOS_EGRESS_LIMIT_GET, ++ HINIC3_QOS_DROP_THRESH_SET, ++ HINIC3_QOS_DROP_THRESH_GET, ++ HINIC3_PORT_MGMT_GET_CAPABILITY, ++ HINIC3_PORT_MGMT_GET_UPCALL_INFO, ++ HINIC3_QOS_STATISTICS_GET, ++ HINIC3_QOS_STATISTICS_CLEAR_GET, ++ HINIC3_QOS_STATISTICS_CLEAR_CLEAR, ++ HINIC3_HQOS_STATISTICS_CLEAR_GET, ++ HINIC3_HQOS_STATISTICS_CLEAR_CLEAR, ++ HINIC3_PORT_MGMT_ADD_DYNAMIC, ++ HINIC3_VM_QOS_LIMIT_SET, ++ HINIC3_VM_QOS_LIMIT_GET, ++ HINIC3_PORT_QOS_LIMIT_SET, ++ HINIC3_PORT_QOS_LIMIT_GET, ++ HINIC3_VM_QOS_SRTCM_LIMIT_SET, ++ HINIC3_VM_QOS_SRTCM_LIMIT_GET, ++ HINIC3_NET_QOS_LIMIT_SET, ++ HINIC3_NET_QOS_LIMIT_GET, ++ HINIC3_PORT_MGMT_GET_BOND_SALVE_INFO, ++ HINIC3_PORT_MGMT_SET_USAGE_STATE, ++ HINIC3_PORT_MGMT_GET_USAGE_STATE, ++ HINIC3_UPCALL_MTU_SET, ++ HINIC3_PORT_API_MAX ++} hinic3_port_api; ++ ++enum { ++ HINIC3_FLOW_CB_T_PUT_ACK, ++ HINIC3_FLOW_CB_T_AGE, ++ HINIC3_FLOW_CB_T_FLUSH_DONE, ++ HINIC3_FLOW_CB_T_MAX ++}; ++ ++ ++/* global statistics */ ++struct hinic3_global_stats { ++ uint32_t offload_flow_num; ++ uint32_t offload_qpc_num; ++ uint32_t same_flow_with_multi_gpa; ++ uint32_t vxlan_rx_vtep_miss; ++ uint32_t upcall_pf0_invalid_count; ++ uint32_t upcall_pf0_rx_wqe_fail_dropped; ++ uint32_t upcall_pf1_invalid_count; ++ uint32_t upcall_pf1_rx_wqe_fail_dropped; ++ ++ uint64_t upcall_limit_drop_total; ++ uint64_t upcall_from_vf_total; ++ uint64_t upcall_from_hwbond_total; ++ uint64_t flow_default_upcall; ++ uint64_t flow_miss_upcall; ++ uint64_t flow_invalid_upcall; ++ uint64_t qu_prefetch_statics_fail; ++}; ++ ++enum flow_put_ack_error_type { ++ FLOW_PUT_CALL_AGE_CALLBACK_ERROR, ++ FLOW_PUT_CALL_PUT_CALLBACK_ERROR, ++ FLOW_PUT_CALL_FLUSH_DONE_CALLBACK_ERROR, ++ FLOW_PUT_SHMAP_DEL_HW_ERROR, ++ FLOW_PUT_SHMAP_LIST_ADD_ERROR, ++ FLOW_PUT_ACK_ERROR_MAX, ++}; ++ ++struct hwbond_slave_info { ++ /* name is pci address */ ++ char name[MAX_NAME_LEN]; ++ uint8_t status; ++ uint16_t speed; ++ uint8_t duplex; ++ char mac_address[MAX_NAME_LEN]; ++ uint32_t mtu; ++ /* slave statistics */ ++ uint64_t rx_pkts; ++ uint64_t rx_bytes; ++ uint64_t rx_dropped; ++ uint64_t rx_errors; ++ uint64_t tx_pkts; ++ uint64_t tx_bytes; ++ uint64_t tx_dropped; ++ uint64_t tx_errors; ++ uint64_t rx_pdus; ++ uint64_t tx_pdus; ++ uint64_t rx_8023ad_dropped; ++ uint64_t tx_8023ad_dropped; ++ uint64_t unknown_pkt_8023ad_dropped; ++ /* lacp info */ ++ bool lacp_enable; ++ uint8_t agg_port_id; ++ uint8_t select; ++ uint8_t lacp_time; ++ char actor_sys_id[MAX_NAME_LEN]; ++ uint16_t actor_port_priority; ++ uint16_t actor_port_num; ++ uint16_t actor_key; ++ uint16_t actor_sys_priority; ++ uint8_t actor_state; ++ char partner_sys_id[MAX_NAME_LEN]; ++ uint16_t partner_port_priority; ++ uint16_t partner_port_num; ++ uint16_t partner_key; ++ uint16_t partner_sys_priority; ++ uint8_t partner_state; ++ uint8_t may_enable; ++}; ++ ++struct vm_limit_value { ++ uint64_t max_rate; ++ uint64_t max_burst; ++ uint64_t min_rate; ++ uint64_t min_burst; ++ bool is_enabled; ++}; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HINIC3_PROVIDER_H */ +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c +new file mode 100644 +index 0000000..1ab68bd +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c +@@ -0,0 +1,67 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_errno.h" ++#include "rte_mempool.h" ++#include "rte_mbuf.h" ++#include "rte_mbuf_dyn.h" ++#include "rte_distributor.h" ++#include "rte_string_fns.h" ++ ++#include "hinic3_message.h" ++#include "hinic3_util.h" ++#include "hinic3_offload_flow.h" ++#include "hinic3_offload_flow.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_set_userdata.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++#define HINIC3_METER_RTE_MBUF_GET_PTR 8 ++ ++/* ++ * 功能描述 : 在rte_mbuf中注册udata64 ++ * 返 回 值 : -1: 代表注册失败,大于等于0: 分配的偏移 ++ */ ++int hinic3_rte_mbuf_dynfield_register(void) ++{ ++ int offset; ++ ++ const struct rte_mbuf_dynfield dynfield = { ++ .name = "hinic3_userdata", ++ .size = sizeof(struct hinic3_userdata), ++ .align = __alignof__(struct hinic3_userdata), ++ .flags = 0, ++ }; ++ ++ offset = rte_mbuf_dynfield_register(&dynfield); ++ return offset; ++} ++ ++void hinic3_set_vport_id_into_userdata(uint16_t vport_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) ++{ ++ uint16_t i; ++ struct hinic3_pkt_user_data *hinic3_metadata = NULL; ++ struct hinic3_packet **buffer = (struct hinic3_packet **)tx_pkts; ++ ++ if (nb_pkts == 0) { ++ return; ++ } ++ ++ for (i = 0; i < nb_pkts; i++) { ++ hinic3_metadata = (struct hinic3_pkt_user_data *)rte_mbuf_get_udata64_ptr(tx_pkts[i]); ++ if (hinic3_metadata == NULL) { ++ continue; ++ } ++ ++ hinic3_metadata->vport_id = vport_id; ++ /* Transparent packets priority to hardware */ ++ hinic3_metadata->l3_type_cos = (buffer[i]->md.entity_id & LAYER_FLAG_TH); ++ hinic3_metadata->traffic_type = HINIC3_TRAFFIC_FROM_HOST_FALLBACK; ++ } ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.h +new file mode 100644 +index 0000000..a6f4b62 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_SET_USERDATA_H ++#define HINIC3_SET_USERDATA_H ++ ++#include "hinic3_packets_types.h" ++ ++struct hinic3_userdata { ++ uint32_t dynfield0; ++ ++ union { ++ void *userdata; /**< Can be used for external metadata */ ++ uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */ ++ }; ++ ++ uint32_t internal; /**< internal use mbuf, evs set it to 0 */ ++}; ++ ++#define LAYER_FLAG_TH 0x7 ++ ++int hinic3_rte_mbuf_dynfield_register(void); ++void hinic3_set_vport_id_into_userdata(uint16_t vport_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h +new file mode 100644 +index 0000000..9e282f1 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_TIMEVAL_H_ ++#define _HINIC3_TIMEVAL_H_ ++ ++#include ++ ++#define HINIC3_US_PER_MS 1000 ++#define HINIC3_MS_PER_SEC 1000 ++#define HINIC3_STRUCT_TM_BASE_YEAR 1900 ++#define HINIC3_STRUCT_TM_BASE_MONTH 1 ++#define HINIC3_MS_STR_FMT "%04u-%02u-%02u %02u:%02u:%02u.%03u" ++#define HINIC3_MS_STR_SIZE 25 // 2000-01-01 00:00:00.000 ++ ++static inline int time_msec_to_str(long long int msec, char buf[], size_t bufsize) ++{ ++ time_t sec = msec / HINIC3_MS_PER_SEC; ++ int millisec = (int) (msec % HINIC3_MS_PER_SEC); ++ struct tm *info = localtime(&sec); ++ return sprintf(buf, HINIC3_MS_STR_FMT, ++ info->tm_year + HINIC3_STRUCT_TM_BASE_YEAR, info->tm_mon + HINIC3_STRUCT_TM_BASE_MONTH, info->tm_mday, ++ info->tm_hour, info->tm_min, info->tm_sec, millisec); ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_tlv_key.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_tlv_key.h +new file mode 100644 +index 0000000..b3a1cca +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_tlv_key.h +@@ -0,0 +1,154 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_TLV_KEY_H ++#define HINIC3_TLV_KEY_H 1 ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_PORT_VLAN_OL "vlan_ol" ++#define HINIC3_PORT_VLAN_TAG "vlan" ++#define HINIC3_PORT_VLAN_MODE "vlan_mode" ++#define HINIC3_PORT_VNI "vni" ++#define HINIC3_DPDK_PORT_ID "dpdk_port_id" ++#define HINIC3_PORT_MAX_QUEUE_NUM "max_queue_num" /* for virtio-vf flavor mgmt */ ++#define HINIC3_PORT_PCI_ADDR "pci_addr" /* for virtio-vf mgmt add dynamic */ ++#define HINIC3_PORT_BLOCK_START "block_start" /* for virtio-vf mgmt add dynamic */ ++#define HINIC3_PORT_BLOCK_SIZE "block_size" /* for virtio-vf mgmt add dynamic */ ++#define HINIC3_PORT_UPCALL_QUEUE_NUM "upcall_queue_num" /* for vport upcall queue */ ++#define HINIC3_PORT_VM_ID "vm_id" /* for virtio-vf QoS */ ++#define HINIC3_PORT_BUCKET_ID "bucket_id" /* for virtio-vf QoS */ ++#define HINIC3_PORT_BW_INGRESS "bw_ingress" /* for virtio-vf VM-QoS (unused) */ ++#define HINIC3_PORT_VM_BW_INGRESS "vm_bw_ingress" /* for virtio-vf VM-QoS */ ++#define HINIC3_PORT_VM_PPS_INGRESS "vm_pps_ingress" /* for virtio-vf VM-QoS */ ++#define HINIC3_PORT_VM_BW_EGRESS "vm_bw_egress" /* for virtio-vf VM-QoS */ ++#define HINIC3_PORT_VM_PPS_EGRESS "vm_pps_egress" /* for virtio-vf VM-QoS */ ++#define HINIC3_PORT_DROP_THRESH_LEVEL "drop_thresh_level" /* for virtio-vf QoS */ ++#define HINIC3_PORT_QUEUE_MAP "vport_queue_map" /* for virtio-vf queue map */ ++#define HINIC3_PORT_UPCALL_QUEUE_MAP "vport_upcall_queue_map" /* for upcall queue map */ ++#define HINIC3_PORT_GRO_ENABLE "gro_enable" /* for virtio-vf gro */ ++#define HINIC3_PORT_IPV6_GRO_ENABLE "ipv6_gro_enable" /* for virtio-vf ipv6 gro */ ++#define HINIC3_PORT_MIGRATE_TUNNEL_INFO "migrate_tunnel_info" ++#define HINIC3_PORT_MIGRATE_STATE "migrate_state" ++#define HINIC3_PORT_EP_PFID "ep_pfid" /* for zero-virtio-pt init */ ++#define HINIC3_PORT_EP_VFID "ep_vfid" /* for zero-virtio-pt init */ ++#define HINIC3_PORT_QUEUE_SIZE "queue_size" /* for zero-virtio-pt init */ ++#define HINIC3_PORT_HIGH_RATE "high_rate" /* for virtio-vf high_rate */ ++#define HINIC3_PORT_FDIR_POLICY "fdir_policy" /* for hinic3 fdir policy options */ ++#define HINIC3_PORT_XMIT_HASH "xmit_hash" /* for hinic3 port xmit_hash options */ ++#define HINIC3_PORT_QUEUE_DEPTH "virtio_queue_depth" /* for ce1800v set queue_depth from cfg */ ++ ++#define HINIC3_BOND_NAME "bond_name" ++#define HINIC3_PORT_PCI_ID "pci" /* format same as below */ ++#define HINIC3_BOND_UPLINK_PCI_ID "bond_uplink_pci_id" /* format: HH:HH.D, H means hex, D means dec */ ++#define HINIC3_BOND_MODE "mode" ++#define HINIC3_BOND_XMIT_HASH_POLICY "policy" ++#define HINIC3_BOND_SLAVES "slaves" ++#define HINIC3_BOND_ACTIVE_SLAVE "active_slave" ++#define HINIC3_BOND_LACP_RATE "lacp_rate" ++#define HINIC3_BOND_LACP_DEACTIVE_SLAVES "lacp_deactive_slaves" ++#define HINIC3_PRIORITY_UPCALL "priority_upcall" ++#define HINIC3_PORT_MAC "mac_addr" /* format:fa:16:3e:01:e7:42 */ ++#define HINIC3_MAX_QUEUE_NUM "max_queues" ++#define HINIC3_REPRESENTOR_ID "representor" ++#define HINIC3_VF_MAC_ADDR_DEFAULT "00:00:00:00:00:00" ++ ++/* attribute for json_slaves_arrays---for get only */ ++#define HINIC3_BOND_ARG_UPDELAY_STR "updelay" ++#define HINIC3_BOND_ARG_DOWNDELAY_STR "downdelay" ++#define HINIC3_BOND_ARG_LACP_STATUS_STR "lacp_status" ++#define HINIC3_BOND_ARG_ACTIVE_MAC_STR "active_mac" ++#define HINIC3_BOND_ARG_SLAVE_NAME_STR "name" ++#define HINIC3_BOND_ARG_SLAVE_STATUS_STR "status" ++#define HINIC3_BOND_ARG_SLAVE_SPEED_STR "speed" ++#define HINIC3_BOND_ARG_SLAVE_DUPLEX_STR "duplex" ++#define HINIC3_BOND_ARG_SLAVE_MAC_ADDRESS_STR "mac_address" ++#define HINIC3_BOND_ARG_SLAVE_MTU_STR "mtu" ++#define HINIC3_BOND_ARG_SLAVE_STATISTICS_STR "statistics" ++#define HINIC3_BOND_ARG_SLAVE_LACP_INFO_STR "lacp_info" ++ ++/* attribute for slave_statistics---for get only */ ++#define STATISTICS_RX_PKTS_STR "rx_pkts" ++#define STATISTICS_RX_BYTES_STR "rx_bytes" ++#define STATISTICS_RX_DROPPED_STR "rx_dropped" ++#define STATISTICS_RX_ERRORS_STR "rx_errors" ++#define STATISTICS_TX_PKTS_STR "tx_pkts" ++#define STATISTICS_TX_BYTES_STR "tx_bytes" ++#define STATISTICS_TX_DROPPED_STR "tx_dropped" ++#define STATISTICS_TX_ERRORS_STR "tx_errors" ++#define SLAVE_STATISTICS_RX_PDUS_STR "rx_pdus" ++#define SLAVE_STATISTICS_TX_PDUS_STR "tx_pdus" ++#define STATISTICS_RX_8023AD_DROPPED_STR "rx_8023ad_dropped" ++#define STATISTICS_TX_8023AD_DROPPED_STR "tx_8023ad_dropped" ++#define STATISTICS_UNKNOWN_PKT_8023AD_DROPPED_STR "unknown_drop_pkts" ++ ++/* attribute for slave_lacp_info---for get only */ ++#define LACP_INFO_AGG_PORD_ID_STR "agg_port_id" ++#define LACP_INFO_SELECT_STR "select" ++#define LACP_INFO_LACP_TIME_STR "lacp_time" ++ ++#define LACP_INFO_ACTOR_STR "actor" ++#define LACP_INFO_PARTNER_STR "partner" ++#define LACP_INFO_SYS_ID_STR "sys_id" ++#define LACP_INFO_PORT_PRIORITY_STR "port_priority" ++#define LACP_INFO_SYS_PRIORITY_STR "sys_priority" ++#define LACP_INFO_PORT_NUM_STR "port_num" ++#define LACP_INFO_KEY_STR "key" ++#define LACP_INFO_STATE_STR "state" ++ ++/* define for smap or json as str-key */ ++#define HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE_STR "vlan_ethtype" ++#define HINIC3_GLOBAL_CFG_ARG_RSS_VF_NUM_STR "rss_vf_num" ++#define HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP_STR "local_ip" ++#define HINIC3_GLOBAL_CFG_ARG_PCI_VENDOR_ID_STR "pci_vendor_id" ++#define HINIC3_GLOBAL_CFG_ARG_PCI_DEVICE_ID_STR "pci_device_id" ++#define HINIC3_GLOBAL_CFG_ARG_PCI_SUB_VENDOR_ID_STR "pci_sub_vendor_id" ++#define HINIC3_GLOBAL_CFG_ARG_PCI_SUB_DEVICE_ID_STR "pci_sub_device_id" ++#define HINIC3_GLOBAL_CFG_ARG_INVALID_TCP_ACTION_STR "invalid_tcp_action" ++#define HINIC3_GLOBAL_CFG_ARG_IP_FRAG_ACTION_STR "ip_frag_action" ++#define HINIC3_GLOBAL_CFG_ARG_THREAD_MODE_STR "thread_mode" ++#define HINIC3_GLOBAL_CFG_ARG_FLOW_AGE_TIME_STR "flow_age_time" ++#define HINIC3_GLOBAL_CFG_ARG_PTHREAD_FDS_STR "pthread_fds" ++#define GLOBAL_VLAN_ETHTYPE_8021Q_STR "8021Q" ++#define GLOBAL_CFG_ACTION_DROP_STR "drop" ++#define GLOBAL_CFG_ACTION_UPCALL_STR "upcall" ++#define GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN_STR "round-robin" ++#define GLOBAL_CFG_THREAD_MODE_INTERRUPT_STR "interrupt" ++#define HINIC3_GLOBAL_CFG_ARG_VF_INFO_STR "vf_info" ++#define HINIC3_GLOBAL_CFG_ARG_QUEUE_POOL_SIZE_STR "queue_pool_size" ++#define HINIC3_GLOBAL_CFG_ARG_PHY_DEV_INFO_STR "phy_dev_info" ++#define HINIC3_GLOBAL_CFG_ARG_VF_ENABLE_STR "vf_enable" /* enable sriov function for offload nic */ ++#define HINIC3_GLOBAL_CFG_ARG_PMD_MODE_STR "pmd_mode" /* star:1/stop:0 */ ++#define HINIC3_GLOBAL_CFG_ARG_PMD_MODE_START_STR "start" ++#define HINIC3_GLOBAL_CFG_ARG_PMD_MODE_STOP_STR "stop" ++#define HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE_STR "pcap_probe_cfg" ++#define HINIC3_GLOBAL_GET_PCAP_PROBE_STATS_STR "pcap_probe_stats" ++#define HINIC3_GLOBAL_CFG_ARG_ETP_STR "etp_cfg" ++#define HINIC3_GLOBAL_GET_ETP_STATS_STR "etp_stats" ++#define HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_STR "upcall_push_vxlan" ++#define HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_ON_STR "on" ++#define HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_OFF_STR "off" ++#define HINIC3_GLOBAL_CFG_UNAGE_FLAG_STR "unage_flag" ++#define HINIC3_GLOBAL_CFG_PKT_FORWARD_MOD_STR "packet_forward_mode" ++#define HINIC3_GLOBAL_CFG_PKT_LOW_LATENCY_MOD_STR "low_latency" ++#define HINIC3_GLOBAL_CFG_PKT_HIGH_THROUGH_STR "high_throughput" ++ ++/* bum attribute key-define for smap or json as str-key */ ++#define HINIC3_BUM_ARG_SRC_MAC_STR "src-mac:" ++#define HINIC3_BUM_ARG_BRD_RATELIMIT_STR "brd-ratelimit:" ++#define HINIC3_BUM_ARG_ETHER_TYPE_CHECK_STR "ether-type-check:" ++#define HINIC3_BUM_ARG_EXTRA_ETH_TYPE_STR "extra-eth-type:" ++ ++#define HINIC3_QOS_QUEUE_ARG_MAX_RATE_STR "max-rate" ++#define HINIC3_QOS_QUEUE_ARG_MIN_RATE_STR "min-rate" ++#define HINIC3_QOS_QUEUE_ARG_BURST_STR "burst" ++#define HINIC3_QOS_QUEUE_ARG_WEIGHT_STR "weight" ++#define HINIC3_QOS_QUEUE_ARG_PRIORITY_STR "priority" ++ ++#ifdef __cplusplus ++} ++#endif ++#endif /* HINIC3_TLV_KEY_H */ +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_types.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_types.h +new file mode 100644 +index 0000000..84d83ff +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_types.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_TYPES_H ++#define HINIC3_TYPES_H ++ ++#include ++#include ++#include ++#include ++ ++#ifdef __CHECKER__ ++#define HINIC3_BITWISE __attribute__((bitwise)) ++#define HINIC3_FORCE __attribute__((force)) ++#else ++#define HINIC3_BITWISE ++#define HINIC3_FORCE ++#endif ++ ++typedef uint16_t HINIC3_BITWISE hinic3_be16; ++typedef uint32_t HINIC3_BITWISE hinic3_be32; ++typedef uint64_t HINIC3_BITWISE hinic3_be64; ++ ++typedef struct { ++ hinic3_be16 hi, lo; ++} hinic3_16aligned_be32; ++ ++#endif /* HINIC3_TYPES_H */ +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_ui_string.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_ui_string.h +new file mode 100644 +index 0000000..9409dfc +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_ui_string.h +@@ -0,0 +1,410 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_UI_STRING_H ++#define HINIC3_UI_STRING_H ++ ++/* common cmd ui string */ ++#define HINIC3_UI_LEADING_SIGN_INFO "Info: " ++#define HINIC3_UI_LEADING_SIGN_ERROR "Error: " ++#define HINIC3_UI_LEADING_SIGN_WARNING "Warning: " ++#define HINIC3_UI_LEADING_SIGN_FAILURE "Failure: " ++#define HINIC3_UI_EMPTY_STRING "" ++#define HINIC3_UI_INDENT_SPACE "" ++#define HINIC3_UI_ERROR_UNRECOGNIZED_COMMAND "Unrecognized command" ++#define HINIC3_UI_ERROR_WRONG_PARAMETER "Wrong parameter" ++#define HINIC3_UI_ERROR_INCOMPLETE_COMMAND "Incomplete command" ++#define HINIC3_UI_ERROR_TOO_MANY_PARAMETER "Too many parameters" ++#define HINIC3_UI_ERROR_AMBIGUOUS_COMMAND "Ambiguous command" ++ ++enum hinic3_ui_indent { ++ INDENT_0 = 0, ++ INDENT_2 = 2, ++ INDENT_4 = 4, ++ INDENT_5 = 5, ++}; ++ ++/* ufid map cmd ui string */ ++#define HINIC3_UI_UFID_MAP_ERROR_STRING "Info: %s in ufid table %d: %u\n" ++#define HINIC3_UI_UFID_MAP_DUMP_START_ERROR_STRING "Dump hardware ufid start error.\n" ++#define HINIC3_UI_UFID_MAP_HW_UFID_FORMART_ERROR_STRING "Hardware ufid format is invalid, should: xxxxxxxx-xxxxxxxx.\n" ++#define HINIC3_UI_UFID_MAP_SW_UFID_FORMART_ERROR_STRING \ ++ "Software ufid format is invalid, should: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.\n" ++#define HINIC3_UI_UFID_MAP_SW_DUMP_ERROR_STRING "Dump ufid map error, too many maps, total hw ufid: %zd\n" ++#define HINIC3_UI_UFID_MAP_HW_DUMP_ERROR_STRING "Dump ufid map error, too many maps, total hw ufid %zd in table %u\n" ++#define HINIC3_UI_UFID_MAP_RTE_FLOW_ITEMS_STRING " All %zd software flows exist\n" ++#define HINIC3_UI_UFID_MAP_HARD_WARE_FLOW_ITEMS_STRING " Subtable %u has %zd hardware flows exist\n" ++#define HINIC3_UI_UFID_MAP_NO_SOFT_WARE_FLOW_ITEMS_STRING "No software flows exist.\n" ++#define HINIC3_UI_UFID_MAP_HW_FLOW_NUM_PER_SUB_TABLE_STRING " All %zd hardware flows exist in ufid table %u:\n" ++#define HINIC3_UI_UFID_MAP_HW_FLOW_ITEMS_STRING " All %zd hardware flows exist\n" ++#define HINIC3_UI_UFID_MAP_SUBTABLE_SW_FLOW_ITEMS_STRING " Subtable %u has %zd software flows:\n" ++#define HINIC3_UI_HW_UFID_STRING "Hardware Ufid" ++#define HINIC3_UI_SW_UFID_STRING "Mega Ufid" ++#define HINIC3_UI_UFID_MAP_HW_DUMP_HELP_TIPS_STRING \ ++ "dpak-ovs-ctl hwoff/dump-ufid-map-hw { all | | -n | { -h | --help } }\n\n" ++#define HINIC3_UI_UFID_MAP_HW_DUMP_NUM_HELP_STRING "-n Dump the number of hardware ufids in ufid tables\n" ++#define HINIC3_UI_UFID_MAP_HW_DUMP_SINGLE_HELP_STRING \ ++ " Dump all software ufids mapped to the given hardware ufids\n" ++#define HINIC3_UI_UFID_MAP_HW_DUMP_ALL_HELP_STRING "all Dump all hardware ufids\n" ++#define HINIC3_UI_UFID_MAP_SW_DUMP_HELP_TIPS_STRING \ ++ "dpak-ovs-ctl hwoff/dump-ufid-map-sw { all | | -n | { -h | --help } }\n\n" ++#define HINIC3_UI_UFID_MAP_SW_DUMP_NUM_HELP_STRING "-n Dump the number of software ufids in ufid tables\n" ++#define HINIC3_UI_UFID_MAP_SW_DUMP_SINGLE_HELP_STRING \ ++ " Dump all hardware ufids mapped to the given software ufids\n" ++#define HINIC3_UI_UFID_MAP_SW_DUMP_ALL_HELP_STRING "all Dump all software ufids\n" ++#define HINIC3_UI_UFID_MAP_DUMP_HELP_STRING "-h, --help Display the help information\n" ++/* flow show api info cmd ui string */ ++#define HINIC3_UI_FLOW_OPTION_LIST_STRING "Options list: " ++#define HINIC3_UI_FLOW_INPUT_INVALID_STRING "Invalid argument\n" ++#define HINIC3_UI_FLOW_INPUT_UNKOWN_OPTION_STRING "Unknown option %s.\n" ++#define HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING \ ++ "Required %d argument(s), please input -h or --help to get help info.\n" ++#define HINIC3_UI_FLOW_DELETE_HW_FLOW_BY_UFID_FAILED "Failed to delete hw flow by ufid.\n" ++#define HINIC3_UI_FLOW_DELETE_SW_FLOW_BY_UFID_FAILED "Failed to delete sw flow by ufid.\n" ++#define HINIC3_UI_FLOW_DELETE_BY_UFID_NOT_FOUND_FAILED "Flow not found.\n" ++#define HINIC3_UI_FLOW_DELETE_BY_UFID_SUCCESS "Delete flow by ufid success.\n" ++#define HINIC3_UI_FLOW_SHOW_FLOW_API_HELP_STRING \ ++ "Usage: dpak-ovs-ctl hwoff/show-flow-api { all | clear { all | } | api | { -h | --help } }\n" ++#define HINIC3_UI_FLOW_SHOW_ONE_API_HELP_STRING "api Show info about a specified api\n" ++#define HINIC3_UI_FLOW_CLEAR_ONE_API_HELP_STRING "clear Clear info about a specified api\n" ++#define HINIC3_UI_FLOW_SHOW_ALL_API_HELP_STRING "all Show all api info\n" ++#define HINIC3_UI_FLOW_CLEAR_ALL_API_HELP_STRING "clear all Clear all api info\n" ++#define HINIC3_UI_FLOW_HELP_STRING "-h, --help Display the help information\n" ++#define HINIC3_UI_FLOW_ALL_API_TIPS_STRING "api names that can be input are as follows" ++#define HINIC3_UI_FLOW_OPTIONS_WRONG_ARGUMENTS_STRING "Option %s required %d argument.\n" ++#define HINIC3_UI_FLOW_ALLOC_RECORDS_ERROR_STRING "Alloc api record faild.\n" ++#define HINIC3_UI_FLOW_CLEAR_RECORDS_FAILED_STRING "Clear flow api record failed [%s].\n" ++#define HINIC3_UI_FLOW_CLEAR_RECORDS_SUCCESS_STRING "Clear flow api record successful [%s].\n" ++#define HINIC3_UI_FLOW_QUERY_RECORDS_SUCCESS_STRING "Query flow api record successful [%s].\n" ++#define HINIC3_UI_FLOW_QUERY_RECORDS_FAILED_STRING "Query flow api record failed [%s].\n" ++#define HINIC3_UI_FLOW_UNKOWN_API_STRING "api-name is invalid [%s].\n" ++#define HINIC3_UI_FLOW_API_COST_MAX_TIME_STRING "Max api time(us): %" PRIu64 "\n" ++#define HINIC3_UI_FLOW_API_COST_MIN_TIME_STRING "Min api time(us): %" PRIu64 "\n" ++#define HINIC3_UI_FLOW_API_COST_AVERAGE_TIME_STRING "Average api time(us): %" PRIu64 "\n" ++#define HINIC3_UI_FLOW_API_TOTAL_CALL_TIMES_STRING "Total call counts: %" PRIu64 "\n" ++#define HINIC3_UI_FLOW_API_ERROR_CALL_TIMES_STRING "Error call counts: %" PRIu64 "\n" ++#define HINIC3_UI_FLOW_API_LATEST_ERROR_CALL_INFO_STRING "Last error info: return %lld in %s" ++#define HINIC3_UI_FLOW_API_COUNT_STRING "Api counts: %d\n" ++#define HINIC3_UI_FLOW_QUERY_API_NAME_STRING "Query %s:\n" ++#define HINIC3_UI_FLOW_ALL_STRING "all" ++#define HINIC3_UI_DFX_COMMAND_UPCALL_INFO_HEADER_STRING "Upcall queues info as follows: " ++#define HINIC3_UI_DFX_COMMAND_MAX_UPCALL_QUEUE_STRING "Max supported upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_AVAILIBLE_UPCALL_QUEUE_STRING "Availible upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_USED_UPCALL_QUEUE_STRING "Used upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_UPCALL_QUEUE_ERROR_STRING "can't dump upcall queue info, errno = " ++#define HINIC3_UI_DFX_COMMAND_UPCALL_VIRTUAL_INFO_HEADER_STRING "Upcall virtual queues info as follows: " ++#define HINIC3_UI_DFX_COMMAND_MAX_PHYSICAL_QUEUE_STRING "Max physical upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_VIRTUAL_UPCALL_QUEUE_MAX_STRING "Max virtual upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_VIRTUAL_UPCALL_QUEUE_AVAILIABLE_STRING "Total availible virtual upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_GROUP_STRING "Group" ++#define HINIC3_UI_DFX_COMMAND_AVAILIBLE_QUEUE_EVERY_GROUP_STRING "availible virtual upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_USED_VIRTUAL_UPCALL_QUEUE_STRING "Used virtual upcall queue num: " ++#define HINIC3_UI_DFX_COMMAND_VIRTUAL_QUEUE_ERROR_STRING "can't dump virtual queue info, errno = " ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_STRING \ ++ "dpak-ovs-ctl hwoff/dump-upcall-queue-info [ -port | -virual | " \ ++ "-physical | { -h | --help } ]" ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_FORMAT_STRING "-port " ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_TIPS_STRING \ ++ "Obtain the virtual queue list by port, eg: hwoff/dump-upcall-queue-info -port vf0" ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VIRTUAL_FORMAT_STRING "-virtual " ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VIRTUAL_TIPS_STRING \ ++ "Obtain the virtual queue list by virtual queue name, eg: hwoff/dump-upcall-queue-info -virtual group0-rx0" ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PHYSICAL_FORMAT_STRING "-physical " ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PHYSICAL_TIPS_STRING \ ++ "Obtain the virtual queue list by physical queue id, eg: hwoff/dump-upcall-queue-info -physical 0" ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_ID_ERR_STR "get port id error, invalid port name!" ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VF_DEV_ERR_STR "get vf dev error, invalid port id!" ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_NAME_ERR_STR "get port name error, invalid port id!" ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_FIND_VIRTUAL_QUEUE_ERR_STR "can't find virtual queue %s." ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PHYSICAL_QUEUE_DEACTIVE_ERR_STR "physical queue %u is deactive." ++#define HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VIRTUAL_QUEUE_DEACTIVE_ERR_STR "virtual queue %s is deactive." ++#define HINIC3_UI_PORT_DUMP_QUEUE_NETDEV_ERR_STR "Get netdev error, invalid port name!" ++#define HINIC3_UI_PORT_DUMP_QUEUE_PORT_ID_ERR_STR "Dump ports queue info %s failed, get port id error, wrong port name!" ++#define HINIC3_UI_PORT_DUMP_QUEUE_DEVICE_IFINDEX_ERR_STR "Dump ports queue info %s failed, device ifindex error!" ++#define HINIC3_UI_PORT_GET_VF_LINK_ERR "Port mgmt get vf link state err, ret = %d" ++#define HINIC3_DUMP_PORT_GET_BOND_LINK_ERR "Port mgmt get bond link state err, ret = %d" ++#define HINIC3_DUMP_PORT_RX_QUEUE_INFO "%2srx queue info:\n" ++#define HINIC3_DUMP_PORT_QUEUE_ID "%4squeue-id: %u\n" ++#define HINIC3_DUMP_PORT_RX_QUEUE_PKTS "%4srx-pkts: %lld\n" ++#define HINIC3_DUMP_PORT_TX_QUEUE_INFO "%2stx queue info:\n" ++#define HINIC3_DUMP_PORT_TX_QUEUE_PKTS "%4stx-pkts: %lld\n" ++#define HINIC3_UI_PORT_NAME_STRING "port-name" ++#define HINIC3_UI_VPORT_ID_STRING "vport-id" ++#define HINIC3_UI_QUEUE_ID_STRING "queue-id" ++#define HINIC3_UI_QUEUE_NAME_STRING "queue-name" ++#define HINIC3_UI_PKTS_STRING "pkts" ++#define HINIC3_UI_BYTES_STRING "bytes" ++#define HINIC3_UI_VIRTUAL_PKTS_DROPPED_STRING "virt-dropped" ++#define HINIC3_UI_PHYSICAL_PKTS_DROPPED_STRING "phy-dropped" ++ ++/* hinic3 agent flow dump cmd ui string */ ++#define HINIC3_UI_CMD_USAGE_STRING "Usage: " ++#define HINIC3_UI_FLOW_DUMP_HELP_FORMAT_STRING "-h, --help" ++#define HINIC3_UI_FLOW_DUMP_HELP_TIPS_STRING "Display the help information" ++#define HINIC3_UI_FLOW_DUMP_COUNT_FORMAT_STRING "-n" ++#define HINIC3_UI_FLOW_DUMP_COUNT_TIPS_STRING "Obtain the number of all flows" ++#define HINIC3_UI_FLOW_DUMP_UFID_FORMAT_STRING "ufid " ++#define HINIC3_UI_FLOW_DUMP_UFID_TIPS_STRING "Dump flows by hw ufid" ++#define HINIC3_UI_FLOW_DUMP_BLOCK_ID_FORMAT_STRING "-i " ++#define HINIC3_UI_FLOW_DUMP_BLOCK_ID_TIPS_STRING "Dump flows by block id" ++#define HINIC3_UI_FLOW_DUMP_FILE_FORMAT_STRING "-f " ++#define HINIC3_UI_FLOW_DUMP_FILE_TIPS_STRING "Dump all flows to a file" ++#define HINIC3_UI_FLOW_DUMP_CHECK_FORMAT_STRING "check" ++#define HINIC3_UI_FLOW_DUMP_CHECK_TIPS_STRING "Check the schedule of dumping flows to a file" ++#define HINIC3_UI_FLOW_DUMP_STOP_FORMAT_STRING "stop" ++#define HINIC3_UI_FLOW_DUMP_STOP_TIPS_STRING "Stop dumping flows to a file" ++#define HINIC3_UI_FLOW_DUMP_GET_FLOW_COUNT_FAILED_STRING "Failed to get current flow counts." ++#define HINIC3_UI_FLOW_DUMP_GET_BLOCK_SIZE_FAILED_STRING "Failed to get block size." ++#define HINIC3_UI_FLOW_DUMP_BLOCK_ID_ERROR_STRING "Invalid block id." ++#define HINIC3_UI_FLOW_GET_BLOCK_ID_FROM_FLOW_FAILED_STRING "Failed to get block id." ++#define HINIC3_UI_ACL_DUMP_GROUP_ID_STRING "group-id: " ++#define HINIC3_UI_ACL_DUMP_GROUP_ID_ERROR_STRING "group id should be INTEGER<0-3>" ++#define HINIC3_UI_ACL_DUMP_FAILURE_STRING "Acl dump failed, please check snic.log." ++#define HINIC3_UI_DUMP_CONTEXT_INDEX_STRING "context index:" ++#define HINIC3_UI_DUMP_CONTEXT_STATUS_STRING "status:" ++#define HINIC3_UI_DUMP_CONTEXT_IDLE_STRING "idle" ++#define HINIC3_UI_DUMP_CONTEXT_DUMPING_STRING "dumping" ++#define HINIC3_UI_DUMP_CONTEXT_THREAD_ID_STRING "thread id" ++#define HINIC3_UI_DUMP_CONTEXT_COUNT_STRING "dump count" ++#define HINIC3_UI_DUMP_CONTEXT_START_TIME_STRING "start time" ++#define HINIC3_UI_DUMP_CONTEXT_RUNNING_TIME_STRING "running time" ++ ++#define HINIC3_UI_FLOW_DUMP_FlOW_TO_FILE_COMPLETE_STRING "Dump hardware flows to file completed.\n" ++#define HINIC3_UI_FLOW_DUMP_FLOW_COUNT_STRING "Info: Current total flow count: %u.\n" ++#define HINIC3_UI_FLOW_ALLOC_FLOW_INFO_ERROR_STRING "Alloc flow info faild." ++#define HINIC3_UI_FLOW_DUMP_RUN_THREAD_FAILED_STRING "Start dump flows running thread failed." ++#define HINIC3_UI_FLOW_DUMP_FLOW_ERROR_STRING "Dump flow by hardware ufid failed." ++#define HINIC3_UI_FLOW_DUMP_NO_AVALIBLE_FLOW_STRING "No flow available." ++#define HINIC3_UI_FLOW_DUMP_NO_SESSION_STRING "No session available.\n" ++#define HINIC3_UI_FLOW_UFID_STRING " ufid: " ++#define HINIC3_UI_FLOW_RELATED_UFID_STRING "r_ufid:" ++#define HINIC3_UI_FLOW_KEY_STRING "key: " ++#define HINIC3_UI_FLOW_ACTION_STRING "actions: " ++#define HINIC3_UI_FLOW_STATISTIC_STRING "statistics: " ++#define HINIC3_UI_FLOW_FLAG_STRING "flags:" ++#define HINIC3_UI_FLOW_DUMP_STOP_DUMP_TIME_OUT_STRING "Dump all flows into file stopped time out ,please try again." ++#define HINIC3_UI_FLOW_DUMP_STOP_DUMP_SUCCESS_STRING "Dump all flows into file stopped. " ++#define HINIC3_UI_FLOW_DUMPIMG_TO_FILE_STRING "Being dumping all flows to out file." ++#define HINIC3_UI_FLOW_DUMP_TO_FILE_COMPLETE_STRING "Finished dumping all flows to out file." ++#define HINIC3_UI_FLOW_DUMP_FLOW_BUSY_STRING "Dump all flows is busy, please try again after a moment." ++#define HINIC3_UI_FLOW_DUMP_ALL_FLOW_START_FAILED_STRING "Start dump all flows failed." ++#define HINIC3_UI_FLOW_DUMP_ALL_FLOW_START_SUCCESS_STRING "Starting to dump hinic3 flows into file." ++#define HINIC3_UI_FLOW_DUMP_ALL_FLOW_TIPS_STRING "Being dumping all hinic3 flows to file, Please try again later !" ++#define HINIC3_UI_FLOW_UP_MAX_TIPS_STRING "%2sTotal hardware flows %u more than %u, please dump to file\n" ++#define HINIC3_UI_FLOW_WITH_BLOCKID_UP_MAX_TIPS_STRING \ ++ "Total hardware flows with block_id(%u) %u more than %u, please dump to file\n" ++#define HINIC3_UI_FLOW_DUMP_TOTAL_FLOW_STRING "Total flows: " ++#define HINIC3_UI_FLOW_UP_DISPLAY_MAX_TIPS_STRING "%sA maximum of %u flows can be displayed.\n" ++#define HINIC3_UI_FLOW_DUMP_TOTAL_CT_LOST_PKT_STRING "Total lost ct pkts: " ++ ++#define HINIC3_UI_FILE_PATH_MALLOC_TIPS_STRING "Malloc memmory for real path fail!" ++#define HINIC3_UI_FILE_DIRECTORY_SIZE_REACH_LIMIT_STRING \ ++ "%sDirectory (%s) size (%" PRIu64 "MB) reachs or exceeds the limit (%uMB) !\n" ++#define HINIC3_UI_FILE_GET_ABSOLUTE_PATH_FAIL_STRING "%sGet absolute file path fail! wrong filename: %s.\n" ++#define HINIC3_UI_FILE_PATH_TIPS_STRING "%sResolve path: %s is invalid!\n" ++#define HINIC3_UI_FILE_NOT_ABSOLUTE_PATH_STRING "The file path is incorrect, please check the file path.\n" ++#define HINIC3_UI_FILE_OPEN_FAILED_STRING "%sCan not open file : %s, please check the file path.\n" ++#define HINIC3_UI_FILE_PATH_CREATE_STRING "%sCreating file path: %s.\n" ++#define HINIC3_UI_FILE_PATH_APPEND_STRING "%sAppending to file path: %s.\n" ++#define HINIC3_UI_FILE_PATH_LENGTH_TIPS_STRING "Filename is too long!\n" ++#define HINIC3_UI_FILE_NO_SPACE_STRING "%sNo space left for file: %s.\n" ++ ++#define HINIC3_UI_FLOW_PACKET_STRING "packets" ++#define HINIC3_UI_FLOW_BYTES_STRING "bytes" ++#define HINIC3_UI_FLOW_AGE_TIME_STRING "age" ++#define HINIC3_UI_FLOW_LIVE_TIME_STRING "live" ++#define HINIC3_UI_FLOW_CT_INFO_STRING "ct_drop" ++#define HINIC3_UI_KEY_VNI_STR "vni" ++#define HINIC3_UI_KEY_DSCP_STR "dscp" ++#define HINIC3_UI_KEY_VXLAN_RSVD "rsvd0" ++#define HINIC3_UI_KEY_DP_HASH_STR "dp_hash" ++#define HINIC3_UI_KEY_RECIRC_ID_STR "recirc_id" ++#define HINIC3_UI_KEY_VID_STR "vid" ++#define HINIC3_UI_KEY_VLAN_TCI_STR "vlan_tci" ++#define HINIC3_UI_KEY_DL_TYPE_STR "dl_type" ++#define HINIC3_UI_KEY_NW_SRC_STR "nw_src" ++#define HINIC3_UI_KEY_NW_DST_STR "nw_dst" ++#define HINIC3_UI_KEY_NW_PROTO_STR "nw_protocol" ++#define HINIC3_UI_KEY_TP_SRC_STR "tp_src" ++#define HINIC3_UI_KEY_TP_DST_STR "tp_dst" ++#define HINIC3_UI_KEY_OUTER_VLAN_STR "outer_vlan" ++#define HINIC3_UI_KEY_INNER_VLAN_STR "inner_vlan" ++#define HINIC3_UI_KEY_VPORT_STR "vport" ++#define HINIC3_UI_KEY_IFINDEX_STR "ifindex" ++#define HINIC3_UI_KEY_SRC_MAC_STR "smac" ++#define HINIC3_UI_KEY_DST_MAC_STR "dmac" ++#define HINIC3_UI_KEY_DST_IP_STR "dst_ip" ++#define HINIC3_UI_KEY_SRC_IP_STR "src_ip" ++#define HINIC3_UI_KEY_ETH_TYPE_STR "eth_type" ++#define HINIC3_UI_KEY_INNER_ETH_TYPE_STR "inner_type" ++#define HINIC3_UI_KEY_DST_OUT_IP_STR "out_dst_ip" ++#define HINIC3_UI_KEY_SRC_OUT_IP_STR "out_src_ip" ++#define HINIC3_UI_KEY_ICMP_ID_STR "icmp_id" ++#define HINIC3_UI_KEY_ICMP6_ID_STR "icmp6_id" ++#define HINIC3_UI_KEY_ICMP_CODE_STR "icmp_code" ++#define HINIC3_UI_KEY_ICMP6_CODE_STR "icmp6_code" ++#define HINIC3_UI_KEY_DST_PORT_STR "dst_port" ++#define HINIC3_UI_KEY_SRC_PORT_STR "src_port" ++#define HINIC3_UI_KEY_ICMP6_TYPE_STR "icmp6_type" ++#define HINIC3_UI_KEY_ICMP_TYPE_STR "icmp_type" ++#define HINIC3_UI_KEY_CT_STR "ct" ++#define HINIC3_UI_KEY_CT_SEQ_LOW_STR "seqlo" ++#define HINIC3_UI_KEY_CT_SEQ_HIGH_STR "seqhi" ++#define HINIC3_UI_KEY_CT_MAX_WIN_STR "max_win" ++#define HINIC3_UI_KEY_CT_SACLE_STR "wscale" ++#define HINIC3_UI_KEY_CT_STATE_STR "state" ++#define HINIC3_UI_KEY_VXLAN_PUSH_STR "tnl_push" ++#define HINIC3_UI_KEY_VXLAN_POP_STR "tnl_pop" ++#define HINIC3_UI_KEY_GRE_ENCAP "gre_encap" ++#define HINIC3_UI_KEY_TURE_STR "true" ++#define HINIC3_UI_KEY_FALSE_STR "false" ++#define HINIC3_UI_KEY_VLAN_PUSH_STR "vlan_push" ++#define HINIC3_UI_KEY_VLAN_POP_STR "vlan_pop" ++#define HINIC3_UI_KEY_VLAN_PCP_STR "pcp" ++#define HINIC3_UI_KEY_VLAN_SET_PRIORITY_STR "set_priority" ++#define HINIC3_UI_KEY_VLAN_SET_SMAC_STR "set_smac" ++#define HINIC3_UI_KEY_VLAN_SET_DMAC_STR "set_dmac" ++#define HINIC3_UI_KEY_VLAN_SET_SIP_STR "set_sip" ++#define HINIC3_UI_KEY_VLAN_SET_DIP_STR "set_dip" ++#define HINIC3_UI_KEY_VLAN_SET_SPORT_STR "set_sport" ++#define HINIC3_UI_KEY_VLAN_SET_DPORT_STR "set_dport" ++#define HINIC3_UI_KEY_VLAN_OUTPUT_STR "output" ++#define HINIC3_UI_KEY_VLAN_MIRROR_STR "mirror" ++#define HINIC3_UI_KEY_DROP "drop" ++#define HINIC3_UI_KET_TTL_DEC "dec_ttl" ++#define HINIC3_UI_KEY_DP_HASH_STR "dp_hash" ++#define HINIC3_UI_KEY_RECIRC_ID_STR "recirc_id" ++#define HINIC3_UI_KEY_GRE_PROTOCOL "gre_pro" ++#define HINIC3_UI_KEY_GRE_RSVD "gre_rsvd" ++#define HINIC3_UI_KEY_SAMPLE "sample" ++#define HINIC3_UI_KEY_SAMPLE_RATIO "ratio" ++#define HINIC3_UI_TCP_STATE_TYPE_CLOSE_STR "closed" ++#define HINIC3_UI_TCP_STATE_TYPE_LISTEN_STR "listen" ++#define HINIC3_UI_TCP_STATE_TYPE_SYN_SENT_STR "sent" ++#define HINIC3_UI_TCP_STATE_TYPE_ESTABLISHED_STR "established" ++#define HINIC3_UI_TCP_STATE_TYPE_SYN_RECV_STR "recv" ++#define HINIC3_UI_TCP_STATE_TYPE_CLOSE_WAIT_STR "close-wait" ++#define HINIC3_UI_TCP_STATE_TYPE_FIN_WAIT_1_STR "fin-wait-1" ++#define HINIC3_UI_TCP_STATE_TYPE_LAST_ACK_STR "last-ack" ++#define HINIC3_UI_TCP_STATE_TYPE_FIN_WAIT_2_STR "fin-wait-2" ++#define HINIC3_UI_TCP_STATE_TYPE_TIME_WAIT_STR "time-wait" ++#define HINIC3_UI_TCP_STATE_TYPE_CLOSING_STR "closing" ++#define HINIC3_UI_TCP_STATE_TYPE_UNKNOWN_STR "unkown-ct-tcp-state" ++#define HINIC3_UI_ACTION_BLOCK_ID_STR "block-id" ++#define HINIC3_UI_ACTION_BLOCK_VERSION_STR "block-version" ++#define HINIC3_UI_KEY_QOS_INFO "(id: %u, type: %u), " ++ ++#define HINIC3_UI_PORT_NAME_INVALID_STR "port_name %s is invalid\n" ++#define HINIC3_UI_PORT_ID_INVALID_STR "port %s get port id failed\n" ++#define HINIC3_UI_PORT_CONFIG_INVALID_STR "port %s get port config failed\n" ++#define HINIC3_UI_SECURITY_INFO_GET_ERR_STR "get global security filter config failed\n" ++#define HINIC3_UI_PORT_NAME_STR "port_name" ++#define HINIC3_UI_SRC_MAC_STR "src-mac" ++#define HINIC3_UI_ETH_TYPE_GROUP_ID_STR "eth-type-group-%d:\n" ++#define HINIC3_UI_ETH_TYPE_STR "eth-type" ++#define HINIC3_UI_ETH_TYPE_RELATRE_PORT_STR "relate-ports" ++ ++#define HINIC3_UI_INVALID_QOS_ID_STR "Invalid argument (qos-id is out of range).\n" ++#define HINIC3_UI_INVALID_GROUP_ID_STR "Invalid argument (group is out of range).\n" ++#define HINIC3_UI_INVALID_METER_ID_STR "Invalid argument (meter id is wrong).\n" ++#define HINIC3_UI_INVALID_POLICY_ID_STR "Invalid argument (policy id is wrong).\n" ++#define HINIC3_UI_INVALID_PROFILE_ID_STR "Invalid argument (profile id is wrong).\n" ++#define HINIC3_UI_INVALID_PORT_NAME_STR "port name is wrong.\n" ++#define HINIC3_UI_INVALID_FUNC_ID_STR "Invalid argument (func-id is wrong)\n" ++#define HINIC3_UI_QOS_NOT_EXIST_STR "Invalid argument (qos is not exist in this port type)\n" ++#define HINIC3_UI_INVALID_PCI_ID_STR "Invalid argument (pci-id is wrong)\n" ++#define HINIC3_UI_QOS_ID_TOO_LONG_STR "qos_id is too long\n" ++#define HINIC3_UI_GET_QOS_ERR_STR "Failed to get qos_id.\n" ++#define HINIC3_UI_GET_PORT_QOS_ERR_STR "The current port is not bound to qos.\n" ++#define HINIC3_UI_EMPTY_QOS_STR "QoS does not exist.\n" ++#define HINIC3_UI_POLICY_NO_VM_STR "The current rate limiting policy is not configured on the ports.\n" ++#define HINIC3_UI_FIRST_GET_PORT_INFO_ERR_STR "Failed to get the data of sent and received packets for the first time.\n" ++#define HINIC3_UI_SECOND_GET_PORT_INFO_ERR_STR "Failed to get the received and sent packet data for the second time.\n" ++#define HINIC3_UI_TIME_EXEC_ERR_STR "Get prot info execute time error.\n" ++#define HINIC3_UI_KEY_QOS_STR "qos" ++#define HINIC3_UI_KEY_METER_STR "meter_id" ++#define HINIC3_UI_KEY_METER_INFO "meter_info" ++#define HINIC3_UI_QOS_PIR "PIR" ++#define HINIC3_UI_QOS_CIR "CIR" ++#define HINIC3_UI_QOS_PBS "PBS" ++#define HINIC3_UI_QOS_CBS "CBS" ++#define HINIC3_QOS_UNIT_MAX_LEN 30 ++#define N_PKTS_DROPPED " n-pkts-dropped: %u\n" ++#define N_BYTES_DROPPED " n-byte-dropped: %u\n" ++#define QOS_LOSS " qos-id[%u]\n" ++#define METER_INFO " meter-id[%u]:\n" ++#define QOS_INFO "qos-id:" ++#define GET_METER_FAILED "qos-id is not exist\n" ++#define QOS_ACTION_OUTPUT "(qos-id:%u, qos-type:%u), " ++#define UNKNOWN_METER_TYPE "The type of meter must be bandwith or pps.\n" ++#define GET_METER_FORM_HOVS_FAILED "Get meter_info from hovs failed.\n" ++#define OUTPUT_FORMAT_ERROR "There was an output formatting error.\n" ++ ++#define HINIC3_UI_GET_ESCAPE_MODE_FAILED "%sGet flow escape mode failed (err:%d).\n" ++#define HINIC3_UI_SHOW_NO_FLOW_OFFLOAD_MODE "%sCurrent escape mode: no flow offload.\n" ++#define HINIC3_UI_SHOW_ALL_FLOW_OFFLOAD_MODE "%sCurrent escape mode: all flows offload.\n" ++#define HINIC3_UI_ESCAPE_MODE_INVALID "%sEscape mode invalid (type:%u).\n" ++#define HINIC3_UI_ESCAPE_MODE_SET_FAILED "%sSet escape mode failed (err:%d).\n" ++#define HINIC3_UI_ESCAPE_MODE_HELP_TIPS_STRING "hwoff/flow-escape-mode { enable | disable | show | { -h | --help } }" ++#define HINIC3_UI_ESCAPE_MODE_ENABLE_FORMAT_STRING "enable" ++#define HINIC3_UI_ESCAPE_MODE_ENABLE_TIPS_STRING "Enable the escape mode to not offload flows" ++#define HINIC3_UI_ESCAPE_MODE_DISABLE_FORMAT_STRING "disable" ++#define HINIC3_UI_ESCAPE_MODE_DISABLE_TIPS_STRING "Disable the escape mode to offload all flows" ++#define HINIC3_UI_ESCAPE_MODE_SHOW_FORMAT_STRING "show" ++#define HINIC3_UI_ESCAPE_MODE_SHOW_TIPS_STRING "Show the escape mode" ++#define HINIC3_UI_ESCAPE_MODE_SHOW_HELP_STRING "-h, --help" ++#define HINIC3_UI_ESCAPE_MODE_SHOW_HELP_TIPS_STRING "Display the help information" ++ ++#define HINIC3_UI_ITEM_MASK_STRING "mask:" ++#define HINIC3_UI_SESSION_ID "session id:" ++#define HINIC3_UI_TOS_STR "type_of_service" ++#define HINIC3_UI_VTC_STR "vtc_flow" ++#define HINIC3_UI_ARP_OP_STR "arp_op" ++#define HINIC3_UI_TAG_DATA_STR "tag_data" ++#define HINIC3_UI_TAG_INDEX_STR "tag_index" ++#define HINIC3_UI_COUNT_ACTION "count" ++#define HINIC3_UI_UPCALL_ACTION "upcall" ++#define HINIC3_UI_INDIR_ACTION "indir_handle" ++#define HINIC3_UI_REMARK_ACTION "remark" ++#define HINIC3_UI_DEC_TTL_ACTION "dec_ttl" ++#define HINIC3_UI_END "END" ++#define HINIC3_GET_STATS_IN_HOVS "Get stats is failed in hvos.\n" ++ ++#define HINIC3_EMC_ERROR_MSG_ITEM "Process flow emc item failed." ++#define HINIC3_EMC_ERROR_MSG_ACTION "Process flow emc action failed." ++#define HINIC3_EMC_ERROR_MSG_REPEATED "Repeatedly offload the flow table." ++#define HINIC3_EMC_ERROR_MSG_FLOW "Process flow emc failed." ++#define HINIC3_EMC_ERROR_MSG_OFFLOAD_HOVS "Offload flow to HOVS failed." ++#define HINIC3_EMC_ERROR_MSG_MODIFY_HOVS "Modify flow to HOVS failed." ++#define HINIC3_EMC_ERROR_MSG_MODIFY_SESSION "Modify session to HOVS failed." ++ ++#define HINIC3_LOW_LATENCY_CMD_STR "low_latency" ++#define HINIC3_HIGH_THROUGHPUT_CMD_STR "high_throughput" ++#define HINIC3_SET_FORWARD_MODE_INPUT_ERROR_STRING \ ++ "Invalid forward mode input, please input low_latency or high_throughput\n" ++#define HINIC3_SET_FORWARD_MODE_FAILED_STRING "Set forward mode failed.\n" ++#define HINIC3_SET_FORWARD_MODE_SUCCESS_STRING "Set forward mode success.\n" ++ ++/* hinic3 meminfo cmd ui string */ ++#define HINIC3_UI_MEMINFO_UNIT_STRING "Note: Memory unit is Bytes." ++#define HINIC3_UI_HUGEPAGE_MEMINFO_UNIT_STRING \ ++ "Note: Memory unit is Bytes. Available element is number of elements in memory pool." ++#define HINIC3_UI_MEMINFO_TOTAL_ALLOCATED_STRING "total allocated:" ++#define HINIC3_UI_MEMINFO_AVAILABLE_ELEM_STRING "available element:" ++#define HINIC3_UI_HUGEPAGE_MEMINFO_STATISTICS_STRING "Hugepage memory statistics: " ++#define HINIC3_UI_HUGEPAGE_MEMINFO_DISABLED_STRING "Hugepage memory statistic is not enabled. " ++#define HINIC3_UI_HEAP_STATISTICS_STRING "Heap statistics: " ++#define HINIC3_UI_MEMZONE_STATISTICS_STRING "Memzone statistics: " ++#define HINIC3_UI_MEMPOOL_STATISTICS_STRING "Mempool statistics: " ++#define HINIC3_UI_TOTAL_STATISTICS_STRING "Total statistics: " ++ ++/* hinic3 dfx port cmd ui string */ ++#define HINIC3_UI_DUMP_BOND_SLAVE_STRING "hwoff/dump-bond-slave-info " ++#define HINIC3_UI_BOND_TYPE_ERROR_STRING "the port type is not bond" ++#define HINIC3_UI_DUMP_BOND_SLAVE_FAILURE_STRING "%scan't dump bond slave info, errno is %d.\n" ++#define HINIC3_UI_GET_SLAVE_NAME_STRING "%sFailed to obtain the bond slave name info, errno is %d.\n" ++#define HINIC3_UI_BOND_SLAVE_STRING "BOND SLAVE[%u] INFO:" ++ ++/* hinic3 agent cmd ui string */ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_unaligned.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_unaligned.h +new file mode 100644 +index 0000000..0c1449e +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_unaligned.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_UNALIGNED_H_ ++#define _HINIC3_UNALIGNED_H_ ++ ++#include "hinic3_types.h" ++#define HINIC3_SHIFTS_LEN 16 ++ ++static inline uint32_t hinic3_get_16aligned_be32(const hinic3_16aligned_be32 *x) ++{ ++ return ((uint32_t)x->lo << HINIC3_SHIFTS_LEN) | x->hi; ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c +new file mode 100644 +index 0000000..aa7484d +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c +@@ -0,0 +1,515 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_util.h" ++#include ++#include ++#include ++#include "rte_common.h" ++#include "rte_bus.h" ++#include "hinic3_util.h" ++#include "hinic3_log.h" ++#include "hinic3_eth_util.h" ++#include "rte_ethdev.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_string_util.h" ++ ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++#define HINIC3_HEX_PREFIX_LEN 2 ++static clockid_t g_monotonic_clock = CLOCK_MONOTONIC; ++ ++static struct hinic3_mac_transformat g_mac_format[] = { ++ {HINIC3_MAC_COLON_FMT, MAC_SCAN_COLON_FMT}, ++ {HINIC3_MAC_HYPHEN_FMT, MAC_SCAN_HYPHEN_FMT}, ++ {HINIC3_MAC_HYPHEN_SHORT_FMT, MAC_SCAN_HYPHEN_SHORT_FMT}, ++}; ++ ++void* hinic3_xmalloc(size_t size, enum hinic3_module module_id) ++{ ++ void *p = hinic3_malloc(size ? size : 1, module_id); ++ ++ return p; ++} ++ ++char* hinic3_xmemdup0(const char *p_, size_t length, enum hinic3_module module_id) ++{ ++ char *p = NULL; ++ ++ p = hinic3_xmalloc(length + 1, module_id); ++ if (p == NULL) { ++ return NULL; ++ } ++ ++ memcpy(p, p_, length); ++ p[length] = '\0'; ++ ++ return p; ++} ++ ++char* hinic3_xstrdup(const char *s, enum hinic3_module module_id) ++{ ++ return hinic3_xmemdup0(s, strlen(s), module_id); ++} ++ ++char *hinic3_strdup(const char *target_str, enum hinic3_module module_id) ++{ ++ size_t size; ++ char *new_str = NULL; ++ ++ if (target_str == NULL) { ++ return NULL; ++ } ++ ++ size = strlen(target_str) + 1; ++ new_str = hinic3_calloc(1, size, module_id); ++ if (new_str != NULL) { ++ memcpy(new_str, target_str, size); ++ } ++ ++ return new_str; ++} ++ ++char* hinic3_xvasprintf(const char *format, va_list args, enum hinic3_module module_id) ++{ ++#define MAX_BUF_SIZE 256 ++ char str[MAX_BUF_SIZE + 1]; ++ va_list args2; ++ size_t needed; ++ char *s; ++ int ret; ++ ++ va_copy(args2, args); ++ ++ ret = vsnprintf(str, MAX_BUF_SIZE, format, args); ++ if (ret < 0) { ++ return NULL; ++ } ++ ++ needed = (size_t)ret; ++ s = hinic3_xmalloc(needed + 1, module_id); ++ if (s == NULL) { ++ return NULL; ++ } ++ ++ ret = vsnprintf(s, needed + 1, format, args2); ++ if (ret <= 0) { ++ hinic3_free(s); ++ return NULL; ++ } ++ ++ va_end(args2); ++ ++ return s; ++} ++ ++/* ++ * 功能描述: 将mac地址转换成字符串 ++ */ ++int smacs_stringfy(const struct eth_addr macs[], int n, char *str_macs, int str_macs_len) ++{ ++ int off = 0; ++ int suc_len; ++ ++ if (!str_macs || !macs) { ++ return -EINVAL; ++ } ++ ++ for (int i = 0; (i < n) && (str_macs_len - off - 1 > 0); i++) { ++ suc_len = snprintf(str_macs + off, str_macs_len - off, MAC_FMT, MAC_ARGS(macs[i].ea)); ++ if (suc_len < 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to snprintf_s macs"); ++ return -EINVAL; ++ } ++ off += suc_len; ++ } ++ /* 删除最后一个',' */ ++ if (off != 0) { ++ str_macs[off - 1] = '\0'; ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * 功能描述: 将16进制mac转换成字符串 ++ */ ++int extra_eth_types_stringfy(const uint16_t types[], int n, char *str_types, int str_types_len) ++{ ++ int off = 0; ++ int suc_len; ++ ++ if (!str_types || !types) { ++ return -EINVAL; ++ } ++ ++ for (int i = 0; (i < n) && (str_types_len - off - 1 > 0); i++) { ++ suc_len = snprintf(str_types + off, str_types_len - off, "%04x, ", types[i]); ++ if (suc_len < 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to snprintf_s eth type"); ++ return -EINVAL; ++ } ++ off += suc_len; ++ } ++ /* 删除最后一个',' */ ++ if (off != 0) { ++ str_types[off - HINIC3_HEX_PREFIX_LEN] = '\0'; ++ } ++ ++ return 0; ++} ++ ++bool is_valid_digit(const char *digit_str) ++{ ++ size_t len; ++ ++ if (digit_str == NULL) { ++ return false; ++ } ++ ++ len = strlen(digit_str); ++ if (len == 0) { ++ return false; ++ } ++ ++ for (size_t i = 0; i < len; i++) { ++ if (!isdigit(digit_str[i])) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++/* ++ * 功能描述: 将eth_type字符串转成数字 ++ */ ++int parse_extra_eth_types_str(const char *str_types, uint16_t types[], int *n) ++{ ++ char *arg = NULL; ++ char *next = NULL; ++ char *str_type = NULL; ++ int i; ++ int cnt = 0; ++ unsigned long type; ++ ++ if (!str_types || !types) { ++ HINIC3_LOG(ERR, AGENT, "parse eth type failed :empty list"); ++ return -EINVAL; ++ } ++ ++ arg = hinic3_strdup(str_types, HINIC3_COMMON_RESOURCE); ++ if (!arg) { ++ HINIC3_LOG(ERR, AGENT, "Alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ next = arg; ++ for (i = 0; i < BUM_ETYPE_MAX_COUNT; i++) { ++ char *endp = NULL; ++ ++ str_type = strsep(&next, ","); ++ if (str_type == NULL) { ++ break; ++ } ++ type = strtoul(str_type, &endp, STR_TO_HEX_BASE); ++ if ((type > USHRT_MAX) || ++ (type == 0 && str_type == endp) || *endp != '\0') { ++ HINIC3_LOG(ERR, AGENT, "ethernet type is invalid, index is %d", i); ++ hinic3_free(arg); ++ return -EINVAL; ++ } ++ types[i] = (uint16_t)type; ++ ++cnt; ++ } ++ if (next != NULL) { ++ HINIC3_LOG(ERR, AGENT, "ethernet type list is invalid or too many ethernet type codes"); ++ hinic3_free(arg); ++ return -EINVAL; ++ } ++ ++ *n = cnt; ++ hinic3_free(arg); ++ return 0; ++} ++ ++/* ++ * 功能描述: 解析源mac地址 ++ */ ++int parse_src_to_src_macs(const char *str_macs, struct eth_addr macs[], int *n) ++{ ++ char *arg = NULL; ++ char *next = NULL; ++ char *str_eth = NULL; ++ int i; ++ int ret; ++ int cnt = 0; ++ ++ if (!str_macs || !macs) { ++ return -EINVAL; ++ } ++ ++ arg = hinic3_strdup(str_macs, HINIC3_COMMON_RESOURCE); ++ if (!arg) { ++ HINIC3_LOG(ERR, AGENT, "Alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ next = arg; ++ for (i = 0; i < BUM_SMAC_MAX_COUNT; i++) { ++ str_eth = strsep(&next, ","); ++ if (str_eth == NULL) { ++ break; ++ } ++ ret = parse_mac(str_eth, (struct eth_address *)&macs[i]); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "ethernet MAC address is invalid, index is %d", i); ++ hinic3_free(arg); ++ return ret; ++ } ++ ++cnt; ++ } ++ ++ if (next != NULL) { ++ HINIC3_LOG(ERR, AGENT, "SMAC-list is invalid or too many ethernet MAC address"); ++ hinic3_free(arg); ++ return -EINVAL; ++ } ++ ++ *n = cnt; ++ hinic3_free(arg); ++ return 0; ++} ++ ++/* ++ * 功能描述: 将bdf数字转换成字符串 ++ */ ++int pci_addr_format(const struct rte_pci_addr *pci_addr, char *buf, int buf_len) ++{ ++ int len = snprintf(buf, buf_len, PCI_PRI_FMT, ++ pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function); ++ if (len <= 0) { ++ HINIC3_LOG(ERR, AGENT, "snprintf_s pci to bdf error"); ++ return -1; ++ } ++ return 0; ++} ++ ++static inline int char_is_valid_hex(const char input) ++{ ++ if ((input >= '0' && input <= '9') || ++ (input >= 'a' && input <= 'f') || ++ (input >= 'A' && input <= 'F')) { ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++int check_valid_mac(const char *mac, enum hinic3_mac_fmt fmt) ++{ ++ bool is_ready_for_separator = false; ++ int separator_count = 0; ++ int hex_count_between_separator = 0; ++ const char *p = mac; ++ int separator_max; ++ int char_num_between_separator; ++ char separator; ++ ++ switch (fmt) { ++ case HINIC3_MAC_COLON_FMT: ++ /* xx:xx:xx:xx:xx:xx */ ++ separator_max = HINIC3_MAC_COLON_FMT_SEPARATOR_NUM; ++ char_num_between_separator = HINIC3_MAC_COLON_FMT_CHAR_NUM_BETWEEN_SEPARATOR; ++ separator = ':'; ++ break; ++ case HINIC3_MAC_HYPHEN_FMT: ++ /* xx-xx-xx-xx-xx-xx */ ++ separator_max = HINIC3_MAC_HYPHEN_FMT_SEPARATOR_NUM; ++ char_num_between_separator = HINIC3_MAC_HYPHEN_FMT_CHAR_NUM_BETWEEN_SEPARATOR; ++ separator = '-'; ++ break; ++ case HINIC3_MAC_HYPHEN_SHORT_FMT: ++ /* xxxx-xxxx-xxxx */ ++ separator_max = HINIC3_MAC_HEPHEN_SHORT_FMT_SEPARATOR_NUM; ++ char_num_between_separator = HINIC3_MAC_HEPHEN_SHORT_FMT_CHAR_NUM_BETWEEN_SEPARATOR; ++ separator = '-'; ++ break; ++ default: ++ return -1; ++ } ++ ++ while (*p != '\0') { ++ if (is_ready_for_separator && (*p == separator)) { ++ is_ready_for_separator = false; ++ hex_count_between_separator = 0; ++ separator_count++; ++ if (separator_count > separator_max) { ++ return -EINVAL; ++ } ++ p++; ++ continue; ++ } ++ ++ hex_count_between_separator++; ++ if (hex_count_between_separator > char_num_between_separator) { ++ return -EINVAL; ++ } ++ ++ if (char_is_valid_hex(*p) != 0) { ++ return -EINVAL; ++ } ++ ++ is_ready_for_separator = true; ++ p++; ++ } ++ return 0; ++} ++ ++int check_valid_eth_type(const char *eth_type) ++{ ++ int count = 0; ++ const char *p = eth_type; ++ size_t len = strlen(eth_type); ++ if (len < HINIC3_HEX_PREFIX_LEN || eth_type[0] != '0' || eth_type[1] != 'x') { ++ return -1; ++ } else { ++ p += HINIC3_HEX_PREFIX_LEN; ++ } ++ ++ while (*p != '\0') { ++ count++; ++ if (count > (HINIC3_ETH_TYPE_LEN + HINIC3_ETH_TYPE_LEN)) { ++ return -1; ++ } ++ if (char_is_valid_hex(*p) != 0) { ++ return -1; ++ } ++ p++; ++ } ++ return 0; ++} ++ ++int parse_mac(const char *mac, const struct eth_address *output_mac) ++{ ++ int ret = 0; ++ size_t i; ++ int success_len = 0; ++ struct eth_address eth_addr = { 0 }; ++ ++ for (i = 0; i < ARRAY_SIZE(g_mac_format); i++) { ++ ret = check_valid_mac(mac, g_mac_format[i].mac_fmt); ++ if (ret == 0 && g_mac_format[i].mac_fmt != HINIC3_MAC_HYPHEN_SHORT_FMT) { ++ success_len = sscanf(mac, g_mac_format[i].fmt_str, MAC_SCAN_ARGS(*output_mac)); ++ break; ++ } else if (ret == 0 && g_mac_format[i].mac_fmt == HINIC3_MAC_HYPHEN_SHORT_FMT) { ++ success_len = sscanf(mac, g_mac_format[i].fmt_str, MAC_SCAN_HYPHEN_SHORT_ARGS(eth_addr)); ++ for (size_t j = 0; j < ARRAY_SIZE(output_mac->be16); j++) { ++ eth_addr.be16[j] = htons(eth_addr.be16[j]); ++ } ++ memcpy((void *)output_mac->ea, (void *)eth_addr.ea, sizeof(uint8_t) * HINIC3_ETH_ADDR_LEN); ++ break; ++ } ++ } ++ ++ if (success_len != HINIC3_ETH_ADDR_LEN) { ++ if (success_len == ARRAY_SIZE(output_mac->be16) && g_mac_format[i].mac_fmt == HINIC3_MAC_HYPHEN_SHORT_FMT) { ++ return 0; ++ } ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++long long int hinic3_time_msec(void) ++{ ++ struct timespec ts; ++ int ret; ++ ret = clock_gettime(g_monotonic_clock, &ts); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get time by hinic3_time_mesc function, err is %d", errno); ++ return -1; ++ } ++ return (long long int)ts.tv_sec * SEC_TO_MSEC_BASE + ts.tv_nsec / MSEC_TO_NSEC_BASE; ++} ++ ++long long int hinic3_time_sec(void) ++{ ++ struct timespec ts; ++ int ret; ++ ret = clock_gettime(g_monotonic_clock, &ts); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get time by hinic3_time_mesc function, err is %d", errno); ++ return -1; ++ } ++ return (long long int)ts.tv_sec; ++} ++ ++static int hinic3_set_cpu_affinity(pthread_t *thread, uint32_t core_list[], uint32_t count) ++{ ++ uint32_t i; ++ int ret; ++ cpu_set_t cpuset; ++ ++ if (thread == NULL) { ++ return -1; ++ } ++ ++ CPU_ZERO(&cpuset); ++ for (i = 0; i < count; i++) { ++ CPU_SET(core_list[i], &cpuset); ++ } ++ ++ ret = pthread_setaffinity_np(*thread, sizeof(cpuset), &cpuset); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to set thread affinity."); ++ return -1; ++ } ++ return 0; ++} ++ ++int hinic3_set_single_cpu_affinity(pthread_t *thread, uint32_t core) ++{ ++ int ret; ++ cpu_set_t cpuset; ++ ++ if (thread == NULL) { ++ return -1; ++ } ++ ++ CPU_ZERO(&cpuset); ++ CPU_SET(core, &cpuset); ++ ret = pthread_setaffinity_np(*thread, sizeof(cpuset), &cpuset); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to set thread affinity."); ++ return -1; ++ } ++ return 0; ++} ++ ++void hinic3_set_ctrl_thread_cpu_affinity(pthread_t *thread) ++{ ++ struct hinic3_cpu_mask control_cpu_mask = hinic3_control_cpu_mask_get(); ++ struct hinic3_dp_extend_info *dp_info = hinic3_get_offload_extend_info(); ++ ++ if (dp_info->control_num_in_env > 0) { ++ (void)hinic3_set_cpu_affinity(thread, dp_info->control_thread_core, dp_info->control_num_in_env); ++ } else { ++ if (control_cpu_mask.cpu_mask_invalid_num > 0) { ++ (void)hinic3_set_cpu_affinity(thread, control_cpu_mask.cpu_mask, ++ control_cpu_mask.cpu_mask_invalid_num); ++ } ++ } ++} ++ ++int hinic3_set_thread_name_by_str(char *name) ++{ ++ char thread_name[HINIC3_THREAD_NAME_MAX]; ++ size_t len = strnlen(name, sizeof(thread_name) - 1); ++ memcpy(thread_name, name, len); ++ ++ thread_name[len] = '\0'; ++ return pthread_setname_np(pthread_self(), thread_name); ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h +new file mode 100644 +index 0000000..e355038 +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h +@@ -0,0 +1,220 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_UTIL_H ++#define HINIC3_UTIL_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rte_pci.h" ++#include "rte_bus_pci.h" ++#include "rte_cycles.h" ++#include "rte_config.h" ++#include "hinic3_packets_types.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_flow_agent_enum.h" ++ ++#define CPUSET_DIGITAL_BASE 10 ++#define STR_TO_DEC_NUM 10 ++#define STR_TO_HEX_BASE 16 ++#define BUM_SMAC_MAX_COUNT 16 ++#define MAC_STR_LEN 18 ++#define BUM_ETYPE_MAX_COUNT 64 ++#define ETH_TYPE_ALEN 5 ++#define CACHE_LINE_SIZE 64 ++#define ETC_MAXLINE 1024 ++#define BASE_DECIMAL 10 ++#define MAX_BYTE_DATA 256 ++#define LONG_BIT_LONG 64 ++#define HALF_CHAR 4 ++ ++#define PCI_ADDR_LEN 12 ++#define SEC_TO_MSEC_BASE 1000 ++#define MSEC_TO_NSEC_BASE 1000000 ++ ++#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x," ++#define MAC_ARGS(eth) (eth)[0], (eth)[1], (eth)[2], (eth)[3], (eth)[4], (eth)[5] ++ ++/** for bit ops */ ++#define BITS_PER_BYTE 8 ++ ++#define RTE_LCORE_INDEX_CURRENT (rte_lcore_index(-1) < 0 ? 0 : rte_lcore_index(-1)) ++#define HINIC3_OVS_GROUP_NAME "dpak_ovs" ++ ++#if __GNUC__ && !__CHECKER__ ++#define HINIC3_UNUSED __attribute__((__unused__)) ++#define HINIC3_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) ++#define HINIC3_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1) ++#define HINIC3_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0) ++#else ++#define HINIC3_UNUSED ++#define HINIC3_WARN_UNUSED_RESULT ++#define HINIC3_UNLIKELY(CONDITION) (!!(CONDITION)) ++#endif ++ ++#define HINIC3_PRIORITY_SYMBOL 101 ++#define HINIC3_PRIORITY_CONFIG 110 ++#define HINIC3_PRIORITY_MUTEX 120 ++#define HINIC3_PRIORITY_INIT 130 ++#define HINIC3_PRIORITY_DRIVER 140 ++#define HINIC3_PRIORITY_LAST 65535 ++ ++enum { ++ PCI_VENDOR_ID_HINIC = 0x19e5, ++ PCI_DEVICE_ID_HINIC_PF = 0x0222, ++ PCI_VENDOR_ID_HINIC_VF = 0x1af4, ++ PCI_DEVICE_ID_HINIC_VF = 0x1000, ++}; ++ ++#define DPU_MODE_DEVICE_ID_HINIC_PF 0x0224 ++ ++#ifndef MIN ++#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) ++#endif ++ ++#define ARRAY_SIZE_NOCHECK(ARRAY) (sizeof(ARRAY) / sizeof((ARRAY)[0])) ++ ++#define ARRAY_CHECK(ARRAY) \ ++ !__builtin_types_compatible_p(typeof(ARRAY), typeof(&(ARRAY)[0])) ++ ++#define ARRAY_FAIL(ARRAY) (sizeof(char[-2*!ARRAY_CHECK(ARRAY)])) ++ ++#define ARRAY_SIZE(ARRAY) \ ++ __builtin_choose_expr(ARRAY_CHECK(ARRAY), \ ++ ARRAY_SIZE_NOCHECK(ARRAY), ARRAY_FAIL(ARRAY)) ++ ++static inline int parse_str_to_value(const char *str, uint32_t *value) ++{ ++ long long int val; ++ char *end = NULL; ++ ++ val = strtoll(str, &end, STR_TO_DEC_NUM); ++ if (!end || *end != '\0' || val > UINT_MAX || val < 0) { ++ return -EINVAL; ++ } ++ ++ *value = (uint32_t)val; ++ return 0; ++} ++ ++#ifndef __has_feature ++ #define __has_feature(x) 0 ++#endif ++ ++#if __has_feature(c_thread_safety_attributes) ++#define HINIC3_GUARDED __attribute__((guarded_var)) ++#define HINIC3_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__))) ++#define HINIC3_RELEASES(...) __attribute__((unlock_function(__VA_ARGS__))) ++#define HINIC3_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) ++#define HINIC3_ACQ_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) ++#define HINIC3_ACQ_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) ++#define HINIC3_NO_THREAD_SAFETY_ANALYSIS \ ++ __attribute__((no_thread_safety_analysis)) ++#else /* not Clang */ ++#define HINIC3_LOCKABLE ++#define HINIC3_REQ_RDLOCK(...) ++#define HINIC3_ACQ_RDLOCK(...) ++#define HINIC3_REQ_WRLOCK(...) ++#define HINIC3_ACQ_WRLOCK(...) ++#define HINIC3_REQUIRES(...) ++#define HINIC3_ACQUIRES(...) ++#define HINIC3_TRY_WRLOCK(...) ++#define HINIC3_TRY_RDLOCK(...) ++#define HINIC3_TRY_LOCK(...) ++#define HINIC3_GUARDED ++#define HINIC3_GUARDED_BY(...) ++#define HINIC3_EXCLUDED(...) ++#define HINIC3_RELEASES(...) ++#define HINIC3_ACQ_BEFORE(...) ++#define HINIC3_ACQ_AFTER(...) ++#define HINIC3_NO_THREAD_SAFETY_ANALYSIS ++#endif ++ ++#define HINIC3_OBJECT_OFFSETOF(OBJECT, MEMBER) offsetof(typeof(*(OBJECT)), MEMBER) ++ ++#define HINIC3_OBJECT_CONTAINING(POINTER, OBJECT, MEMBER) \ ++ ((typeof(OBJECT)) (void *) \ ++ ((char *) (POINTER) - HINIC3_OBJECT_OFFSETOF(OBJECT, MEMBER))) ++ ++#define HINIC3_CONTAINER_ASSIGN(OBJECT, POINTER, MEMBER) \ ++ ((OBJECT) = HINIC3_OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0) ++ ++#define HINIC3_CONTAINER_INIT(OBJECT, POINTER, MEMBER) \ ++ ((OBJECT) = NULL, HINIC3_CONTAINER_ASSIGN(OBJECT, POINTER, MEMBER)) ++ ++#define HINIC3_BUILD_ASSERT_TYPE(POINTER, TYPE) \ ++ ((void)sizeof((int)((POINTER) == (TYPE)(POINTER)))) ++ ++#define HINIC3_CONST_CAST(TYPE, POINTER) \ ++ (HINIC3_BUILD_ASSERT_TYPE(POINTER, TYPE), \ ++ (TYPE)(POINTER)) ++ ++#define HINIC3_CONTAINER_OF(POINTER, STRUCT, MEMBER) \ ++ ((STRUCT *) (void *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER))) ++ ++#define HINIC3_SOURCE_LOCATOR __FILE__ ":" HINIC3_STRINGIZE(__LINE__) ++#define HINIC3_STRINGIZE(ARG) HINIC3_STRINGIZE2(ARG) ++#define HINIC3_STRINGIZE2(ARG) #ARG ++ ++#define MAC_SCAN_HYPHEN_SHORT_FMT "%" SCNx16 "-%" SCNx16 "-%" SCNx16 ++#define MAC_SCAN_HYPHEN_FMT "%" SCNx8 "-%" SCNx8 "-%" SCNx8 "-%" SCNx8 "-%" SCNx8 "-%" SCNx8 ++#define MAC_SCAN_COLON_FMT "%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ++#define MAC_SCAN_ARGS(EA) &(EA).ea[0], &(EA).ea[1], &(EA).ea[2], &(EA).ea[3], &(EA).ea[4], &(EA).ea[5] ++#define MAC_SCAN_HYPHEN_SHORT_ARGS(EA) &(EA).ea[0], &(EA).ea[2], &(EA).ea[4] ++ ++#ifndef HINIC3_MIN ++#define HINIC3_MIN(X, Y) ((X) < (Y) ? (X) : (Y)) ++#endif ++ ++#define HINIC3_MAC_COLON_FMT_SEPARATOR_NUM 5 ++#define HINIC3_MAC_HYPHEN_FMT_SEPARATOR_NUM 5 ++#define HINIC3_MAC_HEPHEN_SHORT_FMT_SEPARATOR_NUM 2 ++#define HINIC3_MAC_COLON_FMT_CHAR_NUM_BETWEEN_SEPARATOR 2 ++#define HINIC3_MAC_HYPHEN_FMT_CHAR_NUM_BETWEEN_SEPARATOR 2 ++#define HINIC3_MAC_HEPHEN_SHORT_FMT_CHAR_NUM_BETWEEN_SEPARATOR 4 ++ ++enum hinic3_mac_fmt { ++ HINIC3_MAC_COLON_FMT = 0, ++ HINIC3_MAC_HYPHEN_FMT, ++ HINIC3_MAC_HYPHEN_SHORT_FMT, ++ HINIC3_MAC_FMT_MAX, ++}; ++ ++struct hinic3_mac_transformat { ++ enum hinic3_mac_fmt mac_fmt; ++ const char *fmt_str; ++}; ++ ++int smacs_stringfy(const struct eth_addr macs[], int n, char *str_macs, int str_macs_len); ++int extra_eth_types_stringfy(const uint16_t types[], int n, char *str_types, int str_types_len); ++int parse_src_to_src_macs(const char *str_macs, struct eth_addr macs[], int *n); ++int parse_extra_eth_types_str(const char *str_types, uint16_t types[], int *n); ++bool is_valid_digit(const char *digit_str); ++void* hinic3_xmalloc(size_t size, enum hinic3_module module_id); ++char* hinic3_xmemdup0(const char *p_, size_t length, enum hinic3_module module_id); ++char* hinic3_xstrdup(const char *s, enum hinic3_module module_id); ++char *hinic3_strdup(const char *target_str, enum hinic3_module module_id); ++char* hinic3_xvasprintf(const char *format, va_list args, enum hinic3_module module_id); ++int pci_addr_format(const struct rte_pci_addr *pci_addr, char *buf, int buf_len); ++ ++int parse_mac(const char *mac, const struct eth_address *output_mac); ++int check_valid_mac(const char *mac, enum hinic3_mac_fmt fmt); ++int check_valid_eth_type(const char *eth_type); ++ ++long long int hinic3_time_msec(void); ++long long int hinic3_time_sec(void); ++void hinic3_set_ctrl_thread_cpu_affinity(pthread_t *thread); ++int hinic3_set_single_cpu_affinity(pthread_t *thread, uint32_t core); ++int hinic3_set_thread_name_by_str(char *name); ++ ++#endif +diff --git a/drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.c b/drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.c +new file mode 100644 +index 0000000..77e5e5e +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.c +@@ -0,0 +1,89 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include "hinic3_string_util.h" ++#include "hinic3_uuid.h" ++ ++#define HINIC3_STR_TO_HEX_HEAD_TAIL_SIZE 8 ++#define HINIC3_STR_TO_HEX_MIDDLE_SIZE 4 ++#define HINIC3_STR_TO_HEX_MIDDLE_LEFT_SHIFIT 16 ++#define HINIC3_UUID_PART_ONE 0 ++#define HINIC3_UUID_PART_TWO 1 ++#define HINIC3_UUID_PART_THREE 2 ++#define HINIC3_UUID_PART_FOUR 3 ++ ++void hinic3_uuid_zero(struct uuid *uuid) ++{ ++ *uuid = UUID_ZERO; ++} ++ ++bool hinic3_uuid_from_string(struct uuid *uuid, const char *s) ++{ ++ if (!hinic3_uuid_from_string_prefix(uuid, s)) { ++ return false; ++ } else if (s[UUID_LEN] != '\0') { ++ hinic3_uuid_zero(uuid); ++ return false; ++ } else { ++ return true; ++ } ++} ++ ++bool hinic3_uuid_from_string_prefix(struct uuid *uuid, const char *s) ++{ ++ bool ok; ++ int offset = 0; ++ int check_offset = HINIC3_STR_TO_HEX_HEAD_TAIL_SIZE; ++ ++ if (strlen(s) != UUID_LEN) { ++ goto error; ++ } ++ ++ uuid->parts[HINIC3_UUID_PART_ONE] = hinic3_hexits_value(s + offset, HINIC3_STR_TO_HEX_HEAD_TAIL_SIZE, &ok); ++ if (!ok || s[check_offset] != '-') { ++ goto error; ++ } ++ ++ offset += (HINIC3_STR_TO_HEX_HEAD_TAIL_SIZE + 1); ++ check_offset += (HINIC3_STR_TO_HEX_MIDDLE_SIZE + 1); ++ uuid->parts[HINIC3_UUID_PART_TWO] = ++ hinic3_hexits_value(s + offset, HINIC3_STR_TO_HEX_MIDDLE_SIZE, &ok) << HINIC3_STR_TO_HEX_MIDDLE_LEFT_SHIFIT; ++ if (!ok || s[check_offset] != '-') { ++ goto error; ++ } ++ ++ offset += (HINIC3_STR_TO_HEX_MIDDLE_SIZE + 1); ++ check_offset += (HINIC3_STR_TO_HEX_MIDDLE_SIZE + 1); ++ uuid->parts[HINIC3_UUID_PART_TWO] += hinic3_hexits_value(s + offset, HINIC3_STR_TO_HEX_MIDDLE_SIZE, &ok); ++ if (!ok || s[check_offset] != '-') { ++ goto error; ++ } ++ ++ offset += (HINIC3_STR_TO_HEX_MIDDLE_SIZE + 1); ++ check_offset += (HINIC3_STR_TO_HEX_MIDDLE_SIZE + 1); ++ uuid->parts[HINIC3_UUID_PART_THREE] = ++ hinic3_hexits_value(s + offset, HINIC3_STR_TO_HEX_MIDDLE_SIZE, &ok) << HINIC3_STR_TO_HEX_MIDDLE_LEFT_SHIFIT; ++ if (!ok || s[check_offset] != '-') { ++ goto error; ++ } ++ ++ offset += (HINIC3_STR_TO_HEX_MIDDLE_SIZE + 1); ++ uuid->parts[HINIC3_UUID_PART_THREE] += hinic3_hexits_value(s + offset, HINIC3_STR_TO_HEX_MIDDLE_SIZE, &ok); ++ if (!ok) { ++ goto error; ++ } ++ ++ offset += (HINIC3_STR_TO_HEX_MIDDLE_SIZE); ++ uuid->parts[HINIC3_UUID_PART_FOUR] = hinic3_hexits_value(s + offset, HINIC3_STR_TO_HEX_HEAD_TAIL_SIZE, &ok); ++ if (!ok) { ++ goto error; ++ } ++ return true; ++ ++error: ++ hinic3_uuid_zero(uuid); ++ return false; ++} +diff --git a/drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.h b/drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.h +new file mode 100644 +index 0000000..4d4254f +--- /dev/null ++++ b/drivers/net/hinic3/src/common/hinic3_uuid/hinic3_uuid.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_UUID_H ++#define HINIC3_UUID_H ++ ++struct uuid { ++ uint32_t parts[4]; ++}; ++ ++#define UUID_LEN 36 ++#define UUID_ZERO ((struct uuid) { .parts = { 0, 0, 0, 0 } }) ++#define UUID_BIT 128 /* Number of bits in a UUID. */ ++#define UUID_OCTET (UUID_BIT / 8) /* Number of bytes in a UUID. */ ++#define UUID_FMT "%08x-%04x-%04x-%04x-%04x%08x" ++#define UUID_ARGS(UUID) \ ++ ((unsigned int) ((UUID)->parts[0])), \ ++ ((unsigned int) ((UUID)->parts[1] >> 16)), \ ++ ((unsigned int) ((UUID)->parts[1] & 0xffff)), \ ++ ((unsigned int) ((UUID)->parts[2] >> 16)), \ ++ ((unsigned int) ((UUID)->parts[2] & 0xffff)), \ ++ ((unsigned int) ((UUID)->parts[3])) ++ ++void hinic3_uuid_zero(struct uuid *uuid); ++bool hinic3_uuid_from_string(struct uuid *uuid, const char *s); ++bool hinic3_uuid_from_string_prefix(struct uuid *uuid, const char *s); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +new file mode 100644 +index 0000000..099d7b1 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +@@ -0,0 +1,437 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_lcore.h" ++#include "rte_spinlock.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#endif ++ ++#include "hinic3_ds.h" ++#include "hinic3_log.h" ++#include "hinic3_init.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_capture_core.h" ++#include "hinic3_capture_filter.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_util.h" ++#include "rte_ethdev.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_command.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_capture_command.h" ++ ++#define PCAP_CMD_DESC \ ++" Usage: dpak-ovs-ctl hwoff/capture-probe { start -w \n" \ ++" [ [ [ -sip ENUM,IPV6> | \n" \ ++" -dip ENUM,IPV6> ] * | \n" \ ++" -host ENUM,IPV6> ] | \n" \ ++" -thread | -smac MAC | -dmac MAC | \n" \ ++" -eth_type | -ip_proto ENUM |\n" \ ++" -vxlan_inner | -vlan INTEGER<0-4095> | -sport INTEGER<0-65535> |\n" \ ++" -dport INTEGER<0-65535> | -vxlan_vni INTEGER<0-16777215> |\n" \ ++" -P ENUM | -c INTEGER<1-1000000> ] * |\n" \ ++" stop { | -pcap_id } |\n" \ ++" show { all | -pcap_id } |\n" \ ++" { -h | --help } }\n\n" \ ++" Options list: \n" \ ++" start Start the packet capture task on a specified port\n" \ ++" -w Name of the packet capture file\n" \ ++" -sip Source IP address\n" \ ++" -dip Destination IP address\n" \ ++" -host Host IP address\n" \ ++" -smac Source MAC address\n" \ ++" -dmac Destination MAC address\n" \ ++" -eth_type Data type, in hexadecimal format, such as 0x0800, 0x86dd, " \ ++"0x8600\n" \ ++" -ip_proto Layer 4 protocol type, ENUM\n" \ ++" -vxlan_inner If VXLAN packets are captured, apply to the inner packet, " \ ++"Both outer and inner headers are captured\n" \ ++" -vlan VLAN ID, an integer with a range <0-4095>\n" \ ++" -sport Source port\n" \ ++" -dport Destination port\n" \ ++" -vxlan_vni VXLAN ID, an integer with a range <0-16777215>\n" \ ++" -P Packet capture direction, ENUM\n" \ ++" -c Number of captured packets, an integer with a " \ ++"range <1-1000000>. The default value is 8000 \n" \ ++" -thread Write files without the PMD thread\n" \ ++" stop Stop the packet capture task of a specified port or id\n" \ ++" -pcap_id Stop the packet capture task of a specified id. The value " \ ++"is an integer with a range <1-4294967295>\n" \ ++" show Display a packet capture task\n" \ ++" all Display all packet capture tasks\n" \ ++" -pcap_id Display the packet capture task of a specified id. " \ ++"The value is an integer with a range <1-4294967295>\n" \ ++ " -h, --help Display the help information\n" ++ ++static struct pcap_cmd_t g_cap_main_command = { "hwoff/capture-probe", ++ "{ start -w " ++ "[ [ [ -sip ENUM,IPV6> | " ++ "-dip ENUM,IPV6> ] * | " ++ "-host ENUM,IPV6> ] | " ++ "-thread | -smac MAC | -dmac MAC | " ++ "-eth_type | " ++ "-ip_proto ENUM | " ++ "-vxlan_inner | -vlan INTEGER<0-4095> | " ++ "-sport INTEGER<0-65535> | -dport INTEGER<0-65535> | " ++ "-vxlan_vni INTEGER<0-16777215> | -P ENUM | " ++ "-c INTEGER<1-1000000> ] * | " ++ "stop { | -pcap_id } | " ++ "show { all | -pcap_id } | " ++ "{ -h | --help } }", ++ pcap_cmd_exec, ++ PCAP_CMD_MIN_PARAM, ++ PCAP_CMD_MAX_PARAM, ++ PCAP_CMD_DESC }; ++ ++static struct pcap_cmd_t g_cap_sub_commands[] = { ++ {"start", " [ options ]", pcap_cmd_start, PCAP_CMD_START_MIN_PARAM, PCAP_CMD_START_MAX_PARAM, NULL}, ++ {"stop", "{ | -pcap_id }", pcap_cmd_stop, PCAP_CMD_STOP_MIN_PARAM, PCAP_CMD_STOP_MAX_PARAM, NULL}, ++ {"show", "{ all | -pcap_id }", pcap_cmd_show, PCAP_CMD_SHOW_MIN_PARAM, PCAP_CMD_SHOW_MAX_PARAM, NULL}, ++ {"-h", "", pcap_cmd_help, 0, 0, NULL}, ++ {"--help", "", pcap_cmd_help, 0, 0, NULL}, ++}; ++ ++void ++pcap_cmd_usage_print(struct ds *ds) ++{ ++ struct pcap_cmd_t *p_cmd = &g_cap_main_command; ++ ++ hinic3_ds_put_cstr(ds, p_cmd->desc); ++} ++ ++void ++pcap_cmd_enable_capture(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ pcap_switch_set(1); ++ HINIC3_LOG(INFO, AGENT, "capture is enabled."); ++ hinic3_ds_put_format(&ds, "%sCapture is enabled.\n", HINIC3_UI_LEADING_SIGN_INFO); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++} ++ ++void ++pcap_cmd_disable_capture(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ pcap_switch_set(0); ++ HINIC3_LOG(INFO, AGENT, "capture is disabled."); ++ hinic3_ds_put_format(&ds, "%sCapture is disabled.\n", HINIC3_UI_LEADING_SIGN_INFO); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++} ++ ++int ++pcap_stop_param_parse(int argc, const char *argv[], struct pcap_stop_param *param, struct ds *ds) ++{ ++ int ret; ++ struct pcap_port_t port_info; ++ char *port_name = NULL; ++ ++ if (strcmp("-pcap_id", argv[0]) == 0 && argc == PCAP_CMD_STOP_MAX_PARAM) { ++ param->pcap_id = strtoul(argv[PCAP_CMD_STOP_MAX_PARAM - 1], NULL, STR_TO_DEC_NUM); ++ if (param->pcap_id == 0) { ++ hinic3_ds_put_format(ds, "%sInvalid parameter value.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ return 0; ++ } ++ ++ if (argc == PCAP_CMD_STOP_MIN_PARAM) { ++ port_name = (char *)argv[0]; ++ memset(&port_info, 0, sizeof(port_info)); ++ ret = pcap_port_info_get_by_name(port_name, &port_info, ds); ++ if (ret != 0) ++ return -1; ++ ++ param->port_no = port_info.odp_port_no; ++ return 0; ++ } ++ ++ hinic3_ds_put_format(ds, "%sInvalid command format, please type help.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++} ++ ++int ++pcap_task_delete(struct pcap_stop_param *param, struct ds *ds) ++{ ++ if (param->pcap_id == 0) ++ return pcap_task_delete_all(param->port_no, ds); ++ ++ return pcap_task_delete_one(param->pcap_id, ds); ++} ++ ++void ++pcap_cmd_stop(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct pcap_stop_param param; ++ ++ HINIC3_LOG(INFO, AGENT, "going to stop capture tasks"); ++ param.port_no = 0; ++ param.pcap_id = 0; ++ ret = pcap_stop_param_parse(argc, argv, ¶m, &ds); ++ if (ret != 0) ++ goto fail; ++ ++ ret = pcap_task_delete(¶m, &ds); ++ if (ret != 0) ++ goto fail; ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++ ++fail: ++ HINIC3_LOG(INFO, AGENT, "stop capture tasks fail."); ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = -1; ++ return; ++} ++ ++static int ++pcap_task_start_prepare(int argc, const char *argv[], struct pcap_start_param *param, struct ds *ds, struct ds *save_param) ++{ ++ int ret; ++ char *port_name = (char *)argv[0]; ++ ++ ret = pcap_key_parse(¶m->pcap_key, argc, argv, ds, save_param); ++ if (ret != 0) ++ return -1; ++ ++ if (pcap_check_file_used_no_lock(¶m->pcap_key)) { ++ hinic3_ds_put_format(ds, "%sFilename has beed used by other task.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ ret = pcap_port_info_get_by_name(port_name, ¶m->port_info, ds); ++ if (ret != 0) ++ return -1; ++ ++ if (!param->port_info.support_cap) { ++ hinic3_ds_put_format(ds, "%sPort %s don't support capture.\n", HINIC3_UI_LEADING_SIGN_FAILURE, port_name); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void ++pcap_cmd_start(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ uint32_t pcap_id; ++ char *port_name = (char *)argv[0]; ++ struct pcap_start_param param; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct ds save_param = DS_EMPTY_INITIALIZER; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ HINIC3_LOG(INFO, AGENT, "going to start a capture task"); ++ if (pcap_get_cap_switch() == 0) { ++ hinic3_ds_put_format(&ds, "%sPlease enable capture first, use command hwoff/enable-capture-probe.\n", ++ HINIC3_UI_LEADING_SIGN_WARNING); ++ goto fail; ++ } ++ ++ memset(¶m, 0, sizeof(param)); ++ ret = pcap_task_start_prepare(argc, argv, ¶m, &ds, &save_param); ++ if (ret != 0) ++ goto fail; ++ ++ if (task_mgr->task_cnt >= PCAP_MAX_CAP_TASK) { ++ hinic3_ds_put_format(&ds, "%sCapture tasks reach %u now, can't start anymore.\n", HINIC3_UI_LEADING_SIGN_WARNING, ++ PCAP_MAX_CAP_TASK); ++ goto fail; ++ } ++ ++ ret = pcap_task_add(¶m.port_info, ¶m.pcap_key, &pcap_id, &save_param); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, "%sInternal error, please check log.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ goto fail; ++ } ++ ++ HINIC3_LOG(INFO, AGENT, "start a new capture task, pcap_id is %u.", pcap_id); ++ hinic3_ds_put_format(&ds, "%sPort %s start packet capture, pcap id %u.\n", HINIC3_UI_LEADING_SIGN_INFO, port_name, ++ pcap_id); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ hinic3_ds_destroy(&save_param); ++ *(int *)aux = 0; ++ return; ++ ++fail: ++ HINIC3_LOG(INFO, AGENT, "start a capture task fail."); ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ hinic3_ds_destroy(&save_param); ++ *(int *)aux = -1; ++ return; ++} ++ ++void ++pcap_cmd_exec(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ size_t i; ++ int work_argc; ++ const char **work_argv = argv + 1; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ const char *sub_cmd_name = NULL; ++ struct pcap_cmd_t *dst_sub_cmd = NULL; ++ struct pcap_cmd_t *tmp_sub_cmd = NULL; ++ ++ work_argc = argc - 1; ++ sub_cmd_name = work_argv[0]; ++ for (i = 0; i < ARRAY_SIZE(g_cap_sub_commands); i++) { ++ tmp_sub_cmd = &g_cap_sub_commands[i]; ++ if (strcmp(tmp_sub_cmd->cmd, sub_cmd_name) == 0) { ++ dst_sub_cmd = tmp_sub_cmd; ++ break; ++ } ++ } ++ ++ if (!dst_sub_cmd) { ++ hinic3_ds_put_format(&ds, "%s%s, please input -h or --help to get help info.\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_ERROR_UNRECOGNIZED_COMMAND); ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = -1; ++ hinic3_ds_destroy(&ds); ++ return; ++ } ++ ++ work_argc -= 1; ++ work_argv += 1; ++ if ((work_argc < dst_sub_cmd->min_args) || (work_argc > dst_sub_cmd->max_args)) { ++ hinic3_ds_put_format(&ds, "%s%s, please input -h or --help to get help info.\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_ERROR_INCOMPLETE_COMMAND); ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = -1; ++ hinic3_ds_destroy(&ds); ++ return; ++ } ++ ++ dst_sub_cmd->cb(conn, work_argc, work_argv, aux); ++} ++ ++void ++pcap_task_show_reply_format(struct pcap_task_t *task, struct ds *ds) ++{ ++ char *tmp = NULL; ++ struct pcap_stats_t *stats = &task->stats; ++ ++ tmp = task->pcap_port.name; ++ hinic3_ds_put_format(ds, " port: %s\n", tmp); ++ hinic3_ds_put_format(ds, " pcap-id: %u\n", task->pcap_id); ++ hinic3_ds_put_format(ds, " captured: %llu\n", (unsigned long long)stats->wr_cnt); ++ hinic3_ds_put_format(ds, " enqueue-fail: %llu\n", (unsigned long long)stats->en_ring_fail_cnt); ++ hinic3_ds_put_format(ds, " drop: %llu\n", (unsigned long long)stats->soft_drop_cnt); ++ tmp = task->wr_fail_flag ? "true" : "false"; ++ hinic3_ds_put_format(ds, " write-success: %s\n", tmp); ++ hinic3_ds_put_format(ds, " parameters: %s\n", task->parameter); ++} ++ ++void ++pcap_all_tasks_show(struct ds *ds) ++{ ++ int i; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ /* called by maintain thread, task list will not changed, no need to lock task_mgr */ ++ if (task_mgr->task_cnt == 0) ++ return; ++ ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ if (i != 0) ++ hinic3_ds_put_cstr(ds, "\n"); ++ pcap_task_spin_lock(cap_task); ++ pcap_task_show_reply_format(cap_task, ds); ++ pcap_task_spin_unlock(cap_task); ++ } ++ ++ return; ++} ++ ++void ++pcap_cmd_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ uint32_t index; ++ struct pcap_show_param param; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct pcap_task_t *cap_task = NULL; ++ ++ memset(¶m, 0, sizeof(param)); ++ ret = pcap_show_param_parse(argc, argv, ¶m, &ds); ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = -1; ++ return; ++ } ++ ++ if (!param.is_all) { ++ cap_task = pcap_task_find_no_lock(param.pcap_id, &index); ++ if (!cap_task) { ++ hinic3_ds_put_format(&ds, "%sCapture task of pcap_id=%u not found.\n", HINIC3_UI_LEADING_SIGN_INFO, ++ param.pcap_id); ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = -1; ++ return; ++ } ++ ++ pcap_task_spin_lock(cap_task); ++ pcap_task_show_reply_format(cap_task, &ds); ++ pcap_task_spin_unlock(cap_task); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++ } ++ ++ pcap_all_tasks_show(&ds); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} ++ ++void ++pcap_cmd_help(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ pcap_cmd_usage_print(&ds); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++} ++ ++void ++pcap_unix_cmd_register(void) ++{ ++ struct pcap_cmd_t *p_cmd = &g_cap_main_command; ++ ++ hinic3_command_register(p_cmd->cmd, p_cmd->usage, p_cmd->min_args, p_cmd->max_args, p_cmd->cb, NULL); ++ hinic3_command_register("hwoff/enable-capture-probe", "", 0, 0, pcap_cmd_enable_capture, NULL); ++ hinic3_command_register("hwoff/disable-capture-probe", "", 0, 0, pcap_cmd_disable_capture, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.h +new file mode 100644 +index 0000000..966e6de +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CAPTURE_COMMAND_H ++#define HINIC3_CAPTURE_COMMAND_H ++void pcap_cmd_exec(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED); ++void pcap_cmd_help(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED); ++void pcap_cmd_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED); ++void pcap_cmd_start(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED); ++void pcap_cmd_stop(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED); ++void pcap_unix_cmd_register(void); ++#endif /* HINIC3_CAPTURE_COMMAND_H */ +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c +new file mode 100644 +index 0000000..328ce65 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c +@@ -0,0 +1,140 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_mbuf.h" ++#include "hinic3_log.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_capture_filter.h" ++#include "hinic3_capture_save.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#include "hinic3_capture_core.h" ++#endif ++ ++static inline void ++pcap_hinic3_pkt_summary_init(struct pcap_pkt_summary *buf, struct rte_mbuf *pkt) ++{ ++ struct hinic3_pcap_probe_user_data *usrdata = NULL; ++ ++ buf->data = rte_pktmbuf_get_data(pkt); ++ buf->len = rte_pktmbuf_get_data_len(pkt); ++ ++ usrdata = (struct hinic3_pcap_probe_user_data *)rte_mbuf_get_udata64_ptr(pkt); ++ buf->pkt_len = (usrdata->org_pkt_len >= buf->len) ? usrdata->org_pkt_len : buf->len; ++ buf->vlan_id = (rte_mbuf_get_ol_flags(pkt) & RTE_MBUF_F_RX_VLAN) ? ((rte_mbuf_get_vlan_tci(pkt)) & ++ VLAN_VID_MASK) : 0; ++} ++ ++static void ++pcap_hinic3_pkts_process(struct pcap_task_t *cap_task, struct pcap_task_mirror_t *task_mirror, ++ struct rte_mbuf **rx_pkts, uint32_t cnt) ++{ ++ uint32_t i; ++ int save_cnt; ++ uint32_t fail_cnt; ++ struct pcap_save_stats_t save_stats; ++ struct pcap_pkt_summary buf[PKT_MAX_BURST]; ++ struct pcap_pkt_summary *save_list[PKT_MAX_BURST] = {NULL}; ++ ++ save_cnt = 0; ++ fail_cnt = 0; ++ memset(buf, 0, sizeof(buf)); ++ for (i = 0; i < cnt; i++) { ++ pcap_hinic3_pkt_summary_init(&buf[i], rx_pkts[i]); ++ pcap_pkt_parse(&buf[i]); ++ if (buf[i].ctx.parse_result) { ++ save_list[save_cnt] = &buf[i]; ++ save_cnt++; ++ } else ++ fail_cnt++; ++ } ++ ++ memset(&save_stats, 0, sizeof(save_stats)); ++ save_stats.parse_fail_cnt = fail_cnt; ++ if (save_cnt > 0) ++ pcap_pkt_save(cap_task, task_mirror->remain_count, save_list, save_cnt, &save_stats); ++ pcap_task_stats_update(cap_task, &save_stats); ++ ++ return; ++} ++ ++void ++pcap_comm_task_exec(struct pcap_task_t *cap_task, struct pcap_pkt_summary *buf, uint32_t buf_cnt) ++{ ++ uint32_t i; ++ uint32_t fail_cnt; ++ uint32_t save_cnt; ++ bool flag = false; ++ struct pcap_task_mirror_t task_mirror; ++ struct pcap_save_stats_t save_stats; ++ struct pcap_pkt_summary *tmp_buf = NULL; ++ struct pcap_pkt_summary *save_list[PKT_MAX_BURST] = {NULL}; ++ ++ pcap_task_mirror_get(cap_task, &task_mirror); ++ if (cap_task->stop_flag || cap_task->remain_count == 0 || cap_task->wr_fail_flag) ++ return; ++ ++ save_cnt = 0; ++ fail_cnt = 0; ++ for (i = 0; i < buf_cnt; i++) { ++ tmp_buf = &buf[i]; ++ if (!tmp_buf->ctx.parse_result) { ++ fail_cnt++; ++ continue; ++ } ++ ++ flag = pcap_pkt_filter(tmp_buf, &cap_task->key); ++ if (!flag) ++ continue; ++ ++ save_list[save_cnt] = tmp_buf; ++ save_cnt++; ++ } ++ ++ memset(&save_stats, 0, sizeof(save_stats)); ++ save_stats.parse_fail_cnt = fail_cnt; ++ if (save_cnt > 0) { ++ pcap_pkt_save(cap_task, task_mirror.remain_count, save_list, save_cnt, &save_stats); ++ } ++ pcap_task_stats_update(cap_task, &save_stats); ++ return; ++} ++ ++void ++pcap_hinic3_task_exec(struct pcap_task_t *cap_task) ++{ ++ uint32_t pkt_cnt; ++ struct pcap_task_mirror_t task_mirror; ++ struct rte_mbuf *rx_pkts[PKT_MAX_BURST] = { NULL }; ++ struct hinic3_pcap_probe_rule_q_map *queue_info = &cap_task->driver.queue_info; ++ ++ /* maybe more than one pmds will exec a task, so need to lock */ ++ pcap_task_spin_lock(cap_task); ++ ++ if (cap_task->stop_flag || cap_task->remain_count == 0 || cap_task->wr_fail_flag) { ++ pcap_task_spin_unlock(cap_task); ++ return; ++ } ++ ++ task_mirror.stop_flag = cap_task->stop_flag; ++ task_mirror.wr_fail_flag = cap_task->wr_fail_flag; ++ task_mirror.remain_count = cap_task->remain_count; ++ ++ pkt_cnt = hinic3_global_rte_eth_rx_burst(queue_info->hinic3_dpdk_port_id, queue_info->queue_id, ++ rx_pkts, PKT_MAX_BURST); ++ pcap_task_spin_unlock(cap_task); ++ if (pkt_cnt == 0) ++ return; ++ ++ pcap_hinic3_pkts_process(cap_task, &task_mirror, rx_pkts, pkt_cnt); ++ rte_pktmbuf_free_bulk(rx_pkts, pkt_cnt); ++ return; ++} +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.h +new file mode 100644 +index 0000000..5bfa67e +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CAPTURE_CORE_H ++#define HINIC3_CAPTURE_CORE_H ++ ++#include "hinic3_capture_utils.h" ++#include "hinic3_capture_filter.h" ++ ++struct pcap_pkt_dump_data { ++ struct pcap_file_record_hdr record_hdr; ++ char data[PCAP_DUMP_SIZE]; ++}; ++ ++void pcap_comm_task_exec(struct pcap_task_t *cap_task, struct pcap_pkt_summary *buf, uint32_t buf_cnt); ++void pcap_hinic3_task_exec(struct pcap_task_t *cap_task); ++ ++#endif /* HINIC3_CAPTURE_CORE_H */ +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +new file mode 100644 +index 0000000..61c36fa +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +@@ -0,0 +1,1188 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include "rte_ip.h" ++ ++#include "hinic3_unaligned.h" ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_ds.h" ++#include "hinic3_file_util.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_string_format.h" ++#include "hinic3_eth_packets.h" ++#include "hinic3_capture_filter.h" ++ ++#define PCAP_OFFSET_2 2 ++#define PCAP_OFFSET_3 3 ++#define PCAP_BYTE_LEN 8 ++#define PCAP_BIT_MASK 7 ++ ++static int pcap_key_count_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++static int pcap_key_dir_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++static int pcap_key_file_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++static int pcap_key_host_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++ ++static struct pcap_sub_key_parser g_pcap_sub_key_parser[] = { ++ {"-c", sizeof("-c"), pcap_key_count_parse}, ++ {"-w", sizeof("-w"), pcap_key_file_parse}, ++ {"-P", sizeof("-P"), pcap_key_dir_parse}, ++ {"-sip", sizeof("-sip"), hinic3_key_sip_parse}, ++ {"-dip", sizeof("-dip"), hinic3_key_dip_parse}, ++ {"-host", sizeof("-host"), pcap_key_host_parse}, ++ {"-smac", sizeof("-smac"), hinic3_key_smac_parse}, ++ {"-dmac", sizeof("-dmac"), hinic3_key_dmac_parse}, ++ {"-eth_type", sizeof("-eth_type"), hinic3_key_eth_type_parse}, ++ {"-ip_proto", sizeof("-ip_proto"), hinic3_key_ip_proto_parse}, ++ {"-sport", sizeof("-sport"), hinic3_key_sport_parse}, ++ {"-dport", sizeof("-dport"), hinic3_key_dport_parse}, ++ {"-vlan", sizeof("-vlan"), hinic3_key_vlan_parse}, ++ {"-vxlan_vni", sizeof("-vxlan_vni"), hinic3_key_vni_parse}, ++}; ++ ++static inline uint32_t ++pcap_masklen_to_netmask(uint8_t masklen) ++{ ++ return 0xffffffff << (PCAP_OFFSET_32 - masklen); ++} ++ ++static inline void ++pcap_move_pkt_itr(struct pcap_pkt_parse_ctx *ctx, uint32_t len) ++{ ++ ctx->pkt_itr += len; ++} ++ ++static inline bool ++pcap_check_pkt_boundary(const uint8_t *p_start, uint32_t size, const uint8_t *p_end) ++{ ++ if ((p_start + size) <= p_end) ++ return true; ++ else ++ return false; ++} ++ ++static inline bool ++pcap_is_pkt_ip(uint16_t eth_type) ++{ ++ if (eth_type == htons(ETH_TYPE_IP)) ++ return true; ++ ++ if (eth_type == htons(ETH_TYPE_IPV6)) ++ return true; ++ ++ return false; ++} ++ ++static int ++pcap_ip_parse(char *value, struct pcap_ip_t *ip, uint32_t *ip_type) ++{ ++ if (inet_addr(value) != INADDR_NONE) { ++ ip->ip4 = inet_addr(value); ++ *ip_type = PCAP_IP_ADDR_V4; ++ return 0; ++ } ++ if (inet_pton(AF_INET6, value, &ip->ip6) == 1) { ++ *ip_type = PCAP_IP_ADDR_V6; ++ return 0; ++ } ++ return -1; ++} ++ ++static int ++pcap_mask_parse(const char *mask_str, uint8_t *mask_len, uint32_t ip_type) ++{ ++ uint32_t len; ++ char *endPtr = NULL; ++ ++ if (!mask_str) { ++ if (ip_type == PCAP_IP_ADDR_V4) ++ *mask_len = PCAP_IPV4_MAX_MASK_LEN; ++ else ++ *mask_len = PCAP_IPV6_MAX_MASK_LEN; ++ ++ return 0; ++ } ++ ++ len = strtoul(mask_str, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') ++ return -1; ++ ++ if (ip_type == PCAP_IP_ADDR_V4) { ++ if (len > 0 && len <= PCAP_IPV4_MAX_MASK_LEN) { ++ *mask_len = (uint8_t)len; ++ return 0; ++ } ++ return -1; ++ } ++ if (len > 0 && len <= PCAP_IPV6_MAX_MASK_LEN) { ++ *mask_len = (uint8_t)len; ++ return 0; ++ } ++ return -1; ++} ++ ++int ++pcap_ip_mask_parse(char *value, struct pcap_ip_t *ip, uint8_t *mask_len, uint32_t *p_ip_type) ++{ ++ int ret; ++ uint32_t ip_type; ++ char *copy = NULL; ++ char *ip_str = NULL; ++ char *mask_str = NULL; ++ ++ copy = hinic3_xstrdup(value, HINIC3_CAPTURE); ++ if (copy == NULL) ++ return -1; ++ ++ ip_str = copy; ++ mask_str = strchr(copy, '/'); ++ if (mask_str != NULL) { ++ *mask_str = '\0'; ++ mask_str++; ++ } ++ ++ ret = pcap_ip_parse(ip_str, ip, &ip_type); ++ if (ret != 0) { ++ hinic3_free(copy); ++ return -1; ++ } ++ ++ ret = pcap_mask_parse(mask_str, mask_len, ip_type); ++ if (ret != 0) { ++ hinic3_free(copy); ++ return -1; ++ } ++ ++ if (*p_ip_type == 0) ++ *p_ip_type = ip_type; ++ else if (ip_type != *p_ip_type) { ++ HINIC3_LOG(ERR, AGENT, "ip should all be ipv4 or ipv6"); ++ hinic3_free(copy); ++ return -1; ++ } ++ ++ hinic3_free(copy); ++ return 0; ++} ++ ++int ++parse_l4_proto(const char *value, uint8_t *output) ++{ ++ if (strcmp(value, "TCP") == 0) ++ *output = IPPROTO_TCP; ++ else if (strcmp(value, "UDP") == 0) ++ *output = IPPROTO_UDP; ++ else if (strcmp(value, "ICMP") == 0) ++ *output = IPPROTO_ICMP; ++ else if (strcmp(value, "SCTP") == 0) ++ *output = IPPROTO_SCTP; ++ else if (strcmp(value, "ICMPV6") == 0) ++ *output = IPPROTO_ICMPV6; ++ else ++ return -1; ++ ++ return 0; ++} ++ ++static int ++pcap_key_count_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ char *endPtr = NULL; ++ uint64_t count; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_COUNT) != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Duplicate parameter \"%s\"!\n", key_name); ++ return -1; ++ } ++ ++ count = strtoull(value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') ++ return -1; ++ ++ if (count <= 0 || count > PCAP_MAX_PKT_CNT) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Value of parameter \"%s\" is invalid!\n", key_name); ++ return -1; ++ } ++ ++ cap_key->count_total = count; ++ cap_key->flags |= PCAP_FLAG_KEY_COUNT; ++ return 0; ++} ++ ++static int ++pcap_key_file_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ char *result = NULL; ++ char *resolve_path = NULL; ++ char absolute_path[PATH_MAX]; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_FILE) != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Duplicate parameter \"%s\"!\n", key_name); ++ return -1; ++ } ++ ++ if (strlen(value) >= PCAP_MAX_FILE_NAME) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FILE_PATH_LENGTH_TIPS_STRING); ++ return -1; ++ } ++ ++ ret = hinic3_check_output_file_directory(value, absolute_path, sizeof(absolute_path), ds); ++ if (ret != 0) ++ return -1; ++ ++ resolve_path = (char*)hinic3_calloc(1, PATH_MAX + 1, HINIC3_CAPTURE); ++ if (!resolve_path) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FILE_PATH_MALLOC_TIPS_STRING); ++ return -1; ++ } ++ ++ result = realpath(absolute_path, resolve_path); ++ (void)result; ++ ++ if ((strlen(resolve_path) == 0) || (strlen(resolve_path) >= PCAP_MAX_FILE_NAME)) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_PATH_TIPS_STRING, HINIC3_UI_LEADING_SIGN_ERROR, resolve_path); ++ hinic3_free(resolve_path); ++ return -1; ++ } ++ ++ /* 不允许软链接文件,realpath处理前后文件名一致 */ ++ if (strcmp(resolve_path, absolute_path) != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FILE_NOT_ABSOLUTE_PATH_STRING); ++ hinic3_free(resolve_path); ++ return -1; ++ } ++ ++ strcpy(cap_key->filename, resolve_path); ++ if (cap_key->filename == NULL) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Internal fail!\n"); ++ hinic3_free(resolve_path); ++ return -1; ++ } ++ ++ hinic3_free(resolve_path); ++ cap_key->flags |= PCAP_FLAG_KEY_FILE; ++ return 0; ++} ++ ++static int ++pcap_key_dir_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ if ((cap_key->flags & PCAP_FLAG_KEY_DIRECTION) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if (strcmp("in", value) == 0) ++ cap_key->direction = PCAP_DIR_RX; ++ else if (strcmp("out", value) == 0) ++ cap_key->direction = PCAP_DIR_TX; ++ else if (strcmp("inout", value) == 0) ++ cap_key->direction = PCAP_DIR_TX | PCAP_DIR_RX; ++ else { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->flags |= PCAP_FLAG_KEY_DIRECTION; ++ return 0; ++} ++ ++static int ++pcap_key_host_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ int ret; ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_HOST) != 0) { ++ hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_SIP) != 0) { ++ hinic3_ds_put_format(ds, "%sAlready config \"-sip\", cann't config \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ key_name); ++ return -1; ++ } ++ ++ if ((cap_key->flags & PCAP_FLAG_KEY_DIP) != 0) { ++ hinic3_ds_put_format(ds, "%sAlready config \"-dip\", cann't config \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ key_name); ++ return -1; ++ } ++ ++ ret = pcap_ip_mask_parse(value, &cap_key->host_ip, &cap_key->host_masklen, &cap_key->ip_type); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ cap_key->flags |= PCAP_FLAG_KEY_HOST; ++ return 0; ++} ++ ++int ++pcap_sub_key_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++{ ++ size_t i; ++ int ret; ++ struct pcap_sub_key_parser *item = NULL; ++ pcap_sub_key_parse_func func = NULL; ++ ++ for (i = 0; i < ARRAY_SIZE(g_pcap_sub_key_parser); i++) { ++ item = &g_pcap_sub_key_parser[i]; ++ if (strcmp(key_name, item->key_name) == 0) { ++ func = item->func; ++ break; ++ } ++ } ++ ++ if (!func) { ++ hinic3_ds_put_format(ds, "%sIllegal parameter=%s!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ ret = func(cap_key, key_name, value, ds); ++ return ret; ++} ++ ++int ++pcap_key_parse(struct pcap_key_t *cap_key, int argc, const char *argv[], struct ds *ds, struct ds *save_param) ++{ ++ int i; ++ int ret; ++ int work_argc = argc; ++ const char **work_argv = argv; ++ ++ work_argc -= 1; ++ work_argv += 1; ++ ++ memset(cap_key, 0, sizeof(struct pcap_key_t)); ++ cap_key->direction = PCAP_DIR_RX | PCAP_DIR_TX; ++ cap_key->count_total = PCAP_DEF_PKT_CNT; ++ ++ i = 0; ++ while (i < work_argc) { ++ /* -xxx模式的参数 */ ++ if (strcmp("-vxlan_inner", work_argv[i]) == 0) { ++ cap_key->vxlan_inner = true; ++ hinic3_ds_put_format(save_param, " %s", (char *)work_argv[i]); ++ i++; ++ continue; ++ } ++ ++ if (strcmp("-thread", work_argv[i]) == 0) { ++ cap_key->write_way = WRITE_BY_SEP_THREAD; ++ hinic3_ds_put_format(save_param, " %s", (char *)work_argv[i]); ++ i++; ++ continue; ++ } ++ ++ /* -x xxx模式的参数 */ ++ if (i + 1 >= work_argc) { ++ hinic3_ds_put_format(ds, "%sWrong command format.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ ++ ret = pcap_sub_key_parse(cap_key, (char *)work_argv[i], (char *)work_argv[i + 1], ds); ++ if (ret != 0) ++ return -1; ++ ++ if (strcmp(work_argv[i], "-w") == 0) ++ hinic3_ds_put_format(save_param, " %s %s", (char *)work_argv[i], cap_key->filename); ++ else ++ hinic3_ds_put_format(save_param, " %s %s", (char *)work_argv[i], (char *)work_argv[i + 1]); ++ i += PCAP_DOUBLE; ++ } ++ ++ /* check whether neccesary parameters exist */ ++ if ((cap_key->flags & PCAP_FLAG_KEY_FILE) == 0) { ++ hinic3_ds_put_format(ds, "%sShould provide parameter \"-w filename\".\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++int ++pcap_show_param_parse(int argc, const char *argv[], struct pcap_show_param *param, struct ds *ds) ++{ ++ if (strcmp("-pcap_id", argv[0]) == 0 && argc == PCAP_CMD_SHOW_MAX_PARAM) { ++ char *endPtr = NULL; ++ param->pcap_id = strtoul(argv[PCAP_CMD_STOP_MAX_PARAM - 1], &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') ++ return -1; ++ if (param->pcap_id == 0) { ++ hinic3_ds_put_format(ds, "%sValue of parameter \"-pcap_id\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ return 0; ++ } ++ ++ if (strcmp("all", argv[0]) == 0 && argc == PCAP_CMD_SHOW_MIN_PARAM) { ++ param->is_all = true; ++ return 0; ++ } ++ ++ hinic3_ds_put_format(ds, "%sInvalid command format, please type -h or --help for help.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++} ++ ++static inline bool ++pcap_have_any_filter(const struct pcap_key_t *key) ++{ ++ if ((key->flags & PCAP_FILTER_ALL_MASK) != 0) ++ return true; ++ if (key->vxlan_inner) ++ return true; ++ return false; ++} ++ ++static void ++pcap_convert_key_l2(struct pcap_key_t *key, struct hinic3_pcap_probe_filter_t *filter) ++{ ++ if ((key->flags & PCAP_FLAG_KEY_SMAC) != 0) { ++ filter->cap_mask.smac_en = 1; ++ memcpy(filter->rule_cfg.smac, key->smac, RTE_ETHER_ADDR_LEN); ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_DMAC) != 0) { ++ filter->cap_mask.dmac_en = 1; ++ memcpy(filter->rule_cfg.dmac, key->dmac, RTE_ETHER_ADDR_LEN); ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_VLAN) != 0) { ++ filter->cap_mask.vlan_en = 1; ++ filter->rule_cfg.vlan_id = key->vlan_id; ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_ETH_TYPE) != 0) { ++ filter->cap_mask.eth_type_en = 1; ++ filter->rule_cfg.eth_type = key->eth_type; ++ } ++ ++ return; ++} ++ ++static void ++pcap_convert_key_l3(struct pcap_key_t *key, struct hinic3_pcap_probe_filter_t *filter) ++{ ++ if ((key->flags & PCAP_FLAG_KEY_SIP) != 0) { ++ filter->cap_mask.sip_en = 1; ++ if (key->ip_type == PCAP_IP_ADDR_V4) { ++ filter->rule_cfg.sip_mask = pcap_masklen_to_netmask(key->sip_masklen); ++ filter->rule_cfg.sip = key->sip.ip4 & htonl(filter->rule_cfg.sip_mask); ++ } else { ++ filter->cap_mask.ipv6_en = 1; ++ filter->rule_cfg.sip_mask = key->sip_masklen; ++ memcpy(&(filter->rule_ipv6_cfg.sip6), &(key->sip.ip6), sizeof(struct in6_addr)); ++ } ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_DIP) != 0) { ++ filter->cap_mask.dip_en = 1; ++ if (key->ip_type == PCAP_IP_ADDR_V4) { ++ filter->rule_cfg.dip_mask = pcap_masklen_to_netmask(key->dip_masklen); ++ filter->rule_cfg.dip = key->dip.ip4 & htonl(filter->rule_cfg.dip_mask); ++ } else { ++ filter->cap_mask.ipv6_en = 1; ++ filter->rule_cfg.dip_mask = key->dip_masklen; ++ memcpy(&(filter->rule_ipv6_cfg.dip6), &(key->dip.ip6), sizeof(struct in6_addr)); ++ } ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_HOST) != 0) { ++ filter->cap_mask.host = 1; ++ if (key->ip_type == PCAP_IP_ADDR_V4) { ++ filter->rule_cfg.host_mask = pcap_masklen_to_netmask(key->host_masklen); ++ filter->rule_cfg.host_ip = key->host_ip.ip4 & htonl(filter->rule_cfg.host_mask); ++ } else { ++ filter->cap_mask.ipv6_en = 1; ++ filter->rule_cfg.host_mask = key->host_masklen; ++ memcpy(&(filter->rule_ipv6_cfg.hip6), &(key->host_ip.ip6), sizeof(struct in6_addr)); ++ } ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_IP_PROTO) != 0) { ++ filter->cap_mask.proto_en = 1; ++ filter->rule_cfg.ip_proto = key->ip_proto; ++ } ++ ++ return; ++} ++ ++static void ++pcap_convert_key_l4(struct pcap_key_t *key, struct hinic3_pcap_probe_filter_t *filter) ++{ ++ if ((key->flags & PCAP_FLAG_KEY_SPORT) != 0) { ++ filter->cap_mask.sport_en = 1; ++ filter->rule_cfg.sport = key->sport; ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_DPORT) != 0) { ++ filter->cap_mask.dport_en = 1; ++ filter->rule_cfg.dport = key->dport; ++ } ++ ++ if ((key->flags & PCAP_FLAG_KEY_VXLAN_VNI) != 0) { ++ filter->cap_mask.vni_en = 1; ++ filter->rule_cfg.vni = key->vxlan_vni; ++ } ++ ++ return; ++} ++ ++void ++pcap_convert_key_to_driver_filter(struct pcap_task_t *task) ++{ ++ struct pcap_key_t *key = &task->key; ++ struct hinic3_pcap_probe_filter_t *filter = &task->driver.driver_filter; ++ ++ /* count */ ++ filter->cap_mask.cnt_en = 1; ++ filter->rule_cfg.pcap_cfg_cnt_h = key->count_total >> PCAP_OFFSET_32; ++ filter->rule_cfg.pcap_cfg_cnt_l = key->count_total & (0xFFFFFFFF); ++ ++ /* direction */ ++ if ((key->direction & PCAP_DIR_RX) != 0) ++ filter->cap_mask.direct_rx = 1; ++ if ((key->direction & PCAP_DIR_TX) != 0) ++ filter->cap_mask.direct_tx = 1; ++ ++ if (!pcap_have_any_filter(key) && (!key->vxlan_inner)) { ++ filter->cap_mask.all_pass = 1; ++ return; ++ } ++ ++ pcap_convert_key_l2(key, filter); ++ pcap_convert_key_l3(key, filter); ++ pcap_convert_key_l4(key, filter); ++ if (key->vxlan_inner) ++ filter->cap_mask.vxlan_inner = 1; ++ ++ return; ++} ++ ++static inline void ++pcap_pkt_parse_not_ip(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr) ++{ ++ struct pcap_pkt_l2 *l2 = &sub_hdr->l2; ++ ++ if ((l2->eth_type == htons(ETH_TYPE_ARP)) || (l2->eth_type == htons(ETH_TYPE_RARP))) ++ sub_hdr->save_len += HINIC3_ARP_ETH_HEADER_LEN; ++} ++ ++static inline bool ++pcap_is_ipv6_ext_hdr(uint8_t nexthdr) ++{ ++ return (nexthdr == HINIC3_NEXTHDR_HOP) || ++ (nexthdr == HINIC3_NEXTHDR_ROUTING) || ++ (nexthdr == HINIC3_NEXTHDR_FRAGMENT) || ++ (nexthdr == HINIC3_NEXTHDR_AUTH) || ++ (nexthdr == HINIC3_NEXTHDR_NONE) || ++ (nexthdr == HINIC3_NEXTHDR_DEST); ++} ++ ++static int ++pcap_parse_ipv6_ext_hdr(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr, ++ uint8_t nexthdr_para, bool *has_l4) ++{ ++ uint8_t hdr_len; ++ uint16_t hdr_cnt = 0; ++ uint8_t xdr_auth_offset = 2; ++ uint8_t xdr_bit_move = 3; ++ struct hinic3_ipv6_opt_hdr *ext_hdr = NULL; ++ struct pcap_pkt_l3 *l3 = &sub_hdr->l3; ++ uint8_t nexthdr = nexthdr_para; ++ ++ while (pcap_is_ipv6_ext_hdr(nexthdr) && hdr_cnt < HINIC3_NEXTHDR_MAX) { ++ if (nexthdr == HINIC3_NEXTHDR_NONE || nexthdr == HINIC3_NEXTHDR_AUTH) ++ break; ++ ++ ext_hdr = (struct hinic3_ipv6_opt_hdr *)ctx->pkt_itr; ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, sizeof(struct hinic3_ipv6_opt_hdr), ctx->pkt_end)) ++ return -1; ++ ++ if (nexthdr == HINIC3_NEXTHDR_FRAGMENT) { ++ hdr_len = PCAP_IPV6_FRAG_HDR_SIZE; ++ *has_l4 = false; ++ } else if (nexthdr == HINIC3_NEXTHDR_AUTH) ++ hdr_len = ((ext_hdr->hdrlen + xdr_auth_offset) << xdr_auth_offset); ++ else ++ hdr_len = ((ext_hdr->hdrlen + 1) << xdr_bit_move); ++ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, hdr_len, ctx->pkt_end)) ++ return -1; ++ ++ hdr_cnt++; ++ nexthdr = ext_hdr->nexthdr; ++ sub_hdr->save_len += hdr_len; ++ pcap_move_pkt_itr(ctx, hdr_len); ++ } ++ ++ l3->ip_proto = nexthdr; ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_IP_PROTO; ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_l2(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr) ++{ ++ uint16_t eth_type; ++ struct eth_header *eth = NULL; ++ struct vlan_header *vh = NULL; ++ struct pcap_pkt_l2 *l2 = &sub_hdr->l2; ++ ++ eth = (struct eth_header *)ctx->pkt_itr; ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, ETH_HEADER_LEN, ctx->pkt_end)) ++ return -1; ++ ++ eth_type = eth->eth_type; ++ memcpy(l2->dmac, ð->eth_dst, RTE_ETHER_ADDR_LEN); ++ memcpy(l2->smac, ð->eth_src, RTE_ETHER_ADDR_LEN); ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_SMAC | PCAP_FLAG_KEY_DMAC; ++ sub_hdr->save_len += ETH_HEADER_LEN; ++ pcap_move_pkt_itr(ctx, ETH_HEADER_LEN); ++ if (!eth_type_vlan(eth_type)) { ++ l2->eth_type = eth_type; ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_ETH_TYPE; ++ ++ return 0; ++ } ++ ++ /* vlan packet */ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, VLAN_HEADER_LEN, ctx->pkt_end)) { ++ HINIC3_LOG(ERR, AGENT, "length of packet is too small when extract vlan header"); ++ return -1; ++ } ++ ++ vh = (struct vlan_header *)ctx->pkt_itr; ++ l2->vlan_id = ntohs(vh->vlan_tci) & 0xfff; ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_VLAN; ++ eth_type = vh->vlan_next_type; ++ sub_hdr->save_len += VLAN_HEADER_LEN; ++ pcap_move_pkt_itr(ctx, VLAN_HEADER_LEN); ++ if (!eth_type_vlan(eth_type)) { ++ l2->eth_type = eth_type; ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_ETH_TYPE; ++ return 0; ++ } ++ ++ /* extrace inner vlan */ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, sizeof(struct vlan_header), ctx->pkt_end)) { ++ HINIC3_LOG(ERR, AGENT, "length of packet is too small when extract inner vlan header"); ++ return -1; ++ } ++ ++ vh = vh + 1; ++ l2->inner_vlan_id = ntohs(vh->vlan_tci) & 0xfff; ++ l2->eth_type = vh->vlan_next_type; ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_ETH_TYPE; ++ sub_hdr->save_len += VLAN_HEADER_LEN; ++ pcap_move_pkt_itr(ctx, VLAN_HEADER_LEN); ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_l3_ipv4(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr, bool *has_l4) ++{ ++ uint32_t len; ++ struct ip_header *iph = (struct ip_header *)ctx->pkt_itr; ++ struct pcap_pkt_l3 *l3 = &sub_hdr->l3; ++ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, sizeof(struct ip_header), ctx->pkt_end)) { ++ HINIC3_LOG(ERR, AGENT, "length of packet is too small when extract ip header"); ++ return -1; ++ } ++ ++ l3->ip_type = PCAP_IP_ADDR_V4; ++ l3->ip_proto = iph->ip_proto; ++ l3->sip.ip4 = hinic3_get_16aligned_be32(&iph->ip_src); ++ l3->dip.ip4 = hinic3_get_16aligned_be32(&iph->ip_dst); ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_IP_PROTO | PCAP_FLAG_KEY_SIP | PCAP_FLAG_KEY_DIP | PCAP_FLAG_KEY_HOST; ++ ++ len = IP_IHL(iph->ip_ihl_ver) * RTE_IPV4_IHL_MULTIPLIER; ++ sub_hdr->save_len += len; ++ pcap_move_pkt_itr(ctx, len); ++ ++ if (IP_IS_FRAGMENT(iph->ip_frag_off)) { ++ if (iph->ip_frag_off == htons(IP_MORE_FRAGMENTS)) ++ *has_l4 = true; ++ else ++ *has_l4 = false; ++ } else ++ *has_l4 = true; ++ ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_l3_ipv6(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr, bool *has_l4) ++{ ++ int ret; ++ uint8_t nexthdr; ++ struct hinic3_ip6_header *ip6h = NULL; ++ struct pcap_pkt_l3 *l3 = &sub_hdr->l3; ++ ++ ip6h = (struct hinic3_ip6_header *)(ctx->pkt_itr); ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, HINIC3_IP6_HEADER_LEN, ctx->pkt_end)) { ++ HINIC3_LOG(ERR, AGENT, "length of packet is too small when extract ipv6 header"); ++ return -1; ++ } ++ ++ l3->ip_type = PCAP_IP_ADDR_V6; ++ nexthdr = ip6h->nexthdr; ++ memcpy(&l3->dip.ip6, &ip6h->daddr, sizeof(struct in6_addr)); ++ memcpy(&l3->sip.ip6, &ip6h->saddr, sizeof(struct in6_addr)); ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_SIP | PCAP_FLAG_KEY_DIP | PCAP_FLAG_KEY_HOST; ++ sub_hdr->save_len += HINIC3_IP6_HEADER_LEN; ++ pcap_move_pkt_itr(ctx, HINIC3_IP6_HEADER_LEN); ++ ++ /* extract all ipv6 extension headers */ ++ *has_l4 = true; ++ ret = pcap_parse_ipv6_ext_hdr(ctx, sub_hdr, nexthdr, has_l4); ++ if (ret != 0) ++ return -1; ++ ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_l3(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr, bool *has_l4) ++{ ++ if (sub_hdr->l2.eth_type == htons(ETH_TYPE_IP)) ++ return pcap_pkt_parse_l3_ipv4(ctx, sub_hdr, has_l4); ++ else ++ return pcap_pkt_parse_l3_ipv6(ctx, sub_hdr, has_l4); ++} ++ ++static int ++pcap_pkt_parse_l4_udp(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr) ++{ ++ struct pcap_pkt_l4 *l4 = &sub_hdr->l4; ++ struct udp_header *udp = (struct udp_header *)(ctx->pkt_itr); ++ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, sizeof(struct udp_header), ctx->pkt_end)) { ++ HINIC3_LOG(ERR, AGENT, "length of packet is too small when extract udp header"); ++ return -1; ++ } ++ ++ l4->sport = udp->udp_src; ++ l4->dport = udp->udp_dst; ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_SPORT | PCAP_FLAG_KEY_DPORT; ++ sub_hdr->save_len += UDP_HEADER_LEN; ++ pcap_move_pkt_itr(ctx, UDP_HEADER_LEN); ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_l4_tcp(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr) ++{ ++ uint32_t tcp_len; ++ struct pcap_pkt_l4 *l4 = &sub_hdr->l4; ++ struct tcp_header *tcp = (struct tcp_header *)(ctx->pkt_itr); ++ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, sizeof(struct tcp_header), ctx->pkt_end)) ++ return -1; ++ ++ l4->sport = tcp->tcp_src; ++ l4->dport = tcp->tcp_dst; ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_SPORT | PCAP_FLAG_KEY_DPORT; ++ ++ tcp_len = tcp_offset(tcp->tcp_ctl) << PCAP_OFFSET_2; ++ if (tcp_len < TCP_HEADER_LEN) ++ return -1; ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, tcp_len, ctx->pkt_end)) ++ return -1; ++ ++ sub_hdr->save_len += tcp_len; ++ pcap_move_pkt_itr(ctx, tcp_len); ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_l4_comm(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr) ++{ ++ struct pcap_pkt_l4 *l4 = &sub_hdr->l4; ++ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, PCAP_PORT_LEN * PCAP_DOUBLE, ctx->pkt_end)) ++ return -1; ++ ++ l4->sport = *((uint16_t *)ctx->pkt_itr); ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_SPORT; ++ pcap_move_pkt_itr(ctx, PCAP_PORT_LEN); ++ ++ l4->dport = *((uint16_t *)ctx->pkt_itr); ++ sub_hdr->valid_flags |= PCAP_FLAG_KEY_DPORT; ++ pcap_move_pkt_itr(ctx, PCAP_PORT_LEN); ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_l4(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr) ++{ ++ int len; ++ struct pcap_pkt_l3 *l3 = &sub_hdr->l3; ++ ++ if (l3->ip_proto == IPPROTO_TCP) ++ return pcap_pkt_parse_l4_tcp(ctx, sub_hdr); ++ ++ if ((l3->ip_proto == IPPROTO_UDP) || (l3->ip_proto == IPPROTO_UDPLITE)) ++ return pcap_pkt_parse_l4_udp(ctx, sub_hdr); ++ ++ if (l3->ip_proto == IPPROTO_ICMP) { ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, HINIC3_ICMP_HEADER_LEN, ctx->pkt_end)) ++ return -1; ++ sub_hdr->save_len += HINIC3_ICMP_HEADER_LEN; ++ return 0; ++ } ++ ++ if (l3->ip_proto == IPPROTO_ICMPV6) { ++ len = HINIC3_ICMP6_HEADER_LEN + HINIC3_ICMP6_MESSAGE_LEN; ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, len, ctx->pkt_end)) ++ return -1; ++ sub_hdr->save_len += (uint32_t)len; ++ return 0; ++ } ++ ++ if (l3->ip_proto == IPPROTO_IGMP) { ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, HINIC3_IGMP_HEADER_LEN, ctx->pkt_end)) ++ return -1; ++ sub_hdr->save_len += HINIC3_IGMP_HEADER_LEN; ++ return pcap_pkt_parse_l4_comm(ctx, sub_hdr); ++ } ++ ++ if (l3->ip_proto == IPPROTO_SCTP) { ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, HINIC3_SCTP_HEADER_LEN, ctx->pkt_end)) ++ return -1; ++ sub_hdr->save_len += HINIC3_SCTP_HEADER_LEN; ++ return pcap_pkt_parse_l4_comm(ctx, sub_hdr); ++ } ++ ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_vxlan(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_header *pkt_hdr, ++ struct pcap_pkt_sub_hdr *sub_hdr) ++{ ++ struct hinic3_vxlanhdr *vxh = (struct hinic3_vxlanhdr *)(ctx->pkt_itr); ++ ++ if (!pcap_check_pkt_boundary(ctx->pkt_itr, sizeof(struct hinic3_vxlanhdr), ctx->pkt_end)) { ++ HINIC3_LOG(ERR, AGENT, "length of packet is too small when extract vxlan header"); ++ return -1; ++ } ++ ++ pkt_hdr->vxlan_vni = hinic3_get_16aligned_be32(&vxh->vx_vni); ++ pkt_hdr->vxlan_vni = ((uint32_t)ntohl(pkt_hdr->vxlan_vni)) >> PCAP_VNI_TRANSFORM_OFFSET; ++ sub_hdr->save_len += sizeof(struct hinic3_vxlanhdr); ++ pcap_move_pkt_itr(ctx, sizeof(struct hinic3_vxlanhdr)); ++ return 0; ++} ++ ++static int ++pcap_pkt_parse_sub(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr, bool *is_vxlan) ++{ ++ int ret; ++ bool has_l4 = false; ++ struct hinic3_dp_extend_info *extend_info = hinic3_get_offload_extend_info(); ++ if (extend_info == NULL) ++ return -1; ++ struct hinic3_flow_agent_db *hinic3_db = (struct hinic3_flow_agent_db *)extend_info->hw_offload; ++ ++ ret = pcap_pkt_parse_l2(ctx, sub_hdr); ++ if (ret != 0) ++ return ret; ++ ++ if (!pcap_is_pkt_ip(sub_hdr->l2.eth_type)) { ++ pcap_pkt_parse_not_ip(ctx, sub_hdr); ++ return 0; ++ } ++ ++ ret = pcap_pkt_parse_l3(ctx, sub_hdr, &has_l4); ++ if (ret != 0) ++ return ret; ++ if (!has_l4) ++ return 0; ++ ++ ret = pcap_pkt_parse_l4(ctx, sub_hdr); ++ if (ret != 0) ++ return ret; ++ ++ /* check if vxlan */ ++ if (is_vxlan) { ++ if ((sub_hdr->valid_flags & PCAP_FLAG_KEY_DPORT) && (sub_hdr->l4.dport == htons(hinic3_db->vxlan_dst_port))) ++ *is_vxlan = true; ++ else ++ *is_vxlan = false; ++ } ++ ++ return 0; ++} ++ ++void ++pcap_pkt_parse(struct pcap_pkt_summary *pkt_summary) ++{ ++ int ret; ++ bool is_vxlan = false; ++ struct pcap_pkt_sub_hdr *sub_hdr = NULL; ++ struct pcap_pkt_parse_ctx *ctx = &pkt_summary->ctx; ++ struct pcap_pkt_header *pkt_hdr = &pkt_summary->pkt_header; ++ ++ ctx->pkt_itr = pkt_summary->data; ++ ctx->pkt_end = pkt_summary->data + pkt_summary->len; ++ ctx->parse_result = true; ++ ++ /* outer protocol cluster */ ++ sub_hdr = &pkt_hdr->out_header; ++ sub_hdr->save_head = ctx->pkt_itr; ++ ret = pcap_pkt_parse_sub(ctx, sub_hdr, &is_vxlan); ++ if (ret != 0) { ++ ctx->parse_result = false; ++ return; ++ } ++ ++ pkt_hdr->is_vxlan = is_vxlan; ++ if (!is_vxlan) ++ return; ++ ++ /* inner protocol cluster */ ++ ret = pcap_pkt_parse_vxlan(ctx, pkt_hdr, sub_hdr); ++ if (ret != 0) { ++ ctx->parse_result = false; ++ return; ++ } ++ ++ sub_hdr = &pkt_hdr->inner_header; ++ sub_hdr->save_head = ctx->pkt_itr; ++ ret = pcap_pkt_parse_sub(ctx, sub_hdr, NULL); ++ if (ret != 0) { ++ ctx->parse_result = false; ++ return; ++ } ++ ++ return; ++} ++ ++struct pcap_pkt_sub_hdr * ++pcap_pkt_dst_hdr_get(struct pcap_pkt_summary *buf, const struct pcap_key_t *key) ++{ ++ if (!key->vxlan_inner) ++ return &buf->pkt_header.out_header; ++ if (!buf->pkt_header.is_vxlan) ++ return &buf->pkt_header.out_header; ++ return &buf->pkt_header.inner_header; ++} ++ ++static bool ++pcap_pkt_nbits_cmp(uint8_t *src, uint8_t *dst, uint8_t bit_len) ++{ ++ uint8_t byte_cnt; ++ uint8_t left_bit_len; ++ uint8_t last_byte_mask; ++ ++ byte_cnt = bit_len >> PCAP_OFFSET_3; ++ left_bit_len = bit_len & PCAP_BIT_MASK; ++ ++ if (byte_cnt != 0) { ++ if (memcmp(src, dst, byte_cnt) != 0) ++ return false; ++ } ++ ++ if (left_bit_len == 0) ++ return true; ++ ++ last_byte_mask = (uint8_t)(0xff << (PCAP_BYTE_LEN - left_bit_len)); ++ if ((src[byte_cnt] & last_byte_mask) != (dst[byte_cnt] & last_byte_mask)) ++ return false; ++ return true; ++} ++ ++static inline bool ++pcap_pkt_mem_cmp(struct pcap_mem_cmp_t *item) ++{ ++ int ret; ++ ++ if (item->type == PCAP_CMP_MEM_BIT) ++ return pcap_pkt_nbits_cmp(item->src, item->dst, item->len); ++ ++ ret = memcmp(item->src, item->dst, item->len); ++ if (ret == 0) ++ return true; ++ else ++ return false; ++} ++ ++static inline bool ++pcap_pkt_host_filter(struct pcap_pkt_sub_hdr *dst_hdr, struct pcap_key_t *key) ++{ ++ bool flag = false; ++ ++ flag = pcap_pkt_nbits_cmp((uint8_t *)&dst_hdr->l3.sip, (uint8_t *)&key->host_ip, key->host_masklen); ++ if (flag) ++ return true; ++ ++ flag = pcap_pkt_nbits_cmp((uint8_t *)&dst_hdr->l3.dip, (uint8_t *)&key->host_ip, key->host_masklen); ++ return flag; ++} ++ ++static bool ++pcap_pkt_detail_filter(struct pcap_pkt_header *hdr, struct pcap_pkt_sub_hdr *dst_hdr, ++ struct pcap_key_t *key) ++{ ++ size_t i; ++ bool flag = false; ++ struct pcap_mem_cmp_t *item = NULL; ++ struct pcap_int_value_cmp_t *int_item = NULL; ++ struct pcap_mem_cmp_t pcap_mem_cmp_map[] = { ++ {PCAP_FLAG_KEY_SIP, (uint8_t*)&dst_hdr->l3.sip, (uint8_t*)&key->sip, key->sip_masklen, PCAP_CMP_MEM_BIT}, ++ {PCAP_FLAG_KEY_DIP, (uint8_t*)&dst_hdr->l3.dip, (uint8_t*)&key->dip, key->dip_masklen, PCAP_CMP_MEM_BIT}, ++ {PCAP_FLAG_KEY_SMAC, dst_hdr->l2.smac, key->smac, RTE_ETHER_ADDR_LEN, PCAP_CMP_MEM_BYTE}, ++ {PCAP_FLAG_KEY_DMAC, dst_hdr->l2.dmac, key->dmac, RTE_ETHER_ADDR_LEN, PCAP_CMP_MEM_BYTE}, ++ }; ++ ++ struct pcap_int_value_cmp_t pcap_value_cmp_map[] = { ++ {PCAP_FLAG_KEY_ETH_TYPE, dst_hdr->l2.eth_type, key->eth_type}, ++ {PCAP_FLAG_KEY_IP_PROTO, dst_hdr->l3.ip_proto, key->ip_proto}, ++ {PCAP_FLAG_KEY_SPORT, dst_hdr->l4.sport, key->sport}, ++ {PCAP_FLAG_KEY_DPORT, dst_hdr->l4.dport, key->dport}, ++ {PCAP_FLAG_KEY_VLAN, dst_hdr->l2.vlan_id, key->vlan_id}, ++ {PCAP_FLAG_KEY_VXLAN_VNI, hdr->vxlan_vni, key->vxlan_vni}, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(pcap_mem_cmp_map); i++) { ++ item = &pcap_mem_cmp_map[i]; ++ if ((key->flags & item->filter) == 0) ++ continue; ++ flag = pcap_pkt_mem_cmp(item); ++ if (!flag) ++ return false; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(pcap_value_cmp_map); i++) { ++ int_item = &pcap_value_cmp_map[i]; ++ if ((key->flags & int_item->filter) == 0) ++ continue; ++ ++ if (int_item->value1 != int_item->value2) ++ return false; ++ } ++ ++ /* special process for filter host */ ++ if ((key->flags & PCAP_FLAG_KEY_HOST) != 0) { ++ flag = pcap_pkt_host_filter(dst_hdr, key); ++ if (!flag) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool ++pcap_pkt_filter(struct pcap_pkt_summary *buf, struct pcap_key_t *key) ++{ ++ uint32_t tmp_flags; ++ struct pcap_pkt_sub_hdr *dst_hdr; ++ ++ dst_hdr = pcap_pkt_dst_hdr_get(buf, key); ++ tmp_flags = key->flags & PCAP_FILTER_ALL_MASK; ++ if ((tmp_flags & dst_hdr->valid_flags) != tmp_flags) ++ return false; ++ ++ if (tmp_flags == 0) ++ return true; ++ ++ return pcap_pkt_detail_filter(&buf->pkt_header, dst_hdr, key); ++} ++ ++FILE * ++pcap_file_open(const char *file_name, const char *mode) ++{ ++ FILE *file = NULL; ++ ++ if ((strcmp(mode, "wb") != 0) && (strcmp(mode, "ab") != 0)) ++ return NULL; ++ ++ file = fopen(file_name, mode); ++ if (file == NULL) { ++ HINIC3_LOG(ERR, AGENT, "pcap_file_open fail, errno is %d", errno); ++ return NULL; ++ } ++ ++ if (hinic3_agent_chown_output_file_path(file_name) != 0) { ++ fclose(file); ++ return NULL; ++ } ++ ++ return file; ++} ++ ++int ++pcap_file_write_header(const FILE *file) ++{ ++ ssize_t ret; ++ struct pcap_hdr ph; ++ struct iovec iov_f; ++ ++ ph.magic_num = PCAP_MAGIC_NUMBER; ++ ph.ver_major = PCAP_VERSION_MAJOR; ++ ph.ver_minor = PCAP_VERSION_MINOR; ++ ph.local_zone = 0; ++ ph.acc_ts = 0; ++ ph.max_pkt_len = PCAP_SNAPLEN; ++ ph.link_type = PCAP_LINKTYPE; /* Ethernet */ ++ ++ iov_f.iov_base = &ph; ++ iov_f.iov_len = sizeof(struct pcap_hdr); ++ ret = writev(fileno((FILE *)file), &iov_f, 1); ++ if (ret < 0) { ++ HINIC3_LOG(ERR, AGENT, "pcap_file_write_header fail, errno is %d", errno); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ++pcap_rte_mempool_get(struct rte_mempool *mp, void **obj_p) ++{ ++ return rte_mempool_get(mp, obj_p); ++} ++ ++void ++pcap_rte_mempool_put(struct rte_mempool *mp, void *obj) ++{ ++ rte_mempool_put(mp, obj); ++} ++ ++void ++pcap_rte_mempool_put_bulk(struct rte_mempool *mp, void * const *obj_table, unsigned int n) ++{ ++ rte_mempool_put_bulk(mp, obj_table, n); ++} ++ ++unsigned int ++pcap_rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned int n, ++ unsigned int *free_space) ++{ ++ return rte_ring_enqueue_burst(r, obj_table, n, free_space); ++} ++ ++unsigned int ++pcap_rte_ring_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned int n, unsigned int *available) ++{ ++ return rte_ring_dequeue_burst(r, obj_table, n, available); ++} ++ ++unsigned int ++pcap_rte_ring_count(const struct rte_ring *r) ++{ ++ return rte_ring_count(r); ++} +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h +new file mode 100644 +index 0000000..999ea9f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h +@@ -0,0 +1,185 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CAPTURE_FILTER_H ++#define HINIC3_CAPTURE_FILTER_H ++#include ++#include ++#include ++#include "hinic3_util.h" ++#include "hinic3_ds.h" ++#include "hinic3_capture_utils.h" ++ ++#define PCAP_FLAG_KEY_COUNT (1LLU << 0) ++#define PCAP_FLAG_KEY_FILE (1LLU << 1) ++#define PCAP_FLAG_KEY_DIRECTION (1LLU << 2) ++#define PCAP_FLAG_KEY_SIP (1LLU << 3) ++#define PCAP_FLAG_KEY_DIP (1LLU << 4) ++#define PCAP_FLAG_KEY_HOST (1LLU << 5) ++#define PCAP_FLAG_KEY_SMAC (1LLU << 6) ++#define PCAP_FLAG_KEY_DMAC (1LLU << 7) ++#define PCAP_FLAG_KEY_ETH_TYPE (1LLU << 8) ++#define PCAP_FLAG_KEY_IP_PROTO (1LLU << 9) ++#define PCAP_FLAG_KEY_SPORT (1LLU << 10) ++#define PCAP_FLAG_KEY_DPORT (1LLU << 11) ++#define PCAP_FLAG_KEY_VLAN (1LLU << 12) ++#define PCAP_FLAG_KEY_VXLAN_VNI (1LLU << 13) ++ ++#define PCAP_FILTER_ALL_MASK (PCAP_FLAG_KEY_SIP | \ ++ PCAP_FLAG_KEY_DIP | \ ++ PCAP_FLAG_KEY_HOST | \ ++ PCAP_FLAG_KEY_SMAC | \ ++ PCAP_FLAG_KEY_DMAC | \ ++ PCAP_FLAG_KEY_ETH_TYPE | \ ++ PCAP_FLAG_KEY_IP_PROTO | \ ++ PCAP_FLAG_KEY_SPORT | \ ++ PCAP_FLAG_KEY_DPORT | \ ++ PCAP_FLAG_KEY_VLAN | \ ++ PCAP_FLAG_KEY_VXLAN_VNI) ++ ++#define PCAP_FILTER_NECESSARY_MASK (PCAP_FLAG_KEY_FILE) ++ ++#define PCAP_DIR_RX 1 ++#define PCAP_DIR_TX (1 << 1) ++ ++#define PCAP_PARAM_MAX_LEN 512 ++#define PCAP_PARAM_STEP 2 ++ ++#define PCAP_DEF_PKT_CNT 8000 ++#define PCAP_MAX_PKT_CNT 1000000 ++ ++#define PCAP_MAX_VLAN_NUM 4096 ++#define PCAP_MAX_VLAN 4095 ++#define PCAP_MAX_VNI 0xFFFFFF ++ ++#define PCAP_OFFSET_32 32 ++#define PCAP_PORT_LEN 2 ++ ++#define PCAP_MAGIC_NUMBER 0xa1b2c3d4 ++#define PCAP_VERSION_MAJOR 2 ++#define PCAP_VERSION_MINOR 4 ++#define PCAP_SNAPLEN 65535 ++#define PCAP_LINKTYPE 1 ++ ++#define PCAP_DOUBLE 2 ++#define PCAP_VNI_TRANSFORM_OFFSET 8 ++ ++#define PCAP_IPV6_FRAG_HDR_SIZE 8 /* ipv6 fragment header size is 8 */ ++ ++enum pcap_cmp_mem_type { ++ PCAP_CMP_MEM_BIT = 1, ++ PCAP_CMP_MEM_BYTE ++}; ++ ++struct pcap_hdr { ++ uint32_t magic_num; ++ uint16_t ver_major; ++ uint16_t ver_minor; ++ int32_t local_zone; ++ uint32_t acc_ts; /* accuracy of timestamps */ ++ uint32_t max_pkt_len; /* max length of captured packets */ ++ uint32_t link_type; /* data link type */ ++}; ++ ++struct pcap_pkt_l2 { ++ uint8_t smac[RTE_ETHER_ADDR_LEN]; ++ uint8_t dmac[RTE_ETHER_ADDR_LEN]; ++ uint16_t vlan_id; ++ uint16_t inner_vlan_id; ++ uint16_t eth_type; ++}; ++ ++struct pcap_pkt_l3 { ++ uint32_t ip_type; ++ struct pcap_ip_t sip; ++ struct pcap_ip_t dip; ++ uint8_t ip_proto; ++}; ++ ++struct pcap_pkt_l4 { ++ uint16_t sport; ++ uint16_t dport; ++}; ++ ++struct pcap_pkt_sub_hdr { ++ uint32_t valid_flags; ++ void *save_head; ++ uint32_t save_len; ++ struct pcap_pkt_l2 l2; ++ struct pcap_pkt_l3 l3; ++ struct pcap_pkt_l4 l4; ++}; ++ ++struct pcap_pkt_header { ++ struct pcap_pkt_sub_hdr out_header; ++ struct pcap_pkt_sub_hdr inner_header; ++ bool is_vxlan; ++ uint32_t vxlan_vni; ++}; ++ ++struct pcap_pkt_parse_ctx { ++ uint8_t *pkt_itr; ++ uint8_t *pkt_end; ++ bool parse_result; ++}; ++ ++struct pcap_pkt_summary { ++ void *data; ++ enum PCAP_PKT_MEM_TYPE mem_type; ++ uint32_t len; ++ uint32_t pkt_len; ++ uint64_t ol_flags; ++ uint16_t vlan_tci; ++ uint16_t vlan_id; ++ struct pcap_pkt_parse_ctx ctx; ++ struct pcap_pkt_header pkt_header; ++}; ++ ++typedef int (*pcap_sub_key_parse_func)(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++ ++struct pcap_sub_key_parser { ++ const char *key_name; ++ size_t key_len; ++ pcap_sub_key_parse_func func; ++}; ++ ++struct pcap_mem_cmp_t { ++ uint32_t filter; ++ uint8_t *src; ++ uint8_t *dst; ++ uint8_t len; ++ uint8_t type; ++}; ++ ++struct pcap_int_value_cmp_t { ++ uint32_t filter; ++ uint32_t value1; ++ uint32_t value2; ++}; ++ ++struct pcap_pkt_save_info { ++ void *save_head; ++ uint32_t save_len; ++}; ++ ++int parse_l4_proto(const char *value, uint8_t *output); ++void pcap_convert_key_to_driver_filter(struct pcap_task_t *task); ++FILE *pcap_file_open(const char *file_name, const char *mode); ++int pcap_file_write_header(const FILE *file); ++int pcap_ip_mask_parse(char *value, struct pcap_ip_t *ip, uint8_t *mask_len, uint32_t *p_ip_type); ++int pcap_key_parse(struct pcap_key_t *cap_key, int argc, const char *argv[], struct ds *ds, struct ds *save_param); ++struct pcap_pkt_sub_hdr *pcap_pkt_dst_hdr_get(struct pcap_pkt_summary *buf, const struct pcap_key_t *key); ++bool pcap_pkt_filter(struct pcap_pkt_summary *buf, struct pcap_key_t *key); ++void pcap_pkt_parse(struct pcap_pkt_summary *pkt_summary); ++int pcap_rte_mempool_get(struct rte_mempool *mp, void **obj_p); ++void pcap_rte_mempool_put(struct rte_mempool *mp, void *obj); ++void pcap_rte_mempool_put_bulk(struct rte_mempool *mp, void * const *obj_table, unsigned int n); ++unsigned int pcap_rte_ring_count(const struct rte_ring *r); ++unsigned int pcap_rte_ring_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned int n, ++ unsigned int *available); ++unsigned int pcap_rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned int n, ++ unsigned int *free_space); ++int pcap_show_param_parse(int argc, const char *argv[], struct pcap_show_param *param, struct ds *ds); ++int pcap_stop_param_parse(int argc, const char *argv[], struct pcap_stop_param *param, struct ds *ds); ++#endif /* HINIC3_CAPTURE_FILTER_H */ +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c +new file mode 100644 +index 0000000..4c38fe7 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c +@@ -0,0 +1,58 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_lcore.h" ++#include "rte_spinlock.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#endif ++ ++#include "hinic3_log.h" ++#include "hinic3_init.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_capture_core.h" ++#include "hinic3_capture_filter.h" ++#include "hinic3_capture_save.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_util.h" ++#include "rte_ethdev.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_check_thread_health_state.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_ds.h" ++ ++void ++pcap_hook_rx_pre(void) ++{ ++ int i; ++ struct pcap_port_t port_mirror; ++ struct pcap_task_batch task_batch; ++ struct pcap_task_t *pcap_task_record = NULL; ++ ++ if (pcap_get_cap_switch() == 0) ++ return; ++ ++ pcap_task_batch_init(&task_batch); ++ pcap_port_tasks_get(&task_batch, &port_mirror); ++ if (task_batch.count == 0) ++ return; ++ ++ for (i = 0; i < task_batch.count; i++) { ++ pcap_task_record = task_batch.task_array[i]; ++ pcap_hinic3_task_exec(pcap_task_record); ++ pcap_task_put(pcap_task_record); ++ } ++ ++ return; ++} +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.h +new file mode 100644 +index 0000000..e178f59 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.h +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CAPTURE_HOOKS_H ++#define HINIC3_CAPTURE_HOOKS_H ++ ++ ++#endif /* HINIC3_CAPTURE_HOOKS_H */ +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c +new file mode 100644 +index 0000000..a87f38f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c +@@ -0,0 +1,178 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_lcore.h" ++#include "rte_spinlock.h" ++#include "hinic3_thread.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#endif ++ ++#include "hinic3_log.h" ++#include "hinic3_init.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_capture_core.h" ++#include "hinic3_capture_filter.h" ++#include "hinic3_capture_utils.h" ++#include "hinic3_capture_save.h" ++#include "hinic3_capture_command.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_util.h" ++#include "rte_ethdev.h" ++#include "hinic3_hugepage_meminfo.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_ds.h" ++#include "hinic3_capture_main.h" ++ ++static int ++hinic3_pcap_thread(void) ++{ ++ int ret; ++ struct pcap_task_save_t *pcap_task_save = NULL; ++ struct hinic3_init_arg *init_arg = NULL; ++ uint32_t pcap_cpu_id; ++ ++ pcap_task_save = hinic3_get_cap_task_save(); ++ if (pcap_task_save == NULL) ++ return -1; ++ ++ pcap_task_save->thread_exit = PCAP_THREAD_NORMAL_STATUS; ++ ret = hinic3_thread_create(&pcap_task_save->thread, "hinic3_capture_thread", pcap_thread_main, NULL, HINIC3_CAPTURE); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to create pcap thread. errno is %d", ret); ++ return -1; ++ } ++ if (hinic3_check_masked_to_exact_switch() == false) { ++ hinic3_set_ctrl_thread_cpu_affinity(&pcap_task_save->thread); ++ return 0; ++ } ++ ++ init_arg = hinic3_get_init_arg(); ++ pcap_cpu_id = init_arg->pcap_cpu; ++ (void)hinic3_set_single_cpu_affinity(&pcap_task_save->thread, pcap_cpu_id); ++ ++ return 0; ++} ++ ++int ++hinic3_pcap_mem_pool_init(void) ++{ ++ int socket_id; ++ uint16_t bond_rx_depth = hinic3_bond_rx_depth_get(); ++ uint32_t mbuf_size = hinic3_mbuf_size_get(); ++ struct rte_mempool **pcap_shared_mp = NULL; ++ uint32_t n_mbufs = PCAP_MAX_CAP_TASK * bond_rx_depth; ++ ++ pcap_shared_mp = hinic3_get_pcap_shared_mp(); ++ socket_id = (int)rte_lcore_to_socket_id(rte_get_main_lcore()); ++ if (*pcap_shared_mp == NULL) { ++ *pcap_shared_mp = hinic3_rte_pktmbuf_pool_create("hinic3-pcap-mempool:", n_mbufs, ++ RTE_MEMPOOL_CACHE_MAX_SIZE, 0, mbuf_size, socket_id); ++ if (*pcap_shared_mp == NULL) { ++ HINIC3_LOG(ERR, AGENT, "Failed to create pcap shared memory pool."); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int ++pcap_resource_init(void) ++{ ++ int size; ++ int ret; ++ struct rte_mempool *pool = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ size = sizeof(struct pcap_task_mgr_t); ++ memset(task_mgr, 0, size); ++ ++ pool = rte_mempool_lookup(PCAP_MEMPOOL_NAME); ++ if (pool == NULL) { ++ pool = hinic3_rte_mempool_create(PCAP_MEMPOOL_NAME, PCAP_MEMPOOL_SIZE, ++ sizeof(struct pcap_pkt_dump_data), 0, 0, NULL, NULL, NULL, NULL, ++ rte_socket_id(), 0); ++ if (pool == NULL) { ++ HINIC3_LOG(ERR, AGENT, "create packet capture mempool fail"); ++ return -1; ++ } ++ } ++ task_mgr->mem_pool = pool; ++ ++ task_mgr->epoll_fd = epoll_create(PCAP_EPOLL_SIZE); ++ if (task_mgr->epoll_fd < 0) { ++ HINIC3_LOG(ERR, AGENT, "create epoll fail, errno is %d", errno); ++ hinic3_rte_mempool_free(task_mgr->mem_pool); ++ task_mgr->mem_pool = NULL; ++ return -1; ++ } ++ ++ ret = pthread_create(&task_mgr->save_thread, NULL, pcap_save_thread, NULL); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "create save_thread fail, errno is %d", errno); ++ hinic3_rte_mempool_free(task_mgr->mem_pool); ++ task_mgr->mem_pool = NULL; ++ close(task_mgr->epoll_fd); ++ task_mgr->epoll_fd = -1; ++ return -1; ++ } ++ hinic3_set_ctrl_thread_cpu_affinity(&task_mgr->save_thread); ++ ++ rte_spinlock_init(&task_mgr->lock); ++ task_mgr->task_cnt = 0; ++ ++ HINIC3_LOG(INFO, AGENT, "pcap_init success"); ++ return 0; ++} ++ ++int ++hinic3_pcap_init(void) ++{ ++ int ret = 0; ++ uint64_t begin_time = 0; ++ ++ begin_time = rte_get_tsc_hz() / PCAP_TIME_S_TO_MS; ++ hinic3_set_ticks_per_ms(begin_time); ++ ret = pcap_resource_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "pcap_resource_init fail"); ++ return -1; ++ } ++ ++ ret = hinic3_pcap_mem_pool_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "pcap memory pool init failed."); ++ return -1; ++ } ++ ++ ret = hinic3_pcap_thread(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "pcap thread init fialed."); ++ return -1; ++ } ++ ++ pcap_unix_cmd_register(); ++ return 0; ++} ++ ++void ++hinic3_pcap_uninit(void) ++{ ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ hinic3_rte_mempool_free(task_mgr->mem_pool); ++ task_mgr->mem_pool = NULL; ++ close(task_mgr->epoll_fd); ++ task_mgr->epoll_fd = -1; ++ task_mgr->thread_exit = true; ++ hinic3_stop_pcap_threads(); ++} +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.h +new file mode 100644 +index 0000000..7dd56ae +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CAPTURE_MAIN_H ++#define HINIC3_CAPTURE_MAIN_H ++ ++int hinic3_pcap_init(void); ++void hinic3_pcap_uninit(void); ++void hinic3_stop_pcap_threads(void); ++void pcap_hook_rx_pre(void); ++void pcap_task_stop_as_eth_port_del(uint16_t vport_id); ++#endif /* HINIC3_CAPTURE_MAIN_H */ +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +new file mode 100644 +index 0000000..ffc1c5d +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +@@ -0,0 +1,266 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_lcore.h" ++#include "rte_spinlock.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#endif ++ ++#include "hinic3_log.h" ++#include "hinic3_init.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_capture_core.h" ++#include "hinic3_capture_filter.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_util.h" ++#include "rte_ethdev.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_check_thread_health_state.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_ds.h" ++#include "hinic3_capture_save.h" ++ ++ ++static inline void ++pcap_pkt_save_info_get(struct pcap_pkt_summary *buf, const struct pcap_key_t *key, ++ struct pcap_pkt_save_info *info) ++{ ++ if (key->vxlan_inner && buf->pkt_header.is_vxlan) { ++ info->save_head = buf->pkt_header.out_header.save_head; ++ info->save_len = buf->pkt_header.out_header.save_len + buf->pkt_header.inner_header.save_len; ++ return; ++ } ++ ++ info->save_head = buf->pkt_header.out_header.save_head; ++ info->save_len = buf->pkt_header.out_header.save_len; ++ return; ++} ++ ++static inline uint32_t ++pcap_calc_write_pkt_cnt(uint32_t byte_cnt, struct iovec *iov, uint32_t count) ++{ ++ uint32_t work_byte_cnt = byte_cnt; ++ uint32_t wr_cnt = 0; ++ ++ for (uint32_t i = 0; i < count; i++) { ++ if (work_byte_cnt < iov[i].iov_len) ++ break; ++ wr_cnt++; ++ work_byte_cnt -= iov[i].iov_len; ++ } ++ return wr_cnt; ++} ++ ++static void ++pcap_pkt_file_write(const struct pcap_task_t *cap_task, struct iovec *iov, uint32_t iov_cnt, ++ struct pcap_save_stats_t *save_stats) ++{ ++ ssize_t byte_cnt; ++ uint32_t wr_cnt; ++ ++ byte_cnt = writev(fileno(cap_task->save_file), iov, iov_cnt); ++ if (byte_cnt <= 0) { ++ wr_cnt = 0; ++ HINIC3_LOG(ERR, AGENT, "writev fail, ret is %ld, errno is %d", byte_cnt, errno); ++ } else ++ wr_cnt = pcap_calc_write_pkt_cnt(byte_cnt, iov, iov_cnt); ++ ++ if (wr_cnt >= iov_cnt) ++ save_stats->wr_iov_cnt = iov_cnt; ++ else { ++ save_stats->wr_iov_cnt = wr_cnt; ++ save_stats->write_fail = true; ++ HINIC3_LOG(ERR, AGENT, "write_cnt is %u, fail_cnt is %u", wr_cnt, iov_cnt - wr_cnt); ++ } ++ return; ++} ++ ++static void ++pcap_pkt_file_save(struct pcap_task_t *cap_task, uint64_t remain_cnt, struct pcap_pkt_summary **buf, ++ uint32_t count, struct pcap_save_stats_t *save_stats) ++{ ++ uint32_t i; ++ uint32_t iov_cnt = 0; ++ int idx; ++ struct timeval tv; ++ struct pcap_pkt_save_info save_info; ++ struct pcap_pkt_summary *tmp_buf = NULL; ++ struct pcap_file_record_hdr record_hdr[PKT_MAX_BURST]; ++ struct iovec iov[PKT_MAX_BURST * PCAP_DOUBLE]; ++ ++ gettimeofday(&tv, NULL); ++ for (i = 0; i < count; i++) { ++ tmp_buf = buf[i]; ++ pcap_pkt_save_info_get(tmp_buf, &cap_task->key, &save_info); ++ ++ record_hdr[i].pkt_ts_sec = (uint32_t)tv.tv_sec; ++ record_hdr[i].pkt_ts_usec = (uint32_t)tv.tv_usec; ++ record_hdr[i].pkt_incl_len = save_info.save_len; ++ record_hdr[i].pkt_orig_len = tmp_buf->pkt_len; ++ ++ idx = i * PCAP_DOUBLE; ++ iov[idx].iov_base = &(record_hdr[i]); ++ iov[idx].iov_len = sizeof(struct pcap_file_record_hdr); ++ iov[idx + 1].iov_base = save_info.save_head; ++ iov[idx + 1].iov_len = save_info.save_len; ++ iov_cnt += PCAP_DOUBLE; ++ } ++ ++ if (remain_cnt < count) ++ iov_cnt = remain_cnt * PCAP_DOUBLE; ++ ++ pcap_pkt_file_write(cap_task, iov, iov_cnt, save_stats); ++ save_stats->wr_cnt = save_stats->wr_iov_cnt / PCAP_DOUBLE; ++ return; ++} ++ ++void ++pcap_epoll_event_process(uint32_t pcap_id) ++{ ++ uint32_t i; ++ uint64_t save_cnt; ++ uint32_t pkt_cnt; ++ uint64_t value; ++ struct pcap_save_stats_t save_stats; ++ struct pcap_task_mirror_t task_mirror; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_pkt_dump_data *tmp_data = NULL; ++ struct iovec iov[PKT_MAX_BURST]; ++ struct pcap_pkt_dump_data *pkt_dump_list[PKT_MAX_BURST] = { NULL }; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ cap_task = pcap_task_get_by_id(pcap_id, &task_mirror); ++ if (!cap_task) ++ return; ++ ++ /* get packet from ring */ ++ pkt_cnt = pcap_rte_ring_dequeue_burst(cap_task->ring, (void **)pkt_dump_list, PKT_MAX_BURST, NULL); ++ if (pkt_cnt == 0) { ++ pcap_task_put(cap_task); ++ return; ++ } ++ ++ if (task_mirror.remain_count == 0 || task_mirror.wr_fail_flag) { ++ pcap_task_put(cap_task); ++ pcap_rte_mempool_put_bulk(task_mgr->mem_pool, (void * const *)pkt_dump_list, pkt_cnt); ++ return; ++ } ++ ++ /* save packet */ ++ for (i = 0; i < pkt_cnt; i++) { ++ tmp_data = pkt_dump_list[i]; ++ iov[i].iov_base = &tmp_data->record_hdr; ++ iov[i].iov_len = (sizeof(struct pcap_file_record_hdr) + tmp_data->record_hdr.pkt_incl_len); ++ } ++ save_cnt = (pkt_cnt > task_mirror.remain_count) ? task_mirror.remain_count : pkt_cnt; ++ ++ memset(&save_stats, 0, sizeof(save_stats)); ++ pcap_pkt_file_write(cap_task, iov, save_cnt, &save_stats); ++ save_stats.wr_cnt = save_stats.wr_iov_cnt; ++ pcap_task_stats_update(cap_task, &save_stats); ++ ++ if (pcap_rte_ring_count(cap_task->ring) == 0) ++ eventfd_read(cap_task->event_fd, &value); ++ ++ pcap_task_put(cap_task); ++ pcap_rte_mempool_put_bulk(task_mgr->mem_pool, (void * const *)pkt_dump_list, pkt_cnt); ++ return; ++} ++ ++static void ++pcap_pkt_ring_save(struct pcap_task_t *cap_task, struct pcap_pkt_summary **buf, ++ uint32_t count, struct pcap_save_stats_t *save_stats) ++{ ++ uint32_t i; ++ int ret; ++ uint32_t enq_cnt; ++ uint32_t save_cnt = 0; ++ uint32_t really_len; ++ struct timeval tv; ++ struct pcap_pkt_save_info save_info; ++ struct pcap_pkt_summary *tmp_buf = NULL; ++ struct pcap_pkt_dump_data *tmp_item = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ struct pcap_pkt_dump_data *dump_list[PKT_MAX_BURST] = { NULL }; ++ ++ gettimeofday(&tv, NULL); ++ for (i = 0; i < count; i++) { ++ tmp_buf = buf[i]; ++ ret = pcap_rte_mempool_get(task_mgr->mem_pool, (void **)(&tmp_item)); ++ if (ret != 0) { ++ save_stats->en_ring_fail_cnt++; ++ continue; ++ } ++ ++ pcap_pkt_save_info_get(tmp_buf, &cap_task->key, &save_info); ++ tmp_item->record_hdr.pkt_ts_sec = tv.tv_sec; ++ tmp_item->record_hdr.pkt_ts_usec = tv.tv_usec; ++ really_len = (save_info.save_len > PCAP_DUMP_SIZE) ? PCAP_DUMP_SIZE : save_info.save_len; ++ tmp_item->record_hdr.pkt_incl_len = really_len; ++ tmp_item->record_hdr.pkt_orig_len = tmp_buf->pkt_len; ++ ++ memcpy(tmp_item->data, save_info.save_head, really_len); ++ if (tmp_item->data == NULL) { ++ pcap_rte_mempool_put(task_mgr->mem_pool, tmp_item); ++ save_stats->en_ring_fail_cnt++; ++ continue; ++ } ++ dump_list[save_cnt] = tmp_item; ++ save_cnt++; ++ } ++ if (save_cnt <= 0) ++ return; ++ ++ enq_cnt = pcap_rte_ring_enqueue_burst(cap_task->ring, (void * const *)dump_list, save_cnt, NULL); ++ if (enq_cnt < save_cnt) { ++ save_stats->en_ring_fail_cnt += save_cnt - enq_cnt; ++ pcap_rte_mempool_put_bulk(task_mgr->mem_pool, (void * const *)&dump_list[enq_cnt], save_cnt - enq_cnt); ++ } ++ if (enq_cnt > 0) ++ eventfd_write(cap_task->event_fd, 1); ++ ++ return; ++} ++ ++void * ++pcap_save_thread(void *args) ++{ ++ int i; ++ int nfds; ++ struct epoll_event events[PCAP_MAX_CAP_TASK]; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ pthread_setname_np(pthread_self(), "hinic3_pcap_save"); ++ enum check_thread_item_type check_thread = PCAP_SAVE_THREAD; ++ long long start = hinic3_time_msec(); ++ while (!task_mgr->thread_exit) { ++ start = hinic3_thread_signal_increase(start, check_thread, HINIC3_PCAP_SAVE_THREAD_SIGNAL_INCREASE_INTER); ++ nfds = epoll_wait(task_mgr->epoll_fd, events, PCAP_MAX_CAP_TASK, PCAP_EPOLL_TIMEOUT); ++ for (i = 0; i < nfds; ++i) ++ pcap_epoll_event_process(events[i].data.u32); ++ } ++ ++ return NULL; ++} ++ ++void ++pcap_pkt_save(struct pcap_task_t *cap_task, uint64_t remain_cnt, struct pcap_pkt_summary **buf, ++ uint32_t count, struct pcap_save_stats_t *save_stats) ++{ ++ if (cap_task->key.write_way == WRITE_BY_PMD) ++ pcap_pkt_file_save(cap_task, remain_cnt, buf, count, save_stats); ++ else ++ pcap_pkt_ring_save(cap_task, buf, count, save_stats); ++} +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.h +new file mode 100644 +index 0000000..8d50ed8 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CAPTURE_SAVE_H ++#define HINIC3_CAPTURE_SAVE_H ++ ++void pcap_pkt_save(struct pcap_task_t *cap_task, uint64_t remain_cnt, struct pcap_pkt_summary **buf, ++ uint32_t count, struct pcap_save_stats_t *save_stats); ++void *pcap_save_thread(void *args); ++#endif /* HINIC3_CAPTURE_SAVE_H */ +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +new file mode 100644 +index 0000000..dedcaf5 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +@@ -0,0 +1,1303 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_lcore.h" ++#include "rte_spinlock.h" ++ ++#include "hinic3_log.h" ++#include "hinic3_init.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_capture_core.h" ++#include "hinic3_capture_filter.h" ++#include "hinic3_capture_main.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_util.h" ++#include "rte_ethdev.h" ++#include "hinic3_port_util.h" ++#include "hinic3_check_thread_health_state.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ds.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_dpdk_adapter.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#include "hinic3_capture_utils.h" ++#endif ++ ++#define HINIC3_EVENT_FD_INVAILD (-1) ++uint64_t g_ticks_per_ms; ++static uint32_t g_pcap_id_begin = 1; ++static bool g_pcap_rule_idx[PCAP_MAX_CAP_TASK] = {0}; ++struct rte_mempool *g_pcap_shared_mp = NULL; ++ ++int g_cap_switch = 0; ++struct pcap_task_mgr_t g_cap_task_mgr; ++struct pcap_task_save_t g_cap_task_save = { 0 }; ++ ++struct pcap_task_mgr_t* ++pcap_get_task_mgr(void) ++{ ++ return &g_cap_task_mgr; ++} ++ ++int ++pcap_get_cap_switch(void) ++{ ++ return g_cap_switch; ++} ++ ++void ++pcap_task_mgr_spin_lock(void) ++{ ++ rte_spinlock_lock(&g_cap_task_mgr.lock); ++} ++ ++void ++pcap_task_mgr_spin_unlock(void) ++{ ++ rte_spinlock_unlock(&g_cap_task_mgr.lock); ++} ++ ++void ++pcap_task_spin_lock(struct pcap_task_t *task) ++{ ++ rte_spinlock_lock(&task->lock); ++} ++ ++void ++pcap_task_spin_unlock(struct pcap_task_t *task) ++{ ++ rte_spinlock_unlock(&task->lock); ++} ++ ++static inline int ++pcap_idle_rule_index_occupy(void) ++{ ++ int i; ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ if (!g_pcap_rule_idx[i]) { ++ g_pcap_rule_idx[i] = true; ++ return i; ++ } ++ } ++ return -1; ++} ++ ++static void ++pcap_rule_index_free(int idx) ++{ ++ g_pcap_rule_idx[idx] = false; ++} ++ ++static int ++hinic3_get_port_info(uint16_t port_id, struct pcap_port_t *port_info) ++{ ++ struct rte_eth_dev_info info = {0}; ++ ++ int ret = rte_eth_dev_info_get(port_id, &info); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ uint32_t if_index = info.if_index; ++ if (if_index > UINT16_MAX) { ++ HINIC3_LOG(ERR, AGENT, "if_index %u is invalid.", if_index); ++ return -1; ++ } ++ ++ const char *driver_name = info.driver_name; ++ if (driver_name == NULL || strcmp(driver_name, HINIC3_ETH_VDEV_DRV_NAME) != 0) { ++ return -1; ++ } ++ port_info->hinic3_port_id = (uint16_t)if_index; ++ port_info->odp_port_no = (uint16_t)if_index; ++ ++ return 0; ++} ++ ++int ++pcap_port_info_get_by_name(char *port_name, struct pcap_port_t *port_info, struct ds *ds) ++{ ++ int ret; ++ uint16_t port_id = 0; ++ char name[PCAP_MAX_PORT_COMBINE_NAME] = {0}; ++ ++ ret = snprintf(name, PCAP_MAX_PORT_COMBINE_NAME - 1, "%s%s", HINIC3_ETH_VDEV_DRV_NAME, port_name); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "The port name is misspelled."); ++ return -1; ++ } ++ ++ ret = rte_eth_dev_get_port_by_name(name, &port_id); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sCan not find device in dp for name %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, name); ++ return -1; ++ } ++ ++ strcpy(port_info->name, port_name); ++ if (port_info->name == NULL) { ++ HINIC3_LOG(ERR, AGENT, "strcpy_s port name fail."); ++ hinic3_ds_put_format(ds, "%sInternal error.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ return -1; ++ } ++ ++ ret = hinic3_get_port_info(port_id, port_info); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%sFailed to obtain the port information.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ return -1; ++ } ++ ++ port_info->support_cap = true; ++ return 0; ++} ++ ++static bool ++pcap_timeout_check(uint64_t start_tsc, uint64_t timout_ms) ++{ ++ uint64_t now; ++ ++ now = rte_rdtsc(); ++ if ((now - start_tsc) > timout_ms * g_ticks_per_ms) ++ return true; ++ ++ return false; ++} ++ ++static void ++pcap_task_stop_reply_format(struct pcap_task_t *task, struct ds *ds) ++{ ++ char *tmp_str = NULL; ++ struct pcap_stats_t *stats = &task->stats; ++ ++ hinic3_ds_put_format(ds, "%2sstopped pcap id: %u \n", HINIC3_UI_INDENT_SPACE, task->pcap_id); ++ tmp_str = task->wr_fail_flag ? "true" : "false"; ++ hinic3_ds_put_format(ds, "%2scaptured: %llu \n", ++ HINIC3_UI_INDENT_SPACE, (unsigned long long)stats->wr_cnt); ++ hinic3_ds_put_format(ds, "%2senqueue-fail: %llu \n", ++ HINIC3_UI_INDENT_SPACE, (unsigned long long)stats->en_ring_fail_cnt); ++ hinic3_ds_put_format(ds, "%2sdrop: %llu \n", ++ HINIC3_UI_INDENT_SPACE, (unsigned long long)stats->soft_drop_cnt); ++ hinic3_ds_put_format(ds, "%2swrite-success: %s\n", ++ HINIC3_UI_INDENT_SPACE, tmp_str); ++ ++ hinic3_ds_put_format(ds, "%2shardware card:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4scaptured: %llu\n", ++ HINIC3_UI_INDENT_SPACE, (unsigned long long)stats->hinic3_stats.pkts_pcap_cnt); ++ hinic3_ds_put_format(ds, "%4sdrop: %llu\n", ++ HINIC3_UI_INDENT_SPACE, (unsigned long long)stats->hinic3_stats.pkts_drop_cnt); ++} ++ ++static void ++pcap_task_batch_reply_format(struct pcap_task_batch *task_batch, const char *prefix, struct ds *ds) ++{ ++ int i; ++ struct pcap_task_t *pcap_task_record = NULL; ++ ++ if (task_batch->count <= 0) { ++ return; ++ } ++ ++ hinic3_ds_put_format(ds, "stop %s tasks: ", prefix); ++ for (i = 0; i < task_batch->count; i++) { ++ pcap_task_record = task_batch->task_array[i]; ++ hinic3_ds_put_format(ds, "%u ", pcap_task_record->pcap_id); ++ } ++ hinic3_ds_put_cstr(ds, "\n"); ++} ++ ++static int ++pcap_driver_exec(struct pcap_task_t *task, struct hinic3_nlattr *reply_nla) ++{ ++ int ret; ++ void *buff = NULL; ++ char *tmp_value = NULL; ++ struct hinic3_nlattr set_nla; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_cfg_set, HINIC3_DRV_FUNC_NO_PTR); ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_CAPTURE); ++ if (!buff) { ++ HINIC3_LOG(ERR, AGENT, "pcap_driver_exec calloc fail."); ++ return -1; ++ } ++ ++ tmp_value = buff; ++ hinic3_nlattr_init(&set_nla, tmp_value, HOVS_MAX_TLV_BUF_LEN); ++ hinic3_nlattr_put_unspec(&set_nla, HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE, &task->driver.driver_filter, ++ sizeof(struct hinic3_pcap_probe_filter_t)); ++ ret = ops->hovs_global_cfg_set((struct nlattr *)set_nla.data, set_nla.used_len, ++ (struct nlattr *)reply_nla->data, &reply_nla->used_len); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hovs_global_cfg_set exec fail, ret is %d", ret); ++ hinic3_free(buff); ++ return -1; ++ } ++ ++ hinic3_free(buff); ++ return 0; ++} ++ ++static int ++pcap_extract_start_reply(struct pcap_task_t *task, struct hinic3_nlattr *reply_nla) ++{ ++ int ret; ++ bool flag = false; ++ hinic3_nlattr_itr nla_itr = NULL; ++ struct hinic3_pcap_probe_rule_q_map *rule_q_map = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH (nla_itr, reply_nla) { ++ if (hinic3_nlattr_get_itr_type(nla_itr) == HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE) { ++ flag = true; ++ break; ++ } ++ } ++ if (!flag) { ++ HINIC3_LOG(ERR, AGENT, "no reply info from hovs_global_cfg_set"); ++ return -1; ++ } ++ ++ rule_q_map = (struct hinic3_pcap_probe_rule_q_map *)hinic3_nlattr_get_itr_data(nla_itr); ++ task->driver.queue_info.hinic3_dpdk_port_id = rule_q_map->hinic3_dpdk_port_id; ++ task->driver.queue_info.queue_id = rule_q_map->queue_id; ++ task->driver.queue_info.rule_idx = rule_q_map->rule_idx; ++ HINIC3_LOG(INFO, AGENT, "start capture in hardware success, dpdk_port_id is %u, queue is %u, rule_idx is %u.", ++ rule_q_map->hinic3_dpdk_port_id, rule_q_map->queue_id, rule_q_map->rule_idx); ++ ++ if (g_pcap_shared_mp == NULL) { ++ HINIC3_LOG(ERR, AGENT, "pcap mempool has not been created.\n"); ++ return -1; ++ } ++ ++ ret = hinic3_port_mgmt_setup_upcall_queue(rule_q_map->hinic3_dpdk_port_id, rule_q_map->queue_id, ++ 0, g_pcap_shared_mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "pcap setup upcall queue error.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++pcap_extract_stop_reply(struct pcap_task_t *task, struct hinic3_nlattr *reply_nla) ++{ ++ int ret; ++ bool flag = false; ++ hinic3_nlattr_itr nla_itr = NULL; ++ struct hinic3_pcap_probe_stats *hw_stats = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH (nla_itr, reply_nla) { ++ if (hinic3_nlattr_get_itr_type(nla_itr) == HINIC3_GLOBAL_GET_PCAP_PROBE_STATS) { ++ flag = true; ++ break; ++ } ++ } ++ if (!flag) { ++ HINIC3_LOG(ERR, AGENT, "no reply info from hovs_global_cfg_set"); ++ return -1; ++ } ++ ++ hw_stats = (struct hinic3_pcap_probe_stats *)hinic3_nlattr_get_itr_data(nla_itr); ++ task->stats.hinic3_stats.pkts_pcap_cnt = hw_stats->pkts_pcap_cnt; ++ task->stats.hinic3_stats.pkts_drop_cnt = hw_stats->pkts_drop_cnt; ++ ++ ret = hinic3_port_mgmt_release_upcall_queue(task->driver.queue_info.hinic3_dpdk_port_id, ++ task->driver.queue_info.queue_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "pcap release upcall queue error.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++pcap_start_in_driver(struct pcap_task_t *task) ++{ ++ int ret; ++ void *buff = NULL; ++ char *tmp_value = NULL; ++ struct hinic3_nlattr reply_nla; ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_CAPTURE); ++ if (!buff) { ++ HINIC3_LOG(ERR, AGENT, "calloc buff fail"); ++ return -1; ++ } ++ ++ tmp_value = buff; ++ hinic3_nlattr_init(&reply_nla, tmp_value, HOVS_MAX_TLV_BUF_LEN); ++ ret = pcap_driver_exec(task, &reply_nla); ++ if (ret != 0) ++ goto fail; ++ ++ hinic3_nlattr_reset_itr(&reply_nla, reply_nla.used_len); ++ ret = pcap_extract_start_reply(task, &reply_nla); ++ if (ret != 0) ++ goto fail; ++ ++ hinic3_free(buff); ++ return 0; ++ ++fail: ++ hinic3_free(buff); ++ return -1; ++} ++ ++static int ++pcap_stop_in_driver(struct pcap_task_t *task) ++{ ++ int ret; ++ void *buff = NULL; ++ char *tmp_value = NULL; ++ struct hinic3_nlattr reply_nla; ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_CAPTURE); ++ if (!buff) { ++ HINIC3_LOG(ERR, AGENT, "calloc buff failed"); ++ return -1; ++ } ++ ++ tmp_value = buff; ++ hinic3_nlattr_init(&reply_nla, tmp_value, HOVS_MAX_TLV_BUF_LEN); ++ ret = pcap_driver_exec(task, &reply_nla); ++ if (ret != 0) ++ goto fail; ++ ++ hinic3_nlattr_reset_itr(&reply_nla, reply_nla.used_len); ++ ret = pcap_extract_stop_reply(task, &reply_nla); ++ if (ret != 0) ++ goto fail; ++ ++ hinic3_free(buff); ++ return 0; ++ ++fail: ++ hinic3_free(buff); ++ return -1; ++} ++ ++void ++pcap_task_stats_update(struct pcap_task_t *cap_task, struct pcap_save_stats_t *save_stats) ++{ ++ pcap_task_spin_lock(cap_task); ++ if (cap_task->remain_count <= save_stats->wr_cnt) ++ cap_task->remain_count = 0; ++ else ++ cap_task->remain_count -= save_stats->wr_cnt; ++ ++ if (save_stats->write_fail) ++ cap_task->wr_fail_flag = true; ++ cap_task->stats.wr_cnt += save_stats->wr_cnt; ++ cap_task->stats.en_ring_fail_cnt += save_stats->en_ring_fail_cnt; ++ cap_task->stats.soft_drop_cnt += save_stats->parse_fail_cnt; ++ pcap_task_spin_unlock(cap_task); ++} ++ ++void ++pcap_task_mirror_get(struct pcap_task_t *cap_task, struct pcap_task_mirror_t *task_mirror) ++{ ++ pcap_task_spin_lock(cap_task); ++ task_mirror->stop_flag = cap_task->stop_flag; ++ task_mirror->wr_fail_flag = cap_task->wr_fail_flag; ++ task_mirror->remain_count = cap_task->remain_count; ++ pcap_task_spin_unlock(cap_task); ++} ++ ++static int ++pcap_task_driver_start(struct pcap_task_t *task) ++{ ++ int ret; ++ int port_task_cnt; ++ struct hinic3_pcap_probe_filter_t *filter = &task->driver.driver_filter; ++ ++ pcap_convert_key_to_driver_filter(task); ++ filter->rule_cfg.cap_id = task->rule_idx; ++ filter->rule_cfg.vport_id = task->pcap_port.hinic3_port_id; ++ ++ filter->pcap_ctl.rule_idx = task->rule_idx; ++ filter->pcap_ctl.enable = PCAP_PROBE_ENABLE; ++ filter->pcap_ctl.hinic3_port_id = task->pcap_port.hinic3_port_id; ++ ++ port_task_cnt = pcap_port_tasks_count_no_lock(task->pcap_port.odp_port_no); ++ filter->pcap_ctl.first_last_rule = (port_task_cnt == 0); ++ ++ ret = pcap_start_in_driver(task); ++ return ret; ++} ++ ++static int ++pcap_task_driver_stop(struct pcap_task_t *task) ++{ ++ int ret; ++ int port_task_cnt; ++ struct hinic3_pcap_probe_filter_t *filter = &task->driver.driver_filter; ++ ++ port_task_cnt = pcap_port_tasks_count_no_lock(task->pcap_port.odp_port_no); ++ filter->pcap_ctl.enable = PCAP_PROBE_DISABLE; ++ filter->pcap_ctl.first_last_rule = (port_task_cnt == 1); ++ ++ ret = pcap_stop_in_driver(task); ++ return ret; ++} ++ ++static int ++pcap_task_ring_create(struct pcap_task_t *task) ++{ ++ int ret; ++ char *tmp_str = NULL; ++ struct rte_ring *ring = NULL; ++ char ring_name[PCAP_MAX_RING_NAME] = {0}; ++ ++ ret = sprintf(ring_name, "%s_%u", PCAP_RING_NAME_PREFIX, task->pcap_id); ++ if (ret < 0) { ++ HINIC3_LOG(ERR, AGENT, "sprintf_s fail, ret is %d", ret); ++ return -1; ++ } ++ ++ tmp_str = ring_name; ++ ring = rte_ring_lookup(tmp_str); ++ if (ring) { ++ task->ring = ring; ++ return 0; ++ } ++ ++ ring = rte_ring_create(tmp_str, PCAP_RING_SIZE, rte_socket_id(), 0); ++ if (!ring) { ++ HINIC3_LOG(ERR, AGENT, "rte_ring_create fail, pcap_id is %u", task->pcap_id); ++ return -1; ++ } ++ ++ task->ring = ring; ++ return 0; ++} ++ ++static int ++pcap_task_epoll_fd_create(struct pcap_task_t *task) ++{ ++ int ret; ++ struct epoll_event event; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ task->event_fd = eventfd(0, EFD_NONBLOCK); ++ if (task->event_fd < 0) { ++ HINIC3_LOG(ERR, AGENT, "create eventfd fail, errno is %d", errno); ++ return -1; ++ } ++ ++ memset(&event, 0, sizeof(event)); ++ event.events = EPOLLIN; ++ event.data.u32 = task->pcap_id; ++ ++ ret = epoll_ctl(task_mgr->epoll_fd, EPOLL_CTL_ADD, task->event_fd, &event); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "EPOLL_CTL_ADD fail, ret is %d, errno is %d", ret, errno); ++ close(task->event_fd); ++ task->event_fd = HINIC3_EVENT_FD_INVAILD; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++pcap_task_resource_create(struct pcap_task_t *task) ++{ ++ int ret; ++ struct pcap_key_t *task_key = &task->key; ++ ++ rte_spinlock_init(&task->lock); ++ ++ task->save_file = pcap_file_open(task_key->filename, "wb"); ++ if (!task->save_file) ++ return -1; ++ ++ ret = pcap_file_write_header(task->save_file); ++ if (ret != 0) ++ goto file_free; ++ ++ if (task_key->write_way == WRITE_BY_PMD) ++ return 0; ++ ++ ret = pcap_task_ring_create(task); ++ if (ret != 0) ++ goto file_free; ++ ++ ret = pcap_task_epoll_fd_create(task); ++ if (ret != 0) ++ goto ring_free; ++ ++ return 0; ++ ++ring_free: ++ rte_ring_free(task->ring); ++ task->ring = NULL; ++file_free: ++ (void)fclose(task->save_file); ++ return -1; ++} ++ ++static void ++pcap_task_resource_destroy(struct pcap_task_t *task) ++{ ++ int ret; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ ret = fflush(task->save_file); ++ if (ret != 0) ++ HINIC3_LOG(ERR, AGENT, "fflush fail."); ++ (void)fclose(task->save_file); ++ task->save_file = NULL; ++ ++ if (task->key.write_way == WRITE_BY_PMD) ++ return; ++ ++ if (task->ring) ++ rte_ring_free(task->ring); ++ ++ if (task->event_fd > 0) { ++ epoll_ctl(task_mgr->epoll_fd, EPOLL_CTL_DEL, task->event_fd, NULL); ++ close(task->event_fd); ++ task->event_fd = HINIC3_EVENT_FD_INVAILD; ++ } ++ ++ return; ++} ++ ++static struct pcap_task_t* ++pcap_task_create(struct pcap_key_t *pcap_key, struct ds *save_param) ++{ ++ int ret; ++ int len; ++ struct pcap_task_t *cap_task = NULL; ++ ++ cap_task = (struct pcap_task_t*)hinic3_calloc(1, sizeof(struct pcap_task_t), HINIC3_CAPTURE); ++ if (!cap_task) { ++ HINIC3_LOG(ERR, AGENT, "malloc cap_task fail"); ++ return NULL; ++ } ++ ++ len = strlen(hinic3_ds_cstr(save_param)) + 1; ++ cap_task->parameter = (char*)hinic3_calloc(1, len, HINIC3_CAPTURE); ++ if (!cap_task->parameter) { ++ hinic3_free(cap_task); ++ HINIC3_LOG(ERR, AGENT, "malloc cap_task->parameter fail"); ++ return NULL; ++ } ++ ++ memcpy(cap_task->parameter, hinic3_ds_cstr(save_param), len - 1); ++ if (cap_task->parameter == NULL) { ++ hinic3_free(cap_task->parameter); ++ hinic3_free(cap_task); ++ return NULL; ++ } ++ ++ memcpy(&cap_task->key, pcap_key, sizeof(struct pcap_key_t)); ++ if (&cap_task->key == NULL) { ++ hinic3_free(cap_task->parameter); ++ hinic3_free(cap_task); ++ return NULL; ++ } ++ ++ cap_task->ref_cnt = 1; ++ cap_task->remain_count = pcap_key->count_total; ++ cap_task->pcap_id = g_pcap_id_begin++; ++ ret = pcap_task_resource_create(cap_task); ++ if (ret != 0) { ++ hinic3_free(cap_task->parameter); ++ hinic3_free(cap_task); ++ return NULL; ++ } ++ ++ cap_task->rule_idx = pcap_idle_rule_index_occupy(); ++ return cap_task; ++} ++ ++static void ++pcap_task_destroy(struct pcap_task_t *cap_task) ++{ ++ HINIC3_LOG(INFO, AGENT, "stop a capture task, pcap_id is %u", cap_task->pcap_id); ++ pcap_task_resource_destroy(cap_task); ++ pcap_rule_index_free(cap_task->rule_idx); ++ hinic3_free(cap_task->parameter); ++ hinic3_free(cap_task); ++} ++ ++static void ++pcap_task_batch_destroy(struct pcap_task_batch *task_batch, struct ds *ds) ++{ ++ int i; ++ bool first_flag = true; ++ struct pcap_task_t *pcap_task_record = NULL; ++ ++ for (i = 0; i < task_batch->count; i++) { ++ if (!first_flag) ++ hinic3_ds_put_cstr(ds, "\n"); ++ ++ pcap_task_record = task_batch->task_array[i]; ++ pcap_task_stop_reply_format(pcap_task_record, ds); ++ pcap_task_destroy(pcap_task_record); ++ first_flag = false; ++ } ++} ++ ++static void ++pcap_task_batch_destroy_raw(struct pcap_task_batch *task_batch) ++{ ++ int i; ++ struct pcap_task_t *pcap_task_record = NULL; ++ ++ for (i = 0; i < task_batch->count; i++) { ++ pcap_task_record = task_batch->task_array[i]; ++ pcap_task_destroy(pcap_task_record); ++ } ++} ++ ++/* this function is called by maintain thread, task list will not changed, no need to lock */ ++bool ++pcap_check_file_used_no_lock(struct pcap_key_t *cap_key) ++{ ++ int i; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ if (task_mgr->task_cnt == 0) { ++ return 0; ++ } ++ ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->stop_flag) ++ continue; ++ ++ if (strcmp(cap_task->key.filename, cap_key->filename) == 0) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* this function is called by maintain thread, task list will not changed, no need to lock */ ++int ++pcap_port_tasks_count_no_lock(uint32_t port_no) ++{ ++ int i; ++ int count; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ if (task_mgr->task_cnt == 0) ++ return 0; ++ ++ count = 0; ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->stop_flag) ++ continue; ++ ++ if (cap_task->pcap_port.odp_port_no != port_no) ++ continue; ++ ++ count++; ++ } ++ ++ return count; ++} ++ ++struct pcap_task_t* ++pcap_task_find_no_lock(uint32_t pcap_id, uint32_t *index) ++{ ++ int i; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ if (task_mgr->task_cnt == 0) ++ return NULL; ++ ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->pcap_id != pcap_id) ++ continue; ++ ++ *index = i; ++ return cap_task; ++ } ++ ++ return NULL; ++} ++ ++void ++pcap_port_tasks_get(struct pcap_task_batch *task_batch, struct pcap_port_t *port_mirror) ++{ ++ int i; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ pcap_task_mgr_spin_lock(); ++ if (task_mgr->task_cnt == 0) { ++ pcap_task_mgr_spin_unlock(); ++ return; ++ } ++ ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->stop_flag || (cap_task->remain_count == 0)) ++ continue; ++ ++ cap_task->ref_cnt++; ++ task_batch->task_array[task_batch->count] = cap_task; ++ task_batch->count++; ++ } ++ ++ pcap_task_mgr_spin_unlock(); ++ return; ++} ++ ++struct pcap_task_t* ++pcap_task_get_by_id(uint32_t pcap_id, struct pcap_task_mirror_t *task_mirror) ++{ ++ int i; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ pcap_task_mgr_spin_lock(); ++ if (task_mgr->task_cnt == 0) { ++ pcap_task_mgr_spin_unlock(); ++ return NULL; ++ } ++ ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->stop_flag || (cap_task->remain_count == 0)) ++ continue; ++ ++ if (cap_task->pcap_id != pcap_id) ++ continue; ++ ++ cap_task->ref_cnt++; ++ if (task_mirror) { ++ task_mirror->stop_flag = cap_task->stop_flag; ++ task_mirror->wr_fail_flag = cap_task->wr_fail_flag; ++ task_mirror->remain_count = cap_task->remain_count; ++ } ++ pcap_task_mgr_spin_unlock(); ++ return cap_task; ++ } ++ ++ pcap_task_mgr_spin_unlock(); ++ return NULL; ++} ++ ++void ++pcap_task_put(struct pcap_task_t *cap_task) ++{ ++ pcap_task_mgr_spin_lock(); ++ cap_task->ref_cnt--; ++ pcap_task_mgr_spin_unlock(); ++} ++ ++void ++pcap_task_batch_put(struct pcap_task_batch *task_batch) ++{ ++ int i; ++ ++ pcap_task_mgr_spin_lock(); ++ for (i = 0; i < task_batch->count; i++) ++ task_batch->task_array[i]->ref_cnt--; ++ pcap_task_mgr_spin_unlock(); ++} ++ ++static uint32_t ++pcap_all_vf_tasks_stop_set(uint16_t vport_id, struct pcap_task_batch *fail_task_batch) ++{ ++ int i; ++ int ret; ++ uint32_t count; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ if (task_mgr->task_cnt == 0) ++ return 0; ++ ++ count = 0; ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->pcap_port.hinic3_port_id != vport_id) ++ continue; ++ ++ if (cap_task->stop_flag) { ++ count++; ++ continue; ++ } ++ ++ pcap_task_spin_lock(cap_task); ++ if (!cap_task->driver.stop_flag) { ++ ret = pcap_task_driver_stop(cap_task); ++ if (ret != 0) { ++ fail_task_batch->task_array[fail_task_batch->count] = cap_task; ++ fail_task_batch->count++; ++ pcap_task_spin_unlock(cap_task); ++ continue; ++ } ++ cap_task->driver.stop_flag = true; ++ } ++ cap_task->stop_flag = true; ++ pcap_task_spin_unlock(cap_task); ++ count++; ++ } ++ ++ return count; ++} ++ ++static uint32_t ++pcap_all_tasks_stop_set(uint32_t port_no, struct pcap_task_batch *fail_task_batch) ++{ ++ int i; ++ int ret; ++ uint32_t count; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ if (task_mgr->task_cnt == 0) ++ return 0; ++ ++ count = 0; ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->pcap_port.odp_port_no != port_no) ++ continue; ++ ++ if (cap_task->stop_flag) { ++ count++; ++ continue; ++ } ++ ++ pcap_task_spin_lock(cap_task); ++ if (!cap_task->driver.stop_flag) { ++ ret = pcap_task_driver_stop(cap_task); ++ if (ret != 0) { ++ fail_task_batch->task_array[fail_task_batch->count] = cap_task; ++ fail_task_batch->count++; ++ pcap_task_spin_unlock(cap_task); ++ continue; ++ } ++ cap_task->driver.stop_flag = true; ++ } ++ cap_task->stop_flag = true; ++ pcap_task_spin_unlock(cap_task); ++ count++; ++ } ++ ++ return count; ++} ++ ++static void ++pcap_task_stop_set(uint32_t pcap_id, struct pcap_stop_task_ctl *stop_ctl) ++{ ++ int ret; ++ struct pcap_task_t *dst_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ dst_task = pcap_task_find_no_lock(pcap_id, &stop_ctl->index); ++ if (!dst_task) ++ return; ++ ++ stop_ctl->task = dst_task; ++ pcap_task_spin_lock(dst_task); ++ if (!dst_task->driver.stop_flag) { ++ ret = pcap_task_driver_stop(dst_task); ++ if (ret != 0) { ++ stop_ctl->result = -1; ++ pcap_task_spin_unlock(dst_task); ++ return; ++ } ++ } ++ dst_task->driver.stop_flag = true; ++ dst_task->stop_flag = true; ++ pcap_task_spin_unlock(dst_task); ++ ++ pcap_task_mgr_spin_lock(); ++ if (dst_task->ref_cnt <= 1) { ++ task_mgr->cap_task_list[stop_ctl->index] = NULL; ++ stop_ctl->is_stopped = true; ++ task_mgr->task_cnt--; ++ } ++ pcap_task_mgr_spin_unlock(); ++ ++ return; ++} ++ ++static uint32_t ++pcap_stopped_vf_tasks_select(uint16_t vport_id, struct pcap_task_batch *stoped_task_batch, ++ struct pcap_task_batch *not_stopped_task_batch) ++{ ++ int i; ++ uint32_t remain_cnt; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ pcap_task_mgr_spin_lock(); ++ if (task_mgr->task_cnt == 0) { ++ pcap_task_mgr_spin_unlock(); ++ return 0; ++ } ++ ++ remain_cnt = 0; ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->pcap_port.hinic3_port_id != vport_id) ++ continue; ++ ++ if (!cap_task->stop_flag) ++ continue; ++ ++ if (cap_task->ref_cnt > 1) { ++ not_stopped_task_batch->task_array[not_stopped_task_batch->count] = cap_task; ++ not_stopped_task_batch->count++; ++ remain_cnt++; ++ continue; ++ } ++ ++ stoped_task_batch->task_array[stoped_task_batch->count] = cap_task; ++ stoped_task_batch->count++; ++ task_mgr->cap_task_list[i] = NULL; ++ task_mgr->task_cnt--; ++ } ++ ++ pcap_task_mgr_spin_unlock(); ++ return remain_cnt; ++} ++ ++static uint32_t ++pcap_stopped_tasks_select(uint32_t port_no, struct pcap_task_batch *stoped_task_batch, ++ struct pcap_task_batch *not_stopped_task_batch) ++{ ++ int i; ++ uint32_t remain_cnt; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ pcap_task_mgr_spin_lock(); ++ if (task_mgr->task_cnt == 0) { ++ pcap_task_mgr_spin_unlock(); ++ return 0; ++ } ++ ++ remain_cnt = 0; ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ cap_task = task_mgr->cap_task_list[i]; ++ if (!cap_task) ++ continue; ++ ++ if (cap_task->pcap_port.odp_port_no != port_no) ++ continue; ++ ++ if (!cap_task->stop_flag) ++ continue; ++ ++ if (cap_task->ref_cnt > 1) { ++ not_stopped_task_batch->task_array[not_stopped_task_batch->count] = cap_task; ++ not_stopped_task_batch->count++; ++ remain_cnt++; ++ continue; ++ } ++ ++ stoped_task_batch->task_array[stoped_task_batch->count] = cap_task; ++ stoped_task_batch->count++; ++ task_mgr->cap_task_list[i] = NULL; ++ task_mgr->task_cnt--; ++ } ++ ++ pcap_task_mgr_spin_unlock(); ++ return remain_cnt; ++} ++ ++static void ++pcap_task_stopped_check(struct pcap_stop_task_ctl *stop_ctl) ++{ ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ pcap_task_mgr_spin_lock(); ++ ++ if (stop_ctl->task->ref_cnt > 1) { ++ pcap_task_mgr_spin_unlock(); ++ return; ++ } ++ ++ stop_ctl->is_stopped = true; ++ task_mgr->cap_task_list[stop_ctl->index] = NULL; ++ task_mgr->task_cnt--; ++ pcap_task_mgr_spin_unlock(); ++ return; ++} ++ ++int ++pcap_task_add(const struct pcap_port_t *port_info, struct pcap_key_t *pcap_key, uint32_t *pcap_id, ++ struct ds *save_param) ++{ ++ int i; ++ int ret; ++ struct pcap_task_t *cap_task = NULL; ++ struct pcap_task_mgr_t *task_mgr = pcap_get_task_mgr(); ++ ++ cap_task = pcap_task_create(pcap_key, save_param); ++ if (!cap_task) ++ return -1; ++ ++ cap_task->pcap_port = *port_info; ++ *pcap_id = cap_task->pcap_id; ++ ++ ret = pcap_task_driver_start(cap_task); ++ if (ret != 0) { ++ pcap_task_destroy(cap_task); ++ return -1; ++ } ++ ++ pcap_task_mgr_spin_lock(); ++ for (i = 0; i < PCAP_MAX_CAP_TASK; i++) { ++ if (task_mgr->cap_task_list[i] == NULL) { ++ task_mgr->cap_task_list[i] = cap_task; ++ task_mgr->task_cnt++; ++ break; ++ } ++ } ++ pcap_task_mgr_spin_unlock(); ++ return 0; ++} ++ ++int ++pcap_task_delete_all(uint32_t port_no, struct ds *ds) ++{ ++ bool flag = false; ++ uint64_t start_tsc; ++ uint32_t remain_cnt; ++ struct pcap_task_batch stopped_task_batch; ++ struct pcap_task_batch not_stopped_task_batch; ++ struct pcap_task_batch stop_fail_task_batch; ++ ++ pcap_task_batch_init(&stop_fail_task_batch); ++ remain_cnt = pcap_all_tasks_stop_set(port_no, &stop_fail_task_batch); ++ if (remain_cnt == 0) { ++ if (stop_fail_task_batch.count == 0) { ++ hinic3_ds_put_format(ds, "%sPort isn't in packet capture.\n", HINIC3_UI_LEADING_SIGN_WARNING); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%sAll capture tasks stop fail.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ pcap_task_batch_reply_format(&stop_fail_task_batch, "fail", ds); ++ return -1; ++ } ++ ++ start_tsc = rte_rdtsc(); ++ while (true) { ++ rte_delay_ms(PCAP_STOP_CHECK_PERIOD_MS); ++ ++ pcap_task_batch_init(&stopped_task_batch); ++ pcap_task_batch_init(¬_stopped_task_batch); ++ remain_cnt = pcap_stopped_tasks_select(port_no, &stopped_task_batch, ¬_stopped_task_batch); ++ pcap_task_batch_destroy(&stopped_task_batch, ds); ++ if (remain_cnt == 0) { ++ pcap_task_batch_reply_format(&stop_fail_task_batch, "fail", ds); ++ break; ++ } ++ ++ flag = pcap_timeout_check(start_tsc, PCAP_STOP_ALL_TIME_OUT_MS); ++ if (flag) { ++ pcap_task_batch_reply_format(¬_stopped_task_batch, "timeout", ds); ++ pcap_task_batch_reply_format(&stop_fail_task_batch, "fail", ds); ++ hinic3_ds_put_format(ds, "%sSome capture tasks stop timeout, please try again later.\n", ++ HINIC3_UI_LEADING_SIGN_INFO); ++ return 0; ++ } ++ } ++ ++ return 0; ++} ++ ++int ++pcap_task_delete_one(uint32_t pcap_id, struct ds *ds) ++{ ++ bool flag = false; ++ uint64_t start_tsc; ++ struct pcap_stop_task_ctl stop_ctl; ++ ++ stop_ctl.task = NULL; ++ stop_ctl.is_stopped = false; ++ stop_ctl.result = 0; ++ pcap_task_stop_set(pcap_id, &stop_ctl); ++ if (!stop_ctl.task) { ++ hinic3_ds_put_format(ds, "%sCapture task of pcap id %u not found.\n", HINIC3_UI_LEADING_SIGN_INFO, pcap_id); ++ return -1; ++ } ++ if (stop_ctl.result != 0) { ++ hinic3_ds_put_format(ds, "%sCapture task of pcap id %u stopped fail, please try again later.\n", ++ HINIC3_UI_LEADING_SIGN_FAILURE, pcap_id); ++ return -1; ++ } ++ ++ if (stop_ctl.is_stopped) { ++ hinic3_ds_put_format(ds, "%s\n", HINIC3_UI_LEADING_SIGN_INFO); ++ pcap_task_stop_reply_format(stop_ctl.task, ds); ++ pcap_task_destroy(stop_ctl.task); ++ return 0; ++ } ++ ++ start_tsc = rte_rdtsc(); ++ while (true) { ++ rte_delay_ms(PCAP_STOP_CHECK_PERIOD_MS); ++ ++ pcap_task_stopped_check(&stop_ctl); ++ if (stop_ctl.is_stopped) { ++ hinic3_ds_put_format(ds, "%s\n", HINIC3_UI_LEADING_SIGN_INFO); ++ pcap_task_stop_reply_format(stop_ctl.task, ds); ++ pcap_task_destroy(stop_ctl.task); ++ break; ++ } ++ ++ flag = pcap_timeout_check(start_tsc, PCAP_STOP_TIME_OUT_MS); ++ if (flag) { ++ hinic3_ds_put_format(ds, "%sWait pcap id %u stop timeout, please try again later.\n", ++ HINIC3_UI_LEADING_SIGN_FAILURE, pcap_id); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++void ++pcap_task_stop_as_eth_port_del(uint16_t vport_id) ++{ ++ bool flag = false; ++ uint64_t start_tsc; ++ uint32_t remain_cnt; ++ struct pcap_task_batch stopped_task_batch; ++ struct pcap_task_batch not_stopped_task_batch; ++ struct pcap_task_batch stop_fail_task_batch; ++ ++ HINIC3_LOG(INFO, AGENT, "to stop capture task on vport_id is %u, as this port will be deleted.", vport_id); ++ if (vport_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, AGENT, "pcap_task_stop_as_port_del, vport_id is invalid!"); ++ return; ++ } ++ ++ pcap_task_batch_init(&stop_fail_task_batch); ++ remain_cnt = pcap_all_vf_tasks_stop_set(vport_id, &stop_fail_task_batch); ++ if (remain_cnt == 0) { ++ if (stop_fail_task_batch.count > 0) ++ HINIC3_LOG(INFO, AGENT, "some capture task stop fail, count is %d", stop_fail_task_batch.count); ++ return; ++ } ++ ++ start_tsc = rte_rdtsc(); ++ while (true) { ++ rte_delay_ms(PCAP_STOP_CHECK_PERIOD_MS); ++ ++ pcap_task_batch_init(&stopped_task_batch); ++ pcap_task_batch_init(¬_stopped_task_batch); ++ remain_cnt = pcap_stopped_vf_tasks_select(vport_id, &stopped_task_batch, ¬_stopped_task_batch); ++ pcap_task_batch_destroy_raw(&stopped_task_batch); ++ if (remain_cnt == 0) ++ break; ++ ++ flag = pcap_timeout_check(start_tsc, PCAP_STOP_ALL_TIME_OUT_MS); ++ if (flag) { ++ HINIC3_LOG(ERR, AGENT, "stop some capture tasks timeout."); ++ break; ++ } ++ } ++ ++ return; ++} ++ ++void ++pcap_switch_set(int value) ++{ ++ g_cap_switch = value; ++} ++ ++void * ++pcap_thread_main(void *arg) ++{ ++ enum check_thread_item_type check_thread = CAPTURE_THREAD; ++ long long start = hinic3_time_msec(); ++ ++ for (;;) { ++ start = hinic3_thread_signal_increase(start, check_thread, HINIC3_CAPTURE_THREAD_SIGNAL_INCREASE_INTER); ++ ++ if (g_cap_task_save.thread_exit == PCAP_THREAD_EXIT_STATUS) ++ break; ++ ++ if (pcap_get_cap_switch() == 0) { ++ usleep(PCAP_SIEEP_TIME); ++ continue; ++ } ++ ++ pcap_hook_rx_pre(); ++ } ++ ++ return 0; ++} ++ ++void ++hinic3_stop_pcap_threads(void) ++{ ++ if (g_cap_task_save.thread != 0) { ++ g_cap_task_save.thread_exit = PCAP_THREAD_EXIT_STATUS; ++ pthread_join(g_cap_task_save.thread, NULL); ++ } ++} ++ ++struct pcap_task_save_t * ++hinic3_get_cap_task_save(void) ++{ ++ return &g_cap_task_save; ++} ++ ++void ++hinic3_set_ticks_per_ms(uint64_t value) ++{ ++ g_ticks_per_ms = value; ++} ++ ++struct rte_mempool ** ++hinic3_get_pcap_shared_mp(void) ++{ ++ return &g_pcap_shared_mp; ++} +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h +new file mode 100644 +index 0000000..7477896 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h +@@ -0,0 +1,281 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_CAPTURE_UTILS_H ++#define HINIC3_CAPTURE_UTILS_H ++ ++#include ++#include ++ ++#include "rte_ether.h" ++#include "rte_mempool.h" ++#include "rte_spinlock.h" ++#include "rte_ring.h" ++#include "hinic3_list.h" ++ ++#include "hinic3_command.h" ++#include "hinic3_message.h" ++#include "hinic3_ds.h" ++ ++#define PCAP_MAX_FILE_NAME 256 ++#define PCAP_MAX_RING_NAME 32 ++#define PCAP_MAX_PORT_NAME 32 ++#define PCAP_MAX_PORT_COMBINE_NAME 64 ++ ++#define PCAP_MAX_CAP_TASK 4 ++#define PCAP_EPOLL_SIZE 1024 ++#define PCAP_DUMP_SIZE 160 ++#define PCAP_MEMPOOL_SIZE (8192 * 10) ++#define PCAP_RING_SIZE 8192 ++#define PCAP_EPOLL_TIMEOUT (20 * 1000) ++ ++#define PCAP_TIME_S_TO_MS 1000 ++#define PCAP_SIEEP_TIME 1000 ++ ++#define PCAP_CMD_MIN_PARAM 1 ++#define PCAP_CMD_MAX_PARAM 32 ++#define PCAP_CMD_START_MIN_PARAM 3 ++#define PCAP_CMD_START_MAX_PARAM 31 ++#define PCAP_CMD_STOP_MIN_PARAM 1 ++#define PCAP_CMD_STOP_MAX_PARAM 2 ++#define PCAP_CMD_SHOW_MIN_PARAM 1 ++#define PCAP_CMD_SHOW_MAX_PARAM 2 ++ ++#define PCAP_STOP_CHECK_PERIOD_MS 5 ++#define PCAP_STOP_TIME_OUT_MS (10 * 1000) ++#define PCAP_STOP_ALL_TIME_OUT_MS (30 * 1000) ++ ++#define PCAP_IPV4_MAX_MASK_LEN 32 ++#define PCAP_IPV6_MAX_MASK_LEN 128 ++ ++#define PCAP_MAX_RULE_NUM 255 ++ ++#define PCAP_PROBE_DISABLE 0 ++#define PCAP_PROBE_ENABLE 1 ++#define PCAP_THREAD_NORMAL_STATUS 0 ++#define PCAP_THREAD_EXIT_STATUS 1 ++ ++#define CPU_MAX_NUMBER 23U ++ ++#define PCAP_MEMPOOL_NAME "hinic3-pcap-save-mp:" ++#define PCAP_SAVE_THREAD_NAME "pcap-save-thread" ++#define PCAP_RING_NAME_PREFIX "hinic3-pcap-ring" ++ ++enum pcap_write_way { ++ WRITE_BY_PMD = 0, ++ WRITE_BY_SEP_THREAD ++}; ++ ++enum pcap_ip_type { ++ PCAP_IP_ADDR_V4 = 1, ++ PCAP_IP_ADDR_V6 ++}; ++ ++enum PCAP_PKT_MEM_TYPE { ++ PCAP_PKT_MEM_REUSED = 1, ++ PCAP_PKT_MEM_MALLOC ++}; ++ ++struct pcap_ip_t { ++ union { ++ uint32_t ip4; ++ struct in6_addr ip6; ++ }; ++}; ++ ++struct input_key { ++ uint8_t dmac[HINIC3_ETH_ADDR_LEN]; /* Destination MAC address */ ++ uint8_t smac[HINIC3_ETH_ADDR_LEN]; /* Source MAC address */ ++ uint16_t eth_type; ++ struct pcap_ip_t sip; ++ struct pcap_ip_t dip; /* Destination IP address, network order */ ++ uint8_t ip_proto; ++ uint16_t vlan_id; ++ uint16_t sport; ++ uint16_t dport; ++ bool is_vxlan; ++ uint8_t port_id; ++ uint8_t icmp_type; ++ uint8_t icmp_code; ++ uint16_t icmp_id; ++ uint32_t vni; ++ rte_be16_t inner_type; ++}; ++ ++struct pcap_key_t { ++ uint32_t flags; ++ uint64_t count_total; ++ char filename[PCAP_MAX_FILE_NAME]; ++ uint32_t ip_type; ++ struct pcap_ip_t sip; ++ struct pcap_ip_t dip; ++ struct pcap_ip_t host_ip; ++ uint16_t sport; ++ uint16_t dport; ++ uint32_t vxlan_vni; ++ uint8_t sip_masklen; ++ uint8_t dip_masklen; ++ uint8_t host_masklen; ++ uint8_t smac[RTE_ETHER_ADDR_LEN]; ++ uint8_t dmac[RTE_ETHER_ADDR_LEN]; ++ uint16_t eth_type; ++ uint8_t ip_proto; ++ uint8_t direction; ++ uint16_t vlan_id; ++ bool vxlan_inner; ++ uint32_t port_id; ++ uint8_t icmp_type; ++ uint8_t icmp_code; ++ uint16_t icmp_id; ++ bool is_vxlan; ++ rte_be16_t inner_type; ++ enum pcap_write_way write_way; ++}; ++ ++struct pcap_stats_t { ++ uint64_t wr_cnt; ++ uint64_t en_ring_fail_cnt; ++ uint64_t soft_drop_cnt; ++ struct hinic3_pcap_probe_stats hinic3_stats; ++}; ++ ++struct pcap_file_record_hdr { ++ uint32_t pkt_ts_sec; ++ uint32_t pkt_ts_usec; ++ uint32_t pkt_incl_len; ++ uint32_t pkt_orig_len; ++}; ++ ++struct pcap_driver_t { ++ bool stop_flag; ++ struct hinic3_pcap_probe_filter_t driver_filter; ++ struct hinic3_pcap_probe_rule_q_map queue_info; ++}; ++ ++struct pcap_task_mirror_t { ++ bool stop_flag; ++ bool wr_fail_flag; ++ uint64_t remain_count; ++}; ++ ++struct pcap_port_t { ++ char name[PCAP_MAX_PORT_NAME]; ++ bool support_cap; ++ uint32_t odp_port_no; ++ uint16_t hinic3_port_id; ++}; ++ ++struct pcap_task_t { ++ struct pcap_key_t key; ++ struct pcap_stats_t stats; ++ struct pcap_driver_t driver; ++ ++ bool stop_flag; ++ bool wr_fail_flag; ++ uint32_t pcap_id; ++ uint64_t remain_count; ++ ++ int event_fd; ++ FILE *save_file; ++ struct rte_ring *ring; ++ ++ rte_spinlock_t lock; ++ uint32_t ref_cnt; ++ uint32_t rule_idx; ++ char *parameter; ++ struct pcap_port_t pcap_port; ++}; ++ ++struct pcap_task_mgr_t { ++ rte_spinlock_t lock; ++ uint32_t task_cnt; ++ pthread_t save_thread; ++ bool thread_exit; ++ int epoll_fd; ++ struct rte_mempool *mem_pool; ++ struct pcap_task_t *cap_task_list[PCAP_MAX_CAP_TASK]; ++}; ++ ++struct pcap_task_save_t { ++ pthread_t thread; ++ bool thread_exit; ++}; ++ ++struct pcap_task_batch { ++ int count; ++ struct pcap_task_t *task_array[PCAP_MAX_CAP_TASK]; ++}; ++ ++struct pcap_cmd_t { ++ char *cmd; ++ char *usage; ++ unixctl_cb_func *cb; ++ int min_args; ++ int max_args; ++ char *desc; ++}; ++ ++struct pcap_start_param { ++ struct pcap_port_t port_info; ++ struct pcap_key_t pcap_key; ++}; ++ ++struct pcap_stop_param { ++ uint32_t port_no; ++ uint32_t pcap_id; ++}; ++ ++struct pcap_show_param { ++ bool is_all; ++ uint32_t pcap_id; ++}; ++ ++struct pcap_stop_task_ctl { ++ bool is_stopped; ++ int result; ++ uint32_t index; ++ struct pcap_task_t *task; ++}; ++ ++struct pcap_save_stats_t { ++ bool write_fail; ++ uint32_t wr_iov_cnt; ++ uint32_t wr_cnt; ++ uint32_t en_ring_fail_cnt; ++ uint32_t parse_fail_cnt; ++}; ++ ++static inline void pcap_task_batch_init(struct pcap_task_batch *task_batch) ++{ ++ task_batch->count = 0; ++} ++ ++struct pcap_task_save_t *hinic3_get_cap_task_save(void); ++struct rte_mempool **hinic3_get_pcap_shared_mp(void); ++void hinic3_set_ticks_per_ms(uint64_t value); ++bool pcap_check_file_used_no_lock(struct pcap_key_t *cap_key); ++int pcap_get_cap_switch(void); ++struct pcap_task_mgr_t* pcap_get_task_mgr(void); ++void pcap_port_tasks_get(struct pcap_task_batch *task_batch, struct pcap_port_t *port_mirror); ++int pcap_port_tasks_count_no_lock(uint32_t port_no); ++int pcap_port_info_get_by_name(char *port_name, struct pcap_port_t *port_info, struct ds *ds); ++void pcap_switch_set(int value); ++int pcap_task_add(const struct pcap_port_t *port_info, struct pcap_key_t *pcap_key, uint32_t *pcap_id, ++ struct ds *save_param); ++void pcap_task_batch_put(struct pcap_task_batch *task_batch); ++int pcap_task_delete(struct pcap_stop_param *param, struct ds *ds); ++int pcap_task_delete_all(uint32_t port_no, struct ds *ds); ++int pcap_task_delete_one(uint32_t pcap_id, struct ds *ds); ++struct pcap_task_t* pcap_task_find_no_lock(uint32_t pcap_id, uint32_t *index); ++struct pcap_task_t* pcap_task_get_by_id(uint32_t pcap_id, struct pcap_task_mirror_t *task_mirror); ++void pcap_task_mgr_spin_lock(void); ++void pcap_task_mgr_spin_unlock(void); ++void pcap_task_mirror_get(struct pcap_task_t *cap_task, struct pcap_task_mirror_t *task_mirror); ++void pcap_task_put(struct pcap_task_t *cap_task); ++void pcap_task_spin_lock(struct pcap_task_t *task); ++void pcap_task_spin_unlock(struct pcap_task_t *task); ++void pcap_task_stats_update(struct pcap_task_t *cap_task, struct pcap_save_stats_t *save_stats); ++void *pcap_thread_main(void *arg); ++ ++#endif /* HINIC3_CAPTURE_UTILS_H */ +diff --git a/drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c b/drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c +new file mode 100644 +index 0000000..6c5a52d +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c +@@ -0,0 +1,278 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_agent.h" ++#include "hinic3_ui_string.h" ++ ++#define COMMAND_CTL_LOCATION "/opt/dpak/dpak_ovs_command.ctl" ++#define MAX_UN_LEN (sizeof(((struct sockaddr_un *)0)->sun_path) - 1) ++#define HINIC3_COMMAND_LACK_PARA_ERROR "dpak-ovs-ctl: at least one non-option argument is required (use -h for help)" ++#define HINIC3_NOT_SUPPORT_OPTION "this option is not supported (use -h for help)" ++#define HINIC3_CONNECTION_FAILED_ERROR "The connection to the server cannot be established." ++#define HINIC3_TIMEOUT_ERROR "Command execution timed out." ++#define HINIC3_EXECUTION_ERROR "Command server does not return the correct result." ++#define HINIC3_FOPEN_ERROR "fdopen operation failed" ++#define HINIC3_COMMAND_LENGTH_ERROR "The command is too long." ++#define HINIC3_FLUSH_PORT_WARNING_CONTINUE \ ++ "Warning: flush-ports may cuase port statistics on vSwitch to jump, Continue? [Y/N]" ++ ++#define COMMAND_OPTION_MATCH 1 ++#define MIN_COMMAND_NUM 2 ++#define MAX_COMMAND_LENGTH 512 ++#define MAX_REPLY_BUFFER_SIZE 1000 ++#define CONNECT_FAILED_TIMEOUT 10 ++#define RETRY_TIMES 3 ++#define HINIC3_DEFAULT_MAJOR_VERSION_STRING "(null)" ++#define HINIC3_DEFAULT_SUB_VERSION_STRING "(null)" ++ ++#ifdef BUILD_MAJOR_VERSION ++#define HINIC3_BUILD_MAJOR_VERSION BUILD_MAJOR_VERSION ++#else ++#define HINIC3_BUILD_MAJOR_VERSION HINIC3_DEFAULT_MAJOR_VERSION_STRING ++#endif ++ ++#ifdef BUILD_SUB_VERSION ++#define HINIC3_BUILD_SUB_VERSION BUILD_SUB_VERSION ++#else ++#define HINIC3_BUILD_SUB_VERSION HINIC3_DEFAULT_SUB_VERSION_STRING ++#endif ++ ++enum command_error { ++ TIMEOUT_ERROR = -2, ++ EXECUTION_ERROR = -3, ++}; ++ ++static void ++hinic3_show_command_version_info(void) ++{ ++ printf("%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_COMPONENT_NAME); ++ printf("%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_COMMAND_FEATURE_NAME); ++ printf("%2s%s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_COMPONENT_VERSION, HINIC3_BUILD_MAJOR_VERSION); ++ return; ++} ++ ++static void ++hinic3_show_command_help_info(void) ++{ ++ printf("%2sUsage: ", HINIC3_UI_INDENT_SPACE); ++ printf("dpak-ovs-ctl COMMAND [ARG...]\n\n"); ++ printf("%2sCommon commands:\n", HINIC3_UI_INDENT_SPACE); ++ printf("%4s%-30sList the commands supported by dpak-ovs\n\n", HINIC3_UI_INDENT_SPACE, "list-commands"); ++ printf("%2sOther options:\n", HINIC3_UI_INDENT_SPACE); ++ printf("%4s%-30sDisplay the dpak-ovs-ctl version information\n", HINIC3_UI_INDENT_SPACE, "-v"); ++ printf("%4s%-30sDisplay the help information\n", HINIC3_UI_INDENT_SPACE, "-h, --help"); ++} ++ ++static int ++hinic3_client_make_sockaddr_un(const char *name, struct sockaddr_un *un) ++{ ++ size_t max_size = sizeof(un->sun_path); ++ size_t len = strnlen(name, max_size - 1); ++ memcpy(un->sun_path, name, len); ++ un->sun_path[len] = '\0'; ++ un->sun_family = AF_UNIX; ++ return 0; ++} ++ ++static int ++hinic3_connect_to_target(const char *connect_path) ++{ ++ int ret; ++ int fd; ++ struct sockaddr_un un; ++ struct timeval timeo = {CONNECT_FAILED_TIMEOUT, 0}; ++ ++ fd = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (fd < 0) ++ return -1; ++ ++ setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(struct timeval)); ++ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(struct timeval)); ++ ret = hinic3_client_make_sockaddr_un(connect_path, &un); ++ if (ret != 0) { ++ close(fd); ++ return -1; ++ } ++ ret = connect(fd, (struct sockaddr *)&un, sizeof(struct sockaddr_un)); ++ if (ret != 0) { ++ close(fd); ++ return -1; ++ } ++ return fd; ++} ++ ++static int ++hinic3_client_send_command(FILE *file, int argc, char *agrv[]) ++{ ++ uid_t uid = getuid(); ++ struct passwd *pw = getpwuid(uid); ++ if (pw == NULL) { ++ printf("%sgetpwuid error, uid is %u(errno=%d).\n", HINIC3_UI_LEADING_SIGN_FAILURE, uid, errno); ++ return -1; ++ } ++ int ret = fprintf(file, "%s", pw->pw_name); ++ if (ret <= 0) { ++ printf("fprintf error.\n"); ++ return -1; ++ } ++ (void)fputs(" ", file); ++ for (int i = 0; i < argc; i++) { ++ (void)fputs(agrv[i], file); ++ ++ if (i + 1 != argc) { ++ (void)fputs(" ", file); ++ } ++ } ++ (void)fputs("\n", file); ++ (void)fflush(file); ++ return 0; ++} ++ ++static int ++hinic3_client_print_response(FILE *file) ++{ ++ int res = TIMEOUT_ERROR; ++ char resp_buff[MAX_REPLY_BUFFER_SIZE] = { 0 }; ++ bool is_result = true; ++ bool exit_cond = false; ++ do { ++ char *result = fgets(resp_buff, sizeof(resp_buff) - 1, file); ++ if (result == NULL) { ++ exit_cond = true; ++ break; ++ } ++ if (is_result) { ++ if (strcmp(result, "0\n") == 0) { ++ res = 0; ++ } else if (strcmp(result, "-1\n") == 0) { ++ res = -1; ++ } else { ++ return EXECUTION_ERROR; ++ } ++ is_result = false; ++ } else { ++ printf("%s", resp_buff); ++ memset(resp_buff, 0, MAX_REPLY_BUFFER_SIZE); ++ } ++ } while (!exit_cond); ++ return res; ++} ++ ++int ++hinic3_get_confirm(const char *warningInfo) ++{ ++ char buf[MAX_COMMAND_LENGTH + 1] = {0}; ++ int ch; ++ for (int i = 0; i < RETRY_TIMES; i++) { ++ printf("%s", warningInfo); ++ if (fgets(buf, MAX_COMMAND_LENGTH + 1, stdin) == NULL) ++ continue; ++ if (strcmp(buf, "Y\n") == 0 || strcmp(buf, "y\n") == 0) ++ return 0; ++ if (strcmp(buf, "N\n") == 0 || strcmp(buf, "n\n") == 0) ++ return -1; ++ if (strlen(buf) >= MAX_COMMAND_LENGTH) ++ while ((ch = getchar()) != (int)'\n' && ch != EOF) {}; ++ } ++ return -1; ++} ++ ++static int ++hinic3_check_client_args(int argc, char *argv[]) ++{ ++ int length = 0; ++ for (int i = 0; i < argc; i++) { ++ length += strlen(argv[i]); ++ } ++ if (length > MAX_COMMAND_LENGTH) { ++ printf("%s%s\n", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_COMMAND_LENGTH_ERROR); ++ return -1; ++ } ++ if (argv[MIN_COMMAND_NUM - 1][0] == '-') { ++ if ((strcmp(argv[MIN_COMMAND_NUM - 1], "-h") == 0) || (strcmp(argv[MIN_COMMAND_NUM - 1], "--help") == 0)) { ++ (void)hinic3_show_command_help_info(); ++ return COMMAND_OPTION_MATCH; ++ } else if (strcmp(argv[MIN_COMMAND_NUM - 1], "-v") == 0) { ++ (void)hinic3_show_command_version_info(); ++ return COMMAND_OPTION_MATCH; ++ } else { ++ printf("%s%s\n", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_NOT_SUPPORT_OPTION); ++ return -1; ++ } ++ } ++ if (strcmp(argv[MIN_COMMAND_NUM - 1], "hwoff/flush-ports") == 0 && ++ strcmp(argv[argc - 1], "-h") != 0 && strcmp(argv[argc - 1], "--help") != 0) { ++ if (hinic3_get_confirm(HINIC3_FLUSH_PORT_WARNING_CONTINUE) == -1) { ++ printf("%sUser not confirmed, exit command.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ int fd; ++ FILE *file = NULL; ++ int ret; ++ ++ if (argc < MIN_COMMAND_NUM) { ++ printf("%s%s\n", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_COMMAND_LACK_PARA_ERROR); ++ return -1; ++ } ++ ++ ret = hinic3_check_client_args(argc, argv); ++ if (ret == COMMAND_OPTION_MATCH) ++ return 0; ++ if (ret == -1) ++ return -1; ++ ++ fd = hinic3_connect_to_target(COMMAND_CTL_LOCATION); ++ if (fd < 0) { ++ printf("%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_CONNECTION_FAILED_ERROR); ++ return -1; ++ } ++ ++ file = fdopen(fd, "a+"); ++ if (file == NULL) { ++ printf("%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_FOPEN_ERROR); ++ close(fd); ++ return -1; ++ } ++ ++ ret = hinic3_client_send_command(file, argc - 1, argv + 1); ++ if (ret != 0) ++ return -1; ++ ++ ret = hinic3_client_print_response(file); ++ if (ret != 0) { ++ if (ret == -1) { ++ goto fail; ++ } else if (ret == EXECUTION_ERROR) { ++ printf("%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_EXECUTION_ERROR); ++ goto fail; ++ } else { ++ printf("%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_TIMEOUT_ERROR); ++ goto fail; ++ } ++ } ++ (void)fclose(file); ++ (void)close(fd); ++ return 0; ++fail: ++ (void)fclose(file); ++ (void)close(fd); ++ return -1; ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c +new file mode 100644 +index 0000000..47d04fd +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c +@@ -0,0 +1,74 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_key_query.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_vf_dfx.h" ++#include "hinic3_dfx_port.h" ++#include "hinic3_init.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_util.h" ++#include "hinic3_log.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_command.h" ++#include "hinic3_log.h" ++#include "hinic3_check_thread_health_state.h" ++#include "hinic3_agent_cmd_time.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_ds.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_flow_dump_public.h" ++#include "hinic3_age_delete_flow.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_agent_flow_cmd_dump.h" ++#include "hinic3_cmd_error_stats.h" ++#include "hinic3_cmd_version.h" ++#include "hinic3_cmd_forward.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_cmd_meminfo.h" ++ ++#define HINIC3_BATCH_BOLCK_NUM 128 ++#define HINIC3_DUMP_BATCH_MIN_ARGC 1 ++#define HINIC3_DUMP_BATCH_MAX_ARGC 2 ++#define HINIC3_AGENT_DUMP_IDLE_SLEEP 1 ++ ++static void ++unixctl_hinic3_agent_cmd_init(void) ++{ ++ hinic3_command_register("hwoff/show-sample-session", "", 0, 0, hinic3_show_sample_session, NULL); ++} ++static void ++unixctl_common_cmd_register(void) ++{ ++ hinic3_command_register("hwoff/show-hmap-flow-num", "", 0, 0, hinic3_dump_hmap_flow_num, NULL); ++} ++ ++void ++hinic3_agent_cmd_init(void) ++{ ++ unixctl_hinic3_cmd_error_stats_register(); ++ unixctl_hinic3_cmd_version_register(); ++ unixctl_hinic3_cmd_forward_register(); ++ unixctl_hinic3_cmd_exec_register(); ++ unixctl_hinic3_cmd_meminfo_register(); ++ unixctl_hinic3_cmd_log_register(); ++ ++ unixctl_hinic3_flow_cmd_init(); ++ unixctl_hinic3_flow_dump_cmd_init(); ++ unixctl_vf_dfx_init(); ++ unixctl_hinic3_port_cmd_init(); ++ unixctl_hinic3_agent_cmd_init(); ++ unixctl_hinic3_trace_flow_init(); ++ unixctl_thread_status_dfx_init(); ++ unixctl_common_cmd_register(); ++ unixctl_hinic3_query_cmd_init(); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.h +new file mode 100644 +index 0000000..3986d7a +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.h +@@ -0,0 +1,19 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_AGENT_CMD_H ++#define HINIC3_AGENT_CMD_H ++ ++#include "hinic3_command.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++void hinic3_agent_cmd_init(void); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c +new file mode 100644 +index 0000000..c72f3e6 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c +@@ -0,0 +1,527 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_util.h" ++#include "hinic3_eth_packets.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_packets_types.h" ++#include "hinic3_ds.h" ++#include "hinic3_packets.h" ++#include "hinic3_string_util.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_agent_flow_cmd_dump.h" ++#include "hinic3_flow_agent.h" ++ ++static char *g_ct_tcp_state_str[] = { ++ [HINIC3_TCP_STATE_TYPE_CLOSED] = HINIC3_UI_TCP_STATE_TYPE_CLOSE_STR, ++ [HINIC3_TCP_STATE_TYPE_LISTEN] = HINIC3_UI_TCP_STATE_TYPE_LISTEN_STR, ++ [HINIC3_TCP_STATE_TYPE_SYN_SENT] = HINIC3_UI_TCP_STATE_TYPE_SYN_SENT_STR, ++ [HINIC3_TCP_STATE_TYPE_SYN_RECV] = HINIC3_UI_TCP_STATE_TYPE_SYN_RECV_STR, ++ [HINIC3_TCP_STATE_TYPE_ESTABLISHED] = HINIC3_UI_TCP_STATE_TYPE_ESTABLISHED_STR, ++ [HINIC3_TCP_STATE_TYPE_CLOSE_WAIT] = HINIC3_UI_TCP_STATE_TYPE_CLOSE_WAIT_STR, ++ [HINIC3_TCP_STATE_TYPE_FIN_WAIT_1] = HINIC3_UI_TCP_STATE_TYPE_FIN_WAIT_1_STR, ++ [HINIC3_TCP_STATE_TYPE_CLOSING] = HINIC3_UI_TCP_STATE_TYPE_CLOSING_STR, ++ [HINIC3_TCP_STATE_TYPE_LAST_ACK] = HINIC3_UI_TCP_STATE_TYPE_LAST_ACK_STR, ++ [HINIC3_TCP_STATE_TYPE_FIN_WAIT_2] = HINIC3_UI_TCP_STATE_TYPE_FIN_WAIT_2_STR, ++ [HINIC3_TCP_STATE_TYPE_TIME_WAIT] = HINIC3_UI_TCP_STATE_TYPE_TIME_WAIT_STR, ++}; ++ ++void ++hinic3_hw_ufid_format_output(const uint64_t *hw_ufid, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, HINIC3_HW_UFID_FMT, HINIC3_HW_UFID_ARGS(*hw_ufid)); ++} ++ ++static void ++hinic3_flow_key_format_output_src_port(const hinic3_nlattr_itr nla, uint8_t nw_protocol, struct ds *ds) ++{ ++ uint16_t u16_val = hinic3_nlattr_get_itr_u16(nla); ++ uint8_t icmp_type = (uint8_t)((u16_val & HINIC3_MID_EIGHT_BIT_MASK) >> HINIC3_BIT_MID_MOVE_INDEX); ++ uint8_t icmp_code = (uint8_t)(u16_val & HINIC3_LOW_EIGHT_BIT_MASK); ++ if (nw_protocol == IPPROTO_ICMP) { ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_ICMP_TYPE_STR, icmp_type); ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_ICMP_CODE_STR, icmp_code); ++ } else if (nw_protocol == IPPROTO_ICMPV6) { ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_ICMP6_TYPE_STR, icmp_type); ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_ICMP6_CODE_STR, icmp_code); ++ } else { ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_SRC_PORT_STR, ntohs(u16_val)); ++ } ++} ++ ++static void ++hinic3_flow_key_format_output_dst_port(const hinic3_nlattr_itr nla, uint8_t nw_protocol, struct ds *ds) ++{ ++ uint16_t u16_val = hinic3_nlattr_get_itr_u16(nla); ++ if (nw_protocol == IPPROTO_ICMP) { ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_ICMP_ID_STR, ntohs(u16_val)); ++ } else if (nw_protocol == IPPROTO_ICMPV6) { ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_ICMP6_ID_STR, ntohs(u16_val)); ++ } else { ++ hinic3_ds_put_format(ds, "%s(%hu), ", HINIC3_UI_KEY_DST_PORT_STR, ntohs(u16_val)); ++ } ++} ++ ++static void ++hinic3_flow_process_vni(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ uint32_t u32_val = hinic3_nlattr_get_itr_u32(nla); ++ hinic3_ds_put_format(ds, "%s(%u), ", HINIC3_UI_KEY_VNI_STR, ntohl(u32_val)); ++} ++ ++static void hinic3_flow_process_dl_type(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ uint16_t u16_val = hinic3_nlattr_get_itr_u16(nla); ++ hinic3_ds_put_format(ds, "%s(%04x), ", HINIC3_UI_KEY_DL_TYPE_STR, ntohs(u16_val)); ++} ++ ++static void ++hinic3_flow_process_ip(const hinic3_nlattr_itr nla, int type, struct ds *ds) ++{ ++ const char *ip_string = (type == HINIC3_FLOW_KEY_SRC_IP) ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_DST_IP_STR; ++ uint32_t u32_val; ++ u32_val = hinic3_nlattr_get_itr_u32(nla); ++ hinic3_ds_put_format(ds, "%s(" IP_FMT "), ", ip_string, IP_ARGS(u32_val)); ++} ++ ++static void ++hinic3_flow_process_ipv6(const hinic3_nlattr_itr nla, int type, struct ds *ds) ++{ ++ const char *ip_string = (type == HINIC3_FLOW_KEY_SRC_IPV6) ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_DST_IP_STR; ++ struct in6_addr *ipv6_addr = (struct in6_addr *)hinic3_nlattr_get_itr_data(nla); ++ hinic3_ds_put_format(ds, "%s(", ip_string); ++ hinic3_ipv6_format_addr(ipv6_addr, ds); ++ hinic3_ds_put_format(ds, "), "); ++} ++ ++static void ++hinic3_flow_process_vlan_vid(const hinic3_nlattr_itr nla, int type, struct ds *ds) ++{ ++ const char *vid_string = ++ (type == HINIC3_FLOW_KEY_INNER_VID) ? HINIC3_UI_KEY_INNER_VLAN_STR : HINIC3_UI_KEY_OUTER_VLAN_STR; ++ uint16_t u16_val = hinic3_nlattr_get_itr_u16(nla); ++ hinic3_ds_put_format(ds, "%s(%hu), ", vid_string, ntohs(u16_val)); ++} ++ ++static void ++hinic3_flow_process_vport(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ if (hinic3_forward_mode_get() == OVS_KEY_EXTRACT_EXTEND_MODE_7TUPLE) { ++ return; ++ } ++ uint16_t port_id = 0; ++ uint16_t ifindex = hinic3_nlattr_get_itr_u16(nla); ++ int ret = hinic3_get_port_id_by_ifindex(ntohs(ifindex), &port_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "get port_id failed, ifindex(0x%x)", ifindex); ++ hinic3_ds_put_format(ds, "%s(%s), ", HINIC3_UI_KEY_VPORT_STR, "error"); ++ return; ++ } ++ hinic3_ds_put_format(ds, "%s(%hu), %s(%hu), ", HINIC3_UI_KEY_VPORT_STR, port_id, ++ HINIC3_UI_KEY_IFINDEX_STR, ntohs(ifindex)); ++} ++ ++static void ++hinic3_flow_process_mac(const hinic3_nlattr_itr nla, int type, struct ds *ds) ++{ ++ const char *mac_string = (type == HINIC3_FLOW_KEY_SRC_MAC) ? HINIC3_UI_KEY_SRC_MAC_STR : HINIC3_UI_KEY_DST_MAC_STR; ++ uint8_t *mac = (uint8_t *)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ hinic3_ds_put_format(ds, "%s(" HINIC3_MAC_FMT "), ", mac_string, HINIC3_OUTPUT_MAC(mac)); ++} ++ ++static uint8_t ++hinic3_flow_process_nw_protocol(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ uint8_t nw_protocol = hinic3_nlattr_get_itr_u8(nla); ++ hinic3_ds_put_format(ds, "%s(%hhu), ", HINIC3_UI_KEY_NW_PROTO_STR, nw_protocol); ++ return nw_protocol; ++} ++ ++void hinic3_flow_key_format_output(const struct hinic3_nlattr *key, struct ds *ds) ++{ ++ hinic3_nlattr_itr nla = NULL; ++ uint8_t nw_protocol = 0; ++ HINIC3_NLATTR_FOR_EACH(nla, key) ++ { ++ int type = hinic3_nlattr_get_itr_type(nla); ++ switch (type) { ++ case HINIC3_FLOW_KEY_VNI: ++ hinic3_flow_process_vni(nla, ds); ++ break; ++ case HINIC3_FLOW_KEY_DL_TYPE: ++ hinic3_flow_process_dl_type(nla, ds); ++ break; ++ case HINIC3_FLOW_KEY_PROTOCOL: ++ nw_protocol = hinic3_flow_process_nw_protocol(nla, ds); ++ break; ++ case HINIC3_FLOW_KEY_SRC_IP: ++ case HINIC3_FLOW_KEY_DST_IP: ++ hinic3_flow_process_ip(nla, type, ds); ++ break; ++ case HINIC3_FLOW_KEY_SRC_IPV6: ++ case HINIC3_FLOW_KEY_DST_IPV6: ++ hinic3_flow_process_ipv6(nla, type, ds); ++ break; ++ case HINIC3_FLOW_KEY_SRC_PORT: ++ hinic3_flow_key_format_output_src_port(nla, nw_protocol, ds); ++ break; ++ case HINIC3_FLOW_KEY_DST_PORT: ++ hinic3_flow_key_format_output_dst_port(nla, nw_protocol, ds); ++ break; ++ case HINIC3_FLOW_KEY_OUTER_VID: ++ case HINIC3_FLOW_KEY_INNER_VID: ++ hinic3_flow_process_vlan_vid(nla, type, ds); ++ break; ++ case HINIC3_FLOW_KEY_IN_PORT: ++ hinic3_flow_process_vport(nla, ds); ++ break; ++ case HINIC3_FLOW_KEY_SRC_MAC: ++ case HINIC3_FLOW_KEY_DST_MAC: ++ hinic3_flow_process_mac(nla, type, ds); ++ break; ++ default: ++ break; ++ } ++ } ++} ++ ++static void ++hinic3_ct_tcp_state_format_output(struct ds *ds, uint8_t ct_tcp_state) ++{ ++ char *ct_tcp_state_name = NULL; ++ if (ct_tcp_state <= HINIC3_TCP_STATE_TYPE_TIME_WAIT) { ++ ct_tcp_state_name = g_ct_tcp_state_str[ct_tcp_state]; ++ } else { ++ ct_tcp_state_name = HINIC3_UI_TCP_STATE_TYPE_UNKNOWN_STR; ++ } ++ ++ hinic3_ds_put_cstr(ds, ct_tcp_state_name); ++} ++ ++static void ++hinic3_flow_process_ct_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ struct ds ds_state = DS_EMPTY_INITIALIZER; ++ struct hinic3_ct_tcp_state *ct_tcp_state = ++ (struct hinic3_ct_tcp_state *)hinic3_nlattr_get_itr_unspec(nla, sizeof(struct hinic3_ct_tcp_state)); ++ hinic3_ct_tcp_state_format_output(&ds_state, ct_tcp_state->state); ++ ++ hinic3_ds_put_format(ds, "%s(%s=%u, %s=%u, %s=%u, %s=%u, %s=%s), ", HINIC3_UI_KEY_CT_STR, HINIC3_UI_KEY_CT_SEQ_LOW_STR, ++ ntohl(ct_tcp_state->seqlo), HINIC3_UI_KEY_CT_SEQ_HIGH_STR, ntohl(ct_tcp_state->seqhi), ++ HINIC3_UI_KEY_CT_MAX_WIN_STR, ntohs(ct_tcp_state->max_win), HINIC3_UI_KEY_CT_SACLE_STR, ct_tcp_state->wscale, ++ HINIC3_UI_KEY_CT_STATE_STR, hinic3_ds_cstr(&ds_state)); ++ hinic3_ds_destroy(&ds_state); ++} ++ ++ ++static void ++hinic3_flow_process_vxlan_push_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ size_t size; ++ uint32_t vni; ++ struct hinic3_flow_act_vxlan_gpe_header *vxlan_header = NULL; ++ ++ size = sizeof(struct hinic3_flow_act_vxlan_gpe_header); ++ vxlan_header = (struct hinic3_flow_act_vxlan_gpe_header *)hinic3_nlattr_get_itr_unspec(nla, size); ++ vni = ntohl(vxlan_header->vxlan.vni) >> HINIC3_BYTE_BITS; ++ ++ if (vxlan_header->ip_version == HINIC3_IP_ADDR_V4) { ++ hinic3_ds_put_format(ds, ++ "%s(%s=" HINIC3_MAC_FMT ", %s=" HINIC3_MAC_FMT ", %s=" IP_FMT ", %s=" IP_FMT ", %s=%hu, %s=%hu, %s=%u, %s=%u), ", ++ HINIC3_UI_KEY_VXLAN_PUSH_STR, HINIC3_UI_KEY_DST_MAC_STR, HINIC3_OUTPUT_MAC(vxlan_header->dmac), ++ HINIC3_UI_KEY_SRC_MAC_STR, HINIC3_OUTPUT_MAC(vxlan_header->smac), HINIC3_UI_KEY_SRC_IP_STR, ++ IP_ARGS(vxlan_header->sip[0]), HINIC3_UI_KEY_DST_IP_STR, IP_ARGS(vxlan_header->dip[0]), ++ HINIC3_UI_KEY_SRC_PORT_STR, ntohs(vxlan_header->sport), HINIC3_UI_KEY_VID_STR, ++ hinic3_vlan_tci_to_vid(vxlan_header->vlan_id), HINIC3_UI_KEY_VNI_STR, vni, HINIC3_UI_KEY_DSCP_STR, ++ vxlan_header->dscp); ++ } else if (vxlan_header->ip_version == HINIC3_IP_ADDR_V6) { ++ hinic3_ds_put_format(ds, ++ "%s(%s=" HINIC3_MAC_FMT ", %s=" HINIC3_MAC_FMT ", %s=" IPV6_FMT ", %s=" IPV6_FMT ", %s=%hu, %s=%hu, %s=%u), ", ++ HINIC3_UI_KEY_VXLAN_PUSH_STR, HINIC3_UI_KEY_DST_MAC_STR, HINIC3_OUTPUT_MAC(vxlan_header->dmac), ++ HINIC3_UI_KEY_SRC_MAC_STR, HINIC3_OUTPUT_MAC(vxlan_header->smac), HINIC3_UI_KEY_SRC_IP_STR, ++ IPV6_ARGS(vxlan_header->sip), HINIC3_UI_KEY_DST_IP_STR, IPV6_ARGS(vxlan_header->dip), ++ HINIC3_UI_KEY_SRC_PORT_STR, ntohs(vxlan_header->sport), HINIC3_UI_KEY_VID_STR, ++ hinic3_vlan_tci_to_vid(vxlan_header->vlan_id), HINIC3_UI_KEY_VNI_STR, vni); ++ } ++} ++ ++static void ++hinic3_flow_process_vxlan_pop_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ bool nal_flag = hinic3_nlattr_get_itr_flag(nla); ++ hinic3_ds_put_format(ds, "%s(%s), ", HINIC3_UI_KEY_VXLAN_POP_STR, ++ nal_flag ? HINIC3_UI_KEY_TURE_STR : HINIC3_UI_KEY_FALSE_STR); ++} ++ ++static void ++hinic3_flow_process_vlan_push_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ uint16_t u16_val = hinic3_nlattr_get_itr_u16(nla); ++ uint16_t vlan = ntohs(u16_val); ++ hinic3_ds_put_format(ds, "%s(%s=%hu,%s=%hu), ", HINIC3_UI_KEY_VLAN_PUSH_STR, HINIC3_UI_KEY_VID_STR, ++ vlan & VLAN_VID_MASK, HINIC3_UI_KEY_VLAN_PCP_STR, (vlan & VLAN_PCP_MASK) >> VLAN_PCP_SHIFT); ++} ++ ++static void ++hinic3_flow_process_vlan_pop_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ bool nal_flag = hinic3_nlattr_get_itr_flag(nla); ++ hinic3_ds_put_format(ds, "%s(%s), ", HINIC3_UI_KEY_VLAN_POP_STR, ++ nal_flag ? HINIC3_UI_KEY_TURE_STR : HINIC3_UI_KEY_FALSE_STR); ++} ++ ++static void ++hinic3_flow_process_set_mac_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); ++ const char *mac_string = ++ (type == HINIC3_FLOW_ACT_SET_SMAC) ? HINIC3_UI_KEY_VLAN_SET_SMAC_STR : HINIC3_UI_KEY_VLAN_SET_DMAC_STR; ++ uint8_t *sd_mac = (uint8_t *)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ hinic3_ds_put_format(ds, "%s(" HINIC3_MAC_FMT "), ", mac_string, HINIC3_OUTPUT_MAC(sd_mac)); ++} ++ ++static void ++hinic3_flow_process_set_ip_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); ++ const char *ip_string = ++ (type == HINIC3_FLOW_ACT_SET_SIP) ? HINIC3_UI_KEY_VLAN_SET_SIP_STR : HINIC3_UI_KEY_VLAN_SET_DIP_STR; ++ uint32_t u32_val; ++ u32_val = hinic3_nlattr_get_itr_u32(nla); ++ hinic3_ds_put_format(ds, "%s(" IP_FMT "), ", ip_string, IP_ARGS(u32_val)); ++} ++ ++static void ++hinic3_flow_process_set_ipv6_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); ++ const char *ip_string = ++ (type == HINIC3_FLOW_ACT_SET_SIPV6) ? HINIC3_UI_KEY_VLAN_SET_SIP_STR : HINIC3_UI_KEY_VLAN_SET_DIP_STR; ++ struct in6_addr *ipv6_addr = (struct in6_addr *)hinic3_nlattr_get_itr_data(nla); ++ hinic3_ds_put_format(ds, "%s(", ip_string); ++ hinic3_ipv6_format_addr(ipv6_addr, ds); ++ hinic3_ds_put_format(ds, "), "); ++} ++ ++static void ++hinic3_flow_process_set_u16_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); ++ char *print_string = NULL; ++ uint16_t u16_val = hinic3_nlattr_get_itr_u16(nla); ++ switch (type) { ++ case HINIC3_FLOW_ACT_SET_SPORT: ++ print_string = HINIC3_UI_KEY_VLAN_SET_SPORT_STR; ++ break; ++ case HINIC3_FLOW_ACT_SET_DPORT: ++ print_string = HINIC3_UI_KEY_VLAN_SET_DPORT_STR; ++ break; ++ case HINIC3_FLOW_ACT_OUTPUT: ++ print_string = HINIC3_UI_KEY_VLAN_OUTPUT_STR; ++ break; ++ default: ++ return; ++ } ++ hinic3_ds_put_format(ds, "%s(%hu), ", print_string, ntohs(u16_val)); ++} ++ ++static void ++hinic3_flow_process_drop_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s, ", HINIC3_UI_KEY_DROP); ++} ++ ++static void ++hinic3_flow_process_ttl_dec_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s, ", HINIC3_UI_KET_TTL_DEC); ++} ++ ++static void ++hinic3_flow_process_show_set_priority_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s(%u), ", HINIC3_UI_KEY_VLAN_SET_PRIORITY_STR, hinic3_nlattr_get_itr_u32(nla)); ++} ++ ++static void ++hinic3_flow_process_mirror_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ struct hiovs_mirror_info *mirror_info = (struct hiovs_mirror_info *)hinic3_nlattr_get_itr_data(nla); ++ hinic3_ds_put_format(ds, "%s", HINIC3_UI_KEY_VLAN_MIRROR_STR); ++ if (mirror_info->ws.mirror_rx == 1) { ++ hinic3_ds_put_format(ds, "(session_id:%u, sport:%u, ratio:%u), ", mirror_info->sessions[0], ++ mirror_info->ws.sport, mirror_info->ws.sampling_interval); ++ } else { ++ hinic3_ds_put_format(ds, "(session_id:%u, sport:%u, ratio:%u), ", mirror_info->sessions[1], ++ mirror_info->ws.sport, mirror_info->ws.sampling_interval); ++ } ++} ++ ++static void hinic3_flow_process_block_version_action(const hinic3_nlattr_itr nla, struct ds *ds) ++{ ++ struct hinic3_flow_act_block_version *block = (struct hinic3_flow_act_block_version *)hinic3_nlattr_get_itr_data(nla); ++ hinic3_ds_put_format(ds, "%s(%u), ", HINIC3_UI_ACTION_BLOCK_ID_STR, block->block_id); ++ hinic3_ds_put_format(ds, "%s(%u), ", HINIC3_UI_ACTION_BLOCK_VERSION_STR, block->block_version); ++} ++ ++struct hinic3_actions_format_output_func_map hinic3_actions_format_output_func_array[] = { ++ {HINIC3_FLOW_ACT_CT, hinic3_flow_process_ct_action}, ++ {HINIC3_FLOW_ACT_VXL_PUSH, NULL}, ++ {HINIC3_FLOW_ACT_VXL_POP, hinic3_flow_process_vxlan_pop_action}, ++ {HINIC3_FLOW_ACT_VLAN_PUSH, hinic3_flow_process_vlan_push_action}, ++ {HINIC3_FLOW_ACT_VLAN_POP, hinic3_flow_process_vlan_pop_action}, ++ {HINIC3_FLOW_ACT_SET_SMAC, hinic3_flow_process_set_mac_action}, ++ {HINIC3_FLOW_ACT_SET_DMAC, hinic3_flow_process_set_mac_action}, ++ {HINIC3_FLOW_ACT_SET_SIP, hinic3_flow_process_set_ip_action}, ++ {HINIC3_FLOW_ACT_SET_DIP, hinic3_flow_process_set_ip_action}, ++ {HINIC3_FLOW_ACT_SET_SPORT, hinic3_flow_process_set_u16_action}, ++ {HINIC3_FLOW_ACT_SET_DPORT, hinic3_flow_process_set_u16_action}, ++ {HINIC3_FLOW_ACT_SET_PRIORITY, hinic3_flow_process_show_set_priority_action}, ++ {HINIC3_FLOW_ACT_OUTPUT, hinic3_flow_process_set_u16_action}, ++ {HINIC3_FLOW_ACT_VXL_GPE_PUSH, hinic3_flow_process_vxlan_push_action}, ++ {HINIC3_FLOW_ACT_SET_SIPV6, hinic3_flow_process_set_ipv6_action}, ++ {HINIC3_FLOW_ACT_SET_DIPV6, hinic3_flow_process_set_ipv6_action}, ++ {HINIC3_FLOW_ACT_SET_VXLAN_GROUP_ID, NULL}, ++ {HINIC3_FLOW_ACT_ECMP, NULL}, ++ {HINIC3_FLOW_ACT_DROP, hinic3_flow_process_drop_action}, ++ {HINIC3_FLOW_ACT_MIRROR, hinic3_flow_process_mirror_action}, ++ {HINIC3_FLOW_ACT_CRYPTO, NULL}, ++ {HINIC3_FLOW_ACT_COUNT, NULL}, ++ {HINIC3_FLOW_ACT_DEC_TTL, hinic3_flow_process_ttl_dec_action}, ++ {HINIC3_FLOW_ACT_UPCALL, NULL}, ++ {HINIC3_FLOW_ACT_BLOCK_VERSION, hinic3_flow_process_block_version_action}, ++ {HINIC3_FLOW_ACT_TYPE_MAX, NULL}, ++}; ++ ++void ++hinic3_actions_format_output(struct ds *ds, const struct hinic3_nlattr *actions) ++{ ++ hinic3_nlattr_itr nla = NULL; ++ HINIC3_NLATTR_FOR_EACH(nla, actions) ++ { ++ enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); ++ if (type < HINIC3_FLOW_ACT_TYPE_MAX && hinic3_actions_format_output_func_array[type].func != NULL) ++ hinic3_actions_format_output_func_array[type].func(nla, ds); ++ } ++} ++ ++void ++hinic3_flow_stats_format_output(const struct hinic3_flow_stats *stats, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s(%" PRIu64 "), %s(%" PRIu64 "), ", HINIC3_UI_FLOW_PACKET_STRING, stats->packet_count, ++ HINIC3_UI_FLOW_BYTES_STRING, stats->byte_count); ++ ++ hinic3_ds_put_format(ds, "%s(%" PRIu32 "ms), ", HINIC3_UI_FLOW_LIVE_TIME_STRING, stats->live_time); ++ ++ hinic3_ds_put_cstr(ds, HINIC3_UI_FLOW_FLAG_STRING); ++ hinic3_ds_put_format(ds, " %s(%" PRIu64 ")", HINIC3_UI_FLOW_CT_INFO_STRING, stats->ct_loss_pkts); ++} ++ ++void ++hinic3_agent_flow_format_output(struct hinic3_dpif_flow_for_get *f, struct ds *ds) ++{ ++ struct hinic3_nlattr flow_key; ++ struct hinic3_nlattr flow_actions; ++ hinic3_ds_put_format(ds, HINIC3_UI_FLOW_UFID_STRING); ++ hinic3_hw_ufid_format_output(&f->ol_ufid, ds); ++ if (f->related_hw_ufid != 0) { ++ hinic3_ds_put_format(ds, ", %s", HINIC3_UI_FLOW_RELATED_UFID_STRING); ++ hinic3_hw_ufid_format_output(&f->related_hw_ufid, ds); ++ } ++ ++ hinic3_nlattr_init(&flow_key, f->key, f->key_len); ++ hinic3_nlattr_reset_itr(&flow_key, f->key_len); ++ hinic3_nlattr_init(&flow_actions, f->actions, f->action_len); ++ hinic3_nlattr_reset_itr(&flow_actions, f->action_len); ++ ++ hinic3_ds_put_format(ds, ", %s", HINIC3_UI_FLOW_KEY_STRING); ++ hinic3_cmd_flow_key_format_output(&flow_key, ds); ++ ++ hinic3_ds_put_format(ds, HINIC3_UI_FLOW_ACTION_STRING); ++ hinic3_actions_format_output(ds, &flow_actions); ++ ++ hinic3_ds_put_format(ds, HINIC3_UI_FLOW_STATISTIC_STRING); ++ hinic3_flow_stats_format_output(&(f->stats), ds); ++ ++ hinic3_ds_put_format(ds, "\n"); ++} ++ ++void ++hinic3_show_base_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats) ++{ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-pkts", port_stats->ovs_port_stats.rx_packets); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-pkts", port_stats->ovs_port_stats.tx_packets); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-bytes", port_stats->ovs_port_stats.rx_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-bytes", port_stats->ovs_port_stats.tx_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-errors", port_stats->ovs_port_stats.rx_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-errors", port_stats->ovs_port_stats.tx_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-drop", port_stats->ovs_port_stats.rx_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-drop", port_stats->ovs_port_stats.tx_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-collisions", port_stats->ovs_port_stats.collisions); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-multicast-drop", port_stats->ovs_port_stats.multicast); ++} ++ ++void ++hinic3_show_check_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats) ++{ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-len-errors", port_stats->ovs_port_stats.rx_length_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-over-errors", port_stats->ovs_port_stats.rx_over_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-crc-errors", port_stats->ovs_port_stats.rx_crc_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-frame-errors", ++ port_stats->ovs_port_stats.rx_frame_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-fifo-errors", port_stats->ovs_port_stats.rx_fifo_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-rx-miss-errors", ++ port_stats->ovs_port_stats.rx_missed_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-abort-errors", ++ port_stats->ovs_port_stats.tx_aborted_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-carrier-errors", ++ port_stats->ovs_port_stats.tx_carrier_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-fifo-errors", port_stats->ovs_port_stats.tx_fifo_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-heartbeat-errors", ++ port_stats->ovs_port_stats.tx_heartbeat_errors); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-tx-window-errors", ++ port_stats->ovs_port_stats.tx_window_errors); ++} ++ ++void ++hinic3_show_hiovs_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats) ++{ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-tx-bond-mode-err-drop", port_stats->tx_bond_mode_err_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-tx-bond-noport-drop", port_stats->tx_bond_noport_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-tx-bcmc-limit-drop", port_stats->tx_bcmc_limit_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-tx-bum-smac-drop", port_stats->tx_bum_smac_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-tx-bum-sipsmac-drop", port_stats->tx_bum_sipsmac_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-tx-bum-ethtype-drop", port_stats->tx_bum_ethtype_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-rx-wqe-fail-drop", port_stats->rx_wqe_fail_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-rx-qos-drop", port_stats->rx_qos_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-rx-mtu-drop", port_stats->rx_mtu_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-rx-vport-invalid-drop", port_stats->rx_vport_invalid_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-ct-drop", port_stats->ct_dropped); ++} ++ ++void ++hinic3_show_upcall_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats) ++{ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "hw-upcall-wqe-fail-dropped", ++ port_stats->upcall_wqe_fail_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "hw-upcall-pkt-num-vport", port_stats->upcall_pkt_num_vport); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-uc-bytes", port_stats->tx_uc_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-uc-pkts", port_stats->tx_uc_pkts); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-bc-bytes", port_stats->tx_bc_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-bc-pkts", port_stats->tx_bc_pkts); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-mc-bytes", port_stats->tx_mc_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-mc-pkts", port_stats->tx_mc_pkts); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-uc-bytes", port_stats->rx_uc_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-uc-pkts", port_stats->rx_uc_pkts); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-bc-bytes", port_stats->rx_bc_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-bc-pkts", port_stats->rx_bc_pkts); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-mc-bytes", port_stats->rx_mc_bytes); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-mc-pkts", port_stats->rx_mc_pkts); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.h +new file mode 100644 +index 0000000..3e2e9db +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.h +@@ -0,0 +1,50 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_AGENT_CMD_FORMAT_H ++#define HINIC3_AGENT_CMD_FORMAT_H ++#include "hinic3_util.h" ++#include "hinic3_message.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_ds.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_provider.h" ++#include "hinic3_util.h" ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_HW_UFID_FMT "%08x-%08x" ++#define HINIC3_HW_UFID_ARGS(ufid) ((unsigned int)((ufid) >> 32)), ((unsigned int)((ufid) & 0xffffffff)) ++#define HINIC3_MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" ++#define HINIC3_OUTPUT_MAC(XOUT) (XOUT)[0], (XOUT)[1], (XOUT)[2], (XOUT)[3], (XOUT)[4], (XOUT)[5] ++#define IPV6_ARGS(ip) \ ++ ntohl((ip)[0]) >> 16, ntohl((ip)[0]) & 0xFFFF, ntohl((ip)[1]) >> 16, ntohl((ip)[1]) & 0xFFFF, \ ++ ntohl((ip)[2]) >> 16, ntohl((ip)[2]) & 0xFFFF, ntohl((ip)[3]) >> 16, ntohl((ip)[3]) & 0xFFFF ++#define IPV6_FMT \ ++ "%04" PRIx16 ":%04" PRIx16 ":%04" PRIx16 ":%04" PRIx16 ":%04" PRIx16 ":%04" PRIx16 ":%04" PRIx16 ":%04" PRIx16 ++#define HINIC3_OUTPUT_FUNC_LEN sizeof(hinic3_actions_format_output_func_array) \ ++ / sizeof(struct hinic3_actions_format_output_func_map) ++ ++struct hinic3_actions_format_output_func_map { ++ enum hinic3_flow_action_type type; ++ void (*func)(const hinic3_nlattr_itr nla, struct ds *ds); ++}; ++ ++void hinic3_hw_ufid_format_output(const uint64_t *hw_ufid, struct ds *ds); ++void hinic3_flow_key_format_output(const struct hinic3_nlattr *key, struct ds *ds); ++void hinic3_actions_format_output(struct ds *ds, const struct hinic3_nlattr *actions); ++void hinic3_flow_stats_format_output(const struct hinic3_flow_stats *stats, struct ds *ds); ++void hinic3_agent_flow_format_output(struct hinic3_dpif_flow_for_get *f, struct ds *ds); ++ ++void hinic3_show_upcall_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++void hinic3_show_base_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++void hinic3_show_check_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++void hinic3_show_hiovs_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++ ++#ifdef __cplusplus ++} ++#endif ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.c +new file mode 100644 +index 0000000..63c6380 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.c +@@ -0,0 +1,40 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_agent_cmd_time.h" ++#include ++#include "hinic3_util.h" ++#include "hinic3_log.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_string_util.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_command.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_ds.h" ++ ++struct hinic3_stat_ref_time_measure_task g_offload_stat_ref_time_task = { ++ .basic.alive = false, ++ .basic.mutex = HINIC3_MUTEX_INITIALIZER, ++ .time_list = { { 0, 0 }, { 0, 0 } } ++}; ++ ++struct hinic3_time_measure_task g_offload_time_task = { ++ .basic.alive = false, ++ .basic.mutex = HINIC3_MUTEX_INITIALIZER, ++ .time_list = { { 0, 0 }, { 0, 0 } } ++}; ++ ++bool ++hinic3_is_offload_measure_alive(void) ++{ ++ return g_offload_time_task.basic.alive; ++} ++ ++bool ++hinic3_is_stat_scan_measure_alive(void) ++{ ++ return g_offload_stat_ref_time_task.basic.alive; ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.h +new file mode 100644 +index 0000000..2536971 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_time.h +@@ -0,0 +1,88 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_AGENT_FLOW_TIME_H ++#define HINIC3_AGENT_FLOW_TIME_H ++#include ++#include ++#include "hinic3_mutex.h" ++#include "hinic3_util.h" ++#include "hinic3_command.h" ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_STAT_REF_TIME_MIN_SAMPLE 1 /* 获取统计信息全量刷新时间 最小采集次数 */ ++#define HINIC3_STAT_REF_TIME_MAX_SAMPLE 300 /* 获取统计信息全量刷新时间 最大采集次数 */ ++#define HINIC3_STAT_REF_TIME_GET_INTERVAL 1000 /* 获取统计信息全量刷新时间 采集间隔 */ ++#define HINIC3_STAT_REF_TIME_GET_TIMEOUT 5 /* 获取统计信息全量刷新时间 超时时间 */ ++#define HINIC3_TIME_MIN_SAMPLE 1 /* 获取流表卸载时间 最小采集次数 */ ++#define HINIC3_TIME_MAX_SAMPLE 300 /* 获取流表卸载时间 最大采集次数 */ ++#define HINIC3_TIME_GET_INTERVAL 1000 /* 获取流表卸载时间 采集间隔 */ ++#define HINIC3_TIME_GET_TIMEOUT 5 /* 获取流表卸载时间 超时时间 */ ++#define SECOND_TO_USECOND 1000000 /* 1s = 1e6 us */ ++ ++enum { ++ HINIC3_STAT_REF_TIME_TASK_CMD_STOP = 1, ++ HINIC3_STAT_REF_TIME_TASK_CMD_RESTART, ++}; ++ ++enum { ++ HINIC3_TIME_TASK_CMD_STOP = 1, ++ HINIC3_TIME_TASK_CMD_RESTART, ++}; ++ ++enum { ++ HINIC3_STAT_REF_TIME_TASK_ST_SAMPLING = 1, ++ HINIC3_STAT_REF_TIME_TASK_ST_IDLE, ++}; ++ ++enum { ++ HINIC3_TIME_TASK_ST_SAMPLING = 1, ++ HINIC3_TIME_TASK_ST_IDLE, ++}; ++ ++struct hinic3_time_cmd_param { ++ uint32_t total_samples; ++}; ++ ++struct hinic3_stat_refresh_time { ++ uint32_t thread_id; ++ double time; ++}; ++ ++struct hinic3_time_measure_task_basic { ++ bool alive; ++ int status; ++ int command; ++ uint32_t total_samples; ++ uint32_t count; ++ pthread_t thread; ++ pthread_cond_t cond; ++ struct hinic3_mutex mutex; ++}; ++ ++struct hinic3_stat_ref_time_measure_task { ++ struct hinic3_time_measure_task_basic basic; ++ struct hinic3_stat_refresh_time time_list[HINIC3_STAT_REF_TIME_MAX_SAMPLE]; ++}; ++ ++struct hinic3_time { ++ uint32_t record; ++ double time; ++}; ++ ++struct hinic3_time_measure_task { ++ struct hinic3_time_measure_task_basic basic; ++ struct hinic3_time time_list[HINIC3_TIME_MAX_SAMPLE]; ++}; ++ ++bool hinic3_is_offload_measure_alive(void); ++bool hinic3_is_stat_scan_measure_alive(void); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.c +new file mode 100644 +index 0000000..41fb29a +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.c +@@ -0,0 +1,92 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_util.h" ++#include "hinic3_map.h" ++#include "hinic3_eth_packets.h" ++#include "rte_config.h" ++#include ++#include "hinic3_log.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_option.h" ++#include "hinic3_thread.h" ++#include "hinic3_string_util.h" ++#include "hinic3_flow_dump_public.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_command.h" ++#include "hinic3_ds.h" ++#include "hinic3_vf_dfx.h" ++#include "hinic3_file_util.h" ++#include "hinic3_agent_flow_cmd.h" ++ ++#define UUID_64_LEN (18) ++#define UUID_64_FMT "%08x-%08x" ++ ++static const struct hinic3_opt flow_cmd_opts[] = { ++ {"ufid", REQUIRED_ARGUMENT, 0, HINIC3_UFID_64_OPT}, ++ {"stop", NO_ARGUMENT, 0, HINIC3_STOP_DUMP_ALL_FLOWS_OPT}, ++ {"check", NO_ARGUMENT, 0, HINIC3_CHECK_DUMP_ALL_FLOWS_OPT}, ++ {"-f", REQUIRED_ARGUMENT, 0, HINIC3_FLOW_FILE_OPT}, ++ {"-n", NO_ARGUMENT, 0, HINIC3_FLOW_CNT_OPT}, ++ {"-h", NO_ARGUMENT, 0, HELP_OPT}, ++ {"--help", NO_ARGUMENT, 0, HELP_OPT}, ++ {"api", REQUIRED_ARGUMENT, 0, HINIC3_FLOW_API_NAME_OPT}, ++ {"all", NO_ARGUMENT, 0, HINIC3_FLOW_ALL_OPT}, ++ {"clear", NO_ARGUMENT, 0, HINIC3_FLOW_CLEAR_OPT}, ++ {"-i", REQUIRED_ARGUMENT, 0, HINIC3_FLOW_BLOCK_ID_OPT}, ++}; ++ ++int ++hinic3_find_option(const char *name) ++{ ++ int option_val; ++ size_t idx = 0; ++ ++ if (name == NULL) ++ return -1; ++ for (idx = 0; idx < sizeof(flow_cmd_opts) / sizeof(struct hinic3_opt); idx++) { ++ if (strcmp(name, flow_cmd_opts[idx].name) == 0) { ++ option_val = flow_cmd_opts[idx].val; ++ return option_val; ++ } ++ } ++ return -1; ++} ++ ++static void ++hinic3_offload_flow_num_get(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, ++ void *aux) ++{ ++ uint32_t tmp_value; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ tmp_value = hinic3_get_offload_flow_nums(); ++ hinic3_ds_put_format(&ds, "%2soffload-flow-num: %u\n", HINIC3_UI_INDENT_SPACE, tmp_value); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} ++ ++void ++unixctl_hinic3_flow_cmd_init(void) ++{ ++ enum hinic3_flow_cmd_max { ++ SHOW_FLOW_API_PARAM = 3, ++ SHOW_OFFLOAD_SPEED_PARAM = 5, ++ }; ++ ++ hinic3_command_register("hwoff/show-flow-api", "{ all | clear { all | } | " ++ "api | { -h | --help } }", 1, SHOW_FLOW_API_PARAM, ++ hinic3_agent_show_flow_api, NULL); ++ hinic3_command_register("hwoff/flow-offload-speed-stat", ++ "{ start -i INTEGER<1-10> -t INTEGER<1-300> | restart [ -i INTEGER<1-10> " ++ "| -t INTEGER<1-300> ] * | stop | show | { -h | --help } }", 1, ++ SHOW_OFFLOAD_SPEED_PARAM, hinic3_speed_task_cmd, NULL); ++ hinic3_command_register("hwoff/show-offload-flow-num", "", 0, 0, hinic3_offload_flow_num_get, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.h +new file mode 100644 +index 0000000..4bfdbab +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd.h +@@ -0,0 +1,80 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_AGENT_FLOW_DFX_H ++#define HINIC3_AGENT_FLOW_DFX_H ++#include ++#include ++#include "hinic3_mutex.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_command.h" ++#include "hinic3_flow_dump_public.h" ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_MAX_SPEED_SAMPLE 300 ++#define HINIC3_SPPED_MIN_INTERVAL 1 ++#define HINIC3_SPPED_MAX_INTERVAL 10 ++#define HINIC3_SPPED_MIN_SAMPLE 1 ++#define HINIC3_SPPED_MAX_SAMPLE 300 ++#define HOWFF_NO_FLOW_ERR (-4) ++#define HINIC3_SHOW_API_NUM_PER_LINE 4 ++#define US_PER_MS 1000 ++ ++enum { ++ HINIC3_UFID_64_OPT = 1, ++ HINIC3_FLOW_KEY_OPT, ++ HINIC3_FLOW_FILE_OPT, ++ HINIC3_STOP_DUMP_ALL_FLOWS_OPT, ++ HINIC3_CHECK_DUMP_ALL_FLOWS_OPT, ++ HINIC3_FLOW_CNT_OPT, ++ HELP_OPT, ++ HINIC3_FLOW_API_NAME_OPT, ++ HINIC3_FLOW_ALL_OPT, ++ HINIC3_FLOW_CLEAR_OPT, ++ HINIC3_FLOW_BLOCK_ID_OPT, ++}; ++ ++enum { ++ HINIC3_SPEED_TASK_CMD_STOP = 1, ++ HINIC3_SPEED_TASK_CMD_RESTART, ++}; ++ ++enum { ++ HINIC3_SPEED_TASK_ST_SAMPLING = 1, ++ HINIC3_SPEED_TASK_ST_IDLE, ++}; ++ ++struct hinic3_speed_cmd_param_t { ++ uint32_t total_samples; ++ uint32_t interval; ++}; ++ ++struct hinic3_speed_measure_task_t { ++ bool alive; ++ int status; ++ int command; ++ uint32_t total_samples; ++ uint32_t interval; ++ uint32_t count; ++ uint32_t sample_list[HINIC3_MAX_SPEED_SAMPLE]; ++ pthread_t thread; ++ pthread_cond_t cond; ++ struct hinic3_mutex mutex; ++}; ++ ++void unixctl_hinic3_flow_cmd_init(void); ++ ++void hinic3_agent_show_flow_api(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_agent_show_flow_api(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED); ++void hinic3_speed_task_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++ ++int hinic3_find_option(const char *name); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_api.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_api.c +new file mode 100644 +index 0000000..de4d251 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_api.c +@@ -0,0 +1,268 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_iface_flow_api_record.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_command.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_ds.h" ++#define SHOW_FLOW_API_UI_FOUR_SPACE 4 ++#define SHOW_FLOW_API_UI_SIX_SPACE 6 ++ ++static void ++hinic3_agent_show_api_record_info(int index, const hiovs_api_record *records, struct ds *reply, bool is_all) ++{ ++ char time_str[HINIC3_TIME_STR_LEN] = {0}; ++ char *pstr = time_str; ++ int value_ui_space; ++ if (is_all) { ++ value_ui_space = SHOW_FLOW_API_UI_SIX_SPACE; ++ } else { ++ value_ui_space = SHOW_FLOW_API_UI_FOUR_SPACE; ++ } ++ ++ hinic3_ds_put_format(reply, "%*s" HINIC3_UI_FLOW_API_COST_MAX_TIME_STRING, value_ui_space, HINIC3_UI_INDENT_SPACE, ++ records[index].max_api_time); ++ hinic3_ds_put_format(reply, "%*s" HINIC3_UI_FLOW_API_COST_MIN_TIME_STRING, value_ui_space, HINIC3_UI_INDENT_SPACE, ++ records[index].min_api_time); ++ ++ if (records[index].call_total_count != 0) { ++ hinic3_ds_put_format(reply, "%*s" HINIC3_UI_FLOW_API_COST_AVERAGE_TIME_STRING, value_ui_space, ++ HINIC3_UI_INDENT_SPACE, records[index].total_api_time / records[index].call_total_count); ++ } else { ++ hinic3_ds_put_format(reply, "%*s" HINIC3_UI_FLOW_API_COST_AVERAGE_TIME_STRING, value_ui_space, ++ HINIC3_UI_INDENT_SPACE, (uint64_t)0); ++ } ++ ++ hinic3_ds_put_format(reply, "%*s" HINIC3_UI_FLOW_API_TOTAL_CALL_TIMES_STRING, value_ui_space, HINIC3_UI_INDENT_SPACE, ++ records[index].call_total_count); ++ hinic3_ds_put_format(reply, "%*s" HINIC3_UI_FLOW_API_ERROR_CALL_TIMES_STRING, value_ui_space, HINIC3_UI_INDENT_SPACE, ++ records[index].call_error_count); ++ ++ if (records[index].call_error_count != 0) { ++ ctime_r(&records[index].time_error, pstr); ++ hinic3_ds_put_format(reply, "%*s" HINIC3_UI_FLOW_API_LATEST_ERROR_CALL_INFO_STRING, value_ui_space, ++ HINIC3_UI_INDENT_SPACE, records[index].last_rtn_value, pstr); ++ } ++} ++ ++static int ++hinic3_agent_show_single_flow_api(int index, const char *argv[], struct ds *reply, hiovs_api_record *records) ++{ ++ int err = hinic3_flow_get_api_record(argv[index], false, false, records, 1); ++ if (err != 0) { ++ hinic3_ds_put_format(reply, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_UNKOWN_API_STRING, argv[index]); ++ return err; ++ } ++ ++ hinic3_ds_put_format(reply, "%2s" HINIC3_UI_FLOW_QUERY_API_NAME_STRING, HINIC3_UI_INDENT_SPACE, argv[index]); ++ hinic3_agent_show_api_record_info(HINIC3_DEFAULT_API_RECORD_INDEX, records, reply, false); ++ return err; ++} ++ ++static int ++hinic3_agent_process_single_flow_api(int argc, const char *argv[], struct ds *reply) ++{ ++ enum { ++ ARG_API = 1, ++ ARG_NAME = 2, ++ ARGC = 3 ++ }; ++ int ret; ++ hiovs_api_record tmp_records = {0}; ++ hiovs_api_record *records = &tmp_records; ++ ++ if (argc != ARGC) { ++ hinic3_ds_put_format(reply, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_OPTIONS_WRONG_ARGUMENTS_STRING, ++ argv[ARG_API], ARG_NAME); ++ return -1; ++ } ++ ++ ret = hinic3_agent_show_single_flow_api(ARG_NAME, argv, reply, records); ++ return ret; ++} ++ ++static void ++hinic3_agent_show_per_flow_api_info(int index, hiovs_api_record *records, struct ds *ds) ++{ ++ const char *api_name = hinic3_flow_get_api_name(index); ++ if (api_name == NULL) ++ return; ++ ++ hinic3_ds_put_format(ds, "%4s" HINIC3_UI_FLOW_QUERY_API_NAME_STRING, HINIC3_UI_INDENT_SPACE, api_name); ++ hinic3_agent_show_api_record_info(index, records, ds, true); ++} ++ ++static int ++hinic3_agent_show_all_flow_api_info(int argc, struct ds *ds) ++{ ++ enum { ++ ARGC = 2 ++ }; ++ if (argc > ARGC) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, ARGC - 1); ++ return -1; ++ } ++ ++ hiovs_api_record *records = ++ (hiovs_api_record *)hinic3_calloc(HINIC3_FLOW_API_MAX, sizeof(hiovs_api_record), HINIC3_COMMAND); ++ if (records == NULL) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_ALLOC_RECORDS_ERROR_STRING); ++ return -1; ++ } ++ ++ int ret = hinic3_flow_get_api_record("", true, false, records, HINIC3_FLOW_API_MAX); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_FAILURE HINIC3_UI_FLOW_QUERY_RECORDS_FAILED_STRING, ++ HINIC3_UI_FLOW_ALL_STRING); ++ hinic3_free(records); ++ return ret; ++ } ++ ++ hinic3_ds_put_format(ds, "%2s" HINIC3_UI_FLOW_API_COUNT_STRING, HINIC3_UI_INDENT_SPACE, HINIC3_FLOW_API_MAX); ++ ++ for (int i = 0; i < HINIC3_FLOW_API_MAX; ++i) { ++ hinic3_agent_show_per_flow_api_info(i, records, ds); ++ if (i != HINIC3_FLOW_API_MAX - 1) { ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ } ++ ++ hinic3_free(records); ++ return ret; ++} ++ ++static int ++hinic3_agent_show_flow_api_help(int argc, struct ds *ds) ++{ ++ const char *api_name = NULL; ++ enum { ++ ARGC = 2 ++ }; ++ ++ if (argc > ARGC) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, ARGC - 1); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%2s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_SHOW_FLOW_API_HELP_STRING); ++ hinic3_ds_put_format(ds, "\n"); ++ hinic3_ds_put_format(ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_OPTION_LIST_STRING); ++ hinic3_ds_put_format(ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_SHOW_ALL_API_HELP_STRING); ++ hinic3_ds_put_format(ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_CLEAR_ALL_API_HELP_STRING); ++ hinic3_ds_put_format(ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_CLEAR_ONE_API_HELP_STRING); ++ hinic3_ds_put_format(ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_SHOW_ONE_API_HELP_STRING); ++ hinic3_ds_put_format(ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_HELP_STRING); ++ hinic3_ds_put_format(ds, "\n"); ++ hinic3_ds_put_format(ds, "%2s" HINIC3_UI_FLOW_ALL_API_TIPS_STRING, HINIC3_UI_INDENT_SPACE); ++ ++ for (int i = 0; i < HINIC3_FLOW_API_MAX; ++i) { ++ api_name = hinic3_flow_get_api_name(i); ++ if (api_name == NULL) { ++ continue; ++ } ++ if (i % HINIC3_SHOW_API_NUM_PER_LINE == 0) { ++ hinic3_ds_put_format(ds, "\n"); ++ hinic3_ds_put_format(ds, "%4s", HINIC3_UI_INDENT_SPACE); ++ } ++ hinic3_ds_put_format(ds, "%-40s", api_name); ++ } ++ hinic3_ds_put_format(ds, "\n"); ++ return 0; ++} ++ ++static int ++hinic3_agent_clear_api_info(int argc, const char *argv[], struct ds *ds) ++{ ++ int ret; ++ enum { ++ ARGC = 3 ++ }; ++ hiovs_api_record tmp_records = {0}; ++ hiovs_api_record *records = &tmp_records; ++ ++ if (argc != ARGC) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, ARGC - 1); ++ return -1; ++ } ++ ++ if (strcmp("all", argv[ARGC - 1]) == 0) { ++ ret = hinic3_flow_get_api_record("", true, true, NULL, 0); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "clear all flow api record failed\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_CLEAR_RECORDS_FAILED_STRING, ++ HINIC3_UI_FLOW_ALL_STRING); ++ return ret; ++ } ++ HINIC3_LOG(INFO, AGENT, "clear all flow api record successful\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_INFO HINIC3_UI_FLOW_CLEAR_RECORDS_SUCCESS_STRING, ++ HINIC3_UI_FLOW_ALL_STRING); ++ return ret; ++ } ++ ret = hinic3_flow_get_api_record(argv[ARGC - 1], false, true, records, 1); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "clear flow api record failed\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_FAILURE HINIC3_UI_FLOW_CLEAR_RECORDS_FAILED_STRING, ++ argv[ARGC - 1]); ++ } else { ++ HINIC3_LOG(INFO, AGENT, "clear flow api record success\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_INFO HINIC3_UI_FLOW_CLEAR_RECORDS_SUCCESS_STRING, ++ argv[ARGC - 1]); ++ } ++ return ret; ++} ++ ++void ++hinic3_agent_show_flow_api(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds reply = DS_EMPTY_INITIALIZER; ++ enum { ++ ARGC = 2 ++ }; ++ ++ int argv_index = ARGC - 1; ++ int option_val = hinic3_find_option(argv[argv_index]); ++ int ret = -1; ++ if (option_val == -1) { ++ hinic3_ds_put_format(&reply, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_INPUT_UNKOWN_OPTION_STRING, ++ argv[argv_index]); ++ goto out; ++ } ++ ++ switch (option_val) { ++ case HINIC3_FLOW_API_NAME_OPT: ++ ret = hinic3_agent_process_single_flow_api(argc, argv, &reply); ++ break; ++ ++ case HINIC3_FLOW_ALL_OPT: ++ ret = hinic3_agent_show_all_flow_api_info(argc, &reply); ++ break; ++ ++ case HINIC3_FLOW_CLEAR_OPT: ++ ret = hinic3_agent_clear_api_info(argc, argv, &reply); ++ break; ++ ++ case HELP_OPT: ++ ret = hinic3_agent_show_flow_api_help(argc, &reply); ++ break; ++ ++ default: ++ hinic3_ds_put_format(&reply, HINIC3_UI_FLOW_INPUT_UNKOWN_OPTION_STRING, argv[argv_index]); ++ break; ++ } ++ ++out: ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&reply)); ++ *(int *)aux = -1; ++ } else { ++ hinic3_command_reply(conn, hinic3_ds_cstr(&reply)); ++ *(int *)aux = 0; ++ } ++ hinic3_ds_destroy(&reply); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +new file mode 100644 +index 0000000..3e0b10b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +@@ -0,0 +1,554 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_agent_flow_cmd_dump.h" ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_file_util.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_string_util.h" ++#include "hinic3_vf_dfx.h" ++ ++static struct hinic3_flow_dump_cmd g_hinic3_flow_dump_cmd; ++static struct hinic3_dump_all_flows_mgmt_t dump_flows_mgmt = { ++ .dumping = HINIC3_DUMP_FLOWS_IDLE, ++ .start = NULL, ++ .file = NULL ++}; ++ ++struct hinic3_dump_all_flows_mgmt_t * ++hinic3_cmd_get_flow_dump_mgmt(void) ++{ ++ return &dump_flows_mgmt; ++} ++ ++struct hinic3_flow_dump_cmd * ++hinic3_cmd_get_flow_dump_ops(void) ++{ ++ return &g_hinic3_flow_dump_cmd; ++} ++ ++void ++hinic3_cmd_set_flow_get_maxflows_ops(int (*ops)(uint32_t *)) ++{ ++ g_hinic3_flow_dump_cmd.hinic3_flow_get_maxflows_ops = ops; ++} ++ ++void ++hinic3_cmd_set_flow_dump_start_ops(int (*ops)(void **)) ++{ ++ g_hinic3_flow_dump_cmd.hinic3_flow_dump_start_ops = ops; ++} ++ ++void ++hinic3_cmd_set_flow_dump_next_ops(int (*ops)(void *, struct hinic3_dpif_flow_for_get *)) ++{ ++ g_hinic3_flow_dump_cmd.hinic3_flow_dump_next_ops = ops; ++} ++ ++void ++hinic3_cmd_set_flow_dump_done_ops(int (*ops)(void *)) ++{ ++ g_hinic3_flow_dump_cmd.hinic3_flow_dump_done_ops = ops; ++} ++ ++void ++hinic3_cmd_set_flow_key_format_output_ops(void (*ops)(const struct hinic3_nlattr *, struct ds *)) ++{ ++ g_hinic3_flow_dump_cmd.hinic3_flow_key_format_output_ops = ops; ++} ++ ++void ++hinic3_cmd_set_flow_ops_status(enum hinic3_flow_type type) ++{ ++ g_hinic3_flow_dump_cmd.type = type; ++} ++ ++void ++hinic3_agent_dump_hinic3_emc_flow_init(void) ++{ ++ hinic3_cmd_set_flow_get_maxflows_ops(hinic3_flow_get_maxflows); ++ hinic3_cmd_set_flow_dump_start_ops(hinic3_flow_dump_start); ++ hinic3_cmd_set_flow_dump_next_ops(hinic3_flow_dump_next); ++ hinic3_cmd_set_flow_dump_done_ops(hinic3_flow_dump_done); ++ hinic3_cmd_set_flow_key_format_output_ops(hinic3_flow_key_format_output); ++ hinic3_cmd_set_flow_ops_status(HINIC3_FLOW_TYPE_EMC); ++} ++ ++static int ++hinic3_agent_set_dump_start(struct hinic3_dump_all_flows_mgmt_t *mgmt, struct ds *ds) ++{ ++ hinic3_pthread_mutex_lock(&mgmt->mutex_lock); ++ if (mgmt->dumping != HINIC3_DUMP_FLOWS_IDLE) { ++ hinic3_pthread_mutex_unlock(&mgmt->mutex_lock); ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_DUMP_ALL_FLOW_TIPS_STRING); ++ return -1; ++ } ++ mgmt->dumping = HINIC3_DUMP_FLOWS_RUNNING; ++ hinic3_pthread_mutex_unlock(&mgmt->mutex_lock); ++ return 0; ++} ++ ++static void ++hinic3_agent_dump_flows_handle_ret(int ret, struct ds *ds) ++{ ++ if (ret != HOWFF_NO_FLOW_ERR) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_DUMP_ALL_FLOW_START_FAILED_STRING); ++ } else { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMP_NO_AVALIBLE_FLOW_STRING); ++ } ++} ++ ++int ++hinic3_alloc_mem_for_flow(struct ds *ds, struct hinic3_dpif_flow_for_get *f) ++{ ++ if (f->key == NULL) { ++ f->key = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); ++ if (f->key == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "calloc memory for hw flow key error\n"); ++ return -1; ++ } ++ } ++ ++ if (f->actions == NULL) { ++ f->actions = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); ++ if (f->actions == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "calloc memory for hw flow actions error\n"); ++ hinic3_free(f->key); ++ f->key = NULL; ++ return -1; ++ } ++ } ++ ++ if (f->mask == NULL) { ++ f->mask = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); ++ if (f->mask == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "calloc memory for hw flow mask error\n"); ++ hinic3_free(f->key); ++ f->key = NULL; ++ hinic3_free(f->actions); ++ f->actions = NULL; ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++void ++hinic3_agent_free_mem_for_flow(struct hinic3_dpif_flow_for_get *f) ++{ ++ if (f->key != NULL) { ++ hinic3_free(f->key); ++ f->key = NULL; ++ } ++ f->key_len = 0; ++ ++ if (f->actions != NULL) { ++ hinic3_free(f->actions); ++ f->actions = NULL; ++ } ++ f->action_len = 0; ++ ++ if (f->mask != NULL) { ++ hinic3_free(f->mask); ++ f->mask = NULL; ++ } ++ f->mask_len = 0; ++} ++ ++static int ++hinic3_agent_dump_all_flows_to_screen(struct hinic3_dpif_flow_for_get *f, ++ struct hinic3_dump_all_flows_mgmt_t *mgmt, struct ds *ds) ++{ ++ int ret; ++ void *state = NULL; ++ uint64_t total_loss_ct_pkts = 0; ++ uint32_t total_flows = 0; ++ ++ /* dump all hw-flows */ ++ ret = hinic3_cmd_flow_dump_start(&state); ++ if (ret != 0) { ++ hinic3_agent_dump_flows_handle_ret(ret, ds); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return -1; ++ } ++ ++ ret = hinic3_alloc_mem_for_flow(ds, f); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_ALLOC_FLOW_INFO_ERROR_STRING); ++ (void)hinic3_cmd_flow_dump_done(state); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return -1; ++ } ++ ++ total_flows = 0; ++ while ((hinic3_cmd_flow_dump_next(state, f)) == 0 && total_flows <= HINIC3_DUMP_FLOWS_MAX_ONCE) { ++ hinic3_agent_flow_format_output(f, ds); ++ hinic3_ds_put_format(ds, "\n"); ++ total_loss_ct_pkts += f->stats.ct_loss_pkts; ++ total_flows++; ++ } ++ ++ (void)hinic3_cmd_flow_dump_done(state); ++ hinic3_ds_put_format(ds, "%2s%s%" PRIu32 ", %s%" PRIu64 "\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_TOTAL_FLOW_STRING, total_flows, ++ HINIC3_UI_FLOW_DUMP_TOTAL_CT_LOST_PKT_STRING, total_loss_ct_pkts); ++ ++ if (total_flows > HINIC3_DUMP_FLOWS_MAX_ONCE) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FLOW_UP_DISPLAY_MAX_TIPS_STRING, ++ HINIC3_UI_LEADING_SIGN_INFO, HINIC3_DUMP_FLOWS_MAX_ONCE); ++ } ++ ++ hinic3_agent_free_mem_for_flow(f); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return 0; ++} ++ ++static int ++hinic3_agent_dump_flows(struct ds *ds) ++{ ++ uint32_t total_flows = 0; ++ struct hinic3_dump_all_flows_mgmt_t *mgmt = &dump_flows_mgmt; ++ struct hinic3_dpif_flow_for_get f; ++ ++ memset(&f, 0, sizeof(struct hinic3_dpif_flow_for_get)); ++ ++ if (hinic3_agent_set_dump_start(mgmt, ds) != 0) ++ return -1; ++ ++ int ret = hinic3_cmd_flow_get_maxflows(&total_flows); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_DUMP_GET_FLOW_COUNT_FAILED_STRING); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return -1; ++ } ++ ++ if (total_flows > HINIC3_DUMP_FLOWS_MAX_ONCE) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FLOW_UP_MAX_TIPS_STRING, HINIC3_UI_INDENT_SPACE, ++ total_flows, HINIC3_DUMP_FLOWS_MAX_ONCE); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return 0; ++ } ++ ++ return hinic3_agent_dump_all_flows_to_screen(&f, mgmt, ds); ++} ++ ++static int ++hinic3_agent_dump_flow_by_ufid(const uint64_t *ufid, struct ds *ds) ++{ ++ struct hinic3_dpif_flow_for_get f = {0}; ++ int ret; ++ ++ ret = hinic3_alloc_mem_for_flow(ds, &f); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_ALLOC_FLOW_INFO_ERROR_STRING); ++ return -1; ++ } ++ ++ ret = hinic3_flow_get_by_ufid(*ufid, &f); ++ if (ret != 0) { ++ if (ret != HOWFF_NO_FLOW_ERR) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_DUMP_FLOW_ERROR_STRING); ++ } else { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMP_NO_AVALIBLE_FLOW_STRING); ++ } ++ hinic3_agent_free_mem_for_flow(&f); ++ return -1; ++ } ++ hinic3_agent_flow_format_output(&f, ds); ++ hinic3_agent_free_mem_for_flow(&f); ++ return 0; ++} ++ ++static int ++hinic3_agent_dump_specific_flow(int argc, const char *argv[], struct ds *ds) ++{ ++ enum { ++ ARGC = 3 ++ }; ++ uint64_t ufid; ++ if (argc != ARGC) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ ++ int ret = hinic3_parse_hw_ufid_from_string(argv[ARGC - 1], &ufid); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_UFID_MAP_HW_UFID_FORMART_ERROR_STRING); ++ return -1; ++ } ++ return hinic3_agent_dump_flow_by_ufid(&ufid, ds); ++} ++ ++static void ++hinic3_agent_dump_flows_help(struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%2s%sdpak-ovs-ctl hwoff/dump-hinic3-flows [ ufid | -n |" ++ " -f | -i | check | stop | { -h | --help } ]\n\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_CMD_USAGE_STRING); ++ hinic3_ds_put_format(ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_OPTION_LIST_STRING); ++ hinic3_ds_put_format(ds, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_UFID_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_UFID_TIPS_STRING); ++ hinic3_ds_put_format(ds, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_BLOCK_ID_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_BLOCK_ID_TIPS_STRING); ++ hinic3_ds_put_format(ds, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_FILE_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_FILE_TIPS_STRING); ++ hinic3_ds_put_format(ds, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_COUNT_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_COUNT_TIPS_STRING); ++ hinic3_ds_put_format(ds, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_CHECK_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_CHECK_TIPS_STRING); ++ hinic3_ds_put_format(ds, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_STOP_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_STOP_TIPS_STRING); ++ hinic3_ds_put_format(ds, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_FLOW_DUMP_HELP_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_HELP_TIPS_STRING); ++} ++ ++static int ++hinic3_agent_get_flows_cnt(int argc, struct ds *ds) ++{ ++ enum { ++ ARGC = 2 ++ }; ++ if (argc != ARGC) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ ++ uint32_t max_flow_cnt; ++ int ret = hinic3_cmd_flow_get_maxflows(&max_flow_cnt); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_DUMP_GET_FLOW_COUNT_FAILED_STRING); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, HINIC3_UI_FLOW_DUMP_FLOW_COUNT_STRING, max_flow_cnt); ++ ++ return 0; ++} ++ ++static int ++hinic3_agent_get_block_id_from_flow(const struct hinic3_dpif_flow_for_get *f, ++ uint16_t *return_block_id, struct ds *ds) ++{ ++ struct hinic3_nlattr flow_actions; ++ hinic3_nlattr_itr nla = NULL; ++ struct hinic3_flow_act_block_version *block = NULL; ++ ++ hinic3_nlattr_init(&flow_actions, f->actions, f->action_len); ++ hinic3_nlattr_reset_itr(&flow_actions, f->action_len); ++ HINIC3_NLATTR_FOR_EACH(nla, &flow_actions) ++ { ++ enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); ++ if (type == HINIC3_FLOW_ACT_BLOCK_VERSION) { ++ block = (struct hinic3_flow_act_block_version *)hinic3_nlattr_get_itr_data(nla); ++ if (return_block_id != NULL) { ++ *return_block_id = block->block_id; ++ } ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++static int ++hinic3_agent_dump_flows_to_screen_by_block_id(struct hinic3_dpif_flow_for_get *f, ++ const uint32_t block_id_input, struct ds *ds) ++{ ++ struct hinic3_dump_all_flows_mgmt_t *mgmt = &dump_flows_mgmt; ++ uint64_t total_loss_pkts = 0; ++ uint16_t block_id = 0; ++ int dump_flows = 0; ++ void *state = NULL; ++ ++ if (hinic3_agent_set_dump_start(mgmt, ds) != 0) ++ return -1; ++ ++ int ret = hinic3_cmd_flow_dump_start(&state); ++ if (ret != 0) { ++ hinic3_agent_dump_flows_handle_ret(ret, ds); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return -1; ++ } ++ ++ ret = hinic3_alloc_mem_for_flow(ds, f); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_ALLOC_FLOW_INFO_ERROR_STRING); ++ (void)hinic3_cmd_flow_dump_done(state); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return -1; ++ } ++ ++ while ((hinic3_cmd_flow_dump_next(state, f)) == 0) { ++ ret = hinic3_agent_get_block_id_from_flow(f, &block_id, ds); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_GET_BLOCK_ID_FROM_FLOW_FAILED_STRING); ++ break; ++ } ++ if (block_id_input == block_id) { ++ if (dump_flows <= HINIC3_DUMP_FLOWS_MAX_ONCE) { ++ hinic3_agent_flow_format_output(f, ds); ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ total_loss_pkts += f->stats.ct_loss_pkts; ++ dump_flows++; ++ } ++ } ++ (void)hinic3_cmd_flow_dump_done(state); ++ hinic3_ds_put_format_prefix(ds, INDENT_0, HINIC3_UI_LEADING_SIGN_INFO, " %s%" PRIu32 ", %s%" PRIu64 ".\n", ++ HINIC3_UI_FLOW_DUMP_TOTAL_FLOW_STRING, dump_flows, HINIC3_UI_FLOW_DUMP_TOTAL_CT_LOST_PKT_STRING, total_loss_pkts); ++ if (dump_flows > HINIC3_DUMP_FLOWS_MAX_ONCE) { ++ hinic3_ds_clear(ds); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, ++ HINIC3_UI_FLOW_WITH_BLOCKID_UP_MAX_TIPS_STRING, block_id_input, dump_flows, HINIC3_DUMP_FLOWS_MAX_ONCE); ++ } ++ hinic3_agent_free_mem_for_flow(f); ++ hinic3_set_dumping_status(mgmt, HINIC3_DUMP_FLOWS_IDLE); ++ return 0; ++} ++ ++static int ++hinic3_agent_dump_flows_by_block_id(int argc, const char *argv[], struct ds *ds) ++{ ++ enum {ARGC = 3}; ++ if (argc != ARGC) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ ++ uint32_t block_num = 0; ++ uint16_t block_id_input = 0; ++ char *endPtr = NULL; ++ int ret = hinic3_flow_get_block_table_size(&block_num); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_DUMP_GET_BLOCK_SIZE_FAILED_STRING); ++ return -1; ++ } ++ ++ block_id_input = strtoul((char *)argv[ARGC - 1], &endPtr, DEC_BASE_NUM); ++ if (block_id_input >= block_num || endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_FLOW_DUMP_BLOCK_ID_ERROR_STRING); ++ return -1; ++ } ++ ++ struct hinic3_dpif_flow_for_get f = {0}; ++ return hinic3_agent_dump_flows_to_screen_by_block_id(&f, block_id_input, ds); ++} ++ ++static int ++hinic3_agent_process_dump_option(int index, int argc, const char *argv[], struct ds *ds) ++{ ++ int option_val = hinic3_find_option(argv[index]); ++ if (option_val == -1) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_ERROR_UNRECOGNIZED_COMMAND); ++ return -1; ++ } ++ ++ switch (option_val) { ++ case HINIC3_UFID_64_OPT: ++ return hinic3_agent_dump_specific_flow(argc, argv, ds); ++ ++ case HINIC3_STOP_DUMP_ALL_FLOWS_OPT: ++ return hinic3_agent_force_stop_dump_all_flows_to_file(argc, argv, ds); ++ ++ case HINIC3_CHECK_DUMP_ALL_FLOWS_OPT: ++ return hinic3_agent_check_status_dump_flows_to_file(argc, ds); ++ ++ case HINIC3_FLOW_FILE_OPT: ++ return hinic3_agent_dump_flows_to_file(argc, argv, ds); ++ ++ case HINIC3_FLOW_CNT_OPT: ++ return hinic3_agent_get_flows_cnt(argc, ds); ++ ++ case HELP_OPT: ++ hinic3_agent_dump_flows_help(ds); ++ break; ++ ++ case HINIC3_FLOW_BLOCK_ID_OPT: ++ return hinic3_agent_dump_flows_by_block_id(argc, argv, ds); ++ ++ default: ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_ERROR_UNRECOGNIZED_COMMAND); ++ return -1; ++ } ++ return 0; ++} ++ ++void ++hinic3_agent_dump_hinic3_flows(struct unixctl_conn *conn, int argc, const char *argv[], void *aux, ++ enum hinic3_flow_type type) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ int ret; ++ enum { ++ ARGC = 1 ++ }; ++ ++ if (type != hinic3_cmd_get_flow_ops_status()) { ++ hinic3_ds_put_format(&ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_DUMP_ALL_FLOW_TIPS_STRING); ++ ret = -1; ++ goto out; ++ } ++ ++ if (argc == ARGC) { ++ ret = hinic3_agent_dump_flows(&ds); ++ goto out; ++ } ++ if (type == HINIC3_FLOW_TYPE_DPHASH) { ++ hinic3_ds_put_format(&ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ ret = -1; ++ goto out; ++ } ++ ret = hinic3_agent_process_dump_option(ARGC, argc, argv, &ds); ++ ++out: ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = -1; ++ } else { ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = 0; ++ } ++ hinic3_ds_destroy(&ds); ++} ++ ++void ++hinic3_agent_dump_hinic3_flow_init(void) ++{ ++ hinic3_cmd_set_flow_key_format_output_ops(hinic3_flow_key_format_output); ++} ++ ++void ++hinic3_agent_dump_hinic3_emc_flows(struct unixctl_conn *conn, int argc, const char *argv[], ++ void *aux) ++{ ++ hinic3_agent_dump_hinic3_emc_flow_init(); ++ hinic3_agent_dump_hinic3_flows(conn, argc, argv, aux, HINIC3_FLOW_TYPE_EMC); ++} ++ ++void ++unixctl_hinic3_flow_dump_cmd_init(void) ++{ ++ enum hinic3_flow_cmd_max { ++ DUMP_HINIC3_FLOWS_PARAM = 2, ++ }; ++ ++ hinic3_command_register("hwoff/dump-hinic3-flows", ++ "[ ufid | -n | -f | -i | check | stop | { -h | --help } ]", 0, ++ DUMP_HINIC3_FLOWS_PARAM, hinic3_agent_dump_hinic3_emc_flows, NULL); ++ hinic3_pthread_mutex_init(&dump_flows_mgmt.mutex_lock); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.h +new file mode 100644 +index 0000000..9b2d7b4 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.h +@@ -0,0 +1,152 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_AGENT_FLOW_DUMP_CMD_H ++#define HINIC3_AGENT_FLOW_DUMP_CMD_H ++ ++#include ++#include "hinic3_command.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_ds.h" ++#include "hinic3_flow_dump_public.h" ++#include "hinic3_mutex.h" ++#include "hinic3_agent_flow_cmd_dump.h" ++ ++#ifdef __cplusplus ++{ ++#endif ++ ++#define HINIC3_DUMP_FLOWS_MAX_ONCE 1000 ++#define HINIC3_DUMP_FLOWS_STOP_CHECK_PERIOD_MS 5 ++#define HINIC3_DUMP_FLOWS_STOP_TIME_OUT_MS 500 /* 500 ms */ ++ ++enum hinic3_dump_flows_status { ++ HINIC3_DUMP_FLOWS_IDLE = 0, ++ HINIC3_DUMP_FLOWS_RUNNING, ++ HINIC3_DUMP_FLOWS_STOP, ++}; ++ ++struct hinic3_dump_all_flows_mgmt_t { ++ pthread_t dump_thread; ++ FILE *file; ++ void *start; ++ uint16_t dumping; ++ struct hinic3_mutex mutex_lock; ++ struct hinic3_dpif_flow_for_get flow; ++}; ++ ++struct hinic3_dump_flow_count_t { ++ uint64_t loss_ct_pkts; ++ uint32_t flows; ++}; ++ ++struct hinic3_flow_dump_cmd { ++ int (*hinic3_flow_get_maxflows_ops)(uint32_t *); ++ int (*hinic3_flow_dump_start_ops)(void **); ++ int (*hinic3_flow_dump_next_ops)(void *, struct hinic3_dpif_flow_for_get *); ++ int (*hinic3_flow_dump_done_ops)(void *); ++ void (*hinic3_flow_key_format_output_ops)(const struct hinic3_nlattr *, struct ds *); ++ enum hinic3_flow_type type; ++}; ++ ++void unixctl_hinic3_flow_dump_cmd_init(void); ++void hinic3_agent_dump_hinic3_emc_flows(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, ++ void *aux HINIC3_UNUSED); ++ ++void hinic3_agent_dump_hinic3_flows(struct unixctl_conn *conn, int argc, const char *argv[], ++ void *aux, enum hinic3_flow_type type); ++void hinic3_agent_dump_hinic3_flow_init(void); ++struct hinic3_dump_all_flows_mgmt_t *hinic3_cmd_get_flow_dump_mgmt(void); ++struct hinic3_flow_dump_cmd *hinic3_cmd_get_flow_dump_ops(void); ++int hinic3_alloc_mem_for_flow(struct ds *ds, struct hinic3_dpif_flow_for_get *f); ++void hinic3_agent_free_mem_for_flow(struct hinic3_dpif_flow_for_get *f); ++ ++void hinic3_cmd_set_flow_get_maxflows_ops(int (*ops)(uint32_t *)); ++void hinic3_cmd_set_flow_dump_start_ops(int (*ops)(void **)); ++void hinic3_cmd_set_flow_dump_next_ops(int (*ops)(void *, struct hinic3_dpif_flow_for_get *)); ++void hinic3_cmd_set_flow_dump_done_ops(int (*ops)(void *)); ++void hinic3_cmd_set_flow_key_format_output_ops(void (*ops)(const struct hinic3_nlattr *, struct ds *)); ++void hinic3_cmd_set_flow_ops_status(enum hinic3_flow_type type); ++ ++int hinic3_agent_force_stop_dump_all_flows_to_file(int argc, const char *argv[], struct ds *ds); ++int hinic3_agent_check_status_dump_flows_to_file(int argc, struct ds *ds); ++int hinic3_agent_dump_flows_to_file(int argc, const char *argv[], struct ds *ds); ++ ++static inline void hinic3_set_dumping_status(struct hinic3_dump_all_flows_mgmt_t *mgmt, uint16_t status) ++{ ++ if (mgmt == NULL) { ++ return; ++ } ++ ++ hinic3_pthread_mutex_lock(&mgmt->mutex_lock); ++ mgmt->dumping = status; ++ hinic3_pthread_mutex_unlock(&mgmt->mutex_lock); ++} ++ ++static inline uint16_t hinic3_get_dumping_status(struct hinic3_dump_all_flows_mgmt_t *mgmt) ++{ ++ if (mgmt == NULL) ++ return 0; ++ uint16_t status; ++ hinic3_pthread_mutex_lock(&mgmt->mutex_lock); ++ status = mgmt->dumping; ++ hinic3_pthread_mutex_unlock(&mgmt->mutex_lock); ++ return status; ++} ++ ++static inline enum hinic3_flow_type hinic3_cmd_get_flow_ops_status(void) ++{ ++ struct hinic3_flow_dump_cmd *ops = hinic3_cmd_get_flow_dump_ops(); ++ if (ops == NULL) ++ return -1; ++ return ops->type; ++} ++ ++static inline int hinic3_cmd_flow_get_maxflows(uint32_t *max_flow_cnt) ++{ ++ struct hinic3_flow_dump_cmd *ops = hinic3_cmd_get_flow_dump_ops(); ++ if (ops == NULL || ops->hinic3_flow_get_maxflows_ops == NULL) ++ return -1; ++ return ops->hinic3_flow_get_maxflows_ops(max_flow_cnt); ++} ++ ++static inline int hinic3_cmd_flow_dump_start(void **state) ++{ ++ struct hinic3_flow_dump_cmd *ops = hinic3_cmd_get_flow_dump_ops(); ++ if (ops == NULL || ops->hinic3_flow_dump_start_ops == NULL) ++ return -1; ++ return ops->hinic3_flow_dump_start_ops(state); ++} ++ ++static inline int hinic3_cmd_flow_dump_next(void *state, struct hinic3_dpif_flow_for_get *get) ++{ ++ struct hinic3_flow_dump_cmd *ops = hinic3_cmd_get_flow_dump_ops(); ++ if (ops == NULL || ops->hinic3_flow_dump_next_ops == NULL) ++ return -1; ++ return ops->hinic3_flow_dump_next_ops(state, get); ++} ++ ++static inline int hinic3_cmd_flow_dump_done(void *state) ++{ ++ struct hinic3_flow_dump_cmd *ops = hinic3_cmd_get_flow_dump_ops(); ++ if (ops == NULL || ops->hinic3_flow_dump_done_ops == NULL) ++ return -1; ++ return ops->hinic3_flow_dump_done_ops(state); ++} ++ ++static inline void hinic3_cmd_flow_key_format_output(const struct hinic3_nlattr *key, struct ds *ds) ++{ ++ struct hinic3_flow_dump_cmd *ops = hinic3_cmd_get_flow_dump_ops(); ++ if (ops == NULL || ops->hinic3_flow_key_format_output_ops == NULL) ++ return; ++ ops->hinic3_flow_key_format_output_ops(key, ds); ++} ++ ++ ++#ifdef __cplusplus ++} ++#endif ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +new file mode 100644 +index 0000000..852ed94 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +@@ -0,0 +1,302 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_agent_flow_cmd_dump.h" ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_mutex.h" ++#include "hinic3_file_util.h" ++#include "hinic3_util.h" ++#include "hinic3_agent_cmd_format.h" ++#include "rte_string_fns.h" ++ ++int ++hinic3_agent_force_stop_dump_all_flows_to_file(int argc, const char *argv[], struct ds *ds) ++{ ++ enum { ++ ARGC = 2 ++ }; ++ if (argc != ARGC) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ ++ struct hinic3_dump_all_flows_mgmt_t *mgmt = hinic3_cmd_get_flow_dump_mgmt(); ++ uint64_t drain_tsc = (rte_get_tsc_hz() / US_PER_MS); ++ uint64_t start_tsc; ++ uint64_t diff_tsc; ++ ++ hinic3_pthread_mutex_lock(&mgmt->mutex_lock); ++ if (mgmt->dumping == HINIC3_DUMP_FLOWS_IDLE) { ++ hinic3_pthread_mutex_unlock(&mgmt->mutex_lock); ++ HINIC3_LOG(INFO, AGENT, "dump all flows into file stopped\n"); ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMP_STOP_DUMP_SUCCESS_STRING); ++ return 0; ++ } ++ ++ mgmt->dumping = HINIC3_DUMP_FLOWS_STOP; ++ hinic3_pthread_mutex_unlock(&mgmt->mutex_lock); ++ start_tsc = rte_rdtsc(); ++ while (hinic3_get_dumping_status(mgmt) == HINIC3_DUMP_FLOWS_STOP) { ++ diff_tsc = rte_rdtsc() - start_tsc; ++ if (diff_tsc > drain_tsc * HINIC3_DUMP_FLOWS_STOP_TIME_OUT_MS) { ++ HINIC3_LOG(INFO, AGENT, "Dump all flows into file stopped time out ,please try again\n"); ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_DUMP_STOP_DUMP_TIME_OUT_STRING); ++ return -1; ++ } ++ rte_delay_ms(HINIC3_DUMP_FLOWS_STOP_CHECK_PERIOD_MS); ++ } ++ ++ HINIC3_LOG(INFO, AGENT, "dump all flows into file stopped\n"); ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMP_STOP_DUMP_SUCCESS_STRING); ++ return 0; ++} ++ ++int ++hinic3_agent_check_status_dump_flows_to_file(int argc, struct ds *ds) ++{ ++ enum { ++ ARGC = 2 ++ }; ++ if (argc != ARGC) { ++ hinic3_ds_put_format_prefix(ds, INDENT_0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, ARGC - 1); ++ return -1; ++ } ++ ++ struct hinic3_dump_all_flows_mgmt_t *mgmt = hinic3_cmd_get_flow_dump_mgmt(); ++ if (hinic3_get_dumping_status(mgmt) == HINIC3_DUMP_FLOWS_RUNNING) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMPIMG_TO_FILE_STRING); ++ } else { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMP_TO_FILE_COMPLETE_STRING); ++ } ++ return 0; ++} ++ ++static int ++hinic3_agent_parse_output_file_path(struct hinic3_dump_all_flows_mgmt_t *m, int index, const char *argv[], ++ struct ds *ds) ++{ ++ char absolute_path[PATH_MAX]; ++ ++ if (strlen(argv[index]) >= PATH_MAX) { ++ m->file = NULL; ++ hinic3_ds_put_format(ds, "%s%s", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_FILE_PATH_LENGTH_TIPS_STRING); ++ return -1; ++ } ++ ++ int ret = hinic3_check_output_file_directory(argv[index], absolute_path, sizeof(absolute_path), ds); ++ if (ret != 0) { ++ m->file = NULL; ++ return -1; ++ } ++ ++ char *resolve_path = (char *)hinic3_calloc(1, PATH_MAX + 1, HINIC3_COMMAND); ++ if (resolve_path == NULL) { ++ m->file = NULL; ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FILE_PATH_MALLOC_TIPS_STRING); ++ return -1; ++ } ++ ++ ret = hinic3_check_file_realpath(absolute_path, resolve_path, ds); ++ if (ret != 0) { ++ m->file = NULL; ++ goto fail; ++ } ++ ++ m->file = fopen(resolve_path, "a+"); ++ ++ if (m->file == NULL) { ++ hinic3_ds_put_format(ds, HINIC3_UI_FILE_OPEN_FAILED_STRING, HINIC3_UI_LEADING_SIGN_ERROR, resolve_path); ++ goto fail; ++ } ++ ++ if (hinic3_agent_chown_output_file_path(resolve_path) != 0) { ++ fclose(m->file); ++ m->file = NULL; ++ goto fail; ++ } ++ ++ hinic3_free(resolve_path); ++ return 0; ++ ++fail: ++ hinic3_free(resolve_path); ++ return -1; ++} ++ ++static void ++hinic3_agent_dump_all_flows_to_file_stop(struct hinic3_dump_all_flows_mgmt_t *m) ++{ ++ hinic3_set_dumping_status(m, HINIC3_DUMP_FLOWS_IDLE); ++ if (m->file != NULL) ++ fclose(m->file); ++ if (m->start != NULL) ++ (void)hinic3_cmd_flow_dump_done(m->start); ++ m->file = NULL; ++ m->start = NULL; ++ hinic3_agent_free_mem_for_flow(&m->flow); ++} ++ ++static int ++hinic3_dump_flows_run(struct hinic3_dump_all_flows_mgmt_t *m, struct hinic3_dump_flow_count_t *flow_count) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ size_t len; ++ int ret; ++ int i; ++ ++ for (i = 0; i < HINIC3_DUMP_FLOWS_MAX_ONCE; i++) { ++ ret = hinic3_cmd_flow_dump_next(m->start, &m->flow); ++ if (ret != 0) ++ break; ++ hinic3_agent_flow_format_output(&m->flow, &ds); ++ flow_count->loss_ct_pkts += m->flow.stats.ct_loss_pkts; ++ flow_count->flows++; ++ if (hinic3_get_dumping_status(m) == HINIC3_DUMP_FLOWS_STOP) { ++ ret = -1; ++ break; ++ } ++ } ++ len = fwrite(hinic3_ds_cstr(&ds), strlen(hinic3_ds_cstr(&ds)), 1, m->file); ++ if (((len != 1) || (ferror(m->file) != 0)) && ret != HIOVS_EEMPTY) { ++ HINIC3_LOG(WARNING, AGENT, "dump all flows to file failed !"); ++ ret = -1; ++ } ++ ++ hinic3_ds_destroy(&ds); ++ ++ return ret; ++} ++ ++static void * ++hinic3_dump_flows_running_thread(void *args) ++{ ++ struct hinic3_dump_all_flows_mgmt_t *m = hinic3_cmd_get_flow_dump_mgmt(); ++ struct hinic3_dump_flow_count_t flow_count = {0}; ++ size_t len; ++ int ret; ++ ++ char *name = "hinic3_dump_flow"; ++ ret = hinic3_set_thread_name_by_str(name); ++ if (ret != 0) ++ HINIC3_LOG(WARNING, AGENT, "set dump flow thread name failed!"); ++ ++ if (m->flow.actions == NULL || m->flow.key == NULL || m->flow.mask == NULL) { ++ hinic3_agent_dump_all_flows_to_file_stop(m); ++ return NULL; ++ } ++ ++ do { ++ ret = hinic3_dump_flows_run(m, &flow_count); ++ } while (ret == 0); ++ ++ struct ds ds_flow = DS_EMPTY_INITIALIZER; ++ hinic3_ds_put_format(&ds_flow, "%s%" PRIu32 ", %s%" PRIu64 "\n", HINIC3_UI_FLOW_DUMP_TOTAL_FLOW_STRING, ++ flow_count.flows, HINIC3_UI_FLOW_DUMP_TOTAL_CT_LOST_PKT_STRING, flow_count.loss_ct_pkts); ++ ++ len = fwrite(hinic3_ds_cstr(&ds_flow), strlen(hinic3_ds_cstr(&ds_flow)), 1, m->file); ++ if ((len != 1) && (ferror(m->file) != 0)) ++ HINIC3_LOG(WARNING, AGENT, "dump flow statistics to file failed !"); ++ ++ hinic3_ds_destroy(&ds_flow); ++ hinic3_agent_dump_all_flows_to_file_stop(m); ++ return NULL; ++} ++ ++static int ++hinic3_agent_dump_all_flows_to_file_run(struct hinic3_dump_all_flows_mgmt_t *m, struct ds *ds) ++{ ++ int ret; ++ struct hinic3_dump_all_flows_mgmt_t *mgmt = hinic3_cmd_get_flow_dump_mgmt(); ++ ++ if (hinic3_get_dumping_status(m) == HINIC3_DUMP_FLOWS_STOP) { ++ hinic3_agent_dump_all_flows_to_file_stop(m); ++ return 0; ++ } ++ ++ if (hinic3_get_dumping_status(m) == HINIC3_DUMP_FLOWS_RUNNING) { ++ ret = pthread_create(&mgmt->dump_thread, NULL, hinic3_dump_flows_running_thread, NULL); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_DUMP_RUN_THREAD_FAILED_STRING); ++ return -1; ++ } ++ hinic3_set_ctrl_thread_cpu_affinity(&mgmt->dump_thread); ++ return 0; ++ } ++ return 0; ++} ++ ++ ++static int ++hinic3_agent_dump_all_flows_to_file_start(struct hinic3_dump_all_flows_mgmt_t *m, struct ds *ds) ++{ ++ int ret; ++ hinic3_pthread_mutex_lock(&m->mutex_lock); ++ if (m->dumping == HINIC3_DUMP_FLOWS_RUNNING) { ++ hinic3_pthread_mutex_unlock(&m->mutex_lock); ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_DUMP_FLOW_BUSY_STRING); ++ return -1; ++ } ++ m->dumping = HINIC3_DUMP_FLOWS_RUNNING; ++ hinic3_pthread_mutex_unlock(&m->mutex_lock); ++ ++ ret = hinic3_cmd_flow_dump_start(&m->start); ++ if (ret != 0) { ++ if (ret != HOWFF_NO_FLOW_ERR) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_FLOW_DUMP_ALL_FLOW_START_FAILED_STRING); ++ } else { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMP_NO_AVALIBLE_FLOW_STRING); ++ } ++ hinic3_agent_dump_all_flows_to_file_stop(m); ++ hinic3_set_dumping_status(m, HINIC3_DUMP_FLOWS_IDLE); ++ return -1; ++ } ++ ret = hinic3_alloc_mem_for_flow(ds, &m->flow); ++ if (ret != 0) { ++ hinic3_agent_dump_all_flows_to_file_stop(m); ++ hinic3_set_dumping_status(m, HINIC3_DUMP_FLOWS_IDLE); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, "%s%s\n", ++ HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_FLOW_DUMP_ALL_FLOW_START_SUCCESS_STRING); ++ ++ return 0; ++} ++ ++int ++hinic3_agent_dump_flows_to_file(int argc, const char *argv[], struct ds *ds) ++{ ++ struct hinic3_dump_all_flows_mgmt_t *mgmt = hinic3_cmd_get_flow_dump_mgmt(); ++ enum { ++ ARGC = 3 ++ }; ++ ++ if (hinic3_get_dumping_status(mgmt) != HINIC3_DUMP_FLOWS_IDLE) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_DUMP_ALL_FLOW_TIPS_STRING); ++ return -1; ++ } ++ if (argc != ARGC) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ if ((hinic3_get_dumping_status(mgmt) == HINIC3_DUMP_FLOWS_RUNNING) || mgmt->file || mgmt->start) { ++ hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_FAILURE, HINIC3_UI_FLOW_DUMP_FLOW_BUSY_STRING); ++ return -1; ++ } ++ memset(&mgmt->flow, 0, sizeof(struct hinic3_dpif_flow_for_get)); ++ int ret = hinic3_agent_parse_output_file_path(mgmt, ARGC - 1, argv, ds); ++ if (ret != 0) ++ return -1; ++ ret = hinic3_agent_dump_all_flows_to_file_start(mgmt, ds); ++ if (ret != 0) ++ return -1; ++ return hinic3_agent_dump_all_flows_to_file_run(mgmt, ds); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c +new file mode 100644 +index 0000000..ab6c98b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c +@@ -0,0 +1,472 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_util.h" ++ ++#define HINIC3_FLOW_SPEED_ARG_GAP 2 ++ ++struct hinic3_speed_measure_task_t g_offload_speed_task = { ++ .alive = false, ++ .mutex = HINIC3_MUTEX_INITIALIZER, ++}; ++ ++static int ++hinic3_speed_parse_int_arg(const char *str_value, int min, int max, uint32_t *dst_value) ++{ ++ uint32_t tmp_value; ++ if (is_valid_digit(str_value) == false) ++ return -1; ++ ++ tmp_value = strtoul(str_value, NULL, STR_TO_DEC_NUM); ++ if (tmp_value < min || tmp_value > max) ++ return -1; ++ ++ *dst_value = tmp_value; ++ return 0; ++} ++ ++static int ++hinic3_speed_parse_cmd_argv(int argc, const char *argv[], struct hinic3_speed_cmd_param_t *param, ++ struct ds *ds) ++{ ++ int i; ++ int ret; ++ int work_argc = argc; ++ const char **work_argv = argv; ++ ++ i = 0; ++ work_argc -= 1; ++ work_argv += 1; ++ while (i < work_argc) { ++ if (i + 1 >= work_argc) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_ERROR_TOO_MANY_PARAMETER ".\n"); ++ return -1; ++ } ++ ++ if (strcmp("-i", work_argv[i]) == 0) { ++ ret = hinic3_speed_parse_int_arg(work_argv[i + 1], HINIC3_SPPED_MIN_INTERVAL, HINIC3_SPPED_MAX_INTERVAL, ++ ¶m->interval); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, ++ HINIC3_UI_LEADING_SIGN_ERROR "Invalid interval value, should be an integer range <%u-%u>.\n", ++ HINIC3_SPPED_MIN_INTERVAL, HINIC3_SPPED_MAX_INTERVAL); ++ return -1; ++ } ++ ++ i += HINIC3_FLOW_SPEED_ARG_GAP; ++ continue; ++ } ++ ++ if (strcmp("-t", work_argv[i]) == 0) { ++ ret = hinic3_speed_parse_int_arg(work_argv[i + 1], HINIC3_SPPED_MIN_SAMPLE, HINIC3_SPPED_MAX_SAMPLE, ++ ¶m->total_samples); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, ++ HINIC3_UI_LEADING_SIGN_ERROR "Invalid samples value, should be an integer range <%u-%u>.\n", ++ HINIC3_SPPED_MIN_SAMPLE, HINIC3_SPPED_MAX_SAMPLE); ++ return -1; ++ } ++ ++ i += HINIC3_FLOW_SPEED_ARG_GAP; ++ continue; ++ } ++ ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR ++ HINIC3_UI_ERROR_UNRECOGNIZED_COMMAND ", please type -h or --help for help.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void ++hinic3_speed_task_wait(struct hinic3_speed_measure_task_t *task) ++{ ++ hinic3_pthread_mutex_lock(&task->mutex); ++ hinic3_mutex_cond_wait(&task->cond, &task->mutex); ++ hinic3_pthread_mutex_unlock(&task->mutex); ++} ++ ++static int ++hinic3_speed_task_wakeup(struct hinic3_speed_measure_task_t *task) ++{ ++ int ret; ++ hinic3_pthread_mutex_lock(&task->mutex); ++ ret = hinic3_thread_cond_signal(&task->cond); ++ hinic3_pthread_mutex_unlock(&task->mutex); ++ return ret; ++} ++ ++static void ++hinic3_speed_fetch_samples(struct hinic3_speed_measure_task_t *task) ++{ ++ uint32_t tmp_value; ++ ++ task->status = HINIC3_SPEED_TASK_ST_SAMPLING; ++ while (true) { ++ tmp_value = hinic3_get_offload_flow_nums(); ++ task->sample_list[task->count] = tmp_value; ++ task->count++; ++ sleep(task->interval); ++ ++ if (task->count >= task->total_samples) ++ break; ++ } ++ task->status = HINIC3_SPEED_TASK_ST_IDLE; ++ ++ return; ++} ++ ++static void ++hinic3_speed_show_speeds(struct hinic3_speed_measure_task_t *task, struct ds *ds) ++{ ++ uint32_t i; ++ uint32_t pre_value; ++ uint32_t value; ++ uint32_t diff; ++ uint32_t speed; ++ ++ hinic3_ds_put_format(ds, "%2ssamples: count=%u, [", HINIC3_UI_INDENT_SPACE, task->count); ++ for (i = 0; i < task->count; i++) { ++ if (i == task->count - 1) { ++ hinic3_ds_put_format(ds, "%1s%u ]\n", HINIC3_UI_INDENT_SPACE, task->sample_list[i]); ++ } else { ++ hinic3_ds_put_format(ds, "%1s%u,", HINIC3_UI_INDENT_SPACE, task->sample_list[i]); ++ } ++ } ++ ++ if (task->count <= 1) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_FAILURE "Too few samples,can't calculate speed.\n"); ++ return; ++ } ++ ++ pre_value = task->sample_list[0]; ++ for (i = 1; i < task->count; i++) { ++ value = task->sample_list[i]; ++ if (value < pre_value) { ++ hinic3_ds_put_format(ds, "%2s%u\n", HINIC3_UI_INDENT_SPACE, 0); ++ pre_value = value; ++ continue; ++ } ++ ++ diff = value - pre_value; ++ speed = task->interval == 0 ? 0 : diff / task->interval; ++ hinic3_ds_put_format(ds, "%2s%u\n", HINIC3_UI_INDENT_SPACE, speed); ++ pre_value = value; ++ } ++ ++ return; ++} ++ ++static void* ++hinic3_speed_measure_thread(void *args) ++{ ++ struct hinic3_speed_measure_task_t *task = (struct hinic3_speed_measure_task_t *)args; ++ ++ char *name = "hinic3_speed_measure"; ++ int ret = hinic3_set_thread_name_by_str(name); ++ if (ret != 0) ++ HINIC3_LOG(WARNING, AGENT, "set speed measure thread name failed!"); ++ ++ while (true) { ++ hinic3_speed_fetch_samples(task); ++ if (task->command == HINIC3_SPEED_TASK_CMD_STOP) { ++ break; ++ } else if (task->command == HINIC3_SPEED_TASK_CMD_RESTART) { ++ task->count = 0; ++ task->command = 0; ++ continue; ++ } ++ ++ while (true) { ++ hinic3_speed_task_wait(task); ++ if (task->command == 0) { ++ continue; ++ } else { ++ break; ++ } ++ } ++ ++ if (task->command == HINIC3_SPEED_TASK_CMD_STOP) { ++ break; ++ } else if (task->command == HINIC3_SPEED_TASK_CMD_RESTART) { ++ task->count = 0; ++ task->command = 0; ++ continue; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int ++hinic3_speed_measure_thread_create(struct hinic3_speed_measure_task_t *task, ++ struct hinic3_speed_cmd_param_t *param, struct ds *ds) ++{ ++ int ret = 0; ++ ++ task->interval = param->interval; ++ task->total_samples = param->total_samples; ++ task->count = 0; ++ task->command = 0; ++ task->status = HINIC3_SPEED_TASK_ST_IDLE; ++ ret = hinic3_thread_cond_init(&task->cond, NULL); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to create thread cond.\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_FAILURE "Internal failure.\n"); ++ return -1; ++ } ++ ret = pthread_create(&task->thread, NULL, hinic3_speed_measure_thread, task); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Create thread fail.\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_FAILURE "Internal failure.\n"); ++ return -1; ++ } ++ task->alive = true; ++ hinic3_set_ctrl_thread_cpu_affinity(&task->thread); ++ return 0; ++} ++ ++static int ++hinic3_speed_task_cmd_start(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ int ret; ++ struct hinic3_speed_cmd_param_t param; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_speed_measure_task_t *task = &g_offload_speed_task; ++ ++ if (task->alive) { ++ hinic3_ds_put_format(&ds, ++ HINIC3_UI_LEADING_SIGN_FAILURE "Offload speed task is still alive, please use restart.\n"); ++ goto fail; ++ } ++ ++ param.interval = 0; ++ param.total_samples = 0; ++ ret = hinic3_speed_parse_cmd_argv(argc, argv, ¶m, &ds); ++ if (ret != 0) ++ goto fail; ++ if (param.interval == 0 || param.total_samples < 1) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_ERROR_INCOMPLETE_COMMAND ".\n"); ++ goto fail; ++ } ++ ++ ret = hinic3_speed_measure_thread_create(task, ¶m, &ds); ++ if (ret != 0) ++ goto fail; ++ ++ HINIC3_LOG(INFO, AGENT, "Offload speed measure start success, interval is %u(s), samples is %u.\n", task->interval, ++ task->total_samples); ++ hinic3_ds_put_format(&ds, ++ HINIC3_UI_LEADING_SIGN_INFO "Offload speed measure start success, interval is %u(s), samples is %u.\n", ++ task->interval, task->total_samples); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++fail: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int ++hinic3_speed_task_cmd_restart(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ int ret; ++ struct hinic3_speed_cmd_param_t param; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_speed_measure_task_t *task = &g_offload_speed_task; ++ ++ if (!task->alive) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Offload speed task is not alive, please use start.\n"); ++ goto fail; ++ } ++ ++ if (task->status != HINIC3_SPEED_TASK_ST_IDLE) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Offload speed task is sampling, do it later.\n"); ++ goto fail; ++ } ++ ++ param.interval = 0; ++ param.total_samples = 0; ++ ret = hinic3_speed_parse_cmd_argv(argc, argv, ¶m, &ds); ++ if (ret != 0) ++ goto fail; ++ ++ if (param.interval != 0) ++ task->interval = param.interval; ++ if (param.total_samples != 0) ++ task->total_samples = param.total_samples; ++ task->command = HINIC3_SPEED_TASK_CMD_RESTART; ++ ret = hinic3_speed_task_wakeup(task); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Failed to wakeup speed task.\n"); ++ goto fail; ++ } ++ HINIC3_LOG(INFO, AGENT, "offload speed measure restart success, interval is %u(s), samples is %u!\n", task->interval, ++ task->total_samples); ++ hinic3_ds_put_format(&ds, ++ HINIC3_UI_LEADING_SIGN_INFO "Offload speed measure restart success, interval is %u(s), samples is %u.\n", ++ task->interval, task->total_samples); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++fail: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int ++hinic3_speed_task_cmd_stop(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_speed_measure_task_t *task = &g_offload_speed_task; ++ ++ if (argc > 1) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_ERROR_TOO_MANY_PARAMETER ".\n"); ++ goto fail; ++ } ++ ++ if (!task->alive) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Offload speed task is not alive.\n"); ++ goto fail; ++ } ++ ++ if (task->status == HINIC3_SPEED_TASK_ST_SAMPLING) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Offload speed task is sampling, do it later.\n"); ++ goto fail; ++ } ++ ++ task->alive = false; ++ task->command = HINIC3_SPEED_TASK_CMD_STOP; ++ ret = hinic3_speed_task_wakeup(task); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, "Failed to wakeup speed task.\n"); ++ goto fail; ++ } ++ pthread_join(task->thread, NULL); ++ ret = hinic3_thread_cond_destroy(&task->cond); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to destroy thread cond.\n"); ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Internal failure.\n"); ++ goto fail; ++ } ++ HINIC3_LOG(INFO, AGENT, "offload speed measure stop success.\n"); ++ hinic3_command_reply(conn, HINIC3_UI_LEADING_SIGN_INFO "Offload speed measure stop success.\n"); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++fail: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int ++hinic3_speed_task_cmd_show(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_speed_measure_task_t *task = &g_offload_speed_task; ++ ++ if (argc > 1) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_ERROR_TOO_MANY_PARAMETER ".\n"); ++ goto fail; ++ } ++ ++ if (!task->alive) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Offload speed task is not alive.\n"); ++ goto fail; ++ } ++ ++ if (task->status == HINIC3_SPEED_TASK_ST_SAMPLING) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Offload speed task is sampling, do it later.\n"); ++ goto fail; ++ } ++ ++ hinic3_speed_show_speeds(task, &ds); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++fail: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int ++hinic3_speed_task_cmd_help(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ char *help_desc = " start Start the offload speed measuring task\n" ++ " -i Interval, in second. It is an integer with a range <1-10>\n" ++ " -t Sample number, an integer with a range <1-300>\n" ++ " restart Restart the offload speed measuring task\n" ++ " -i Interval, in second. It is an integer with a range <1-10>\n" ++ " -t Sample number, an integer with a range <1-300>\n" ++ " show Show the offload speed\n" ++ " stop Stop the offload speed measuring task\n" ++ " -h, --help Display the help information\n"; ++ ++ hinic3_ds_put_format(&ds, ++ "%2sUsage: dpak-ovs-ctl hwoff/flow-offload-speed-stat { " ++ "start -i INTEGER<1-10> -t INTEGER<1-300> | \n%54srestart [ -i " ++ "INTEGER<1-10> | -t INTEGER<1-300> ] * | \n%54sstop | show | { -h | --help } }\n", ++ HINIC3_UI_INDENT_SPACE, HINIC3_UI_INDENT_SPACE, HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_OPTION_LIST_STRING); ++ hinic3_ds_put_format(&ds, help_desc); ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++} ++ ++void ++hinic3_speed_task_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int work_argc; ++ const char **work_argv = argv + 1; ++ const char *sub_cmd_name = NULL; ++ ++ work_argc = argc - 1; ++ sub_cmd_name = work_argv[0]; ++ ++ if (strcmp("start", sub_cmd_name) == 0) { ++ *(int *)aux = hinic3_speed_task_cmd_start(conn, work_argc, work_argv); ++ return; ++ } ++ ++ if (strcmp("restart", sub_cmd_name) == 0) { ++ *(int *)aux = hinic3_speed_task_cmd_restart(conn, work_argc, work_argv); ++ return; ++ } ++ ++ if (strcmp("show", sub_cmd_name) == 0) { ++ *(int *)aux = hinic3_speed_task_cmd_show(conn, work_argc, work_argv); ++ return; ++ } ++ ++ if (strcmp("stop", sub_cmd_name) == 0) { ++ *(int *)aux = hinic3_speed_task_cmd_stop(conn, work_argc, work_argv); ++ return; ++ } ++ ++ if ((strcmp("-h", sub_cmd_name) == 0) || (strcmp("--help", sub_cmd_name) == 0)) { ++ *(int *)aux = hinic3_speed_task_cmd_help(conn, work_argc, work_argv); ++ return; ++ } ++ ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR ++ HINIC3_UI_ERROR_UNRECOGNIZED_COMMAND ", please type -h or --help for help.\n"); ++ return; ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c +new file mode 100644 +index 0000000..2114202 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c +@@ -0,0 +1,151 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_ds.h" ++#include "hinic3_log.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_error_stats.h" ++#include "hinic3_command.h" ++#include "hinic3_cmd_error_stats.h" ++#define HINIC3_ERROR_STATS_CMD_ARG_NUM_MIN 2 ++#define HINIC3_ERROR_STATS_CMD_ARG_NUM_MAX 3 ++ ++static const char* g_module_name[] = { ++ [HINIC3_COMMON_RESOURCE] = "hinic3-common", ++ [HINIC3_CAPTURE] = "hinic3-capture", ++ [HINIC3_COMMAND] = "hinic3-command", ++ [HINIC3_CT_OFFLOAD] = "hinic3-ct-offload", ++ [HINIC3_DRIVER_ADAPTER] = "hinic3-driver-adapter", ++ [HINIC3_FLOWS] = "hinic3-flows", ++ [HINIC3_OVS_FLOW] = "hinic3-ovs-flows", ++ [HINIC3_INIT] = "hinic3-init", ++ [HINIC3_POLICY] = "hinic3-policy", ++ [HINIC3_PORTS] = "hinic3-ports", ++ [HINIC3_QOS] = "hinic3-qos", ++ [HINIC3_SECURITY_FILTER] = "hinic3-security-filter", ++ [HINIC3_UFID_MAP] = "hinic3-ufid-map", ++ [HINIC3_OVS_MEMPOOL] = "hinic3-ovs-mempool", ++ [HINIC3_OVS_UFID_MEMPOOL] = "hinic3-ovs-ufid-mempool", ++ [HINIC3_OVS_UFID_MAP] = "hinic3-ovs-ufid-map", ++ [HINIC3_PACKET_PARSE] = "hinic3-packet-parse", ++ [HINIC3_OVS_SMAC] = "hinic3-ovs-smac", ++ [HINIC3_OVS_HINIC3_PRIVATE] = "hinic3-ovs-private-data", ++ [HIOVS_MEM] = "hiovs-mem", ++ [HINIC3_MODULE_MAX] = "unknown module", ++}; ++ ++static void ++hinic3_error_stats_print_module_sub(struct ds *output_str, enum hinic3_module module, ++ uint16_t level, bool *header) ++{ ++ int ret; ++ for (int error_idx = HINIC3_ERRSTAT_START + 1; error_idx < HINIC3_ERRSTAT_END; error_idx++) { ++ struct hinic3_error_stats stats = {0}; ++ char buf[HINIC3_ERROR_STRING_MAX_LEN] = {0}; ++ ret = hinic3_get_error_stats(error_idx, &stats); ++ if (ret != 0 || stats.count == 0 || stats.level != level || stats.module != module || stats.string == NULL) ++ continue; ++ if (*header == true) { ++ const char* name = g_module_name[module]; ++ if (name == NULL) { ++ HINIC3_LOG(ERR, AGENT, "Can not find module name!"); ++ return; ++ } ++ hinic3_ds_put_format(output_str, "%2s%s:\n", HINIC3_UI_INDENT_SPACE, name); ++ *header = false; ++ } ++ ret = snprintf(buf, sizeof(buf), "%s:", stats.string); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "snprintf for error_string failed."); ++ return; ++ } ++ hinic3_ds_put_format(output_str, "%4s%-50s%u\n", ++ HINIC3_UI_INDENT_SPACE, buf, stats.count); ++ } ++} ++ ++static void ++hinic3_error_stats_print_module(struct ds *output_str, uint16_t module, ++ enum hinic3_errstat_print_level print_level) ++{ ++ bool header = true; ++ // 先打印ERROR类型 ++ if ((print_level & HINIC3_ERRSTAT_PRINT_LEVEL_ERROR) == HINIC3_ERRSTAT_PRINT_LEVEL_ERROR) ++ hinic3_error_stats_print_module_sub(output_str, module, HINIC3_ERRSTAT_LEVEL_ERROR, &header); ++ // 再打印WARNING类型 ++ if ((print_level & HINIC3_ERRSTAT_PRINT_LEVEL_WARNING) == HINIC3_ERRSTAT_PRINT_LEVEL_WARNING) ++ hinic3_error_stats_print_module_sub(output_str, module, HINIC3_ERRSTAT_LEVEL_WARNING, &header); ++} ++ ++static int ++hinic3_error_stats_print_all_modules(struct ds *output_str, const char* level_str) ++{ ++ enum hinic3_errstat_print_level level = HINIC3_ERRSTAT_PRINT_LEVEL_NULL; ++ if (strcmp("all", level_str) == 0) { ++ level = HINIC3_ERRSTAT_PRINT_LEVEL_ALL; ++ } else if (strcmp("error", level_str) == 0) { ++ level = HINIC3_ERRSTAT_PRINT_LEVEL_ERROR; ++ } else if (strcmp("warning", level_str) == 0) { ++ level = HINIC3_ERRSTAT_PRINT_LEVEL_WARNING; ++ } else { ++ return -1; ++ } ++ for (int module_idx = 0; module_idx < HINIC3_MODULE_MAX; module_idx++) { ++ hinic3_error_stats_print_module(output_str, module_idx, level); ++ } ++ return 0; ++} ++static void ++hinic3_flow_agent_error_stats_cmd_help(struct ds *output_str) ++{ ++ hinic3_ds_put_format(output_str, ++ "%2sUsage: dpak-ovs-ctl hwoff/show-error-stats { -l ENUM | { -h | --help } }\n\n", ++ HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(output_str, "%2sOptions list:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(output_str, "%4s%-30sSpecify the level of printing\n", HINIC3_UI_INDENT_SPACE, "-l"); ++ hinic3_ds_put_format(output_str, "%6s%-28sPrint error and warning stats\n", HINIC3_UI_INDENT_SPACE, "all"); ++ hinic3_ds_put_format(output_str, "%6s%-28sPrint error level stats\n", HINIC3_UI_INDENT_SPACE, "error"); ++ hinic3_ds_put_format(output_str, "%6s%-28sPrint warning level stats\n", HINIC3_UI_INDENT_SPACE, "warning"); ++ hinic3_ds_put_format(output_str, "%4s%-30sShow help command\n", HINIC3_UI_INDENT_SPACE, "-h, --help"); ++} ++ ++void ++hinic3_flow_agent_error_stats_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ if (argc > HINIC3_ERROR_STATS_CMD_ARG_NUM_MAX || argc < HINIC3_ERROR_STATS_CMD_ARG_NUM_MIN) { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ *(int *)aux = -1; ++ return; ++ } ++ ++ int ret = 0; ++ struct ds output_str = DS_EMPTY_INITIALIZER; ++ if ((strcmp("-h", argv[1]) == 0) || (strcmp("--help", argv[1]) == 0)) { ++ hinic3_flow_agent_error_stats_cmd_help(&output_str); ++ } else if (strcmp("-l", argv[1]) == 0 && argc == HINIC3_ERROR_STATS_CMD_ARG_NUM_MAX) { ++ ret = hinic3_error_stats_print_all_modules(&output_str, argv[HINIC3_ERROR_STATS_CMD_ARG_NUM_MAX-1]); ++ if (ret != 0) { ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR "Invalid parameters.\n"); ++ goto end; ++ } ++ } else { ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR "Invalid parameters.\n"); ++ goto end; ++ } ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&output_str)); ++end: ++ hinic3_ds_destroy(&output_str); ++} ++ ++void ++unixctl_hinic3_cmd_error_stats_register() ++{ ++ hinic3_command_register("hwoff/show-error-stats", "", 1, 2, ++ hinic3_flow_agent_error_stats_cmd, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.h +new file mode 100644 +index 0000000..10cf76f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.h +@@ -0,0 +1,19 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_CMD_ERROR_STATS_H ++#define HINIC3_CMD_ERROR_STATS_H ++#include ++#include "hinic3_flow_agent_enum.h" ++#define HINIC3_ERROR_STRING_MAX_LEN 50 ++ ++enum hinic3_errstat_print_level { ++ HINIC3_ERRSTAT_PRINT_LEVEL_NULL = 0, ++ HINIC3_ERRSTAT_PRINT_LEVEL_ERROR = 1, ++ HINIC3_ERRSTAT_PRINT_LEVEL_WARNING = 2, ++ HINIC3_ERRSTAT_PRINT_LEVEL_ALL = 3 ++}; ++void hinic3_flow_agent_error_stats_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void unixctl_hinic3_cmd_error_stats_register(void); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.c +new file mode 100644 +index 0000000..f835fdf +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.c +@@ -0,0 +1,82 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_agent.h" ++#include "hinic3_log.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_dfx_port.h" ++#include "hinic3_mutex.h" ++#include "hinic3_vf_dfx.h" ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_command.h" ++#include "hinic3_ds.h" ++#include "hinic3_cmd_exec.h" ++ ++void ++unixctl_hinic3_lib_cmd_exec(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[], ++ void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ char *cmd_out = NULL; ++ uint32_t out_len = 0; ++ int ret = -1; ++ ++ cmd_out = (char *)hinic3_calloc(1, HINIC3_DFX_GLOABL_ALLOC_MEM_MAX_SIZE + 1, HINIC3_COMMAND); ++ if (cmd_out == NULL) { ++ hinic3_ds_put_format(&ds, "%sCmd out calloc failed!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ goto purging; ++ } ++ ++ if (strnlen(argv[1], HINIC3_CMD_MAX_LENGTH) >= HINIC3_CMD_MAX_LENGTH) { ++ hinic3_ds_put_format(&ds, "%sCommand too long!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ goto out; ++ } ++ ++ ret = hinic3_global_cmd_exec(argv[1], strnlen(argv[1], HINIC3_CMD_MAX_LENGTH), ++ cmd_out, &out_len, HINIC3_DFX_GLOABL_ALLOC_MEM_MAX_SIZE); ++ ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, "%sHinic3 cmd exec failed with error %d.\n", HINIC3_UI_LEADING_SIGN_ERROR, ret); ++ goto out; ++ } ++ ++ if (out_len > HINIC3_DFX_GLOABL_ALLOC_MEM_MAX_SIZE) { ++ HINIC3_LOG(WARNING, BOND, "hinic3 cmd exec reply out of memory"); ++ out_len = HINIC3_DFX_GLOABL_ALLOC_MEM_MAX_SIZE; ++ } ++ ++ if (out_len == 0) { ++ hinic3_ds_put_format(&ds, "%sHinic3 cmd exec no reply.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ goto out; ++ } ++ *(cmd_out + out_len) = '\0'; ++ hinic3_ds_put_format(&ds, "%s\n", cmd_out); ++out: ++ hinic3_free(cmd_out); ++purging: ++ if (ret == 0) { ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = 0; ++ } else { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = -1; ++ } ++ ++ hinic3_ds_destroy(&ds); ++} ++ ++void ++unixctl_hinic3_cmd_exec_register(void) ++{ ++ hinic3_command_register("hwoff/exec-cmd", ++ "{ dump { -t -x | -h } " ++ "| xstats { -i | -h } | nic_queue { -i -d " ++ "ENUM -t -q [ -w ] | -h } | hpd " ++ "{ -v | -m | -i -t | -h } | { -v | --version } | { -h | --help } }", ++ 1, 1, unixctl_hinic3_lib_cmd_exec, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.h +new file mode 100644 +index 0000000..85a1349 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_exec.h +@@ -0,0 +1,15 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef __HINIC3_CMD_EXEC_H__ ++#define __HINIC3_CMD_EXEC_H__ ++ ++#include "hinic3_command.h" ++#include "hinic3_util.h" ++ ++void unixctl_hinic3_lib_cmd_exec(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[], ++ void *aux HINIC3_UNUSED); ++void unixctl_hinic3_cmd_exec_register(void); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c +new file mode 100644 +index 0000000..465c57c +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c +@@ -0,0 +1,210 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_log.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_cmd_forward.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_command.h" ++ ++static void ++hinic3_forward_mode_set_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ enum hinic3_packet_forward_mod mode = 0; ++ int ret = 0; ++ ++ if (strcmp(argv[1], HINIC3_LOW_LATENCY_CMD_STR) == 0) { ++ mode = HINIC3_FORWARD_MODE_LATENCY; ++ } else if (strcmp(argv[1], HINIC3_HIGH_THROUGHPUT_CMD_STR) == 0) { ++ mode = HINIC3_FORWARD_MODE_BANDWIDTH; ++ } else { ++ *(int*)aux = -1; ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_SET_FORWARD_MODE_INPUT_ERROR_STRING); ++ return; ++ } ++ ++ if (mode == HINIC3_FORWARD_MODE_BANDWIDTH) ++ mode = HINIC3_FORWARD_MODE_30M; ++ ++ ret = hinic3_forward_mode_set(mode); ++ if (ret != 0) { ++ *(int*)aux = -1; ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_FAILURE HINIC3_SET_FORWARD_MODE_FAILED_STRING); ++ return; ++ } ++ ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, HINIC3_UI_LEADING_SIGN_INFO HINIC3_SET_FORWARD_MODE_SUCCESS_STRING); ++ return; ++} ++ ++static void ++hinic3_forward_mode_get_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds reply = DS_EMPTY_INITIALIZER; ++ int ret = 0; ++ ++ ret = hinic3_forward_mod_get(&reply); ++ if (ret != 0) { ++ *(int*)aux = -1; ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_FAILURE"get packet forward mode failed\n"); ++ hinic3_ds_destroy(&reply); ++ return; ++ } ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&reply)); ++ hinic3_ds_destroy(&reply); ++ *(int*)aux = 0; ++ return; ++} ++ ++static int ++hinic3_show_flow_escape_mode_help_info(struct ds *reply) ++{ ++ hinic3_ds_put_format(reply, "%2s%s%s\n\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_CMD_USAGE_STRING, HINIC3_UI_ESCAPE_MODE_HELP_TIPS_STRING); ++ hinic3_ds_put_format(reply, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_OPTION_LIST_STRING); ++ hinic3_ds_put_format(reply, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_ESCAPE_MODE_ENABLE_FORMAT_STRING, HINIC3_UI_ESCAPE_MODE_ENABLE_TIPS_STRING); ++ hinic3_ds_put_format(reply, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_ESCAPE_MODE_DISABLE_FORMAT_STRING, HINIC3_UI_ESCAPE_MODE_DISABLE_TIPS_STRING); ++ hinic3_ds_put_format(reply, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_ESCAPE_MODE_SHOW_FORMAT_STRING, HINIC3_UI_ESCAPE_MODE_SHOW_TIPS_STRING); ++ hinic3_ds_put_format(reply, "%4s%-30s%-s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_ESCAPE_MODE_SHOW_HELP_STRING, HINIC3_UI_ESCAPE_MODE_SHOW_HELP_TIPS_STRING); ++ return 0; ++} ++ ++static int ++hinic3_show_flow_escape_mode(struct ds *reply) ++{ ++ int ret; ++ uint8_t mode; ++ uint8_t escape_mode; ++ ++ ret = hinic3_flow_get_forward_mode(&mode); ++ if (ret != 0) { ++ hinic3_ds_put_format(reply, HINIC3_UI_GET_ESCAPE_MODE_FAILED, HINIC3_UI_LEADING_SIGN_FAILURE, ret); ++ return ret; ++ } ++ ++ escape_mode = (HINIC3_ESCAPE_MODE_MASK & mode) >> HINIC3_ESCAPE_MODE_OFFSET; ++ if (escape_mode == HINIC3_ESCAPE_MODE_NO_OFFLOAD) { ++ hinic3_ds_put_format(reply, HINIC3_UI_SHOW_NO_FLOW_OFFLOAD_MODE, HINIC3_UI_LEADING_SIGN_INFO); ++ } else if (escape_mode == HINIC3_ESCAPE_MODE_ALL_OFFLOAD) { ++ hinic3_ds_put_format(reply, HINIC3_UI_SHOW_ALL_FLOW_OFFLOAD_MODE, HINIC3_UI_LEADING_SIGN_INFO); ++ } else { ++ hinic3_ds_put_format(reply, HINIC3_UI_ESCAPE_MODE_INVALID, HINIC3_UI_LEADING_SIGN_FAILURE, escape_mode); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void ++hinic3_flow_resource_clear(void) ++{ ++ struct rte_flow_error error = {0}; ++ ++ int ret = hinic3_flow_flush_all(&error); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow resource clear failed, ret %d, error %d", ret, error.type); ++ return; ++ } ++ ++ if (hinic3_check_masked_to_exact_switch() == true) ++ hinic3_ufid_map_flush(); ++ ++ (void)hinic3_reset_offload_flow_nums(); ++} ++ ++static int ++hinic3_set_escape_mode(struct ds *reply, bool escape_mode_enable) ++{ ++ int ret; ++ uint8_t mode; ++ uint8_t version; ++ uint8_t forward_mode; ++ uint8_t escape_mode; ++ struct hinic3_dp_extend_info *extend_info = hinic3_get_offload_extend_info(); ++ struct hinic3_flow_agent_db *hinic3_db = (struct hinic3_flow_agent_db *)extend_info->hw_offload; ++ bool is_openovs = hinic3_check_masked_to_exact_switch(); ++ ++ ret = hinic3_flow_get_forward_mode(&mode); ++ if (ret != 0) { ++ hinic3_ds_put_format(reply, HINIC3_UI_GET_ESCAPE_MODE_FAILED, HINIC3_UI_LEADING_SIGN_FAILURE, ret); ++ return ret; ++ } ++ ++ version = (HINIC3_MODE_VERSION_MASK & mode) >> HINIC3_MODE_VERSION_OFFSET; ++ forward_mode = (HINIC3_FORWARD_MODE_MASK & mode) >> HINIC3_FORWARD_MODE_OFFSET; ++ ++ rte_spinlock_lock(&hinic3_db->operate_disable_lock); ++ if (escape_mode_enable) { ++ escape_mode = HINIC3_ESCAPE_MODE_NO_OFFLOAD; ++ hinic3_db->operate_disable = HINIC3_FLOW_OFFLOAD_DISABLE; ++ } else { ++ escape_mode = HINIC3_ESCAPE_MODE_ALL_OFFLOAD; ++ hinic3_db->operate_disable = HINIC3_FLOW_OFFLOAD_ENABLE; ++ } ++ hinic3_db->escape_mode = escape_mode; ++ rte_spinlock_unlock(&hinic3_db->operate_disable_lock); ++ ++ if (escape_mode_enable && is_openovs) ++ hinic3_flow_resource_clear(); ++ ++ mode = (version << HINIC3_MODE_VERSION_OFFSET) | (forward_mode << HINIC3_FORWARD_MODE_OFFSET) | ++ (escape_mode << HINIC3_ESCAPE_MODE_OFFSET); ++ HINIC3_LOG(INFO, AGENT, "set escape mode : version %u, forward_mode %u, escape_mode %u\n", version, forward_mode, ++ escape_mode); ++ ret = hinic3_flow_set_forward_mode(mode); ++ if (ret != 0) { ++ hinic3_ds_put_format(reply, HINIC3_UI_ESCAPE_MODE_SET_FAILED, HINIC3_UI_LEADING_SIGN_FAILURE, ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ++hinic3_flow_escape_mode_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) ++{ ++ struct ds reply = DS_EMPTY_INITIALIZER; ++ int ret; ++ enum {ARGC = 2}; ++ ++ if (strcmp(argv[ARGC - 1], "disable") == 0) { ++ ret = hinic3_set_escape_mode(&reply, false); ++ } else if (strcmp(argv[ARGC - 1], "enable") == 0) { ++ ret = hinic3_set_escape_mode(&reply, true); ++ } else if (strcmp(argv[ARGC - 1], "show") == 0) { ++ ret = hinic3_show_flow_escape_mode(&reply); ++ } else if ((strcmp(argv[ARGC - 1], "-h") == 0) || (strcmp(argv[ARGC - 1], "--help") == 0)) { ++ ret = hinic3_show_flow_escape_mode_help_info(&reply); ++ } else { ++ hinic3_ds_put_format(&reply, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ ret = -1; ++ } ++ ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&reply)); ++ } else { ++ hinic3_command_reply(conn, hinic3_ds_cstr(&reply)); ++ } ++ hinic3_ds_destroy(&reply); ++} ++ ++void ++unixctl_hinic3_cmd_forward_register() ++{ ++ hinic3_command_register("hwoff/set-forward-mode", "{ low_latency | high_throughput }", 1, 1, ++ hinic3_forward_mode_set_cmd, NULL); ++ hinic3_command_register("hwoff/show-forward-mode", "", 0, 0, hinic3_forward_mode_get_cmd, NULL); ++ hinic3_command_register("hwoff/flow-escape-mode", "{ enable | " ++ "disable | show | { -h | --help } }", 1, 1, hinic3_flow_escape_mode_cmd, ++ NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.h +new file mode 100644 +index 0000000..0f579d5 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.h +@@ -0,0 +1,9 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_CMD_FORWARD_H ++#define HINIC3_CMD_FORWARD_H ++ ++void unixctl_hinic3_cmd_forward_register(void); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c +new file mode 100644 +index 0000000..0e9062f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c +@@ -0,0 +1,124 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include "hinic3_ds.h" ++#include "hinic3_command.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_mpool_rte_flow.h" ++#include "hinic3_cmd_meminfo.h" ++#include "hinic3_dpdk_adapter.h" ++ ++#define HINIC3_MODULE_NAME_MAX_LEN 30 ++ ++void ++hinic3_show_meminfo_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_mem_statistics *mem_stats = hinic3_get_meminfo(); ++ uint64_t total_size = 0; ++ ++ for (int i = 0; i < HINIC3_MODULE_MAX; i++) { ++ uint64_t module_size = 0; ++ struct hinic3_module_meminfo *module_meminfo = &mem_stats->module_meminfo[i]; ++ ++ hinic3_rwlock_rdlock(&module_meminfo->rwlock); ++ module_size = module_meminfo->allocated_size; ++ hinic3_rwlock_rdunlock(&module_meminfo->rwlock); ++ total_size += module_size; ++ char module_name[HINIC3_MODULE_NAME_MAX_LEN] = {0}; ++ int ret = snprintf(module_name, sizeof(module_name), "%s:", hinic3_get_module_name_from_module_id(i)); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "snprintf for module_name failed."); ++ return; ++ } ++ hinic3_ds_put_format(&ds, "%2s%-40s%u \n", HINIC3_UI_INDENT_SPACE, module_name, module_size); ++ } ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2s%-40s%u \n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_MEMINFO_TOTAL_ALLOCATED_STRING, total_size); ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_MEMINFO_UNIT_STRING); ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++static uint64_t ++hinic3_format_hugepage_meminfo(struct ds *ds, struct hinic3_module_hugepage_meminfo *module_meminfo) ++{ ++ uint64_t module_size = 0; ++ uint64_t total_size = 0; ++ ++ hinic3_rwlock_rdlock(&module_meminfo->rwlock); ++ for (int i = 0; i < HINIC3_MODULE_MAX; i++) { ++ module_size = module_meminfo->allocated_size[i]; ++ total_size += module_size; ++ char module_name[HINIC3_MODULE_NAME_MAX_LEN] = {0}; ++ int ret = snprintf(module_name, sizeof(module_name), "%s:", hinic3_get_module_name_from_module_id(i)); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "snprintf for module_name failed."); ++ return 0; ++ } ++ hinic3_ds_put_format(ds, "%4s%-30s%u\n", ++ HINIC3_UI_INDENT_SPACE, module_name, module_size); ++ } ++ hinic3_rwlock_rdunlock(&module_meminfo->rwlock); ++ return total_size; ++} ++ ++void ++hinic3_show_hugepage_meminfo_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ uint64_t total_size = 0; ++ struct hinic3_rte_mempool_ele *iter_pool = NULL; ++ struct hinic3_rte_meminfo_list *mempool_list = NULL; ++ struct hinic3_hugepage_mem_statistics *mem_stats = hinic3_get_hugepage_meminfo(); ++ ++ if (mem_stats == NULL) { // 大页内存配置为disable分支 ++ hinic3_ds_put_format(&ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_INFO, HINIC3_UI_HUGEPAGE_MEMINFO_DISABLED_STRING); ++ goto out; ++ } ++ ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_HEAP_STATISTICS_STRING); ++ total_size += hinic3_format_hugepage_meminfo(&ds, &mem_stats->heap_meminfo); ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_MEMZONE_STATISTICS_STRING); ++ total_size += hinic3_format_hugepage_meminfo(&ds, &mem_stats->memzone_meminfo); ++ hinic3_ds_put_format(&ds, "\n"); ++ ++ mempool_list = &mem_stats->mempool_list; ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_MEMPOOL_STATISTICS_STRING); ++ hinic3_pthread_mutex_lock(&mempool_list->mutex); ++ LIST_FOR_EACH(iter_pool, node, &mempool_list->list_head) ++ { ++ total_size += iter_pool->allocated_size; ++ hinic3_ds_put_format(&ds, "%4s%-30s%u\n", ++ HINIC3_UI_INDENT_SPACE, iter_pool->name, iter_pool->allocated_size); ++ hinic3_ds_put_format(&ds, "%4s%-30s%u /" ++ " %u\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_MEMINFO_AVAILABLE_ELEM_STRING, ++ rte_mempool_avail_count(iter_pool->mempool), iter_pool->mempool->size); ++ } ++ hinic3_pthread_mutex_unlock(&mempool_list->mutex); ++ hinic3_ds_put_format(&ds, "\n"); ++ ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_TOTAL_STATISTICS_STRING); ++ hinic3_ds_put_format(&ds, "%4s%-30s%u\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_MEMINFO_TOTAL_ALLOCATED_STRING, total_size); ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_MEMINFO_UNIT_STRING); ++out: ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++void ++unixctl_hinic3_cmd_meminfo_register(void) ++{ ++ hinic3_command_register("hwoff/show-meminfo", "", 0, 0, hinic3_show_meminfo_command, NULL); ++ hinic3_command_register("hwoff/show-hugepage-meminfo", "", 0, 0, hinic3_show_hugepage_meminfo_command, NULL); ++ hinic3_command_register("hwoff/show-mpool-stats", "", 0, 0, hinic3_dump_mempool_info, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.h +new file mode 100644 +index 0000000..278158a +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.h +@@ -0,0 +1,16 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_CMD_MEMINFO_H ++#define HINIC3_CMD_MEMINFO_H ++ ++#include "hinic3_meminfo.h" ++#include "hinic3_hugepage_meminfo.h" ++#include "hinic3_command.h" ++ ++void hinic3_show_meminfo_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_show_hugepage_meminfo_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED); ++void unixctl_hinic3_cmd_meminfo_register(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c +new file mode 100644 +index 0000000..a96f577 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c +@@ -0,0 +1,28 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_log.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_cmd_meminfo.h" ++#include "hinic3_cmd_version.h" ++ ++void ++hinic3_show_agent_version(struct unixctl_conn *conn, int argc HINIC3_UNUSED, ++ const char *argv[] HINIC3_UNUSED, void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_COMPONENT_NAME); ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_FEATURE_NAME); ++ hinic3_ds_put_format(&ds, "%2s%s%s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_AGENT_COMPONENT_VERSION, HINIC3_BUILD_MAJOR_VERSION); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++} ++ ++void ++unixctl_hinic3_cmd_version_register() ++{ ++ hinic3_command_register("hinic3-agent-version", "", 0, 0, hinic3_show_agent_version, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h +new file mode 100644 +index 0000000..bee8621 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h +@@ -0,0 +1,11 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_CMD_VERSION_H ++#define HINIC3_CMD_VERSION_H ++ ++void unixctl_hinic3_cmd_version_register(void); ++void hinic3_show_agent_version(struct unixctl_conn *conn, int argc HINIC3_UNUSED, ++ const char *argv[] HINIC3_UNUSED, void *aux HINIC3_UNUSED); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.c +new file mode 100644 +index 0000000..88cc506 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.c +@@ -0,0 +1,114 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_dfx_port.h" ++#include "hinic3_log.h" ++#include "hinic3_port_util.h" ++#include "hinic3_queue.h" ++#include "rte_ethdev.h" ++#include "hinic3_dpdk_adapter.h" ++ ++int ++hinic3_get_vport_by_netdev_name(const char *cmd, char *netdev_name, uint16_t *port_id) ++{ ++ int ret; ++ uint16_t dpdk_index_id; ++ uint32_t if_index; ++ ++ if (netdev_name == NULL || port_id == NULL) ++ return -1; ++ ++ ret = rte_eth_dev_get_port_by_name(netdev_name, &dpdk_index_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "hwoff/%s failed, get port id error!\n", cmd); ++ return -1; ++ } ++ ret = hinic3_get_port_ifindex(dpdk_index_id, &if_index); ++ if (ret != 0 || if_index > UINT16_MAX) { ++ HINIC3_LOG(ERR, BOND, "hwoff/%s failed, device ifindex error \n", cmd); ++ return -1; ++ } else { ++ *port_id = (uint16_t)if_index; ++ } ++ ++ return 0; ++} ++ ++int ++hinic3_get_port_ifindex(uint16_t src_port, uint32_t *ifindex) ++{ ++ struct rte_eth_dev_info info = {0}; ++ int ret; ++ ++ ret = rte_eth_dev_info_get(src_port, &info); ++ if (ret != 0) { ++ return -1; ++ } ++ *ifindex = info.if_index; ++ ++ return 0; ++} ++ ++int ++hinic3_get_netdev_name(const char *port_name, char *netdev_name) ++{ ++ int ret; ++ ++ if (port_name == NULL || netdev_name == NULL) ++ return -1; ++ ++ ret = snprintf(netdev_name, HINIC3_NETDEV_NAME_MAX_LENGTH, "%s%s", ++ HINIC3_ETH_VDEV_DRV_NAME, port_name); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "The port name is misspelled."); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++bool ++hinic3_dfx_port_process_args(int argc, const char *argv[], char *netdev_name, bool *is_global) ++{ ++ const int port_name_arg_idx = 2; ++ int ret; ++ ++ if (argc != port_name_arg_idx) ++ return false; ++ ++ *is_global = (strcmp("global", argv[port_name_arg_idx - 1]) == 0); ++ if (*is_global) ++ return true; ++ ++ ret = hinic3_get_netdev_name(argv[port_name_arg_idx - 1], netdev_name); ++ if (ret != 0) ++ return false; ++ ++ return true; ++} ++ ++void ++unixctl_hinic3_port_cmd_init(void) ++{ ++ enum hinic3_port_cmd_max { ++ DUMP_UPCALL_QUEUE_INFO_PARAM = 2, ++ }; ++ ++ hinic3_command_register("hwoff/dump-ports", "{ | global | { -h | --help } }", 1, 1, ++ hinic3_dump_ports_stats_command, NULL); ++ hinic3_command_register("hwoff/flush-ports", "{ | global | { -h | --help } }", 1, 1, ++ hinic3_flush_ports_stats_command, NULL); ++ hinic3_command_register("hwoff/dump-bond-slave-info", "", 1, 1, hinic3_dump_bond_slave_info_cmd, NULL); ++ hinic3_command_register("hwoff/dump-ports-queue-info", "{ -p | { -h | --help } }", 1, 2, ++ hinic3_dump_ports_queue_info_command, NULL); ++ if (hinic3_get_virtual_queue_mode_enabled() == false) { ++ hinic3_command_register( ++ "hwoff/dump-upcall-queue-info", "", 0, 0, hinic3_dump_upcall_queues_info_cmd, NULL); ++ } else { ++ hinic3_command_register("hwoff/dump-upcall-queue-info", ++ "[ -port | -virtual | -physical | { -h | --help } ]", ++ 0, OPTIONAL_ARGUMENT, hinic3_dump_upcall_queues_info_cmd, NULL); ++ } ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.h +new file mode 100644 +index 0000000..66bc38a +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port.h +@@ -0,0 +1,55 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_DFX_PORT_H ++#define HINIC3_DFX_PORT_H ++ ++#include ++#include ++#include "rte_ethdev.h" ++#include "hinic3_util.h" ++#include "hinic3_command.h" ++#include "hinic3_option.h" ++#include "hinic3_provider.h" ++#include "hinic3_ds.h" ++ ++#define HINIC3_DFX_GLOABL_ALLOC_MEM_MAX_SIZE (0x20000) ++#define HINIC3_CMD_MAX_LENGTH 2048 ++#define HINIC3_NETDEV_NAME_MAX_LENGTH 512 ++#define HINIC3_BOND_SLAVE_POSTION_INFO 1 ++#define HINIC3_BOND_SLAVE_NUM 4 ++#define HINIC3_VPORT_TYPE_SHIFT 12 ++#define HINIC3_BOND_TYPE 3 ++#define HINIC3_BOND_ARG_SLAVE_NAME_LEN 64 ++#define HINIC3_BOND_SLAVE_NAME_LEN 256 ++ ++void unixctl_hinic3_port_cmd_init(void); ++ ++void hinic3_dump_ports_stats_command(struct unixctl_conn *conn, int argc, ++ const char *argv[], void *aux); ++void hinic3_flush_ports_stats_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_dump_upcall_queues_info_cmd(struct unixctl_conn *conn, ++ int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, void *aux HINIC3_UNUSED); ++void hinic3_dump_ports_queue_info_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_dump_bond_slave_info_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++ ++int hinic3_get_vport_by_netdev_name(const char *cmd, char *netdev_name, uint16_t *port_id); ++int hinic3_get_netdev_name(const char *port_name, char *netdev_name); ++bool hinic3_dfx_port_process_args(int argc, const char *argv[], char *netdev_name, bool *is_global); ++int hinic3_get_port_ifindex(uint16_t src_port, uint32_t *ifindex); ++ ++int hinic3_dump_chip_global_stats(struct ds *output_msg); ++int hinic3_show_pf_port_info(struct ds *output_msg, uint16_t dpdk_index_id, hinic3_port_stats *port_stats, ++ uint32_t link_status); ++int hinic3_show_vf_port_info(struct ds *output_msg, uint16_t dpdk_index_id, hinic3_port_stats *port_stats, ++ uint32_t link_status); ++ ++int hinic3_get_bond_link_from_netdev(struct ds *output_msg, const char *netdev_name, uint32_t *link_status); ++void hinic3_show_base_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++void hinic3_show_check_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++void hinic3_show_hiovs_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++void hinic3_show_upcall_port_stats(struct ds *output_msg, const hinic3_port_stats *port_stats); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c +new file mode 100644 +index 0000000..fd46999 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c +@@ -0,0 +1,238 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "rte_ethdev.h" ++#include "rte_string_fns.h" ++#include "hinic3_provider.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_log.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_bond_controller.h" ++#include ++#include "hinic3_tlv_key.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_ds.h" ++#include "hinic3_smap.h" ++#include "hinic3_command.h" ++#include "hinic3_vf_controller.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++#include "hinic3_dfx_port.h" ++ ++static void ++hinic3_show_bond_slave_stats(struct ds *output_msg, const struct hovs_bond_slave_stats *bond_slave_info, ++ uint8_t index) ++{ ++ uint8_t offset = (HINIC3_BOND_SLAVE_POSTION_INFO << index); ++ uint8_t bond_postion = (bond_slave_info->vld_slave & offset); ++ ++ if (bond_postion != 0) { ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-pkts", bond_slave_info->rx_pkts[index]); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-pkts", bond_slave_info->tx_pkts[index]); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "rx-bytes", bond_slave_info->rx_bytes[index]); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "tx-bytes", bond_slave_info->tx_bytes[index]); ++ return; ++ } ++ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "bond_slave effective Index", bond_slave_info->vld_slave); ++ return; ++} ++ ++static int ++hinic3_split_slave_name(char *slaves, char *slaves_name, ++ char bond_slave_name[][HINIC3_BOND_ARG_SLAVE_NAME_LEN], int len) ++{ ++ int slaves_num = 0; ++ int slaves_name_num = 0; ++ char *slaves_index[HINIC3_BOND_SLAVE_NUM] = {0}; ++ char *slaves_name_str[HINIC3_BOND_SLAVE_NUM] = {0}; ++ ++ slaves_num = rte_strsplit(slaves, HINIC3_BOND_SLAVE_NAME_LEN, slaves_index, HINIC3_BOND_SLAVE_NUM, ','); ++ if (slaves_num <= 0 || slaves_num > HINIC3_BOND_SLAVE_NUM) { ++ HINIC3_LOG(ERR, BOND, "failed to get bond slaves num"); ++ return -1; ++ } ++ ++ slaves_name_num = rte_strsplit(slaves_name, HINIC3_BOND_SLAVE_NAME_LEN, slaves_name_str, HINIC3_BOND_SLAVE_NUM, ','); ++ if (slaves_name_num <= 0 || slaves_name_num > HINIC3_BOND_SLAVE_NUM) { ++ HINIC3_LOG(ERR, BOND, "failed to get bond slaves name num"); ++ return -1; ++ } ++ ++ if (slaves_num != slaves_name_num) { ++ HINIC3_LOG(ERR, BOND, "slaves_num is not equal to slaves_name_num"); ++ return -1; ++ } ++ ++ for (int i = 0, j = 0; i < HINIC3_BOND_SLAVE_NUM && j < slaves_num; i++) { ++ char *endPtr = NULL; ++ uint32_t index = strtoul(slaves_index[j], &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') ++ return -1; ++ if (index >= HINIC3_BOND_SLAVE_NUM) ++ return -1; ++ ++ if (i == index) { ++ strcpy(bond_slave_name[i], slaves_name_str[j]); ++ j++; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_get_bond_name_info(uint16_t bond_id, struct smap *bond_info, ++ char bond_slave_name[][HINIC3_BOND_ARG_SLAVE_NAME_LEN]) ++{ ++ int ret; ++ const char *slaves = NULL; ++ const char *slaves_name = NULL; ++ char slaves_str[HINIC3_BOND_SLAVE_NAME_LEN] = {0}; ++ char slaves_name_str[HINIC3_BOND_SLAVE_NAME_LEN] = {0}; ++ ++ ret = hinic3_bond_mgmt_get(bond_id, bond_info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "failed to get bond info by bond_id"); ++ return -1; ++ } ++ ++ slaves = hinic3_smap_get(bond_info, HINIC3_BOND_SLAVES); ++ if (slaves == NULL) { ++ HINIC3_LOG(ERR, BOND, "slaves is NULL"); ++ return -1; ++ } ++ ++ slaves_name = hinic3_smap_get(bond_info, HINIC3_BOND_ARG_SLAVE_NAME_STR); ++ if (slaves_name == NULL) { ++ HINIC3_LOG(ERR, BOND, "slaves_name is NULL"); ++ return -1; ++ } ++ ++ strcpy(slaves_str, slaves); ++ ++ strcpy(slaves_name_str, slaves_name); ++ ++ ret = hinic3_split_slave_name(slaves_str, slaves_name_str, bond_slave_name, HINIC3_BOND_SLAVE_NAME_LEN); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "hinic3_split_slave_name is failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_get_pf_bond_slave_name(uint16_t vport_id, char bond_slave_name[][HINIC3_BOND_ARG_SLAVE_NAME_LEN]) ++{ ++ int ret; ++ uint16_t ifindex = 0; ++ struct hinic3_bond_dev *pf_dev = NULL; ++ struct smap bond_info; ++ ++ ret = hinic3_get_port_id_by_ifindex(vport_id, &ifindex); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "Get pf bond slave name: get port id failed, vport_id %X", vport_id); ++ return -1; ++ } ++ pf_dev = (struct hinic3_bond_dev *)hinic3_get_private_data(ifindex); ++ if (pf_dev == NULL) { ++ HINIC3_LOG(ERR, BOND, "The current device private_data is NULL."); ++ return -1; ++ } ++ ++ hinic3_smap_init(&bond_info); ++ ret = hinic3_get_bond_name_info(pf_dev->bond_id, &bond_info, bond_slave_name); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "failed to get bond info by bond_id"); ++ hinic3_smap_destroy(&bond_info); ++ return -1; ++ } ++ ++ hinic3_smap_destroy(&bond_info); ++ return 0; ++} ++ ++static int ++hinic3_dump_bond_slave_info(struct ds *ds, char *netdev_name, uint32_t netdev_name_len) ++{ ++ int ret = 0; ++ uint16_t port_id = 0; ++ char bond_slave_name[HINIC3_BOND_SLAVE_NUM][HINIC3_BOND_ARG_SLAVE_NAME_LEN] = { ++ {"Invalid"}, {"Invalid"}, {"Invalid"}, {"Invalid"} ++ }; ++ struct hovs_bond_slave_stats bond_slave_info = {0}; ++ ++ if (netdev_name_len >= HINIC3_NETDEV_NAME_MAX_LENGTH || netdev_name_len <= 0) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ ret = hinic3_get_vport_by_netdev_name("dump-ports", netdev_name, &port_id); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ ++ if ((port_id >> HINIC3_VPORT_TYPE_SHIFT) != HINIC3_BOND_TYPE) { ++ hinic3_ds_put_format(ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_BOND_TYPE_ERROR_STRING); ++ return -1; ++ } ++ ++ ret = hinic3_port_mgmt_get_bond_slave_info(port_id, &bond_slave_info); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_DUMP_BOND_SLAVE_FAILURE_STRING, HINIC3_UI_LEADING_SIGN_FAILURE, ret); ++ return -1; ++ } ++ ++ ret = hinic3_get_pf_bond_slave_name(port_id, bond_slave_name); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_GET_SLAVE_NAME_STRING, HINIC3_UI_LEADING_SIGN_FAILURE, ret); ++ return -1; ++ } ++ ++ for (uint8_t index = 0; index < HINIC3_BOND_SLAVE_NUM; index++) { ++ hinic3_ds_put_format(ds, "BOND SLAVE[%u] INFO:\n", index); ++ hinic3_ds_put_format(ds, "\t%-30s : %s\n", "port_name", bond_slave_name[index]); ++ hinic3_show_bond_slave_stats(ds, &bond_slave_info, index); ++ } ++ ++ return 0; ++} ++ ++void ++hinic3_dump_bond_slave_info_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ *(int *)aux = -1; ++ bool is_global = false; ++ char bond_name[HINIC3_NETDEV_NAME_MAX_LENGTH] = {0}; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ if (argc <= 1) { ++ hinic3_ds_put_format(&ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ hinic3_ds_put_format(&ds, "%s%s\n", HINIC3_UI_CMD_USAGE_STRING, HINIC3_UI_DUMP_BOND_SLAVE_STRING); ++ *(int *)aux = -1; ++ } ++ ++ if (hinic3_dfx_port_process_args(argc, argv, bond_name, &is_global) == true) ++ *(int *)aux = hinic3_dump_bond_slave_info(&ds, bond_name, strlen(bond_name)); ++ ++ if (*(int *)aux != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++ } ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c +new file mode 100644 +index 0000000..e9d8f2b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c +@@ -0,0 +1,502 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_dfx_port.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_command.h" ++#include "hinic3_ds.h" ++#include ++#include "hinic3_iface_global.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_bond_controller.h" ++#include "hinic3_agent_cmd_format.h" ++#include "rte_ethdev.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++#define HINIC3_LINK_STATUS_STR_LEN 10 ++#define HINIC3_LINK_STATUS_NUM 2 ++ ++#define RTE_ETH_LINK_UP_STR "up" ++#define RTE_ETH_LINK_DOWN_STR "down" ++ ++typedef enum { ++ COMMAND_TYPE_OF_DUMP, ++ COMMAND_TYPE_OF_FLUSH, ++} hinic3_command_type; ++ ++struct hinic3_link_status { ++ uint32_t link_status; ++ char link_status_str[HINIC3_LINK_STATUS_STR_LEN]; ++}; ++ ++static struct hinic3_link_status g_hinic3_link_status[HINIC3_LINK_STATUS_NUM] = { ++ {RTE_ETH_LINK_DOWN, RTE_ETH_LINK_DOWN_STR}, ++ {RTE_ETH_LINK_UP, RTE_ETH_LINK_UP_STR}, ++}; ++ ++static int ++hinic3_get_rx_qos_drop_num(struct hinic3_vf_dev *vf_dev, uint32_t *drop_num) ++{ ++ int ret; ++ struct hovs_qos_stats_batch_all qos_stats = {0}; ++ ++ ret = hinic3_vf_qos_statistics_get_all_batch(&vf_dev->qos_id, &qos_stats, 1); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to invoke the driver qos_statistics interface."); ++ return -1; ++ } ++ *drop_num = qos_stats.drop_pkg_num.rx_drop_num; ++ return 0; ++} ++ ++int ++hinic3_show_vf_port_info(struct ds *output_msg, uint16_t dpdk_index_id, hinic3_port_stats *port_stats, ++ uint32_t link_status) ++{ ++ int ret; ++ void *private_data = NULL; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ uint32_t qos_drop_num; ++ ++ private_data = hinic3_get_private_data(dpdk_index_id); ++ if (private_data == NULL) { ++ hinic3_ds_put_format(output_msg, "%sThe current device's private data is NULL\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ vf_dev = (struct hinic3_vf_dev *)private_data; ++ ++ ret = hinic3_get_rx_qos_drop_num(vf_dev, &qos_drop_num); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%shwoff/dump-ports %u failed, get qos dropped num error\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, vf_dev->vport_id); ++ return -1; ++ } ++ port_stats->rx_qos_dropped = qos_drop_num; ++ ++ if ((link_status & HW_ETH_DEVICE_STATUS) != 0) { ++ link_status = RTE_ETH_LINK_UP; ++ } else { ++ link_status = RTE_ETH_LINK_DOWN; ++ } ++ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %s\n", "link-status", ++ g_hinic3_link_status[link_status].link_status_str); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lld\n", "upcall-pkt-num", ++ rte_atomic64_read(&vf_dev->vf_upcall_pk_num)); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lld\n", "reinject-pkt-num", ++ rte_atomic64_read(&vf_dev->vf_reinject_pk_num)); ++ return 0; ++} ++ ++int ++hinic3_show_pf_port_info(struct ds *output_msg, uint16_t dpdk_index_id, hinic3_port_stats *port_stats, ++ uint32_t link_status) ++{ ++ int ret; ++ void *private_data = NULL; ++ struct hinic3_bond_dev *pf_dev = NULL; ++ struct hovs_bond_slave_stats bond_slave_info = { 0 }; ++ ++ private_data = hinic3_get_private_data(dpdk_index_id); ++ if (private_data == NULL) { ++ hinic3_ds_put_format(output_msg, "%sThe current device's private data is NULL\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ pf_dev = (struct hinic3_bond_dev *)private_data; ++ ++ ret = hinic3_port_mgmt_get_bond_slave_info(pf_dev->vport_id, &bond_slave_info); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%scan't dump bond slave info, errno = %d\n", HINIC3_UI_LEADING_SIGN_ERROR, ret); ++ return -1; ++ } ++ ++ for (uint8_t index = 1; index < HINIC3_BOND_SLAVE_NUM; index++) { ++ bond_slave_info.rx_pkts[0] += bond_slave_info.rx_pkts[index]; ++ bond_slave_info.tx_pkts[0] += bond_slave_info.tx_pkts[index]; ++ bond_slave_info.rx_bytes[0] += bond_slave_info.rx_bytes[index]; ++ bond_slave_info.tx_bytes[0] += bond_slave_info.tx_bytes[index]; ++ } ++ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %s\n", "link-status", ++ g_hinic3_link_status[link_status].link_status_str); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lld\n", "upcall-pkt-num", ++ rte_atomic64_read(&pf_dev->pf_upcall_pk_num)); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lld\n", "reinject-pkt-num", ++ rte_atomic64_read(&pf_dev->pf_reinject_pk_num)); ++ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %llu\n", "rx-pkts(net)", bond_slave_info.rx_pkts[0]); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %llu\n", "tx-pkts(net)", bond_slave_info.tx_pkts[0]); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %llu\n", "rx-bytes(net)", bond_slave_info.rx_bytes[0]); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %llu\n", "tx-bytes(net)", bond_slave_info.tx_bytes[0]); ++ ++ return 0; ++} ++ ++static void ++hinic3_show_help_str(struct ds *output_msg, hinic3_command_type type) ++{ ++ const char *command_str = NULL; ++ ++ if (type == COMMAND_TYPE_OF_DUMP) { ++ hinic3_ds_put_format(output_msg, ++ "%2sUsage: dpak-ovs-ctl hwoff/dump-ports { | global | { -h | --help } }\n\n", ++ HINIC3_UI_INDENT_SPACE); ++ command_str = "Dump"; ++ } else { ++ hinic3_ds_put_format(output_msg, ++ "%2sUsage: dpak-ovs-ctl hwoff/flush-ports { | global | { -h | --help } }\n\n", ++ HINIC3_UI_INDENT_SPACE); ++ command_str = "Flush"; ++ } ++ ++ hinic3_ds_put_format(output_msg, "%2sOptions list:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(output_msg, "%4s%-30s%s the stats of a port\n", ++ HINIC3_UI_INDENT_SPACE, "", command_str); ++ hinic3_ds_put_format(output_msg, "%4s%-30s%s the chip global stats\n", HINIC3_UI_INDENT_SPACE, "global", command_str); ++ hinic3_ds_put_format(output_msg, "%4s%-30sDisplay the help information\n", HINIC3_UI_INDENT_SPACE, "-h, --help"); ++} ++ ++int ++hinic3_get_bond_link_from_netdev(struct ds *output_msg, const char *netdev_name, uint32_t *link_status) ++{ ++ int ret; ++ const char *bond_name = NULL; ++ ++ if (strlen(HINIC3_ETH_VDEV_DRV_NAME) >= strlen(netdev_name)) { ++ hinic3_ds_put_format(output_msg, "%sPort mgmt get bond name err.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ bond_name = netdev_name + strlen(HINIC3_ETH_VDEV_DRV_NAME); ++ ret = hinic3_get_bond_link_status(bond_name, link_status); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%sPort mgmt get bond state err, ret is %d.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, ret); ++ return ret; ++ } ++ return ret; ++} ++ ++static int ++hinic3_dump_port_status(struct ds *output_msg, const char *netdev_name) ++{ ++ int ret = 0; ++ uint16_t dpdk_index_id; ++ uint16_t port_id; ++ uint32_t link_status; ++ hinic3_port_stats port_stats = {0}; ++ uint32_t if_index; ++ ++ ret = rte_eth_dev_get_port_by_name(netdev_name, &dpdk_index_id); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%shwoff/dump-ports %s failed, get port id error, wrong port name!\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, netdev_name); ++ return -1; ++ } ++ ret = hinic3_get_port_ifindex(dpdk_index_id, &if_index); ++ if (ret != 0 || if_index > UINT16_MAX) { ++ hinic3_ds_put_format(output_msg, "hwoff/dump-ports %s failed, device ifindex error \n", netdev_name); ++ return -1; ++ } else { ++ port_id = (uint16_t)if_index; ++ } ++ ret = hinic3_port_statistics_get(port_id, &port_stats); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "hwoff/dump-ports %s failed with error %d \n", netdev_name, ret); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(output_msg, "\t%-30s : %hu\n", "vport_id", port_id); ++ ++ if (is_hinic3_vf_dev(dpdk_index_id) == true) { ++ ret = hinic3_port_mgmt_get_usage_state(port_id, &link_status); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%sPort mgmt get vf link state err, ret is %d.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, ret); ++ return ret; ++ } ++ ++ ret = hinic3_show_vf_port_info(output_msg, dpdk_index_id, &port_stats, link_status); ++ } else { ++ ret = hinic3_get_bond_link_from_netdev(output_msg, netdev_name, &link_status); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%sPort mgmt get bond link state err, ret is %d.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, ret); ++ return ret; ++ } ++ ret = hinic3_show_pf_port_info(output_msg, dpdk_index_id, &port_stats, link_status); ++ } ++ ++ hinic3_show_base_port_stats(output_msg, &port_stats); ++ hinic3_show_check_port_stats(output_msg, &port_stats); ++ hinic3_show_hiovs_port_stats(output_msg, &port_stats); ++ hinic3_show_upcall_port_stats(output_msg, &port_stats); ++ return ret; ++} ++ ++int ++hinic3_dump_chip_global_stats(struct ds *output_msg) ++{ ++ int error; ++ struct hinic3_global_stats chip_global_stats = {0}; ++ ++ error = hinic3_global_statistics_get(&chip_global_stats); ++ if (error != 0) { ++ hinic3_ds_put_format(output_msg, "%sDump ports global failed with error :%d.\n", ++ HINIC3_UI_LEADING_SIGN_FAILURE, error); ++ return -1; ++ } ++ hinic3_ds_put_format(output_msg, "global statistics:\n"); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-offload-flow-num", chip_global_stats.offload_flow_num); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-offload-qpc-num", chip_global_stats.offload_qpc_num); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-same-flow_multi-gpa", ++ chip_global_stats.same_flow_with_multi_gpa); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-vxlan-rx-vtep-miss", chip_global_stats.vxlan_rx_vtep_miss); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-upcall-pf0-invalid-count", ++ chip_global_stats.upcall_pf0_invalid_count); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-upcall-pf0-fail-drop", ++ chip_global_stats.upcall_pf0_rx_wqe_fail_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-upcall-pf1-invalid-count", ++ chip_global_stats.upcall_pf1_invalid_count); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %u\n", "g-upcall-pf1-fail-drop", ++ chip_global_stats.upcall_pf1_rx_wqe_fail_dropped); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "g-upcall-limit-drop-total", ++ chip_global_stats.upcall_limit_drop_total); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "g-upcall-from-vf-total", ++ chip_global_stats.upcall_from_vf_total); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "g-upcall-from-hwbond-total", ++ chip_global_stats.upcall_from_hwbond_total); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "g-flow-default-upcall", chip_global_stats.flow_default_upcall); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "g-flow-miss-upcall", chip_global_stats.flow_miss_upcall); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "g-flow-invalid-upcall", chip_global_stats.flow_invalid_upcall); ++ hinic3_ds_put_format(output_msg, "\t%-30s : %lu\n", "g-qu-prefetch-stats-fail", ++ chip_global_stats.qu_prefetch_statics_fail); ++ return 0; ++} ++ ++static int ++hinic3_dump_status(struct ds *output_msg, char *netdev_name, bool is_global) ++{ ++ int ret; ++ if (is_global) { ++ ret = hinic3_dump_chip_global_stats(output_msg); ++ } else { ++ ret = hinic3_dump_port_status(output_msg, netdev_name); ++ } ++ return ret; ++} ++ ++void ++hinic3_dump_ports_stats_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ bool is_global = false; ++ char netdev_name[HINIC3_NETDEV_NAME_MAX_LENGTH] = {0}; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ const hinic3_command_type command_type = COMMAND_TYPE_OF_DUMP; ++ ++ if (argc > 1 && ((strcmp("-h", argv[1]) == 0) || (strcmp("--help", argv[1]) == 0))) { ++ hinic3_show_help_str(&ds, command_type); ++ *(int *)aux = 0; ++ } else if (hinic3_dfx_port_process_args(argc, argv, netdev_name, &is_global) == true) { ++ *(int *)aux = hinic3_dump_status(&ds, netdev_name, is_global); ++ } else { ++ *(int *)aux = -1; ++ hinic3_ds_put_format(&ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ } ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++static int ++hinic3_flush_chip_global_stats(struct ds *output_msg) ++{ ++ HINIC3_LOG(INFO, AGENT, "flush global statistics"); ++ int err = hinic3_global_statistics_flush(); ++ if (err != 0) { ++ hinic3_ds_put_format(output_msg, "%sFlush global stat failed, error is %d.\n", ++ HINIC3_UI_LEADING_SIGN_FAILURE, err); ++ return -1; ++ } ++ hinic3_ds_put_format(output_msg, "%sFlush global stat successfully.\n", HINIC3_UI_LEADING_SIGN_INFO); ++ return 0; ++} ++ ++static int ++hinic3_flush_rx_qos_drop_num(struct hinic3_vf_dev *vf_dev) ++{ ++ int ret; ++ ++ ret = hinic3_vf_qos_statistics_clear_batch(&vf_dev->qos_id, 1); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to invoke the driver qos_statistics interface."); ++ return -1; ++ } ++ return 0; ++} ++ ++static void ++hinic3_flush_vf_port_queue_info(struct hinic3_vf_dev *vf_dev) ++{ ++ for (uint8_t idx = 0; idx < MAX_RX_QUEUE_PER_VPORT; ++idx) { ++ if (vf_dev->upcall_queue.is_queue_valid[idx] == false) ++ continue; ++ if (hinic3_get_virtual_queue_mode_enabled() == false) { ++ rte_atomic64_set(&vf_dev->upcall_queue.rx_queue[idx]->info.pkts, 0); ++ } else { ++ rte_atomic64_set(&vf_dev->upcall_queue.rx_queues[idx]->statistic.pkts, 0); ++ } ++ } ++ ++ for (uint8_t idx = 0; idx < MAX_TX_QUEUE_PER_VPORT; ++idx) { ++ if (vf_dev->reinject_queue.is_queue_valid[idx] == false) ++ continue; ++ rte_atomic64_set(&vf_dev->reinject_queue.tx_queues[idx]->info.pkts, 0); ++ } ++ return; ++} ++ ++static void ++hinic3_flush_pf_port_queue_info(struct hinic3_bond_dev *pf_dev) ++{ ++ for (uint8_t idx = 0; idx < MAX_RX_QUEUE_PER_VPORT; ++idx) { ++ if (pf_dev->upcall_queue.is_queue_valid[idx] == false) { ++ continue; ++ } ++ rte_atomic64_set(&pf_dev->upcall_queue.rx_queue[idx]->info.pkts, 0); ++ } ++ ++ for (uint8_t idx = 0; idx < MAX_TX_QUEUE_PER_VPORT; ++idx) { ++ if (pf_dev->reinject_queue.is_queue_valid[idx] == false) ++ continue; ++ rte_atomic64_set(&pf_dev->reinject_queue.tx_queues[idx]->info.pkts, 0); ++ } ++ return; ++} ++ ++static void ++hinic3_flush_vf_port_info(struct ds *output_msg, uint16_t dpdk_index_id) ++{ ++ int ret; ++ void *private_data = NULL; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ ++ private_data = hinic3_get_private_data(dpdk_index_id); ++ if (private_data == NULL) { ++ hinic3_ds_put_format(output_msg, "%sThe current device's private data is NULL.\n", ++ HINIC3_UI_LEADING_SIGN_FAILURE); ++ return; ++ } ++ vf_dev = (struct hinic3_vf_dev *)private_data; ++ ret = hinic3_flush_rx_qos_drop_num(vf_dev); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%sFlush ports %u failed, flush qos dropped num error.\n", ++ HINIC3_UI_LEADING_SIGN_FAILURE, vf_dev->vport_id); ++ return; ++ } ++ hinic3_flush_vf_port_queue_info(vf_dev); ++ rte_atomic64_set(&vf_dev->vf_upcall_pk_num, 0); ++ rte_atomic64_set(&vf_dev->vf_upcall_pk_byt, 0); ++ rte_atomic64_set(&vf_dev->vf_reinject_pk_num, 0); ++ rte_atomic64_set(&vf_dev->vf_reinject_pk_byt, 0); ++ ++ return; ++} ++ ++static void ++hinic3_flush_pf_port_info(struct ds *output_msg, uint16_t dpdk_index_id) ++{ ++ void *private_data = NULL; ++ struct hinic3_bond_dev *pf_dev = NULL; ++ ++ private_data = hinic3_get_private_data(dpdk_index_id); ++ if (private_data == NULL) { ++ HINIC3_LOG(ERR, AGENT, "The current device's private data is NULL."); ++ return; ++ } ++ pf_dev = (struct hinic3_bond_dev *)private_data; ++ ++ hinic3_flush_pf_port_queue_info(pf_dev); ++ rte_atomic64_set(&pf_dev->pf_upcall_pk_num, 0); ++ rte_atomic64_set(&pf_dev->pf_upcall_pk_byt, 0); ++ rte_atomic64_set(&pf_dev->pf_reinject_pk_num, 0); ++ rte_atomic64_set(&pf_dev->pf_reinject_pk_byt, 0); ++ ++ return; ++} ++ ++static int ++hinic3_flush_port_stats(struct ds *output_msg, char *netdev_name) ++{ ++ int ret; ++ uint16_t dpdk_index_id; ++ uint16_t port_id; ++ uint32_t if_index; ++ ++ ret = rte_eth_dev_get_port_by_name(netdev_name, &dpdk_index_id); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%shwoff/flush-ports %s failed, get port id error, wrong port name!\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, netdev_name); ++ return -1; ++ } ++ ret = hinic3_get_port_ifindex(dpdk_index_id, &if_index); ++ if (ret != 0 || if_index > UINT16_MAX) { ++ hinic3_ds_put_format(output_msg, "%shwoff/dump-ports %s failed, device ifindex error. \n", ++ HINIC3_UI_LEADING_SIGN_ERROR, netdev_name); ++ return -1; ++ } else { ++ port_id = (uint16_t)if_index; ++ } ++ ret = hinic3_port_statistics_flush(port_id); ++ if (ret != 0) { ++ hinic3_ds_put_format(output_msg, "%shwoff/flush-ports %s failed with error %d. \n", ++ HINIC3_UI_LEADING_SIGN_FAILURE, netdev_name, ret); ++ return -1; ++ } ++ ++ if (is_hinic3_vf_dev(dpdk_index_id) == true) { ++ hinic3_flush_vf_port_info(output_msg, dpdk_index_id); ++ } else { ++ hinic3_flush_pf_port_info(output_msg, dpdk_index_id); ++ } ++ hinic3_ds_put_format(output_msg, "%sFlush %s stats successfully.\n", HINIC3_UI_LEADING_SIGN_INFO, netdev_name); ++ return 0; ++} ++ ++static int ++hinic3_flush_stats(struct ds *output_msg, char *netdev_name, bool is_global) ++{ ++ int ret; ++ if (is_global) { ++ ret = hinic3_flush_chip_global_stats(output_msg); ++ } else { ++ ret = hinic3_flush_port_stats(output_msg, netdev_name); ++ } ++ return ret; ++} ++ ++void ++hinic3_flush_ports_stats_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ bool is_global = false; ++ char netdev_name[HINIC3_NETDEV_NAME_MAX_LENGTH] = {0}; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ const hinic3_command_type command_type = COMMAND_TYPE_OF_FLUSH; ++ ++ if (argc > 1 && ((strcmp("-h", argv[1]) == 0) || (strcmp("--help", argv[1]) == 0))) { ++ hinic3_show_help_str(&ds, command_type); ++ *(int *)aux = 0; ++ } else if (hinic3_dfx_port_process_args(argc, argv, netdev_name, &is_global) == true) { ++ *(int *)aux = hinic3_flush_stats(&ds, netdev_name, is_global); ++ } else { ++ hinic3_ds_put_format(&ds, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ *(int *)aux = -1; ++ } ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c +new file mode 100644 +index 0000000..fc6d3f2 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c +@@ -0,0 +1,582 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_dfx_port.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_ds.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_bond_controller.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++static int ++hinic3_dump_virtual_upcall_queues_info(struct ds *ds) ++{ ++ struct hinic3_virtual_queue_info info = {0}; ++ int ret = hinic3_virtual_queue_get_upcall_info(&info); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix( ++ ds, 0, HINIC3_UI_LEADING_SIGN_FAILURE, "%s%d\n", HINIC3_UI_DFX_COMMAND_VIRTUAL_QUEUE_ERROR_STRING, ret); ++ return -EPERM; ++ } ++ ++ hinic3_ds_put_format_prefix( ++ ds, INDENT_2, HINIC3_UI_EMPTY_STRING, HINIC3_UI_DFX_COMMAND_UPCALL_VIRTUAL_INFO_HEADER_STRING "\n"); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%-45s%u\n", HINIC3_UI_DFX_COMMAND_MAX_PHYSICAL_QUEUE_STRING, info.physical_queue_num); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%-45s%u\n", HINIC3_UI_DFX_COMMAND_VIRTUAL_UPCALL_QUEUE_MAX_STRING, info.total_virtual_queue_num); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%-45s%u\n", HINIC3_UI_DFX_COMMAND_VIRTUAL_UPCALL_QUEUE_AVAILIABLE_STRING, info.left_virtual_queue_num); ++ for (uint8_t group_index = 0; group_index < info.virtual_queue_group_num; ++group_index) { ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%s%-3u%-37s%u\n", HINIC3_UI_DFX_COMMAND_GROUP_STRING, group_index, ++ HINIC3_UI_DFX_COMMAND_AVAILIBLE_QUEUE_EVERY_GROUP_STRING, info.left_group_queue_num[group_index]); ++ } ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%-45s%u\n", HINIC3_UI_DFX_COMMAND_USED_VIRTUAL_UPCALL_QUEUE_STRING, ++ info.total_virtual_queue_num - info.left_virtual_queue_num); ++ ++ return 0; ++} ++ ++static void ++hinic3_dump_virtual_queue_table_item_to_screen( ++ struct ds *ds, const char *port_name, struct hinic3_queue *rxq) ++{ ++ struct hinic3_virtual_queue *virtual_rxq = rxq->variant.virtual_queue; ++ ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "port-name: %s\n", port_name); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "queue-id: %u\n", rxq->queue_id); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "vport-id: %u\n", rxq->vport_id); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "queue-name: %s\n", virtual_rxq->ring_name); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "pkts: %u\n", ++ rte_atomic64_read(&rxq->statistic.pkts)); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "virt-dropped: %u\n", ++ rte_atomic64_read(&rxq->statistic.pkts_drop)); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "phy-dropped: %u\n", ++ rte_atomic64_read(&rxq->statistic.pkts_drop)); ++} ++ ++static char * ++hinic3_get_port_name_by_virtual_queue(struct ds *ds, struct hinic3_virtual_queue *virtual_rxq) ++{ ++ struct rte_eth_dev_data *data = NULL; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ char *port_name = NULL; ++ struct hinic3_queue *rxq = virtual_rxq->queue_info; ++ ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(rxq->dpdk_index_id); ++ if (vf_dev == NULL) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VF_DEV_ERR_STR"\n"); ++ return NULL; ++ } ++ data = vf_dev->dev->data; ++ port_name = data->name; ++ ++ return port_name + strlen(HINIC3_ETH_VDEV_DRV_NAME); ++} ++ ++static int ++hinic3_dump_virtual_upcall_queue_by_port(struct ds *ds, const char *port_name) ++{ ++ int ret; ++ uint16_t dpdk_index_id = 0; ++ char netdev_name[HINIC3_NETDEV_NAME_MAX_LENGTH] = {0}; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct hinic3_queue *rxq = NULL; ++ ++ ret = hinic3_get_netdev_name(port_name, netdev_name); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_INVALID_PORT_NAME_STR "\n"); ++ return -EINVAL; ++ } ++ ++ ret = rte_eth_dev_get_port_by_name(netdev_name, &dpdk_index_id); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_ID_ERR_STR"\n"); ++ return -EINVAL; ++ } ++ ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(dpdk_index_id); ++ if (vf_dev == NULL) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VF_DEV_ERR_STR"\n"); ++ return -EINVAL; ++ } ++ ++ for (uint8_t idx = 0; idx < MAX_RX_QUEUE_PER_VPORT; ++idx) { ++ if (vf_dev->upcall_queue.is_queue_valid[idx] == false) ++ continue; ++ if (idx != 0) ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "\n"); ++ rxq = vf_dev->upcall_queue.rx_queues[idx]; ++ hinic3_dump_virtual_queue_table_item_to_screen(ds, port_name, rxq); ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_dump_virtual_upcall_queue_by_name(struct ds *ds, const char *ring_name) ++{ ++ struct hinic3_queue *rxq = NULL; ++ struct hinic3_virtual_queue *virtual_rxq = NULL; ++ char *port_name = NULL; ++ ++ virtual_rxq = hinic3_get_virtual_queue_by_ring(ring_name); ++ if (virtual_rxq == NULL) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_FIND_VIRTUAL_QUEUE_ERR_STR"\n", ring_name); ++ return -EINVAL; ++ } ++ ++ if (virtual_rxq->ring == NULL) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_INFO, ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VIRTUAL_QUEUE_DEACTIVE_ERR_STR"\n", ring_name); ++ return 0; ++ } ++ ++ port_name = hinic3_get_port_name_by_virtual_queue(ds, virtual_rxq); ++ rxq = virtual_rxq->queue_info; ++ hinic3_dump_virtual_queue_table_item_to_screen(ds, port_name, rxq); ++ ++ return 0; ++} ++ ++static int ++hinic3_dump_virtual_upcall_queue_by_physical_queue(struct ds *ds, const char *physical_queue_id_str) ++{ ++ uint16_t physical_queue_id; ++ char *endPtr = NULL; ++ ++ struct hinic3_queue *rxq = NULL; ++ struct hinic3_virtual_queue *virtual_rxq = NULL; ++ struct hinic3_physical_queue *physical_rxq = NULL; ++ char *port_name = NULL; ++ ++ physical_queue_id = strtoul(physical_queue_id_str, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER"\n"); ++ return -EINVAL; ++ } ++ ++ physical_rxq = hinic3_get_physical_queue_by_index(physical_queue_id); ++ if (physical_rxq == NULL) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER"\n"); ++ return -EINVAL; ++ } ++ ++ if (physical_rxq->virtual_queue_valid_cnt == 0) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_INFO, ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PHYSICAL_QUEUE_DEACTIVE_ERR_STR"\n", physical_queue_id); ++ return 0; ++ } ++ ++ for (uint8_t index = 0; index < HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MAX; ++index) { ++ if (physical_rxq->is_virtual_queue_valids[index] == false) ++ continue; ++ if (index != 0) ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "\n"); ++ virtual_rxq = physical_rxq->virtual_queues[index]; ++ port_name = hinic3_get_port_name_by_virtual_queue(ds, virtual_rxq); ++ rxq = virtual_rxq->queue_info; ++ if (port_name == NULL || rxq == NULL) { ++ hinic3_ds_clear(ds); ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_FAILURE, ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_NAME_ERR_STR"\n"); ++ return -EFAULT; ++ } ++ hinic3_dump_virtual_queue_table_item_to_screen(ds, port_name, rxq); ++ } ++ ++ return 0; ++} ++ ++ ++static int ++hinic3_dump_virtual_upcall_queue_help(struct ds *ds) ++{ ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, "%s%s\n\n", ++ HINIC3_UI_CMD_USAGE_STRING, HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_STRING); ++ hinic3_ds_put_format_prefix(ds, INDENT_2, HINIC3_UI_EMPTY_STRING, HINIC3_UI_FLOW_OPTION_LIST_STRING"\n"); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, "%-30s%-s\n", ++ HINIC3_UI_FLOW_DUMP_HELP_FORMAT_STRING, HINIC3_UI_FLOW_DUMP_HELP_TIPS_STRING); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, "%-30s%-s\n", ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_FORMAT_STRING, HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PORT_TIPS_STRING); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, "%-30s%-s\n", ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VIRTUAL_FORMAT_STRING, HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_VIRTUAL_TIPS_STRING); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, "%-30s%-s\n", ++ HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PHYSICAL_FORMAT_STRING, HINIC3_UI_PORT_DUMP_UPCALL_QUEUE_PHYSICAL_TIPS_STRING); ++ ++ return 0; ++} ++ ++enum { ++ HINIC3_HELP_QUEUE_OPT, ++ HINIC3_PORT_QUEUE_OPT, ++ HINIC3_VIRTUAL_QUEUE_OPT, ++ HINIC3_PHYSICAL_QUEUE_OPT, ++}; ++ ++static const struct hinic3_opt upcall_queue_cmd_opts[] = { ++ {"-h", REQUIRED_ARGUMENT, 0, HINIC3_HELP_QUEUE_OPT}, ++ {"--help", REQUIRED_ARGUMENT, 0, HINIC3_HELP_QUEUE_OPT}, ++ {"-port", OPTIONAL_ARGUMENT, 0, HINIC3_PORT_QUEUE_OPT}, ++ {"-virtual", OPTIONAL_ARGUMENT, 0, HINIC3_VIRTUAL_QUEUE_OPT}, ++ {"-physical", OPTIONAL_ARGUMENT, 0, HINIC3_PHYSICAL_QUEUE_OPT}, ++}; ++ ++static int ++hinic3_check_option(struct ds *ds, int argc, const char *name) ++{ ++ int option_val; ++ size_t idx = 0; ++ for (idx = 0; idx < sizeof(upcall_queue_cmd_opts) / sizeof(struct hinic3_opt); idx++) { ++ if (strcmp(name, upcall_queue_cmd_opts[idx].name) == 0) { ++ if (argc != upcall_queue_cmd_opts[idx].has_arg + 1) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, upcall_queue_cmd_opts[idx].has_arg); ++ return -EINVAL; ++ } ++ option_val = upcall_queue_cmd_opts[idx].val; ++ return option_val; ++ } ++ } ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, OPTIONAL_ARGUMENT); ++ return -EINVAL; ++} ++ ++static int ++hinic3_dump_normal_upcall_queues_info(struct ds *ds, int argc) ++{ ++ if (argc != 1) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_TOO_MANY_PARAMETER"\n"); ++ return -EINVAL; ++ } ++ ++ struct hinic3_port_upcall_info upcall_info = { 0 }; ++ int ret = hinic3_port_mgmt_get_upcall_info(&upcall_info); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix( ++ ds, 0, HINIC3_UI_LEADING_SIGN_FAILURE, "%s%d\n", HINIC3_UI_DFX_COMMAND_UPCALL_QUEUE_ERROR_STRING, ret); ++ return -EINVAL; ++ } ++ ++ hinic3_ds_put_format_prefix( ++ ds, INDENT_2, HINIC3_UI_EMPTY_STRING, HINIC3_UI_DFX_COMMAND_UPCALL_INFO_HEADER_STRING "\n"); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%-35s%u\n", HINIC3_UI_DFX_COMMAND_MAX_UPCALL_QUEUE_STRING, upcall_info.total_upcall_qnum); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%-35s%u\n", HINIC3_UI_DFX_COMMAND_AVAILIBLE_UPCALL_QUEUE_STRING, upcall_info.left_upcall_qnum); ++ hinic3_ds_put_format_prefix(ds, INDENT_4, HINIC3_UI_EMPTY_STRING, ++ "%-35s%u\n", HINIC3_UI_DFX_COMMAND_USED_UPCALL_QUEUE_STRING, ++ upcall_info.total_upcall_qnum - upcall_info.left_upcall_qnum); ++ ++ return 0; ++} ++ ++static int ++hinic3_dump_virtual_upcall_queues_option(struct ds *ds, int argc, const char *argv[]) ++{ ++ int ret = -1; ++ if (argc == 1) { ++ ret = hinic3_dump_virtual_upcall_queues_info(ds); ++ return ret; ++ } ++ int option_val = hinic3_check_option(ds, argc, argv[1]); ++ ++ switch (option_val) { ++ case HINIC3_HELP_QUEUE_OPT: ++ ret = hinic3_dump_virtual_upcall_queue_help(ds); ++ break; ++ ++ case HINIC3_PORT_QUEUE_OPT: ++ ret = hinic3_dump_virtual_upcall_queue_by_port(ds, argv[argc - 1]); ++ break; ++ ++ case HINIC3_VIRTUAL_QUEUE_OPT: ++ ret = hinic3_dump_virtual_upcall_queue_by_name(ds, argv[argc - 1]); ++ break; ++ ++ case HINIC3_PHYSICAL_QUEUE_OPT: ++ ret = hinic3_dump_virtual_upcall_queue_by_physical_queue(ds, argv[argc - 1]); ++ break; ++ ++ default: ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER"\n"); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++void ++hinic3_dump_upcall_queues_info_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ if (hinic3_get_virtual_queue_mode_enabled() == false) { ++ ret = hinic3_dump_normal_upcall_queues_info(&ds, argc); ++ } else { ++ ret = hinic3_dump_virtual_upcall_queues_option(&ds, argc, argv); ++ } ++ ++ if (ret != 0) { ++ *(int *)aux = -EINVAL; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++ } ++ ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++static void ++hinic3_dump_ports_queue_info_help(struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, ++ "%2sUsage: dpak-ovs-ctl hwoff/dump-ports-queue-info { -p | { -h | --help } }\n\n", ++ HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%2sOptions list:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4s%-30sDump one port queue info\n", HINIC3_UI_INDENT_SPACE, "-p "); ++ hinic3_ds_put_format(ds, "%4s%-30sShow help command\n", HINIC3_UI_INDENT_SPACE, "-h, --help"); ++} ++ ++enum { ++ HINIC3_DUMP_PORT_QUEUE_HELP_OPT, ++ HINIC3_DUMP_PORT_QUEUE_OPT, ++}; ++ ++static const struct hinic3_opt dump_queue_cmd_opts[] = { ++ {"-h", NO_ARGUMENT, 0, HINIC3_DUMP_PORT_QUEUE_HELP_OPT}, ++ {"--help", NO_ARGUMENT, 0, HINIC3_DUMP_PORT_QUEUE_HELP_OPT}, ++ {"-p", REQUIRED_ARGUMENT, 0, HINIC3_DUMP_PORT_QUEUE_OPT}, ++}; ++ ++static int ++hinic3_dump_queue_info_check_option(struct ds *ds, int argc, const char *name) ++{ ++ enum { ++ ARGC = 2 ++ }; ++ ++ size_t idx = 0; ++ for (idx = 0; idx < sizeof(dump_queue_cmd_opts) / sizeof(struct hinic3_opt); idx++) { ++ if (strcmp(name, dump_queue_cmd_opts[idx].name) == 0) { ++ if (argc != dump_queue_cmd_opts[idx].has_arg + ARGC) { ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, dump_queue_cmd_opts[idx].has_arg + 1); ++ return -1; ++ } ++ return dump_queue_cmd_opts[idx].val; ++ } ++ } ++ return -1; ++} ++ ++static void ++hinic3_dump_vf_port_queue_stats_to_screen(struct ds *output_msg, struct hinic3_vf_dev *vf_dev) ++{ ++ struct hinic3_standard_queue *rxq = NULL; ++ struct hinic3_standard_queue *txq = NULL; ++ struct hinic3_queue *virtual_rxq = NULL; ++ ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_RX_QUEUE_INFO, HINIC3_UI_INDENT_SPACE); ++ for (uint8_t idx = 0; idx < MAX_RX_QUEUE_PER_VPORT; ++idx) { ++ if (vf_dev->upcall_queue.is_queue_valid[idx] == false) ++ continue; ++ if (idx != 0) ++ hinic3_ds_put_format_prefix(output_msg, INDENT_2, HINIC3_UI_EMPTY_STRING, "\n"); ++ ++ if (hinic3_get_virtual_queue_mode_enabled() == false) { ++ rxq = vf_dev->upcall_queue.rx_queue[idx]; ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_QUEUE_ID, HINIC3_UI_INDENT_SPACE, rxq->queue_id); ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_RX_QUEUE_PKTS, HINIC3_UI_INDENT_SPACE, ++ rte_atomic64_read(&rxq->info.pkts)); ++ } else { ++ virtual_rxq = vf_dev->upcall_queue.rx_queues[idx]; ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_QUEUE_ID, HINIC3_UI_INDENT_SPACE, virtual_rxq->queue_id); ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_RX_QUEUE_PKTS, HINIC3_UI_INDENT_SPACE, ++ rte_atomic64_read(&virtual_rxq->statistic.pkts)); ++ } ++ } ++ ++ hinic3_ds_put_format(output_msg, "\n"); ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_TX_QUEUE_INFO, HINIC3_UI_INDENT_SPACE); ++ for (uint8_t idx = 0; idx < MAX_TX_QUEUE_PER_VPORT; ++idx) { ++ if (vf_dev->reinject_queue.is_queue_valid[idx] == false) { ++ continue; ++ } ++ if (idx != 0) { ++ hinic3_ds_put_format_prefix(output_msg, INDENT_2, HINIC3_UI_EMPTY_STRING, "\n"); ++ } ++ txq = vf_dev->reinject_queue.tx_queues[idx]; ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_QUEUE_ID, HINIC3_UI_INDENT_SPACE, txq->queue_id); ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_TX_QUEUE_PKTS, HINIC3_UI_INDENT_SPACE, ++ rte_atomic64_read(&txq->info.pkts)); ++ } ++} ++ ++static void ++hinic3_dump_pf_port_queue_stats_to_screen(struct ds *output_msg, struct hinic3_bond_dev *pf_dev) ++{ ++ struct hinic3_standard_queue *rxq = NULL; ++ struct hinic3_standard_queue *txq = NULL; ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_RX_QUEUE_INFO, HINIC3_UI_INDENT_SPACE); ++ for (uint8_t idx = 0; idx < MAX_RX_QUEUE_PER_VPORT; ++idx) { ++ if (pf_dev->upcall_queue.is_queue_valid[idx] == false) ++ continue; ++ if (idx != 0) ++ hinic3_ds_put_format_prefix(output_msg, INDENT_2, HINIC3_UI_EMPTY_STRING, "\n"); ++ rxq = pf_dev->upcall_queue.rx_queue[idx]; ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_QUEUE_ID, HINIC3_UI_INDENT_SPACE, rxq->queue_id); ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_RX_QUEUE_PKTS, HINIC3_UI_INDENT_SPACE, ++ rte_atomic64_read(&rxq->info.pkts)); ++ } ++ ++ hinic3_ds_put_format(output_msg, "\n"); ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_TX_QUEUE_INFO, HINIC3_UI_INDENT_SPACE); ++ for (uint8_t idx = 0; idx < MAX_TX_QUEUE_PER_VPORT; ++idx) { ++ if (pf_dev->reinject_queue.is_queue_valid[idx] == false) ++ continue; ++ if (idx != 0) ++ hinic3_ds_put_format_prefix(output_msg, INDENT_2, HINIC3_UI_EMPTY_STRING, "\n"); ++ txq = pf_dev->reinject_queue.tx_queues[idx]; ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_QUEUE_ID, HINIC3_UI_INDENT_SPACE, txq->queue_id); ++ hinic3_ds_put_format(output_msg, HINIC3_DUMP_PORT_TX_QUEUE_PKTS, HINIC3_UI_INDENT_SPACE, ++ rte_atomic64_read(&txq->info.pkts)); ++ } ++} ++ ++static int ++hinic3_show_vf_port_queue_stats_info(struct ds *output_msg, uint16_t dpdk_index_id, uint32_t link_status) ++{ ++ struct hinic3_vf_dev *vf_dev = NULL; ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(dpdk_index_id); ++ if (vf_dev == NULL) { ++ hinic3_ds_put_format(output_msg, "%sThe current device's private data is NULL!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ ++ hinic3_dump_vf_port_queue_stats_to_screen(output_msg, vf_dev); ++ return 0; ++} ++ ++static int ++hinic3_show_pf_port_queue_stats_info(struct ds *output_msg, uint16_t dpdk_index_id, uint32_t link_status) ++{ ++ struct hinic3_bond_dev *pf_dev = NULL; ++ pf_dev = (struct hinic3_bond_dev *)hinic3_get_private_data(dpdk_index_id); ++ if (pf_dev == NULL) { ++ hinic3_ds_put_format(output_msg, "%sThe current device's private data is NULL\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ ++ hinic3_dump_pf_port_queue_stats_to_screen(output_msg, pf_dev); ++ return 0; ++} ++ ++static int ++hinic3_dump_ports_queue_info_sub(struct ds *output_msg, const char *port_name) ++{ ++ int ret = 0; ++ char netdev_name[HINIC3_NETDEV_NAME_MAX_LENGTH] = {0}; ++ uint16_t dpdk_index_id; ++ uint16_t port_id; ++ uint32_t link_status; ++ uint32_t if_index; ++ ++ ret = hinic3_get_netdev_name(port_name, netdev_name); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix(output_msg, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_PORT_DUMP_QUEUE_NETDEV_ERR_STR "\n"); ++ return -1; ++ } ++ ++ ret = rte_eth_dev_get_port_by_name(netdev_name, &dpdk_index_id); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix(output_msg, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_PORT_DUMP_QUEUE_PORT_ID_ERR_STR "\n", netdev_name); ++ return -1; ++ } ++ ++ ret = hinic3_get_port_ifindex(dpdk_index_id, &if_index); ++ if (ret != 0 || if_index > UINT16_MAX) { ++ hinic3_ds_put_format_prefix(output_msg, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_UI_PORT_DUMP_QUEUE_DEVICE_IFINDEX_ERR_STR "\n", netdev_name); ++ return -1; ++ } ++ port_id = (uint16_t)if_index; ++ ++ if (is_hinic3_vf_dev(dpdk_index_id) == true) { ++ ret = hinic3_port_mgmt_get_usage_state(port_id, &link_status); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix(output_msg, 0, HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_PORT_GET_VF_LINK_ERR "\n", ++ ret); ++ return ret; ++ } ++ ++ ret = hinic3_show_vf_port_queue_stats_info(output_msg, dpdk_index_id, link_status); ++ } else { ++ ret = hinic3_get_bond_link_from_netdev(output_msg, netdev_name, &link_status); ++ if (ret != 0) { ++ hinic3_ds_put_format_prefix(output_msg, 0, HINIC3_UI_LEADING_SIGN_ERROR, ++ HINIC3_DUMP_PORT_GET_BOND_LINK_ERR "\n", ret); ++ return ret; ++ } ++ ret = hinic3_show_pf_port_queue_stats_info(output_msg, dpdk_index_id, link_status); ++ } ++ return ret; ++} ++ ++static int ++hinic3_dump_ports_queue_info_options(struct ds *ds, int argc, const char *argv[]) ++{ ++ int ret = 0; ++ int option_val = hinic3_dump_queue_info_check_option(ds, argc, argv[1]); ++ switch (option_val) { ++ case HINIC3_DUMP_PORT_QUEUE_HELP_OPT: ++ hinic3_dump_ports_queue_info_help(ds); ++ break; ++ ++ case HINIC3_DUMP_PORT_QUEUE_OPT: ++ ret = hinic3_dump_ports_queue_info_sub(ds, argv[argc - 1]); ++ break; ++ ++ default: ++ hinic3_ds_put_format_prefix(ds, 0, HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER "\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++void ++hinic3_dump_ports_queue_info_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ ret = hinic3_dump_ports_queue_info_options(&ds, argc, argv); ++ if (ret != 0) { ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++ } ++ ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c +new file mode 100644 +index 0000000..14b32d9 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c +@@ -0,0 +1,395 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_trace_flow.h" ++#include "hinic3_util.h" ++#include "hinic3_eth_packets.h" ++#include "hinic3_log.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_command.h" ++#include "hinic3_ds.h" ++#include "hinic3_eth_packets.h" ++ ++#define HINIC3_TRACE_FLOW_FILTER_EXIST (-1) ++#define HINIC3_TRACE_FLOW_HAS_DIFF_FILTER (-2) ++#define HINIC3_TRACE_FLOW_FILTER_OVERFLOW (-3) ++ ++#define TRACE_FLOW_MASK_8 0xFF ++#define TRACE_FLOW_MASK_16 0xFFFF ++#define TRACE_FLOW_MASK_32 0xFFFFFFFF ++ ++#define STRTOUL_NUM 10 ++#define TRACE_FLOW_PARA_MAX 11 ++ ++static const char *g_hinic3_trace_flow_status_string[] = { ++ "hinic3_flow_pkt_key_resolve_done", ++ "hinic3_flow_agent_error_input_not_hiovs", ++ "hinic3_flow_construct_key_done", ++ "hinic3_flow_agent_error_trans_key", ++ "hinic3_flow_offload_key_process_done", ++ "hinic3_flow_offload_key_hash_done", ++ "hinic3_flow_offload_hash_table_insert_done", ++ "hinic3_flow_offload_hash_table_insert_error", ++ "hinic3_flow_copy_recircle_act_done", ++ "hinic3_flow_process_offload_action_done", ++ "hinic3_flow_process_offload_action_error", ++ "hinic3_backup_ct_state_done", ++ "hinic3_flow_agent_error_process_recirc", ++ "hinic3_process_offload_key_act_done", ++ "hinic3_flow_agent_error_prepare_offload_args", ++ "hinic3_process_offload_args_done", ++ "hinic3_flow_agent_error_offload_limits", ++ "hinic3_flow_agent_error_no_conn_table", ++ "hinic3_flow_agent_stats_offload_delay", ++ "hinic3_flow_agent_error_duplicate_offload", ++ "hinic3_agent_is_flow_ready_put_done", ++ "hinic3_flow_agent_error_ct_check_fail", ++ "hinic3_flow_agent_error_ct_not_ready", ++ "hinic3_agent_is_ct_ready_to_offload_done", ++ "hinic3_flow_agent_error_hardware_fail", ++ "hinic3_agent_flow_put_done", ++}; ++ ++void ++hinic3_trace_flow_current_key_update(struct hinic3_filter_tuple *cur_key, const struct hinic3_conntrack_key *key) ++{ ++ struct hinic3_key_5tuple *tuple = (struct hinic3_key_5tuple *)key->key; ++ ++ cur_key->proto = key->meta.tcp_udp_flag; ++ cur_key->src_ip = tuple->ip.src; ++ cur_key->dst_ip = tuple->ip.dst; ++ cur_key->port_src = tuple->port_src; ++ cur_key->port_dst = tuple->port_dst; ++} ++ ++void ++hinic3_trace_flow_init(struct hinic3_trace_flow *trace_flow_info) ++{ ++ memset(trace_flow_info->filter, 0, ++ sizeof(struct hinic3_trace_filter) * HINIC3_MAX_TRACE_FLOW_NUM); ++ trace_flow_info->count = 0; ++} ++ ++static void ++hinic3_trace_flow_clean(struct hinic3_trace_flow *trace_flow_info) ++{ ++ hinic3_trace_flow_init(trace_flow_info); ++} ++ ++static inline int ++hinic3_get_trace_flow_count(struct hinic3_trace_flow *trace_table) ++{ ++ return trace_table->count; ++} ++ ++static struct hinic3_trace_filter * ++hinic3_trace_flow_get_filter(struct hinic3_trace_flow *trace_table, int i) ++{ ++ if (hinic3_get_trace_flow_count(trace_table) <= i) ++ return NULL; ++ ++ return &trace_table->filter[i]; ++} ++ ++static bool ++hinic3_trace_flow_filter_cmp(struct hinic3_filter_tuple *src, struct hinic3_filter_tuple *mask, ++ struct hinic3_filter_tuple *dst) ++{ ++ uint8_t *src_ptr = (uint8_t *)src; ++ uint8_t *mask_ptr = (uint8_t *)mask; ++ uint8_t *dst_ptr = (uint8_t *)dst; ++ size_t tuple_size = sizeof(struct hinic3_filter_tuple); ++ ++ for (size_t i = 0; i < tuple_size; i++) { ++ if ((src_ptr[i] & mask_ptr[i]) != dst_ptr[i]) ++ return false; ++ } ++ ++ return true; ++} ++ ++void ++hinic3_trace_flow_info_update(int status, const struct hinic3_conntrack_key *key) ++{ ++ int cnt; ++ struct hinic3_trace_flow *trace_table_info = NULL; ++ struct hinic3_trace_filter *filter = NULL; ++ struct hinic3_flow_agent_db *hw_offload = NULL; ++ struct hinic3_filter_tuple cur_key = {0}; ++ struct hinic3_dp_extend_info *extend_info = hinic3_get_offload_extend_info(); ++ ++ if (extend_info == NULL || extend_info->hw_offload == NULL || key == NULL) ++ return; ++ ++ hinic3_trace_flow_current_key_update(&cur_key, key); ++ ++ hw_offload = extend_info->hw_offload; ++ trace_table_info = &hw_offload->trace_flow_info; ++ cnt = trace_table_info->count; ++ ++ for (int i = 0; i < cnt; i++) { ++ filter = hinic3_trace_flow_get_filter(trace_table_info, i); ++ if (HINIC3_UNLIKELY(filter == NULL)) ++ continue; ++ ++ if (hinic3_trace_flow_filter_cmp(&cur_key, &filter->mask, &filter->key)) ++ filter->status[status]++; ++ } ++} ++ ++static int ++hinic3_trace_flow_has_same_filter(struct hinic3_trace_flow *trace_table, struct hinic3_filter_tuple *key) ++{ ++ struct hinic3_trace_filter *filter = NULL; ++ ++ for (int i = 0; i < trace_table->count; i++) { ++ filter = hinic3_trace_flow_get_filter(trace_table, i); ++ if (HINIC3_UNLIKELY(filter == NULL)) ++ continue; ++ ++ if (hinic3_trace_flow_filter_cmp(key, &filter->mask, &filter->key)) ++ return HINIC3_TRACE_FLOW_FILTER_EXIST; ++ } ++ ++ return HINIC3_TRACE_FLOW_HAS_DIFF_FILTER; ++} ++ ++static inline void ++hinic3_set_ip_mask(struct hinic3_ip_addr *ip_mask, struct hinic3_ip_addr *ip_addr) ++{ ++ uint32_t *mask = (uint32_t *)&ip_mask->ipv6; ++ uint32_t *key = (uint32_t *)&ip_addr->ipv6; ++ size_t loop_size = sizeof(struct in6_addr) / sizeof(uint32_t); ++ ++ for (size_t i = 0; i < loop_size; i++) { ++ if (key[i] != 0) { ++ mask[i] = TRACE_FLOW_MASK_32; ++ continue; ++ } ++ mask[i] = 0; ++ } ++} ++ ++static void ++hinic3_trace_flow_set_filter(struct hinic3_trace_filter *filter, struct hinic3_filter_tuple *key) ++{ ++ memset(filter, 0, sizeof(struct hinic3_trace_filter)); ++ ++ filter->key = *key; ++ ++ filter->mask.proto = TRACE_FLOW_MASK_8; /* current only support tcp udp */ ++ hinic3_set_ip_mask(&filter->mask.src_ip, &key->src_ip); ++ hinic3_set_ip_mask(&filter->mask.dst_ip, &key->dst_ip); ++ filter->mask.port_src = (key->port_src != 0) ? TRACE_FLOW_MASK_16 : 0; ++ filter->mask.port_dst = (key->port_dst != 0) ? TRACE_FLOW_MASK_16 : 0; ++} ++ ++static int ++hinic3_add_trace_flow_filter(struct hinic3_trace_flow *trace_table, struct hinic3_filter_tuple *key) ++{ ++ int ret; ++ int cnt; ++ ++ if (trace_table->count >= HINIC3_MAX_TRACE_FLOW_NUM) ++ return HINIC3_TRACE_FLOW_FILTER_OVERFLOW; ++ ++ ret = hinic3_trace_flow_has_same_filter(trace_table, key); ++ if (ret == HINIC3_TRACE_FLOW_FILTER_EXIST) ++ return ret; ++ ++ cnt = trace_table->count; ++ hinic3_trace_flow_set_filter(&trace_table->filter[cnt], key); ++ trace_table->count++; ++ ++ return trace_table->count; ++} ++ ++static int ++hinic3_trace_flow_cmd_para_check(int argc, const char *argv[], struct hinic3_filter_tuple *key, ++ struct ds *reply) ++{ ++ char *endptr = NULL; ++ ++ int work_argc = 1; ++ do { ++ if (strncmp("-proto", argv[work_argc], sizeof("-proto")) == 0) { ++ work_argc += 1; ++ if (strncmp("tcp", argv[work_argc], sizeof("tcp")) == 0) { ++ key->proto = HINIC3_CT_TCP_FLAG; ++ } else if (strncmp("udp", argv[work_argc], sizeof("udp")) == 0) { ++ key->proto = HINIC3_CT_UDP_FLAG; ++ } else { ++ hinic3_ds_put_format(reply, "%sonly support tcp or udp\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ } else if (strncmp("-sip", argv[work_argc], sizeof("-sip")) == 0) { ++ work_argc += 1; ++ if (inet_pton(AF_INET, argv[work_argc], &(key->src_ip.ipv4)) <= 0) { ++ hinic3_ds_put_format(reply, "%sinvalid source ip\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ } else if (strncmp("-dip", argv[work_argc], sizeof("-dip")) == 0) { ++ work_argc += 1; ++ if (inet_pton(AF_INET, argv[work_argc], &(key->dst_ip.ipv4)) <= 0) { ++ hinic3_ds_put_format(reply, "%sinvalid destination ip\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ } else if (strncmp("-sport", argv[work_argc], sizeof("-sport")) == 0) { ++ work_argc += 1; ++ if (strtoul(argv[work_argc], &endptr, STRTOUL_NUM) > UINT16_MAX || !endptr || (*endptr != '\0')) { ++ hinic3_ds_put_format(reply, "%sinvalid source port number\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ key->port_src = strtoul(argv[work_argc], &endptr, STRTOUL_NUM); ++ key->port_src = htons(key->port_src); ++ } else if (strncmp("-dport", argv[work_argc], sizeof("-dport")) == 0) { ++ work_argc += 1; ++ if (strtoul(argv[work_argc], &endptr, STRTOUL_NUM) > UINT16_MAX || !endptr || (*endptr != '\0')) { ++ hinic3_ds_put_format(reply, "%sinvalid destination port number\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ key->port_dst = strtoul(argv[work_argc], &endptr, STRTOUL_NUM); ++ key->port_dst = htons(key->port_dst); ++ } else { ++ hinic3_ds_put_format(reply, "Error: %s, input -h to get help info.\n", HINIC3_UI_ERROR_WRONG_PARAMETER); ++ return -1; ++ } ++ work_argc += 1; ++ } while (work_argc < TRACE_FLOW_PARA_MAX); ++ ++ return 0; ++} ++ ++void ++hinic3_agent_trace_flow_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) ++{ ++ struct ds reply = DS_EMPTY_INITIALIZER; ++ struct hinic3_filter_tuple key = {0}; ++ struct hinic3_flow_agent_db *hw_offload = NULL; ++ struct hinic3_dp_extend_info *extend_info = hinic3_get_offload_extend_info(); ++ int ret = 0; ++ ++ if (extend_info == NULL || extend_info->hw_offload == NULL) { ++ hinic3_ds_put_format(&reply, "%sdatapath info not exist\n", HINIC3_UI_LEADING_SIGN_INFO); ++ goto exit; ++ } ++ hw_offload = extend_info->hw_offload; ++ ++ if (argc != TRACE_FLOW_PARA_MAX) { ++ hinic3_ds_put_format(&reply, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, ++ TRACE_FLOW_PARA_MAX - 1); ++ goto exit; ++ } ++ ++ ret = hinic3_trace_flow_cmd_para_check(argc, argv, &key, &reply); ++ if (ret != 0) ++ goto exit; ++ ++ ret = hinic3_add_trace_flow_filter(&hw_offload->trace_flow_info, &key); ++ if (ret == HINIC3_TRACE_FLOW_FILTER_OVERFLOW) { ++ HINIC3_LOG(INFO, AGENT, "trace flow table is full\n"); ++ hinic3_ds_put_format(&reply, "%strace flow table is full.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ } else if (ret == HINIC3_TRACE_FLOW_FILTER_EXIST) { ++ HINIC3_LOG(INFO, AGENT, "trace flow filter already exist.\n"); ++ hinic3_ds_put_format(&reply, "%strace flow filter already exist.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ } else { ++ HINIC3_LOG(INFO, AGENT, "Add trace flow filter DONE.\n"); ++ hinic3_ds_put_format(&reply, "%sAdd trace flow filter DONE.\n", HINIC3_UI_LEADING_SIGN_INFO); ++ } ++ ++exit: ++ hinic3_command_reply(conn, hinic3_ds_cstr(&reply)); ++ hinic3_ds_destroy(&reply); ++} ++ ++static void ++hinic3_dump_trace_get_info(uint64_t *status, int i, struct hinic3_filter_tuple *key, ++ struct hinic3_trace_flow *trace_table) ++{ ++ for (int j = 0; j < HINIC3_FLOW_TRACE_STATUS_MAX; j++) { ++ status[j] = trace_table->filter[i].status[j]; ++ } ++ *key = trace_table->filter[i].key; ++} ++ ++static void ++hinic3_dump_filter_info(struct hinic3_trace_flow *trace_flow, struct ds *reply) ++{ ++ int cnt; ++ struct hinic3_filter_tuple key = {0}; ++ uint64_t status[HINIC3_FLOW_TRACE_STATUS_MAX] = {0}; ++ ++ cnt = hinic3_get_trace_flow_count(trace_flow); ++ hinic3_ds_put_format(reply, " Total Trace Filter: %d\n", cnt); ++ for (int i = 0; i < cnt; i++) { ++ hinic3_ds_put_format(reply, " Filter %d: ", i + 1); ++ hinic3_dump_trace_get_info(status, i, &key, trace_flow); ++ hinic3_ds_put_format(reply, "%s ", key.proto == HINIC3_CT_TCP_FLAG ? "TCP" : "UDP"); ++ hinic3_ds_put_format(reply, "" IP_FMT " ", IP_ARGS(key.src_ip.ipv4)); ++ hinic3_ds_put_format(reply, "" IP_FMT " ", IP_ARGS(key.dst_ip.ipv4)); ++ hinic3_ds_put_format(reply, "%u ", ntohs(key.port_src)); ++ hinic3_ds_put_format(reply, "%u\n", ntohs(key.port_dst)); ++ ++ for (int j = 0; j < HINIC3_FLOW_TRACE_STATUS_MAX; j++) { ++ if (status[j] != 0) { ++ hinic3_ds_put_format(reply, "%-50s: %" PRIu64 "\n", g_hinic3_trace_flow_status_string[j], status[j]); ++ } ++ } ++ } ++} ++ ++void ++hinic3_agent_dump_trace_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) ++{ ++ struct ds reply = DS_EMPTY_INITIALIZER; ++ struct hinic3_trace_flow *trace_flow = NULL; ++ struct hinic3_flow_agent_db *hw_offload = NULL; ++ struct hinic3_dp_extend_info *extend_info = hinic3_get_offload_extend_info(); ++ ++ if (extend_info == NULL || extend_info->hw_offload == NULL) { ++ hinic3_ds_put_format(&reply, "%sDatapath info not exist.\n", HINIC3_UI_LEADING_SIGN_INFO); ++ goto exit; ++ } ++ ++ hw_offload = extend_info->hw_offload; ++ trace_flow = &hw_offload->trace_flow_info; ++ ++ if (argc == 2) { ++ if (strncmp("-f", argv[1], sizeof("-f")) == 0) { ++ hinic3_trace_flow_clean(trace_flow); ++ hinic3_ds_put_format(&reply, "%sTrace flow clean.\n", HINIC3_UI_LEADING_SIGN_INFO); ++ } else if ((strncmp("-h", argv[1], sizeof("-h")) == 0) || strncmp("--help", argv[1], sizeof("--help")) == 0) { ++ hinic3_ds_put_format(&reply, "%2sUsage: dpak-ovs-ctl hwoff/dump-trace [ -f | { -h | --help } ]\n\n", ++ HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(&reply, "%2sOptions list:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(&reply, "%4s-f Clear all trace filters\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(&reply, "%4s-h, --help Display the help information\n", HINIC3_UI_INDENT_SPACE); ++ } else { ++ hinic3_ds_put_format(&reply, "%s%s, please input -h or --help to get help info.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER); ++ } ++ goto exit; ++ } ++ ++ hinic3_dump_filter_info(trace_flow, &reply); ++ ++exit: ++ hinic3_command_reply(conn, hinic3_ds_cstr(&reply)); ++ hinic3_ds_destroy(&reply); ++} ++ ++void ++unixctl_hinic3_trace_flow_init(void) ++{ ++ hinic3_command_register("hwoff/trace-flow", ++ "-proto -sip ENUM,IPV6> -dip " ++ "ENUM,IPV6> -sport INTEGER<0-65535> -dport INTEGER<0-65535>", ++ TRACE_FLOW_PARA_MAX - 1, TRACE_FLOW_PARA_MAX - 1, hinic3_agent_trace_flow_cmd, NULL); ++ hinic3_command_register("hwoff/dump-trace", "[ -f | { -h | --help } ]", 0, 1, hinic3_agent_dump_trace_cmd, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.h +new file mode 100644 +index 0000000..89a9455 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.h +@@ -0,0 +1,79 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_TRACE_FLOW_H ++#define HINIC3_TRACE_FLOW_H ++ ++#include ++#include "hinic3_packet_key_public.h" ++#include "hinic3_types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_MAX_TRACE_FLOW_NUM 20 ++ ++enum hinic3_flow_trace_status { ++ /* normal process info */ ++ HINIC3_FLOW_PKT_KEY_RESOLVE_DONE_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_INPUT_NOT_HIOVS_TRACE, ++ HINIC3_FLOW_CONSTRUCT_KEY_DONE_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_TRANS_KEY_TRACE, ++ HINIC3_FLOW_OFFLOAD_KEY_PROCESS_DONE_TRACE, ++ HINIC3_FLOW_OFFLOAD_KEY_HASH_DONE_TRACE, ++ HINIC3_FLOW_OFFLOAD_KEY_INSERT_TABLE_DONE_TRACE, ++ HINIC3_FLOW_OFFLOAD_KEY_INSERT_TABLE_ERROR_TRACE, ++ HINIC3_FLOW_COPY_RECIRCLE_ACT_DONE_TRACE, ++ HINIC3_FLOW_PROCESS_OFFLOAD_ACTION_DONE_TRACE, ++ HINIC3_FLOW_PROCESS_OFFLOAD_ACTION_ERROR_TRACE, ++ HINIC3_BACKUP_CT_STATE_DONE_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_PROCESS_RECIRC_TRACE, ++ HINIC3_PROCESS_OFFLOAD_KEY_ACT_DONE_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_PREPARE_OFFLOAD_ARGS_TRACE, ++ HINIC3_PROCESS_OFFLOAD_ARGS_DONE_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_OFFLOAD_LIMITS_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_NO_CONN_TABLE_TRACE, ++ HINIC3_FLOW_AGENT_STATS_OFFLOAD_DELAY_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_DUPLICATE_OFFLOAD_TRACE, ++ HINIC3_AGENT_IS_FLOW_READY_PUT_DONE_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_CT_CHECK_FAIL_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_CT_NOT_READY_TRACE, ++ HINIC3_AGENT_IS_CT_READY_TO_OFFLOAD_DONE_TRACE, ++ HINIC3_FLOW_AGENT_ERROR_HARDWARE_FAIL_TRACE, ++ HINIC3_AGENT_FLOW_PUT_DONE_TRACE, ++ HINIC3_FLOW_TRACE_STATUS_MAX ++}; ++ ++struct hinic3_filter_tuple { ++ struct hinic3_ip_addr src_ip; ++ struct hinic3_ip_addr dst_ip; ++ hinic3_be16 port_src; ++ hinic3_be16 port_dst; ++ uint8_t proto; ++}; ++ ++struct hinic3_trace_filter { ++ struct hinic3_filter_tuple key; ++ struct hinic3_filter_tuple mask; ++ uint64_t status[HINIC3_FLOW_TRACE_STATUS_MAX]; ++}; ++struct hinic3_trace_flow { ++ struct hinic3_trace_filter filter[HINIC3_MAX_TRACE_FLOW_NUM]; ++ struct hinic3_filter_tuple cur_key; ++ int count; ++}; ++ ++void hinic3_trace_flow_init(struct hinic3_trace_flow *trace_flow_info); ++ ++void hinic3_trace_flow_info_update(int status, const struct hinic3_conntrack_key *key); ++ ++void unixctl_hinic3_trace_flow_init(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c +new file mode 100644 +index 0000000..63d8969 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c +@@ -0,0 +1,363 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_vf_dfx.h" ++#include ++#include "rte_string_fns.h" ++#include "hinic3_util.h" ++#include "hinic3_mutex.h" ++#include "hinic3_util.h" ++#include "hinic3_drv.h" ++#include "hinic3_vf_mgmt.h" ++#include "hinic3_util.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_dfx_port.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ds.h" ++#include "hinic3_mtr.h" ++#include "hinic3_command.h" ++#include "hinic3_flow_agent.h" ++ ++static char *g_vm_qos_unit[QOS_UNIT_NUM] = { ++ BW_QOS_UNIT, ++ PPS_QOS_UNIT, ++ BW_QOS_UNIT, ++ PPS_QOS_UNIT, ++}; ++ ++static struct port_status g_port_status[] = { ++ {HWPT_FLAVOR_REFCNT_UNUSED, "unused"}, ++ {HWPT_FLAVOR_REFCNT_USED, "used"}, ++ {HWPT_FLAVOR_REFCNT_INVALID, "invalid"}, ++}; ++ ++char ** ++hinic3_vm_qos_unit_get(void) ++{ ++ return g_vm_qos_unit; ++} ++ ++static void ++hinic3_port_virtio_queue_show(struct ds *ds, struct port_stats *vf_stats, struct port_stats *pf_stats) ++{ ++ hinic3_ds_put_format(ds, "%2sTotal statistics are as follows:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4s%-16s\n%6stotal: %u\n%6sused now: %u\n%6sinvalid now: %u\n", ++ HINIC3_UI_INDENT_SPACE, "vf num:", HINIC3_UI_INDENT_SPACE, ++ vf_stats->total_num, HINIC3_UI_INDENT_SPACE, vf_stats->used_num, HINIC3_UI_INDENT_SPACE, vf_stats->invalid_num); ++ hinic3_ds_put_format(ds, "%4s%-16s\n%6stotal: %u\n%6sused now: %u\n%6sinvalid now: %u\n", ++ HINIC3_UI_INDENT_SPACE, "pf num:", HINIC3_UI_INDENT_SPACE, ++ pf_stats->total_num, HINIC3_UI_INDENT_SPACE, pf_stats->used_num, HINIC3_UI_INDENT_SPACE, pf_stats->invalid_num); ++ hinic3_ds_put_format(ds, "%4s%-16s \n%6stotal: %u\n%6sused now: %u\n", HINIC3_UI_INDENT_SPACE, ++ "virtio queue:", HINIC3_UI_INDENT_SPACE, ++ vf_stats->virtio_total_num, HINIC3_UI_INDENT_SPACE, vf_stats->virtio_used_num); ++ hinic3_ds_put_format(ds, "%2sNote: Each VF/PF occupies an extra Virtio control queue.\n", HINIC3_UI_INDENT_SPACE); ++ return; ++} ++ ++void ++hinic3_virtual_vf_flavor_show(struct ds *ds) ++{ ++ struct hinic3_dev_node *iter = NULL; ++ struct dev_mgmt *dev_list = get_netdev_hwpt_flavor(); ++ ++ if (hinic3_get_port_conf_type() == PORT_CONF_FUNC) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Failed to port conf.\n"); ++ return; ++ } ++ ++ if (hinic3_device_mode_get() == SMART_NIC_MODE) { ++ dev_list = hinic3_updata_netdev_hwpt_flavor(); ++ if (dev_list == NULL) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Failed to update the VF list.\n"); ++ return; ++ } ++ } ++ ++ if (hinic3_list_is_empty(&dev_list->vf_list) == false) { ++ LIST_FOR_EACH(iter, node, &dev_list->vf_list) { ++ hinic3_ds_put_format(ds, "%2shost-pci-addr: %04x:%02x:%02x.%u\n%2stype: %11s\n%2sstatus: %s\n", ++ HINIC3_UI_INDENT_SPACE, iter->phy_dev.pci_addr.domain, iter->phy_dev.pci_addr.bus, ++ iter->phy_dev.pci_addr.devid, iter->phy_dev.pci_addr.function, HINIC3_UI_INDENT_SPACE, ++ HWPT_HWTYPE_VF_STR, HINIC3_UI_INDENT_SPACE, g_port_status[iter->phy_dev.refcnt].str); ++ if (iter->node.next != &dev_list->vf_list || hinic3_list_is_empty(&dev_list->pf_list) == false) { ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ } ++ } ++ ++ if (hinic3_list_is_empty(&dev_list->pf_list) == false) { ++ LIST_FOR_EACH(iter, node, &dev_list->pf_list) { ++ hinic3_ds_put_format(ds, "%2shost-pci-addr: %04x:%02x:%02x.%u\n%2stype: %11s\n%2sstatus: %s\n", ++ HINIC3_UI_INDENT_SPACE, iter->phy_dev.pci_addr.domain, iter->phy_dev.pci_addr.bus, ++ iter->phy_dev.pci_addr.devid, iter->phy_dev.pci_addr.function, HINIC3_UI_INDENT_SPACE, ++ HWPT_HWTYPE_PF_STR, HINIC3_UI_INDENT_SPACE, g_port_status[iter->phy_dev.refcnt].str); ++ if (iter->node.next != &dev_list->pf_list) { ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ } ++ } ++ ++ return; ++} ++ ++static const char* ++hinic3_get_port_name_by_vport_id(int vport_id) ++{ ++ int ret; ++ uint16_t port_id; ++ const char *port_name = NULL; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ ret = hinic3_get_port_id_by_ifindex(vport_id, &port_id); ++ if (ret != 0) ++ goto err; ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(port_id); ++ if (vf_dev == NULL) ++ goto err; ++ port_name = vf_dev->dev->device->name; ++ if (port_name == NULL) ++ goto err; ++ return port_name; ++err: ++ return "unknown"; ++} ++ ++static void ++hinic3_put_format_dev_flavor(struct ds *ds, struct hinic3_dev_node *iter, const char* type) ++{ ++ int id; ++ const char* status = NULL; ++ char pci_addr_buf[HWPT_PCI_ADDR_LEN_MAX] = {0}; ++ int vport_id; ++ const char* port_name = NULL; ++ const char* pci_header = NULL; ++ bool real_pci = false; ++ id = iter->phy_dev.function_id; ++ if (id == -1) { ++ HINIC3_LOG(ERR, BOND, "function id fetch failed.\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_FAILURE "Function ID fetch failed.\n"); ++ return; ++ } ++ if (pci_addr_format(&iter->phy_dev.pci_addr, pci_addr_buf, HWPT_PCI_ADDR_LEN_MAX) != 0) { ++ HINIC3_LOG(ERR, BOND, "pci addr buf parse failed.\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_FAILURE "Pci addr buf parse failed.\n"); ++ return; ++ } ++ vport_id = id + FUNCTION_ID_TO_VPORT_ID; ++ status = g_port_status[iter->phy_dev.refcnt].str; ++ port_name = hinic3_get_port_name_by_vport_id(vport_id); ++ ++ real_pci = (hinic3_query_bdf_type_get() == QUERY_BDF_TYPE_REAL); ++ if (real_pci == true) { ++ pci_header = "host-pci-addr:"; ++ } else { ++ pci_header = "fake-pci-addr:"; ++ } ++ hinic3_ds_put_format(ds, "%2sfunction-id: %d\n%2s%-15s" ++ "%s\n%2stype: %s\n%2sstatus: %s\n%2sport-name: %s\n", HINIC3_UI_INDENT_SPACE, ++ id, HINIC3_UI_INDENT_SPACE, pci_header, pci_addr_buf, HINIC3_UI_INDENT_SPACE, type, ++ HINIC3_UI_INDENT_SPACE, status, HINIC3_UI_INDENT_SPACE, port_name); ++ hinic3_ds_put_format(ds, "\n"); ++} ++ ++static void ++hinic3_function_flavor_show(struct ds *ds) ++{ ++ struct dev_mgmt *dev_list = get_netdev_hwpt_flavor(); ++ struct hinic3_dev_node *iter = NULL; ++ struct hinic3_list *list = NULL; ++ if (dev_list == NULL) { ++ HINIC3_LOG(ERR, BOND, "Failed to get dev_list"); ++ return; ++ } ++ ++ list = &dev_list->pf_list; ++ if (hinic3_list_is_empty(list) == false) { ++ LIST_FOR_EACH(iter, node, list) ++ { ++ hinic3_put_format_dev_flavor(ds, iter, HWPT_HWTYPE_PF_STR); ++ } ++ } ++ ++ list = &dev_list->vf_list; ++ if (hinic3_list_is_empty(list) == false) { ++ LIST_FOR_EACH(iter, node, list) ++ { ++ hinic3_put_format_dev_flavor(ds, iter, HWPT_HWTYPE_VF_STR); ++ } ++ } ++ return; ++} ++ ++void ++hinic3_vf_flavor_show(struct unixctl_conn *conn, int argc HINIC3_UNUSED, ++ const char *argv[] HINIC3_UNUSED, void *aux) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ if (hinic3_device_mode_get() == DPU_MODE && hinic3_get_port_list_init() == false) { ++ ret = hinic3_dpu_vf_flavor_add(); ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR "hinic3_dpu_vf_flavor_add err\n"); ++ return; ++ } ++ hinic3_set_port_list_init(true); ++ } ++ ++ hinic3_function_flavor_show(&ds); ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} ++ ++static int ++hinic3_get_port_stats(struct port_stats *vf_stats, struct port_stats *pf_stats, bool nic_type) ++{ ++ struct hinic3_dev_node *iter = NULL; ++ struct hinic3_dp_extend_info *dp_info = NULL; ++ struct hinic3_flow_agent_db *hw_offload = NULL; ++ struct dev_mgmt *dev_list = NULL; ++ ++ if (nic_type == SMART_NIC_MODE) { ++ dev_list = hinic3_updata_netdev_hwpt_flavor(); ++ } else { ++ dev_list = get_netdev_hwpt_flavor(); ++ } ++ ++ if (dev_list == NULL) ++ return -1; ++ ++ dp_info = hinic3_get_offload_extend_info(); ++ if ((dp_info == NULL) || (dp_info->hw_offload == NULL)) ++ return -1; ++ ++ if (hinic3_list_is_empty(&dev_list->vf_list) == false) { ++ LIST_FOR_EACH(iter, node, &dev_list->vf_list) { ++ vf_stats->total_num++; ++ if (iter->phy_dev.refcnt == HWPT_FLAVOR_REFCNT_USED) { ++ vf_stats->used_num++; ++ } else if (iter->phy_dev.refcnt == HWPT_FLAVOR_REFCNT_INVALID) { ++ vf_stats->invalid_num++; ++ } else if (iter->phy_dev.refcnt == HWPT_FLAVOR_REFCNT_UNUSED) { ++ vf_stats->unused_num++; ++ } ++ } ++ } ++ if (hinic3_list_is_empty(&dev_list->pf_list) == false) { ++ LIST_FOR_EACH(iter, node, &dev_list->pf_list) { ++ pf_stats->total_num++; ++ if (iter->phy_dev.refcnt == HWPT_FLAVOR_REFCNT_USED) { ++ pf_stats->used_num++; ++ } else if (iter->phy_dev.refcnt == HWPT_FLAVOR_REFCNT_INVALID) { ++ pf_stats->invalid_num++; ++ } else if (iter->phy_dev.refcnt == HWPT_FLAVOR_REFCNT_UNUSED) { ++ pf_stats->unused_num++; ++ } ++ } ++ } ++ ++ hw_offload = dp_info->hw_offload; ++ vf_stats->virtio_total_num = hw_offload->queue_num.total_count; ++ vf_stats->virtio_used_num = hw_offload->queue_num.used_now; ++ pf_stats->virtio_total_num = hw_offload->queue_num.total_count; ++ pf_stats->virtio_used_num = hw_offload->queue_num.used_now; ++ ++ return 0; ++} ++ ++static void ++hinic3_vf_stats_show(struct unixctl_conn *conn, int argc HINIC3_UNUSED, ++ const char *argv[] HINIC3_UNUSED, void *aux) ++{ ++ int ret = 0; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct port_stats vf_stats = {0}; ++ struct port_stats pf_stats = {0}; ++ bool nic_type = hinic3_device_mode_get(); ++ ++ ret = hinic3_get_port_stats(&vf_stats, &pf_stats, nic_type); ++ if (ret != 0) ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Failed to obtain the port statistics.\n"); ++ ++ hinic3_port_virtio_queue_show(&ds, &vf_stats, &pf_stats); ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} ++ ++int ++hinic3_get_ifindex_id_by_name(const char **argv, uint16_t *dpdk_index_id) ++{ ++ char netdev_name[HINIC3_NETDEV_NAME_MAX_LENGTH]; ++ int ret; ++ ++ ret = hinic3_get_netdev_name(argv[1], netdev_name); ++ if (ret != 0) ++ return -1; ++ ++ ret = rte_eth_dev_get_port_by_name(netdev_name, dpdk_index_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "hwoff/%s failed, get port id error!\n", "show-port-qos"); ++ return -1; ++ } ++ return 0; ++} ++ ++void ++hinic3_qos_speed_print(struct unixctl_conn *conn, const struct vm_ports_info *start, ++ const struct vm_ports_info *end) ++{ ++ long long int time_exec = end->time_moment - start->time_moment; ++ if (time_exec <= 0) { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_TIME_EXEC_ERR_STR); ++ return; ++ } ++ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ float rx_bps = end->rx_bytes > start->rx_bytes ? ++ (((float)(end->rx_bytes - start->rx_bytes)) * BYTE_TO_BIT / time_exec) : 0; ++ uint64_t rx_pps = end->rx_pkts > start->rx_pkts ? ++ ((end->rx_pkts - start->rx_pkts) * SEC_TO_MSEC_BASE)/ time_exec : 0; ++ float tx_bps = end->tx_bytes > start->tx_bytes ? ++ (((float)(end->tx_bytes - start->tx_bytes)) * BYTE_TO_BIT / time_exec) : 0; ++ uint64_t tx_pps = end->tx_pkts > start->tx_pkts ? ++ ((end->tx_pkts - start->tx_pkts) * SEC_TO_MSEC_BASE) / time_exec : 0; ++ ++ hinic3_ds_put_format(&ds, " rx-bytes(kbit/s): %.2f \n", rx_bps); ++ hinic3_ds_put_format(&ds, " rx-pkts(p/s): %lu \n\n", rx_pps); ++ hinic3_ds_put_format(&ds, " tx-bytes(kbit/s): %.2f\n", tx_bps); ++ hinic3_ds_put_format(&ds, " tx-pkts(p/s): %lu\n", tx_pps); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ ++ return; ++} ++ ++void ++unixctl_vf_dfx_init(void) ++{ ++ hinic3_command_register("hwoff/show-function-flavor", "", 0, 0, hinic3_vf_flavor_show, NULL); ++ hinic3_command_register("hwoff/show-function-stats", "", 0, 0, hinic3_vf_stats_show, NULL); ++ hinic3_command_register("hwoff/dump-qos-loss", "INTEGER<1-1023>", 1, 1, hinic3_multi_qos_dump_loss, NULL); ++ hinic3_command_register("hwoff/show-qos-speed", "INTEGER<1-1023>", 1, 1, hinic3_multi_qos_speed_show, NULL); ++ hinic3_command_register("hwoff/show-port-qos", "", 1, 1, hinic3_multi_port_qos_dump_show, NULL); ++ hinic3_command_register("hwoff/dump-qos", "INTEGER<1-1023>", 0, 1, hinic3_multi_qos_dump_show, NULL); ++ hinic3_command_register("hwoff/dump-port-qos-loss", "", 1, 1, hinic3_multi_port_qos_dump_loss, NULL); ++ hinic3_command_register("hwoff/show-meter", "[ ]", 0, 1, hinic3_multi_meter_show, NULL); ++ hinic3_command_register("hwoff/show-policy", "[ ]", 0, 1, hinic3_multi_policy_show, NULL); ++ hinic3_command_register("hwoff/show-profile", "[ ]", 0, 1, hinic3_multi_profile_show, NULL); ++ hinic3_command_register("hwoff/show-port-qos-speed", "", 1, 1, ++ hinic3_multi_port_qos_speed_show, NULL); ++ hinic3_command_register("hwoff/dump-net-qos", "", 0, 0, hinic3_multi_net_qos_dump_show, NULL); ++ hinic3_command_register("hwoff/dump-net-qos-loss", "", 0, 0, hinic3_multi_net_qos_dump_loss, NULL); ++ hinic3_command_register("hwoff/dump-qos-stats", "INTEGER<1-1023>", 1, 1, hinic3_multi_qos_stats_show, NULL); ++ hinic3_command_register("hwoff/dump-port-qos-stats", "", 1, 1, hinic3_multi_port_qos_stats_show, NULL); ++ hinic3_command_register("hwoff/dump-net-qos-stats", "", 0, 0, hinic3_multi_net_qos_stats_show, NULL); ++ ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h +new file mode 100644 +index 0000000..cb0f106 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h +@@ -0,0 +1,76 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VF_DFX_H ++#define HINIC3_VF_DFX_H ++ ++#include "hinic3_util.h" ++#include "hinic3_command.h" ++ ++#define HWPT_ETH_DEVICE_FORMAT_PATH "/sys/bus/pci/devices/%04x:%02x:%02x.%u/net" ++ ++#define LCORE_INDEX_INVALID (-1) ++ ++#define PROFILE_UNIT_NUM 2 ++#define QOS_UNIT_NUM 4 ++#define QOS_MAX_NUM 512 ++#define BW_QOS_UNIT "kbps" ++#define PPS_QOS_UNIT "pps" ++ ++#define BW_QOS_MODE "byte" ++#define PPS_QOS_MODE "packet" ++ ++#define BYTE_TO_BIT 8 ++#define SAMPLING_INTERVAL 500000 ++#define MAX_BUCKET_ID 512 ++#define DEC_BASE_NUM 10 ++ ++#define FUNCTION_ID_TO_VPORT_ID 4096 ++ ++struct vm_ports_info { ++ uint64_t rx_pkts; ++ uint64_t tx_pkts; ++ uint64_t rx_bytes; ++ uint64_t tx_bytes; ++ long long int time_moment; ++}; ++ ++struct port_status { ++ uint8_t refcnt; ++ const char *str; ++}; ++ ++struct port_stats { ++ uint32_t total_num; ++ uint32_t unused_num; ++ uint32_t used_num; ++ uint32_t invalid_num; ++ uint32_t virtio_total_num; ++ uint32_t virtio_used_num; ++}; ++ ++void unixctl_vf_dfx_init(void); ++void hinic3_vf_flavor_show(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, ++ void *aux HINIC3_UNUSED); ++void hinic3_multi_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_qos_speed_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_port_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_port_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_meter_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_policy_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_profile_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_port_qos_speed_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_net_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_net_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_net_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_multi_port_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++int hinic3_get_ifindex_id_by_name(const char **argv, uint16_t *dpdk_index_id); ++void hinic3_qos_speed_print(struct unixctl_conn *conn, const struct vm_ports_info *start, ++ const struct vm_ports_info *end); ++char **hinic3_vm_qos_unit_get(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c +new file mode 100644 +index 0000000..fed7659 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c +@@ -0,0 +1,1121 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_vf_dfx.h" ++#include "hinic3_ds.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_drv.h" ++#include "hiovs_api.h" ++#include "hinic3_command.h" ++#include "hinic3_mtr.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_mtr_profile.h" ++#include "hinic3_mtr_policy.h" ++#include "hinic3_offload_flow_port.h" ++#include "rte_ethdev.h" ++ ++#define MULTI_QOS_MASK_TX (1ULL << 0) ++#define MULTI_QOS_MASK_RX (1ULL << 1) ++#define MULTI_QOS_ARG_NUMS 2 ++#define MULTI_PPS_QOS_SPEACE_NUMS 6 ++#define MULTI_KBPS_QOS_SPEACE_NUMS 5 ++ ++static char *g_profile_unit[PROFILE_UNIT_NUM] = { ++ BW_QOS_UNIT, ++ PPS_QOS_UNIT, ++}; ++ ++static char *g_profile_mode[PROFILE_UNIT_NUM] = { ++ BW_QOS_MODE, ++ PPS_QOS_MODE, ++}; ++ ++static void ++hinic3_multi_qos_show_loss(struct ds *ds, struct hovs_hqos_stats_batch_all hovs_stats, uint16_t stats_mask) ++{ ++ if ((stats_mask & MULTI_QOS_MASK_TX) == MULTI_QOS_MASK_TX) { ++ hinic3_ds_put_format(ds, "%4s%-30s: %llu\n", HINIC3_UI_INDENT_SPACE, "tx-qos-drop-num", ++ hovs_stats.tx_drop_pkts); ++ hinic3_ds_put_format(ds, "%4s%-30s: %llu\n", HINIC3_UI_INDENT_SPACE, "tx-qos-drop-byte", ++ hovs_stats.tx_drop_bytes); ++ } else { ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "tx-qos-drop-num"); ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "tx-qos-drop-byte"); ++ } ++ if ((stats_mask & MULTI_QOS_MASK_RX) == MULTI_QOS_MASK_RX) { ++ hinic3_ds_put_format(ds, "%4s%-30s: %llu\n", HINIC3_UI_INDENT_SPACE, "rx-qos-drop-num", ++ hovs_stats.rx_drop_pkts); ++ hinic3_ds_put_format(ds, "%4s%-30s: %llu\n", HINIC3_UI_INDENT_SPACE, "rx-qos-drop-byte", ++ hovs_stats.rx_drop_bytes); ++ } else { ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "rx-qos-drop-num"); ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "rx-qos-drop-byte"); ++ } ++} ++ ++static struct hinic3_vf_dev * ++hinic3_multi_qos_get_dev(const char **argv, struct ds *ds) ++{ ++ int ret; ++ uint16_t dpdk_index_id = 0; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ ++ ret = hinic3_get_ifindex_id_by_name(argv, &dpdk_index_id); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, "%s%s, %s", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_ERROR_WRONG_PARAMETER, ++ HINIC3_UI_INVALID_PORT_NAME_STR); ++ return NULL; ++ } ++ ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(dpdk_index_id); ++ if (vf_dev == NULL) { ++ hinic3_ds_put_format(ds, "%sInternal failure, fail to get current device data.\n", ++ HINIC3_UI_LEADING_SIGN_FAILURE); ++ return NULL; ++ } ++ ++ return vf_dev; ++} ++ ++static int ++hinic3_port_dump_loss_get(struct hinic3_vf_dev *vf_dev, struct ds *ds, const char *argv) ++{ ++ uint16_t stats_mask = 0; ++ uint16_t vport_id = vf_dev->vport_id; ++ struct hovs_hqos_stats_batch_all stats = {0}; ++ ++ if (hinic3_hqos_statistics_get_all_batch(QOS_TYPE_FUNC_LIMIT, &vport_id, &stats, 1)) { ++ HINIC3_LOG(ERR, QOS, "hinic3 dump qos stats failed. port id is %u", vport_id); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, " vf name[%s] dump loss:\n", argv); ++ if (vf_dev->mtr[BW_TX_TYPE].is_used == true || vf_dev->mtr[PPS_TX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_TX; ++ if (vf_dev->mtr[BW_RX_TYPE].is_used == true || vf_dev->mtr[PPS_RX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_RX; ++ hinic3_multi_qos_show_loss(ds, stats, stats_mask); ++ return 0; ++} ++ ++void ++hinic3_multi_port_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ if (argc != MULTI_QOS_ARG_NUMS) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ vf_dev = hinic3_multi_qos_get_dev(argv, &ds); ++ if (vf_dev == NULL) ++ goto err; ++ ++ if (vf_dev->qos_type == VF_NONE_QOS_FLAG) { ++ hinic3_ds_put_format(&ds, "%sPort has no qos.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ goto err; ++ } ++ ++ ret = hinic3_port_dump_loss_get(vf_dev, &ds, argv[1]); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Dump hardware stats error.\n"); ++ goto err; ++ } ++ ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++static int ++hinic3_get_qos_one_port_info(uint16_t vport_id, struct vm_ports_info *ports_info) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ struct hovs_port_stats stats = {0}; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_statistics_get, HINIC3_DRV_FUNC_NO_PTR); ++ ++ ret = ops->hovs_port_statistics_get(vport_id, &stats); ++ if (ret != 0) ++ return -1; ++ ++ ports_info->rx_pkts = stats.rx_pkts; ++ ports_info->tx_pkts = stats.tx_pkts; ++ ports_info->rx_bytes = stats.rx_bytes; ++ ports_info->tx_bytes = stats.tx_bytes; ++ ++ ports_info->time_moment = hinic3_time_msec(); ++ if (ports_info->time_moment < 0) ++ return -1; ++ return 0; ++} ++ ++void ++hinic3_multi_port_qos_speed_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct vm_ports_info first_sample_value = {0}; ++ struct vm_ports_info second_sample_value = {0}; ++ ++ if (argc != MULTI_QOS_ARG_NUMS) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ vf_dev = hinic3_multi_qos_get_dev(argv, &ds); ++ if (vf_dev == NULL) ++ goto err; ++ ++ if (vf_dev->group_qos_id == 0 && vf_dev->qos_type == VF_NONE_QOS_FLAG) { ++ hinic3_ds_put_format(&ds, "%sPort has no qos.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ goto err; ++ } ++ ++ ret = hinic3_get_qos_one_port_info(vf_dev->vport_id, &first_sample_value); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FIRST_GET_PORT_INFO_ERR_STR); ++ goto err; ++ } ++ ++ usleep(SAMPLING_INTERVAL); ++ ret = hinic3_get_qos_one_port_info(vf_dev->vport_id, &second_sample_value); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_SECOND_GET_PORT_INFO_ERR_STR); ++ goto err; ++ } ++ ++ hinic3_qos_speed_print(conn, &first_sample_value, &second_sample_value); ++ *(int *)aux = 0; ++ hinic3_ds_destroy(&ds); ++ return; ++err: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = -1; ++ hinic3_ds_destroy(&ds); ++} ++ ++static int ++hinic3_get_multi_qos_ports_info(struct hinic3_list *port_list, struct vm_ports_info *ports_info) ++{ ++ struct hinic3_group_port_info *iter = NULL; ++ struct hinic3_drv_ops *ops = NULL; ++ int ret; ++ struct hovs_port_stats stats = {0}; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_statistics_get, HINIC3_DRV_FUNC_NO_PTR); ++ ++ LIST_FOR_EACH(iter, node, port_list) { ++ ret = ops->hovs_port_statistics_get(iter->vport_id, &stats); ++ if (ret != 0) ++ return -1; ++ ports_info->rx_pkts += stats.rx_pkts; ++ ports_info->tx_pkts += stats.tx_pkts; ++ ports_info->rx_bytes += stats.rx_bytes; ++ ports_info->tx_bytes += stats.tx_bytes; ++ memset(&stats, 0, sizeof(struct hovs_port_stats)); ++ } ++ ports_info->time_moment = hinic3_time_msec(); ++ if (ports_info->time_moment < 0) ++ return -1; ++ return 0; ++} ++ ++void ++hinic3_multi_qos_speed_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ uint16_t group_id; ++ char *endPtr = NULL; ++ struct vm_ports_info first_sample_value = {0}; ++ struct vm_ports_info second_sample_value = {0}; ++ struct hinic3_group_info *group_info = NULL; ++ ++ if (argc != MULTI_QOS_ARG_NUMS) { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ *(int *)aux = -1; ++ return; ++ } ++ ++ group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); ++ *(int *)aux = -1; ++ return; ++ } ++ hinic3_group_info_lock(group_id); ++ group_info = hinic3_group_info_get(group_id); ++ if (group_info->length == 0) { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR "The number of ports bound to the group is 0.\n"); ++ goto err; ++ } ++ ++ ret = hinic3_get_multi_qos_ports_info(&group_info->node, &first_sample_value); ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FIRST_GET_PORT_INFO_ERR_STR); ++ goto err; ++ } ++ ++ usleep(SAMPLING_INTERVAL); ++ ret = hinic3_get_multi_qos_ports_info(&group_info->node, &second_sample_value); ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_SECOND_GET_PORT_INFO_ERR_STR); ++ goto err; ++ } ++ ++ hinic3_qos_speed_print(conn, &first_sample_value, &second_sample_value); ++ *(int *)aux = 0; ++ hinic3_group_info_unlock(group_id); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_group_info_unlock(group_id); ++} ++ ++static int ++hinic3_show_multi_port_qos(struct ds *ds, enum hinic3_qos_tablehead index, ++ uint32_t meter_id, uint16_t vport_id) ++{ ++ int ret; ++ struct hinic3_meter_node *meter = NULL; ++ struct qos_single_value *profile = NULL; ++ struct qos_single_value qos_value = {0}; ++ group_qos_type_key *qos_key = hinic3_get_qos_type_key(); ++ char **vm_qos_unit = hinic3_vm_qos_unit_get(); ++ enum hinic3_meter_qos_direction dir = hinic3_qos_get_dir(index); ++ ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos show: meter id is not find.\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Meter id is not find. meater id is %u\n", meter_id); ++ return -1; ++ } ++ profile = &meter->profile->profile; ++ ++ ret = hinic3_port_qos_limit_get(vport_id, dir, profile->packet_mode, &qos_value); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos show: get qos value failed.\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Get qos value failed.\n"); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, "%4smeter id: %u\n", HINIC3_UI_INDENT_SPACE, meter_id); ++ hinic3_ds_put_format(ds, "%4s%s(%s):\n", HINIC3_UI_INDENT_SPACE, qos_key->qos_type_key[index], vm_qos_unit[index]); ++ hinic3_ds_put_format(ds, "%6sPIR: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, profile->max_rate, ++ qos_value.max_rate); ++ hinic3_ds_put_format(ds, "%6sPBS: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, profile->max_burst, ++ qos_value.max_burst); ++ hinic3_ds_put_format(ds, "%6sCIR: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, profile->min_rate, ++ qos_value.min_rate); ++ hinic3_ds_put_format(ds, "%6sCBS: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, profile->min_burst, ++ qos_value.min_burst); ++ return 0; ++} ++ ++void ++hinic3_multi_port_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret = 0; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ if (argc != MULTI_QOS_ARG_NUMS) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ vf_dev = hinic3_multi_qos_get_dev(argv, &ds); ++ if (vf_dev == NULL) ++ goto err; ++ ++ if (vf_dev->qos_type == VF_NONE_QOS_FLAG) { ++ hinic3_ds_put_format(&ds, "%sPort has no qos.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ goto err; ++ } ++ ++ hinic3_ds_put_format(&ds, " vf name[%s] qos info:\n", argv[1]); ++ for (int i = 0; i < QOS_TABLEHEAD_NUM; i++) { ++ if (vf_dev->mtr[i].is_used == true) ++ ret |= hinic3_show_multi_port_qos(&ds, i, vf_dev->mtr[i].mtr_id, vf_dev->vport_id); ++ } ++ ++ if (ret != 0) ++ goto err; ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++static int ++hinic3_show_multi_qos(struct ds *ds, enum hinic3_qos_tablehead index, uint16_t group_id, ++ struct qos_single_value *profile) ++{ ++ int ret; ++ struct qos_single_value qos_value = {0}; ++ group_qos_type_key *qos_key = hinic3_get_qos_type_key(); ++ char **vm_qos_unit = hinic3_vm_qos_unit_get(); ++ enum hinic3_meter_qos_direction dir = hinic3_qos_get_dir(index); ++ ++ ret = hinic3_vm_qos_limit_get(group_id, dir, profile->packet_mode, &qos_value); ++ if (ret != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Failed to get qos info for group_id %u.\n", group_id); ++ return ret; ++ } ++ ++ if (profile->is_RFC2697) { ++ hinic3_ds_put_format(ds, "%4s%s(%s):\n", HINIC3_UI_INDENT_SPACE, qos_key->qos_type_key[index], ++ vm_qos_unit[index]); ++ hinic3_ds_put_format(ds, "%6sEBS: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, ++ profile->max_burst, qos_value.max_burst); ++ hinic3_ds_put_format(ds, "%6sCIR: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, ++ profile->min_rate, qos_value.min_rate); ++ hinic3_ds_put_format(ds, "%6sCBS: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, ++ profile->min_burst, qos_value.min_burst); ++ } else { ++ hinic3_ds_put_format(ds, "%4s%s(%s):\n", HINIC3_UI_INDENT_SPACE, qos_key->qos_type_key[index], ++ vm_qos_unit[index]); ++ hinic3_ds_put_format(ds, "%6sPIR: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, ++ profile->max_rate, qos_value.max_rate); ++ hinic3_ds_put_format(ds, "%6sPBS: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, ++ profile->max_burst, qos_value.max_burst); ++ hinic3_ds_put_format(ds, "%6sCIR: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, ++ profile->min_rate, qos_value.min_rate); ++ hinic3_ds_put_format(ds, "%6sCBS: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, ++ profile->min_burst, qos_value.min_burst); ++ } ++ return 0; ++} ++ ++static int ++hinic3_multi_qos_dump_show_vport(struct ds *ds, struct hinic3_group_info *group_info) ++{ ++ int i = 0; ++ uint16_t port_id; ++ char pci_id[PATH_MAX] = {0}; ++ struct hinic3_group_port_info *iter = NULL; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ ++ hinic3_ds_put_format(ds, "%4spci-id:\n", HINIC3_UI_INDENT_SPACE); ++ LIST_FOR_EACH(iter, node, &group_info->node) { ++ if (hinic3_get_port_id_by_ifindex(iter->vport_id, &port_id) != 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Get port_id failed, vport id = %u.\n", ++ iter->vport_id); ++ return -1; ++ } ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(port_id); ++ if (vf_dev == NULL) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Get vf_dev failed, vport id = %u, port id = %u\n", ++ iter->vport_id, port_id); ++ return -1; ++ } ++ int ret = snprintf(pci_id, sizeof(pci_id), "pci-id[%d]:", i++); ++ if (ret <= 0) ++ return -1; ++ if (hinic3_get_port_conf_type() == PORT_CONF_FUNC) { ++ int function_id = hinic3_get_function_id_by_pci(&vf_dev->pci_addr); ++ hinic3_ds_put_format(ds, "%6s%s function id %d\n", HINIC3_UI_INDENT_SPACE, pci_id, function_id); ++ } else { ++ hinic3_ds_put_format(ds, "%6s%s %04x:%02x:%02x.%x\n", HINIC3_UI_INDENT_SPACE, pci_id, ++ vf_dev->pci_addr.domain, vf_dev->pci_addr.bus, vf_dev->pci_addr.devid, vf_dev->pci_addr.function); ++ } ++ memset(pci_id, 0, sizeof(pci_id)); ++ } ++ return 0; ++} ++ ++static int ++hinic3_multi_qos_dump_show_one(struct ds *ds, struct hinic3_group_info *group_info) ++{ ++ int ret; ++ struct hinic3_meter_node *meter = NULL; ++ struct qos_single_value *profile = NULL; ++ ++ hinic3_ds_put_format(ds, " group id[%u] qos info:\n", group_info->group_id); ++ for (int i = 0; i < QOS_TABLEHEAD_NUM; i++) { ++ if (group_info->meter[i].is_used == true) { ++ meter = hinic3_meter_find(group_info->meter[i].meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: Meter id is not find, meter id is %u.\n", ++ group_info->meter[i].meter_id); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Meter id is not find. meter id is %u\n", ++ group_info->meter[i].meter_id); ++ return -1; ++ } ++ profile = &meter->profile->profile; ++ ret = hinic3_show_multi_qos(ds, i, group_info->group_id, profile); ++ if (ret != 0) ++ return -1; ++ hinic3_ds_put_format(ds, "%4s%s %u\n", HINIC3_UI_INDENT_SPACE, "meter id:", ++ group_info->meter[i].meter_id); ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ } ++ ++ hinic3_ds_put_format(ds, "%4s%s %u\n", HINIC3_UI_INDENT_SPACE, "port nums:", group_info->length); ++ ret = hinic3_multi_qos_dump_show_vport(ds, group_info); ++ return ret; ++} ++ ++static int ++hinic3_multi_qos_dump_show_all(struct ds *ds) ++{ ++ int ret; ++ int group_num = 0; ++ struct hinic3_group_info *group_info = NULL; ++ ++ for (int group_id = 0; group_id < MAX_QOS_ID_NUM + 1; group_id++) { ++ hinic3_group_info_lock(group_id); ++ group_info = hinic3_group_info_get(group_id); ++ if (group_info->length != 0) { ++ ret = hinic3_multi_qos_dump_show_one(ds, group_info); ++ if (ret != 0) { ++ hinic3_group_info_unlock(group_id); ++ return -1; ++ } ++ group_num++; ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ hinic3_group_info_unlock(group_id); ++ } ++ hinic3_ds_put_format(ds, " group nums: %d\n", group_num); ++ return 0; ++} ++ ++void ++hinic3_multi_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ uint16_t group_id; ++ char *endPtr = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_group_info *group_info = NULL; ++ ++ if (argc == 1) { ++ ret = hinic3_multi_qos_dump_show_all(&ds); ++ } else if (argc == MULTI_QOS_ARG_NUMS) { ++ group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); ++ ret = -1; ++ } else { ++ hinic3_group_info_lock(group_id); ++ group_info = hinic3_group_info_get(group_id); ++ if (group_info->length == 0) { ++ hinic3_group_info_unlock(group_id); ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "The number of ports bound to the group is 0.\n"); ++ ret = -1; ++ } else { ++ ret = hinic3_multi_qos_dump_show_one(&ds, group_info); ++ } ++ hinic3_group_info_unlock(group_id); ++ } ++ } else { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ ret = -1; ++ } ++ ++ if (ret != 0) { ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ } else { ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ } ++ hinic3_ds_destroy(&ds); ++} ++ ++static void ++hinic3_multi_meter_show_one(struct ds *ds, struct hinic3_meter_node *meter) ++{ ++ hinic3_ds_put_format(ds, " meter id: %u\n", meter->meter_id); ++ switch (meter->type) { ++ case QOS_TYPE_MAX: ++ hinic3_ds_put_format(ds, " %-20s %s\n", "type:", "NONE"); ++ break; ++ case QOS_TYPE_VM_LIMIT: ++ hinic3_ds_put_format(ds, " %-20s %s\n", "type:", "GROUP"); ++ hinic3_ds_put_format(ds, " %-20s %u\n", "group id:", meter->group_id); ++ break; ++ case QOS_TYPE_FUNC_LIMIT: ++ hinic3_ds_put_format(ds, " %-20s %s\n", "type:", "PORT"); ++ struct hinic3_vf_dev *vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(meter->port_id); ++ if (vf_dev == NULL) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Get vf_dev failed, port id = %u\n", ++ meter->port_id); ++ return; ++ } ++ if (hinic3_get_port_conf_type() == PORT_CONF_FUNC) { ++ int function_id = hinic3_get_function_id_by_pci(&vf_dev->pci_addr); ++ hinic3_ds_put_format(ds, " %-20s %d\n", "func id:", function_id); ++ } else { ++ hinic3_ds_put_format(ds, " %-20s %04x:%02x:%02x.%x\n", "pci addr:", vf_dev->pci_addr.domain, ++ vf_dev->pci_addr.bus, vf_dev->pci_addr.devid, vf_dev->pci_addr.function); ++ } ++ break; ++ case QOS_TYPE_NET_LIMIT: ++ hinic3_ds_put_format(ds, " %-20s %s\n", "type:", "NET"); ++ default: ++ break; ++ } ++ hinic3_ds_put_format(ds, " %-20s %u\n", "policy-id:", meter->policy->policy_id); ++ hinic3_ds_put_format(ds, " %-20s %u\n", "profile-id:", meter->profile->profile_id); ++ switch (meter->dir) { ++ case HINIC3_TX_METER_QOS: ++ hinic3_ds_put_format(ds, " %-20s %s\n", "direction:", "TX"); ++ break; ++ case HINIC3_RX_METER_QOS: ++ hinic3_ds_put_format(ds, " %-20s %s\n", "direction:", "RX"); ++ break; ++ case HINIC3_NODIR_METER_QOS: ++ hinic3_ds_put_format(ds, " %-20s %s\n", "direction:", "NONE"); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void ++hinic3_multi_meter_show_all(struct ds *ds) ++{ ++ struct hinic3_meter_node *iter = NULL; ++ struct hinic3_meter_list *meter_list = hinic3_meter_list_get(); ++ if (meter_list->length == 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_INFO "No meter.\n"); ++ return; ++ } ++ hinic3_meter_list_lock(); ++ LIST_FOR_EACH(iter, node, &meter_list->node) { ++ hinic3_multi_meter_show_one(ds, iter); ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ hinic3_ds_put_format(ds, " meter-num: %u\n", meter_list->length); ++ hinic3_meter_list_unlock(); ++} ++ ++void ++hinic3_multi_meter_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret = 0; ++ uint32_t meter_id; ++ char *endPtr = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_meter_node *meter = NULL; ++ ++ if (argc == 1) { ++ hinic3_multi_meter_show_all(&ds); ++ } else if (argc == MULTI_QOS_ARG_NUMS) { ++ meter_id = strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_METER_ID_STR); ++ ret = -1; ++ } else { ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_METER_ID_STR); ++ ret = -1; ++ } else { ++ hinic3_meter_list_lock(); ++ hinic3_multi_meter_show_one(&ds, meter); ++ hinic3_meter_list_unlock(); ++ } ++ } ++ } else { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ ret = -1; ++ } ++ *(int *)aux = ret; ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ } else { ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ } ++ hinic3_ds_destroy(&ds); ++} ++ ++static void ++hinic3_multi_policy_show_one(struct ds *ds, struct hinic3_mtr_policy_node *policy) ++{ ++ hinic3_ds_put_format(ds, " policy id: %u\n", policy->policy_id); ++ if (policy->has_next_meter == true) { ++ hinic3_ds_put_format(ds, " %-15s %u\n", "next meter id:", policy->next_meter_id); ++ } else { ++ hinic3_ds_put_format(ds, " %-15s NONE\n", "next meter id:"); ++ } ++} ++ ++static void ++hinic3_multi_policy_show_all(struct ds *ds) ++{ ++ struct hinic3_mtr_policy_node *iter = NULL; ++ struct hinic3_mtr_policy_list *policy_list = hinic3_policy_list_get(); ++ ++ if (policy_list->length == 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_INFO "No policy.\n"); ++ return; ++ } ++ hinic3_mtr_policy_list_lock(); ++ LIST_FOR_EACH(iter, node, &policy_list->node) { ++ hinic3_multi_policy_show_one(ds, iter); ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ hinic3_ds_put_format(ds, " policy-num: %u\n", policy_list->length); ++ hinic3_mtr_policy_list_unlock(); ++} ++ ++void ++hinic3_multi_policy_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret = 0; ++ uint32_t policy_id; ++ char *endPtr = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_mtr_policy_node *policy = NULL; ++ ++ if (argc == 1) { ++ hinic3_multi_policy_show_all(&ds); ++ } else if (argc == MULTI_QOS_ARG_NUMS) { ++ policy_id = strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_POLICY_ID_STR); ++ ret = -1; ++ goto end; ++ } ++ policy = hinic3_mtr_policy_find(policy_id); ++ if (policy == NULL) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_POLICY_ID_STR); ++ ret = -1; ++ } else { ++ hinic3_mtr_policy_list_lock(); ++ hinic3_multi_policy_show_one(&ds, policy); ++ hinic3_mtr_policy_list_unlock(); ++ } ++ } else { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ ret = -1; ++ } ++end: ++ *(int *)aux = ret; ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ } else { ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ } ++ hinic3_ds_destroy(&ds); ++} ++ ++static void ++hinic3_multi_profile_show_one(struct ds *ds, struct hinic3_mtr_profile_node *profile) ++{ ++ int index; ++ struct qos_single_value *qos_value = &profile->profile; ++ int value_ui_space; ++ ++ index = (qos_value->packet_mode == QOS_BW_TYPE) ? 0 : 1; ++ ++ if (index == 0) { ++ value_ui_space = MULTI_KBPS_QOS_SPEACE_NUMS; ++ } else { ++ value_ui_space = MULTI_PPS_QOS_SPEACE_NUMS; ++ } ++ ++ hinic3_ds_put_format(ds, "%2sprofile id: %u\n", HINIC3_UI_INDENT_SPACE, profile->profile_id); ++ ++ if (qos_value->is_RFC2697) { ++ hinic3_ds_put_format(ds, "%4stype:%10ssrtcm_rfc2697\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4sEBS(%s):%*s%u\n", HINIC3_UI_INDENT_SPACE, ++ g_profile_unit[index], value_ui_space, HINIC3_UI_INDENT_SPACE, qos_value->max_burst); ++ hinic3_ds_put_format(ds, "%4sCIR(%s):%*s%u\n", HINIC3_UI_INDENT_SPACE, ++ g_profile_unit[index], value_ui_space, HINIC3_UI_INDENT_SPACE, qos_value->min_rate); ++ hinic3_ds_put_format(ds, "%4sCBS(%s):%*s%u\n", HINIC3_UI_INDENT_SPACE, ++ g_profile_unit[index], value_ui_space, HINIC3_UI_INDENT_SPACE, qos_value->min_burst); ++ hinic3_ds_put_format(ds, "%4smode:%10s%s\n", HINIC3_UI_INDENT_SPACE, ++ value_ui_space, HINIC3_UI_INDENT_SPACE, g_profile_mode[index]); ++ } else { ++ hinic3_ds_put_format(ds, "%4stype:%10strtcm_rfc2698\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(ds, "%4sPIR(%s):%*s%u\n", HINIC3_UI_INDENT_SPACE, ++ g_profile_unit[index], value_ui_space, HINIC3_UI_INDENT_SPACE, qos_value->max_rate); ++ hinic3_ds_put_format(ds, "%4sPBS(%s):%*s%u\n", HINIC3_UI_INDENT_SPACE, ++ g_profile_unit[index], value_ui_space, HINIC3_UI_INDENT_SPACE, qos_value->max_burst); ++ hinic3_ds_put_format(ds, "%4sCIR(%s):%*s%u\n", HINIC3_UI_INDENT_SPACE, ++ g_profile_unit[index], value_ui_space, HINIC3_UI_INDENT_SPACE, qos_value->min_rate); ++ hinic3_ds_put_format(ds, "%4sCBS(%s):%*s%u\n", HINIC3_UI_INDENT_SPACE, ++ g_profile_unit[index], value_ui_space, HINIC3_UI_INDENT_SPACE, qos_value->min_burst); ++ hinic3_ds_put_format(ds, "%4smode:%10s%s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_INDENT_SPACE, g_profile_mode[index]); ++ } ++} ++ ++static void ++hinic3_multi_profile_show_all(struct ds *ds) ++{ ++ struct hinic3_mtr_profile_node *iter = NULL; ++ struct hinic3_mtr_profile_list *profile_list = hinic3_profile_list_get(); ++ ++ if (profile_list->length == 0) { ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_INFO "No profile.\n"); ++ return; ++ } ++ hinic3_mtr_profile_list_lock(); ++ LIST_FOR_EACH(iter, node, &profile_list->node) { ++ hinic3_multi_profile_show_one(ds, iter); ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ hinic3_ds_put_format(ds, "%2sprofile-num: %u\n", HINIC3_UI_INDENT_SPACE, profile_list->length); ++ hinic3_mtr_profile_list_unlock(); ++} ++ ++void ++hinic3_multi_profile_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret = 0; ++ uint32_t porfile_id; ++ char *endPtr = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_mtr_profile_node *profile = NULL; ++ ++ if (argc == 1) { ++ hinic3_multi_profile_show_all(&ds); ++ } else if (argc == MULTI_QOS_ARG_NUMS) { ++ porfile_id = strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_PROFILE_ID_STR); ++ ret = -1; ++ goto end; ++ } ++ profile = hinic3_mtr_profile_find(porfile_id); ++ if (profile == NULL) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_PROFILE_ID_STR); ++ ret = -1; ++ } else { ++ hinic3_mtr_policy_list_lock(); ++ hinic3_multi_profile_show_one(&ds, profile); ++ hinic3_mtr_policy_list_unlock(); ++ } ++ } else { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ ret = -1; ++ } ++ ++end: ++ *(int *)aux = ret; ++ if (ret != 0) { ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ } else { ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ } ++ hinic3_ds_destroy(&ds); ++} ++ ++void ++hinic3_multi_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ uint16_t group_id; ++ char *endPtr = NULL; ++ uint16_t stats_mask = 0; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_group_info *group_info = NULL; ++ struct hovs_hqos_stats_batch_all hovs_stats = {0}; ++ ++ if (argc != MULTI_QOS_ARG_NUMS) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); ++ goto err; ++ } ++ ++ group_info = hinic3_group_info_get(group_id); ++ if (group_info->length == 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Group has no port.\n"); ++ goto err; ++ } ++ ++ if (hinic3_hqos_statistics_get_all_batch(QOS_TYPE_VM_LIMIT, &group_id, &hovs_stats, 1) != 0) ++ HINIC3_LOG(ERR, QOS, "Get qos statistics failed.\n"); ++ ++ if (group_info->meter[BW_TX_TYPE].is_used == true || group_info->meter[PPS_TX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_TX; ++ ++ if (group_info->meter[BW_RX_TYPE].is_used == true || group_info->meter[PPS_RX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_RX; ++ ++ hinic3_ds_put_format(&ds, "%2sgroup id[%u] dump loss:\n", HINIC3_UI_INDENT_SPACE, group_id); ++ hinic3_multi_qos_show_loss(&ds, hovs_stats, stats_mask); ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++static int ++hinic3_multi_net_qos_show_one(uint32_t meter_id, enum hinic3_qos_tablehead index, struct ds *ds) ++{ ++ int ret; ++ uint64_t max_rate; ++ uint64_t max_burst; ++ struct hinic3_meter_node *meter = NULL; ++ struct qos_single_value *profile = NULL; ++ group_qos_type_key *qos_key = hinic3_get_qos_type_key(); ++ char **vm_qos_unit = hinic3_vm_qos_unit_get(); ++ ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi net qos show: meter id is not find. meter id is %u.\n", meter_id); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Meter id is not find. meter id is %u.\n", meter_id); ++ return -1; ++ } ++ profile = &meter->profile->profile; ++ ++ ret = hinic3_net_qos_limit_get(0, meter->dir, profile->packet_mode, &max_rate, &max_burst); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi net qos show: get net qos value failed.\n"); ++ hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Get qos value failed.\n"); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%4s%s(%s):\n", HINIC3_UI_INDENT_SPACE, qos_key->qos_type_key[index], vm_qos_unit[index]); ++ hinic3_ds_put_format(ds, "%6sCIR: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, profile->min_rate, ++ max_rate); ++ hinic3_ds_put_format(ds, "%6sCBS: %" PRIu64 " (%" PRIu64 ")\n", HINIC3_UI_INDENT_SPACE, profile->min_burst, ++ max_burst); ++ return 0; ++} ++ ++void ++hinic3_multi_net_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_net_meter_info *net_meter = hinic3_net_meter_info_get(); ++ ++ if (argc != 1) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ hinic3_ds_put_format(&ds, "%2sNET QoS info:\n", HINIC3_UI_INDENT_SPACE); ++ for (int i = 0; i < QOS_TABLEHEAD_NUM; i++) { ++ if (net_meter[i].is_used == true) { ++ ret = hinic3_multi_net_qos_show_one(net_meter[i].meter_id, i, &ds); ++ if (ret != 0) { ++ goto err; ++ } ++ } ++ } ++ ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++void ++hinic3_multi_net_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ uint16_t host_id = 0; ++ uint16_t stats_mask = 0; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hovs_hqos_stats_batch_all hovs_stats = {0}; ++ struct hinic3_net_meter_info *net_meter = hinic3_net_meter_info_get(); ++ ++ if (argc != 1) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ if (hinic3_hqos_statistics_get_all_batch(QOS_TYPE_NET_LIMIT, &host_id, &hovs_stats, 1) != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Get stats failed.\n"); ++ goto err; ++ } ++ ++ if (net_meter[BW_TX_TYPE].is_used == true || net_meter[PPS_TX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_TX; ++ if (net_meter[BW_RX_TYPE].is_used == true || net_meter[PPS_RX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_RX; ++ ++ hinic3_ds_put_format(&ds, "%2snet qos loss:\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_multi_qos_show_loss(&ds, hovs_stats, stats_mask); ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++static void ++hinic3_multi_qos_show_stats(struct ds *ds, struct hovs_hqos_stats_batch_all hovs_stats, uint16_t stats_mask) ++{ ++ hinic3_ds_put_format(ds, "%2sGreen Color:\n", HINIC3_UI_INDENT_SPACE); ++ if ((stats_mask & MULTI_QOS_MASK_TX) == MULTI_QOS_MASK_TX) { ++ hinic3_ds_put_format(ds, "%4s%-30s: %u\n", HINIC3_UI_INDENT_SPACE, "tx-pkts-num", ++ hovs_stats.tx_pkts[RTE_COLOR_GREEN]); ++ hinic3_ds_put_format(ds, "%4s%-30s: %u\n", HINIC3_UI_INDENT_SPACE, "tx-byte-num", ++ hovs_stats.tx_bytes[RTE_COLOR_GREEN]); ++ } else { ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "tx-pkts-num"); ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "tx-byte-num"); ++ } ++ if ((stats_mask & MULTI_QOS_MASK_RX) == MULTI_QOS_MASK_RX) { ++ hinic3_ds_put_format(ds, "%4s%-30s: %u\n", HINIC3_UI_INDENT_SPACE, "rx-pkts-num", ++ hovs_stats.rx_pkts[RTE_COLOR_GREEN]); ++ hinic3_ds_put_format(ds, "%4s%-30s: %u\n", HINIC3_UI_INDENT_SPACE, "rx-byte-num", ++ hovs_stats.rx_bytes[RTE_COLOR_GREEN]); ++ } else { ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "rx-pkts-num"); ++ hinic3_ds_put_format(ds, "%4s%-30s: N/A\n", HINIC3_UI_INDENT_SPACE, "rx-byte-num"); ++ } ++} ++ ++void ++hinic3_multi_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ uint16_t group_id; ++ char *endPtr = NULL; ++ uint16_t stats_mask = 0; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hinic3_group_info *group_info = NULL; ++ struct hovs_hqos_stats_batch_all hovs_stats = {0}; ++ ++ if (argc != MULTI_QOS_ARG_NUMS) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); ++ goto err; ++ } ++ ++ group_info = hinic3_group_info_get(group_id); ++ if (group_info->length == 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Group has no port.\n"); ++ goto err; ++ } ++ ++ if (hinic3_hqos_statistics_get_all_batch(QOS_TYPE_VM_LIMIT, &group_info->group_id, &hovs_stats, 1) != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Get stats failed.\n"); ++ goto err; ++ } ++ if (group_info->meter[BW_TX_TYPE].is_used == true || group_info->meter[PPS_TX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_TX; ++ if (group_info->meter[BW_RX_TYPE].is_used == true || group_info->meter[PPS_RX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_RX; ++ ++ hinic3_multi_qos_show_stats(&ds, hovs_stats, stats_mask); ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++void ++hinic3_multi_port_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ uint16_t stats_mask = 0; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hovs_hqos_stats_batch_all hovs_stats = {0}; ++ ++ if (argc != MULTI_QOS_ARG_NUMS) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ vf_dev = hinic3_multi_qos_get_dev(argv, &ds); ++ if (vf_dev == NULL) ++ goto err; ++ ++ if (vf_dev->qos_type == VF_NONE_QOS_FLAG) { ++ hinic3_ds_put_format(&ds, "%sPort has no qos.\n", HINIC3_UI_LEADING_SIGN_FAILURE); ++ goto err; ++ } ++ ++ if (hinic3_hqos_statistics_get_all_batch(QOS_TYPE_FUNC_LIMIT, &vf_dev->vport_id, &hovs_stats, 1) != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Get stats failed.\n"); ++ goto err; ++ } ++ ++ if (vf_dev->mtr[BW_TX_TYPE].is_used == true || vf_dev->mtr[PPS_TX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_TX; ++ if (vf_dev->mtr[BW_RX_TYPE].is_used == true || vf_dev->mtr[PPS_RX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_RX; ++ ++ hinic3_multi_qos_show_stats(&ds, hovs_stats, stats_mask); ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} ++ ++void ++hinic3_multi_net_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ uint16_t stats_mask = 0; ++ uint16_t host_id = 0; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct hovs_hqos_stats_batch_all hovs_stats = {0}; ++ struct hinic3_net_meter_info *net_qos_info = hinic3_net_meter_info_get(); ++ ++ if (argc != 1) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Invalid number of parameters.\n"); ++ goto err; ++ } ++ ++ if (hinic3_hqos_statistics_get_all_batch(QOS_TYPE_NET_LIMIT, &host_id, &hovs_stats, 1) != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Get stats failed.\n"); ++ goto err; ++ } ++ ++ if (net_qos_info[BW_TX_TYPE].is_used == true || net_qos_info[PPS_TX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_TX; ++ if (net_qos_info[BW_RX_TYPE].is_used == true || net_qos_info[PPS_RX_TYPE].is_used == true) ++ stats_mask |= MULTI_QOS_MASK_RX; ++ ++ hinic3_multi_qos_show_stats(&ds, hovs_stats, stats_mask); ++ *(int *)aux = 0; ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ return; ++err: ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +new file mode 100644 +index 0000000..9208521 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +@@ -0,0 +1,625 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_command.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_shash.h" ++#include "hinic3_log.h" ++#include "hinic3_thread.h" ++#include "hinic3_ds.h" ++#include "hinic3_check_thread_health_state.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ui_string.h" ++ ++#define HINIC3_COMMAND_STR_MAX_LEN 50 ++#define HINIC3_COMMAND_MAX_LEN 1000 ++ ++#define HINIC3_COMMAND_HASH_BUCKET_NUM 5 ++#define MAX_COMMAND_ARG_NUM 30 ++#define HINIC3_COMMAND_NUM 30 ++#define HINIC3_LISTEN_THREAD_TIMEOUT (20 * 1000) ++#define SOCKET_PATH "/opt/dpak/dpak_ovs_command.ctl" ++#define HINIC3_SOCKET_RIGHT 0660 ++#define HINIC3_COMMAND_MAX_RECV_TIME 10000 // 10s ++#define HINIC3_COMMAND_MAX_SEND_TIME 10000 // 10s, 如果输出内容过长,需要修改为输出到文件,避免影响其他用户 ++#define HINIC3_COMMAND_SLEEP_INTERVAL 100000 // 100ms ++#define CMD_EPOLL_SIZE 1024 ++#define EVENT_MAX_COUNT 20 ++ ++struct hinic3_command_mgr { ++ pthread_t thread; ++ struct shash command_map; ++ int listen_socket; ++ int epoll_fd; ++ uint32_t thread_exit; ++}; ++ ++struct hinic3_command_mgr g_command_mgr = {0}; ++ ++void ++hinic3_list_commands(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct shash_node *node = NULL; ++ struct ds reply = DS_EMPTY_INITIALIZER; ++ ++ hinic3_ds_put_format(&reply, "Available commands:\n"); ++ ++ HINIC3_SHASH_FOR_EACH(node, &g_command_mgr.command_map) { ++ struct hinic3_command *command = node->data; ++ hinic3_ds_put_format(&reply, " %-35s %s\n", node->name, command->usage); ++ } ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&reply)); ++ hinic3_ds_destroy(&reply); ++ *(int *)aux = 0; ++} ++ ++void ++hinic3_command_register(const char *name, const char *usage, int min_args, int max_args, unixctl_cb_func *cb, ++ void *aux HINIC3_UNUSED) ++{ ++ struct hinic3_command *command = NULL; ++ char key[HINIC3_COMMAND_STR_MAX_LEN] = {0}; ++ strcpy(key, name); ++ ++ struct hinic3_command *command_ptr = (struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); ++ if (command_ptr != NULL) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 command %s already registered", key); ++ return; ++ } ++ ++ command = (struct hinic3_command*)hinic3_calloc(1, sizeof(struct hinic3_command), HINIC3_COMMAND); ++ if (command == NULL) { ++ HINIC3_LOG(ERR, AGENT, "Create new hinic3 command %s failed", key); ++ return; ++ } ++ ++ command->usage = usage; ++ command->min_argc = min_args; ++ command->max_argc = max_args; ++ command->cb_func = cb; ++ ++ bool ret = hinic3_shash_add_once(&g_command_mgr.command_map, key, (void*)command, HINIC3_COMMAND); ++ if (ret != true) { ++ HINIC3_LOG(ERR, AGENT, "reg command %s fail", key); ++ hinic3_free(command); ++ return; ++ } ++ ++ return; ++} ++ ++int ++hinic3_write_str_to_socket(struct unixctl_conn *conn, const char *str) ++{ ++ if (str == NULL) ++ return -1; ++ ++ long long time_start = hinic3_time_msec(); ++ const char *cursor = str; ++ ++ while (*cursor != 0) { ++ long long time_now = hinic3_time_msec(); ++ if (time_now - time_start > HINIC3_COMMAND_MAX_SEND_TIME) { ++ HINIC3_LOG(INFO, AGENT, "command send time out"); ++ return -1; ++ } ++ ++ // 实测用fputc接口,数据量较大时,部分数据无法发送出去,这里write接口 ++ int ret = write(conn->sock_fd, cursor, 1); ++ if (ret == EOF) { ++ if (errno == EAGAIN || errno == EWOULDBLOCK) { ++ usleep(HINIC3_COMMAND_SLEEP_INTERVAL); ++ continue; ++ } else { ++ return -1; ++ } ++ } ++ ++ cursor++; ++ } ++ ++ return 0; ++} ++ ++void ++hinic3_command_reply(struct unixctl_conn *conn, const char *body) ++{ ++ hinic3_write_str_to_socket(conn, "0\n"); ++ hinic3_write_str_to_socket(conn, body); ++} ++ ++void ++hinic3_command_reply_error(struct unixctl_conn *conn, const char *error) ++{ ++ hinic3_write_str_to_socket(conn, "-1\n"); ++ hinic3_write_str_to_socket(conn, error); ++} ++ ++unixctl_cb_func *get_cmd_func(const char *command_str) ++{ ++ char key[HINIC3_COMMAND_STR_MAX_LEN] = {0}; ++ strcpy(key, command_str); ++ ++ struct hinic3_command *command = (struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); ++ if (command == NULL) ++ return (unixctl_cb_func *)NULL; ++ ++ return command->cb_func; ++} ++ ++static struct hinic3_command * ++get_cmd_command(const char *command_str) ++{ ++ char key[HINIC3_COMMAND_STR_MAX_LEN] = {0}; ++ strcpy(key, command_str); ++ struct hinic3_command *command = (struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); ++ return command; ++} ++ ++static int ++hinic3_cmd_param_check(const char *command_str, int argc) ++{ ++ struct hinic3_command *command = get_cmd_command(command_str); ++ if (command == NULL) ++ return HINIC3_COMMAND_ERROR_TYPE_NULL; ++ if (argc - 1 > command->max_argc) ++ return HINIC3_COMMAND_ERROR_TYPE_EXCESSIVE; ++ if (argc - 1 < command->min_argc) ++ return HINIC3_COMMAND_ERROR_TYPE_INSUFFICIENT; ++ return 0; ++} ++ ++int ++dispatch_command(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ if (argc == 0) ++ return -1; ++ int ret = 0; ++ unixctl_cb_func *cmd_func = get_cmd_func(argv[0]); ++ if (cmd_func != NULL) { ++ ret = hinic3_cmd_param_check(argv[0], argc); ++ if (ret == 0) { ++ cmd_func(conn, argc, argv, &ret); ++ } else if (ret == HINIC3_COMMAND_ERROR_TYPE_EXCESSIVE) { ++ HINIC3_LOG(ERR, AGENT, HINIC3_UI_ERROR_TOO_MANY_PARAMETER); ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_ERROR_TOO_MANY_PARAMETER ".\n"); ++ return -EINVAL; ++ } else if (ret == HINIC3_COMMAND_ERROR_TYPE_INSUFFICIENT) { ++ HINIC3_LOG(ERR, AGENT, HINIC3_UI_ERROR_INCOMPLETE_COMMAND); ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_ERROR_INCOMPLETE_COMMAND ".\n"); ++ return -EINVAL; ++ } ++ } else { ++ HINIC3_LOG(ERR, AGENT, "command mgr can't find func."); ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_ERROR_UNRECOGNIZED_COMMAND ".\n"); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++int ++parse_args(struct unixctl_conn *conn, char *command, int *argc_ptr, const char *argv[]) ++{ ++ char *cursor = command; ++ char *str_end = cursor + strlen(command); ++ char *delimiters = " "; ++ ++ *argc_ptr = 0; ++ ++ cursor = command; ++ while (strchr(delimiters, *cursor) != NULL) { ++ cursor++; ++ } ++ ++ if (cursor == str_end) ++ return 0; ++ ++ argv[(*argc_ptr)++] = cursor; ++ ++ do { ++ strsep(&cursor, delimiters); ++ if (cursor == NULL) ++ break; ++ ++ while (strchr(delimiters, *cursor) != NULL) { ++ cursor++; ++ } ++ ++ if (cursor == str_end) ++ break; ++ if ((*argc_ptr) == MAX_COMMAND_ARG_NUM) { ++ HINIC3_LOG(ERR, AGENT, "Too many command parameters"); ++ hinic3_command_reply_error(conn, "Too many command parameters\n"); ++ return -1; ++ } ++ ++ argv[(*argc_ptr)++] = cursor; ++ ++ if (strcmp(argv[1], "hwoff/exec-cmd") == 0) ++ break; ++ } while (cursor < str_end); ++ ++ return 0; ++} ++ ++int ++hinic3_server_recv_command(FILE *file, char *start, char *end) ++{ ++ long long time_start = hinic3_time_msec(); ++ ++ char *cursor = start; ++ while (cursor + 1 < end) { ++ long long time_now = hinic3_time_msec(); ++ if (time_now - time_start > HINIC3_COMMAND_MAX_RECV_TIME) { ++ HINIC3_LOG(INFO, AGENT, "command recv time out"); ++ return -1; ++ } ++ ++ int ch = fgetc(file); ++ if (ch == EOF) { ++ if (errno == EAGAIN) { ++ usleep(HINIC3_COMMAND_SLEEP_INTERVAL); ++ continue; ++ } else { ++ return -1; ++ } ++ } ++ ++ if (ch == '\n') ++ break; ++ ++ *cursor++ = ch; ++ } ++ ++ *cursor = '\0'; ++ ++ return 0; ++} ++ ++int ++hinic3_set_socket_nonblocking(int fd) ++{ ++ int flags = fcntl(fd, F_GETFL, 0); ++ if (flags < 0) ++ return -1; ++ ++ flags |= O_NONBLOCK; ++ ++ int result = fcntl(fd, F_SETFL, flags); ++ if (result < 0) ++ return -1; ++ ++ return 0; ++} ++ ++static struct hinic3_command_info g_hinic3_command_info[] = { ++ {"hwoff/show-hmap-flow-num", "Queries the number of flow tables in the hash table."}, ++ {"hinic3-agent-version", "Query the dpak-libovs version."}, ++ {"hwoff/exec-cmd", "This command is used to issue or query OVS driver information for debugging."}, ++ {"hwoff/show-flow-api", "This API is used to query the hardware flow table."}, ++ {"hwoff/show-error-stats", "Indicates the error information recorded during flow table unloading."}, ++ {"hwoff/dump-hinic3-flows", "Queries hardware flow table information."}, ++ {"hwoff/flow-offload-speed-stat", "Collects statistics on or queries the flow table offloading rate."}, ++ {"hwoff/show-offload-flow-num", ++ "This command is used to query the number of flow tables that are unloaded (software statistics)."}, ++ {"hwoff/dump-ports", "Queries the port status."}, ++ {"hwoff/flush-ports", "Clears port/chip statistics."}, ++ {"hwoff/dump-upcall-queue-info", "Queries upcall queue information."}, ++ {"hwoff/dump-bond-slave-info", "Displays information about the bond_slave port."}, ++ {"hwoff/show-function-flavor", "Queries the port list."}, ++ {"hwoff/show-function-stats", "Queries the VirtIO queue usage."}, ++ {"hwoff/dump-qos-loss", "Queries the number of packets discarded in the receive direction due to rate limitation."}, ++ {"hwoff/dump-port-qos-loss", ++ "Queries the number of packets discarded due to rate limitation in the receive direction of a port."}, ++ {"hwoff/show-qos-speed", "Queries the actual rate in a specified rate limit gorup policy."}, ++ {"hwoff/show-port-qos-speed", "Queries the net rate limit information."}, ++ {"hwoff/dump-net-qos-loss", ++ "Queries the number of packets discarded in the receive direction due to net rate limitation."}, ++ {"hwoff/dump-net-qos", "Queries the QoS information of a specified port."}, ++ {"hwoff/dump-qos-stats", "Queries the QoS Statistics of a specified group."}, ++ {"hwoff/dump-port-qos-stats", "Queries the QoS Statistics of a specified port."}, ++ {"hwoff/dump-net-qos-stats", "Queries the QoS Statistics of a specified net."}, ++ {"hwoff/show-meter", "Queries meter Information."}, ++ {"hwoff/show-policy", "Queries policy Information."}, ++ {"hwoff/show-profile", "Queries profile Information."}, ++ {"hwoff/show-port-qos", "Indicates the port rate limit type, which can be device rate limit or port rate limit."}, ++ {"hwoff/dump-qos", "Queries the group rate limit information."}, ++ {"hwoff/enable-capture-probe", "Enable the packet capture function."}, ++ {"hwoff/disable-capture-probe", "Disable the packet capture function."}, ++ {"hwoff/capture-probe", "Capturing Packets function."}, ++ {"list-commands", "Displays the list of all commands."}, ++ {"hwoff/show-global-api", "This API is used to query global hardware operations."}, ++ {"hwoff/show-mpool-stats", "Query the memory pool status."}, ++ {"hwoff/show-port-api", "This command is used to query API invoking statistics of hardware ports."}, ++ {"hwoff/show-emc-session", "This command is used to query session info of emc flows."}, ++ {"hwoff/flow-escape-mode", "Configuring the Escape Mode."}, ++ ++ {"hwoff/dump-trace", "Querying the Error Information Tracing of an Added Flow."}, ++ {"hwoff/trace-flow", "Configure error information tracing for a specified flow."}, ++ ++ {"hwoff/show-thread-stats", "This command is used to obtain the thread health status."}, ++ {"hwoff/show-meminfo", "This command is used to show requested memory size."}, ++ {"hwoff/show-hugepage-meminfo", "This command is used to show hugepage memory size."}, ++ {"hwoff/show-sample-session", "This command is used to show sample session."}, ++ {"hwoff/set-log-level", "This command is used to set log level for module"}, ++ {"hwoff/show-log-list", "This command is used to show log list."}, ++ {"hwoff/del-flow-by-ufid", "This command is used to delete flow by ufid."}, ++ {"hwoff/query-offloaded-flow", "This command is used to set query info and query flow."}, ++ {"hwoff/set-forward-mode", "This command is used to set forward mode."}, ++ {"hwoff/show-forward-mode", "This command is used to get forward mode configuration."}, ++ {"hwoff/dump-flow-qos-loss", "This command is used to dump flow qos loss."}, ++}; ++ ++static int ++get_cmd_info(const char *func_name, char *cmd_info) ++{ ++ for (int i = 0; i < sizeof(g_hinic3_command_info) / sizeof(struct hinic3_command_info); i++) { ++ if (strncmp(func_name, g_hinic3_command_info[i].func_name, strlen(g_hinic3_command_info[i].func_name)) == 0) { ++ memcpy(cmd_info, g_hinic3_command_info[i].info, HINIC3_CMD_INFO_MAX_LEN); ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++static void ++hinic3_set_cmd_info_to_log(const char *usr_name, const char *func_name, int result) ++{ ++ int ret; ++ char *cmd_info = (char *)hinic3_calloc(1, HINIC3_CMD_INFO_MAX_LEN, HINIC3_COMMAND); ++ if (cmd_info == NULL) { ++ HINIC3_LOG(ERR, AGENT, "Calloc cmd info mem failed."); ++ return; ++ } ++ ret = get_cmd_info(func_name, cmd_info); ++ if (ret != 0) { ++ HINIC3_LOG(WARNING, AGENT, "The command is not registered."); ++ hinic3_free(cmd_info); ++ return; ++ } ++ if (result != 0) { ++ HINIC3_LOG(INFO, AGENT, "[%s@localhost]%s:%s - Execution fail", usr_name, func_name, cmd_info); ++ } else { ++ HINIC3_LOG(INFO, AGENT, "[%s@localhost]%s:%s - Execution success", usr_name, func_name, cmd_info); ++ } ++ hinic3_free(cmd_info); ++} ++ ++int ++proc_conn(int data_socket) ++{ ++ int ret = hinic3_set_socket_nonblocking(data_socket); ++ if (ret != 0) { ++ close(data_socket); ++ HINIC3_LOG(ERR, AGENT, "set nonblocking fail"); ++ return ret; ++ } ++ ++ struct unixctl_conn conn = {0}; ++ conn.sock_fd = data_socket; ++ ++ conn.sock_file = fdopen(conn.sock_fd, "a+"); ++ if (conn.sock_file == NULL) { ++ close(conn.sock_fd); ++ return -1; ++ } ++ ++ char command[HINIC3_COMMAND_MAX_LEN]; ++ ++ ret = hinic3_server_recv_command(conn.sock_file, command, command + sizeof(command)); ++ if (ret != 0) { ++ fclose(conn.sock_file); ++ return -1; ++ } ++ ++ const char *argv[MAX_COMMAND_ARG_NUM]; ++ int argc = 0; ++ if (parse_args(&conn, command, &argc, argv) != 0) { ++ fclose(conn.sock_file); ++ return -1; ++ } ++ ++ ret = dispatch_command(&conn, argc - 1, argv + 1); // argv参数的第一个为uid ++ (void)hinic3_set_cmd_info_to_log(argv[0], argv[1], ret); ++ ++ (void)fclose(conn.sock_file); ++ return 0; ++} ++ ++void ++hinic3_command_epoll_process(int fd) ++{ ++ int listen_socket = g_command_mgr.listen_socket; ++ if (fd == listen_socket) { ++ int data_socket = accept(listen_socket, NULL, NULL); ++ if (data_socket == -1) ++ return; ++ proc_conn(data_socket); ++ } ++ return; ++} ++ ++void * ++hinic3_command_thread(void *arg) ++{ ++ int listen_socket = g_command_mgr.listen_socket; ++ int epoll_fd = g_command_mgr.epoll_fd; ++ int i = 0; ++ HINIC3_LOG(INFO, AGENT, "command mgr start listen"); ++ ++ struct epoll_event event_list[EVENT_MAX_COUNT]; ++ memset(&event_list, 0, sizeof(event_list)); ++ ++ enum check_thread_item_type check_thread = LISTEN_THREAD; ++ long long start = hinic3_time_msec(); ++ while (g_command_mgr.thread_exit == HINIC3_THREAD_NORMAL_STATUS) { ++ start = hinic3_thread_signal_increase(start, check_thread, HINIC3_LISTEN_THREAD_SIGNAL_INCREASE_INTER); ++ int nfds = epoll_wait(epoll_fd, event_list, EVENT_MAX_COUNT, HINIC3_LISTEN_THREAD_TIMEOUT); ++ if (nfds <= 0) ++ continue; ++ for (i = 0; i < nfds; ++i) { ++ hinic3_command_epoll_process(event_list[i].data.fd); ++ } ++ } ++ ++ close(epoll_fd); ++ close(listen_socket); ++ ++ return 0; ++} ++ ++static int ++hinic3_change_group(void) ++{ ++ int ret; ++ gid_t group_id; ++ struct group *grp; ++ ++ grp = getgrnam(HINIC3_OVS_GROUP_NAME); ++ if (grp == NULL) { ++ HINIC3_LOG(ERR, AGENT, "getgrnam fail"); ++ return -1; ++ } ++ group_id = grp->gr_gid; ++ ++ ret = chown(SOCKET_PATH, -1, group_id); ++ if (ret == -1) { ++ HINIC3_LOG(ERR, AGENT, "chown fail"); ++ return -1; ++ } ++ ++ ret = chmod(SOCKET_PATH, HINIC3_SOCKET_RIGHT); ++ if (ret == -1) { ++ HINIC3_LOG(ERR, AGENT, "chmod fail"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int ++hinic3_command_pre_init(int *listen_socket) ++{ ++ int ret; ++ int pre_socket; ++ const char *sock_path = SOCKET_PATH; ++ unlink(sock_path); ++ ++ struct sockaddr_un addr = {0}; ++ addr.sun_family = AF_UNIX; ++ strcpy(addr.sun_path, sock_path); ++ ++ pre_socket = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (pre_socket == -1) { ++ HINIC3_LOG(ERR, AGENT, "create socket fail"); ++ return -1; ++ } ++ ++ ret = bind(pre_socket, (const struct sockaddr *)&addr, sizeof(addr)); ++ if (ret == -1) { ++ HINIC3_LOG(ERR, AGENT, "bind socket fail"); ++ close(pre_socket); ++ return -1; ++ } ++ ++ ret = listen(pre_socket, 10); // 10: 最大等待链接的客户端个数 ++ if (ret == -1) { ++ HINIC3_LOG(ERR, AGENT, "listen socket fail"); ++ close(pre_socket); ++ return -1; ++ } ++ ++ *listen_socket = pre_socket; ++ return 0; ++} ++ ++int ++hinic3_command_init(void) ++{ ++ int ret; ++ int listen_socket; ++ struct epoll_event event; ++ ++ ret = hinic3_command_pre_init(&listen_socket); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 command pre init fail"); ++ return -1; ++ } ++ ++ int epoll_fd = epoll_create(CMD_EPOLL_SIZE); ++ if (epoll_fd < 0) { ++ HINIC3_LOG(ERR, AGENT, "epoll create fail"); ++ goto err; ++ } ++ ++ memset(&event, 0, sizeof(event)); ++ event.data.fd = listen_socket; ++ event.events = EPOLLIN; ++ ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_socket, &event); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "epoll_ctl add fail"); ++ goto err; ++ } ++ g_command_mgr.listen_socket = listen_socket; ++ g_command_mgr.epoll_fd = epoll_fd; ++ ret = hinic3_thread_create(&g_command_mgr.thread, "hinic3_listen_thread", hinic3_command_thread, NULL, HINIC3_COMMAND); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "listen thread create fail"); ++ goto err; ++ } ++ ++ hinic3_set_ctrl_thread_cpu_affinity(&g_command_mgr.thread); ++ return 0; ++ ++err: ++ close(epoll_fd); ++ close(listen_socket); ++ return -1; ++} ++ ++void ++hinic3_command_hmap_init(void) ++{ ++ hinic3_shash_init(&g_command_mgr.command_map); ++} ++ ++int ++hinic3_command_mgr_init(void) ++{ ++ int ret; ++ ++ hinic3_command_register("list-commands", "", 0, 0, hinic3_list_commands, NULL); ++ ++ ret = hinic3_command_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "command mgr init fail"); ++ return ret; ++ } ++ ++ ret = hinic3_change_group(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "change group fail"); ++ return ret; ++ } ++ ++ HINIC3_LOG(INFO, AGENT, "command mgr init success"); ++ return 0; ++} ++ ++void ++hinic3_command_mgr_uninit(void) ++{ ++ hinic3_shash_destroy_free_data(&g_command_mgr.command_map); ++ g_command_mgr.thread_exit = HINIC3_THREAD_EXIT_STATUS; ++} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.h b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.h +new file mode 100644 +index 0000000..d3056df +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.h +@@ -0,0 +1,49 @@ ++/* ++ * SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef _HINIC3_COMMAND_H_ ++#define _HINIC3_COMMAND_H_ ++ ++#include "stdio.h" ++ ++#define HINIC3_CMD_INFO_MAX_LEN 200 ++#define HINIC3_CMD_NAME_MAX_LEN 50 ++ ++struct unixctl_conn { ++ int sock_fd; ++ FILE *sock_file; ++}; ++ ++typedef void unixctl_cb_func(struct unixctl_conn *, int argc, const char *argv[], void *aux); ++ ++struct hinic3_command { ++ unixctl_cb_func *cb_func; ++ int min_argc; ++ int max_argc; ++ const char *usage; ++}; ++ ++void hinic3_command_register(const char *name, const char *usage, int min_args, int max_args, unixctl_cb_func *cb, ++ void *aux); ++ ++void hinic3_command_reply_error(struct unixctl_conn *conn, const char *error); ++void hinic3_command_reply(struct unixctl_conn *conn, const char *body); ++ ++void hinic3_command_hmap_init(void); ++int hinic3_command_mgr_init(void); ++void hinic3_command_mgr_uninit(void); ++ ++struct hinic3_command_info { ++ char func_name[HINIC3_CMD_NAME_MAX_LEN]; ++ char info[HINIC3_CMD_INFO_MAX_LEN]; ++}; ++ ++enum hinic3_command_parameter_num_error_type { ++ HINIC3_COMMAND_ERROR_TYPE_NULL = 1, ++ HINIC3_COMMAND_ERROR_TYPE_EXCESSIVE, ++ HINIC3_COMMAND_ERROR_TYPE_INSUFFICIENT, ++}; ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h +new file mode 100644 +index 0000000..0e882b8 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h +@@ -0,0 +1,152 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_DRIVER_PUBLIC_H ++#define HINIC3_DRIVER_PUBLIC_H ++ ++#include ++#include ++#include ++#include "rte_bus_vdev.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_message.h" ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define HINIC3_ERROR_CODE_LEN sizeof(hiovs_error_code_map_array) / sizeof(struct hiovs_error_code_map) ++ ++enum { ++ HINIC3_MODE_VERSION_00, ++ HINIC3_MODE_VERSION_01, ++ HINIC3_MODE_VERSION_MAX ++}; ++ ++typedef enum provider_notice { ++ PROVIDER_NOTICE_FLOW_PUT, ++ PROVIDER_NOTICE_FLOW_AGE, ++ PROVIDER_NOTICE_MAX, ++} provider_notice_t; ++ ++struct hiovs_error_code_map { ++ enum hinic3_api_return_val hiovs_err_code; ++ int errno_code; ++}; ++ ++typedef struct tag_hiovs_api_record { ++ /* the max time that api executes */ ++ uint64_t max_api_time; ++ /* the min time that api executes */ ++ uint64_t min_api_time; ++ /* the total time that api executes, which allows integer inversion and will not affect the function */ ++ uint64_t total_api_time; ++ /* the total count that api executes */ ++ uint64_t call_total_count; ++ /* the total count that api executes error */ ++ uint64_t call_error_count; ++ /* some api returns long long int, so use the max */ ++ long long int last_rtn_value; ++ /* the time when error occurs */ ++ time_t time_error; ++} hiovs_api_record; ++ ++struct hinic3_dpif_flow { ++ /* Flow to Put */ ++ struct hinic3_nlattr_obj *key; ++ /* length of key in bytes */ ++ size_t key_len; ++ /* mask to put */ ++ const struct hinic3_nlattr_obj *mask; ++ /* length of mask in bytes */ ++ size_t mask_len; ++ /* actions to perform on flow */ ++ struct hinic3_nlattr_obj *actions; ++ size_t action_len; ++ uint8_t mask_present; ++ uint64_t hw_ufid; ++ struct hinic3_flow_stats stats; ++}; ++ ++struct hinic3_dpif_flow_for_get { ++ /* Flow to Put */ ++ struct hinic3_nlattr_obj *key; ++ /* length of key in bytes */ ++ size_t key_len; ++ /* mask to put */ ++ struct hinic3_nlattr_obj *mask; ++ /* length of mask in bytes */ ++ size_t mask_len; ++ /* actions to perform on flow */ ++ struct hinic3_nlattr_obj *actions; ++ size_t action_len; ++ uint8_t mask_present; ++ uint64_t ol_ufid; ++ uint64_t related_hw_ufid; ++ struct hinic3_flow_stats stats; ++}; ++ ++ ++struct hinic3_flow_del_buf { ++ struct hinic3_dpif_flow_for_get get_flow; ++ uint8_t key_buf[HINIC3_MSG_MAX_BUF]; ++ uint8_t actions_buf[HINIC3_MSG_MAX_BUF]; ++}; ++ ++struct hinic3_flow_del_context { ++ /* current num of hardware flow */ ++ size_t num_entries; ++ /* per del ufid list */ ++ uint64_t ufids[HINIC3_MAX_ENTRY_PER_BATCH_DEL]; ++ /* per del flow info ptr */ ++ struct hinic3_dpif_flow_for_get *flows[HINIC3_MAX_ENTRY_PER_BATCH_DEL]; ++ /* per del flow info */ ++ struct hinic3_flow_del_buf buf[HINIC3_MAX_ENTRY_PER_BATCH_DEL]; ++}; ++ ++static struct hiovs_error_code_map hiovs_error_code_map_array[] = { ++ {HINIC3_API_OK, 0}, ++ {HIOVS_OK, 0}, ++ {HINIC3_PORT_API_ERROR_BASE, -EPERM}, ++ {HINIC3_FLOW_API_ERROR_BASE, -EINVAL}, ++ {HINIC3_FLOW_API_KEY_ERROR, -EPERM}, ++ {HINIC3_FLOW_API_ACTION_ERROR, -EPERM}, ++ {HINIC3_FLOW_API_FLUSH_ERROR, -EBUSY}, ++ {HINIC3_FLOW_API_CBPARM_ERROR, -EPERM}, ++ {HINIC3_FLOW_API_FULL_ERROR, -EPERM}, ++ {HINIC3_FLOW_API_SEND_ERROR, -EBUSY}, ++ {HINIC3_FLOW_API_OTHER_ERROR, -EPERM}, ++ {HINIC3_FLOW_API_ERROR_END, -EPERM}, ++ {HINIC3_CALLBACK_API_ERROR_BASE, -EPERM}, ++ {HINIC3_BUM_API_ERROR_BASE, -EPERM}, ++ {HINIC3_QOS_API_ERROR_BASE, -EPERM}, ++ {HINIC3_GLOBAL_API_ERROR_BASE, -EPERM}, ++ {HINIC3_API_ERROR_END, -EPERM}, ++ {HIOVS_ERROR, -EPERM}, ++ {HIOVS_EEXEC, -ENOMEM}, ++}; ++ ++static inline int hinic3_convert_error_code(int error_code) ++{ ++ for (int i = 0; i < HINIC3_ERROR_CODE_LEN; i++) { ++ if (error_code == hiovs_error_code_map_array[i].hiovs_err_code) { ++ return hiovs_error_code_map_array[i].errno_code; ++ } ++ } ++ return error_code; ++} ++ ++typedef int (*hinic3_flow_callback_t)(uint64_t ufid, const struct hinic3_dpif_flow_for_get *flow, ++ const struct hinic3_nlattr_obj *args, size_t args_len); ++typedef int (*hinic3_flow_put_cb_t)(uint64_t ufid, const struct hinic3_nlattr_obj *args, size_t args_len); ++typedef int (*hinic3_flow_age_cb_t)(uint64_t ufid, const struct hinic3_dpif_flow_for_get *flow, ++ const struct hinic3_nlattr_obj *args, size_t args_len); ++typedef int (*hinic3_flush_done_cb_t)(void); ++const struct rte_vdev_driver* vpmd_vdev_driver_get(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c +new file mode 100644 +index 0000000..dc1b053 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c +@@ -0,0 +1,552 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_iface_flow.h" ++#include ++#include ++#include "rte_cycles.h" ++#include "hinic3_init.h" ++#include "hinic3_message.h" ++#include "hinic3_log.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_iface_flow_api_record.h" ++ ++#define NO_HINIC3_FLOWS_ERR (-4) ++#define GLOBAL_CFG_ARGS_SIZE (128) ++ ++ ++struct hiovs_flow_map { ++ hinic3_flow_api api_index; ++ const char *api_name; ++}; ++ ++ ++static const struct hiovs_flow_map g_flow_api_arr[HINIC3_FLOW_API_MAX] = { ++ { HINIC3_FLOW_AGENT_PUT, "hovs_flow_mgmt_put" }, ++ { HINIC3_FLOW_AGENT_GET_BY_KEY, "hovs_flow_mgmt_get_by_key" }, ++ { HINIC3_FLOW_AGENT_GET_BY_UFID, "hovs_flow_mgmt_get_by_ufid" }, ++ { HINIC3_FLOW_AGENT_DEL_BY_UFID, "hovs_flow_mgmt_del_by_ufid" }, ++ { HINIC3_FLOW_AGENT_DEL_BATCH, "hovs_flow_mgmt_del_by_batch" }, ++ { HINIC3_FLOW_AGENT_FLUSH, "hovs_flow_mgmt_flush" }, ++ { HINIC3_FLOW_AGENT_DUMP_START, "hovs_flow_mgmt_dump_start" }, ++ { HINIC3_FLOW_AGENT_DUMP_NEXT, "hovs_flow_mgmt_dump_next" }, ++ { HINIC3_FLOW_AGENT_DUMP_DONE, "hovs_flow_mgmt_dump_done" }, ++ { HINIC3_FLOW_AGENT_GET_MAXFLOWS, "hovs_flow_mgmt_get_maxflows" }, ++ { HINIC3_FLOW_AGENT_GET_CAPABILITY, "hovs_flow_mgmt_get_capability" }, ++ { HINIC3_FLOW_AGENT_SET_FORWARD_MODE, "hovs_flow_mgmt_set_forward_mode" }, ++ { HINIC3_FLOW_AGENT_GET_FORWARD_MODE, "hovs_flow_mgmt_get_forward_mode" }, ++ { HINIC3_STATISTICS_FLOW_GET_BY_UFID, "hovs_statistics_flow_get_by_ufid" }, ++ { HINIC3_STATISTICS_FLOW_FLUSH_BY_UFID, "hovs_statistics_flow_flush_by_ufid" }, ++ { HINIC3_RTE_FLOW_CREATE, "hinic3_rte_flow_create"}, ++ { HINIC3_RTE_FLOW_QUERY, "hinic3_rte_flow_query"}, ++ { HINIC3_RTE_FLOW_DELETE, "hinic3_rte_flow_delete"}, ++ { HINIC3_RTE_FLOW_FLUAH_ALL, "hinic3_rte_flow_flush_all"}, ++ { HINIC3_RTE_FLOW_DESTROY_BY_BATCH, "hinic3_rte_flow_destroy_by_batch"}, ++ { HINIC3_RTE_FLOW_DUMP_START, "hinic3_rte_flow_dump_start"}, ++ { HINIC3_RTE_FLOW_DUMP_NEXT, "hinic3_rte_flow_dump_next"}, ++ { HINIC3_RTE_FLOW_DUMP_END, "hinic3_rte_flow_dump_end"}, ++ { HINIC3_FLOW_BLOCK_SIZE_GET, "hovs_flow_mgmt_get_block_table_size"}, ++ { HINIC3_FLOW_MODIFY, "hovs_flow_mgmt_update"}, ++ { HINIC3_FLOW_BLOCK_VERSION_SET, "hovs_flow_mgmt_set_block_version"}, ++ { HINIC3_FLOW_BLOCK_VERSION_GET, "hovs_flow_mgmt_get_block_version"}, ++}; ++ ++static pthread_mutex_t g_hinic3_flow_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++int hinic3_flow_get_capability(struct hinic3_flow_capability *cap) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ struct hovs_flow_capability hovs_cap; ++ int ret; ++ ++ if (cap == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3 get capability parameter is NULL"); ++ return -EINVAL; ++ } ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_capability, HINIC3_DRV_FUNC_NO_PTR); ++ ++ memset(&hovs_cap, 0x0, sizeof(hovs_cap)); ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_WARN(ret, HINIC3_FLOW_AGENT_GET_CAPABILITY, ++ ops->hovs_flow_mgmt_get_capability(&hovs_cap)); ++ ++ if (ret != 0) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3 get capability parameter failed, error :%d", ret); ++ return hinic3_convert_error_code(ret); ++ } ++ ++ cap->vendor_id = hovs_cap.vendor_id; ++ cap->supported_dev_types = hovs_cap.supported_dev_types | (1 << PORT_TYPE_VIRTIO_VF) | (1 << PORT_TYPE_HWBOND); ++ cap->supported_actions = hovs_cap.supported_actions; ++ cap->key_format_type = hovs_cap.key_format_type; ++ cap->cleanup_max_level = hovs_cap.cleanup_max_level; ++ cap->flags = hovs_cap.flags; ++ cap->max_flow_size = hovs_cap.max_flow_size; ++ cap->rx_thread_num = hovs_cap.rx_thread_num; ++ return ret; ++} ++ ++int hinic3_flow_put(const struct hinic3_dpif_flow *put, const struct hinic3_nlattr *args, size_t args_len) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ struct hovs_dpif_flow hovs_put = { 0 }; ++ int ret; ++ if (put == NULL || args == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_put pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_put, HINIC3_DRV_FUNC_NO_PTR); ++ ++ hovs_put.key = (struct nlattr *)put->key; ++ hovs_put.key_len = put->key_len; ++ hovs_put.mask = (struct nlattr *)put->mask; ++ hovs_put.mask_len = put->mask_len; ++ hovs_put.actions = (struct nlattr *)put->actions; ++ hovs_put.action_len = put->action_len; ++ hovs_put.mask_present = put->mask_present; ++ hovs_put.hw_ufid = put->hw_ufid; ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_PUT, ++ ops->hovs_flow_mgmt_put(&hovs_put, (struct nlattr *)args, args_len)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_mgmt_get_by_key(const struct hinic3_nlattr *key, size_t key_len, struct hinic3_dpif_flow *put, ++ uint64_t get_flow_related_ufid) ++{ ++ if (key == NULL || put == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_mgmt_get_by_key pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ struct hovs_dpif_flow_for_get hovs_put = { 0 }; ++ ++ hovs_put.key = (struct nlattr *)put->key; ++ hovs_put.key_len = put->key_len; ++ hovs_put.mask = (struct nlattr *)put->mask; ++ hovs_put.mask_len = put->mask_len; ++ hovs_put.actions = (struct nlattr *)put->actions; ++ hovs_put.action_len = put->action_len; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_by_key, HINIC3_DRV_FUNC_NO_PTR); ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_GET_BY_KEY, ++ ops->hovs_flow_mgmt_get_by_key((struct nlattr *)key, key_len, &hovs_put)); ++ if (ret == 0) { ++ put->hw_ufid = hovs_put.hw_ufid; ++ put->key = (struct hinic3_nlattr_obj*)hovs_put.key; ++ put->key_len = hovs_put.key_len; ++ put->mask = (struct hinic3_nlattr_obj*)hovs_put.mask; ++ put->mask_len = hovs_put.mask_len; ++ put->actions = (struct hinic3_nlattr_obj*)hovs_put.actions; ++ put->mask_present = hovs_put.mask_present; ++ put->action_len = hovs_put.action_len; ++ get_flow_related_ufid = hovs_put.related_hw_ufid; ++ memcpy(&put->stats, &hovs_put.stats, sizeof(struct hovs_flow_stats)); ++ } ++ return ret; ++} ++ ++int hinic3_flow_get_by_ufid(uint64_t ufid, struct hinic3_dpif_flow_for_get *get) ++{ ++ struct hovs_dpif_flow_for_get hovs_get; ++ struct hinic3_drv_ops *ops = NULL; ++ int ret; ++ ++ if (get == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_get_by_ufid pointer parameter is NULL!"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_by_ufid, HINIC3_DRV_FUNC_NO_PTR); ++ ++ memset(&hovs_get, 0, sizeof(hovs_get)); ++ hovs_get.key = (struct nlattr *)get->key; ++ hovs_get.mask = (struct nlattr *)get->mask; ++ hovs_get.actions = (struct nlattr *)get->actions; ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_GET_BY_UFID, ++ ops->hovs_flow_mgmt_get_by_ufid(ufid, &hovs_get)); ++ if (ret != 0) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3 flow get by ufid failed, error is %d", ret); ++ return hinic3_convert_error_code(ret); ++ } ++ get->key_len = hovs_get.key_len; ++ get->mask_len = hovs_get.mask_len; ++ get->action_len = hovs_get.action_len; ++ get->mask_present = hovs_get.mask_present; ++ get->ol_ufid = hovs_get.hw_ufid; ++ get->related_hw_ufid = hovs_get.related_hw_ufid; ++ ++ memcpy(&get->stats, &hovs_get.stats, sizeof(struct hovs_flow_stats)); ++ return 0; ++} ++ ++int hinic3_flow_del_by_ufid(uint64_t ufid) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_del_by_ufid, HINIC3_DRV_FUNC_NO_PTR); ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_DEL_BY_UFID, ops->hovs_flow_mgmt_del_by_ufid(ufid)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_del_batch(const uint64_t *ufids, struct hinic3_dpif_flow_for_get **flows, const size_t cnt) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ if (ufids == NULL || flows == NULL || *flows == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_del_batch pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_del_by_batch, HINIC3_DRV_FUNC_NO_PTR); ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_DEL_BATCH, ++ ops->hovs_flow_mgmt_del_by_batch(ufids, (struct hovs_dpif_flow_for_get **)flows, cnt)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_flush(void) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_flush, HINIC3_DRV_FUNC_NO_PTR); ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_FLUSH, ops->hovs_flow_mgmt_flush()); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_dump_start(void **state) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_dump_start, HINIC3_DRV_FUNC_NO_PTR); ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_DUMP_START, ops->hovs_flow_mgmt_dump_start(state)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_process_dpif_flow_for_get_data(struct hovs_dpif_flow_for_get dump_for_get, ++ struct hinic3_dpif_flow_for_get *dump) ++{ ++ dump->key_len = dump_for_get.key_len; ++ dump->mask_len = dump_for_get.mask_len; ++ dump->action_len = dump_for_get.action_len; ++ dump->mask_present = dump_for_get.mask_present; ++ dump->ol_ufid = dump_for_get.hw_ufid; ++ dump->related_hw_ufid = dump_for_get.related_hw_ufid; ++ ++ dump->stats.packet_count = dump_for_get.stats.packet_count; ++ dump->stats.byte_count = dump_for_get.stats.byte_count; ++ dump->stats.ct_loss_pkts = dump_for_get.stats.ct_loss_pkts; ++ dump->stats.live_time = dump_for_get.stats.live_time; ++ dump->stats.age_time = dump_for_get.stats.age_time; ++ dump->stats.tcp_flags = dump_for_get.stats.tcp_flags; ++ ++ memcpy(dump->stats.block, dump_for_get.stats.block, sizeof(dump_for_get.stats.block)); ++ return 0; ++} ++ ++int hinic3_flow_dump_next(void *state, struct hinic3_dpif_flow_for_get *dump) ++{ ++ if (state == NULL || dump == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_dump_next pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ struct hinic3_drv_ops *ops = NULL; ++ struct hovs_dpif_flow_for_get dump_for_get; ++ int ret; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_dump_next, HINIC3_DRV_FUNC_NO_PTR); ++ ++ memset(&dump_for_get, 0, sizeof(dump_for_get)); ++ dump_for_get.key = (struct nlattr *)dump->key; ++ dump_for_get.mask = (struct nlattr *)dump->mask; ++ dump_for_get.actions = (struct nlattr *)dump->actions; ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_DUMP_NEXT, ++ ops->hovs_flow_mgmt_dump_next(state, &dump_for_get)); ++ if (ret != 0) { ++ return hinic3_convert_error_code(ret); ++ } ++ return hinic3_process_dpif_flow_for_get_data(dump_for_get, dump); ++} ++ ++int hinic3_flow_dump_done(void *state) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ if (state == NULL) { ++ return 0; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_dump_done, HINIC3_DRV_FUNC_NO_PTR); ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_DUMP_DONE, ops->hovs_flow_mgmt_dump_done(state)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_get_maxflows(uint32_t *max_flows) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ if (max_flows == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_get_maxflows pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_maxflows, HINIC3_DRV_FUNC_NO_PTR); ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG(ret, HINIC3_FLOW_AGENT_GET_MAXFLOWS, ops->hovs_flow_mgmt_get_maxflows(max_flows)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_set_forward_mode(uint8_t forward_mode) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_set_forward_mode, HINIC3_DRV_FUNC_NO_PTR); ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG(ret, HINIC3_FLOW_AGENT_SET_FORWARD_MODE, ++ ops->hovs_flow_mgmt_set_forward_mode(forward_mode)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_get_forward_mode(uint8_t *forward_mode) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ if (forward_mode == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_get_forward_mode pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_forward_mode, HINIC3_DRV_FUNC_NO_PTR); ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG(ret, HINIC3_FLOW_AGENT_GET_FORWARD_MODE, ++ ops->hovs_flow_mgmt_get_forward_mode(forward_mode)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_statistics_flow_get_by_ufid(const uint64_t *ufid, const size_t cnt, struct hinic3_flow_stats *stats) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_statistics_flow_get_by_ufid, HINIC3_DRV_FUNC_NO_PTR); ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_STATISTICS_FLOW_GET_BY_UFID, ++ ops->hovs_statistics_flow_get_by_ufid(ufid, cnt, (struct hovs_flow_stats *)stats)); ++ return hinic3_convert_error_code(ret); ++} ++ ++const char *hinic3_flow_get_api_name(hinic3_flow_api api_index) ++{ ++ for (int i = 0; i < HINIC3_FLOW_API_MAX; ++i) { ++ if (api_index == g_flow_api_arr[i].api_index) { ++ return g_flow_api_arr[i].api_name; ++ } ++ } ++ return NULL; ++} ++ ++hinic3_flow_api hinic3_flow_get_api_index(const char *api_name) ++{ ++ for (int i = 0; i < HINIC3_FLOW_API_MAX; ++i) { ++ if (strncmp(api_name, g_flow_api_arr[i].api_name, strlen(g_flow_api_arr[i].api_name) + 1) == 0) { ++ return g_flow_api_arr[i].api_index; ++ } ++ } ++ return HINIC3_FLOW_API_MAX; ++} ++ ++int hinic3_flow_init(void) ++{ ++ struct hinic3_flow_capability cap; ++ memset(&cap, 0, sizeof(cap)); ++ ++ if (hinic3_flow_get_capability(&cap) != 0) { ++ HINIC3_LOG(ERR, FLOW, "Failed to get hiovs capability"); ++ return -1; ++ } ++ ++ if (cap.rx_thread_num > HINIC3_RX_THREAD_MAX) { ++ HINIC3_LOG(ERR, FLOW, "flow agent rx thread num: %u is greater than max num: %d!", cap.rx_thread_num, ++ HINIC3_RX_THREAD_MAX); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int hinic3_flow_class_init(void) ++{ ++ hiovs_api_record *flow_api_record = NULL; ++ ++ flow_api_record = hinic3_get_hiovs_api_record(); ++ if (flow_api_record == NULL) { ++ return -1; ++ } ++ ++ memset(flow_api_record, 0, sizeof(hiovs_api_record) * HINIC3_FLOW_API_MAX); ++ ++ pthread_mutex_lock(&g_hinic3_flow_mutex); ++ int ret = hinic3_flow_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_flow_init fail ret is %d", ret); ++ pthread_mutex_unlock(&g_hinic3_flow_mutex); ++ return ret; ++ } ++ ++ pthread_mutex_unlock(&g_hinic3_flow_mutex); ++ return ret; ++} ++ ++void hinic3_flow_class_uninit(void) ++{ ++ hiovs_api_record* flow_api_record = hinic3_get_hiovs_api_record(); ++ memset(flow_api_record, 0, sizeof(hiovs_api_record) * HINIC3_FLOW_API_MAX); ++} ++ ++int hinic3_iface_global_cfg_set(struct hiovs_mirror_session_info *hiovs_session_info, ++ enum hinic3_global_cfg_arg_type type) ++{ ++ int ret; ++ uint32_t session_id; ++ uint8_t buf[GLOBAL_CFG_ARGS_SIZE]; ++ struct hinic3_nlattr set_nla; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_cfg_set, HINIC3_DRV_FUNC_NO_PTR); ++ ++ hinic3_nlattr_init(&set_nla, buf, GLOBAL_CFG_ARGS_SIZE); ++ ++ switch (type) { ++ case HINIC3_GLOBAL_CFG_ARG_MIRROR_SESSION_SET: ++ hinic3_nlattr_put_unspec(&set_nla, type, hiovs_session_info, sizeof(struct hiovs_mirror_session_info)); ++ break; ++ case HINIC3_GLOBAL_CFG_ARG_MIRROR_SESSION_DEL: ++ session_id = (uint32_t)hiovs_session_info->session_id; ++ hinic3_nlattr_put_u32(&set_nla, type, session_id); ++ break; ++ default: ++ break; ++ } ++ ++ ret = ops->hovs_global_cfg_set((struct nlattr *)set_nla.data, set_nla.used_len, ++ (struct nlattr *)set_nla.data, &set_nla.used_len); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_GLOBAL_CFG_SET, 1); ++ } ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_iface_high_priority_upcall_set(const uint16_t port_id, struct hinic3_high_priority_cfgs *cfgs) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_set_upcall_priority, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_port_mgmt_set_upcall_priority(port_id, cfgs->hovs_cfgs, cfgs->cfgs_len, 1); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 high priority upcall set fail, ret is %d", ret); ++ } ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_modify(const struct hinic3_dpif_flow *put, const struct hinic3_nlattr *args, size_t args_len) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ struct hovs_dpif_flow hovs_put = { 0 }; ++ ++ if (put == NULL || args == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_put pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_update, HINIC3_DRV_FUNC_NO_PTR); ++ ++ hovs_put.key = (struct nlattr *)put->key; ++ hovs_put.key_len = put->key_len; ++ hovs_put.mask = (struct nlattr *)put->mask; ++ hovs_put.mask_len = put->mask_len; ++ hovs_put.actions = (struct nlattr *)put->actions; ++ hovs_put.action_len = put->action_len; ++ hovs_put.mask_present = put->mask_present; ++ hovs_put.hw_ufid = put->hw_ufid; ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_MODIFY, ++ ops->hovs_flow_mgmt_update(&hovs_put, (struct nlattr *)args, args_len)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_flow_get_block_table_size(uint32_t *block_num) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (block_num == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_get_block_table_size block_num pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_block_table_size, HINIC3_DRV_FUNC_NO_PTR); ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_BLOCK_SIZE_GET, ++ ops->hovs_flow_mgmt_get_block_table_size(block_num)); ++ return hinic3_convert_error_code(ret); ++} ++ ++void hinic3_flow_set_block_version(uint32_t block_num, uint16_t block_id[], uint16_t block_version[], int result[]) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (block_id == NULL || block_version == NULL || result == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_set_block_version pointer parameter is NULL"); ++ return; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ if (ops->hovs_flow_mgmt_set_block_version == NULL) { ++ for (uint32_t index = 0; index < block_num; index++) { ++ result[index] = -1; ++ } ++ return; ++ } ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG_RET(HINIC3_FLOW_BLOCK_VERSION_SET, ++ ops->hovs_flow_mgmt_set_block_version(block_num, block_id, block_version, result)); ++} ++ ++int hinic3_flow_get_block_version(uint32_t block_num, uint16_t block_id[], uint16_t block_version[]) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (block_id == NULL || block_version == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_flow_get_block_version input pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_block_version, HINIC3_DRV_FUNC_NO_PTR); ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_BLOCK_VERSION_GET, ++ ops->hovs_flow_mgmt_get_block_version(block_num, block_id, block_version)); ++ return hinic3_convert_error_code(ret); ++} +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h +new file mode 100644 +index 0000000..ea409a7 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h +@@ -0,0 +1,112 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FLOW_INTERFACE_H ++#define HINIC3_FLOW_INTERFACE_H ++ ++#include ++#include ++#include "rte_common.h" ++#include "rte_pci.h" ++#include "hinic3_util.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_driver_public.h" ++#include "hiovs_api.h" ++#include "hinic3_message.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef DEBUG_MODE ++#define HINIC3_DEBUG_PRINT_FLOW_INFO ++#define HINIC3_DEBUG_PRINT_CT_OFFLOAD ++#endif ++ ++/* in a byte: ++ * bit 6-7: version ++ * bit 3-5: forward mode ++ * bit 0-2: permit mode ++ */ ++#define HINIC3_PERMIT_MODE_OFFSET 0U ++#define HINIC3_FORWARD_MODE_OFFSET 3U ++#define HINIC3_MODE_VERSION_OFFSET 6U ++#define HINIC3_DEFAULT_API_RECORD_INDEX 0 ++#define HINIC3_RTE_ETH_TYPE_MAX 2 ++ ++ ++typedef enum tag_hinic3_flow_api { ++ HINIC3_FLOW_AGENT_PUT = 0, ++ HINIC3_FLOW_AGENT_GET_BY_KEY, ++ HINIC3_FLOW_AGENT_GET_BY_UFID, ++ HINIC3_FLOW_AGENT_DEL_BY_UFID, ++ HINIC3_FLOW_AGENT_DEL_BATCH, ++ HINIC3_FLOW_AGENT_FLUSH, ++ HINIC3_FLOW_AGENT_DUMP_START, ++ HINIC3_FLOW_AGENT_DUMP_NEXT, ++ HINIC3_FLOW_AGENT_DUMP_DONE, ++ HINIC3_FLOW_AGENT_GET_MAXFLOWS, ++ HINIC3_FLOW_AGENT_GET_CAPABILITY, ++ HINIC3_FLOW_AGENT_SET_FORWARD_MODE, ++ HINIC3_FLOW_AGENT_GET_FORWARD_MODE, ++ HINIC3_STATISTICS_FLOW_GET_BY_UFID, ++ HINIC3_STATISTICS_FLOW_FLUSH_BY_UFID, ++ HINIC3_RTE_FLOW_CREATE, ++ HINIC3_RTE_FLOW_QUERY, ++ HINIC3_RTE_FLOW_DELETE, ++ HINIC3_RTE_FLOW_FLUAH_ALL, ++ HINIC3_RTE_FLOW_DESTROY_BY_BATCH, ++ HINIC3_RTE_FLOW_DUMP_START, ++ HINIC3_RTE_FLOW_DUMP_NEXT, ++ HINIC3_RTE_FLOW_DUMP_END, ++ HINIC3_FLOW_BLOCK_SIZE_GET, ++ HINIC3_FLOW_MODIFY, ++ HINIC3_FLOW_BLOCK_VERSION_SET, ++ HINIC3_FLOW_BLOCK_VERSION_GET, ++ HINIC3_FLOW_API_MAX, ++} hinic3_flow_api; ++ ++struct hinic3_high_priority_cfgs { ++ uint8_t cfgs_len; ++ struct hovs_high_priority_protocol_cfg hovs_cfgs[HINIC3_RTE_ETH_TYPE_MAX]; ++}; ++ ++int hinic3_flow_class_init(void); ++void hinic3_flow_class_uninit(void); ++int hinic3_flow_init(void); ++int hinic3_flow_get_api_record(const char *api_name, bool is_all, bool is_clear, hiovs_api_record *records, ++ int record_len); ++const char *hinic3_flow_get_api_name(hinic3_flow_api api_index); ++int hinic3_statistics_flow_get_by_ufid(const uint64_t *ufid, const size_t cnt, struct hinic3_flow_stats *stats); ++int hinic3_flow_get_forward_mode(uint8_t *forward_mode); ++int hinic3_flow_set_forward_mode(uint8_t forward_mode); ++int hinic3_flow_get_maxflows(uint32_t *max_flows); ++int hinic3_flow_dump_done(void *state); ++int hinic3_flow_dump_next(void *state, struct hinic3_dpif_flow_for_get *dump); ++int hinic3_flow_dump_start(void **state); ++int hinic3_flow_del_batch(const uint64_t *ufids, struct hinic3_dpif_flow_for_get **flows, const size_t cnt); ++int hinic3_flow_del_by_ufid(uint64_t ufid); ++int hinic3_flow_get_by_ufid(uint64_t ufid, struct hinic3_dpif_flow_for_get *get); ++int hinic3_flow_put(const struct hinic3_dpif_flow *put, const struct hinic3_nlattr *args, size_t args_len); ++int hinic3_flow_mgmt_get_by_key(const struct hinic3_nlattr *key, size_t key_len, struct hinic3_dpif_flow *get, ++ uint64_t g_get_flow_related_ufid); ++int hinic3_flow_get_capability(struct hinic3_flow_capability *cap); ++int hinic3_flow_flush(void); ++uint32_t hinic3_get_offload_thread_num(void); ++int hinic3_iface_global_cfg_set(struct hiovs_mirror_session_info *hiovs_session_info, ++ enum hinic3_global_cfg_arg_type type); ++int hinic3_iface_high_priority_upcall_set(const uint16_t port_id, struct hinic3_high_priority_cfgs *cfgs); ++uint32_t hinic3_get_offload_thread_num(void); ++hinic3_flow_api hinic3_flow_get_api_index(const char *api_name); ++int hinic3_process_dpif_flow_for_get_data(struct hovs_dpif_flow_for_get dump_for_get, ++ struct hinic3_dpif_flow_for_get *dump); ++int hinic3_flow_modify(const struct hinic3_dpif_flow *put, const struct hinic3_nlattr *args, size_t args_len); ++int hinic3_flow_get_block_table_size(uint32_t *block_num); ++void hinic3_flow_set_block_version(uint32_t block_num, uint16_t block_id[], uint16_t block_version[], int result[]); ++int hinic3_flow_get_block_version(uint32_t block_num, uint16_t block_id[], uint16_t block_version[]); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.c +new file mode 100644 +index 0000000..d7d901c +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.c +@@ -0,0 +1,122 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#include ++#include ++#include "rte_cycles.h" ++#include "hinic3_init.h" ++#include "hinic3_message.h" ++#include "hinic3_log.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_iface_flow_api_record.h" ++ ++hiovs_api_record g_flow_api_record[HINIC3_FLOW_API_MAX]; ++ ++void hinic3_flow_api_record_error(int ret_code, hinic3_flow_api api_index, uint64_t exec_time) ++{ ++ if (api_index >= HINIC3_FLOW_API_MAX) { ++ HINIC3_LOG(WARNING, FLOW, "flow api record error, api_index is %d more than max index %d.", api_index, ++ HINIC3_FLOW_API_MAX); ++ return; ++ } ++ ++ if (ret_code != 0) { ++ g_flow_api_record[api_index].call_error_count++; ++ g_flow_api_record[api_index].last_rtn_value = ret_code; ++ g_flow_api_record[api_index].time_error = time(NULL); ++ HINIC3_LOG(ERR, FLOW, "flow api record error, return %d, cost %" PRIu64 " us.", ret_code, exec_time); ++ } ++} ++ ++void hinic3_add_flow_api_record(hinic3_flow_api api_index, uint64_t exec_time) ++{ ++ if (api_index >= HINIC3_FLOW_API_MAX) { ++ HINIC3_LOG(WARNING, FLOW, "add flow api called record error, api_index is %d more than max index %d.", api_index, ++ HINIC3_FLOW_API_MAX); ++ return; ++ } ++ ++ g_flow_api_record[api_index].call_total_count++; ++ /* the total_api_time allows integer inversion and will not affect the function */ ++ g_flow_api_record[api_index].total_api_time += exec_time; ++ if (exec_time > g_flow_api_record[api_index].max_api_time) { ++ g_flow_api_record[api_index].max_api_time = exec_time; ++ } ++ if (exec_time < g_flow_api_record[api_index].min_api_time || g_flow_api_record[api_index].min_api_time == 0) { ++ g_flow_api_record[api_index].min_api_time = exec_time; ++ } ++} ++ ++void hinic3_flow_api_record_error_no_log(int ret_code, hinic3_flow_api api_index) ++{ ++ if (api_index >= HINIC3_FLOW_API_MAX) { ++ return; ++ } ++ if (ret_code != 0) { ++ g_flow_api_record[api_index].call_error_count++; ++ g_flow_api_record[api_index].last_rtn_value = ret_code; ++ g_flow_api_record[api_index].time_error = time(NULL); ++ } ++} ++ ++static int hinic3_flow_process_all_api_record(bool is_clear, hiovs_api_record *records, int record_len) ++{ ++ if (is_clear) { ++ memset(g_flow_api_record, 0, sizeof(hiovs_api_record) * HINIC3_FLOW_API_MAX); ++ return 0; ++ } ++ ++ if (records == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_flow_process_all_api_record point parameter err!"); ++ return -1; ++ } ++ ++ for (int i = 0; i < record_len && i < HINIC3_FLOW_API_MAX; ++i) { ++ records[i] = g_flow_api_record[i]; ++ } ++ return 0; ++} ++ ++static int hinic3_flow_process_single_api_record(const char *api_name, bool is_clear, hiovs_api_record *records) ++{ ++ hinic3_flow_api api_index = hinic3_flow_get_api_index(api_name); ++ if (api_index >= HINIC3_FLOW_API_MAX) { ++ return -1; ++ } ++ if (is_clear) { ++ memset(&g_flow_api_record[api_index], 0, sizeof(hiovs_api_record)); ++ return 0; ++ } ++ ++ if (records == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_flow_process_single_api_record point parameter err!"); ++ return -1; ++ } ++ ++ records[HINIC3_DEFAULT_API_RECORD_INDEX] = g_flow_api_record[api_index]; ++ return 0; ++} ++ ++ ++int hinic3_flow_get_api_record(const char *api_name, bool is_all, bool is_clear, hiovs_api_record *records, ++ int record_len) ++{ ++ if (api_name == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_flow_get_api_record point parameter err!"); ++ return -1; ++ } ++ ++ if (is_all) { ++ return hinic3_flow_process_all_api_record(is_clear, records, record_len); ++ } ++ ++ return hinic3_flow_process_single_api_record(api_name, is_clear, records); ++} ++ ++hiovs_api_record *hinic3_get_hiovs_api_record(void) ++{ ++ return g_flow_api_record; ++} +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.h +new file mode 100644 +index 0000000..bbb16d3 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow_api_record.h +@@ -0,0 +1,82 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_IFACE_FLOW_API_RECORD_H ++#define HINIC3_IFACE_FLOW_API_RECORD_H ++ ++#include "hinic3_iface_flow.h" ++ ++#define USEC_PER_SEC (1000000UL) ++ ++void hinic3_flow_api_record_error_no_log(int ret_code, hinic3_flow_api api_index); ++void hinic3_flow_api_record_error(int ret_code, hinic3_flow_api api_index, uint64_t exec_time); ++void hinic3_add_flow_api_record(hinic3_flow_api api_index, uint64_t exec_time); ++hiovs_api_record *hinic3_get_hiovs_api_record(void); ++ ++#define HINIC3_LOG_HINIC_FLOW_API_LOG(RET_CODE, API_INDEX, API_FUNC) \ ++ do { \ ++ uint64_t time_start = rte_get_tsc_cycles(); \ ++ RET_CODE = API_FUNC; \ ++ uint64_t exec_time = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ exec_time = ((rte_get_tsc_cycles() - time_start) * USEC_PER_SEC) / hz; \ ++ } \ ++ hinic3_add_flow_api_record(API_INDEX, exec_time); \ ++ hinic3_flow_api_record_error(RET_CODE, API_INDEX, exec_time); \ ++ } while (0) ++ ++#define HINIC3_LOG_HINIC_FLOW_API_LOG_WARN(RET_CODE, API_INDEX, API_FUNC) \ ++ do { \ ++ uint64_t time_start = rte_get_tsc_cycles(); \ ++ RET_CODE = API_FUNC; \ ++ uint64_t exec_time = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ exec_time = ((rte_get_tsc_cycles() - time_start) * USEC_PER_SEC) / hz; \ ++ } \ ++ hinic3_add_flow_api_record(API_INDEX, exec_time); \ ++ hinic3_flow_api_record_error(RET_CODE, API_INDEX, exec_time); \ ++ } while (0) ++ ++#define HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(RET_CODE, API_INDEX, API_FUNC) \ ++ do { \ ++ uint64_t time_start = rte_get_tsc_cycles(); \ ++ RET_CODE = API_FUNC; \ ++ uint64_t exec_time = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ exec_time = ((rte_get_tsc_cycles() - time_start) * USEC_PER_SEC) / hz; \ ++ } \ ++ hinic3_add_flow_api_record(API_INDEX, exec_time); \ ++ hinic3_flow_api_record_error_no_log(RET_CODE, API_INDEX); \ ++ } while (0) ++ ++#define HINIC3_LOG_HINIC_FLOW_ISNULL_API_LOG_NO_LOG(RET_CODE, API_INDEX, API_FUNC) \ ++ do { \ ++ uint64_t time_start = rte_get_tsc_cycles(); \ ++ RET_CODE = API_FUNC; \ ++ uint64_t exec_time = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ exec_time = ((rte_get_tsc_cycles() - time_start) * USEC_PER_SEC) / hz; \ ++ } \ ++ hinic3_add_flow_api_record(API_INDEX, exec_time); \ ++ hinic3_flow_api_record_error_no_log(((RET_CODE) == NULL), API_INDEX); \ ++ } while (0) ++ ++#define HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG_RET(API_INDEX, API_FUNC) \ ++ do { \ ++ uint64_t time_start = rte_get_tsc_cycles(); \ ++ API_FUNC; \ ++ uint64_t exec_time = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ exec_time = ((rte_get_tsc_cycles() - time_start) * USEC_PER_SEC) / hz; \ ++ } \ ++ hinic3_add_flow_api_record(API_INDEX, exec_time); \ ++ hinic3_flow_api_record_error_no_log(0, API_INDEX); \ ++ } while (0) ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +new file mode 100644 +index 0000000..c292fc6 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +@@ -0,0 +1,1560 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_ether.h" ++#include "rte_lcore.h" ++#include "rte_malloc.h" ++#include "hinic3_packets.h" ++#include "hinic3_init.h" ++#include "hinic3_log.h" ++#include "hinic3_provider.h" ++#include "hinic3_message.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_util.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_hugepage_meminfo.h" ++#include "hinic3_smap.h" ++#include "hinic3_ds.h" ++#include "hinic3_iface_global.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#endif ++#include "hinic3_command.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_iface_global_api_record.h" ++#include "hinic3_port_util.h" ++ ++#define MAX_ARGS_SIZE (2048) ++#define MAX_KEY_VAL_LEN (64) ++#define DEFAULT_LOCAL_IP "0.0.0.0" ++#define DEFAULT_ZERO_VALUE "0" ++#define GLOBAL_ARGS_SIZE (128) ++#define HINIC3_IO_MODE_LEN (10) ++#define VLAN_HEADER_LEN 4 ++#define NETDEV_DPDK_MBUF_ALIGN 1024 ++#define DEFAULT_MTU 1500 ++#define HINIC3_DEC_BASE 10 ++#define HINIC3_HIGH_BANDWIDTH_MODE_ADAPTE 2 ++ ++/* ++ * PF upcall queue depth. ++ * PF4 has 64 queues with a single queue depth of 1024 . ++ * PF5 has 256 queues with a single queue depth of 512 . ++ * Reserve 1024 * 64 mbufs for command delivery. ++ */ ++#define HINIC3_VTEP_TABLE_MAX_IP_ADDR 8 ++ ++#define SHOW_ONE_API_ARG_NUM 2 ++#define CLEAR_GLOBAL_API_ARG_NUM 2 ++#define SHOW_MAX_API_ONE_LINE 4 ++#define SHOW_GLOBAL_API_UI_TWO_SPACE 2 ++#define SHOW_GLOBAL_API_UI_FOUR_SPACE 4 ++#define SHOW_GLOBAL_API_UI_SIX_SPACE 6 ++ ++/* hardware global args flag */ ++#define HINIC3_FLAG_RX_THREAD_NUM (1LLU << 0) ++#define HINIC3_FLAG_MAX_FLOW_NUM (1LLU << 1) ++#define RTE_DP_PACKETS_SIZE 1152 ++#define HINIC3_PMD_NUM_DEFAULT 2 ++#define HINIC3_FLOW_UNAGE_FLAG "1" ++#define HINIC3_FLOW_AGE_FLAG "0" ++#define VLAN_HEADER_COUNT 2 ++#define HINIC3_FORWARD_MODE_BUFFER_LEN 64 ++#define HINIC3_BOND_HASH_POLICY_LEN 64 ++ ++struct hinic3_vtep_ip_get_args { ++ uint32_t num; ++ struct hinic3_vtep_ip dip[HINIC3_VTEP_TABLE_MAX_IP_ADDR]; ++}; ++ ++struct hiovs_global_map { ++ hinic3_global_api api_index; ++ const char *api_name; ++}; ++ ++static pthread_mutex_t g_hinic3_global_mutex = PTHREAD_MUTEX_INITIALIZER; ++static rte_spinlock_t g_hinic3_tx_burst_lock[MAX_TX_QUEUE_PER_VPORT]; ++ ++static volatile struct rte_mempool *g_dpdk_shared_mp = NULL; ++/* hardware global args set flag */ ++static uint64_t g_global_args_flag = 0; ++// please modify hinic3_global_api when modify this structure ++static const struct hiovs_global_map g_global_api_arr[HINIC3_GLOBAL_API_MAX] = { ++ { HINIC3_GLOBAL_CFG_SET, "hovs_global_cfg_set" }, ++ { HINIC3_GLOBAL_CFG_GET, "hovs_global_cfg_get" }, ++ { HINIC3_GLOBAL_STATISTICS_GET, "hovs_global_statistics_get" }, ++ { HINIC3_GLOBAL_STATISTICS_FLUSH, "hovs_global_statistics_flush" }, ++ { HINIC3_GLOBAL_OPEN_LOG, "hovs_open_log" }, ++ { HINIC3_GLOBAL_SET_LOG_LEVEL, "hovs_set_log_level" }, ++ { HINIC3_GLOBAL_CMD_EXEC, "hovs_mml_lib" }, ++ { HINIC3_GLOBAL_PCIE_LIST_QUERY, "hovs_global_pcie_list_query" }, ++}; ++ ++struct hovs_global_api_func_map { ++ hinic3_global_api api_index; ++ int (*func)(struct hinic_global_api_args *args); ++}; ++ ++static int hovs_global_cfg_set_wrapper(struct hinic_global_api_args *args) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_cfg_set, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_global_cfg_set(args->in_nlattr_data, args->in_nlattr_len, args->out_nlattr_data, ++ args->out_nlattr_len); ++} ++ ++static int hovs_global_cfg_get_wrapper(struct hinic_global_api_args *args) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_cfg_get, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_global_cfg_get(args->out_nlattr_data, args->out_nlattr_len); ++} ++ ++static int hovs_global_statistics_get_wrapper(struct hinic_global_api_args *args) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_statistics_get, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_global_statistics_get(args->hovs_stats); ++} ++ ++static int hovs_global_statistics_flush_wrapper(struct hinic_global_api_args *args __rte_unused) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_statistics_flush, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_global_statistics_flush(); ++} ++ ++static int hovs_open_log_wrapper(struct hinic_global_api_args *args) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_open_log, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_open_log(args->log_module, args->log_level_or_enable); ++} ++ ++static int hovs_set_log_level_wrapper(struct hinic_global_api_args *args) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_set_log_level, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_set_log_level(args->log_module, args->log_level_or_enable); ++} ++static int hovs_mml_lib_wrapper(struct hinic_global_api_args *args) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_mml_lib, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_mml_lib(args->cmd_in, args->cmd_in_len, args->cmd_out, args->cmd_out_len, args->cmd_out_buf_size); ++} ++ ++static int hovs_global_pcie_list_query_wrapper(struct hinic_global_api_args *args) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_pcie_list_query, HINIC3_DRV_FUNC_NO_PTR); ++ return ops->hovs_global_pcie_list_query(args->front_back, args->bdf_type, args->dev); ++} ++ ++struct hovs_global_api_func_map hovs_global_api_func_map_array[] = { ++ {HINIC3_GLOBAL_CFG_SET, hovs_global_cfg_set_wrapper}, ++ {HINIC3_GLOBAL_CFG_GET, hovs_global_cfg_get_wrapper}, ++ {HINIC3_GLOBAL_STATISTICS_GET, hovs_global_statistics_get_wrapper}, ++ {HINIC3_GLOBAL_STATISTICS_FLUSH, hovs_global_statistics_flush_wrapper}, ++ {HINIC3_GLOBAL_OPEN_LOG, hovs_open_log_wrapper}, ++ {HINIC3_GLOBAL_SET_LOG_LEVEL, hovs_set_log_level_wrapper}, ++ {HINIC3_GLOBAL_CMD_EXEC, hovs_mml_lib_wrapper}, ++ {HINIC3_GLOBAL_PCIE_LIST_QUERY, hovs_global_pcie_list_query_wrapper}, ++}; ++ ++static int hinic3_log_hinic_global_api_log(hinic3_global_api api_index, struct hinic_global_api_args *args) ++{ ++ int ret = -1; ++ uint64_t time_start; ++ uint64_t exec_time = 0; ++ ++ if (api_index >= HINIC3_GLOBAL_CFG_SET && api_index < HINIC3_GLOBAL_API_MAX) { ++ time_start = rte_get_tsc_cycles(); ++ ++ ret = hovs_global_api_func_map_array[api_index].func(args); ++ uint64_t hz = rte_get_tsc_hz(); ++ if (hz != 0) { ++ exec_time = ((rte_get_tsc_cycles() - time_start) * 1000000UL) / hz; ++ } ++ hinic_global_fill_api_record(api_index, exec_time); ++ hinic_global_api_record_error(ret, api_index, exec_time); ++ } ++ return ret; ++} ++ ++static int global_cfg_parse_action(const char *action, uint8_t *val) ++{ ++ if (strncmp(action, GLOBAL_CFG_ACTION_DROP_STR, strlen(action) + 1) == 0) { ++ *val = GLOBAL_CFG_ACTION_DROP; ++ } else if (strncmp(action, GLOBAL_CFG_ACTION_UPCALL_STR, strlen(action) + 1) == 0) { ++ *val = GLOBAL_CFG_ACTION_UPCALL; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static char *global_cfg_action_stringfy(uint8_t val) ++{ ++ if (val == GLOBAL_CFG_ACTION_DROP) { ++ return GLOBAL_CFG_ACTION_DROP_STR; ++ } else if (val == GLOBAL_CFG_ACTION_UPCALL) { ++ return GLOBAL_CFG_ACTION_UPCALL_STR; ++ } ++ ++ return NULL; ++} ++ ++ ++static char *global_cfg_unage_flag_stringfy(uint8_t val) ++{ ++ if (val == 1) { ++ return HINIC3_FLOW_UNAGE_FLAG; ++ } else if (val == 0) { ++ return HINIC3_FLOW_AGE_FLAG; ++ } ++ ++ return NULL; ++} ++ ++static int global_cfg_parse_thread_mode(const char *mode, uint8_t *val) ++{ ++ if (strncmp(mode, GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN_STR, strlen(mode) + 1) == 0) { ++ *val = GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN; ++ } else if (strncmp(mode, GLOBAL_CFG_THREAD_MODE_INTERRUPT_STR, strlen(mode) + 1) == 0) { ++ *val = GLOBAL_CFG_THREAD_MODE_INTERRUPT; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int global_cfg_parse_pmd_mode(const char *mode, uint8_t *val) ++{ ++ if (strncmp(mode, HINIC3_GLOBAL_CFG_ARG_PMD_MODE_STOP_STR, strlen(mode) + 1) == 0) { ++ *val = GLOBAL_CFG_PMD_MODE_STOP; ++ } else if (strncmp(mode, HINIC3_GLOBAL_CFG_ARG_PMD_MODE_START_STR, strlen(mode) + 1) == 0) { ++ *val = GLOBAL_CFG_PMD_MODE_START; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static char *global_cfg_thread_mode_stringfy(uint8_t val) ++{ ++ if (val == GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN) { ++ return GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN_STR; ++ } else if (val == GLOBAL_CFG_THREAD_MODE_INTERRUPT) { ++ return GLOBAL_CFG_THREAD_MODE_INTERRUPT_STR; ++ } ++ ++ return NULL; ++} ++ ++static int global_cfg_parse_action_check_mode(const char *mode, uint8_t *val) ++{ ++ if (strncmp(mode, HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_ON_STR, strlen(mode) + 1) == 0) { ++ *val = GLOBAL_ACTION_CHECK_ON; ++ } else if (strncmp(mode, HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_OFF_STR, strlen(mode) + 1) == 0) { ++ *val = GLOBAL_ACTION_CHECK_OFF; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static char *g_global_smap_key[HINIC3_GLOBAL_CFG_ARG_TYPE_MAX] = { ++ HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE_STR, ++ HINIC3_GLOBAL_CFG_ARG_RSS_VF_NUM_STR, ++ HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP_STR, ++ HINIC3_GLOBAL_CFG_ARG_PCI_VENDOR_ID_STR, ++ HINIC3_GLOBAL_CFG_ARG_PCI_DEVICE_ID_STR, ++ HINIC3_GLOBAL_CFG_ARG_PCI_SUB_VENDOR_ID_STR, ++ HINIC3_GLOBAL_CFG_ARG_PCI_SUB_DEVICE_ID_STR, ++ NULL, ++ HINIC3_GLOBAL_CFG_ARG_INVALID_TCP_ACTION_STR, ++ HINIC3_GLOBAL_CFG_ARG_IP_FRAG_ACTION_STR, ++ HINIC3_GLOBAL_CFG_ARG_THREAD_MODE_STR, ++ HINIC3_GLOBAL_CFG_ARG_FLOW_AGE_TIME_STR, ++ HINIC3_GLOBAL_CFG_ARG_PTHREAD_FDS_STR, ++ NULL, ++ HINIC3_GLOBAL_CFG_ARG_VF_INFO_STR, ++ HINIC3_GLOBAL_CFG_ARG_VF_ENABLE_STR, ++ HINIC3_GLOBAL_CFG_ARG_PMD_MODE_STR, ++ HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE_STR, ++ HINIC3_GLOBAL_GET_PCAP_PROBE_STATS_STR, ++ HINIC3_GLOBAL_CFG_ARG_ETP_STR, ++ HINIC3_GLOBAL_GET_ETP_STATS_STR, ++ HINIC3_GLOBAL_CFG_ARG_PHY_DEV_INFO_STR, ++ HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_STR, ++ HINIC3_GLOBAL_CFG_ARG_QUEUE_POOL_SIZE_STR, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ HINIC3_GLOBAL_CFG_UNAGE_FLAG_STR, ++ NULL, ++ HINIC3_GLOBAL_CFG_PKT_FORWARD_MOD_STR, ++}; ++ ++static enum hinic3_global_cfg_arg_type get_nl_type_by_smap_key(char *key) ++{ ++ int i; ++ for (i = 0; i < HINIC3_GLOBAL_CFG_ARG_TYPE_MAX; i++) { ++ if (g_global_smap_key[i] && strncmp(key, g_global_smap_key[i], strlen(key) + 1) == 0) { ++ break; ++ } ++ } ++ ++ return (enum hinic3_global_cfg_arg_type)i; ++} ++ ++static void handle_nl_put_unspec(struct hinic3_nlattr *nla, enum hinic3_global_cfg_arg_type type, char *value) ++{ ++ size_t size = strlen(value) + 1; ++ hinic3_nlattr_put_unspec(nla, type, value, size); ++} ++ ++static int handle_nl_put_u8(struct hinic3_nlattr *nla, enum hinic3_global_cfg_arg_type type, char *value) ++{ ++ uint8_t val = 0; ++ int ret = 0; ++ char *end_ptr = NULL; ++ ++ if (type == HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE && ++ strncmp(value, GLOBAL_VLAN_ETHTYPE_8021Q_STR, strlen(value) + 1) != 0) { ++ val = GLOBAL_VLAN_ETHTYPE_8021Q; ++ ret = 0; ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_INVALID_TCP_ACTION || type == HINIC3_GLOBAL_CFG_ARG_IP_FRAG_ACTION) { ++ ret = global_cfg_parse_action(value, &val); ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_THREAD_MODE) { ++ ret = global_cfg_parse_thread_mode(value, &val); ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_PMD_MODE) { ++ ret = global_cfg_parse_pmd_mode(value, &val); ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_ACTION_CHECKING) { ++ ret = global_cfg_parse_action_check_mode(value, &val); ++ } else if (type == HINIC3_GLOBAL_CFG_UNAGE_FLAG) { ++ val = (uint8_t)strtol(value, &end_ptr, HINIC3_DEC_BASE); ++ if (end_ptr == value || end_ptr == NULL) { ++ HINIC3_LOG(ERR, AGENT, " strtol in global unage cfg failed"); ++ ret = -1; ++ } ++ } ++ ++ if (ret != 0) { ++ return -1; ++ } ++ ++ return hinic3_nlattr_put_u8(nla, type, val); ++} ++ ++static int handle_nl_put_u32(struct hinic3_nlattr *nla, enum hinic3_global_cfg_arg_type type, char *value) ++{ ++ uint32_t val = 0; ++ int ret; ++ ++ if (type == HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP) { ++ ret = inet_pton(AF_INET, value, &val); ++ /* inet_pton return 1 when success ++ * return 0 when address is invaild ++ * return -1 when str format error ++ */ ++ if (ret <= 0) { ++ return -1; ++ } ++ } else { ++ ret = parse_str_to_value(value, &val); ++ if (ret != 0) { ++ return -1; ++ } ++ } ++ ++ hinic3_nlattr_put_u32(nla, type, val); ++ return 0; ++} ++ ++static int global_smap_to_nlattr(struct hinic3_nlattr *nla, enum hinic3_global_cfg_arg_type nl_type, char *value) ++{ ++ switch (nl_type) { ++ case HINIC3_GLOBAL_CFG_ARG_VF_INFO: ++ case HINIC3_GLOBAL_CFG_ARG_RSS_VF_NUM: ++ case HINIC3_GLOBAL_CFG_ARG_VF_ENABLE: ++ case HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE: ++ case HINIC3_GLOBAL_CFG_ARG_ETP: ++ case HINIC3_GLOBAL_CFG_ARG_QUEUE_POOL_SIZE: ++ handle_nl_put_unspec(nla, nl_type, value); ++ break; ++ case HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE: ++ case HINIC3_GLOBAL_CFG_ARG_INVALID_TCP_ACTION: ++ case HINIC3_GLOBAL_CFG_ARG_IP_FRAG_ACTION: ++ case HINIC3_GLOBAL_CFG_ARG_THREAD_MODE: ++ case HINIC3_GLOBAL_CFG_ARG_PMD_MODE: ++ case HINIC3_GLOBAL_CFG_ARG_ACTION_CHECKING: ++ case HINIC3_GLOBAL_CFG_UNAGE_FLAG: ++ case HINIC3_GLOBAL_CFG_ARG_LATENCY_MOD: ++ return handle_nl_put_u8(nla, nl_type, value); ++ case HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_VENDOR_ID: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_DEVICE_ID: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_SUB_VENDOR_ID: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_SUB_DEVICE_ID: ++ case HINIC3_GLOBAL_CFG_ARG_FLOW_AGE_TIME: ++ return handle_nl_put_u32(nla, nl_type, value); ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++ ++static int global_cfg_smap_to_nlattr(const struct smap *args, struct hinic3_nlattr *args_nla) ++{ ++ int ret; ++ struct smap_node *node = NULL; ++ enum hinic3_global_cfg_arg_type nl_type; ++ ++ HINIC3_SMAP_FOR_EACH(node, args) { ++ nl_type = get_nl_type_by_smap_key(node->key); ++ if (nl_type == HINIC3_GLOBAL_CFG_ARG_TYPE_MAX) { ++ continue; ++ } ++ ret = global_smap_to_nlattr(args_nla, nl_type, node->value); ++ if (ret != 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int nla_to_smap_u8(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++{ ++ uint8_t val = hinic3_nlattr_get_itr_u8(nla); ++ int type = hinic3_nlattr_get_itr_type(nla); ++ char *smap_value = NULL; ++ ++ if (type == HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE) { ++ if (val == GLOBAL_VLAN_ETHTYPE_8021Q) { ++ smap_value = GLOBAL_VLAN_ETHTYPE_8021Q_STR; ++ } ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_INVALID_TCP_ACTION) { ++ smap_value = global_cfg_action_stringfy(val); ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_IP_FRAG_ACTION) { ++ smap_value = global_cfg_action_stringfy(val); ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_THREAD_MODE) { ++ smap_value = global_cfg_thread_mode_stringfy(val); ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_ACTION_CHECKING) { ++ if (val == GLOBAL_ACTION_CHECK_ON) { ++ smap_value = HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_ON_STR; ++ } else if (val == GLOBAL_ACTION_CHECK_OFF) { ++ smap_value = HINIC3_GLOBAL_CFG_UPCALL_PUSH_VXLAN_OFF_STR; ++ } ++ } else if (type == HINIC3_GLOBAL_CFG_UNAGE_FLAG) { ++ smap_value = global_cfg_unage_flag_stringfy(val); ++ } else if (type == HINIC3_GLOBAL_CFG_ARG_LATENCY_MOD) { ++ if (val == 0 || val == HINIC3_HIGH_BANDWIDTH_MODE_ADAPTE) { ++ smap_value = HINIC3_GLOBAL_CFG_PKT_HIGH_THROUGH_STR; ++ } else if (val == 1) { ++ smap_value = HINIC3_GLOBAL_CFG_PKT_LOW_LATENCY_MOD_STR; ++ } ++ } ++ ++ if (smap_value == NULL) { ++ return -1; ++ } ++ ++ hinic3_smap_add(args, key, smap_value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static int nla_to_smap_u16(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++{ ++ char *value = NULL; ++ char value_buf[MAX_ARGS_SIZE] = { 0 }; ++ ++ snprintf(value_buf, sizeof(value_buf) - 1, "%hu", hinic3_nlattr_get_itr_u16(nla)); ++ value = value_buf; ++ hinic3_smap_add(args, key, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static int nla_to_smap_u32(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++{ ++ char *value = NULL; ++ char value_buf[MAX_ARGS_SIZE] = { 0 }; ++ uint32_t val = hinic3_nlattr_get_itr_u32(nla); ++ int type = hinic3_nlattr_get_itr_type(nla); ++ ++ if (type == HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP) { ++ inet_ntop(AF_INET, &val, value_buf, INET_ADDRSTRLEN); ++ } else { ++ snprintf(value_buf, sizeof(value_buf) - 1, "%x", val); ++ } ++ value = value_buf; ++ hinic3_smap_add(args, key, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static int nla_to_smap_raw(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++{ ++ char *value = NULL; ++ char value_buf[MAX_ARGS_SIZE] = { 0 }; ++ int type = hinic3_nlattr_get_itr_type(nla); ++ const int *int_p = NULL; ++ enum SMAP_PTR_INDEX { ++ HEAD_PTR, ++ MID_PTR, ++ TAIL_PTR ++ }; ++ ++ if (type == HINIC3_GLOBAL_CFG_ARG_PTHREAD_FDS) { ++ int_p = hinic3_nlattr_get_itr_data(nla); ++ snprintf(value_buf, sizeof(value_buf) - 1, "%d,%d,%d", int_p[0], int_p[MID_PTR], int_p[TAIL_PTR]); ++ } ++ ++ value = value_buf; ++ hinic3_smap_add(args, key, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static char *global_smap_key_from_nla_type(uint32_t type) ++{ ++ if (type >= HINIC3_GLOBAL_CFG_ARG_TYPE_MAX) { ++ return NULL; ++ } ++ ++ return g_global_smap_key[type]; ++} ++ ++static int global_nla_to_smap(const hinic3_nlattr_itr nla_itr, struct smap *args, char *key) ++{ ++ const char *vf_info = NULL; ++ ++ switch (hinic3_nlattr_get_itr_type(nla_itr)) { ++ case HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE: ++ case HINIC3_GLOBAL_CFG_ARG_INVALID_TCP_ACTION: ++ case HINIC3_GLOBAL_CFG_ARG_IP_FRAG_ACTION: ++ case HINIC3_GLOBAL_CFG_ARG_THREAD_MODE: ++ case HINIC3_GLOBAL_CFG_ARG_ACTION_CHECKING: ++ case HINIC3_GLOBAL_CFG_UNAGE_FLAG: ++ case HINIC3_GLOBAL_CFG_ARG_LATENCY_MOD: ++ return nla_to_smap_u8(args, nla_itr, key); ++ case HINIC3_GLOBAL_CFG_ARG_RSS_VF_NUM: ++ case HINIC3_GLOBAL_CFG_ARG_QUEUE_POOL_SIZE: ++ return nla_to_smap_u16(args, nla_itr, key); ++ case HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_VENDOR_ID: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_DEVICE_ID: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_SUB_VENDOR_ID: ++ case HINIC3_GLOBAL_CFG_ARG_PCI_SUB_DEVICE_ID: ++ case HINIC3_GLOBAL_CFG_ARG_FLOW_AGE_TIME: ++ return nla_to_smap_u32(args, nla_itr, key); ++ case HINIC3_GLOBAL_CFG_ARG_PTHREAD_FDS: ++ case HINIC3_GLOBAL_GET_PCAP_PROBE_STATS: ++ case HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE: ++ case HINIC3_GLOBAL_GET_ETP_STATS: ++ case HINIC3_GLOBAL_CFG_ARG_ETP: ++ return nla_to_smap_raw(args, nla_itr, key); ++ case HINIC3_GLOBAL_CFG_ARG_VF_INFO: ++ vf_info = hinic3_nlattr_get_itr_string(nla_itr); ++ hinic3_smap_add(args, HINIC3_GLOBAL_CFG_ARG_VF_INFO_STR, HINIC3_CONST_CAST(char *, vf_info), ++ HINIC3_DRIVER_ADAPTER); ++ break; ++ case HINIC3_GLOBAL_CFG_ARG_PHY_DEV_INFO: ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int global_cfg_nlattr_to_smap(const struct hinic3_nlattr *args_nla, struct smap *args) ++{ ++ hinic3_nlattr_itr nla_itr = NULL; ++ char *key = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH(nla_itr, args_nla) { ++ if (hinic3_nlattr_get_itr_size(nla_itr) == 0) { ++ continue; ++ } ++ ++ key = global_smap_key_from_nla_type(hinic3_nlattr_get_itr_type(nla_itr)); ++ if (key == NULL) { ++ continue; ++ } ++ ++ if (global_nla_to_smap(nla_itr, args, key) != 0) { ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++hinic3_global_api hinic3_global_get_api_index(const char *api_name) ++{ ++ int i; ++ for (i = 0; i < HINIC3_GLOBAL_API_MAX; ++i) { ++ if (strncmp(api_name, g_global_api_arr[i].api_name, strlen(g_global_api_arr[i].api_name) + 1) == 0) { ++ return g_global_api_arr[i].api_index; ++ } ++ } ++ return HINIC3_GLOBAL_API_MAX; ++} ++ ++static void hinic3_lib_arg_init(struct rte_mempool *mempool, uint32_t data_room_size, struct hiovs_lib_arg *arg) ++{ ++ arg->mempool = mempool; ++ arg->mode = HIOVS_DPDK_MODE; ++ arg->role = 1; ++ arg->state = 1; ++ arg->work_mode = hinic3_hiovs_mode_get(); ++ arg->flow_num = hinic3_max_flow_num_get(); ++ arg->rx_thread_num = hinic3_offload_thread_num_get(); ++ arg->data_room_size = data_room_size; ++ arg->cb_ops.hovs_malloc = hinic3_adapt_malloc; ++ arg->cb_ops.hovs_mfree = hinic3_adapt_mfree; ++ arg->cb_ops.hovs_mbuf_alloc = hinic3_adapt_mbuf_alloc; ++ arg->cb_ops.hovs_mbuf_alloc_bulk = hinic3_adapt_mbuf_alloc_bulk; ++ arg->cb_ops.hovs_mbuf_free = hinic3_adapt_mbuf_free; ++ arg->ext_cb_ops.hovs_malloc_socket = hinic3_adapt_malloc_socket; ++ arg->ext_cb_ops.hovs_free = hinic3_adapt_free; ++ arg->ext_cb_ops.hovs_memzone_reserve = hinic3_adapt_memzone_reserve; ++ arg->ext_cb_ops.hovs_memzone_reserve_aligned = hinic3_adapt_memzone_reserve_aligned; ++ arg->ext_cb_ops.hovs_memzone_free = hinic3_adapt_memzone_free; ++ arg->bond_rx_depth = hinic3_bond_rx_depth_get(); ++ arg->bond_tx_depth = hinic3_bond_tx_depth_get(); ++ arg->vport_rx_depth = hinic3_vport_rx_depth(); ++ arg->vport_tx_depth = hinic3_vport_tx_depth(); ++ arg->ext_cb_flag = 1; ++ arg->ext_mp_flag = 1; ++ arg->rsvd0[0] = 1; ++} ++ ++static int hinic3_global_init(struct rte_mempool *mempool, uint32_t data_room_size) ++{ ++ struct hiovs_lib_arg arg; ++ struct hinic3_drv_ops *ops = NULL; ++ uint64_t time_start; ++ uint64_t exec_time = 0; ++ int ret; ++ ++ memset(&arg, 0, sizeof(struct hiovs_lib_arg)); ++ ++ /* hinic lib just only support DPDK MODE */ ++ memset(&arg, 0, sizeof(arg)); ++ hinic3_lib_arg_init(mempool, data_room_size, &arg); ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_lib_init, HINIC3_DRV_FUNC_NO_PTR); ++ time_start = rte_get_tsc_cycles(); ++ ret = ops->hovs_lib_init((void *)(&arg)); ++ uint64_t hz = rte_get_tsc_hz(); ++ if (hz != 0) { ++ exec_time = ((rte_get_tsc_cycles() - time_start) * 1000000UL) / hz; ++ } ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic HWAPI %s called, return %d, cost %" PRIu64 " us.", __FUNCTION__, ret, exec_time); ++ } else { ++ g_global_args_flag |= HINIC3_FLAG_RX_THREAD_NUM; ++ g_global_args_flag |= HINIC3_FLAG_MAX_FLOW_NUM; ++ HINIC3_LOG(WARNING, AGENT, "hinic HWAPI %s called, return %d, cost %"PRIu64"us.", __FUNCTION__, ret, exec_time); ++ } ++ return ret; ++} ++ ++void hinic3_global_unit(void) ++{ ++ struct hiovs_lib_arg arg; ++ struct hinic3_drv_ops *ops = NULL; ++ uint64_t time_start; ++ uint64_t exec_time = 0; ++ uint32_t old_role_arg = 1; ++ ++ /* * ++ * Wait for all other threads to know hinic3 lib uninit ++ * This step must be done after hinic3_flow and hinic3_port uninit ++ * no finished ++ */ ++ ops = hinic3_get_drv_ops(); ++ if (ops->hovs_lib_deinit == NULL) { ++ HINIC3_LOG(ERR, AGENT, "there is no hovs_lib_deinit ptr"); ++ return; ++ } ++ ++ memset(&arg, 0, sizeof(struct hiovs_lib_arg)); ++ /* just set role and state */ ++ arg.role = old_role_arg; ++ arg.state = 1; ++ time_start = rte_get_tsc_cycles(); ++ ops->hovs_lib_deinit((void *)(&arg)); ++ uint64_t hz = rte_get_tsc_hz(); ++ if (hz != 0) { ++ exec_time = ((rte_get_tsc_cycles() - time_start) * 1000000UL) / hz; ++ } ++ HINIC3_LOG(WARNING, AGENT, "hinic HWAPI hinic3_global_unit called, return void, cost %" PRIu64 " us.", exec_time); ++ ++ if (g_dpdk_shared_mp != NULL) { ++ rte_mempool_free((struct rte_mempool *)g_dpdk_shared_mp); ++ g_dpdk_shared_mp = NULL; ++ } ++} ++ ++int hinic3_global_cfg_set(const struct smap *args, struct smap *unset_args) ++{ ++ int ret; ++ void *buff = NULL; ++ void *reply_buff = NULL; ++ void *tmp_buff = NULL; ++ struct hinic3_nlattr set_args_nla; ++ struct hinic3_nlattr unset_args_nla; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ if (args == NULL || unset_args == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "pointer parameter is NULL"); ++ return -1; ++ } ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (buff == NULL) { ++ return -1; ++ } ++ ++ reply_buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (reply_buff == NULL) { ++ hinic3_free(buff); ++ return -1; ++ } ++ ++ tmp_buff = buff; ++ hinic3_nlattr_init(&set_args_nla, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ tmp_buff = reply_buff; ++ hinic3_nlattr_init(&unset_args_nla, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ ++ /* struct smap to hinic3_nlattr */ ++ ret = global_cfg_smap_to_nlattr(args, &set_args_nla); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "call global_cfg_smap_to_nlattr error!"); ++ goto err; ++ } ++ ++ if (set_args_nla.used_len == 0) { ++ goto err; ++ } ++ ++ api_args.in_nlattr_data = set_args_nla.data; ++ api_args.in_nlattr_len = set_args_nla.used_len; ++ api_args.out_nlattr_data = unset_args_nla.data; ++ api_args.out_nlattr_len = &unset_args_nla.used_len; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_CFG_SET, &api_args); ++ if (ret != 0) { ++ goto err; ++ } ++ hinic3_nlattr_reset_itr(&unset_args_nla, unset_args_nla.used_len); ++ /* hinic3_nlattr to struct smap */ ++ ret = global_cfg_nlattr_to_smap(&unset_args_nla, unset_args); ++ ++err: ++ hinic3_free(buff); ++ hinic3_free(reply_buff); ++ return ret; ++} ++ ++int hinic3_global_cfg_get(struct smap *args) ++{ ++ int ret; ++ void *buff = NULL; ++ void *tmp_buff = NULL; ++ struct hinic3_nlattr args_nla; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ if (args == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "pointer parameter is NULL"); ++ return -1; ++ } ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (buff == NULL) { ++ HINIC3_LOG(ERR, AGENT, "alloc memory error"); ++ return -1; ++ } ++ ++ tmp_buff = buff; ++ hinic3_nlattr_init(&args_nla, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ /* struct smap to hinic3_nlattr */ ++ ret = global_cfg_smap_to_nlattr(args, &args_nla); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "call global_cfg_smap_to_nlattr error!"); ++ goto err; ++ } ++ ++ api_args.out_nlattr_data = args_nla.data; ++ api_args.out_nlattr_len = &args_nla.used_len; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_CFG_GET, &api_args); ++ if (ret != 0) { ++ goto err; ++ } ++ ++ hinic3_smap_clear(args); ++ hinic3_nlattr_reset_itr(&args_nla, args_nla.used_len); ++ /* hinic3_nlattr to struct smap */ ++ ret = global_cfg_nlattr_to_smap(&args_nla, args); ++ ++err: ++ hinic3_free(buff); ++ return ret; ++} ++ ++int hinic3_global_statistics_get(struct hinic3_global_stats *stats) ++{ ++ int ret; ++ struct hovs_global_stats hovs_stats = { 0 }; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ if (stats == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "pointer parameter is NULL"); ++ return -1; ++ } ++ ++ api_args.hovs_stats = &hovs_stats; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_STATISTICS_GET, &api_args); ++ if (ret != 0) { ++ return ret; ++ } ++ stats->offload_flow_num = hovs_stats.offload_flow_num; ++ stats->offload_qpc_num = hovs_stats.offload_qpc_num; ++ stats->same_flow_with_multi_gpa = hovs_stats.same_flow_with_multi_gpa; ++ stats->vxlan_rx_vtep_miss = hovs_stats.vxlan_rx_vtep_miss; ++ ++ stats->upcall_limit_drop_total = hovs_stats.upcall_limit_drop_total; ++ stats->upcall_from_vf_total = hovs_stats.upcall_from_vf_total; ++ stats->upcall_from_hwbond_total = hovs_stats.upcall_from_hwbond_total; ++ stats->flow_default_upcall = hovs_stats.flow_default_upcall; ++ stats->flow_miss_upcall = hovs_stats.flow_miss_upcall; ++ stats->flow_invalid_upcall = hovs_stats.flow_invalid_upcall; ++ stats->qu_prefetch_statics_fail = hovs_stats.qu_prefetch_statics_fail; ++ ++ return ret; ++} ++ ++int hinic3_global_statistics_flush(void) ++{ ++ int ret; ++ ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_STATISTICS_FLUSH, NULL); ++ ++ return ret; ++} ++ ++int hinic3_global_open_log(uint32_t module, uint32_t enable) ++{ ++ int ret; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ api_args.log_module = module; ++ api_args.log_level_or_enable = enable; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_OPEN_LOG, &api_args); ++ return ret; ++} ++ ++int hinic3_global_set_log_level(uint32_t module, uint32_t level) ++{ ++ int ret; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ api_args.log_module = module; ++ api_args.log_level_or_enable = level; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_SET_LOG_LEVEL, &api_args); ++ return ret; ++} ++ ++int hinic3_global_cmd_exec(const char *cmd_in, uint32_t in_size, char *cmd_out, uint32_t *out_len, uint32_t max_out_len) ++{ ++ int ret; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ api_args.cmd_in = cmd_in; ++ api_args.cmd_in_len = in_size; ++ api_args.cmd_out = cmd_out; ++ api_args.cmd_out_len = out_len; ++ api_args.cmd_out_buf_size = max_out_len; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_CMD_EXEC, &api_args); ++ return ret; ++} ++ ++int hinic3_global_pcie_list_query(uint8_t front_back, uint8_t bdf_type, struct hovs_phy_dev_info *dev) ++{ ++ int ret; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ api_args.bdf_type = bdf_type; ++ api_args.front_back = front_back; ++ api_args.dev = dev; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_PCIE_LIST_QUERY, &api_args); ++ return ret; ++} ++ ++void hinic3_eth_dev_tx_lock_init(void) ++{ ++ for (uint8_t i = 0; i < MAX_TX_QUEUE_PER_VPORT; i++) { ++ rte_spinlock_init(&g_hinic3_tx_burst_lock[i]); ++ } ++} ++ ++uint16_t hinic3_global_rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) ++{ ++ uint16_t ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ if (HINIC3_UNLIKELY(ops->hovs_rte_tx_burst == NULL)) { ++ hinic3_add_error_stats(HINIC3_VPORT_HOVS_RTE_TX_BURST_NULL, 1); ++ return 0; ++ } ++ ++ if (HINIC3_UNLIKELY(queue_id >= MAX_TX_QUEUE_PER_VPORT)) { ++ hinic3_add_error_stats(HINIC3_VPORT_HOVS_RTE_TX_BURST_NULL, 1); ++ return 0; ++ } ++ ++ rte_spinlock_lock(&g_hinic3_tx_burst_lock[queue_id]); ++ ret = ops->hovs_rte_tx_burst(port_id, queue_id, (void **)tx_pkts, nb_pkts); ++ rte_spinlock_unlock(&g_hinic3_tx_burst_lock[queue_id]); ++ ++ return ret; ++} ++ ++uint16_t hinic3_global_rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ if (HINIC3_UNLIKELY(ops->hovs_rte_rx_burst == NULL)) { ++ hinic3_add_error_stats(HINIC3_VPORT_HOVS_RTE_RX_BURST_NULL, 1); ++ return 0; ++ } ++ return ops->hovs_rte_rx_burst(port_id, queue_id, (void **)rx_pkts, nb_pkts); ++} ++ ++int hinic3_global_set_vxlan_vtep(const struct hinic3_vtep_ip_set_args *ops) ++{ ++ int ret = -1; ++ void *buff = NULL; ++ void *reply_buff = NULL; ++ void *tmp_buff = NULL; ++ const uint32_t nla_buf_size = 32; ++ struct hinic3_nlattr args_nla; ++ struct hinic3_nlattr unset_args_nla; ++ struct hinic3_vtep_ip_set_args *ops_buf = NULL; ++ struct hinic_global_api_args api_args = { 0 }; ++ ++ buff = (void *)hinic3_calloc(1, nla_buf_size, HINIC3_DRIVER_ADAPTER); ++ if (buff == NULL) { ++ HINIC3_LOG(ERR, AGENT, "alloc memory error"); ++ return -1; ++ } ++ ++ reply_buff = (void *)hinic3_calloc(1, nla_buf_size, HINIC3_DRIVER_ADAPTER); ++ if (reply_buff == NULL) { ++ hinic3_free(buff); ++ HINIC3_LOG(ERR, AGENT, "alloc memory error"); ++ return -1; ++ } ++ ++ tmp_buff = buff; ++ hinic3_nlattr_init(&args_nla, tmp_buff, nla_buf_size); ++ tmp_buff = reply_buff; ++ hinic3_nlattr_init(&unset_args_nla, tmp_buff, nla_buf_size); ++ ops_buf = hinic3_nlattr_put_unspec_uninit(&args_nla, HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP, ++ sizeof(struct hinic3_vtep_ip_set_args)); ++ if (ops_buf == NULL) { ++ goto clear_exit; ++ } ++ ++ memcpy(ops_buf, ops, sizeof(struct hinic3_vtep_ip_set_args)); ++ ++ api_args.in_nlattr_data = args_nla.data; ++ api_args.in_nlattr_len = args_nla.used_len; ++ api_args.out_nlattr_data = unset_args_nla.data; ++ api_args.out_nlattr_len = &unset_args_nla.used_len; ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_CFG_SET, &api_args); ++clear_exit: ++ hinic3_free(buff); ++ hinic3_free(reply_buff); ++ return ret; ++} ++ ++static void hinic3_init_flow_unage_flag(struct smap *args) ++{ ++ hinic3_smap_add(args, HINIC3_GLOBAL_CFG_UNAGE_FLAG_STR, HINIC3_FLOW_UNAGE_FLAG, HINIC3_DRIVER_ADAPTER); ++ HINIC3_LOG(INFO, AGENT, "Set the hardware flow not to be aged."); ++} ++ ++static void hinic3_init_flow_age_time(struct smap *args) ++{ ++ char age_time_str[HINIC3_FLOW_AGE_TIME_MAX_LEN] = { 0 }; ++ uint32_t age_time = hinic3_flow_max_idle_get(); ++ ++ sprintf(age_time_str, "%u", age_time); ++ hinic3_smap_add(args, HINIC3_GLOBAL_CFG_ARG_FLOW_AGE_TIME_STR, age_time_str, HINIC3_DRIVER_ADAPTER); ++ HINIC3_LOG(INFO, AGENT, "Set the aging time of the hardware flow table to %s ms.", age_time_str); ++} ++ ++void hinic3_global_cfg_set_when_restart(void) ++{ ++ int ret; ++ struct smap args; ++ struct smap unset_args; ++ ++ hinic3_smap_init(&args); ++ hinic3_smap_init(&unset_args); ++ ++ (void)hinic3_init_flow_unage_flag(&args); ++ ++ ret = hinic3_global_cfg_set(&args, &unset_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_global_cfg_set error, %s\n", __FUNCTION__); ++ } ++ ++ hinic3_smap_destroy(&args); ++ hinic3_smap_destroy(&unset_args); ++ ++ hinic3_flow_flush(); ++} ++ ++struct rte_mempool *dpdk_shared_mp_get(void) ++{ ++ return (struct rte_mempool *)g_dpdk_shared_mp; ++} ++ ++static const char *hinic3_global_get_api_name(hinic3_global_api api_index) ++{ ++ int i; ++ for (i = 0; i < HINIC3_GLOBAL_API_MAX; ++i) { ++ if (api_index == g_global_api_arr[i].api_index) { ++ return g_global_api_arr[i].api_name; ++ } ++ } ++ return NULL; ++} ++ ++static void hinic3_global_format_api(const char *api_name, const hiovs_api_record *rec, struct ds *ds, bool is_all) ++{ ++ char time_str[HINIC3_TIME_STR_LEN] = {0}; ++ char *pstr = time_str; ++ int title_ui_space; ++ int value_ui_space; ++ ++ if (is_all) { ++ title_ui_space = SHOW_GLOBAL_API_UI_FOUR_SPACE; ++ value_ui_space = SHOW_GLOBAL_API_UI_SIX_SPACE; ++ } else { ++ title_ui_space = SHOW_GLOBAL_API_UI_TWO_SPACE; ++ value_ui_space = SHOW_GLOBAL_API_UI_FOUR_SPACE; ++ } ++ hinic3_ds_put_format(ds, "%*sQuery %s:\n", title_ui_space, HINIC3_UI_INDENT_SPACE, api_name); ++ hinic3_ds_put_format(ds, "%*smax api time(us): %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->max_api_time); ++ hinic3_ds_put_format(ds, "%*smin api time(us): %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->min_api_time); ++ if (rec->call_total_count != 0) { ++ hinic3_ds_put_format(ds, "%*saverage api time(us): %u\n", value_ui_space, HINIC3_UI_INDENT_SPACE, ++ rec->total_api_time / rec->call_total_count); ++ } else { ++ hinic3_ds_put_format(ds, "%*saverage api time(us): 0\n", value_ui_space, HINIC3_UI_INDENT_SPACE); ++ } ++ hinic3_ds_put_format(ds, "%*stotal call counts: %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->call_total_count); ++ hinic3_ds_put_format(ds, "%*serror call counts: %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->call_error_count); ++ if (rec->call_error_count != 0) { ++ ctime_r(&rec->time_error, pstr); ++ hinic3_ds_put_format(ds, "%*slast error info: return %lld in %s\n", ++ value_ui_space, HINIC3_UI_INDENT_SPACE, rec->last_rtn_value, ++ pstr); ++ } ++} ++ ++static int hinic3_global_show_one_api(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ int ret; ++ char *api_name = NULL; ++ hiovs_api_record rec; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ if (argc != SHOW_ONE_API_ARG_NUM) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "invalid command format, type -h or --help for help.\n"); ++ goto err; ++ } ++ api_name = (char *)argv[1]; ++ if (hinic3_global_get_api_index(api_name) == HINIC3_GLOBAL_API_MAX) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "api-name is invalid [%s].\n", api_name); ++ goto err; ++ } ++ ret = hinic3_global_get_api_record(api_name, false, false, &rec, 1); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "api-name is invalid [%s].\n", api_name); ++ goto err; ++ } ++ ++ hinic3_global_format_api(api_name, &rec, &ds, false); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++err: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int hinic3_global_show_all_api(struct unixctl_conn *conn) ++{ ++ int i; ++ int ret; ++ char *api_name = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ hiovs_api_record *rec_list = NULL; ++ ++ rec_list = (hiovs_api_record *)hinic3_calloc(HINIC3_GLOBAL_API_MAX, sizeof(hiovs_api_record), HINIC3_DRIVER_ADAPTER); ++ if (rec_list == NULL) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "calloc memory failed!\n"); ++ goto err; ++ } ++ ++ ret = hinic3_global_get_api_record("", true, false, rec_list, HINIC3_GLOBAL_API_MAX); ++ if (ret != 0) { ++ hinic3_free(rec_list); ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "internal error, please check log!\n"); ++ goto err; ++ } ++ ++ hinic3_ds_put_format(&ds, "%2sAPI Counts: %d\n", HINIC3_UI_INDENT_SPACE, HINIC3_GLOBAL_API_MAX); ++ for (i = 0; i < HINIC3_GLOBAL_API_MAX; i++) { ++ api_name = (char *)hinic3_global_get_api_name(i); ++ if (api_name == NULL) { ++ goto err; ++ } ++ hinic3_global_format_api(api_name, &rec_list[i], &ds, true); ++ if (i != HINIC3_GLOBAL_API_MAX - 1) { ++ hinic3_ds_put_format(&ds, "\n"); ++ } ++ } ++ ++ hinic3_free(rec_list); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++err: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int hinic3_global_clear_api(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ char *api_name = NULL; ++ hiovs_api_record rec; ++ ++ if (argc != CLEAR_GLOBAL_API_ARG_NUM) { ++ hinic3_ds_put_format(&ds, "%sinvalid command format, please type -h or --help for help.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR); ++ goto err; ++ } ++ if (strcmp("all", argv[CLEAR_GLOBAL_API_ARG_NUM - 1]) == 0) { ++ ret = hinic3_global_get_api_record("", true, true, NULL, 0); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "clear all global api record failed\n"); ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_FAILURE "Clear global API records failed [all]!\n"); ++ goto err; ++ } ++ HINIC3_LOG(INFO, AGENT, "clear all global api record successful\n"); ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_INFO "Clear global API records successful [all].\n"); ++ } else { ++ api_name = (char *)argv[CLEAR_GLOBAL_API_ARG_NUM - 1]; ++ if (hinic3_global_get_api_index(api_name) == HINIC3_GLOBAL_API_MAX) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "api-name is invalid [%s].\n", api_name); ++ goto err; ++ } ++ ret = hinic3_global_get_api_record(api_name, false, true, &rec, 1); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "clear global api record failed\n"); ++ hinic3_ds_put_format(&ds, "%sClear global API record failed [%s]!\n", HINIC3_UI_LEADING_SIGN_ERROR, api_name); ++ goto err; ++ } ++ HINIC3_LOG(INFO, AGENT, "clear global api record successful.\n"); ++ hinic3_ds_put_format(&ds, "%sClear global API record successful [%s].\n", HINIC3_UI_LEADING_SIGN_INFO, api_name); ++ } ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++err: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static void hinic3_global_api_show_cmd_help(struct unixctl_conn *conn) ++{ ++ int i; ++ const char *api_name = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ hinic3_ds_put_format(&ds, "%2sUsage: dpak-ovs-ctl hwoff/show-global-api { all | clear { all | } | " ++ "api | { -h | --help } }\n", HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_OPTION_LIST_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_SHOW_ALL_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_CLEAR_ALL_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_CLEAR_ONE_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_SHOW_ONE_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_HELP_STRING); ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2sapi names that can be input are as follows:", HINIC3_UI_INDENT_SPACE); ++ for (i = 0; i < HINIC3_GLOBAL_API_MAX; i++) { ++ api_name = hinic3_global_get_api_name(i); ++ if (api_name == NULL) { ++ continue; ++ } ++ if (i % SHOW_MAX_API_ONE_LINE == 0) { ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%4s", HINIC3_UI_INDENT_SPACE); ++ } ++ hinic3_ds_put_format(&ds, "%-36s", api_name); ++ } ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++} ++ ++static void unixctl_hinic3_show_global_api(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int work_agrc = argc; ++ const char **work_argv = argv; ++ ++ work_agrc -= 1; ++ work_argv += 1; ++ if (strcmp("api", work_argv[0]) == 0) { ++ *(int *)aux = hinic3_global_show_one_api(conn, work_agrc, work_argv); ++ return; ++ } ++ ++ if ((strcmp("all", work_argv[0]) == 0) && work_agrc == 1) { ++ *(int *)aux = hinic3_global_show_all_api(conn); ++ return; ++ } ++ ++ if ((strcmp("clear", work_argv[0]) == 0) && work_agrc == CLEAR_GLOBAL_API_ARG_NUM) { ++ *(int *)aux = hinic3_global_clear_api(conn, work_agrc, work_argv); ++ return; ++ } ++ ++ if (((strcmp("-h", work_argv[0]) == 0) || (strcmp("--help", work_argv[0]) == 0)) && work_agrc == 1) { ++ *(int *)aux = 0; ++ return hinic3_global_api_show_cmd_help(conn); ++ } ++ ++ hinic3_command_reply_error(conn, ++ HINIC3_UI_LEADING_SIGN_ERROR "invalid command format, type -h or --help for help.\n"); ++ *(int *)aux = -1; ++ return; ++} ++ ++/* this function must be call when thread start */ ++int hinic3_global_class_init(void) ++{ ++ int ret; ++ hiovs_api_record *global_api_record = NULL; ++ ++ global_api_record = hinic3_get_global_api_record(); ++ if (global_api_record == NULL) { ++ return -1; ++ } ++ ++ memset(global_api_record, 0, sizeof(hiovs_api_record) * HINIC3_GLOBAL_API_MAX); ++ pthread_mutex_lock(&g_hinic3_global_mutex); ++ ret = hinic3_global_init(NULL, hinic3_mbuf_size_get()); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_global_class_init: hinic3_global_init failed."); ++ hinic3_global_unit(); ++ pthread_mutex_unlock(&g_hinic3_global_mutex); ++ return ret; ++ } ++ ++ pthread_mutex_unlock(&g_hinic3_global_mutex); ++ hinic3_command_register("hwoff/show-global-api", "{ all | clear { all | } |" ++ " api | { -h | --help } }", ++ HINIC3_SHOW_GLOBAL_API_MIN_ARG, HINIC3_SHOW_GLOBAL_API_MAX_ARG, unixctl_hinic3_show_global_api, NULL); ++ return ret; ++} ++ ++/* this function must be call when thread stop */ ++void hinic3_global_class_uninit(void) ++{ ++ pthread_mutex_lock(&g_hinic3_global_mutex); ++ hinic3_global_unit(); ++ pthread_mutex_unlock(&g_hinic3_global_mutex); ++ ++ hiovs_api_record *global_api_record = NULL; ++ ++ global_api_record = hinic3_get_global_api_record(); ++ if (global_api_record == NULL) { ++ HINIC3_LOG(ERR, AGENT, "global_api_record is NULL"); ++ return; ++ } ++ ++ memset(global_api_record, 0, sizeof(hiovs_api_record) * HINIC3_GLOBAL_API_MAX); ++} ++ ++int hinic3_adapt_malloc(const char *type, size_t size, int socket_arg, unsigned int flags, size_t align, size_t bound, ++ bool contig, struct hovs_melem *mem) ++{ ++ return -1; ++} ++ ++int hinic3_adapt_mfree(void *addr) ++{ ++ return -1; ++} ++ ++void *hinic3_adapt_malloc_socket(const char *type, size_t size, unsigned int align, int socket_arg) ++{ ++ return hinic3_rte_malloc_socket(HIOVS_MEM, size, align, socket_arg); ++} ++ ++void hinic3_adapt_free(void *addr) ++{ ++ return hinic3_rte_free(addr); ++} ++ ++const void *hinic3_adapt_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) ++{ ++ return (void *)hinic3_rte_memzone_reserve(name, len, socket_id, flags, HIOVS_MEM); ++} ++ ++const void *hinic3_adapt_memzone_reserve_aligned(const char *name, size_t len, int socket_id, unsigned flags, ++ unsigned align) ++{ ++ return (void *)hinic3_rte_memzone_reserve_aligned(name, len, socket_id, flags, align, HIOVS_MEM); ++} ++ ++int hinic3_adapt_memzone_free(void *addr) ++{ ++ return hinic3_rte_memzone_free((struct rte_memzone *)addr); ++} ++ ++struct hovs_mbuf *hinic3_adapt_mbuf_alloc(void *mp) ++{ ++ struct rte_mbuf *mbuf = NULL; ++ struct hovs_mbuf *trans_mbuf = NULL; ++ ++ mbuf = rte_pktmbuf_alloc((struct rte_mempool *)mp); ++ if (mbuf == NULL) { ++ return NULL; ++ } ++ ++ trans_mbuf = (struct hovs_mbuf *)mbuf; ++ return trans_mbuf; ++} ++ ++int hinic3_adapt_mbuf_alloc_bulk(void *mp, struct hovs_mbuf **mbufs, uint32_t count) ++{ ++ return rte_pktmbuf_alloc_bulk((struct rte_mempool *)mp, (struct rte_mbuf **)mbufs, count); ++} ++ ++void hinic3_adapt_mbuf_free(struct hovs_mbuf *m) ++{ ++ rte_pktmbuf_free((struct rte_mbuf *)m); ++} ++ ++static int hinic3_forward_mode_set_sub(struct hinic3_nlattr *nla, enum hinic3_packet_forward_mod mod) ++{ ++ if (nla == NULL) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 forward mod set error, input null ptr"); ++ return -1; ++ } ++ int ret = 0; ++ ++ if (mod == HINIC3_FORWARD_MODE_BANDWIDTH) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 forward mod set, set bandwidth"); ++ ret = hinic3_nlattr_put_u8(nla, HINIC3_GLOBAL_CFG_ARG_LATENCY_MOD, 0); ++ } else if (mod == HINIC3_FORWARD_MODE_LATENCY) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 forward mod set, set latency"); ++ ret = hinic3_nlattr_put_u8(nla, HINIC3_GLOBAL_CFG_ARG_LATENCY_MOD, HINIC3_FORWARD_MODE_LATENCY); ++ } else if (mod == HINIC3_FORWARD_MODE_30M) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 forward mod set, 30M"); ++ ret = hinic3_nlattr_put_u8(nla, HINIC3_GLOBAL_CFG_ARG_LATENCY_MOD, HINIC3_FORWARD_MODE_30M); ++ } else { ++ HINIC3_LOG(ERR, AGENT, "hinic3 forward mod set error, input invalid mod %d", mod); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int hinic3_forward_mode_set(enum hinic3_packet_forward_mod mod) ++{ ++ struct hinic3_nlattr args_in; ++ struct hinic3_nlattr args_out; ++ char buffer_out[HINIC3_FORWARD_MODE_BUFFER_LEN] = {0}; ++ char buffer_in[HINIC3_FORWARD_MODE_BUFFER_LEN] = {0}; ++ int ret = 0; ++ struct hinic_global_api_args api_args = {0}; ++ ++ hinic3_nlattr_init(&args_in, buffer_in, HINIC3_FORWARD_MODE_BUFFER_LEN); ++ hinic3_nlattr_init(&args_out, buffer_out, HINIC3_FORWARD_MODE_BUFFER_LEN); ++ ++ ret = hinic3_forward_mode_set_sub(&args_in, mod); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to set forward mode."); ++ return -1; ++ } ++ ++ api_args.in_nlattr_data = args_in.data; ++ api_args.in_nlattr_len = args_in.used_len; ++ api_args.out_nlattr_data = args_out.data; ++ api_args.out_nlattr_len = &args_out.used_len; ++ ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_CFG_SET, &api_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to set forward mode, ret %d.\n", ret); ++ } ++ ++ return ret; ++} ++ ++static int hinic3_bond_hash_policy_set_sub(struct hinic3_nlattr *nla, enum hinic3_bond_hash_policy mod) ++{ ++ if (nla == NULL) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 bond hash policy set error, input null ptr"); ++ return -1; ++ } ++ int ret = 0; ++ ++ if (mod == EFFICIENT_HASH) { ++ HINIC3_LOG(INFO, AGENT, "hinic3 bond hash policy set, set efficient hash"); ++ ret = hinic3_nlattr_put_u8(nla, HINIC3_GLOBAL_CFG_ARG_BOND_HASH_POLICY_CFG, EFFICIENT_HASH); ++ } else if (mod == STANDARD_HASH) { ++ ret = hinic3_nlattr_put_u8(nla, HINIC3_GLOBAL_CFG_ARG_BOND_HASH_POLICY_CFG, STANDARD_HASH); ++ HINIC3_LOG(INFO, AGENT, "hinic3 bond hash policy set, set standard hash"); ++ } else { ++ HINIC3_LOG(ERR, AGENT, "hinic3 bond hash policy set error, input invalid mod %d", mod); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int hinic3_bond_hash_policy_set(enum hinic3_packet_forward_mod mod) ++{ ++ struct hinic3_nlattr args_in; ++ struct hinic3_nlattr args_out; ++ char buffer_out[HINIC3_BOND_HASH_POLICY_LEN] = {0}; ++ char buffer_in[HINIC3_BOND_HASH_POLICY_LEN] = {0}; ++ int ret = 0; ++ struct hinic_global_api_args api_args = {0}; ++ ++ hinic3_nlattr_init(&args_in, buffer_in, HINIC3_BOND_HASH_POLICY_LEN); ++ hinic3_nlattr_init(&args_out, buffer_out, HINIC3_BOND_HASH_POLICY_LEN); ++ ++ ret = hinic3_bond_hash_policy_set_sub(&args_in, mod); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to bond hash policy."); ++ return -1; ++ } ++ ++ api_args.in_nlattr_data = args_in.data; ++ api_args.in_nlattr_len = args_in.used_len; ++ api_args.out_nlattr_data = args_out.data; ++ api_args.out_nlattr_len = &args_out.used_len; ++ ++ ret = hinic3_log_hinic_global_api_log(HINIC3_GLOBAL_CFG_SET, &api_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to set bond hash policy, ret %d.\n", ret); ++ } ++ ++ return ret; ++} ++ ++int hinic3_forward_mod_get(struct ds *ds) ++{ ++ int ret = 0; ++ struct smap cfg_map; ++ hinic3_smap_init(&cfg_map); ++ ++ ret = hinic3_global_cfg_get(&cfg_map); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get forward mode."); ++ hinic3_smap_destroy(&cfg_map); ++ return -1; ++ } ++ ++ const char *res = hinic3_smap_get(&cfg_map, HINIC3_GLOBAL_CFG_PKT_FORWARD_MOD_STR); ++ if (res == NULL) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get forward configuration."); ++ hinic3_smap_destroy(&cfg_map); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "Info: Current forward mode: %s.\n", res); ++ hinic3_smap_destroy(&cfg_map); ++ return 0; ++} ++ ++int hinic3_forward_mode_init(void) ++{ ++ enum hinic3_packet_forward_mod mod = hinic3_packet_forward_mod_get(); ++ int ret = 0; ++ ++ if (mod == HINIC3_FORWARD_MODE_BANDWIDTH) { ++ mod = HINIC3_FORWARD_MODE_30M; ++ } ++ ++ ret = hinic3_forward_mode_set(mod); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to init forward mode."); ++ } ++ return ret; ++} ++ ++int hinic3_bond_hash_policy_init(void) ++{ ++ enum hinic3_bond_hash_policy mod = hinic3_packet_bond_hash_policy_get(); ++ int ret = 0; ++ ++ ret = hinic3_bond_hash_policy_set(mod); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to init bond hash policy."); ++ } ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.h +new file mode 100644 +index 0000000..6696273 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.h +@@ -0,0 +1,156 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_IFACE_GLOBAL_H ++#define HINIC3_IFACE_GLOBAL_H ++ ++#include ++ ++#include "rte_pci.h" ++#include "rte_mempool.h" ++#include "rte_cfgfile.h" ++ ++#include "hinic3_smap.h" ++#include "hinic3_map.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_provider.h" ++#include "hinic3_ds.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define ETHER_HDR_MAX_LEN (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN \ ++ + (2 * VLAN_HEADER_LEN)) ++#define NETDEV_DPDK_MBUF_ALIGN 1024 ++#define NETDEV_DPDK_MAX_PKT_LEN 9728 ++ ++#define HINIC3_SHOW_GLOBAL_API_MAX_ARG 3 ++#define HINIC3_SHOW_GLOBAL_API_MIN_ARG 1 ++ ++#define HINIC3_FLOW_AGE_TIME "hinic3-max-idle" ++#define HINIC3_RX_THREAD_NUM "hinic3-offload-thread-num" ++#define HINIC3_MAX_FLOW_NUM "hinic3-max-flow-num" ++#define HINIC3_PMD_NUM "pmd-num" ++ ++#define HINIC3_FLOW_AGE_TIME_MAX_LEN 16 ++#define HINIC3_BDF_TYPE_FAKE_WITH_FUNC_ID 2 ++#define HINIC3_FRONT_BACK_FAKE_WITH_FUNC_ID 1 ++ ++#define HINIC3_RX_THREAD_NUM_MIN 1 ++#define HINIC3_RX_THREAD_NUM_MAX 4 ++#define HINIC3_RX_THREAD_NUM_DEFAULT 2 ++ ++#define HINIC3_OFFLOAD_FLOW_NUM_MIN 1 ++#define HINIC3_OFFLOAD_FLOW_NUM_MAX 2 /* it will be 32 M later */ ++ ++#define HINIC3_DEVICE_TYPE (1LLU << 0) ++#define HINIC3_DEVICE_DRIVER_TYPE (1LLU << 1) ++ ++#define HINIC3_OFFLOAD_FLOW_NUM_DEFAULT 2 ++#define HINIC3_VTEP_TABLE_IP_ADDR_LEN 4 ++ ++#define HINIC3_DEFAULT_BOND_RX_SIZE 1024 ++#define HINIC3_DEFAULT_BOND_TX_SIZE 512 ++#define HINIC3_DEFAULT_VPORT_RX_SIZE 256 ++#define HINIC3_DEFAULT_VPORT_TX_SIZE 256 ++#define HINIC3_DEFAULT_MBUF_SIZE 2176 ++#define HINIC3_BOND_RX_SIZE_STR "bond_rx_depth" ++#define HINIC3_BOND_TX_SIZE_STR "bond_tx_depth" ++#define HINIC3_VPORT_RX_SIZE_STR "vport_rx_depth" ++#define HINIC3_VPORT_TX_SIZE_STR "vport_tx_depth" ++#define HINIC3_MBUF_SIZE_STR "mbuf_size" ++ ++enum hinic3_vtep_cmd { ++ HINIC3_VTEP_DEL = 0, ++ HINIC3_VTEP_ADD ++}; ++ ++struct hinic3_vtep_ip { ++ uint32_t is_ipv6; /* 0: ipv4, 1: ipv6 */ ++ /* ++ * ip_dw0: IPv6 DIP[127:96] ++ * ip_dw1: IPv6 DIP[95:64] ++ * ip_dw2: IPv6 DIP[63:32] ++ * ip_dw3: IPv6 DIP[31:0] or IPv4 DIP[31:0] ++ */ ++ uint32_t ip_addr[HINIC3_VTEP_TABLE_IP_ADDR_LEN]; ++}; ++ ++struct hinic3_vtep_ip_set_args { ++ uint32_t ops; /* 0: del 1: add */ ++ struct hinic3_vtep_ip dip; ++}; ++ ++struct hinic_global_api_args { ++ void *in_nlattr_data; ++ size_t in_nlattr_len; ++ void *out_nlattr_data; ++ size_t *out_nlattr_len; ++ struct hovs_global_stats *hovs_stats; ++ uint32_t log_module; ++ uint32_t log_level_or_enable; ++ const char *cmd_in; ++ uint32_t cmd_in_len; ++ char *cmd_out; ++ uint32_t *cmd_out_len; ++ uint32_t cmd_out_buf_size; ++ uint8_t front_back; ++ uint8_t bdf_type; ++ struct hovs_phy_dev_info *dev; ++}; ++ ++enum hinic3_packet_forward_mod { ++ HINIC3_FORWARD_MODE_BANDWIDTH, ++ HINIC3_FORWARD_MODE_LATENCY, ++ HINIC3_FORWARD_MODE_30M ++}; ++ ++// global apis ++void hinic3_global_unit(void); ++struct rte_mempool *dpdk_shared_mp_get(void); ++int hinic3_global_cfg_set(const struct smap *args, struct smap *unset_args); ++int hinic3_global_cfg_get(struct smap *args); ++int hinic3_global_statistics_get(struct hinic3_global_stats *stats); ++int hinic3_global_statistics_flush(void); ++int hinic3_global_open_log(uint32_t module, uint32_t enable); ++int hinic3_global_set_log_level(uint32_t module, uint32_t level); ++int hinic3_global_cmd_exec(const char *cmd_in, uint32_t in_size, ++ char *cmd_out, uint32_t *out_len, uint32_t max_out_len); ++int hinic3_global_pcie_list_query(uint8_t front_back, uint8_t bdf_type, struct hovs_phy_dev_info *dev); ++void hinic3_eth_dev_tx_lock_init(void); ++uint16_t hinic3_global_rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id, ++ struct rte_mbuf **tx_pkts, uint16_t nb_pkts); ++uint16_t hinic3_global_rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id, ++ struct rte_mbuf **rx_pkts, uint16_t nb_pkts); ++int hinic3_global_get_api_record(const char *api_name, bool is_all, bool is_clear, ++ hiovs_api_record *records, int record_len); ++int hinic3_global_add_vxlan_vtep(bool is_ipv6, uint8_t *vxlan_dstip, uint32_t length, uint16_t dst_port); ++int hinic3_global_del_vxlan_vtep(bool is_ipv6, uint8_t *vxlan_dstip, uint32_t length); ++void hinic3_global_cfg_set_when_restart(void); ++int hinic3_global_class_init(void); ++void hinic3_global_class_uninit(void); ++int hinic3_adapt_malloc(const char *type, size_t size, int socket_arg, unsigned int flags, size_t align, size_t bound, ++ bool contig, struct hovs_melem *mem); ++int hinic3_adapt_mfree(void *addr); ++struct hovs_mbuf *hinic3_adapt_mbuf_alloc(void *mp); ++void hinic3_adapt_mbuf_free(struct hovs_mbuf *m); ++void *hinic3_adapt_malloc_socket(const char *type, size_t size, unsigned int align, int socket_arg); ++void hinic3_adapt_free(void *addr); ++const void *hinic3_adapt_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags); ++const void *hinic3_adapt_memzone_reserve_aligned(const char *name, size_t len, int socket_id, unsigned flags, ++ unsigned align); ++int hinic3_adapt_memzone_free(void *addr); ++int hinic3_adapt_mbuf_alloc_bulk(void *mp, struct hovs_mbuf **mbufs, uint32_t count); ++int hinic3_global_set_vxlan_vtep(const struct hinic3_vtep_ip_set_args *ops); ++hinic3_global_api hinic3_global_get_api_index(const char *api_name); ++int hinic3_forward_mode_set(enum hinic3_packet_forward_mod mod); ++int hinic3_forward_mod_get(struct ds *ds); ++int hinic3_forward_mode_init(void); ++int hinic3_bond_hash_policy_init(void); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HINIC3_IFACE_GLOBAL_H */ +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c +new file mode 100644 +index 0000000..b76c281 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c +@@ -0,0 +1,86 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#include ++#include ++#include "rte_cycles.h" ++#include "rte_ether.h" ++#include "rte_lcore.h" ++#include "rte_malloc.h" ++#include "hinic3_log.h" ++#include "hinic3_smap.h" ++#include "hinic3_init.h" ++#include "hinic3_provider.h" ++#include "hinic3_message.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_util.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_ds.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#endif ++#include "hinic3_iface_global_api_record.h" ++ ++hiovs_api_record g_global_api_record[HINIC3_GLOBAL_API_MAX]; ++ ++ ++int hinic3_global_get_api_record(const char *api_name, bool is_all, bool is_clear, ++ hiovs_api_record *records, int record_len) ++{ ++ int i; ++ hinic3_global_api api_index; ++ ++ if (is_all) { ++ if (is_clear) { ++ memset(g_global_api_record, 0, sizeof(hiovs_api_record) * HINIC3_GLOBAL_API_MAX); ++ return 0; ++ } ++ for (i = 0; i < record_len && i < HINIC3_GLOBAL_API_MAX; ++i) { ++ records[i] = g_global_api_record[i]; ++ } ++ return 0; ++ } ++ ++ api_index = hinic3_global_get_api_index(api_name); ++ if (api_index >= HINIC3_GLOBAL_API_MAX) { ++ return -1; ++ } ++ ++ if (is_clear) { ++ memset(&g_global_api_record[api_index], 0, sizeof(hiovs_api_record)); ++ } ++ records[0] = g_global_api_record[api_index]; ++ return 0; ++} ++ ++void hinic_global_api_record_error(int ret_code, hinic3_port_api api_index, uint64_t exec_time) ++{ ++ if (ret_code != 0) { ++ g_global_api_record[api_index].call_error_count++; ++ g_global_api_record[api_index].last_rtn_value = ret_code; ++ g_global_api_record[api_index].time_error = time(NULL); ++ HINIC3_LOG(ERR, AGENT, "hinic HWAPI called, return %d, cost %"PRIu64"us.", ret_code, exec_time); ++ } ++} ++ ++void hinic_global_fill_api_record(hinic3_global_api api_index, uint64_t exec_time) ++{ ++ g_global_api_record[api_index].call_total_count++; ++ /* the total_api_time allows integer inversion and will not affect the function */ ++ g_global_api_record[api_index].total_api_time += exec_time; ++ if (exec_time > g_global_api_record[api_index].max_api_time) { ++ g_global_api_record[api_index].max_api_time = exec_time; ++ } ++ if (exec_time < g_global_api_record[api_index].min_api_time || g_global_api_record[api_index].min_api_time == 0) { ++ g_global_api_record[api_index].min_api_time = exec_time; ++ } ++} ++ ++hiovs_api_record *hinic3_get_global_api_record(void) ++{ ++ return g_global_api_record; ++} +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.h +new file mode 100644 +index 0000000..17859b6 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.h +@@ -0,0 +1,14 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_IFACE_GLOBAL_API_RECORD_H ++#define HINIC3_IFACE_GLOBAL_API_RECORD_H ++ ++#include "hinic3_iface_global.h" ++ ++void hinic_global_api_record_error(int ret_code, hinic3_port_api api_index, uint64_t exec_time); ++void hinic_global_fill_api_record(hinic3_global_api api_index, uint64_t exec_time); ++hiovs_api_record *hinic3_get_global_api_record(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c +new file mode 100644 +index 0000000..48635ed +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c +@@ -0,0 +1,910 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "hinic3_map.h" ++ ++#include "hinic3_smap.h" ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_provider.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_command.h" ++#include "hinic3_ds.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_iface_port_util.h" ++#include "hinic3_iface_port_api_record.h" ++#include "hinic3_iface_port.h" ++ ++#define MAX_SLAVES_NUM_EACH_BOND RTE_MAX_ETHPORTS ++#define MAX_SLAVES_SIZE MAX_SLAVES_NUM_EACH_BOND ++ ++#define SHOW_ONE_API_ARG_NUM 2 ++#define SHOW_MAX_API_ONE_LINE 4 ++#define CLEAR_PORT_API_ARG_NUM 2 ++#define SHOW_PORT_API_UI_TWO_SPACE 2 ++#define SHOW_PORT_API_UI_FOUR_SPACE 4 ++#define SHOW_PORT_API_UI_SIX_SPACE 6 ++ ++struct hiovs_port_map { ++ hinic3_port_api api_index; ++ const char *api_name; ++}; ++ ++ ++// please modify hinic3_port_api when modify this structure ++static const struct hiovs_port_map g_port_api_arr[HINIC3_PORT_API_MAX] = { ++ { HINIC3_PORT_MGMT_ADD, "hovs_port_mgmt_add" }, ++ { HINIC3_PORT_MGMT_DEL, "hovs_port_mgmt_del" }, ++ { HINIC3_PORT_MGMT_GET, "hovs_port_mgmt_get" }, ++ { HINIC3_PORT_MGMT_SET, "hovs_port_mgmt_set" }, ++ { HINIC3_PORT_QUEUE_SET, "hovs_port_mgmt_setup_upcall_queue"}, ++ { HINIC3_PORT_QUEUE_RELEASE, "hovs_port_mgmt_release_upcall_queue"}, ++ { HINIC3_BOND_MGMT_CREATE, "hovs_bond_mgmt_create" }, ++ { HINIC3_BOND_MGMT_DELETE, "hovs_bond_mgmt_delete" }, ++ { HINIC3_BOND_MGMT_GET, "hovs_bond_mgmt_get" }, ++ { HINIC3_BOND_MGMT_SET, "hovs_bond_mgmt_set" }, ++ { HINIC3_BOND_MGMT_CLEAR, "hovs_bond_mgmt_clear" }, ++ { HINIC3_BOND_SLAVE_INFO_GET, "hovs_bond_slave_info_get" }, ++ { HINIC3_ETHERADDR_GET, "hovs_etheraddr_get" }, ++ { HINIC3_MTU_SET, "hovs_mtu_set" }, ++ { HINIC3_CARRIER_GET, "hovs_carrier_get" }, ++ { HINIC3_CARRIER_RESETS_GET, "hovs_carrier_resets_get" }, ++ { HINIC3_PORT_STATISTICS_GET, "hovs_port_statistics_get" }, ++ { HINIC3_PORT_STATISTICS_FLUSH, "hovs_port_statistics_flush" }, ++ { HINIC3_FEATURES_GET, "hovs_features_get" }, ++ { HINIC3_SECURITY_GET, "hovs_bum_get" }, ++ { HINIC3_SECURITY_SET, "hovs_bum_set" }, ++ { HINIC3_SECURITY_REMOVE, "hovs_bum_remove" }, ++ { HINIC3_SECURITY_CLEAR, "hovs_bum_clear" }, ++ { HINIC3_QOS_INGRESS_LIMIT_SET, "hovs_qos_ingress_limit_set" }, ++ { HINIC3_QOS_INGRESS_LIMIT_GET, "hovs_qos_ingress_limit_get" }, ++ { HINIC3_QOS_EGRESS_LIMIT_SET, "hovs_qos_egress_limit_set" }, ++ { HINIC3_QOS_EGRESS_LIMIT_GET, "hovs_qos_egress_limit_get" }, ++ { HINIC3_QOS_DROP_THRESH_SET, "hovs_qos_drop_thresh_set" }, ++ { HINIC3_QOS_DROP_THRESH_GET, "hovs_qos_drop_thresh_get" }, ++ { HINIC3_PORT_MGMT_GET_CAPABILITY, "hovs_port_mgmt_get_capability" }, ++ { HINIC3_PORT_MGMT_GET_UPCALL_INFO, "hovs_port_mgmt_get_upcall_info" }, ++ { HINIC3_QOS_STATISTICS_GET, "hovs_qos_statistics_get_batch"}, ++ { HINIC3_QOS_STATISTICS_CLEAR_GET, "hovs_qos_statistics_get_all_batch"}, ++ { HINIC3_QOS_STATISTICS_CLEAR_CLEAR, "hovs_qos_statistics_clear_batch"}, ++ { HINIC3_HQOS_STATISTICS_CLEAR_GET, "hovs_hqos_statistics_get_all_batch"}, ++ { HINIC3_HQOS_STATISTICS_CLEAR_CLEAR, "hovs_hqos_statistics_clear_batch"}, ++ { HINIC3_PORT_MGMT_ADD_DYNAMIC, "hovs_port_mgmt_add_dynamic"}, ++ { HINIC3_VM_QOS_LIMIT_SET, "hovs_qos_vm_limit_set"}, ++ { HINIC3_VM_QOS_LIMIT_GET, "hovs_qos_vm_limit_get"}, ++ { HINIC3_PORT_QOS_LIMIT_SET, "hovs_qos_vport_limit_set"}, ++ { HINIC3_PORT_QOS_LIMIT_GET, "hovs_qos_vport_limit_get"}, ++ { HINIC3_VM_QOS_SRTCM_LIMIT_SET, "hovs_qos_vm_srtcm_limit_set"}, ++ { HINIC3_VM_QOS_SRTCM_LIMIT_GET, "hovs_qos_vm_srtcm_limit_get"}, ++ { HINIC3_NET_QOS_LIMIT_SET, "hovs_qos_net_limit_set"}, ++ { HINIC3_NET_QOS_LIMIT_GET, "hovs_qos_net_limit_get"}, ++ { HINIC3_PORT_MGMT_GET_BOND_SALVE_INFO, "hovs_bond_slave_statistics_get"}, ++ { HINIC3_PORT_MGMT_SET_USAGE_STATE, "hovs_port_mgmt_set_usage_state"}, ++ { HINIC3_PORT_MGMT_GET_USAGE_STATE, "hovs_port_mgmt_get_usage_state"}, ++ { HINIC3_UPCALL_MTU_SET, "hovs_upcall_mtu_set"}, ++ ++}; ++ ++#define RTF_LOG_HINIC_PORT_API_LOG(TIME_START, EXEC_TIME, RET_CODE, API_INDEX, API_FUNC) \ ++ do { \ ++ TIME_START = rte_get_tsc_cycles(); \ ++ RET_CODE = API_FUNC; \ ++ EXEC_TIME = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ EXEC_TIME = ((rte_get_tsc_cycles() - (TIME_START)) * 1000000UL) / hz; \ ++ } \ ++ hinic3_port_fill_api_record(API_INDEX, EXEC_TIME); \ ++ if ((RET_CODE) != 0) { \ ++ hinic_port_api_record_error(RET_CODE, API_INDEX, EXEC_TIME); \ ++ } \ ++ } while (0) ++ ++int hinic3_port_mgmt_add(uint16_t *port_id, const struct rte_pci_addr *pci_addr) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ struct rte_pci_addr *p_tmp = (struct rte_pci_addr *)pci_addr; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_add, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_ADD, ++ ops->hovs_port_mgmt_add(port_id, p_tmp)); ++ return hinic3_convert_error_code(ret); ++} ++ ++void hinic3_port_mgmt_del(uint16_t port_id) ++{ ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ if (ops->hovs_port_mgmt_del == NULL) { ++ HINIC3_LOG(ERR, BOND, "hovs_port_mgmt_del is NULL in ops"); ++ return; ++ } ++ RTF_LOG_HINIC_PORT_API_LOG_VOID(time_start, exec_time, HINIC3_PORT_MGMT_DEL, ops->hovs_port_mgmt_del(port_id)); ++} ++ ++int hinic3_port_mgmt_get(uint16_t port_id, struct smap *args) ++{ ++ int ret = -1; ++ uint64_t time_start; ++ uint64_t exec_time; ++ void *buff = NULL; ++ void *tmp_value = NULL; ++ struct hinic3_nlattr nla_args; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (args == NULL) { ++ HINIC3_LOG(WARNING, VPORT, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (!buff) { ++ HINIC3_LOG(ERR, VPORT, "alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ if (ops->hovs_port_mgmt_get == NULL) { ++ ret = HINIC3_DRV_FUNC_NO_PTR; ++ goto out; ++ } ++ ++ tmp_value = buff; ++ hinic3_nlattr_init(&nla_args, tmp_value, HOVS_MAX_TLV_BUF_LEN); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_GET, ++ ops->hovs_port_mgmt_get(port_id, nla_args.data, (uint32_t *)&nla_args.used_len)); ++ if (ret != 0) { ++ ret = hinic3_convert_error_code(ret); ++ goto out; ++ } ++ ++ hinic3_nlattr_reset_itr(&nla_args, nla_args.used_len); ++ /* nlattr to smap */ ++ port_args_nlattr_to_smap(&nla_args, args); ++ ++out: ++ hinic3_free(buff); ++ return ret; ++} ++ ++int hinic3_port_mgmt_set(uint16_t port_id, const struct smap *args, struct smap *unset_args) ++{ ++ int ret = -1; ++ uint64_t time_start; ++ uint64_t exec_time; ++ void *buff = NULL; ++ void *reply_buff = NULL; ++ void *tmp_buff = NULL; ++ struct hinic3_nlattr nla_args; ++ struct hinic3_nlattr nla_unset_args; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (!args || !unset_args) { ++ HINIC3_LOG(WARNING, VPORT, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_set, HINIC3_DRV_FUNC_NO_PTR); ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (!buff) { ++ HINIC3_LOG(ERR, VPORT, "alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ reply_buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (!reply_buff) { ++ hinic3_free(buff); ++ HINIC3_LOG(ERR, VPORT, "alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ tmp_buff = buff; ++ hinic3_nlattr_init(&nla_args, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ tmp_buff = reply_buff; ++ hinic3_nlattr_init(&nla_unset_args, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ /* smap to nlattr */ ++ port_args_smap_to_nlattr(args, &nla_args); ++ ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_SET, ++ ops->hovs_port_mgmt_set(port_id, nla_args.data, nla_args.used_len, nla_unset_args.data, ++ (uint32_t *)&nla_unset_args.used_len)); ++ if (ret != 0) { ++ ret = hinic3_convert_error_code(ret); ++ goto out; ++ } ++ ++ /* nlattr to smap */ ++ hinic3_nlattr_reset_itr(&nla_unset_args, nla_unset_args.used_len); ++ port_args_nlattr_to_smap(&nla_unset_args, unset_args); ++ ++out: ++ hinic3_free(buff); ++ hinic3_free(reply_buff); ++ return ret; ++} ++ ++int hinic3_port_mgmt_setup_upcall_queue(uint16_t port_id, uint16_t queue_id, unsigned int socket_id, ++ struct rte_mempool *mp) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_setup_upcall_queue, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_QUEUE_SET, ++ ops->hovs_port_mgmt_setup_upcall_queue(port_id, queue_id, socket_id, (void *)mp)); ++ return ret; ++} ++ ++int hinic3_port_mgmt_release_upcall_queue(uint16_t port_id, uint16_t queue_id) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_release_upcall_queue, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_QUEUE_RELEASE, ++ ops->hovs_port_mgmt_release_upcall_queue(port_id, queue_id)); ++ return ret; ++} ++ ++int hinic3_bond_mgmt_create(uint8_t mode, const char *name, uint16_t *bond_id) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (bond_id == NULL) { ++ HINIC3_LOG(WARNING, BOND, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_bond_mgmt_create, HINIC3_DRV_FUNC_NO_PTR); ++ ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_BOND_MGMT_CREATE, ++ ops->hovs_bond_mgmt_create(mode, name, bond_id)); ++ return hinic3_convert_error_code(ret); ++} ++ ++void hinic3_bond_mgmt_delete(uint16_t bond_id) ++{ ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ if (ops->hovs_bond_mgmt_delete == NULL) { ++ HINIC3_LOG(ERR, BOND, "hovs_port_mgmt_del is NULL in ops"); ++ return; ++ } ++ RTF_LOG_HINIC_PORT_API_LOG_VOID(time_start, exec_time, HINIC3_BOND_MGMT_DELETE, ops->hovs_bond_mgmt_delete(bond_id)); ++} ++ ++int hinic3_bond_mgmt_get(uint16_t bond_id, struct smap *args) ++{ ++ int ret = -1; ++ uint64_t time_start; ++ uint64_t exec_time; ++ void *buff = NULL; ++ void *tmp_buff = NULL; ++ struct hinic3_nlattr nla_args; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (args == NULL) { ++ HINIC3_LOG(WARNING, BOND, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_bond_mgmt_get, HINIC3_DRV_FUNC_NO_PTR); ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (!buff) { ++ HINIC3_LOG(ERR, VPORT, "alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ tmp_buff = buff; ++ hinic3_nlattr_init(&nla_args, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_BOND_MGMT_GET, ++ ops->hovs_bond_mgmt_get(bond_id, nla_args.data, (uint32_t *)&nla_args.used_len)); ++ if (ret != 0) { ++ ret = hinic3_convert_error_code(ret); ++ goto out; ++ } ++ ++ hinic3_nlattr_reset_itr(&nla_args, nla_args.used_len); ++ /* nlattr to smap */ ++ bond_args_nlattr_to_smap(&nla_args, args); ++ ++out: ++ hinic3_free(buff); ++ return ret; ++} ++ ++int hinic3_etheraddr_get(uint16_t port_id, struct eth_address *mac) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hovs_eth_addr eth_addr = {{.ea = {0}}}; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (mac == NULL) { ++ HINIC3_LOG(WARNING, VPORT, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_etheraddr_get, HINIC3_DRV_FUNC_NO_PTR); ++ ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_ETHERADDR_GET, ++ ops->hovs_etheraddr_get(port_id, ð_addr)); ++ if (ret != 0) { ++ return hinic3_convert_error_code(ret); ++ } ++ ++ memcpy(mac, ð_addr, sizeof(struct hovs_eth_addr)); ++ ++ return 0; ++} ++ ++int hinic3_etheraddr_set(uint16_t port_id, struct eth_addr mac) ++{ ++ struct hovs_eth_addr eth_addr = {{.ea = {0}}}; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_etheraddr_set, HINIC3_DRV_FUNC_NO_PTR); ++ ++ memcpy(ð_addr, &mac, sizeof(struct eth_addr)); ++ ++ return hinic3_convert_error_code(ops->hovs_etheraddr_set(port_id, eth_addr)); ++} ++ ++int hinic3_mtu_set(uint16_t port_id, int mtu) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_mtu_set, HINIC3_DRV_FUNC_NO_PTR); ++ ++ HINIC3_LOG(INFO, VPORT, "set mtu value %d", mtu); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_MTU_SET, ops->hovs_mtu_set(port_id, mtu)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_security_get(uint16_t port_id, struct smap *args) ++{ ++ int ret = -1; ++ struct hinic3_nlattr nla_args; ++ uint64_t time_start; ++ uint64_t exec_time; ++ void *buff = NULL; ++ void *tmp_buff = NULL; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (args == NULL) { ++ HINIC3_LOG(WARNING, BUM, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_bum_get, HINIC3_DRV_FUNC_NO_PTR); ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (!buff) { ++ HINIC3_LOG(ERR, VPORT, "alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ tmp_buff = buff; ++ hinic3_nlattr_init(&nla_args, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_SECURITY_GET, ++ ops->hovs_bum_get(port_id, nla_args.data, (uint32_t *)&nla_args.used_len)); ++ if (ret != 0) { ++ ret = hinic3_convert_error_code(ret); ++ goto err; ++ } ++ ++ hinic3_nlattr_reset_itr(&nla_args, nla_args.used_len); ++ ret = bum_args_nlattr_to_smap(&nla_args, args); ++ if (ret != 0) { ++ goto err; ++ } ++ ++err: ++ hinic3_free(buff); ++ return ret; ++} ++ ++int hinic3_security_remove(uint16_t port_id, struct hinic3_nlattr *nla_args) ++{ ++ uint64_t time_start; ++ uint64_t exec_time; ++ int ret = -1; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_bum_remove, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_SECURITY_REMOVE, ++ ops->hovs_bum_remove(port_id, nla_args->data, nla_args->used_len)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_security_set(uint16_t port_id, struct hinic3_nlattr *nla_args, struct hinic3_nlattr *nla_unset_args) ++{ ++ uint64_t time_start; ++ uint64_t exec_time; ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_bum_set, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_SECURITY_SET, ++ ops->hovs_bum_set(port_id, nla_args->data, nla_args->used_len, nla_unset_args->data, ++ (uint32_t *)&nla_unset_args->used_len)); ++ return hinic3_convert_error_code(ret); ++} ++ ++ ++int hinic3_port_statistics_get(uint16_t port_id, hinic3_port_stats *stats) ++{ ++ const int data_count = HINIC3_DATA_COUNT; ++ int ret; ++ struct hovs_port_stats hovs_stats = { 0 }; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (stats == NULL) { ++ HINIC3_LOG(WARNING, VPORT, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_statistics_get, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_STATISTICS_GET, ++ ops->hovs_port_statistics_get(port_id, &hovs_stats)); ++ if (ret != 0) { ++ return hinic3_convert_error_code(ret); ++ } ++ ++ memcpy(stats, &hovs_stats, sizeof(hovs_stats)); ++ memcpy(&stats->timestamp, &hovs_stats.timestamp, sizeof(uint64_t) * data_count); ++ return 0; ++} ++ ++int hinic3_port_statistics_flush(uint16_t port_id) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_statistics_flush, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_STATISTICS_FLUSH, ++ ops->hovs_port_statistics_flush(port_id)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_port_mgmt_get_capability(struct hinic3_port_capability *cap) ++{ ++ uint64_t time_start; ++ uint64_t exec_time; ++ int ret; ++ struct hovs_port_capability hovs_cap; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_get_capability, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_GET_CAPABILITY, ++ ops->hovs_port_mgmt_get_capability(&hovs_cap)); ++ if (ret != 0) { ++ return hinic3_convert_error_code(ret); ++ } ++ ++ cap->supported_upcall_qnum = hovs_cap.supported_upcall_qnum; ++ return 0; ++} ++ ++int hinic3_port_mgmt_get_upcall_info(struct hinic3_port_upcall_info *info) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_get_upcall_info, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_GET_UPCALL_INFO, ++ ops->hovs_port_mgmt_get_upcall_info((struct hovs_port_upcall_info *)info)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_port_mgmt_get_bond_slave_info(const uint16_t port_id, struct hovs_bond_slave_stats *bond_slave_info) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_bond_slave_statistics_get, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_GET_BOND_SALVE_INFO, ++ ops->hovs_bond_slave_statistics_get(port_id, bond_slave_info)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_port_mgmt_set_usage_state(uint16_t port_id, uint16_t status) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_set_usage_state, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_SET_USAGE_STATE, ++ ops->hovs_port_mgmt_set_usage_state(port_id, status)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_port_mgmt_get_usage_state(uint16_t port_id, uint32_t *status) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_get_usage_state, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_GET_USAGE_STATE, ++ ops->hovs_port_mgmt_get_usage_state(port_id, status)); ++ return hinic3_convert_error_code(ret); ++} ++ ++int hinic3_port_upcall_mtu_set(uint8_t type, int mtu) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_upcall_mtu_set, HINIC3_DRV_FUNC_NO_PTR); ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_UPCALL_MTU_SET, ++ ops->hovs_upcall_mtu_set(type, mtu)); ++ return hinic3_convert_error_code(ret); ++} ++ ++hinic3_port_api hinic3_port_get_api_index(const char *api_name) ++{ ++ int i; ++ ++ for (i = 0; i < HINIC3_PORT_API_MAX; ++i) { ++ if (g_port_api_arr[i].api_name == NULL) { ++ continue; ++ } ++ if (strncmp(api_name, g_port_api_arr[i].api_name, strlen(g_port_api_arr[i].api_name) + 1) == 0) { ++ return g_port_api_arr[i].api_index; ++ } ++ } ++ return HINIC3_PORT_API_MAX; ++} ++ ++const char *hinic3_port_get_api_name(hinic3_port_api api_index) ++{ ++ int i; ++ ++ for (i = 0; i < HINIC3_PORT_API_MAX; ++i) { ++ if (api_index == g_port_api_arr[i].api_index) { ++ return g_port_api_arr[i].api_name; ++ } ++ } ++ return NULL; ++} ++ ++int hinic3_port_mgmt_add_dynamic(uint16_t *port_id, const struct smap *args) ++{ ++ int ret; ++ uint64_t time_start; ++ uint64_t exec_time; ++ void *buff = NULL; ++ void *tmp_buff = NULL; ++ struct hinic3_nlattr nla_args; ++ struct hinic3_drv_ops *ops = NULL; ++ uint64_t vdpa_feature = 0; ++ ++ if (!args) { ++ HINIC3_LOG(WARNING, VPORT, "pointer parameter is NULL"); ++ return -EINVAL; ++ } ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_port_mgmt_add_dynamic, HINIC3_DRV_FUNC_NO_PTR); ++ ++ buff = (void *)hinic3_calloc(1, HOVS_MAX_TLV_BUF_LEN, HINIC3_DRIVER_ADAPTER); ++ if (!buff) { ++ HINIC3_LOG(ERR, VPORT, "alloc memory error"); ++ return -ENOMEM; ++ } ++ ++ tmp_buff = buff; ++ hinic3_nlattr_init(&nla_args, tmp_buff, HOVS_MAX_TLV_BUF_LEN); ++ /* smap to nlattr */ ++ port_args_smap_to_nlattr(args, &nla_args); ++ /* vdpa feature */ ++ vdpa_feature = hinic3_vdpa_feature_get(); ++ if (vdpa_feature != 0) { ++ hinic3_nlattr_put_u64(&nla_args, HINIC3_PORT_ARG_DEVICE_FEATURE, vdpa_feature); ++ } ++ ++ RTF_LOG_HINIC_PORT_API_LOG(time_start, exec_time, ret, HINIC3_PORT_MGMT_ADD_DYNAMIC, ++ ops->hovs_port_mgmt_add_dynamic(port_id, nla_args.data, nla_args.used_len)); ++ hinic3_free(buff); ++ return hinic3_convert_error_code(ret); ++} ++ ++static void hinic3_port_format_api(const char *api_name, const hiovs_api_record *rec, struct ds *ds, bool is_all) ++{ ++ char time_str[HINIC3_TIME_STR_LEN] = {0}; ++ char *pstr = time_str; ++ int title_ui_space; ++ int value_ui_space; ++ ++ if (is_all) { ++ title_ui_space = SHOW_PORT_API_UI_FOUR_SPACE; ++ value_ui_space = SHOW_PORT_API_UI_SIX_SPACE; ++ } else { ++ title_ui_space = SHOW_PORT_API_UI_TWO_SPACE; ++ value_ui_space = SHOW_PORT_API_UI_FOUR_SPACE; ++ } ++ hinic3_ds_put_format(ds, "%*sQuery %s:\n", title_ui_space, HINIC3_UI_INDENT_SPACE, api_name); ++ hinic3_ds_put_format(ds, "%*smax api time(us): %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->max_api_time); ++ hinic3_ds_put_format(ds, "%*smin api time(us): %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->min_api_time); ++ if (rec->call_total_count != 0) { ++ hinic3_ds_put_format(ds, "%*saverage api time(us): %u\n", value_ui_space, HINIC3_UI_INDENT_SPACE, ++ rec->total_api_time / rec->call_total_count); ++ } else { ++ hinic3_ds_put_format(ds, "%*saverage api time(us): 0\n", value_ui_space, HINIC3_UI_INDENT_SPACE); ++ } ++ hinic3_ds_put_format(ds, "%*stotal call counts: %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->call_total_count); ++ hinic3_ds_put_format(ds, "%*serror call counts: %u\n", value_ui_space, ++ HINIC3_UI_INDENT_SPACE, rec->call_error_count); ++ if (rec->call_error_count != 0) { ++ ctime_r(&rec->time_error, pstr); ++ hinic3_ds_put_format(ds, "%*slast error info: return %lld in %s\n", ++ value_ui_space, HINIC3_UI_INDENT_SPACE, rec->last_rtn_value, pstr); ++ } ++} ++ ++static int hinic3_port_show_one_api(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ int ret; ++ char *api_name = NULL; ++ hiovs_api_record rec; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ if (argc != SHOW_ONE_API_ARG_NUM) { ++ hinic3_ds_put_format(&ds, "%sinvalid command format, please type -h or --help for help.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR); ++ goto err; ++ } ++ ++ api_name = (char *)argv[1]; ++ if (hinic3_port_get_api_index(api_name) == HINIC3_PORT_API_MAX) { ++ hinic3_ds_put_format(&ds, "%sapi-name is invalid [%s].\n", HINIC3_UI_LEADING_SIGN_ERROR, api_name); ++ goto err; ++ } ++ ret = hinic3_port_get_api_record(api_name, false, false, &rec, 1); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, "%sapi-name is invalid [%s].\n", HINIC3_UI_LEADING_SIGN_ERROR, api_name); ++ goto err; ++ } ++ ++ hinic3_port_format_api(api_name, &rec, &ds, false); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++err: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int hinic3_port_show_all_api(struct unixctl_conn *conn) ++{ ++ int i; ++ int ret; ++ char *api_name = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ hiovs_api_record *rec_list = NULL; ++ ++ rec_list = (hiovs_api_record *)hinic3_calloc(HINIC3_PORT_API_MAX, sizeof(hiovs_api_record), HINIC3_DRIVER_ADAPTER); ++ if (!rec_list) { ++ hinic3_ds_put_format(&ds, "%scalloc memory failed!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ goto err; ++ } ++ ++ ret = hinic3_port_get_api_record("", true, false, rec_list, HINIC3_PORT_API_MAX); ++ if (ret != 0) { ++ hinic3_free(rec_list); ++ hinic3_ds_put_format(&ds, "%sinternal error, please check log!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ goto err; ++ } ++ ++ hinic3_ds_put_format(&ds, "%2sAPI Counts: %d\n", HINIC3_UI_INDENT_SPACE, HINIC3_PORT_API_MAX); ++ for (i = 0; i < HINIC3_PORT_API_MAX; i++) { ++ api_name = (char *)hinic3_port_get_api_name(i); ++ hinic3_port_format_api(api_name, &rec_list[i], &ds, true); ++ if (i != HINIC3_PORT_API_MAX - 1) { ++ hinic3_ds_put_format(&ds, "\n"); ++ } ++ } ++ ++ hinic3_free(rec_list); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++ ++err: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static int hinic3_port_clear_api(struct unixctl_conn *conn, int argc, const char *argv[]) ++{ ++ int ret; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ char *api_name = NULL; ++ hiovs_api_record rec; ++ ++ if (argc != CLEAR_PORT_API_ARG_NUM) { ++ hinic3_ds_put_format(&ds, "%sinvalid command format, please type -h or --help for help.\n", ++ HINIC3_UI_LEADING_SIGN_ERROR); ++ goto err; ++ } ++ ++ if (strcmp("all", argv[CLEAR_PORT_API_ARG_NUM - 1]) == 0) { ++ ret = hinic3_port_get_api_record("", true, true, NULL, 0); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "clear all port api record failed\n"); ++ hinic3_ds_put_format(&ds, "%sClear port API records failed [all]!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ goto err; ++ } ++ HINIC3_LOG(INFO, AGENT, "clear all port api record successful\n"); ++ hinic3_ds_put_format(&ds, "%sClear port API records successful [all].\n", HINIC3_UI_LEADING_SIGN_INFO); ++ } else { ++ api_name = (char *)argv[CLEAR_PORT_API_ARG_NUM - 1]; ++ if (hinic3_port_get_api_index(api_name) == HINIC3_PORT_API_MAX) { ++ hinic3_ds_put_format(&ds, "%sapi-name is invalid [%s].\n", HINIC3_UI_LEADING_SIGN_ERROR, api_name); ++ goto err; ++ } ++ ret = hinic3_port_get_api_record(api_name, false, true, &rec, 1); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "clear port api record failed\n"); ++ hinic3_ds_put_format(&ds, "%sClear port API record failed [%s]!\n", HINIC3_UI_LEADING_SIGN_ERROR, api_name); ++ goto err; ++ } ++ HINIC3_LOG(INFO, AGENT, "clear port api record successful.\n"); ++ hinic3_ds_put_format(&ds, "%sClear port API record successful [%s].\n", HINIC3_UI_LEADING_SIGN_INFO, api_name); ++ } ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return 0; ++err: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return -1; ++} ++ ++static void hinic3_port_api_show_cmd_help(struct unixctl_conn *conn) ++{ ++ int i; ++ const char *api_name = NULL; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ hinic3_ds_put_format(&ds, "%2sUsage: dpak-ovs-ctl hwoff/show-port-api" ++ " { all | clear { all | } | api | { -h | --help } }\n", ++ HINIC3_UI_INDENT_SPACE); ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_OPTION_LIST_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_SHOW_ALL_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_CLEAR_ALL_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_CLEAR_ONE_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_SHOW_ONE_API_HELP_STRING); ++ hinic3_ds_put_format(&ds, "%4s%s", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_HELP_STRING); ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%2sapi names that can be input are as follows:", HINIC3_UI_INDENT_SPACE); ++ for (i = 0; i < HINIC3_PORT_API_MAX; ++i) { ++ api_name = hinic3_port_get_api_name(i); ++ if (api_name == NULL) { ++ continue; ++ } ++ if (i % SHOW_MAX_API_ONE_LINE == 0) { ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_ds_put_format(&ds, "%4s", HINIC3_UI_INDENT_SPACE); ++ } ++ hinic3_ds_put_format(&ds, "%-36s", api_name); ++ } ++ hinic3_ds_put_format(&ds, "\n"); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++} ++ ++static void unixctl_hinic3_show_port_api(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int work_argc = argc; ++ const char **work_argv = argv; ++ ++ work_argc -= 1; ++ work_argv += 1; ++ if (strcmp("api", work_argv[0]) == 0) { ++ *(int *)aux = hinic3_port_show_one_api(conn, work_argc, work_argv); ++ return; ++ } ++ ++ if ((strcmp("all", work_argv[0]) == 0) && work_argc == 1) { ++ *(int *)aux = hinic3_port_show_all_api(conn); ++ return; ++ } ++ ++ if ((strcmp("clear", work_argv[0]) == 0)) { ++ *(int *)aux = hinic3_port_clear_api(conn, work_argc, work_argv); ++ return; ++ } ++ ++ if (((strcmp("-h", work_argv[0]) == 0) || (strcmp("--help", work_argv[0]) == 0)) && work_argc == 1) { ++ *(int *)aux = 0; ++ return hinic3_port_api_show_cmd_help(conn); ++ } ++ ++ *(int *)aux = -1; ++ hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR"invalid command format, type -h or --help for help.\n"); ++ return; ++} ++ ++int hinic3_port_class_init(void) ++{ ++ memset(g_port_api_record, 0, sizeof(hiovs_api_record) * HINIC3_PORT_API_MAX); ++ ++ hinic3_command_register("hwoff/show-port-api", "{ all | clear " ++ "{ all | } | api | { -h | --help } }", ++ HINIC3_SHOW_PORT_API_MIN_ARG, HINIC3_SHOW_PORT_API_MAX_ARG, unixctl_hinic3_show_port_api, NULL); ++ return 0; ++} ++ ++void hinic3_port_class_uninit(void) ++{ ++ memset(g_port_api_record, 0, sizeof(hiovs_api_record) * HINIC3_PORT_API_MAX); ++} +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h +new file mode 100644 +index 0000000..1385e99 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h +@@ -0,0 +1,121 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_IFACE_PORT_H ++#define HINIC3_IFACE_PORT_H ++ ++#include ++#include ++#include "rte_pci.h" ++#include "rte_common.h" ++#include "hinic3_smap.h" ++#include "hinic3_map.h" ++#include "hinic3_provider.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define MAX_PORT_NAME 15 ++ ++/* Macros for pci id verification .support two format:XX:XX.X,XXXX:XX:XX.X */ ++#define PCI_ID_LENGTH 7 ++#define PCI_ID_DELIMITER1_OFFSET 2 ++#define PCI_ID_DELIMITER2_OFFSET 5 ++#define PCI_ID_DOMAIN_LENGTH 12 ++#define PCI_ID_DOMAIN_DELIMITER1_OFFSET 4 ++#define PCI_ID_DOMAIN_DELIMITER2_OFFSET 7 ++#define PCI_ID_DOMAIN_DELIMITER3_OFFSET 10 ++ ++#define HINIC3_PORT_ID_INVALID 0 ++#define INVALID_DPDK_PORT_ID 0xff ++ ++#define HINIC3_DATA_COUNT 25 ++#define VM_LEVEL 1 ++ ++#define HINIC3_SHOW_PORT_API_MAX_ARG 3 ++#define HINIC3_SHOW_PORT_API_MIN_ARG 1 ++ ++enum { ++ MIN_DPDK_RX_QUEUE = 1, /* Minimum number of port queues */ ++ MAX_DPDK_RX_QUEUE = HINIC3_MAX_LCORE_COUNT, /* Maximum number of dpdk port rx queues */ ++ DEFAULT_DPDK_RX_QUEUE = 4, /* Default number of dpdk port rx queues */ ++ MAX_L2FWD_DPDK_QUEUE = 16, /* L2FWD mode number of port queues */ ++ MAX_DPDK_QUEUE = HINIC3_MAX_LCORE_COUNT ++}; /* Maximum number of port queues */ ++ ++enum EVS_PORT_TYPE { ++ PORT_TYPE_NULLITY = -1, /* inefficacy port. */ ++ PORT_TYPE_HNIC, /* port which is connected to host. */ ++ PORT_TYPE_PATCHNIC, /* port which is connected between bridge and bridge. */ ++ PORT_TYPE_DPDKPHY, /* port which is connected to DPDK physical network. */ ++ PORT_TYPE_LINUXPHY, /* port which is connected to linux physical network. */ ++ PORT_TYPE_VIRTIO, /* port which is connected to vhost-user. */ ++ PORT_TYPE_BOND, /* port which is connected to bond */ ++ PORT_TYPE_VXLAN, /* port which is connected to vxlan */ ++ PORT_TYPE_DUMMY, ++ PORT_TYPE_DUMMY_INTERNAL, ++ PORT_TYPE_DUMMY_PMD, ++ PORT_TYPE_STT, ++ PORT_TYPE_GRE, ++ PORT_TYPE_GENEVE, ++ PORT_TYPE_LISP, ++ PORT_TYPE_HWBOND, /* port which is connected to hwbond */ ++ PORT_TYPE_VIRTIO_VF, /* port which is connected to vhost agent */ ++ PORT_TYPE_HWPT, /* port which is connected to hwpt */ ++ PORT_TYPE_DPDK, ++ PORT_TYPE_DPDK_VHOSTUSER, ++}; ++ ++enum hiovs_bdf_type { ++ BDF_TYPE_REAL, /**< real bdf type. */ ++ BDF_TYPE_FAKE, /**< fake bdf type. */ ++}; ++ ++union bdf_info_u { ++ struct { ++ uint8_t bdf_type : 1; ++ uint8_t func_id_flag : 1; ++ uint8_t rsvd1 : 6; ++ } bs; ++ uint8_t value; ++}; ++ ++int hinic3_port_mgmt_add(uint16_t *port_id, const struct rte_pci_addr *pci_addr); ++int hinic3_port_mgmt_add_dynamic(uint16_t *port_id, const struct smap *args); ++void hinic3_port_mgmt_del(uint16_t port_id); ++int hinic3_port_mgmt_get(uint16_t port_id, struct smap *args); ++int hinic3_port_mgmt_set(uint16_t port_id, const struct smap *args, struct smap *unset_args); ++int hinic3_port_mgmt_setup_upcall_queue(uint16_t port_id, uint16_t queue_id, unsigned int socket_id, ++ struct rte_mempool *mp); ++int hinic3_port_mgmt_release_upcall_queue(uint16_t port_id, uint16_t queue_id); ++int hinic3_bond_mgmt_create(uint8_t mode, const char *name, uint16_t *bond_id); ++void hinic3_bond_mgmt_delete(uint16_t bond_id); ++int hinic3_bond_mgmt_get(uint16_t bond_id, struct smap *args); ++int hinic3_etheraddr_get(uint16_t port_id, struct eth_address *mac); ++int hinic3_etheraddr_set(uint16_t port_id, struct eth_addr mac); ++int hinic3_mtu_set(uint16_t port_id, int mtu); ++int hinic3_security_get(uint16_t port_id, struct smap *args); ++int hinic3_security_remove(uint16_t port_id, struct hinic3_nlattr *nla_args); ++int hinic3_security_set(uint16_t port_id, struct hinic3_nlattr *nla_args, struct hinic3_nlattr *nla_unset_args); ++int hinic3_port_statistics_get(uint16_t port_id, hinic3_port_stats *stats); ++int hinic3_port_statistics_flush(uint16_t port_id); ++int hinic3_port_mgmt_get_capability(struct hinic3_port_capability *cap); ++int hinic3_port_mgmt_get_upcall_info(struct hinic3_port_upcall_info *info); ++int hinic3_port_get_api_record(const char *api_name, bool is_all, bool is_clear, ++ hiovs_api_record *records, int record_len); ++const char *hinic3_port_get_api_name(hinic3_port_api api_index); ++int hinic3_port_class_init(void); ++void hinic3_port_class_uninit(void); ++int hinic3_port_mgmt_get_bond_slave_info(const uint16_t port_id, struct hovs_bond_slave_stats *info); ++int hinic3_port_mgmt_set_usage_state(uint16_t port_id, uint16_t status); ++int hinic3_port_mgmt_get_usage_state(uint16_t port_id, uint32_t *status); ++int hinic3_port_upcall_mtu_set(uint8_t type, int mtu); ++hinic3_port_api hinic3_port_get_api_index(const char *api_name); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _HINIC3_IFACE_PORT_H_ */ +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.c +new file mode 100644 +index 0000000..3e09b4f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.c +@@ -0,0 +1,92 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "hinic3_smap.h" ++#include "hinic3_map.h" ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_provider.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_iface_port_util.h" ++#include "hinic3_iface_port_api_record.h" ++ ++hiovs_api_record g_port_api_record[HINIC3_PORT_API_MAX]; ++ ++void hinic_port_api_record_error(int ret_code, hinic3_port_api api_index, uint64_t exec_time) ++{ ++ hiovs_api_record *p_record = NULL; ++ ++ p_record = &g_port_api_record[api_index]; ++ p_record->call_error_count++; ++ p_record->last_rtn_value = ret_code; ++ p_record->time_error = time(NULL); ++ HINIC3_LOG(ERR, VPORT, "Hinic HWAPI api %d called, return %d, cost %" PRIu64 " us.", api_index, ret_code, exec_time); ++} ++ ++void hinic3_port_fill_api_record(hinic3_port_api api_index, uint64_t exec_time) ++{ ++ hiovs_api_record *p_record = NULL; ++ ++ p_record = &g_port_api_record[api_index]; ++ p_record->call_total_count++; ++ /* the total_api_time allows integer inversion and will not affect the function */ ++ p_record->total_api_time += exec_time; ++ if (exec_time > p_record->max_api_time) { ++ p_record->max_api_time = exec_time; ++ } ++ if (exec_time < p_record->min_api_time || p_record->min_api_time == 0) { ++ p_record->min_api_time = exec_time; ++ } ++} ++ ++static int hinic3_clear_api_record(const char *api_name, bool is_all) ++{ ++ hinic3_port_api api_index; ++ ++ if (is_all) { ++ memset(g_port_api_record, 0, sizeof(hiovs_api_record) * HINIC3_PORT_API_MAX); ++ return 0; ++ } ++ ++ api_index = hinic3_port_get_api_index(api_name); ++ if (api_index >= HINIC3_PORT_API_MAX) { ++ return -1; ++ } ++ ++ memset(&g_port_api_record[api_index], 0, sizeof(hiovs_api_record)); ++ return 0; ++} ++ ++int hinic3_port_get_api_record(const char *api_name, bool is_all, bool is_clear, ++ hiovs_api_record *records, int record_len) ++{ ++ int i; ++ hinic3_port_api api_index; ++ int min_len = HINIC3_MIN(record_len, HINIC3_PORT_API_MAX); ++ ++ if (is_clear) { ++ return hinic3_clear_api_record(api_name, is_all); ++ } ++ ++ /* not clear */ ++ if (is_all) { ++ for (i = 0; i < min_len; ++i) { ++ records[i] = g_port_api_record[i]; ++ } ++ return 0; ++ } ++ ++ api_index = hinic3_port_get_api_index(api_name); ++ if (api_index >= HINIC3_PORT_API_MAX) { ++ return -1; ++ } ++ ++ records[0] = g_port_api_record[api_index]; ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.h +new file mode 100644 +index 0000000..9e6e3df +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_api_record.h +@@ -0,0 +1,60 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_IFACE_PORT_API_RECORD_H ++#define HINIC3_IFACE_PORT_API_RECORD_H ++ ++#include "hinic3_iface_port.h" ++ ++extern hiovs_api_record g_port_api_record[HINIC3_PORT_API_MAX]; ++void hinic3_port_fill_api_record(hinic3_port_api api_index, uint64_t exec_time); ++void hinic_port_api_record_error(int ret_code, hinic3_port_api api_index, uint64_t exec_time); ++ ++ ++/* * some API returns long long int, so must rewrite one. */ ++#define RTF_LOG_HINIC_PORT_API_LOG_LONG_INT(TIME_START, EXEC_TIME, RET_CODE, API_INDEX, API_FUNC) \ ++ do { \ ++ TIME_START = rte_get_tsc_cycles(); \ ++ RET_CODE = API_FUNC; \ ++ EXEC_TIME = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ EXEC_TIME = ((rte_get_tsc_cycles() - (TIME_START)) * 1000000UL) / hz; \ ++ } \ ++ hinic3_port_fill_api_record(API_INDEX, EXEC_TIME); \ ++ if ((RET_CODE) != 0) { \ ++ hinic_port_api_record_error(RET_CODE, API_INDEX, EXEC_TIME); \ ++ } \ ++ } while (0) ++ ++#define RTF_LOG_HINIC_PORT_API_LOG_LESS_THAN_ZERO(TIME_START, EXEC_TIME, RET_CODE, API_INDEX, API_FUNC) \ ++ do { \ ++ TIME_START = rte_get_tsc_cycles(); \ ++ RET_CODE = API_FUNC; \ ++ EXEC_TIME = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ EXEC_TIME = ((rte_get_tsc_cycles() - (TIME_START)) * 1000000UL) / hz; \ ++ } \ ++ hinic3_port_fill_api_record(API_INDEX, EXEC_TIME); \ ++ if ((RET_CODE) < 0) { \ ++ hinic_port_api_record_error(RET_CODE, API_INDEX, EXEC_TIME); \ ++ } \ ++ } while (0) ++ ++#define RTF_LOG_HINIC_PORT_API_LOG_VOID(TIME_START, EXEC_TIME, API_INDEX, API_FUNC) \ ++ do { \ ++ TIME_START = rte_get_tsc_cycles(); \ ++ API_FUNC; \ ++ EXEC_TIME = 0; \ ++ uint64_t hz = rte_get_tsc_hz(); \ ++ if (hz != 0) { \ ++ EXEC_TIME = ((rte_get_tsc_cycles() - (TIME_START)) * 1000000UL) / hz; \ ++ } \ ++ hinic3_port_fill_api_record(API_INDEX, EXEC_TIME); \ ++ HINIC3_LOG(WARNING, VPORT, "Hinic HWAPI %s called, return void, cost %" PRIu64 " us.", __FUNCTION__, \ ++ EXEC_TIME); \ ++ } while (0) ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c +new file mode 100644 +index 0000000..86e55d3 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c +@@ -0,0 +1,529 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "rte_cycles.h" ++#include "hinic3_smap.h" ++#include "hinic3_map.h" ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_provider.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_iface_port_api_record.h" ++#include "hinic3_smap.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_iface_port_util.h" ++ ++#define MAX_ARGS_SIZE (2048) ++#define MAX_NAME 32 ++#define MAX_RX_QUEUE_PER_VPORT 16 ++ ++static char *g_port_smap_key[HINIC3_PORT_ARG_TYPE_MAX] = { ++ HINIC3_PORT_VLAN_OL, ++ HINIC3_PORT_VLAN_TAG, ++ HINIC3_PORT_VLAN_MODE, ++ HINIC3_PORT_VNI, ++ HINIC3_DPDK_PORT_ID, ++ NULL, ++ NULL, ++ HINIC3_PORT_QUEUE_MAP, ++ HINIC3_PORT_GRO_ENABLE, ++ HINIC3_PORT_IPV6_GRO_ENABLE, ++ HINIC3_PORT_UPCALL_QUEUE_MAP, ++ HINIC3_PORT_BUCKET_ID, ++ HINIC3_PORT_MAX_QUEUE_NUM, ++ HINIC3_PORT_MIGRATE_TUNNEL_INFO, ++ HINIC3_PORT_MIGRATE_STATE, ++ HINIC3_PORT_PCI_ADDR, ++ HINIC3_PORT_BLOCK_START, ++ HINIC3_PORT_BLOCK_SIZE, ++ HINIC3_PORT_UPCALL_QUEUE_NUM, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ HINIC3_PORT_QUEUE_DEPTH ++}; ++ ++static char *g_bond_smap_key[HINIC3_BOND_ARG_TYPE_MAX] = { ++ HINIC3_BOND_UPLINK_PCI_ID, ++ HINIC3_BOND_LACP_DEACTIVE_SLAVES, ++ HINIC3_BOND_MODE, ++ HINIC3_BOND_XMIT_HASH_POLICY, ++ HINIC3_BOND_SLAVES, ++ HINIC3_BOND_ACTIVE_SLAVE, ++ HINIC3_BOND_ARG_UPDELAY_STR, ++ HINIC3_BOND_ARG_DOWNDELAY_STR, ++ HINIC3_BOND_ARG_LACP_STATUS_STR, ++ HINIC3_BOND_ARG_ACTIVE_MAC_STR, ++ HINIC3_BOND_ARG_SLAVE_NAME_STR, ++ NULL, /* slave cfg str start */ ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, /* slave cfg str end */ ++ HINIC3_BOND_LACP_RATE, ++}; ++ ++static inline int port_smap_key_to_nla_type(char *smap_key) ++{ ++ int i; ++ ++ for (i = 0; i < HINIC3_PORT_ARG_TYPE_MAX; i++) { ++ if (g_port_smap_key[i] && !strncmp(smap_key, g_port_smap_key[i], strlen(smap_key) + 1)) { ++ return i; ++ } ++ } ++ ++ return HINIC3_PORT_ARG_TYPE_MAX; ++} ++ ++static int smap_to_nlattr_u8(struct hinic3_nlattr *nla, char *value, int type) ++{ ++ uint8_t val; ++ int rc; ++ ++ rc = sscanf(value, "%hhu", &val); ++ if (rc != 1) { ++ HINIC3_LOG(ERR, VPORT, "Failed to sscanf %d, err is %d", type, rc); ++ return -1; ++ } ++ hinic3_nlattr_put_u8(nla, type, val); ++ return 0; ++} ++ ++static int smap_to_nlattr_u16(struct hinic3_nlattr *nla, char *value, int type) ++{ ++ uint16_t val; ++ int rc; ++ ++ rc = sscanf(value, "%hu", &val); ++ if (rc != 1) { ++ HINIC3_LOG(ERR, VPORT, "Failed to sscanf %d, err is %d", type, rc); ++ return -1; ++ } ++ hinic3_nlattr_put_u16(nla, type, val); ++ return 0; ++} ++ ++static int smap_to_nlattr_u32(struct hinic3_nlattr *nla, char *value, int type) ++{ ++ uint32_t val; ++ int rc; ++ ++ rc = sscanf(value, "%u", &val); ++ if (rc != 1) { ++ HINIC3_LOG(ERR, VPORT, "Failed to sscanf %d, err is %d", type, rc); ++ return -1; ++ } ++ hinic3_nlattr_put_u32(nla, type, val); ++ return 0; ++} ++ ++static int smap_to_nlattr_unspec(struct hinic3_nlattr *nla, char *value, int type) ++{ ++ uint64_t val; ++ int rc = sscanf(value, "%"PRIu64, &val); ++ if (rc != 1) { ++ HINIC3_LOG(ERR, VPORT, "Failed to sscanf %d, err is %d", type, rc); ++ return -1; ++ } ++ if (type == HINIC3_PORT_ARG_PORT_QUEUE_MAP) { ++ hinic3_nlattr_put_unspec(nla, type, &val, sizeof(val)); ++ } else if (type == HINIC3_PORT_ARG_MIGRATE_TUNNEL_INFO) { ++ hinic3_nlattr_put_unspec(nla, type, (struct migrate_tunnel_info *)val, sizeof(struct migrate_tunnel_info)); ++ } else if (type == HINIC3_PORT_ARG_MIGRATE_STATE) { ++ hinic3_nlattr_put_unspec(nla, type, (struct migrate_state_dir *)val, sizeof(struct migrate_state_dir)); ++ } else if (type == HINIC3_PORT_ARG_PCI_ADDR) { ++ hinic3_nlattr_put_unspec(nla, type, (struct rte_pci_addr *)val, sizeof(struct rte_pci_addr)); ++ } else if (type == HINIC3_PORT_ARG_PORT_UPCALL_QUEUE_MAP) { ++ hinic3_nlattr_put_unspec(nla, type, (uint16_t *)val, MAX_RX_QUEUE_PER_VPORT * sizeof(uint16_t)); ++ } ++ ++ return 0; ++} ++ ++static int port_smap_to_nlattr(struct hinic3_nlattr *nla, char *key, char *value) ++{ ++ enum hinic3_port_arg_type nla_type = (enum hinic3_port_arg_type)port_smap_key_to_nla_type(key); ++ if (nla_type == HINIC3_PORT_ARG_TYPE_MAX) { ++ return 0; ++ } ++ switch (nla_type) { ++ case HINIC3_PORT_ARG_VLAN_OL: ++ case HINIC3_PORT_ARG_VLAN_MODE: ++ case HINIC3_PORT_ARG_GRO_ENABLE: ++ case HINIC3_PORT_ARG_MAX_QUEUE_NUM: ++ case HINIC3_PORT_ARG_UPCALL_QUEUE_NUM: ++ return smap_to_nlattr_u8(nla, value, nla_type); ++ case HINIC3_PORT_ARG_VLAN_TAG: ++ case HINIC3_PORT_ARG_DPDK_PORT_ID: ++ case HINIC3_PORT_ARG_BUCKET_ID: ++ case HINIC3_PORT_ARG_QUEUE_SIZE: ++ return smap_to_nlattr_u16(nla, value, nla_type); ++ case HINIC3_PORT_ARG_VNI: ++ case HINIC3_PORT_ARG_IPV6_GRO_ENABLE: ++ case HINIC3_PORT_ARG_BLOCK_START: ++ case HINIC3_PORT_ARG_BLOCK_SIZE: ++ return smap_to_nlattr_u32(nla, value, nla_type); ++ case HINIC3_PORT_ARG_PORT_QUEUE_MAP: ++ case HINIC3_PORT_ARG_MIGRATE_TUNNEL_INFO: ++ case HINIC3_PORT_ARG_MIGRATE_STATE: ++ case HINIC3_PORT_ARG_PCI_ADDR: ++ case HINIC3_PORT_ARG_PORT_UPCALL_QUEUE_MAP: ++ return smap_to_nlattr_unspec(nla, value, nla_type); ++ case HINIC3_PORT_ARG_UPCALL_REUSE: ++ return smap_to_nlattr_u8(nla, value, nla_type); ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++void port_args_smap_to_nlattr(const struct smap *args, struct hinic3_nlattr *nla_args) ++{ ++ struct smap_node *node = NULL; ++ ++ HINIC3_SMAP_FOR_EACH(node, args) { ++ if (port_smap_to_nlattr(nla_args, node->key, node->value) != 0) { ++ return; ++ } ++ } ++} ++ ++static inline int nla_to_smap_u8(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++{ ++ char *value = NULL; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ snprintf(args_buf, sizeof(args_buf) - 1, "%hhu", hinic3_nlattr_get_itr_u8(nla)); ++ value = args_buf; ++ hinic3_smap_add(unset_args, key, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static inline int nla_to_smap_u16(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++{ ++ char *value = NULL; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ snprintf(args_buf, sizeof(args_buf) - 1, "%hu", hinic3_nlattr_get_itr_u16(nla)); ++ value = args_buf; ++ hinic3_smap_add(unset_args, key, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static inline int nla_to_smap_u32(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++{ ++ char *value = NULL; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ snprintf(args_buf, sizeof(args_buf) - 1, "%u", hinic3_nlattr_get_itr_u32(nla)); ++ value = args_buf; ++ hinic3_smap_add(unset_args, key, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static inline int nla_to_smap_u64(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++{ ++ char *value = NULL; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ snprintf(args_buf, sizeof(args_buf) - 1, "%"PRIu64, hinic3_nlattr_get_itr_u64(nla)); ++ value = args_buf; ++ hinic3_smap_add(unset_args, key, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static inline char *bond_get_smap_key_by_nla_type(uint32_t type) ++{ ++ if (type >= HINIC3_BOND_ARG_TYPE_MAX) { ++ return NULL; ++ } ++ ++ return g_bond_smap_key[type]; ++} ++ ++void bond_args_nlattr_to_smap(const struct hinic3_nlattr *nla_config, struct smap *smap_config) ++{ ++ const char *pstr = NULL; ++ char *smap_key = NULL; ++ hinic3_nlattr_itr nla_itr = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH (nla_itr, nla_config) { ++ smap_key = bond_get_smap_key_by_nla_type(hinic3_nlattr_get_itr_type(nla_itr)); ++ if (smap_key == NULL) { ++ continue; ++ } ++ switch (hinic3_nlattr_get_itr_type(nla_itr)) { ++ case HINIC3_BOND_ARG_BOND_MODE: ++ case HINIC3_BOND_ARG_XMIT_HASH_POLICY: ++ case HINIC3_BOND_ARG_LACP_RATE: ++ case HINIC3_BOND_ARG_LACP_STATUS: ++ if (nla_to_smap_u8(smap_config, nla_itr, smap_key) != 0) { ++ return; ++ } ++ break; ++ case HINIC3_BOND_ARG_UPDELAY: ++ case HINIC3_BOND_ARG_DOWNDELAY: ++ if (nla_to_smap_u16(smap_config, nla_itr, smap_key) != 0) { ++ return; ++ } ++ break; ++ ++ case HINIC3_BOND_ARG_ACTIVE_MAC: ++ case HINIC3_BOND_ARG_LACP_DEACTIVE_SLAVES: ++ case HINIC3_BOND_ARG_UPLINK_PCI_ID: ++ case HINIC3_BOND_ARG_SLAVES: ++ case HINIC3_BOND_ARG_SLAVE_NAME: ++ case HINIC3_BOND_ARG_ACTIVE_SLAVE: ++ pstr = hinic3_nlattr_get_itr_data(nla_itr); ++ hinic3_smap_add(smap_config, smap_key, HINIC3_CONST_CAST(char *, pstr), HINIC3_DRIVER_ADAPTER); ++ break; ++ default: ++ break; ++ } ++ } ++} ++ ++static int vport_upcall_ques_to_str(const hinic3_nlattr_itr nla, char *args, int len) ++{ ++ int off; ++ size_t i; ++ size_t nla_size; ++ const uint32_t *que_ids = NULL; ++ size_t n_que; ++ int succ_len; ++ ++ nla_size = hinic3_nlattr_get_itr_size(nla); ++ que_ids = hinic3_nlattr_get_itr_unspec(nla, nla_size); ++ n_que = nla_size / sizeof(uint32_t); ++ if (n_que > MAX_RX_QUEUE_PER_VPORT) { ++ HINIC3_LOG(ERR, VPORT, "Invalid queue ids from hiovs, n_que is %zu, max_upcall_num is %d\n", ++ n_que, MAX_RX_QUEUE_PER_VPORT); ++ return -1; ++ } ++ ++ off = 0; ++ for (i = 0; i < n_que; i++) { ++ succ_len = snprintf(args + off, len - off - 1, ++ "%u,", que_ids[i]); ++ if (succ_len <= 0) { ++ HINIC3_LOG(ERR, VPORT, "Failed to snprintf arg buf, err_len is %d", succ_len); ++ return -1; ++ } ++ ++ off += succ_len; ++ } ++ ++ /* overwrite the last ',' */ ++ if (off != 0) { ++ args[off - 1] = '\0'; ++ } ++ ++ return 0; ++} ++ ++static int port_nla_to_smap_queue_nr(struct smap *unset_args, const hinic3_nlattr_itr nla) ++{ ++ char *value = NULL; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ int rc = vport_upcall_ques_to_str(nla, args_buf, MAX_ARGS_SIZE); ++ /* attribute is invalid, error info has print in vport_upcall_ques_to_str */ ++ if (rc != 0) { ++ return -1; ++ } ++ ++ value = args_buf; ++ hinic3_smap_add(unset_args, HINIC3_PORT_UPCALL_QUEUE_MAP, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static char *get_smap_key_by_nla_type(uint32_t type) ++{ ++ if (type >= HINIC3_PORT_ARG_TYPE_MAX) { ++ return NULL; ++ } ++ ++ return g_port_smap_key[type]; ++} ++ ++static int port_nla_to_smap(struct smap *unset_args, const hinic3_nlattr_itr nla) ++{ ++ char *smap_key = get_smap_key_by_nla_type(hinic3_nlattr_get_itr_type(nla)); ++ if (smap_key == NULL) { ++ return 0; ++ } ++ ++ switch (hinic3_nlattr_get_itr_type(nla)) { ++ case HINIC3_PORT_ARG_VLAN_TAG: ++ case HINIC3_PORT_ARG_DPDK_PORT_ID: ++ case HINIC3_PORT_ARG_BUCKET_ID: ++ return nla_to_smap_u16(unset_args, nla, smap_key); ++ case HINIC3_PORT_ARG_VLAN_OL: ++ case HINIC3_PORT_ARG_VLAN_MODE: ++ case HINIC3_PORT_ARG_GRO_ENABLE: ++ case HINIC3_PORT_ARG_MAX_QUEUE_NUM: ++ return nla_to_smap_u8(unset_args, nla, smap_key); ++ case HINIC3_PORT_ARG_VNI: ++ case HINIC3_PORT_ARG_IPV6_GRO_ENABLE: ++ return nla_to_smap_u32(unset_args, nla, smap_key); ++ case HINIC3_PORT_ARG_PORT_QUEUE_MAP: ++ return nla_to_smap_u64(unset_args, nla, smap_key); ++ case HINIC3_PORT_ARG_PORT_UPCALL_QUEUE_MAP: ++ return port_nla_to_smap_queue_nr(unset_args, nla); ++ case HINIC3_PORT_ARG_MIGRATE_TUNNEL_INFO: ++ case HINIC3_PORT_ARG_MIGRATE_STATE: ++ hinic3_smap_add(unset_args, smap_key, (char *)hinic3_nlattr_get_itr_data(nla), HINIC3_DRIVER_ADAPTER); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++void port_args_nlattr_to_smap(const struct hinic3_nlattr *nla_unset_args, struct smap *unset_args) ++{ ++ hinic3_nlattr_itr nla = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH (nla, nla_unset_args) { ++ if (port_nla_to_smap(unset_args, nla) != 0) { ++ return; ++ } ++ } ++} ++ ++static int nlattr_to_smap_src_mac(struct smap *args_smap, const hinic3_nlattr_itr nla) ++{ ++ char *value = NULL; ++ const struct eth_address *macs = NULL; ++ int n_macs; ++ int ret; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ ++ macs = hinic3_nlattr_get_itr_data(nla); ++ n_macs = hinic3_nlattr_get_itr_size(nla) / sizeof(struct eth_address); ++ ret = smacs_stringfy((struct eth_addr*)macs, n_macs, args_buf, MAX_ARGS_SIZE); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BUM, "src macs stringfy error"); ++ return -EINVAL; ++ } ++ ++ value = args_buf; ++ hinic3_smap_add(args_smap, HINIC3_BUM_ARG_SRC_MAC_STR, value, HINIC3_DRIVER_ADAPTER); ++ return 0; ++} ++ ++static int nlattr_to_smap_ethertype_check(struct smap *args_smap, const hinic3_nlattr_itr nla) ++{ ++ uint8_t u8_val; ++ ++ u8_val = hinic3_nlattr_get_itr_u8(nla); ++ if (u8_val == ETHER_TYPE_CHECK_TRUE) { ++ hinic3_smap_add(args_smap, HINIC3_BUM_ARG_ETHER_TYPE_CHECK_STR, "true", HINIC3_DRIVER_ADAPTER); ++ } else if (u8_val == ETHER_TYPE_CHECK_FALSE) { ++ hinic3_smap_add(args_smap, HINIC3_BUM_ARG_ETHER_TYPE_CHECK_STR, "false", HINIC3_DRIVER_ADAPTER); ++ } else { ++ HINIC3_LOG(ERR, BUM, "ether_type_check val is invalid"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int nlattr_to_smap_extra_ethertype(struct smap *args_smap, const hinic3_nlattr_itr nla) ++{ ++ char *value = NULL; ++ const uint16_t *types = NULL; ++ int n_types; ++ int ret; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ ++ types = hinic3_nlattr_get_itr_data(nla); ++ n_types = hinic3_nlattr_get_itr_size(nla) / sizeof(uint16_t); ++ ret = extra_eth_types_stringfy(types, n_types, args_buf, MAX_ARGS_SIZE); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BUM, "extra_eth_type stringfy error"); ++ return -EINVAL; ++ } ++ ++ value = args_buf; ++ hinic3_smap_add(args_smap, HINIC3_BUM_ARG_EXTRA_ETH_TYPE_STR, value, HINIC3_DRIVER_ADAPTER); ++ ++ return 0; ++} ++ ++static int nlattr_to_smap_brd_ratelimit(struct smap *args_smap, const hinic3_nlattr_itr nla) ++{ ++ uint32_t u32_val; ++ char *value = NULL; ++ char args_buf[MAX_ARGS_SIZE] = { 0 }; ++ ++ u32_val = hinic3_nlattr_get_itr_u32(nla); ++ snprintf(args_buf, sizeof(args_buf) - 1, "%u", u32_val); ++ ++ value = args_buf; ++ hinic3_smap_add(args_smap, HINIC3_BUM_ARG_BRD_RATELIMIT_STR, value, HINIC3_DRIVER_ADAPTER); ++ ++ return 0; ++} ++ ++int bum_args_nlattr_to_smap(const struct hinic3_nlattr *args_nla, struct smap *args_smap) ++{ ++ hinic3_nlattr_itr nla = NULL; ++ int ret = 0; ++ ++ enum hinic3_bum_ether_type_check eth_type_check = 0; ++ HINIC3_NLATTR_FOR_EACH(nla, args_nla) { ++ if (hinic3_nlattr_get_itr_type(nla) == HINIC3_SECURITY_ARG_ETHER_TYPE_CHECK) { ++ eth_type_check = hinic3_nlattr_get_itr_u8(nla); ++ ret = nlattr_to_smap_ethertype_check(args_smap, nla); ++ if (ret != 0) { ++ goto err; ++ } ++ break; ++ } ++ } ++ ++ HINIC3_NLATTR_FOR_EACH(nla, args_nla) { ++ if (hinic3_nlattr_get_itr_size(nla) == 0) { ++ continue; ++ } ++ ++ switch (hinic3_nlattr_get_itr_type(nla)) { ++ case HINIC3_SECURITY_ARG_SRC_MAC: ++ ret = nlattr_to_smap_src_mac(args_smap, nla); ++ if (ret != 0) { ++ goto err; ++ } ++ break; ++ case HINIC3_SECURITY_ARG_BRD_RATELIMIT: ++ ret = nlattr_to_smap_brd_ratelimit(args_smap, nla); ++ if (ret != 0) { ++ goto err; ++ } ++ break; ++ case HINIC3_SECURITY_ARG_EXTRA_ETH_TYPE: ++ if (eth_type_check == ETHER_TYPE_CHECK_FALSE) { ++ continue; ++ } ++ ret = nlattr_to_smap_extra_ethertype(args_smap, nla); ++ if (ret != 0) { ++ goto err; ++ } ++ break; ++ case HINIC3_SECURITY_ARG_SRC_IPMAC: /* no need */ ++ default: ++ break; ++ } ++ } ++ ++err: ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.h +new file mode 100644 +index 0000000..1d58d5f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.h +@@ -0,0 +1,23 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_IFACE_PORT_UTIL_H ++#define HINIC3_IFACE_PORT_UTIL_H ++ ++#include "hinic3_nlattr.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++void port_args_smap_to_nlattr(const struct smap *args, struct hinic3_nlattr *nla_args); ++void bond_args_nlattr_to_smap(const struct hinic3_nlattr *nla_config, struct smap *smap_config); ++int bum_args_nlattr_to_smap(const struct hinic3_nlattr *args_nla, struct smap *args_smap); ++void port_args_nlattr_to_smap(const struct hinic3_nlattr *nla_unset_args, struct smap *unset_args); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HINIC3_IFACE_PORT_UTIL_H */ +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_acl_api.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_acl_api.h +new file mode 100644 +index 0000000..f04a3be +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_acl_api.h +@@ -0,0 +1,21 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#ifndef HIOVS_ACL_API_H ++#define HIOVS_ACL_API_H ++#include ++#include ++ ++enum hinic3_acl_act_type { ++ HINIC3_ACL_ACT_UPCALL, ++ HINIC3_ACL_ACT_UPCALL_TAG_DATA, ++ HINIC3_ACL_ACT_UPCALL_TAG_INDEX, ++ HINIC3_ACL_ACT_INDIRECT_COUNTER, ++ HINIC3_ACL_ACT_SET_VXLAN_RSVD0, ++ HINIC3_ACL_ACT_COUNT, ++ HINIC3_ACL_ACT_MIRROR_TX, ++ HINIC3_ACL_ACT_MIRROR_RX, ++ HINIC3_ACL_ACT_TYPE_MAX ++}; ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h +new file mode 100644 +index 0000000..e5caf62 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h +@@ -0,0 +1,1170 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HIOVS_API_H ++#define HIOVS_API_H ++ ++#include ++#include ++#include ++#include "rte_mtr.h" ++#include "hiovs_acl_api.h" ++#include "hinic3_packets_types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct eth_addr; ++ ++#define HOVS_MAX_TLV_BUF_LEN 2048 ++#define MAX_PHY_DEV_NUM 1024 ++#define HWPT_DRV_TYPE_SHIFT 1 ++#define HINIC3_MAX_SESSION_ONE_FLOW 2 ++ ++enum tag_hiovs_install_mode { ++ HIOVS_DPDK_MODE = 1, /* *< Hinic3 offload OVS only support DPDK_MODE. */ ++ HIOVS_MAX_MODE ++}; ++ ++enum hiovs_work_mode { ++ HIOVS_WORK_MODE_DEFAULT, /* *< Hinic3 offload OVS works in default mode. */ ++ HIOVS_WORK_MODE_BMGW, /* *< Hinic3 offload OVS works in BMGW mode. */ ++ HIOVS_WORK_MODE_PT_CONTAINER = 3, /* *< hinic3 offload OVS works in Container Pass-through mode. */ ++ HIOVS_WORK_MODE_ZERO_VM_PT /* *< Hinic3 offload OVS works in Zero VM Pass-through mode. */ ++}; ++ ++enum hiovs_hwpt_phy_dev_type { ++ HWPT_PHY_DEV_TYPE_PF, /* *< Device type PF. */ ++ HWPT_PHY_DEV_TYPE_VF, /* *< Device type VF. */ ++}; ++ ++enum hovs_qos_dir { ++ QOS_DIR_INGRESS, ++ QOS_DIR_EGRESS, ++ QOS_DIR_INGRESS_EGRESS, ++ QOS_DIR_MAX ++}; ++ ++enum hovs_qos_limit_type { ++ QOS_LIMIT_BANDWIDTH, ++ QOS_LIMIT_PPS, ++ QOS_LIMIT_MAX ++}; ++ ++enum hinic3_netdev_features { ++ HINIC3_NETDEV_F_10MB_HD = 1 << 0, /* *< 10 Mb half-duplex rate support. */ ++ HINIC3_NETDEV_F_10MB_FD = 1 << 1, /* *< 10 Mb full-duplex rate support. */ ++ HINIC3_NETDEV_F_100MB_HD = 1 << 2, /* *< 100 Mb half-duplex rate support. */ ++ HINIC3_NETDEV_F_100MB_FD = 1 << 3, /* *< 100 Mb full-duplex rate support. */ ++ HINIC3_NETDEV_F_1GB_HD = 1 << 4, /* *< 1 Gb half-duplex rate support. */ ++ HINIC3_NETDEV_F_1GB_FD = 1 << 5, /* *< 1 Gb full-duplex rate support. */ ++ HINIC3_NETDEV_F_10GB_FD = 1 << 6, /* *< 10 Gb full-duplex rate support. */ ++ HINIC3_NETDEV_F_40GB_FD = 1 << 7, /* *< 40 Gb full-duplex rate support. */ ++ HINIC3_NETDEV_F_100GB_FD = 1 << 8, /* *< 100 Gb full-duplex rate support. */ ++ HINIC3_NETDEV_F_1TB_FD = 1 << 9, /* *< 1 Tb full-duplex rate support. */ ++ HINIC3_NETDEV_F_OTHER = 1 << 10, /* *< Other rate, not in the list. */ ++ HINIC3_NETDEV_F_COPPER = 1 << 11, /* *< Copper medium. */ ++ HINIC3_NETDEV_F_FIBER = 1 << 12, /* *< Fiber medium. */ ++ HINIC3_NETDEV_F_AUTONEG = 1 << 13, /* *< Auto-negotiation. */ ++ HINIC3_NETDEV_F_PAUSE = 1 << 14, /* *< Pause. */ ++ HINIC3_NETDEV_F_PAUSE_ASYM = 1 << 15, /* *< Asymmetric pause. */ ++ ++ HINIC3_NETDEV_F_25GB_FD = 1 << 31, /* *< 25 Gb full-duplex rate support. */ ++}; ++ ++/** ++ * Port type. ++ */ ++enum hovs_port_type { ++ HOVS_PORT_TYPE_HWBOND = 14, /* *< port which is connected to hwbond */ ++ HOVS_PORT_TYPE_VIRTIO_VF, /* *< port which is connected to vhostagent */ ++ HOVS_PORT_TYPE_HWPT, /* *< port which is worked in hardware pass-through mode */ ++}; ++ ++enum hovs_key_format { ++ HOVS_KEY_FMT_4TUPLE, /* *< Key = LOCALTAG + SMAC + DMAC + ETHER_TYPE */ ++ HOVS_KEY_FMT_6TUPLE, /* *< Key = LOCALTAG + SMAC + DMAC + ETHER_TYPE + SIP + DIP */ ++ HOVS_KEY_FMT_9TUPLE, /* *< Key = LOCALTAG + SMAC + DMAC + ETHER_TYPE + SIP + DIP + PROTOCOL + SPORT + DPORT */ ++}; ++ ++struct hiovs_mirror_info { ++ uint32_t sessions[HINIC3_MAX_SESSION_ONE_FLOW]; // tx方向session_id在下标为1的位置,rx方向在下标为0的位置 ++ union { ++ struct { ++ uint32_t mirror_rx : 1; ++ uint32_t mirror_tx : 1; ++ uint32_t sport : 16; ++ uint32_t rsvd : 4; ++ uint32_t sampling_interval : 10; ++ } ws; ++ struct { ++ uint32_t mirror_rx : 1; ++ uint32_t mirror_tx : 1; ++ uint32_t sport : 16; ++ uint32_t rsvd : 4; ++ uint32_t sampling_interval : 10; ++ } bs; ++ uint32_t value; ++ }; ++}; ++ ++struct hovs_high_priority_protocol_cfg { ++ uint16_t protocol_l2; ++ uint16_t protocol_l3; ++ uint16_t reserve0; ++ uint16_t reserve1; ++}; ++ ++struct hiovs_mirror_session_info { ++ uint8_t enabled : 1; ++ uint8_t is_vlan : 1; ++ uint8_t is_ipv4 : 1; ++ uint8_t type : 1; // 0:vxlan镜像 1:GRE镜像 ++ uint8_t rsvd0 : 4; ++ uint8_t session_id; ++ uint8_t cutoff_len; // 镜像报文截断长度,0代表不截断 ++ uint8_t rsvd1; ++ uint16_t dest_port; ++ uint16_t vlan_tag; ++ uint8_t smac[ETH_ALEN]; ++ uint8_t dmac[ETH_ALEN]; ++ uint32_t sip[4]; ++ uint32_t dip[4]; ++ union { ++ struct { ++ uint32_t rsvd2 : 8; ++ uint32_t vxlan_rsvd0 : 24; ++ uint32_t vni : 24; ++ uint32_t rsvd3 : 8; ++ } vxlan; ++ struct { ++ uint16_t c_rsvd0_ver; ++ uint16_t protocol; ++ } gre; ++ } tunnel; ++}; ++ ++struct hovs_melem { ++ void *addr; /* *< virtual address */ ++ uint64_t iova; /* *< IO address */ ++ uint64_t page_sz; /* *< page size of underlying memory */ ++ int socket_id; /* *< NUMA socket ID */ ++ int rsvd; ++}; ++ ++struct hovs_mbuf { ++ void *buf_addr; /* *< Virtual address of segment buffer. */ ++ uint64_t buf_iova; /* *< physical address */ ++ ++ uint16_t data_off; ++ volatile int16_t refcnt_atomic; ++ uint16_t nb_segs; /* *< Number of segments. */ ++ uint16_t port; ++ ++ uint64_t ol_flags; /* *< Offload features. */ ++ ++ uint32_t packet_type; /* *< L2/L3/L4 and tunnel information. */ ++ ++ uint32_t pkt_len; /* *< Total pkt len: sum of all segments. */ ++ uint16_t data_len; /* *< Amount of data in segment buffer. */ ++ uint16_t vlan_tci; /* *< VLAN TCI (CPU order), valid if PKT_RX_VLAN is set. */ ++ ++ uint64_t rss; /* *< RSS hash result if RSS enabled */ ++ ++ uint16_t vlan_tci_outer; /* *< Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ is set. */ ++ uint16_t buf_len; /* *< Length of segment buffer. */ ++ ++ void *pool; /* *< Pool from which mbuf was allocated. */ ++ struct hovs_mbuf *next; /* *< Next segment of scattered packet. */ ++ ++ uint64_t tx_offload; ++ ++ void *shinfo; ++ ++ uint16_t priv_size; ++ uint16_t timesync; ++ uint32_t dynfield0; ++ ++ uint64_t udata64; /* *< Allow 8-byte userdata on 32-bit */ ++ ++ uint32_t internal; /* *< internal use mbuf, app set it to 0 */ ++ uint32_t dynfield1[5]; /* *< Reserved for dynamic fields. */ ++}; ++ ++typedef enum tag_ovs_vport_type { ++ OVS_VPORT_TYPE_VF = 1, ++ OVS_VPORT_TYPE_PF, /* not used */ ++ OVS_VPORT_TYPE_BOND, ++ OVS_VPORT_TYPE_MAX ++} ovs_vport_type_e; ++ ++struct hovs_callback_ops { ++ int (*hovs_malloc)(const char *type, size_t size, int socket_arg, unsigned int flags, size_t align, size_t bound, ++ bool contig, struct hovs_melem *mem); ++ int (*hovs_mfree)(void *addr); ++ ++ struct hovs_mbuf *(*hovs_mbuf_alloc)(void *mp); ++ int (*hovs_mbuf_alloc_bulk)(void *mp, struct hovs_mbuf **mbufs, uint32_t count); ++ void (*hovs_mbuf_free)(struct hovs_mbuf *m); ++}; ++ ++struct hovs_callback_ext_ops { ++ void *(*hovs_malloc_socket)(const char *type, size_t size, uint32_t align, int32_t socket_arg); ++ void (*hovs_free)(void *addr); ++ ++ const void *(*hovs_memzone_reserve)(const char *name, size_t len, int socket_id, uint32_t flags); ++ const void *(*hovs_memzone_reserve_aligned)(const char *name, size_t len, ++ int socket_id, uint32_t flags, uint32_t align); ++ int (*hovs_memzone_free)(void *mz); ++}; ++ ++struct hiovs_lib_arg { ++ enum tag_hiovs_install_mode mode; /**< hiovs lib only support HIOVS_DPDK_MODE */ ++ uint8_t ext_cb_flag; /**< extend callback flag */ ++ uint8_t ext_mp_flag; /**< whether use external mempool */ ++ uint8_t rsvd0[2]; ++ void *mempool; /**< packet memory pool */ ++ uint32_t role; /**< for hot replacement: 0-INVALID, 1-OLD, 2-NEW. ++ Set this paramenter to OLD when the lib is started for the first time. ++ Set this paramenter to NEW when the lib is started for hot replacement. */ ++ uint32_t state; /**< Indicates whether to clear resources when lib initialization fails. ++ 0-Do not clean resources, 1-Clean resources when init fail. */ ++ enum hiovs_work_mode work_mode; /**< Indicates hinic3 offload OVS work mode. */ ++ uint32_t rx_thread_num; /**< Indicates the number of thread instances for hardware flow offloading. */ ++ uint32_t flow_num; /**< Indicates the number of hareware offload flows. The unit is M. */ ++ ++ uint32_t data_room_size; /**< data room size of member 'mempool' and 'fm_mempool' */ ++ struct hovs_callback_ops cb_ops; /**< member pointer should not be null */ ++ void *fm_mempool; /**< flow monitor memory pool */ ++ uint16_t bond_rx_depth; /**< bond mgmt pf upcall queue depth */ ++ uint16_t bond_tx_depth; /**< bond mgmt pf reinject queue depth */ ++ uint16_t vport_rx_depth; /**< vport mgmt pf upcall queue depth */ ++ uint16_t vport_tx_depth; /**< vport mgmt pf reinject queue depth */ ++ uint16_t dp_hash_flow_num; ++ uint16_t max_lcore; ++ uint32_t reserved[4]; /**< reserved data */ ++ struct hovs_callback_ext_ops ext_cb_ops; ++}; ++ ++struct hovs_port_capability { ++ uint32_t supported_upcall_qnum; /* *< Max number of upcall queues for one port(vnic/hwbond). */ ++ uint8_t upcall_reuse; /* *< Indicate whether upcall reuse is supported: 1-support, 0-not support */ ++ uint8_t rsvd[3]; ++}; ++ ++struct hovs_port_upcall_info { ++ uint32_t total_upcall_qnum; /* *< Number of total upcall queues on the vf(vport) */ ++ uint32_t left_upcall_qnum; /* *< Number of idle queue on the vf(vport) */ ++ uint32_t rsvd[2]; ++}; ++ ++ ++enum hovs_fm_rule_event_type { ++ HOVS_RULE_EVENT_BIT_RETRANSMISSION, ++ HOVS_RULE_EVENT_BIT_TIMEOUT_RETRANSMISSION, ++ HOVS_RULE_EVENT_BIT_DOWNTIME, ++ HOVS_RULE_EVENT_MAX = 12 ++}; ++ ++struct hovs_fm_rule_event { ++ uint32_t event; /* *< rule event bit, see hovs_fm_rule_event_type */ ++ uint16_t rec[HOVS_RULE_EVENT_MAX]; ++ uint8_t ip_type; /* *< 0: ipv4, 1: ipv6 */ ++ uint8_t rule_id; ++ uint16_t vport_id; ++ uint32_t sip[4]; /* *< when ipv4, sip[0] is valid */ ++ uint32_t dip[4]; /* *< when ipv4, dip[0] is valid */ ++ uint16_t src_port; ++ uint16_t dst_port; ++ uint32_t max_tcp_latency; /* *< fix to zero */ ++ uint32_t max_icmp_latency; /* *< fix to zero */ ++}; ++ ++struct hovs_fm_statistics_info { ++ uint32_t max_tcp_retrans_count; /* *< max tcp retransmission count */ ++ uint32_t max_tcp_downtime; /* *< max tcp network outage */ ++ uint32_t max_tcp_timeout_retrans_cnt; /* *< max tcp timeout-retransmission count */ ++ uint32_t max_tcp_jitter; /* *< fix to zero */ ++ uint32_t avg_tcp_time; /* *< fix to zero */ ++ uint32_t max_icmp_jitter; /* *< fix to zero */ ++ uint32_t avg_icmp_time; /* *< fix to zero */ ++ uint32_t icmp_packet_lost; /* *< fix to zero */ ++}; ++ ++struct hovs_fm_vport_stats { ++ uint32_t vport_id; ++ struct hovs_fm_statistics_info stats; ++}; ++ ++enum hovs_fm_event_type { ++ HOVS_FM_EVENT_PERIODICAL_VPORT_REPORT, ++ HOVS_FM_EVENT_PERIODICAL_RULE_REPORT, ++ HOVS_FM_EVENT_THRESHOLD_RULE_REPORT, ++ HOVS_FM_EVENT_MAX ++}; ++ ++struct hovs_fm_report { ++ uint16_t report_type; /* *< see hovs_fm_event_type */ ++ union { ++ struct hovs_fm_vport_stats stats_report; ++ struct hovs_fm_rule_event rule_report; ++ }; ++}; ++ ++enum { ++ HOVS_ENG_CAP_F_BATCH_DEL, ++ HOVS_ENG_CAP_F_OFFLOAD_RAW_IP, ++ HOVS_ENG_CAP_F_OFFLOAD_ETHERNET, ++ HOVS_ENG_CAP_F_STATS_SYNC_PULL, ++ HOVS_ENG_CAP_F_OFFLOAD_ICMP, ++ HOVS_ENG_CAP_F_OFFLOAD_IPV6, ++ HOVS_ENG_CAP_F_OFFLOAD_ICMPV6, ++ HOVS_ENG_CAP_F_OFFLOAD_3TUPLE, ++ HOVS_ENG_CAP_F_ASYNC_FLUSH, ++ HOVS_ENG_CAP_F_MAX ++}; ++ ++struct hovs_flow_capability { ++ uint32_t vendor_id; /* *< Unique identifier */ ++ uint32_t supported_dev_types; /* *< Bitmap of ports in "enum hovs_port_type" */ ++ uint32_t supported_actions; /* *< Bitmap of actions in "enum hinic3_flow_action_type" */ ++ uint8_t key_format_type; /* *< Bitmap of key format in "enum hinic3_key_format" */ ++ uint8_t cleanup_max_level; /* *< 0 : don't cleanup hardware flow even hardware table is full */ ++ uint16_t flags; /* *< Bitmap of cap in HOVS_ENG_CAP_F_xxx */ ++ uint32_t max_flow_size; /* *< Max flow context num */ ++ uint32_t rx_thread_num; /* *< Max rx thread num for flow response pull */ ++}; ++ ++/** ++ * Reinject packet to NIC from OVS, send the packet to vf or bond port. ++ * ++ * @param dpdk_port_id unused. ++ * @param dpdk_queue_id reinject queue id. ++ * @param tx_pkts The address of an array of *nb_pkts* pointers to *udk_mbuf* structures ++ * which contain the output packets. ++ * @param nb_pkts The maximum number of packets to transmit. ++ * @return ++ * - The number of transmitted packets ++ */ ++uint16_t hovs_rte_tx_burst(uint16_t dpdk_port_id, uint16_t dpdk_queue_id, void **tx_pkts, uint16_t nb_pkts); ++ ++/** ++ * Upcall packet to OVS from NIC, receive packet to ovs. ++ * ++ * @param dpdk_port_id sub table for flow flush, others unused ++ * @param dpdk_queue_id queue id for upcall packet, HINIC3_PTHREAD_ACK/HINIC3_PTHREAD_AGING for flow ++ * @param[out] rx_pkts The address of an array of pointers to *udk_mbuf* structures that ++ * must be large enough to store *nb_pkts* pointers in it. ++ * @param[out] nb_pkts The maximum number of packets to retrieve. ++ * @return ++ * - The number of received packets ++ */ ++uint16_t hovs_rte_rx_burst(uint16_t dpdk_port_id, uint16_t dpdk_queue_id, void **rx_pkts, uint16_t nb_pkts); ++ ++ ++/** ++ * vPort API Class ++ */ ++struct hovs_port_stats { ++ uint64_t rx_pkts; /* *< Total packets received. */ ++ uint64_t tx_pkts; /* *< Total packets transmitted. */ ++ uint64_t rx_bytes; /* *< Total bytes received. */ ++ uint64_t tx_bytes; /* *< Total bytes transmitted. */ ++ uint64_t rx_errors; /* *< Bad packets received. */ ++ uint64_t tx_errors; /* *< Packet transmit problems. */ ++ uint64_t rx_dropped; /* *< No buffer space. */ ++ uint64_t tx_dropped; /* *< No buffer space. */ ++ uint64_t tx_multicast_dropped; /* *< No buffer space. */ ++ uint64_t collisions; ++ ++ /* Detailed receive errors. */ ++ uint64_t rx_length_errors; ++ uint64_t rx_over_errors; /* *< Receiver ring buff overflow. */ ++ uint64_t rx_crc_errors; /* *< Recved pkt with crc error. */ ++ uint64_t rx_frame_errors; /* *< Recv'd frame alignment error. */ ++ uint64_t rx_fifo_errors; /* *< Recv'r fifo overrun . */ ++ uint64_t rx_missed_errors; /* *< Receiver missed packet. */ ++ ++ /* Detailed transmit errors. */ ++ uint64_t tx_aborted_errors; ++ uint64_t tx_carrier_errors; ++ uint64_t tx_fifo_errors; ++ uint64_t tx_heartbeat_errors; ++ uint64_t tx_window_errors; ++ ++ uint64_t timestamp; ++ ++ /* ucode counter */ ++ uint32_t tx_bond_mode_err_dropped; ++ uint32_t tx_bond_noport_dropped; ++ uint32_t tx_bcmc_limit_dropped; ++ uint32_t tx_bum_smac_dropped; ++ uint32_t tx_bum_sipsmac_dropped; ++ uint32_t tx_bum_ethtype_dropped; ++ uint32_t rx_wqe_fail_dropped; ++ uint32_t rx_qos_dropped; ++ uint32_t rx_mtu_dropped; ++ uint32_t rx_vport_invalid_dropped; ++ uint32_t ct_dropped; /* *< tx_drop:vport type is function; else rx_drop */ ++ uint32_t upcall_wqe_fail_dropped; ++ ++ uint64_t upcall_pkt_num_vport; ++ uint64_t tx_uc_bytes; /* *< only valid when vport type is function */ ++ uint64_t tx_uc_pkts; ++ uint64_t tx_bc_bytes; /* *< only valid when vport type is function */ ++ uint64_t tx_bc_pkts; ++ uint64_t tx_mc_bytes; /* *< only valid when vport type is function */ ++ uint64_t tx_mc_pkts; ++ uint64_t rx_uc_bytes; /* *< only valid when vport type is function */ ++ uint64_t rx_uc_pkts; ++ uint64_t rx_bc_bytes; /* *< only valid when vport type is function */ ++ uint64_t rx_bc_pkts; ++ uint64_t rx_mc_bytes; /* *< only valid when vport type is function */ ++ uint64_t rx_mc_pkts; ++ ++ uint32_t upcall_no_sge_dropped; /* upcall pre-drop without sge */ ++ uint32_t rss_q_invalid_dropped; /* rss queue invalid drop, only valid for vport */ ++ uint32_t rq_bp_dropped; /* only valid when vport type is function */ ++ uint32_t lacp_rx_nowqe_dropped; /* only valid when vport type is bond */ ++ uint16_t ipfrag_upcall_limit_dropped; ++ uint16_t rsvd0; ++ uint32_t rsvd[5]; ++}; ++ ++/** ++ * global statistics ++ */ ++struct hovs_global_stats { ++ uint32_t offload_flow_num; ++ uint32_t offload_qpc_num; ++ uint32_t same_flow_with_multi_gpa; ++ uint32_t vxlan_rx_vtep_miss; ++ uint32_t upcall_pf_invalid_dropped[6]; ++ uint32_t upcall_pf_rx_wqe_fail_dropped[6]; ++ ++ uint64_t upcall_limit_drop_total; ++ uint64_t upcall_from_vf_total; ++ uint64_t upcall_from_hwbond_total; ++ uint64_t flow_default_upcall; ++ uint64_t flow_miss_upcall; ++ uint64_t flow_invalid_upcall; ++ uint64_t qu_prefetch_statics_fail; ++ ++ uint32_t tso_space_invalid_dropped; ++ uint32_t output_type_invalid_dropped; ++ uint32_t lacp_tx_dst_err_dropped; ++ uint32_t lldp_tx_dst_err_dropped; ++ uint32_t arp_tx_dst_err_dropped; ++ uint32_t p0_rx_bp_drop; ++ uint32_t p1_rx_bp_drop; ++ uint32_t p2_rx_bp_drop; ++ uint32_t p3_rx_bp_drop; ++ uint32_t rsvd[5]; ++}; ++ ++struct hovs_flow_stats { ++ uint64_t packet_count; /* *< Number of packets matched. */ ++ uint64_t byte_count; /* *< Number of bytes matched. */ ++ uint64_t ct_loss_pkts; /* *< Number of packets dropped for CT failure. */ ++ uint32_t live_time; /* *< Remain life time of flow, unit : ms */ ++ uint32_t age_time; /* *< Total life time of flow, unit : ms */ ++ uint16_t tcp_flags; ++ uint8_t block[128]; ++}; ++ ++enum qos_type_limit { ++ QOS_TYPE_FUNC_LIMIT = 0, ++ QOS_TYPE_VM_LIMIT, ++ QOS_TYPE_FLOW_LIMIT, ++ QOS_TYPE_NET_LIMIT, ++ QOS_TYPE_MAX, ++}; ++ ++struct hovs_qos_stats { ++ uint32_t qos_type; /* *< 0:func limit 1:vm limit */ ++ uint32_t index; /* *< when qos_type=0: index=func_id, qos_type=1:index=vm_id */ ++ uint32_t rx_drop_num; ++ uint32_t tx_drop_num; ++ uint32_t reserved0; /* *< reserved for later */ ++ uint32_t reserved1; /* *< reserved for later */ ++}; ++ ++struct hovs_dpif_flow { ++ const struct nlattr *key; /* *< Flow to Put */ ++ size_t key_len; /* *< length of key in bytes */ ++ const struct nlattr *mask; /* *< mask to put */ ++ size_t mask_len; /* *< length of mask in bytes */ ++ const struct nlattr *actions; /* *< actions to perform on flow */ ++ size_t action_len; ++ uint8_t mask_present; ++ uint64_t hw_ufid; ++ struct hovs_flow_stats stats; ++}; ++ ++struct hovs_dpif_flow_for_get { ++ struct nlattr *key; /* *< Flow to get */ ++ size_t key_len; /* *< length of key in bytes */ ++ struct nlattr *mask; /* *< mask to get */ ++ size_t mask_len; /* *< length of mask in bytes */ ++ struct nlattr *actions; /* *< actions to perform on flow */ ++ size_t action_len; ++ uint8_t mask_present; ++ uint64_t hw_ufid; ++ uint64_t related_hw_ufid; ++ struct hovs_flow_stats stats; ++}; ++ ++struct hovs_eth_addr { ++ union { ++ uint8_t ea[6]; ++ uint16_t be16[3]; /* *< network order */ ++ }; ++}; ++ ++struct hovs_src_ipmac { ++ uint32_t ip_addr; ++ struct hovs_eth_addr mac_addr; ++}; ++ ++struct hovs_slave_info { ++ struct nlattr *slave_info; ++ uint32_t args_len; ++}; ++ ++struct hovs_pci_addr { ++ uint32_t domain; /* Device domain */ ++ uint8_t bus; /* Device bus */ ++ uint8_t devid; /* Device ID */ ++ uint8_t function; /* Device function */ ++}; ++ ++struct hovs_pci_addr_info { ++ struct hovs_pci_addr pci_addr; ++ uint8_t type; ++ union { ++ uint16_t max_queue_num; ++ uint16_t glb_func_inx; ++ }; ++}; ++ ++struct hovs_phy_dev_info { ++ uint32_t phy_dev_num; ++ struct hovs_pci_addr_info pci_info[MAX_PHY_DEV_NUM]; ++}; ++ ++struct hovs_acl_indir_stats { ++ uint64_t packet_count; ++ uint64_t byte_count; ++}; ++ ++struct hovs_bond_slave_stats { ++ uint64_t vld_slave; ++ uint64_t rx_pkts[4]; ++ uint64_t tx_pkts[4]; ++ uint64_t rx_bytes[4]; ++ uint64_t tx_bytes[4]; ++}; ++/** ++ * Add a virtual NIC port and associate it with a VF. ++ * ++ * @param[out] port_id Output the generated port ID after the vNIC is add successfully. ++ * @param pci_addr The PCI address of the port to be added. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_EEXEC: if api execute fail. ++ * - HIOVS_ERROR: if the queue for this port is not enough. ++ */ ++int hovs_port_mgmt_add(uint16_t *port_id, void *pci_addr); ++ ++/** ++ * Add a virtual NIC port that supports dynamic queues and associate it with a VF. ++ * ++ * @param[out] port_id Output the generated port ID after the vNIC is add successfully. ++ * @param args TLV format: configuration information about the port. ++ * Including the PCIe address, number of upcall queues, and dynamic queue information. ++ * @param args_len The length of the parameter args. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_EEXEC: if API execute fail. ++ * - HIOVS_ERROR: if the parameter check fails. ++ */ ++int hovs_port_mgmt_add_dynamic(uint16_t *port_id, const struct nlattr *args, uint32_t args_len); ++ ++/** ++ * Delete a virtual NIC port ++ * ++ * @param port_id The port_id of vNIC to be deleted. ++ */ ++void hovs_port_mgmt_del(uint16_t port_id); ++ ++/** ++ * Query a virtual NIC port base on args. ++ * ++ * @param[out] port_id Output the generated port ID base on args. ++ * @param args TLV format: configuration information about the port. ++ * Including the HINIC3_PORT_ARG_PCI_ADDR, HINIC3_PORT_ARG_FAKE_BDF. ++ * @param args_len The length of the parameter args. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_port_mgmt_query_flexible(const struct nlattr *args, uint32_t args_len, uint16_t *port_id); ++ ++/* * ++ * Query the configuration of a port. Supports query configurations in batches. ++ * ++ * @param port_id The port_id of vNIC to be queried. ++ * @param[out] args TLV format: List of attribute obtained by querying. @ref enum hinic3_port_arg_type ++ * - HINIC3_PORT_ARG_DPDK_PORT_ID ++ * - HINIC3_PORT_ARG_PORT_UPCALL_QUEUE_MAP ++ * @param[out] args_len The length of the result args. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_port_mgmt_get(uint16_t port_id, struct nlattr *args, uint32_t *args_len); ++ ++/** ++ * Set the configuration of a port. Supports set configurations in batches. ++ * ++ * @param port_id The port_id of vNIC to be set. ++ * @param args TLV format: List of attributes to be set. @ref enum hinic3_port_arg_type ++ * - HINIC3_PORT_ARG_VLAN_TAG ++ * - HINIC3_PORT_ARG_VNI ++ * - HINIC3_PORT_ARG_BUCKET_ID ++ * @param args_len The length of the parameter args. ++ * @param unset_args TLV format: unsupport. ++ * @param unset_args_len The length of the parameter unset_args. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_port_mgmt_set(uint16_t port_id, const struct nlattr *args, uint32_t args_len, struct nlattr *unset_args, ++ uint32_t *unset_args_len); ++ ++/** ++ * Get port capability. ++ * ++ * @param cap Port capability. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_port_mgmt_get_capability(struct hovs_port_capability *cap); ++ ++/** ++ * Get upcall info. ++ * ++ * @param info Port upcall info. Include the number of total upcall queues and the left number of upcall queues. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_port_mgmt_get_upcall_info(struct hovs_port_upcall_info *info); ++ ++ ++int hovs_port_mgmt_setup_upcall_queue(uint16_t port_id, uint16_t qid, unsigned int socket_id, void *mp); ++/** ++ * Create bond. ++ * This interface is used to create a virtual bond port. ++ * ++ * @param mode unused ++ * @param name The name of bond device. ++ * @param[out] bond_port_id Output the bond_port_id after the bond is created successfully. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_bond_mgmt_create(uint8_t mode, const char *name, uint16_t *bond_port_id); ++ ++/** ++ * Delete bond. ++ * This interface is used to delete the bond port and delete the synchronization between the bond port and ++ * linux-kernel bonding. ++ * ++ * @param bond_port_id The ID of bond_port to be deleted. ++ */ ++void hovs_bond_mgmt_delete(uint16_t bond_port_id); ++ ++/** ++ * Get bond configuration. ++ * The ovs bond is synchronized from the linux-kernel bonding interface. This interface is used to get the linux-kernel ++ * bonding status. ++ * ++ * @param bond_port_id The ID of bond_port. ++ * @param[out] args TLV format: List of attribute obtained by querying. @ref enum hinic3_bond_arg_type ++ * - HINIC3_BOND_ARG_UPLINK_PCI_ID ++ * - HINIC3_BOND_ARG_SLAVES ++ * - HINIC3_BOND_ARG_SLAVE_NAME ++ * @param[out] args_len The length of the parameter args. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_bond_mgmt_get(uint16_t bond_port_id, struct nlattr *args, uint32_t *args_len); ++ ++/** ++ * Get the mac address of vport. ++ * ++ * @param port_id The vport id, only support the mac address of bond port can be query. unsupport vf port now. ++ * @param[out] mac The mac address. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_etheraddr_get(uint16_t port_id, struct hovs_eth_addr *mac); ++ ++/** ++ * Set the mac address of vport. ++ * ++ * @param port_id The vport id, only support the mac address of bond port can be set. unsupport vf port now. ++ * @param mac The mac address. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_etheraddr_set(uint16_t port_id, const struct hovs_eth_addr mac); ++ ++/** ++ * Set the mtu of vport. ++ * ++ * @param port_id The vport id, only support the mtu of bond port can be set. unsupport vf port now. ++ * @param mtu The mtu [256, 9216]. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_mtu_set(uint16_t port_id, int mtu); ++ ++/** ++ * Get the statistics of vNIC. ++ * ++ * @param port_id The port_id of vNIC. ++ * @param[out] stats Output the statistics info of vNIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if API execute fail. ++ */ ++int hovs_port_statistics_get(uint16_t port_id, struct hovs_port_stats *stats); ++ ++/** ++ * Clear the statistics of vNIC. ++ * ++ * @param port_id The port_id of vNIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_port_statistics_flush(uint16_t port_id); ++ ++/** ++ * Get BUM configuration. ++ * ++ * @param port_id The port_id of vNIC. ++ * @param[out] args TLV format: List of attribute obtained by querying. @ref enum hinic3_bum_arg_type ++ * - HINIC3_BUM_ARG_SRC_MAC ++ * - HINIC3_BUM_ARG_BRD_RATELIMIT ++ * - HINIC3_BUM_ARG_ETHER_TYPE_CHECK ++ * - HINIC3_BUM_ARG_EXTRA_ETH_TYPE ++ * @param[out] args_len The length of the parameter args. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_bum_get(uint16_t port_id, struct nlattr *args, uint32_t *args_len); ++ ++int hovs_bum_set(uint16_t port_id, const struct nlattr *args, uint32_t args_len, struct nlattr *unset_args, ++ uint32_t *unset_args_len); ++ ++int hovs_bum_remove(uint16_t port_id, const struct nlattr *args, uint32_t args_len); ++ ++/** ++ * Clear BUM configuration. ++ * ++ * @param bond_port_id The port_id of vNIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_bum_clear(uint16_t port_id); ++ ++/** ++ * Get the forward mode of the hardware offload flow. ++ * ++ * @param[out] forward_mode The forward mode obtained from the NIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_flow_mgmt_get_forward_mode(uint8_t *forward_mode); ++ ++int hovs_flow_mgmt_set_forward_mode(uint8_t forward_mode); ++ ++int hovs_flow_mgmt_put(const struct hovs_dpif_flow *put, const struct nlattr *args, size_t args_len); ++ ++/** ++ * Get a hardware offload flow table based on the key. ++ * ++ * @param key The flow key. ++ * @param key_len The length of flow key. ++ * @param[out] get Obtained flow table result ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ * - HIOVS_EEMPTY: if flow is not existed. ++ */ ++int hovs_flow_mgmt_get_by_key(const struct nlattr *key, size_t key_len, ++ struct hovs_dpif_flow_for_get *get); ++ ++int hovs_flow_mgmt_get_by_ufid(uint64_t ufid, struct hovs_dpif_flow_for_get *get); ++ ++int hovs_flow_mgmt_del_by_key(const struct nlattr *key, size_t key_len); ++ ++int hovs_flow_mgmt_del_by_ufid(uint64_t ufid); ++ ++int hovs_flow_mgmt_del_by_batch(const uint64_t *ufids, struct hovs_dpif_flow_for_get **flows, const size_t cnt); ++ ++ ++int hovs_flow_mgmt_flush(void); ++ ++ ++int hovs_flow_mgmt_dump_start(void **state); ++ ++int hovs_flow_mgmt_dump_next(void *state, struct hovs_dpif_flow_for_get *dump); ++ ++int hovs_flow_mgmt_dump_done(void *state); ++ ++int hovs_flow_mgmt_get_maxflows(uint32_t *max_flows); ++ ++int hovs_flow_mgmt_get_capability(struct hovs_flow_capability *cap); ++ ++int hovs_statistics_flow_get_by_ufid(const uint64_t *ufid, const size_t cnt, struct hovs_flow_stats *stats); ++ ++/** ++ * Flush the the flow statistics in batch. ++ * ++ * @param ufid The ID of united flow. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_statistics_flow_flush_by_ufid(uint64_t ufid); ++ ++typedef int (*hovs_flow_callback_t)(uint64_t ufid, const struct hovs_dpif_flow_for_get *flow, const struct nlattr *args, ++ size_t args_len); ++ ++ ++hovs_flow_callback_t hovs_flow_callback_register(hovs_flow_callback_t cb); ++ ++int hovs_global_cfg_set(const struct nlattr *args, size_t args_len, struct nlattr *unset_args, size_t *unset_args_len); ++ ++int hovs_global_cfg_get(struct nlattr *args, size_t *args_len); ++ ++/** ++ * Get the the global statistics, include offload stats, upcall stats, other drop stats. ++ * ++ * @param[out] stats Output the the global statistics. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_global_statistics_get(struct hovs_global_stats *stats); ++ ++/** ++ * Flush the the global statistics. ++ * ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_global_statistics_flush(void); ++ ++int hovs_mml_lib(const char *buf_in, uint32_t in_size, char *buf_out, uint32_t *out_len, uint32_t max_buf_out_len); ++ ++/** ++ * hiovs lib initialize. ++ * ++ * @param arg Input parameters: @ref struct hiovs_lib_arg ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int32_t hovs_lib_init(void *arg); ++ ++int hovs_lib_deinit(void *arg); ++ ++int hovs_open_log(uint32_t module_type, uint32_t enable); ++ ++int hovs_set_log_level(uint32_t module_type, uint32_t log_level); ++ ++struct hovs_qos_stats_batch { ++ union { ++ uint32_t rx_drop_num; ++ uint32_t flow_qos_drop_num; ++ }; ++ uint32_t tx_drop_num; ++}; ++ ++int hovs_qos_statistics_get_batch(uint16_t type, uint16_t *ids, struct hovs_qos_stats_batch *stats, size_t cnt); ++ ++struct hovs_qos_stats_batch_all { ++ struct hovs_qos_stats_batch drop_pkg_num; ++ union { ++ uint64_t rx_drop_byte_num; ++ uint64_t flow_qos_drop_byte_num; ++ }; ++ uint64_t tx_drop_byte_num; ++}; ++ ++struct hovs_hqos_stats_batch_all { ++ uint64_t tx_pkts[RTE_COLORS]; ++ uint64_t tx_bytes[RTE_COLORS]; ++ uint64_t tx_drop_pkts; ++ uint64_t tx_drop_bytes; ++ uint64_t rx_pkts[RTE_COLORS]; ++ uint64_t rx_bytes[RTE_COLORS]; ++ uint64_t rx_drop_pkts; ++ uint64_t rx_drop_bytes; ++}; ++ ++int hovs_qos_statistics_get_all_batch(uint16_t type, uint16_t *ids, struct hovs_qos_stats_batch_all *stats, ++ size_t cnt); ++ ++/** ++ * Get the QoS for stats. ++ * ++ * @param type The type of QoS, [0:func limit, 1:vm limit, 3:flow limit, 4:net limit]. ++ * @param ids The id of QoS, [func limit: vport_id, vm limit: vm_id, flow limit: ufid, net limit: net_id]. ++ * @param[out] stats The QoS statistics. ++ * @param[out] cnt Array size of ids. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_hqos_statistics_get_all_batch(uint16_t type, uint16_t *ids, struct hovs_hqos_stats_batch_all *stats, ++ size_t cnt); ++ ++/** ++ * Clear the QoS for stats. ++ * ++ * @param type The type of QoS, [0:func limit, 1:vm limit, 3:flow limit, 4:net limit]. ++ * @param ids The id of QoS, [func limit: vport_id, vm limit: vm_id, flow limit: ufid, net limit: net_id]. ++ * @param[out] cnt Array size of ids. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_hqos_statistics_clear_batch(uint16_t type, uint16_t dir, uint16_t *ids, size_t cnt); ++ ++/* * ++ * Set the QoS limiting for a virtual machine. ++ * ++ * @attention Port rate limiting and vm rate limiting cannot be used at the same time. ++ * @param group_id The ID of virtual machine, [1 ~ 255]. ++ * @param dir 0-ingress(vm -> NIC, vm tx), 1-egress(NIC -> vm, vm rx), 2-both ingress and egress ++ * @param type 0-bandwidth, 1-pps ++ * @param max_rate PIR : min_rate ~ 400000000 kbps(400Gbps) for bandwidth. ++ * min_rate ~ 128000 pps for pps. ++ * If the rate is 0, configure the value as the maximum value. ++ * @param max_burst PBS : min_burst ~ 2560000 kbits(2.56Gbits) for bandwidth. ++ * min_burst ~ 1000 packets for pps ++ * If the burst is 0, configure the value as the maximum value. ++ * @param min_rate CIR : 0 ~ 400000000 kbps(400Gbps) for bandwidth. ++ * 0 ~ 128000 pps for pps. ++ * If the rate is 0, configure the value as the maximum value. ++ * @param min_burst CBS : 0 ~ 2560000 kbits(2.56Gbits) for bandwidth. ++ * 0 ~ 1000 packets for pps. ++ * If the burst is 0, configure the value as the maximum value. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_vm_limit_set(uint16_t group_id, uint16_t dir, uint16_t type, uint64_t max_rate, uint64_t max_burst, ++ uint64_t min_rate, uint64_t min_burst); ++ ++/** ++ * Get the QoS limiting for a virtual machine. ++ * ++ * @attention Port rate limiting and vm rate limiting cannot be used at the same time. ++ * @param group_id The ID of virtual machine. ++ * @param dir 0-ingress(vm -> NIC, vm tx), 1-egress(NIC -> vm, vm rx), 2-both ingress and egress ++ * @param type 0-bandwidth, 1-pps ++ * @param[out] max_rate VM PIR/kbps/pps obtained from the NIC. ++ * @param[out] max_burst VM PBS/kbits/packets obtained from the NIC. ++ * @param[out] min_rate VM CIR/kbps/pps obtained from the NIC. ++ * @param[out] min_burst VM CBS/kbits/packets obtained from the NIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_vm_limit_get(uint16_t group_id, uint16_t dir, uint16_t type, uint64_t *max_rate, uint64_t *max_burst, ++ uint64_t *min_rate, uint64_t *min_burst); ++ ++/** ++ * Set the QoS limiting for a virtual machine using srTCM. ++ * ++ * @attention 1. Port rate limiting and vm rate limiting cannot be used at the same time. ++ * 2. Call the trTCM hardware engine to simulate srTCM algorithm interface. ++ * 3. If CIR is 0 or maximum, configure CIR and CBS as the maximum value, configure EBS as 0. ++ * 4. If CBS is 0, configure CBS as the maximum value. ++ * 5. If EBS is 0, the algorithm changes to single rate single bucket. ++ * 6. CBS + EBS <= max and EBS < max, max is 2560000 kbits(2.56Gbits) for bandwidth or 1000 packets for pps. ++ * @param group_id The ID of virtual machine. ++ * @param dir 0-ingress(vm -> NIC, vm tx), 1-egress(NIC -> vm, vm rx), 2-both ingress and egress ++ * @param type 0-bandwidth, 1-pps ++ * @param min_rate CIR : 0 ~ 400000000 kbps(400Gbps) for bandwidth. ++ * 0 ~ 128000 pps for pps. ++ * @param min_burst CBS : 0 ~ (2560000 - EBS) kbits(2.56Gbits) for bandwidth. ++ * 0 ~ (1000 - EBS) packets for pps. ++ * @param exs_burst EBS : 0 ~ (2560000 - CBS) kbits(2.56Gbits) for bandwidth. ++ * 0 ~ (1000 - CBS) packets for pps. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_vm_srtcm_limit_set(uint16_t group_id, uint16_t dir, uint16_t type, ++ uint64_t min_rate, uint64_t min_burst, uint64_t exs_burst); ++ ++/** ++ * Get the QoS limiting for a virtual machine using srTCM. ++ * ++ * @attention 1. Port rate limiting and vm rate limiting cannot be used at the same time. ++ * 2. Call the trTCM hardware engine to simulate srTCM algorithm interface. ++ * @param group_id The ID of virtual machine. ++ * @param dir 0-ingress(vm -> NIC, vm tx), 1-egress(NIC -> vm, vm rx), 2-both ingress and egress ++ * @param type 0-bandwidth, 1-pps ++ * @param[out] min_rate VM CIR/kbps/pps obtained from the NIC. ++ * @param[out] min_burst VM CBS/kbits/packets obtained from the NIC. ++ * @param[out] exs_burst VM EBS/kbits/packets obtained from the NIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_vm_srtcm_limit_get(uint16_t group_id, uint16_t dir, uint16_t type, ++ uint64_t *min_rate, uint64_t *min_burst, uint64_t *exs_burst); ++ ++/* * ++ * Set the QoS limiting for a port. ++ * ++ * @param port_id The ID of port, [1 ~ 4095]. ++ * @param dir 0-ingress(vm -> NIC, vm tx), 1-egress(NIC -> vm, vm rx) ++ * @param type 0-bandwidth, 1-pps ++ * @param max_rate PIR : min_rate ~ 400000000 kbps(400Gbps) for bandwidth. ++ * min_rate ~ 128000 pps for pps. ++ * If the rate is 0, configure the value as the maximum value. ++ * @param max_burst PBS : min_burst ~ 2560000 kbits(2.56Gbits) for bandwidth. ++ * min_burst ~ 1000 packets for pps ++ * If the burst is 0, configure the value as the maximum value. ++ * @param min_rate CIR : 0 ~ 400000000 kbps(400Gbps) for bandwidth. ++ * 0 ~ 128000 pps for pps. ++ * If the rate is 0, configure the value as the maximum value. ++ * @param min_burst CBS : 0 ~ 2560000 kbits(2.56Gbits) for bandwidth. ++ * 0 ~ 1000 packets for pps. ++ * If the burst is 0, configure the value as the maximum value. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_vport_limit_set(uint16_t port_id, uint16_t dir, uint16_t type, ++ uint64_t max_rate, uint64_t max_burst, uint64_t min_rate, uint64_t min_burst); ++ ++/** ++ * Get the QoS limiting for a port. ++ * ++ * @param port_id The ID of port. ++ * @param dir 0-ingress(vm -> NIC, vm tx), 1-egress(NIC -> vm, vm rx) ++ * @param type 0-bandwidth, 1-pps ++ * @param[out] max_rate VM PIR/kbps/pps obtained from the NIC. ++ * @param[out] max_burst VM PBS/kbits/packets obtained from the NIC. ++ * @param[out] min_rate VM CIR/kbps/pps obtained from the NIC. ++ * @param[out] min_burst VM CBS/kbits/packets obtained from the NIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_vport_limit_get(uint16_t port_id, uint16_t dir, uint16_t type, ++ uint64_t max_rate, uint64_t max_burst, uint64_t min_rate, uint64_t min_burst); ++ ++/** ++ * Set the QoS limiting for a net. ++ * ++ * @param dir 0-ingress(net -> NIC, net tx), 1-egress(NIC -> net, net rx) ++ * @param type 0-bandwidth, 1-pps ++ * @param[out] max_rate net PIR/kbps/pps obtained from the NIC. ++ * @param[out] max_burst net PBS/kbits/packets obtained from the NIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_net_limit_set(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t max_rate, uint64_t max_burst); ++ ++/** ++ * Set the QoS limiting for a net. ++ * ++ * @param dir 0-ingress(net -> NIC, net tx), 1-egress(NIC -> net, net rx) ++ * @param type 0-bandwidth, 1-pps ++ * @param[out] max_rate net PIR/kbps/pps obtained from the NIC. ++ * @param[out] max_burst net PBS/kbits/packets obtained from the NIC. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_qos_net_limit_get(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t *max_rate, uint64_t *max_burst); ++ ++/** ++ * Get the pcie list. ++ * @attention only support front_back is 1, which means get front-end pcie list. ++ * @param front_back 1-front end, 0-back end. ++ * @param bdf_type see enum hiovs_bdf_type ++ * @param[out] dev pcie list ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_global_pcie_list_query(uint8_t front_back, uint8_t bdf_type, struct hovs_phy_dev_info *dev); ++ ++/** ++ * Set high priority upcall queue ++ * ++ * @param port_id The indirect id to be freed ++ * @param cfgs The Array of constraints ++ * @param config_num Length of the cfgs array ++ * @param upcall_queue_num Length of the upcall queue ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_port_mgmt_set_upcall_priority(uint16_t port_id, ++ struct hovs_high_priority_protocol_cfg cfgs[], ++ uint32_t config_num, ++ uint8_t upcall_queue_num); ++ ++ ++int hovs_bond_slave_statistics_get(uint16_t port_id, struct hovs_bond_slave_stats *stats); ++ ++int hovs_port_mgmt_set_usage_state(uint16_t port_id, uint16_t status); ++ ++int hovs_port_mgmt_get_usage_state(uint16_t port_id, uint32_t *device_status); ++ ++int hovs_upcall_mtu_set(uint8_t type, int mtu); ++ ++int hovs_flow_mgmt_get_block_table_size(uint32_t *block_num); ++ ++int hovs_flow_mgmt_update(const struct hovs_dpif_flow *modify, const struct nlattr *args, size_t args_len); ++ ++void hovs_flow_mgmt_set_block_version(uint32_t block_num, uint16_t block_id[], uint16_t block_version[], int result[]); ++ ++int hovs_flow_mgmt_get_block_version(uint32_t block_num, uint16_t block_id[], uint16_t block_version[]); ++ ++int hovs_qos_flow_limit_set(uint16_t qos_id, uint64_t max_rate, uint64_t max_burst, ++ uint64_t min_rate, uint64_t min_burst); ++ ++int hovs_qos_flow_limit_get(uint16_t qos_id, uint64_t *max_rate, uint64_t *max_burst, ++ uint64_t *min_rate, uint64_t *min_burst); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.c b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.c +new file mode 100644 +index 0000000..394a923 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.c +@@ -0,0 +1,22 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_age_delete_flow_public.h" ++ ++#include "hinic3_iface_flow.h" ++#include "hinic3_provider.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_log.h" ++#define HINIC3_AGE_RX_BURST_MAX 8 ++ ++void hinic3_thread_rx_hw_age_info(uint32_t thread_id, const struct hinic3_dp_extend_info *dp_info) ++{ ++ if (dp_info == NULL) { ++ return; ++ } ++ struct rte_mbuf *buffer[HINIC3_THREAD_RX_BURST_MAX] = {0}; ++ (void)hinic3_global_rte_eth_rx_burst((uint16_t)thread_id, (uint16_t)HINIC3_PTHREAD_AGING, buffer, ++ HINIC3_AGE_RX_BURST_MAX); ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.h b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.h +new file mode 100644 +index 0000000..3abc1bb +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_age_delete_flow_public.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_AGE_DELETE_FLOW_PUBLIC_H ++#define HINIC3_AGE_DELETE_FLOW_PUBLIC_H ++ ++#include ++#include ++#include "rte_ethdev.h" ++#include "rte_flow.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_driver_public.h" ++ ++void hinic3_thread_rx_hw_age_info(uint32_t thread_id, const struct hinic3_dp_extend_info *dp_info); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_agent_sync_stats_public.h b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_agent_sync_stats_public.h +new file mode 100644 +index 0000000..40d7ff3 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_agent_sync_stats_public.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_AGENT_SYNC_STATS_PUBLIC_H ++#define HINIC3_FLOW_AGENT_SYNC_STATS_PUBLIC_H ++ ++#include "hinic3_flow_agent_public.h" ++ ++#define HINIC3_STATS_SYNC_INTERVAL 1500 /* 1.5s */ ++#define HINIC3_MAX_STATS_SYNC_INTERVAL 3000 /* 3.0s */ ++#define HINIC3_EVERY_STATS_SYNC_INTERVAL 100 /* 0.1s */ ++#define HINIC3_MAX_OFFLOAD_RATE 50 ++#define HINIC3_STATS_SYNC_PKT_MIN 8 ++#define HINIC3_MAX_ENTRY_PER_STATS_DUMP 1000 ++#define HINIC3_FLOW_FACTOR 4 ++#define HINIC3_MAX_FLOW_SIZE 500000 ++#define HINIC3_FLOW_STATUS_DEAD 1 ++ ++static inline bool hinic3_stats_sync_pull_mode(const struct hinic3_flow_agent_db *hw_offload) ++{ ++ return hw_offload->forward_engine.cap.flags & (1 << HINIC3_ENG_CAP_F_STATS_SYNC_PULL); ++} ++ ++static inline bool hinic3_stats_sync_push_mode(const struct hinic3_flow_agent_db *hw_offload) ++{ ++ return !hinic3_stats_sync_pull_mode(hw_offload); ++} ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.c b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.c +new file mode 100644 +index 0000000..e4fb288 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.c +@@ -0,0 +1,142 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "rte_flow.h" ++#include "hinic3_init.h" ++#include "hinic3_log.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_flow_dump_public.h" ++ ++static dump_start g_hinic3_dump_start[HINIC3_FLOW_TYPE_MAX] = {0}; ++static dump_next g_hinic3_dump_next[HINIC3_FLOW_TYPE_MAX] = {0}; ++static dump_done g_hinic3_dump_done[HINIC3_FLOW_TYPE_MAX] = {0}; ++ ++int hinic3_build_item_data(struct hinic3_dump_item_data *data, ++ enum hinic3_dump_data_type type, size_t size) ++{ ++ if (data == NULL) { ++ HINIC3_LOG(ERR, FLOW, "flow dump build item data, input null ptr"); ++ return -1; ++ } ++ ++ if (size == 0) { ++ data->is_valid = true; ++ return 0; ++ } ++ if (type == HINIC3_DUMP_DATA_TYPE_KEY) { ++ if (data->key == NULL) { ++ data->key = hinic3_calloc(1, size, HINIC3_FLOWS); ++ if (data->key == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, alloc key error"); ++ return -1; ++ } ++ } ++ } else { ++ if (data->mask == NULL) { ++ data->mask = hinic3_calloc(1, size, HINIC3_FLOWS); ++ if (data->mask == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 dump, alloc mask error"); ++ return -1; ++ } ++ } ++ } ++ data->is_valid = true; ++ return 0; ++} ++ ++void hinic3_clean_items_data(struct hinic3_dump_item_data items[], uint32_t len) ++{ ++ for (uint32_t i = 0; i < len; i++) { ++ items[i].is_valid = false; ++ if (items[i].key != NULL) { ++ hinic3_free(items[i].key); ++ items[i].key = NULL; ++ } ++ if (items[i].mask != NULL) { ++ hinic3_free(items[i].mask); ++ items[i].mask = NULL; ++ } ++ } ++} ++ ++void *hinic3_get_item_data(struct hinic3_dump_item_data *item, ++ enum hinic3_dump_data_type type) ++{ ++ if (type == HINIC3_DUMP_DATA_TYPE_KEY) { ++ return item->key; ++ } else { ++ return item->mask; ++ } ++} ++ ++int hinic3_build_action_data(struct hinic3_dump_act_data *data, size_t size) ++{ ++ if (size == 0) { ++ data->is_valid = true; ++ return 0; ++ } ++ if (data->action == NULL) { ++ data->action = hinic3_calloc(1, size, HINIC3_FLOWS); ++ if (data->action == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 dump, alloc action error"); ++ return -1; ++ } ++ } ++ data->is_valid = true; ++ return 0; ++} ++ ++void hinic3_clean_actions_data(struct hinic3_dump_act_data items[], uint32_t len) ++{ ++ for (uint32_t i = 0; i < len; i++) { ++ items[i].is_valid = false; ++ if (items[i].action != NULL) { ++ hinic3_free(items[i].action); ++ items[i].action = NULL; ++ } ++ } ++} ++ ++int hinic3_set_dump_start(enum hinic3_flow_type type, dump_start func) ++{ ++ g_hinic3_dump_start[type] = func; ++ return 0; ++} ++ ++int hinic3_set_dump_next(enum hinic3_flow_type type, dump_next func) ++{ ++ g_hinic3_dump_next[type] = func; ++ return 0; ++} ++ ++int hinic3_set_dump_done(enum hinic3_flow_type type, dump_done func) ++{ ++ g_hinic3_dump_done[type] = func; ++ return 0; ++} ++ ++dump_start hinic3_get_dump_start(enum hinic3_flow_type type) ++{ ++ if (type >= HINIC3_FLOW_TYPE_MAX) { ++ return NULL; ++ } ++ return g_hinic3_dump_start[type]; ++} ++ ++dump_next hinic3_get_dump_next(enum hinic3_flow_type type) ++{ ++ if (type >= HINIC3_FLOW_TYPE_MAX) { ++ return NULL; ++ } ++ return g_hinic3_dump_next[type]; ++} ++ ++dump_done hinic3_get_dump_done(enum hinic3_flow_type type) ++{ ++ if (type >= HINIC3_FLOW_TYPE_MAX) { ++ return NULL; ++ } ++ return g_hinic3_dump_done[type]; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.h b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.h +new file mode 100644 +index 0000000..a4616a3 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_flow_dump_public.h +@@ -0,0 +1,102 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_DUMP_PUBLIC_H ++#define HINIC3_FLOW_DUMP_PUBLIC_H ++ ++#include "rte_flow.h" ++#include "hiovs_acl_api.h" ++#include "hinic3_mutex.h" ++#include "hinic3_flow_format.h" ++ ++#define HINIC3_FLOW_DUMP_MAX_PATTERN HINIC3_FLOW_ITEMS_NUM ++#define HINIC3_FLOW_DUMP_MAX_ACTION HINIC3_FLOW_ACTIONS_NUM ++#define HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE 2048 ++ ++typedef struct hinic3_flow_act_vxlan_gpe_header hinic3_act_vxlan_header; ++ ++struct hinic3_dump_flow_info { ++ struct rte_flow_item items[HINIC3_FLOW_DUMP_MAX_PATTERN]; ++ unsigned int useful_item_index; ++ struct rte_flow_action actions[HINIC3_FLOW_DUMP_MAX_ACTION]; ++ unsigned int useful_action_index; ++ uint64_t hw_ufid; ++}; ++ ++struct hinic3_dump_flow_mem { ++ unsigned int max_flow_num; ++ unsigned int cur_flow_num; ++ long long int start_timestamp; ++ struct hinic3_dump_flow_info *flows; ++}; ++ ++enum hinic3_dump_context_status { ++ HINIC3_FLOW_DUMPING_READY, ++ HINIC3_FLOW_DUMPING, ++ HINIC3_FLOW_DUMPING_DONE ++}; ++ ++struct hinic3_flow_dump_context { ++ union { ++ void *hiovs_state; ++ }; ++ uint32_t type; ++ struct hinic3_dump_flow_mem context_mem; ++ pthread_t thread_id; ++ enum hinic3_dump_context_status dumping; ++}; ++ ++struct hinic3_dump_act_data { ++ bool is_valid; ++ void *action; ++}; ++ ++struct hinic3_dump_item_data { ++ bool is_valid; ++ void *key; ++ void *mask; ++}; ++ ++enum hinic3_flow_type { ++ HINIC3_FLOW_TYPE_EMC, ++ HINIC3_FLOW_TYPE_MEGA, ++ HINIC3_FLOW_TYPE_DPHASH, ++ HINIC3_FLOW_TYPE_ACL, ++ HINIC3_FLOW_TYPE_MAX ++}; ++ ++enum hinic3_dump_data_type { ++ HINIC3_DUMP_DATA_TYPE_KEY, ++ HINIC3_DUMP_DATA_TYPE_MASK, ++ HINIC3_DUMP_DATA_TYPE_ACT ++}; ++ ++typedef int (*dump_start)(struct hinic3_flow_dump_context *context, struct rte_flow_error *error); ++typedef int (*dump_next)(struct hinic3_flow_dump_context* context, int count, ++ struct rte_flow_error *error); ++typedef int (*dump_done)(struct hinic3_flow_dump_context *context, struct rte_flow_error *error); ++ ++int hinic3_build_item_data(struct hinic3_dump_item_data *data, ++ enum hinic3_dump_data_type type, size_t size); ++ ++void hinic3_clean_items_data(struct hinic3_dump_item_data items[], uint32_t len); ++ ++void *hinic3_get_item_data(struct hinic3_dump_item_data *item, ++ enum hinic3_dump_data_type type); ++ ++int hinic3_build_action_data(struct hinic3_dump_act_data *data, size_t size); ++ ++void hinic3_clean_actions_data(struct hinic3_dump_act_data items[], uint32_t len); ++ ++int hinic3_set_dump_start(enum hinic3_flow_type type, dump_start func); ++ ++int hinic3_set_dump_next(enum hinic3_flow_type type, dump_next func); ++ ++int hinic3_set_dump_done(enum hinic3_flow_type type, dump_done func); ++ ++dump_start hinic3_get_dump_start(enum hinic3_flow_type type); ++ ++dump_next hinic3_get_dump_next(enum hinic3_flow_type type); ++ ++dump_done hinic3_get_dump_done(enum hinic3_flow_type type); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c +new file mode 100644 +index 0000000..e246786 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c +@@ -0,0 +1,299 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_offload_action_public.h" ++ ++#define VXLAN_HEADER_FLAG 0x08 ++ ++static void hinic3_fill_vxlan_ip_header(struct hinic3_flow_act_vxlan_gpe_header *offload_vxlan_hdr, ++ const struct rte_flow_item *item) ++{ ++ const struct hinic3_ip_header *ipv4 = NULL; ++ const struct hinic3_ip6_header *ipv6 = NULL; ++ ++ switch (item->type) { ++ case RTE_FLOW_ITEM_TYPE_IPV4: ++ ipv4 = item->spec; ++ offload_vxlan_hdr->ip_version = HINIC3_IP_ADDR_V4; ++ offload_vxlan_hdr->sip[0] = ipv4->ip_src; ++ offload_vxlan_hdr->dip[0] = ipv4->ip_dst; ++ offload_vxlan_hdr->dscp = ipv4->ip_tos; ++ break; ++ case RTE_FLOW_ITEM_TYPE_IPV6: ++ ipv6 = item->spec; ++ offload_vxlan_hdr->ip_version = HINIC3_IP_ADDR_V6; ++ memcpy(offload_vxlan_hdr->sip, &ipv6->saddr, sizeof(ipv6->saddr)); ++ memcpy(offload_vxlan_hdr->dip, &ipv6->daddr, sizeof(ipv6->daddr)); ++ break; ++ default: ++ break; ++ } ++ return; ++} ++ ++static void hinic3_offload_fill_vxlan_udp_header(struct hinic3_flow_act_vxlan_gpe_header *offload_vxlan_hdr, ++ const struct rte_flow_item *item) ++{ ++ const struct rte_flow_item_udp *udp = NULL; ++ udp = item->spec; ++ offload_vxlan_hdr->sport = udp->hdr.src_port; ++ offload_vxlan_hdr->dport = udp->hdr.dst_port; // ovs统一使用上层传入的dst_port值 ++ ++ return; ++} ++ ++int hinic3_offload_fill_vxlan_header(struct hinic3_flow_act_vxlan_gpe_header *offload_vxlan_hdr, ++ const struct rte_flow_action_vxlan_encap *vxlan_info) ++{ ++ uint32_t flags = 0; ++ const struct hinic3_eth_header *eth = NULL; ++ const struct rte_flow_item_vxlan *vxlan = NULL; ++ const struct rte_flow_item *item = NULL; ++ ++ item = next_no_end_pattern(vxlan_info->definition, NULL); ++ while (item) { ++ if (item->spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3load vxlan action parse error. item spec is null. item type is %d", item->type); ++ return -1; ++ } ++ switch (item->type) { ++ case RTE_FLOW_ITEM_TYPE_ETH: ++ eth = item->spec; ++ memcpy(offload_vxlan_hdr->dmac, ð->dst, ETH_ALEN); ++ memcpy(offload_vxlan_hdr->smac, ð->src, ETH_ALEN); ++ flags |= HINIC3_FLG_VXLAN_ETH; ++ break; ++ case RTE_FLOW_ITEM_TYPE_VLAN: ++ offload_vxlan_hdr->vlan_id = *((uint16_t*)item->spec); ++ flags |= HINIC3_FLG_VXLAN_VLAN; ++ break; ++ case RTE_FLOW_ITEM_TYPE_IPV4: ++ case RTE_FLOW_ITEM_TYPE_IPV6: ++ (void)hinic3_fill_vxlan_ip_header(offload_vxlan_hdr, item); ++ flags |= HINIC3_FLG_VXLAN_IP; ++ break; ++ case RTE_FLOW_ITEM_TYPE_UDP: ++ hinic3_offload_fill_vxlan_udp_header(offload_vxlan_hdr, item); ++ flags |= HINIC3_FLG_VXLAN_UDP; ++ break; ++ case RTE_FLOW_ITEM_TYPE_VXLAN: ++ vxlan = item->spec; ++ /* ovs统一使用上层传入的vxlan.flag值 */ ++ memcpy(&offload_vxlan_hdr->vxlan, vxlan, sizeof(*vxlan)); ++ flags |= HINIC3_FLG_VXLAN_VNI; ++ break; ++ default: ++ break; ++ } ++ item = next_no_end_pattern(vxlan_info->definition, item); ++ } ++ if (flags == HINIC3_FLG_VXLAN_INTEGRITY_COMM || flags == HINIC3_FLG_VXLAN_INTEGRITY_VLAN) { ++ return 0; ++ } ++ return -1; ++} ++ ++int hinic3_offload_parse_vxlan_act(struct hinic3_offload_action *offload_action, ++ const struct rte_flow_action_vxlan_encap *vxlan_info) ++{ ++ int ret; ++ struct hinic3_flow_act_vxlan_gpe_header *vxlan_hdr = NULL; ++ struct hinic3_nlattr *hinic3_actions = &offload_action->act_nla; ++ ++ if (vxlan_info == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3offload vxlan action is null"); ++ return -1; ++ } ++ ++ vxlan_hdr = hinic3_nlattr_put_unspec_uninit(hinic3_actions, HINIC3_FLOW_ACT_VXL_GPE_PUSH, ++ sizeof(struct hinic3_flow_act_vxlan_gpe_header)); ++ if (vxlan_hdr == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FLOW_NO_VXLAN_ACTION_OFFSET, 1); ++ return -1; ++ } ++ offload_action->vxlan_hdr = vxlan_hdr; ++ ret = hinic3_offload_fill_vxlan_header(vxlan_hdr, vxlan_info); ++ if (ret != 0) { ++ return -1; ++ } ++ offload_action->has_vxlan_push = true; ++ return 0; ++} ++ ++static int hinic3_offload_parse_set_act(struct hinic3_nlattr *hinic3_actions, const struct rte_flow_action *act) ++{ ++ int ret = 0; ++ if (act->conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3load set action conf is null."); ++ return -1; ++ } ++ ++ switch (act->type) { ++ case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_SMAC, ++ act->conf, sizeof(struct eth_address)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_DMAC, ++ act->conf, sizeof(struct eth_address)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_SIP, act->conf, sizeof(in4_addr_t)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_DIP, act->conf, sizeof(in4_addr_t)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_SIPV6, act->conf, sizeof(in6_addr_t)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_DIPV6, act->conf, sizeof(in6_addr_t)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_SPORT, act->conf, sizeof(uint16_t)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_TP_DST: ++ ret = hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_SET_DPORT, act->conf, sizeof(uint16_t)); ++ break; ++ default: ++ break; ++ } ++ return ret; ++} ++ ++static int hinic3_offload_set_tag_act(struct hinic3_nlattr *hinic3_actions, const struct rte_flow_action *act) ++{ ++ struct hinic3_flow_act_block_version block; ++ const struct rte_flow_action_set_tag *set_tag = act->conf; ++ ++ if (set_tag == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3load set tag action is null."); ++ return -1; ++ } ++ ++ struct hinic3_dp_extend_info *extend_info = hinic3_get_offload_extend_info(); ++ if (extend_info == NULL) { ++ return -1; ++ } ++ ++ struct hinic3_flow_agent_db *hinic3_db = (struct hinic3_flow_agent_db *)extend_info->hw_offload; ++ ++ block.block_id = set_tag->mask; ++ block.block_version = set_tag->data; ++ ++ if (block.block_id >= hinic3_db->max_block_num) { ++ hinic3_add_error_stats(HINIC3_FLOW_ERROR_FLOW_BLOCK_ERR, 1); ++ return -1; ++ } ++ ++ if (block.block_version > UINT16_MAX) { ++ hinic3_add_error_stats(HINIC3_FLOW_ERROR_FLOW_BLOCK_ERR, 1); ++ return -1; ++ } ++ ++ return hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_BLOCK_VERSION, ++ &block, sizeof(struct hinic3_flow_act_block_version)); ++} ++ ++int hinic3_offload_parse_action_sub(const struct rte_flow_action *act, ++ struct hinic3_offload_action *offload_action) ++{ ++ int ret = 0; ++ struct hinic3_nlattr *hinic3_actions = &offload_action->act_nla; ++ switch (act->type) { ++ case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: ++ case RTE_FLOW_ACTION_TYPE_RSS: ++ case RTE_FLOW_ACTION_TYPE_AGE: ++ case RTE_FLOW_ACTION_TYPE_JUMP: ++ return 0; ++ case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: ++ case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: ++ case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: ++ case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: ++ case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: ++ case RTE_FLOW_ACTION_TYPE_SET_TP_DST: ++ case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: ++ case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: ++ ret = hinic3_offload_parse_set_act(hinic3_actions, act); ++ break; ++ case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: ++ ret = hinic3_nlattr_put_flag(hinic3_actions, HINIC3_FLOW_ACT_VLAN_POP); ++ offload_action->has_vlan_pop = true; ++ break; ++ case RTE_FLOW_ACTION_TYPE_DROP: ++ ret = hinic3_nlattr_put_flag(hinic3_actions, HINIC3_FLOW_ACT_DROP); ++ break; ++ case RTE_FLOW_ACTION_TYPE_DEC_TTL: ++ ret = hinic3_nlattr_put_flag(hinic3_actions, HINIC3_FLOW_ACT_DEC_TTL); ++ break; ++ case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: ++ ret = hinic3_nlattr_put_flag(hinic3_actions, HINIC3_FLOW_ACT_VXL_POP); ++ break; ++ case RTE_FLOW_ACTION_TYPE_COUNT: ++ ret = hinic3_nlattr_put_flag(hinic3_actions, HINIC3_FLOW_ACT_COUNT); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SET_TAG: ++ ret = hinic3_offload_set_tag_act(hinic3_actions, act); ++ break; ++ case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: ++ ret = hinic3_offload_parse_vxlan_act(offload_action, act->conf); ++ break; ++ default: ++ return -1; ++ }; ++ ++ return ret; ++} ++ ++int hinic3_offload_copy_current_action(const struct hinic3_nlattr *cur_action, struct hinic3_nlattr *final_action) ++{ ++ uint8_t *dst_buf_ptr = NULL; ++ ++ if (cur_action->used_len > (final_action->total_len - final_action->used_len)) { ++ return PROCESS_ACTION_FAIL; ++ } ++ dst_buf_ptr = final_action->data + final_action->used_len; ++ memcpy(dst_buf_ptr, cur_action->data, cur_action->used_len); ++ final_action->used_len += cur_action->used_len; ++ final_action->nla_itr = (hinic3_nlattr_itr)((uint8_t *)final_action->data + final_action->used_len); ++ return 0; ++} ++ ++bool hinic3_offload_check_actions(struct hinic3_nlattr *hinic3_actions) ++{ ++ int output_cnt = 0; ++ int act_type; ++ hinic3_nlattr_itr nla_itr = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH(nla_itr, hinic3_actions) { ++ act_type = hinic3_nlattr_get_itr_type(nla_itr); ++ if (act_type == HINIC3_FLOW_ACT_OUTPUT) { ++ output_cnt++; ++ } ++ } ++ ++ if (output_cnt > 1) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_MANY_OUTPUT, 1); ++ HINIC3_LOG(ERR, FLOW, "Multi-port flow error!"); ++ return false; ++ } ++ return true; ++} ++ ++bool hinic3_offload_flow_actions_check(struct rte_flow_action *action, size_t nums) ++{ ++ int output_cnt = 0; ++ ++ for (size_t i = 0; i < nums && action[i].type != RTE_FLOW_ACTION_TYPE_END; ++i) { ++ if (action[i].type == RTE_FLOW_ACTION_TYPE_PORT_ID) { ++ output_cnt++; ++ } ++ } ++ ++ if (output_cnt > 1) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_MANY_OUTPUT, 1); ++ HINIC3_LOG(ERR, FLOW, "Multi-port flow error!"); ++ return false; ++ } ++ return true; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.h b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.h +new file mode 100644 +index 0000000..ce186b2 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.h +@@ -0,0 +1,24 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_OFFLOAD_ACTION_PUBLIC_H ++#define HINIC3_OFFLOAD_ACTION_PUBLIC_H ++ ++#include "hinic3_message.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_log.h" ++ ++int hinic3_offload_parse_vxlan_act(struct hinic3_offload_action *offload_action, ++ const struct rte_flow_action_vxlan_encap *vxlan_info); ++int hinic3_offload_parse_action_sub(const struct rte_flow_action *act, ++ struct hinic3_offload_action *offload_action); ++int hinic3_offload_copy_current_action(const struct hinic3_nlattr *cur_action, struct hinic3_nlattr *final_action); ++bool hinic3_offload_check_actions(struct hinic3_nlattr *hinic3_actions); ++bool hinic3_offload_flow_actions_check(struct rte_flow_action *action, size_t nums); ++int hinic3_offload_fill_vxlan_header(struct hinic3_flow_act_vxlan_gpe_header *offload_vxlan_hdr, ++ const struct rte_flow_action_vxlan_encap *vxlan_info); ++bool hinic3_offload_flow_actions_check(struct rte_flow_action *action, size_t nums); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.c b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.c +new file mode 100644 +index 0000000..d879186 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.c +@@ -0,0 +1,125 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include ++#include ++#include "hinic3_log.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_mutex.h" ++#include "hinic3_offload_flow_port.h" ++ ++#define HINIC3_VF_PORT_MAX_NUM 1024 ++#define HINIC3_PF_PORT_MAX_NUM 32 ++#define HINIC3_BOND_PORT_MAX_NUM 2 ++#define HINIC3_PORT_INDEX_OFFSET 1 ++#define HINIC3_PORT_MAP_MAX_LENGTH (HINIC3_VF_PORT_MAX_NUM + HINIC3_PF_PORT_MAX_NUM + \ ++ HINIC3_BOND_PORT_MAX_NUM + HINIC3_PORT_INDEX_OFFSET) ++ ++struct hinic3_port_node { ++ uint16_t hinic3_vport_id; ++ uint16_t hinic3_port_index; ++ bool is_used; ++}; ++ ++static struct hinic3_rwlock g_hinic3_port_lock; ++static struct hinic3_port_node g_hinic3_port_map[HINIC3_PORT_MAP_MAX_LENGTH] = {0}; ++ ++void hinic3_ifindex_port_map_init(void) ++{ ++ hinic3_rwlock_init(&g_hinic3_port_lock); ++} ++ ++void hinic3_ifindex_port_map_uninit(void) ++{ ++ hinic3_rwlock_destroy(&g_hinic3_port_lock); ++} ++ ++static int hinic3_ifindex_port_find(uint16_t vport_id, struct hinic3_port_node **node) ++{ ++ for (int i = 0; i < HINIC3_PORT_MAP_MAX_LENGTH; ++i) { ++ if (g_hinic3_port_map[i].is_used == true && g_hinic3_port_map[i].hinic3_vport_id == vport_id) { ++ *node = &g_hinic3_port_map[i]; ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++static int hinic3_ifindex_port_insert(uint16_t vport_id, uint16_t port_index) ++{ ++ int ret; ++ struct hinic3_port_node *node = NULL; ++ ++ hinic3_rwlock_wrlock(&g_hinic3_port_lock); ++ ret = hinic3_ifindex_port_find(vport_id, &node); ++ if (ret == 0) { ++ node->hinic3_port_index = port_index; ++ hinic3_rwlock_wrunlock(&g_hinic3_port_lock); ++ return 0; ++ } ++ ++ for (int i = 0; i < HINIC3_PORT_MAP_MAX_LENGTH; ++i) { ++ if (!g_hinic3_port_map[i].is_used) { ++ g_hinic3_port_map[i].hinic3_vport_id = vport_id; ++ g_hinic3_port_map[i].hinic3_port_index = port_index; ++ g_hinic3_port_map[i].is_used = true; ++ hinic3_rwlock_wrunlock(&g_hinic3_port_lock); ++ return 0; ++ } ++ } ++ HINIC3_LOG(ERR, FLOW, "hinic3_ifindex_port_insert: insert port failed"); ++ hinic3_rwlock_wrunlock(&g_hinic3_port_lock); ++ return -1; ++} ++ ++int hinic3_ifindex_port_remove(uint16_t vport_id) ++{ ++ struct hinic3_port_node *node = NULL; ++ int ret; ++ ++ hinic3_rwlock_wrlock(&g_hinic3_port_lock); ++ ret = hinic3_ifindex_port_find(vport_id, &node); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_ifindex_port_remove: remove port node failed"); ++ hinic3_rwlock_wrunlock(&g_hinic3_port_lock); ++ return -1; ++ } ++ ++ node->hinic3_vport_id = 0; ++ node->hinic3_port_index = 0; ++ node->is_used = false; ++ hinic3_rwlock_wrunlock(&g_hinic3_port_lock); ++ return 0; ++} ++ ++int hinic3_set_port_map_by_ifindex(uint16_t vport_id, uint16_t port_index) ++{ ++ int ret = 0; ++ ret = hinic3_ifindex_port_insert(vport_id, port_index); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_set_port_map_by_ifindex: set port id map failed"); ++ return -1; ++ } ++ return ret; ++} ++ ++int hinic3_get_port_id_by_ifindex(uint16_t vport_id, uint16_t *port_index) ++{ ++ struct hinic3_port_node *node = NULL; ++ int ret; ++ ++ if (port_index == NULL) { ++ return -1; ++ } ++ ++ hinic3_rwlock_rdlock(&g_hinic3_port_lock); ++ ret = hinic3_ifindex_port_find(vport_id, &node); ++ if (ret != 0) { ++ hinic3_rwlock_rdunlock(&g_hinic3_port_lock); ++ return -1; ++ } ++ ++ *port_index = node->hinic3_port_index; ++ hinic3_rwlock_rdunlock(&g_hinic3_port_lock); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.h b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.h +new file mode 100644 +index 0000000..1e05689 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_port.h +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_OFFLOAD_FLOW_PORT_H ++#define HINIC3_OFFLOAD_FLOW_PORT_H ++#include ++int hinic3_set_port_map_by_ifindex(uint16_t vport_id, uint16_t port_index); ++int hinic3_get_port_id_by_ifindex(uint16_t vport_id, uint16_t *port_index); ++void hinic3_ifindex_port_map_init(void); ++void hinic3_ifindex_port_map_uninit(void); ++int hinic3_ifindex_port_remove(uint16_t vport_id); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c +new file mode 100644 +index 0000000..b84961a +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c +@@ -0,0 +1,45 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_offload_flow_public.h" ++#include "rte_lcore.h" ++#include "rte_flow.h" ++#include "hinic3_message.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_log.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#endif ++ ++void hinic3_offload_thread_rx_put_ack(uint32_t thread_id, struct hinic3_dp_extend_info *dp_info) ++{ ++ struct rte_mbuf *buffer[HINIC3_THREAD_RX_BURST_MAX] = { 0 }; ++ ++ if (dp_info == NULL) { ++ return; ++ } ++ (void)hinic3_global_rte_eth_rx_burst(thread_id, HINIC3_PTHREAD_ACK, buffer, HINIC3_THREAD_RX_BURST_MAX); ++} ++ ++uint32_t hinic3_convert_u8_to_u32(const uint8_t *src_array, uint8_t len) ++{ ++ if (src_array == NULL) { ++ return 0; ++ } ++ uint32_t target_value = 0; ++ if (len <= 0 || len > sizeof(uint32_t)) { ++ return 0; ++ } ++ for (int i = len - 1; i >= 0; i--) { ++ target_value += src_array[i]; ++ if (i == 0) { ++ break; ++ } ++ target_value <<= HINIC3_UINT8_SHIFT; ++ } ++ return target_value; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.h b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.h +new file mode 100644 +index 0000000..04abf69 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.h +@@ -0,0 +1,204 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_OFFLOAD_FLOW_PUBLIC_H ++#define HINIC3_OFFLOAD_FLOW_PUBLIC_H ++ ++#include "rte_flow.h" ++#include "rte_ethdev.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_message.h" ++ ++#define PKT_RX_HW_OFFLOAD_INFO (1ULL << 39) ++#define HINIC3_OFFLOAD_DUPLICATE_TIME_CHECK 1000 /* ms */ ++#define HINIC3_IPV6_ADDR_UINT32_LEN 4 ++#define HINIC3_IPV6_ADDR_UINT8_LEN 16 ++#define HINIC3_UINT8_SHIFT 8u ++#define HINIC3_VNI_LEN 3 ++#define HINIC3_RSVD0_LEN 3 ++#define HINIC3_TNI_LEN 3 ++#define HINIC3_MIRROR_IP_LEN 16 ++#define HINIC3_FLOW_PORT_ID 0 ++ ++#define HINIC3_FLG_VXLAN_ETH (1LLU << 0) ++#define HINIC3_FLG_VXLAN_IP (1LLU << 1) ++#define HINIC3_FLG_VXLAN_UDP (1LLU << 2) ++#define HINIC3_FLG_VXLAN_VNI (1LLU << 3) ++#define HINIC3_FLG_VXLAN_VLAN (1LLU << 4) ++ ++#define HINIC3_FLG_VXLAN_INTEGRITY_COMM (HINIC3_FLG_VXLAN_ETH | \ ++ HINIC3_FLG_VXLAN_IP | \ ++ HINIC3_FLG_VXLAN_UDP | \ ++ HINIC3_FLG_VXLAN_VNI) ++ ++#define HINIC3_FLG_VXLAN_INTEGRITY_VLAN (HINIC3_FLG_VXLAN_ETH | \ ++ HINIC3_FLG_VXLAN_VLAN | \ ++ HINIC3_FLG_VXLAN_IP | \ ++ HINIC3_FLG_VXLAN_UDP | \ ++ HINIC3_FLG_VXLAN_VNI) ++ ++#define MILLION_FLOWS (1 << 20) ++#define OFFLOAD_FLOW_BUCKETS_SHIFT 16 ++#define OFFLOAD_FLOW_BUCKETS (1 << OFFLOAD_FLOW_BUCKETS_SHIFT) ++ ++#define HINIC3_FLOW_TYPE_OFFSET 30 ++#define HINIC3_FLOW_ATTR_TYPE_OFFSET 27 ++#define HINIC3_FLOW_TYPE_MASK 0x3 ++#define HINIC3_EMC_FLOW_TYPE 0 ++#define HINIC3_MEGA_FLOW_TYPE 1 ++#define HINIC3_DPHASH_FLOW_TYPE 2 ++#define HINIC3_ACL_FLOW_TYPE 3 ++#define HINIC3_DEFAULT_WINDOW 0x1000 ++#define HINIC3_PUT_FLOW_SUCCESS 0 ++ ++enum { ++ HINIC3_DP_OPENFLOW, ++ HINIC3_DP_ELB_TRANSLATE, ++ HINIC3_DP_IFP, ++ HINIC3_DP_L2FWD, ++ HINIC3_DP_MAX ++}; ++ ++enum { ++ PROCESS_KEY_ACT_SUCC, ++ PROCESS_KEY_ACT_FAIL, ++ PROCESS_KEY_ACT_SKIP, ++ PROCESS_KEY_ACT_FRAG, ++}; ++ ++enum { ++ PROCESS_KEY_SUCC, ++ PROCESS_KEY_FAIL, ++ PROCESS_KEY_SKIP, ++}; ++ ++enum { ++ PROCESS_ACTION_SUCC = 0, ++ PROCESS_ACTION_FAIL, ++ PROCESS_ACTION_RECIRCLE, ++}; ++ ++ ++struct hinic3_offload_action { ++ struct hinic3_nlattr act_nla; ++ bool has_output; ++ bool has_vxlan_pop; ++ bool has_vxlan_push; ++ bool has_ct; ++ bool has_circle; ++ bool has_vlan_push; ++ bool has_vlan_pop; ++ bool has_dp_hash; ++ uint16_t vlan_id; ++ struct hinic3_flow_act_vxlan_gpe_header *vxlan_hdr; ++}; ++ ++ ++struct hinic3_flow_offload_param { ++ struct hinic3_flow_agent_db *hw_offload; ++ struct hinic3_pkt_key_cache_s pkt_key_cache; ++ struct dp_packet *one_pkt; ++ struct hinic3_pkt_info *pkt_info; ++ struct hinic3_conntrack_full_key full_key; ++ struct hinic3_nlattr hinic3_key; ++ struct hinic3_offload_action cur_actions; ++ struct hinic3_nlattr hinic3_actions; ++ struct hinic3_nlattr hinic3_args; ++ int lcore_idx; ++ struct hinic3_offload_buf_s offload_buff; ++}; ++ ++struct hinic3_flow_callback_info { ++ bool reply; ++ bool is_ct; ++ bool is_dp_hash; ++ bool is_modify; ++ uint8_t flow_put_result; ++ uint8_t policy_flag; ++ uint32_t mega_ufid_cnt; ++ uint32_t core_id; ++ uint32_t flow_hash; ++ clock_t start_t; ++ hinic3_u128 *mega_ufid_list; ++ hinic3_u128 mega_ufid; ++ struct hinic3_conntrack_full_key ct_key; ++ struct hinic3_conntrack_full_key no_ct_key; ++}; ++ ++typedef struct { ++ struct rte_flow *rte_flow; ++ struct dp_packet *packet; ++ struct hinic3_pkt_info *pkt_info; ++ uint64_t reverse_ufid; ++ struct hinic3_dpif_flow *flow; ++ struct hinic3_nlattr *args; ++ size_t args_len; ++ struct hinic3_nlattr *hinic3_actions; ++ struct hinic3_conntrack_full_key *full_key; ++} hinic3_flow_info; ++ ++struct hinic3_inner_metadata { ++ uint32_t rx_seq; ++ struct { ++ uint8_t offload : 2; ++ /* Copied from struct hinic3_pkt_user_data */ ++ uint8_t traffic_type : 6; ++ } status; ++ /* index of array pmd_status[pmd_core_id]->pkt_info_bufs */ ++ uint8_t offset; ++ uint16_t lcore_idx; ++}; ++ ++typedef struct { ++ uint32_t live_time; ++ uint32_t core_id; ++ int sw_ufid_buffer_size; ++ int sw_ufid_cnt; ++ void *sw_ufid_buffer; ++ uint64_t reverse_hw_ufid; ++ struct hinic3_conntrack_full_key *ct_key; ++ struct hinic3_conntrack_full_key *no_ct_key; ++} hinic3_args_context; ++ ++struct rte_flow_action_of_set_meter_info { ++ uint16_t qos_type : 1; ++ uint16_t qos_id : 10; ++ uint16_t rsvd : 5; ++}; ++ ++static inline const struct rte_flow_action *next_no_void_action(const struct rte_flow_action actions[], ++ const struct rte_flow_action *cur) ++{ ++ const struct rte_flow_action *next = cur ? (cur + 1) : &actions[0]; ++ while (1) { ++ if (next->type != RTE_FLOW_ACTION_TYPE_VOID) { ++ return next; ++ } ++ next++; ++ } ++} ++ ++static inline const struct rte_flow_item *next_no_end_pattern(const struct rte_flow_item pattern[], ++ const struct rte_flow_item *cur) ++{ ++ const struct rte_flow_item *next = cur ? (cur + 1) : &pattern[0]; ++ ++ if (next->type == RTE_FLOW_ITEM_TYPE_END) { ++ next = NULL; ++ } ++ ++ return next; ++} ++ ++static inline uint32_t hinic3_eth_flow_type(const struct rte_flow_attr *attr) ++{ ++ uint32_t flow_type = (attr->reserved >> HINIC3_FLOW_ATTR_TYPE_OFFSET) & HINIC3_FLOW_TYPE_MASK; ++ return flow_type; ++} ++ ++void hinic3_offload_thread_rx_put_ack(uint32_t thread_id, struct hinic3_dp_extend_info *dp_info); ++uint32_t hinic3_convert_u8_to_u32(const uint8_t *src_array, uint8_t len); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_packet_key_public.h b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_packet_key_public.h +new file mode 100644 +index 0000000..3cc7524 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_packet_key_public.h +@@ -0,0 +1,284 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_PACKET_KEY_PUBLIC_H ++#define HINIC3_PACKET_KEY_PUBLIC_H ++ ++#include "hinic3_util.h" ++#include ++#include "hinic3_types.h" ++#include "hinic3_packets_types.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* in a byte: ++ * bit 6-7: version ++ * bit 3-5: forward mode ++ * bit 0-2: escape mode ++ */ ++#define HINIC3_ESCAPE_MODE_OFFSET 0U ++#define HINIC3_FORWARD_MODE_OFFSET 3U ++#define HINIC3_MODE_VERSION_OFFSET 6U ++ ++#define HINIC3_ESCAPE_MODE_MASK 0x07 ++#define HINIC3_FORWARD_MODE_MASK 0x38 ++#define HINIC3_MODE_VERSION_MASK 0xC0 ++ ++#define ETH_PAD_SIZE 19 ++ ++#define HINIC3_CT_UPDATE_MAX_ZONE 2 ++ ++#define KEY_VLAN_OFFSET 1 ++#define KEY_VXLAN_OFFSET 2 ++#define KEY_INNER_VID_OFFSET 1 ++#define KEY_OUTER_VID_OFFSET 2 ++ ++enum HINIC3_IP_TYPE { ++ HINIC3_IP_TYPE_V4 = 1, ++ HINIC3_IP_TYPE_V6 ++}; ++ ++enum { ++ HINIC3_CT_SEQ_RECORD_NONE, ++ HINIC3_CT_SEQ_RECORD_ORIGIN, ++ HINIC3_CT_SEQ_RECORD_REVERSE, ++ HINIC3_CT_SEQ_RECORD_MAX, ++}; ++ ++enum { ++ HINIC3_FLUSH_ALL, ++ HINIC3_FLUSH_SINGLE_CT_ZONE, ++ HINIC3_FLUSH_ALL_CT_ZONE ++}; ++ ++enum { ++ CONN_HINIC3_STATUS_NONE, ++ CONN_HINIC3_STATUS_ADDING, ++ CONN_HINIC3_STATUS_ADDED, ++ CONN_HINIC3_STATUS_DELETE ++}; ++ ++enum { ++ /* Key = in_port + 7 tuple(smac, dmac, sip, dip, sport, dport, protocol) */ ++ HINIC3_KEY_5TUPLE, ++ /* Key = in_port + outer vid + 7 tuple(smac, dmac, sip, dip, sport, dport, protocol) */ ++ HINIC3_KEY_VID_5TUPLE, ++ /* Key = in_port + vxlan(sip, dip, vni) + 7 tuple(smac, dmac, sip, dip, sport, dport, protocol) */ ++ HINIC3_KEY_VXLAN_5TUPLE, ++ /* Key = in_port + vxlan(sip, dip, vni) + inner vid + 7 tuple(smac, dmac, sip, dip, sport, dport, protocol) */ ++ HINIC3_KEY_VXLAN_VID_5TUPLE, ++ /* Key = in_port + outer vid+ vxlan(sip, dip, vni) + 7 tuple(smac, dmac, sip, dip, sport, dport, protocol) */ ++ HINIC3_KEY_VID_VXLAN_5TUPLE, ++ /* Key = in_port+outer vid+vxlan(sip, dip, vni)+inner vid+7 tuple(smac, dmac, sip, dip, sport, dport, protocol) */ ++ HINIC3_KEY_VID_VXLAN_VID_5TUPLE, ++ /* Key = ct_zone + 7 tuple(smac, dmac, sip, dip, sport, dport, protocol) */ ++ HINIC3_KEY_CT_ZONE_5TUPLE, ++ /* Key = in_port + 5 tuple(smac, dmac, sip, dip, protocol) */ ++ HINIC3_KEY_RAW_IP, ++ /* Key = in_port + outer vid + 5 tuple(smac, dmac, sip, dip, protocol) */ ++ HINIC3_KEY_VID_RAW_IP, ++ /* Key = in_port + vxlan(sip, dip, vni) + 5 tuple(smac, dmac, sip, dip, protocol) */ ++ HINIC3_KEY_VXLAN_RAW_IP, ++ /* Key = in_port + vxlan(sip, dip, vni) + inner vid + 5 tuple(smac, dmac, sip, dip, protocol) */ ++ HINIC3_KEY_VXLAN_VID_RAW_IP, ++ /* Key = in_port + outer vid + vxlan(sip, dip, vni) + 5 tuple(smac, dmac, sip, dip, protocol) */ ++ HINIC3_KEY_VID_VXLAN_RAW_IP, ++ /* Key = in_port + outer vid + vxlan(sip, dip, vni) + inner vid + 5 tuple(smac, dmac, sip, dip, protocol) */ ++ HINIC3_KEY_VID_VXLAN_VID_RAW_IP, ++ /* Key = in_port + eth(src mac, dst mac, ethernet type) */ ++ HINIC3_KEY_ETH, ++ /* Key = in_port + outer vid + eth(src mac, dst mac, ethernet type) */ ++ HINIC3_KEY_VID_ETH, ++ /* Key = in_port + vxlan(sip, dip, vni) + eth(src mac, dst mac, ethernet type) */ ++ HINIC3_KEY_VXLAN_ETH, ++ /* Key = in_port + vxlan(sip, dip, vni) + inner vid + eth(src mac, dst mac, ethernet type) */ ++ HINIC3_KEY_VXLAN_VID_ETH, ++ /* Key = in_port + outer vid + vxlan(sip, dip, vni) + eth(src mac, dst mac, ethernet type) */ ++ HINIC3_KEY_VID_VXLAN_ETH, ++ /* Key = in_port + outer vid + vxlan(sip, dip, vni) + inner vid + eth(src mac, dst mac, ethernet type) */ ++ HINIC3_KEY_VID_VXLAN_VID_ETH, ++ /* Key = hash + recisd_id */ ++ HINIC3_KEY_DP_HASH, ++}; ++ ++enum { ++ HINIC3_CT_DEFAULT_FLAG, ++ HINIC3_CT_UDP_FLAG, ++ HINIC3_CT_TCP_FLAG, ++ HINIC3_CT_ICMP_FLAG, ++ HINIC3_CT_ICMPV6_FLAG, ++ HINIC3_CT_MAX_FLAG, ++}; ++ ++struct hinic3_ip_addr { ++ union { ++ hinic3_be32 ipv4; ++ struct in6_addr ipv6; ++ }; ++}; ++ ++struct hinic3_key_ip { ++ struct hinic3_ip_addr src; ++ struct hinic3_ip_addr dst; ++ hinic3_be16 ether_type; ++ hinic3_be16 padding; ++}; ++ ++struct hinic3_key_vxlan { ++ struct hinic3_key_ip ip; ++ hinic3_be32 vni; ++}; ++ ++struct hinic3_key_mac { ++ uint8_t dmac[ETH_ALEN]; ++ uint8_t smac[ETH_ALEN]; ++}; ++ ++/* the struct below should be the same size */ ++struct hinic3_key_5tuple { ++ struct hinic3_key_mac eth; ++ struct hinic3_key_ip ip; ++ hinic3_be16 port_src; ++ hinic3_be16 port_dst; ++}; ++ ++struct hinic3_key_icmp { ++ struct hinic3_key_mac eth; ++ struct hinic3_key_ip ip; ++ uint8_t icmp_code; ++ uint8_t icmp_type; ++ hinic3_be16 id; ++}; ++ ++struct hinic3_key_raw_ip { ++ struct hinic3_key_mac eth; ++ struct hinic3_key_ip ip; ++ uint32_t protocol; ++}; ++ ++struct hinic3_key_eth { ++ struct hinic3_key_mac eth; ++ hinic3_be16 ether_type; ++ uint16_t padding[ETH_PAD_SIZE]; ++}; /* the struct above should be the same size */ ++ ++/* the struct below should be the same size before the vxlan field */ ++struct hinic3_key_vid_5tuple { ++ struct hinic3_key_5tuple tuple; ++ hinic3_be16 outer_vid; ++ hinic3_be16 inner_vid; ++ hinic3_be16 cvlan_id; /* Inner cvlan in QinQ */ ++ hinic3_be16 vlan_id; ++}; ++ ++struct hinic3_key_vid_raw_ip { ++ struct hinic3_key_raw_ip ip; ++ hinic3_be16 outer_vid; ++ hinic3_be16 inner_vid; ++ uint16_t padding1; ++ uint16_t padding2; ++}; ++ ++struct hinic3_key_vid_eth { ++ struct hinic3_key_eth eth; ++ hinic3_be16 outer_vid; ++ hinic3_be16 inner_vid; ++ uint16_t padding1; ++ uint16_t padding2; ++}; ++ ++struct hinic3_key_vxlan_vid_5tuple { ++ struct hinic3_key_5tuple tuple; ++ hinic3_be16 outer_vid; ++ hinic3_be16 inner_vid; ++ hinic3_be16 cvlan_id; /* Inner cvlan in QinQ */ ++ uint16_t input_port; ++ struct hinic3_key_vxlan vxlan; ++}; ++ ++struct hinic3_key_vxlan_vid_raw_ip { ++ struct hinic3_key_raw_ip ip; ++ hinic3_be16 outer_vid; ++ hinic3_be16 inner_vid; ++ uint16_t padding1; ++ uint16_t padding2; ++ struct hinic3_key_vxlan vxlan; ++}; ++ ++struct hinic3_key_vxlan_vid_eth { ++ struct hinic3_key_eth eth; ++ hinic3_be16 outer_vid; ++ hinic3_be16 inner_vid; ++ uint16_t padding1; ++ uint16_t padding2; ++ struct hinic3_key_vxlan vxlan; ++}; /* the struct above should be the same size before the vxlan field */ ++ ++struct hinic3_conntrack_key_metadata { ++ /* ct_zone is valid when type is HINIC3_KEY_CT_ZONE_5TUPLE, zero means notrack */ ++ union { ++ uint16_t input_port; ++ uint16_t ct_zone; ++ }; ++ uint32_t is_vxlan_encap : 1; ++ uint32_t is_vlan_push : 1; ++ uint32_t key_len : 7; ++ uint32_t tcp_udp_flag : 3; ++ uint32_t type : 5; ++ uint32_t need_ct_action : 1; ++ uint32_t reserved : 14; ++}; ++ ++struct hinic3_conntrack_key { ++ union { ++ uint32_t meta_num; ++ struct hinic3_conntrack_key_metadata meta; ++ }; ++ uint8_t key[0]; ++}; ++ ++struct hinic3_conntrack_simple_key { ++ struct hinic3_conntrack_key key; ++ struct hinic3_key_5tuple tuple; ++}; ++ ++struct hinic3_key_dp_hash { ++ uint32_t hash; // DP-HASH value ++ uint32_t recirc_id; // Recirc_id ++}; ++ ++struct hinic3_conntrack_full_key { ++ struct hinic3_conntrack_key key; ++ union { ++ struct hinic3_key_5tuple tuple; ++ struct hinic3_key_vid_5tuple vid_tuple; ++ struct hinic3_key_vxlan_vid_5tuple vxlan_vid_tuple; ++ struct hinic3_key_raw_ip ip; ++ struct hinic3_key_vid_raw_ip vid_ip; ++ struct hinic3_key_vxlan_vid_raw_ip vxlan_vid_ip; ++ struct hinic3_key_eth eth; ++ struct hinic3_key_vid_eth vid_eth; ++ struct hinic3_key_vxlan_vid_eth vxlan_vid_eth; ++ struct hinic3_key_dp_hash dp_hash; ++ }; ++}; ++ ++static inline uint8_t hinic3_ct_get_proto_by_flag(uint32_t tcp_udp_flag) ++{ ++ uint8_t proto[] = {HINIC3_CT_DEFAULT_FLAG, IPPROTO_UDP, IPPROTO_TCP, IPPROTO_ICMP, IPPROTO_ICMPV6}; ++ ++ if (tcp_udp_flag < HINIC3_CT_MAX_FLAG) { ++ return proto[tcp_udp_flag]; ++ } else { ++ return HINIC3_CT_DEFAULT_FLAG; ++ } ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c +new file mode 100644 +index 0000000..668ce6b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c +@@ -0,0 +1,616 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_flow_dump_action.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_util.h" ++#include "hinic3_message.h" ++#include "hinic3_log.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_vxlan_dump.h" ++#include "hinic3_meminfo.h" ++ ++#define VLAN_TCI_OFFSET 0xF000 ++#define VLAN_VID_BIT 0xFF0F ++#define VLAN_PCP_BIT 0XE000 ++#define HINIC3_VXLAN_ITEM_NUMBER 5 ++#define HINIC3_SAMLPE_ACTION_NUM 3 ++#define HINIC3_PORT_TRANS_MASK 0x1000 ++#define HINIC3_PORT_BIT_MASK 0X3FFF ++#define HINIC3_VLAN_VID_BIT 13 ++#define DUMP_VLAN_PCP_OFFSET 8 ++#define HINIC3_DP_HASH_DUMP_DEFALUT_PORT 0X0080 ++typedef int (*hinic3_action_conf)(const hinic3_nlattr_itr, void **); ++ ++struct hinic3_flow_action_info_s { ++ enum hinic3_flow_action_type hinic3_type; ++ enum rte_flow_action_type rte_type; ++ hinic3_action_conf conf_call_back; ++}; ++ ++static void hinic3_free_rte_sample_action(struct rte_flow_action *action) ++{ ++ if (action == NULL || action->type != RTE_FLOW_ACTION_TYPE_SAMPLE) { ++ return; ++ } ++ ++ if (action->conf == NULL) { ++ return; ++ } ++ ++ const struct rte_flow_action_sample *sample = action->conf; ++ const struct rte_flow_action *sample_action = sample->actions; ++ ++ struct rte_flow_action_port_id *port_id = NULL; ++ struct rte_flow_action_vxlan_encap *vxlan_encap = NULL; ++ ++ if (sample_action != NULL) { ++ port_id = (struct rte_flow_action_port_id *)sample_action[0].conf; ++ vxlan_encap = (struct rte_flow_action_vxlan_encap *)sample_action[1].conf; ++ ++ hinic3_free_vxlan_header(vxlan_encap); ++ hinic3_free(port_id); ++ hinic3_free(HINIC3_CONST_CAST(void *, sample_action)); ++ } ++ ++ hinic3_free(HINIC3_CONST_CAST(void*, sample)); ++ return; ++} ++ ++static void hinic3_free_rte_flow_action(struct rte_flow_action *action) ++{ ++ if (action == NULL) { ++ return; ++ } ++ ++ if (action->conf != NULL) { ++ switch (action->type) { ++ case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: ++ hinic3_free_vxlan_header(HINIC3_CONST_CAST(void *, action->conf)); ++ break; ++ case RTE_FLOW_ACTION_TYPE_SAMPLE: ++ hinic3_free_rte_sample_action(action); ++ break; ++ default: ++ hinic3_free(HINIC3_CONST_CAST(void *, action->conf)); ++ action->conf = NULL; ++ break; ++ } ++ } ++} ++ ++void hinic3_free_one_flow_actions(struct rte_flow_action *actions, int action_num) ++{ ++ if (actions == NULL) { ++ return; ++ } ++ for (int i = 0; i < action_num; ++i) { ++ hinic3_free_rte_flow_action(&actions[i]); ++ } ++} ++ ++static struct rte_flow_action *hinic3_build_rte_flow_action(enum rte_flow_action_type type, const void *conf) ++{ ++ struct rte_flow_action *action = hinic3_calloc(1, sizeof(struct rte_flow_action), HINIC3_FLOWS); ++ if (action == NULL) { ++ HINIC3_LOG(ERR, FLOW, "HINIC3 FLOW DUMP: malloc for flow action failed"); ++ return NULL; ++ } ++ action->type = type; ++ action->conf = conf; ++ return action; ++} ++ ++static int hinic3_dump_flow_action_insert(struct hinic3_dump_flow_info *flow, struct rte_flow_action *action) ++{ ++ if (flow == NULL || action == NULL) { ++ return -1; ++ } ++ unsigned int index = flow->useful_action_index; ++ if (index < HINIC3_FLOW_DUMP_MAX_ACTION) { ++ memcpy(&flow->actions[index], action, sizeof(struct rte_flow_action)); ++ flow->useful_action_index++; ++ ++ hinic3_free(action); ++ action = NULL; ++ return 0; ++ } ++ return -1; ++} ++ ++// construct rte_flow_action conf ++static void *hinic3_get_vlan_push_conf(void) ++{ ++ uint16_t *eth = hinic3_calloc(1, sizeof(uint16_t), HINIC3_FLOWS); ++ if (eth == NULL) { ++ return NULL; ++ } ++ *eth = htons(ETH_TYPE_VLAN); ++ return (void *)eth; ++} ++ ++static void *hinic3_get_conf_set_vlan_vid(uint16_t vid) ++{ ++ uint16_t *vlan_vid = hinic3_calloc(1, sizeof(uint16_t), HINIC3_FLOWS); ++ if (vlan_vid == NULL) { ++ return NULL; ++ } ++ *vlan_vid = (vid & VLAN_VID_BIT); ++ return (void *)vlan_vid; ++} ++ ++static void *hwof_get_conf_set_vlan_pcp(uint16_t vid) ++{ ++ uint8_t *vlan_pcp = hinic3_calloc(1, sizeof(uint8_t), HINIC3_FLOWS); ++ if (vlan_pcp == NULL) { ++ return NULL; ++ } ++ *vlan_pcp = (ntohs(vid) & VLAN_PCP_BIT) >> DUMP_VLAN_PCP_OFFSET; ++ return (void *)vlan_pcp; ++} ++ ++static struct rte_flow_action *hinic3_vlan_action_factory(enum rte_flow_action_type rte_type, uint16_t vid) ++{ ++ void *conf = NULL; ++ switch (rte_type) { ++ case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: ++ conf = hinic3_get_vlan_push_conf(); ++ break; ++ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: ++ conf = hinic3_get_conf_set_vlan_vid(vid); ++ break; ++ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: ++ conf = hwof_get_conf_set_vlan_pcp(vid); ++ break; ++ default: ++ break; ++ } ++ if (conf == NULL) { ++ return NULL; ++ } ++ ++ struct rte_flow_action *action = hinic3_build_rte_flow_action(rte_type, conf); ++ if (action == NULL) { ++ hinic3_free(conf); ++ } ++ ++ return action; ++} ++ ++static int hinic3_flow_dump_mac_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ void *conf_meta = NULL; ++ void *conf = hinic3_calloc(1, sizeof(struct eth_address), HINIC3_FLOWS); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return -1; ++ } ++ conf_meta = (void *)hinic3_nlattr_get_itr_unspec(nla, sizeof(struct eth_address)); ++ if (conf_meta == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get mac conf failed"); ++ return -1; ++ } ++ ++ memcpy(conf, conf_meta, sizeof(struct eth_address)); ++ *dst_conf = conf; ++ return 0; ++} ++ ++static int hinic3_flow_dump_u32_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ rte_be32_t *conf = hinic3_calloc(1, sizeof(rte_be32_t), HINIC3_FLOWS); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return -1; ++ } ++ ++ rte_be32_t src_conf = hinic3_nlattr_get_itr_u32(nla); ++ *conf = src_conf; ++ *dst_conf = conf; ++ return 0; ++} ++ ++static int hinic3_flow_dump_ipv4_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ return hinic3_flow_dump_u32_conf_get(nla, dst_conf); ++} ++ ++static int hinic3_flow_dump_ipv6_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ const in6_addr_t *meta_ipv6 = NULL; ++ ++ void *conf = hinic3_calloc(1, sizeof(in6_addr_t), HINIC3_FLOWS); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return -1; ++ } ++ ++ meta_ipv6 = hinic3_nlattr_get_itr_unspec(nla, sizeof(in6_addr_t)); ++ if (meta_ipv6 == NULL) { ++ hinic3_free(conf); ++ return -1; ++ } ++ ++ memcpy(conf, meta_ipv6, sizeof(in6_addr_t)); ++ *dst_conf = conf; ++ return 0; ++} ++ ++static int hinic3_flow_dump_port_conf(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ struct rte_flow_action_port_id *conf = hinic3_calloc(1, sizeof(struct rte_flow_action_port_id), HINIC3_FLOWS); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return -1; ++ } ++ ++ uint16_t meta_port = hinic3_nlattr_get_itr_u16(nla); ++ uint16_t port_net = ntohs(meta_port); ++ conf->id = port_net; ++ ++ uint16_t dpdk_port; ++ int res = hinic3_get_port_id_by_ifindex(port_net, &dpdk_port); ++ if (res != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get port id failed, vport_id %X", port_net); ++ hinic3_free(conf); ++ return -1; ++ } ++ conf->id = dpdk_port; ++ *dst_conf = conf; ++ return 0; ++} ++ ++static int hinic3_flow_dump_vxlan_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ hinic3_act_vxlan_header *meta_header = ++ (hinic3_act_vxlan_header *)hinic3_nlattr_get_itr_unspec(nla, sizeof(hinic3_act_vxlan_header)); ++ if (meta_header == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get vxlan header failed"); ++ return -1; ++ } ++ ++ void *conf = hinic3_get_vxlan_gpe_header_items(meta_header); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get vxlan header items failed"); ++ return -1; ++ } ++ *dst_conf = conf; ++ return 0; ++} ++ ++struct rte_flow_action_port_id *hinic3_flow_dump_sample_port_conf(uint8_t session_id) ++{ ++ struct rte_flow_action_port_id *output_port = NULL; ++ int ret = 0; ++ output_port = ++ (struct rte_flow_action_port_id *)hinic3_calloc(1, sizeof(struct rte_flow_action_port_id), HINIC3_FLOWS); ++ if (output_port == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return NULL; ++ } ++ uint16_t port_net; ++ ret = hinic3_flow_get_port_id_by_session(session_id, &port_net); ++ if (ret != 0) { ++ hinic3_free(output_port); ++ return NULL; ++ } ++ ++ uint16_t port_dpdk; ++ ret = hinic3_get_port_id_by_ifindex(port_net, &port_dpdk); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump sample port info, get port id failed, vport_id %X", port_net); ++ hinic3_free(output_port); ++ return NULL; ++ } ++ output_port->id = port_dpdk; ++ output_port->reserved = session_id; // 利用port_id action中的reserved字段暂存session_id ++ return output_port; ++} ++ ++struct rte_flow_action_vxlan_encap *hinic3_flow_dump_sample_vxlan_encap_conf(uint8_t session_id) ++{ ++ struct hinic3_flow_act_vxlan_gpe_header meta_header = { 0 }; ++ int ret = hinic3_flow_dump_construct_vxlan_header(session_id, &meta_header); ++ if (ret != 0) { ++ return NULL; ++ } ++ ++ return hinic3_get_vxlan_gpe_header_items(&meta_header); ++} ++ ++struct rte_flow_action *hinic3_flow_dump_construct_sample_actions(const struct hiovs_mirror_info *mirror_info) ++{ ++ enum hinic3_session_tpye session_type; ++ struct rte_flow_action *actions = NULL; ++ uint8_t session_id = mirror_info->sessions[1]; ++ actions = ++ (struct rte_flow_action *)hinic3_calloc(HINIC3_SAMLPE_ACTION_NUM, sizeof(struct rte_flow_action), HINIC3_FLOWS); ++ if (actions == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return NULL; ++ } ++ ++ struct rte_flow_action *port_id_action = actions; ++ port_id_action->type = RTE_FLOW_ACTION_TYPE_PORT_ID; ++ port_id_action->conf = hinic3_flow_dump_sample_port_conf(session_id); ++ if (port_id_action->conf == NULL) { ++ hinic3_free(actions); ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, construct sample port conf filed"); ++ return NULL; ++ } ++ ++ session_type = hinic3_get_session_type(session_id); ++ struct rte_flow_action *vxlan_encap_action = ++port_id_action; ++ if (session_type == HINIC3_EMC_VXLAN_SESSION) { ++ vxlan_encap_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP; ++ vxlan_encap_action->conf = hinic3_flow_dump_sample_vxlan_encap_conf(session_id); ++ } else { ++ vxlan_encap_action->type = RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP; ++ vxlan_encap_action->conf = hinic3_flow_dump_sample_nvgre_encap_conf(session_id); ++ } ++ if (vxlan_encap_action->conf == NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void *, port_id_action->conf)); ++ hinic3_free(actions); ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, construct sample port conf filed"); ++ return NULL; ++ } ++ ++ struct rte_flow_action *end_action = ++vxlan_encap_action; ++ end_action->type = RTE_FLOW_ACTION_TYPE_END; ++ end_action->conf = NULL; ++ ++ return actions; ++} ++ ++static struct rte_flow_action_sample *hinic3_flow_dump_get_sample_conf(const struct hiovs_mirror_info *mirror_info) ++{ ++ struct rte_flow_action_sample *conf = NULL; ++ conf = (struct rte_flow_action_sample *)hinic3_calloc(1, sizeof(struct rte_flow_action_sample), HINIC3_FLOWS); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return NULL; ++ } ++ ++ conf->ratio = 1; ++ conf->actions = hinic3_flow_dump_construct_sample_actions(mirror_info); ++ if (conf->actions == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, construct sample actions failed"); ++ hinic3_free(conf); ++ return NULL; ++ } ++ return conf; ++} ++ ++int hinic3_flow_dump_acl_sample_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ uint16_t session_id = hinic3_nlattr_get_itr_u16(nla); ++ struct hiovs_mirror_info mirror_info = { 0 }; ++ mirror_info.sessions[1] = session_id; ++ ++ *dst_conf = hinic3_flow_dump_get_sample_conf(&mirror_info); ++ if (*dst_conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, construct acl sample action failed."); ++ return -1; ++ } ++ return 0; ++} ++ ++int hinic3_flow_dump_sample_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ const struct hiovs_mirror_info *mirror_info = hinic3_nlattr_get_itr_unspec(nla, sizeof(struct hiovs_mirror_info)); ++ if (mirror_info == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get sample failed"); ++ return -1; ++ } ++ ++ void *conf = hinic3_flow_dump_get_sample_conf(mirror_info); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, construct emc sample action failed."); ++ return -1; ++ } ++ *dst_conf = conf; ++ return 0; ++} ++ ++static int hinic3_flow_dump_block_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) ++{ ++ const struct hinic3_flow_act_block_version *flow_block = NULL; ++ ++ struct rte_flow_action_set_tag *conf = hinic3_calloc(1, sizeof(struct rte_flow_action_set_tag), HINIC3_FLOWS); ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); ++ return -1; ++ } ++ ++ flow_block = hinic3_nlattr_get_itr_unspec(nla, sizeof(struct hinic3_flow_act_block_version)); ++ if (flow_block == NULL) { ++ hinic3_free(conf); ++ return -1; ++ } ++ conf->data = flow_block->block_version; ++ conf->mask = flow_block->block_id; ++ conf->index = 0xFE; ++ ++ *dst_conf = conf; ++ return 0; ++} ++ ++// rte_flow_action info table ++static struct hinic3_flow_action_info_s g_hinic3_flow_action_conf_table[] = { ++ {HINIC3_FLOW_ACT_OUTPUT, RTE_FLOW_ACTION_TYPE_PORT_ID, hinic3_flow_dump_port_conf}, ++ {HINIC3_FLOW_ACT_VXL_GPE_PUSH, RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, hinic3_flow_dump_vxlan_conf_get}, ++ {HINIC3_FLOW_ACT_SET_SMAC, RTE_FLOW_ACTION_TYPE_SET_MAC_SRC, hinic3_flow_dump_mac_conf_get}, ++ {HINIC3_FLOW_ACT_SET_DMAC, RTE_FLOW_ACTION_TYPE_SET_MAC_DST, hinic3_flow_dump_mac_conf_get}, ++ {HINIC3_FLOW_ACT_SET_SIP, RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC, hinic3_flow_dump_ipv4_conf_get}, ++ {HINIC3_FLOW_ACT_SET_DIP, RTE_FLOW_ACTION_TYPE_SET_IPV4_DST, hinic3_flow_dump_ipv4_conf_get}, ++ {HINIC3_FLOW_ACT_SET_SIPV6, RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC, hinic3_flow_dump_ipv6_conf_get}, ++ {HINIC3_FLOW_ACT_SET_DIPV6, RTE_FLOW_ACTION_TYPE_SET_IPV6_DST, hinic3_flow_dump_ipv6_conf_get}, ++ {HINIC3_FLOW_ACT_DROP, RTE_FLOW_ACTION_TYPE_DROP, NULL}, ++ {HINIC3_FLOW_ACT_DEC_TTL, RTE_FLOW_ACTION_TYPE_DEC_TTL, NULL}, ++ {HINIC3_FLOW_ACT_VLAN_POP, RTE_FLOW_ACTION_TYPE_OF_POP_VLAN, NULL}, ++ {HINIC3_FLOW_ACT_VXL_POP, RTE_FLOW_ACTION_TYPE_VXLAN_DECAP, NULL}, ++ {HINIC3_FLOW_ACT_COUNT, RTE_FLOW_ACTION_TYPE_COUNT, NULL}, ++ {HINIC3_FLOW_ACT_MIRROR, RTE_FLOW_ACTION_TYPE_SAMPLE, hinic3_flow_dump_sample_conf_get}, ++ {HINIC3_FLOW_ACT_BLOCK_VERSION, RTE_FLOW_ACTION_TYPE_SET_TAG, hinic3_flow_dump_block_conf_get}, ++}; ++ ++static struct hinic3_flow_action_info_s *hinic3_get_flow_action_info(enum hinic3_flow_action_type type) ++{ ++ int size = sizeof(g_hinic3_flow_action_conf_table) / sizeof(struct hinic3_flow_action_info_s); ++ for (int i = 0; i < size; ++i) { ++ if (g_hinic3_flow_action_conf_table[i].hinic3_type == type) { ++ return &g_hinic3_flow_action_conf_table[i]; ++ } ++ } ++ return NULL; ++} ++ ++static int hinic3_trans_action_type_by_hiovs(enum hinic3_flow_action_type type, const hinic3_nlattr_itr nla, ++ void **dst_conf, enum rte_flow_action_type *rte_type) ++{ ++ struct hinic3_flow_action_info_s *action_info = hinic3_get_flow_action_info(type); ++ if (action_info == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, invalid hinic3_flow_action_type, type: %d", type); ++ return -1; ++ } ++ ++ if (action_info->conf_call_back == NULL) { ++ *rte_type = action_info->rte_type; ++ *dst_conf = NULL; ++ return 0; ++ } ++ ++ int ret = action_info->conf_call_back(nla, dst_conf); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get hinic3_fow_action conf failed"); ++ return -1; ++ } ++ ++ *rte_type = action_info->rte_type; ++ return 0; ++} ++ ++static struct rte_flow_action *hinic3_flow_action_factory(enum hinic3_flow_action_type type, const hinic3_nlattr_itr nla) ++{ ++ void *conf = NULL; ++ enum rte_flow_action_type rte_type = 0; ++ ++ int ret = hinic3_trans_action_type_by_hiovs(type, nla, &conf, &rte_type); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get hinic3_fow_action form hiovs failed"); ++ return NULL; ++ } ++ ++ struct rte_flow_action *action = hinic3_build_rte_flow_action(rte_type, conf); ++ if (action == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, action factory error, rte_type: %d", rte_type); ++ if (conf != NULL) { ++ hinic3_free(conf); ++ } ++ } ++ ++ return action; ++} ++ ++static int hinic3_build_vlan_action(struct hinic3_dump_flow_info *flow, hinic3_nlattr_itr nla) ++{ ++ uint16_t vid = hinic3_nlattr_get_itr_u16(nla); ++ struct rte_flow_action *action = NULL; ++ action = hinic3_vlan_action_factory(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN, vid); ++ if (action == NULL) { ++ goto err_free; ++ } ++ ++ int ret = hinic3_dump_flow_action_insert(flow, action); ++ if (ret != 0) { ++ goto err_free; ++ } ++ ++ action = hinic3_vlan_action_factory(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID, vid); ++ if (action == NULL) { ++ goto err_free; ++ } ++ ++ ret = hinic3_dump_flow_action_insert(flow, action); ++ if (ret != 0) { ++ goto err_free; ++ } ++ ++ action = hinic3_vlan_action_factory(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP, vid); ++ if (action == NULL) { ++ goto err_free; ++ } ++ ++ ret = hinic3_dump_flow_action_insert(flow, action); ++ if (ret != 0) { ++ goto err_free; ++ } ++ return 0; ++ ++err_free: ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build vlan action error"); ++ hinic3_free_rte_flow_action(action); ++ hinic3_free(action); ++ return -1; ++} ++ ++static bool hinic3_dp_hash_output_port_check(const hinic3_nlattr_itr nla) ++{ ++ uint16_t port = hinic3_nlattr_get_itr_u16(nla); ++ return port == HINIC3_DP_HASH_DUMP_DEFALUT_PORT ? true : false; ++} ++ ++ ++int hinic3_build_flow_action_sub(struct hinic3_dump_flow_info *flow, const struct hinic3_nlattr *key) ++{ ++ hinic3_nlattr_itr nla = NULL; ++ ++ int ret = 0; ++ struct rte_flow_action *action = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH(nla, key) { ++ enum hinic3_flow_action_type type = hinic3_nlattr_get_itr_type(nla); ++ // vlan: one hinic3_action map to three rte_actions; ++ if (type == HINIC3_FLOW_ACT_VLAN_PUSH) { ++ ret = hinic3_build_vlan_action(flow, nla); ++ if (ret != 0) { ++ goto err_func; ++ } ++ } else if (type == HINIC3_FLOW_ACT_CT || ++ (type == HINIC3_FLOW_ACT_OUTPUT && hinic3_dp_hash_output_port_check(nla))) { ++ continue; ++ } else { ++ action = hinic3_flow_action_factory(type, nla); ++ if (action == NULL) { ++ goto err_func; ++ } ++ ret = hinic3_dump_flow_action_insert(flow, action); ++ if (ret != 0) { ++ goto err_func; ++ } ++ } ++ } ++ return 0; ++ ++err_func: ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action error"); ++ hinic3_free_rte_flow_action(action); ++ if (action != NULL) { ++ hinic3_free(action); ++ } ++ return -1; ++} ++ ++int hinic3_hinic3_flow_info_action_build(struct hinic3_dump_flow_info *flow, struct hinic3_nlattr_obj *dump_key, ++ size_t key_length) ++{ ++ struct hinic3_nlattr flow_action; ++ hinic3_nlattr_init(&flow_action, dump_key, key_length); ++ hinic3_nlattr_reset_itr(&flow_action, key_length); ++ ++ int ret = hinic3_build_flow_action_sub(flow, &flow_action); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build flow_info action error"); ++ } ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.h +new file mode 100644 +index 0000000..840c082 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_DUMP_ACTION_H ++#define HINIC3_FLOW_DUMP_ACTION_H ++ ++#include ++#include "hinic3_nlattr.h" ++#include "rte_flow.h" ++#include "hinic3_flow_dump_public.h" ++ ++void hinic3_free_one_flow_actions(struct rte_flow_action* actions, int action_num); ++int hinic3_hinic3_flow_info_action_build(struct hinic3_dump_flow_info *flow, struct hinic3_nlattr_obj* dump_key, ++ size_t key_length); ++int hinic3_flow_dump_sample_conf_get(const hinic3_nlattr_itr nla, void **dst_conf); ++int hinic3_flow_dump_acl_sample_conf_get(const hinic3_nlattr_itr nla, void **dst_conf); ++int hinic3_build_flow_action_sub(struct hinic3_dump_flow_info *flow, const struct hinic3_nlattr *key); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c +new file mode 100644 +index 0000000..d056b6c +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c +@@ -0,0 +1,363 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_flow_dump_item.h" ++#include "hinic3_flow_dump_item_key.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_log.h" ++#include "hinic3_packet_key_public.h" ++#include "hinic3_util.h" ++#include "hinic3_meminfo.h" ++ ++static void hinic3_free_rte_flow_item(struct rte_flow_item *item) ++{ ++ if (item == NULL) { ++ return; ++ } ++ if (item -> spec != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void*, item -> spec)); ++ item -> spec = NULL; ++ } ++ if (item -> last != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void*, item -> last)); ++ item -> last = NULL; ++ } ++ if (item -> mask != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void*, item -> mask)); ++ item -> mask = NULL; ++ } ++} ++ ++void hinic3_free_one_flow_items(struct rte_flow_item* items, int item_num) ++{ ++ for (int i = 0; i < item_num; ++i) { ++ hinic3_free_rte_flow_item(&items[i]); ++ } ++} ++ ++int hinic3_dump_flow_item_insert(struct hinic3_dump_flow_info *flow, struct rte_flow_item *item) ++{ ++ unsigned int index = flow->useful_item_index; ++ ++ if (index >= HINIC3_FLOW_DUMP_MAX_PATTERN) { ++ return -1; ++ } ++ ++ memcpy(&flow->items[index], item, sizeof(struct rte_flow_item)); ++ ++ flow->useful_item_index++; ++ hinic3_free(item); ++ item = NULL; ++ return 0; ++} ++ ++static struct rte_flow_item_vxlan* hinic3_build_vxlan_item(uint32_t vni_value) ++{ ++ struct rte_flow_item_vxlan* vxlan = hinic3_calloc(1, sizeof(struct rte_flow_item_vxlan), HINIC3_FLOWS); ++ if (vxlan == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for rte_flow_item_vxlan failed!"); ++ return NULL; ++ } ++ ++ vni_value = vni_value >> HINIC3_BIT_MID_MOVE_INDEX; ++ ++ uint8_t vni[HINIC3_VNI_ARR_SIZE]; ++ vni[HINIC3_VNI_ARR_LOW] = vni_value & HINIC3_LOW_EIGHT_BIT_MASK; ++ ++ uint32_t vni_mid = (vni_value & HINIC3_MID_EIGHT_BIT_MASK); ++ vni[HINIC3_VNI_ARR_MID] = vni_mid >> HINIC3_BIT_MID_MOVE_INDEX; ++ ++ uint32_t vni_high = vni_value & HINIC3_HIGH_EIGHT_BIT_MASK; ++ vni[HINIC3_VNI_ARR_HIGH] = vni_high >> HINIC3_BIT_HIGH_MOVE_INDEX; ++ ++ memcpy(vxlan->vni, vni, sizeof(uint8_t) * HINIC3_VNI_ARR_SIZE); ++ return vxlan; ++} ++ ++static struct rte_flow_item_vlan *hinic3_build_vlan_item(uint32_t inner_vid, uint16_t ether_type, ++ uint16_t ether_inner_type) ++{ ++ struct rte_flow_item_vlan* vlan = hinic3_calloc(1, sizeof(struct rte_flow_item_vlan), HINIC3_FLOWS); ++ if (vlan == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for rte_flow_item_vlan failed!"); ++ return NULL; ++ } ++ ++ if (ether_type != ETH_TYPE_VLAN) { ++ vlan->inner_type = 0; ++ } else { ++ vlan->inner_type = htons(ether_inner_type); ++ } ++ vlan -> tci = inner_vid; ++ return vlan; ++} ++ ++static struct rte_flow_item_eth* hinic3_build_eth_item(uint16_t ether_type, const struct hinic3_key_mac* mac) ++{ ++ struct rte_flow_item_eth* eth = hinic3_calloc(1, sizeof(struct rte_flow_item_eth), HINIC3_FLOWS); ++ if (eth == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for rte_flow_item_eth failed!"); ++ return NULL; ++ } ++ memcpy(&(eth ->dst), mac->dmac, sizeof(mac->dmac)); ++ memcpy(&(eth ->src), mac->smac, sizeof(mac->smac)); ++ eth->type = htons(ether_type); ++ return eth; ++} ++ ++static struct rte_flow_item_ipv4* hinic3_build_ipv4_item(const struct hinic3_key_ip *ip, uint16_t tcp_udp_flag) ++{ ++ if (ip == NULL) { ++ return NULL; ++ } ++ struct rte_flow_item_ipv4* ipv4 = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv4), HINIC3_FLOWS); ++ if (ipv4 == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for rte_flow_item_eth failed!"); ++ return NULL; ++ } ++ memcpy(&ipv4 ->hdr.src_addr, &ip->src, sizeof(ipv4->hdr.src_addr)); ++ memcpy(&ipv4 ->hdr.dst_addr, &ip->dst, sizeof(ipv4->hdr.dst_addr)); ++ ++ if (tcp_udp_flag == HINIC3_DUMP_UDP_FLAG) { ++ ipv4->hdr.next_proto_id = HINIC3_UDP_PROTO; ++ } else if (tcp_udp_flag == HINIC3_DUMP_TCP_FLAG) { ++ ipv4->hdr.next_proto_id = HINIC3_TCP_PROTO; ++ } ++ ++ return ipv4; ++} ++ ++static struct rte_flow_item_ipv6* hinic3_build_ipv6_item(const struct hinic3_key_ip *ip, uint16_t tcp_udp_flag) ++{ ++ if (ip == NULL) { ++ return NULL; ++ } ++ struct rte_flow_item_ipv6* ipv6 = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv6), HINIC3_FLOWS); ++ if (ipv6 == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for rte_flow_item_eth failed!"); ++ return NULL; ++ } ++ memcpy(&ipv6 ->hdr.src_addr, &ip->src, sizeof(ipv6->hdr.src_addr)); ++ memcpy(&ipv6 ->hdr.dst_addr, &ip->dst, sizeof(ipv6->hdr.dst_addr)); ++ ++ if (tcp_udp_flag == HINIC3_DUMP_UDP_FLAG) { ++ ipv6->hdr.proto = HINIC3_UDP_PROTO; ++ } else if (tcp_udp_flag == HINIC3_DUMP_TCP_FLAG) { ++ ipv6->hdr.proto = HINIC3_TCP_PROTO; ++ } ++ return ipv6; ++} ++ ++static struct rte_flow_item_tcp* hinic3_build_tcp_item(uint16_t src_port, uint16_t dst_port) ++{ ++ struct rte_flow_item_tcp* tcp = hinic3_calloc(1, sizeof(struct rte_flow_item_tcp), HINIC3_FLOWS); ++ if (tcp == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for rte_flow_item_tcp failed!"); ++ return NULL; ++ } ++ tcp->hdr.dst_port = dst_port; ++ tcp->hdr.src_port = src_port; ++ return tcp; ++} ++ ++static struct rte_flow_item_udp* hinic3_build_udp_item(uint16_t src_port, uint16_t dst_port) ++{ ++ struct rte_flow_item_udp* udp = hinic3_calloc(1, sizeof(struct rte_flow_item_udp), HINIC3_FLOWS); ++ if (udp == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for rte_flow_item_udp failed!"); ++ return NULL; ++ } ++ udp->hdr.dst_port = dst_port; ++ udp->hdr.src_port = src_port; ++ return udp; ++} ++ ++static uint32_t* hinic3_build_inpou_port_item(uint32_t input_port) ++{ ++ uint32_t* port = hinic3_calloc(1, sizeof(uint32_t), HINIC3_FLOWS); ++ if (port == NULL) { ++ HINIC3_LOG(DEBUG, FLOW, "Malloc memmory for inpou_port_item failed!"); ++ return NULL; ++ } ++ *port = input_port; ++ return port; ++} ++ ++static void* hinic3_build_flow_item_spec(enum rte_flow_item_type type, const struct hinic3_flow_dump_keys* keys) ++{ ++ void *spec = NULL; ++ ++ switch (type) { ++ case RTE_FLOW_ITEM_TYPE_PORT_ID: ++ spec = hinic3_build_inpou_port_item(keys->input_port); ++ break; ++ case RTE_FLOW_ITEM_TYPE_ETH: ++ spec = (void*)hinic3_build_eth_item(keys->ether_type, &(keys->mac)); ++ break; ++ case RTE_FLOW_ITEM_TYPE_IPV4: ++ spec = (void*)hinic3_build_ipv4_item(&(keys->ip), keys->tcp_udp_flag); ++ break; ++ case RTE_FLOW_ITEM_TYPE_IPV6: ++ spec = (void*)hinic3_build_ipv6_item(&(keys->ip), keys->tcp_udp_flag); ++ break; ++ case RTE_FLOW_ITEM_TYPE_VLAN: ++ spec = (void*)hinic3_build_vlan_item(keys ->inner_vid, keys->ether_type, keys->ether_inner_type); ++ break; ++ case RTE_FLOW_ITEM_TYPE_TCP: ++ spec = (void*)hinic3_build_tcp_item(keys->port_src, keys->port_dst); ++ break; ++ case RTE_FLOW_ITEM_TYPE_UDP: ++ spec = (void*)hinic3_build_udp_item(keys->port_src, keys->port_dst); ++ break; ++ case RTE_FLOW_ITEM_TYPE_VXLAN: ++ spec = (void*)hinic3_build_vxlan_item(keys ->vni); ++ break; ++ default: ++ break; ++ } ++ return spec; ++} ++ ++struct rte_flow_item* hinic3_build_rte_flow_item(enum rte_flow_item_type type, const void *spec, ++ const void *last, const void *mask) ++{ ++ struct rte_flow_item* item = hinic3_calloc(1, sizeof(struct rte_flow_item), HINIC3_FLOWS); ++ if (item == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump: calloc for rte flow item failed"); ++ return NULL; ++ } ++ ++ item->type = type; ++ item->spec = spec; ++ item->mask = mask; ++ item->last = last; ++ return item; ++} ++ ++static struct rte_flow_item* hinic3_dump_flow_item_factory(enum rte_flow_item_type type, ++ const struct hinic3_flow_dump_keys* keys) ++{ ++ if (keys == NULL) { ++ return NULL; ++ } ++ ++ void *spec = NULL; ++ void *mask = NULL; ++ struct rte_flow_item* item = NULL; ++ ++ spec = hinic3_build_flow_item_spec(type, keys); ++ if (spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "HINIC3 FLOW DUMP: malloc for item spec failed"); ++ return NULL; ++ } ++ ++ item = hinic3_build_rte_flow_item(type, (void*)spec, NULL, mask); ++ if (item == NULL) { ++ hinic3_free(spec); ++ } ++ return item; ++} ++ ++static struct rte_flow_item *hinic3_flow_dump_tcpudp_item_build(const struct hinic3_flow_dump_keys *keys) ++{ ++ struct rte_flow_item *flow_item = NULL; ++ if (keys->tcp_udp_flag == HINIC3_DUMP_TCP_FLAG) { ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_TCP, keys); ++ } else if (keys->tcp_udp_flag == HINIC3_DUMP_UDP_FLAG) { ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_UDP, keys); ++ } ++ return flow_item; ++} ++ ++static struct rte_flow_item *hinic3_flow_dump_ip_item_build(const struct hinic3_flow_dump_keys *keys) ++{ ++ struct rte_flow_item *flow_item = NULL; ++ if (keys->ip_version == 0) { ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_IPV4, keys); ++ } else if (keys ->ip_version == 1) { ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_IPV6, keys); ++ } ++ return flow_item; ++} ++ ++static int hinic3_flow_item_build_sub(struct hinic3_dump_flow_info *flow, struct hinic3_flow_dump_keys* keys) ++{ ++ if (keys == NULL) { ++ return -1; ++ } ++ struct rte_flow_item *flow_item = NULL; ++ int ret = 0; ++ ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_PORT_ID, keys); ++ ret = hinic3_dump_flow_item_insert(flow, flow_item); ++ if (ret != 0) { ++ goto err_func; ++ } ++ ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_ETH, keys); ++ ret = hinic3_dump_flow_item_insert(flow, flow_item); ++ if (ret != 0) { ++ goto err_func; ++ } ++ ++ flow_item = hinic3_flow_dump_ip_item_build(keys); ++ ret = hinic3_dump_flow_item_insert(flow, flow_item); ++ if (ret != 0) { ++ goto err_func; ++ } ++ ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_VLAN, keys); ++ ret = hinic3_dump_flow_item_insert(flow, flow_item); ++ if (ret != 0) { ++ goto err_func; ++ } ++ ++ if (keys->tcp_udp_flag != HINIC3_DUMP_TCP_UDP_INVALID) { ++ flow_item = hinic3_flow_dump_tcpudp_item_build(keys); ++ ret = hinic3_dump_flow_item_insert(flow, flow_item); ++ if (ret != 0) { ++ goto err_func; ++ } ++ } ++ ++ flow_item = hinic3_dump_flow_item_factory(RTE_FLOW_ITEM_TYPE_VXLAN, keys); ++ ret = hinic3_dump_flow_item_insert(flow, flow_item); ++ if (ret != 0) { ++ goto err_func; ++ } ++ ++ return 0; ++err_func: ++ hinic3_free_rte_flow_item(flow_item); ++ if (flow_item != NULL) { ++ hinic3_free(flow_item); ++ } ++ flow_item = NULL; ++ HINIC3_LOG(ERR, FLOW, "HINIC3 FLOW DUMP: build hinic3_dump_flow_info item failed"); ++ return -1; ++} ++ ++int hinic3_hinic3_flow_info_item_build(struct hinic3_dump_flow_info *flow, struct hinic3_nlattr_obj* dump_key, ++ size_t key_length) ++{ ++ if (flow == NULL) { ++ return -1; ++ } ++ ++ struct hinic3_nlattr flow_key; ++ hinic3_nlattr_init(&flow_key, dump_key, key_length); ++ hinic3_nlattr_reset_itr(&flow_key, key_length); ++ ++ struct hinic3_flow_dump_keys row_keys = {0}; ++ row_keys.vlan_flag = false; ++ row_keys.vxlan_flag = false; ++ ++ int ret = hinic3_get_full_key(&row_keys, &flow_key); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "HINIC3 FLOW DUMP: flow item build failed"); ++ return -1; ++ } ++ ++ ret = hinic3_flow_item_build_sub(flow, &row_keys); ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.h +new file mode 100644 +index 0000000..48e122e +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.h +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_DUMP_ITEM_H ++#define HINIC3_FLOW_DUMP_ITEM_H ++#include ++#include "hinic3_nlattr.h" ++#include "rte_flow.h" ++#include "hinic3_flow_dump_public.h" ++#include "hinic3_flow_agent_public.h" ++ ++void hinic3_free_one_flow_items(struct rte_flow_item* items, int item_num); ++int hinic3_hinic3_flow_info_item_build(struct hinic3_dump_flow_info *flow, struct hinic3_nlattr_obj* dump_key, ++ size_t key_length); ++struct rte_flow_item* hinic3_build_rte_flow_item(enum rte_flow_item_type type, const void *spec, ++ const void *last, const void *mask); ++int hinic3_dump_flow_item_insert(struct hinic3_dump_flow_info *flow, struct rte_flow_item *item); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c +new file mode 100644 +index 0000000..6cab59b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c +@@ -0,0 +1,174 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_flow_dump_item_key.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_message.h" ++#include "hinic3_log.h" ++#define HINIC3_VFPORT_TRANS_HEAD_BIT 0X1000 ++#define HINIC3_PORT_VALUE_MASK 0x0FFF ++static void hinic3_construct_port_key(enum hinic3_flow_key_type type, const hinic3_nlattr_itr nla, ++ uint16_t *port_src, uint16_t *port_dst) ++{ ++ switch (type) { ++ case HINIC3_FLOW_KEY_SRC_PORT: ++ *port_src = hinic3_nlattr_get_itr_u16(nla); ++ break; ++ case HINIC3_FLOW_KEY_DST_PORT: ++ *port_dst = hinic3_nlattr_get_itr_u16(nla); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void hinic3_construct_protocol_key(const hinic3_nlattr_itr nla, uint16_t *tcp_udp_flag) ++{ ++ uint16_t flag = hinic3_nlattr_get_itr_u8(nla); ++ switch (flag) { ++ case IPPROTO_UDP: ++ *tcp_udp_flag = HINIC3_DUMP_UDP_FLAG; ++ break; ++ case IPPROTO_TCP: ++ *tcp_udp_flag = HINIC3_DUMP_TCP_FLAG; ++ break; ++ default: ++ *tcp_udp_flag = HINIC3_DUMP_TCP_UDP_INVALID; ++ break; ++ } ++ return; ++} ++ ++static void hinic3_construct_ip_key(enum hinic3_flow_key_type type, const hinic3_nlattr_itr nla, ++ struct hinic3_key_ip *ip_key, uint8_t *ip_version) ++{ ++ const void* ipv6 = NULL; ++ switch (type) { ++ case HINIC3_FLOW_KEY_SRC_IP: ++ *ip_version = 0; ++ ip_key ->src.ipv4 = hinic3_nlattr_get_itr_u32(nla); ++ break; ++ case HINIC3_FLOW_KEY_DST_IP: ++ ip_key ->dst.ipv4 = hinic3_nlattr_get_itr_u32(nla); ++ break; ++ case HINIC3_FLOW_KEY_SRC_IPV6: ++ *ip_version = 1; ++ ipv6 = hinic3_nlattr_get_itr_unspec(nla, sizeof(ip_key ->src.ipv6)); ++ memcpy(&(ip_key ->src.ipv6), ipv6, sizeof(ip_key ->src.ipv6)); ++ break; ++ case HINIC3_FLOW_KEY_DST_IPV6: ++ ipv6 = hinic3_nlattr_get_itr_unspec(nla, sizeof(ip_key ->dst.ipv6)); ++ memcpy(&(ip_key ->dst.ipv6), ipv6, sizeof(ip_key ->dst.ipv6)); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void hinic3_construct_mac_key(enum hinic3_flow_key_type type, const hinic3_nlattr_itr nla, ++ struct hinic3_key_mac *mac) ++{ ++ uint8_t *nla_mac = NULL; ++ switch (type) { ++ case HINIC3_FLOW_KEY_SRC_MAC: ++ nla_mac = (uint8_t*)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ memcpy(mac -> smac, nla_mac, sizeof(mac->smac)); ++ break; ++ case HINIC3_FLOW_KEY_DST_MAC: ++ nla_mac = (uint8_t*)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ memcpy(mac -> dmac, nla_mac, sizeof(mac->dmac)); ++ break; ++ default: ++ break; ++ } ++ return; ++} ++ ++static void hinic3_construct_vxlan_key(const hinic3_nlattr_itr nla, uint32_t *vni) ++{ ++ *vni = hinic3_nlattr_get_itr_u32(nla); ++ return; ++} ++ ++static void hinic3_construct_vlan_key(enum hinic3_flow_key_type type, const hinic3_nlattr_itr nla, ++ uint32_t *vlan_id) ++{ ++ *vlan_id = hinic3_nlattr_get_itr_u16(nla); ++ return; ++} ++ ++static void hinic3_construct_ether_type_key(const hinic3_nlattr_itr nla, uint16_t *ether_type) ++{ ++ *ether_type = ntohs(hinic3_nlattr_get_itr_u16(nla)); ++ return; ++} ++ ++static void hinic3_construct_input_port_key(const hinic3_nlattr_itr nla, uint32_t *port) ++{ ++ uint16_t meta_port = hinic3_nlattr_get_itr_u16(nla); ++ uint16_t ifindex = ntohs(meta_port); ++ uint16_t dpdk_port; ++ ++ int ret = hinic3_get_port_id_by_ifindex(ifindex, &dpdk_port); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "HINIC3 FLOW DUMP: construct_input_port_key, get error port"); ++ return; ++ } ++ ++ *port = dpdk_port; ++ return; ++} ++ ++int hinic3_get_full_key(struct hinic3_flow_dump_keys* row_keys, const struct hinic3_nlattr *key) ++{ ++ if (row_keys == NULL || key == NULL) { ++ HINIC3_LOG(ERR, FLOW, "HINIC3 FLOW DUMP: Get full key error, input NULL pointer"); ++ return -1; ++ } ++ ++ hinic3_nlattr_itr nla = NULL; ++ HINIC3_NLATTR_FOR_EACH(nla, key) { ++ enum hinic3_flow_key_type type = hinic3_nlattr_get_itr_type(nla); ++ switch (type) { ++ case HINIC3_FLOW_KEY_VNI: ++ row_keys ->vxlan_flag = true; ++ hinic3_construct_vxlan_key(nla, &(row_keys->vni)); ++ break; ++ case HINIC3_FLOW_KEY_OUTER_VID: ++ row_keys ->vlan_flag = true; ++ hinic3_construct_vlan_key(type, nla, &(row_keys->inner_vid)); ++ break; ++ case HINIC3_FLOW_KEY_PROTOCOL: ++ hinic3_construct_protocol_key(nla, &(row_keys->tcp_udp_flag)); ++ break; ++ case HINIC3_FLOW_KEY_SRC_PORT: ++ case HINIC3_FLOW_KEY_DST_PORT: ++ hinic3_construct_port_key(type, nla, &(row_keys->port_src), &(row_keys->port_dst)); ++ break; ++ case HINIC3_FLOW_KEY_SRC_MAC: ++ case HINIC3_FLOW_KEY_DST_MAC: ++ hinic3_construct_mac_key(type, nla, &(row_keys->mac)); ++ break; ++ case HINIC3_FLOW_KEY_DL_TYPE: ++ hinic3_construct_ether_type_key(nla, &(row_keys->ether_type)); ++ break; ++ case HINIC3_FLOW_KEY_SRC_IP: ++ case HINIC3_FLOW_KEY_DST_IP: ++ case HINIC3_FLOW_KEY_SRC_IPV6: ++ case HINIC3_FLOW_KEY_DST_IPV6: ++ hinic3_construct_ip_key(type, nla, &row_keys->ip, &row_keys->ip_version); ++ break; ++ case HINIC3_FLOW_KEY_IN_PORT: ++ hinic3_construct_input_port_key(nla, &(row_keys->input_port)); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if (row_keys->inner_vid != 0) { ++ row_keys->ether_inner_type = row_keys->ether_type; ++ row_keys->ether_type = ETH_TYPE_VLAN; ++ } ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.h +new file mode 100644 +index 0000000..dbc8c07 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.h +@@ -0,0 +1,39 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_DUMP_ITEM_KEY ++#define HINIC3_FLOW_DUMP_ITEM_KEY ++#include "hinic3_packet_key_public.h" ++#include "hinic3_nlattr.h" ++struct hinic3_flow_dump_keys { ++ // ether ++ struct hinic3_key_mac mac; ++ hinic3_be16 ether_type; ++ // vlan ++ bool vlan_flag; ++ hinic3_be32 cvlan_id; ++ hinic3_be32 inner_vid; ++ hinic3_be16 ether_inner_type; ++ // vxlan ++ bool vxlan_flag; ++ hinic3_be32 vni; ++ ++ // ip_version : 0 ipv4, 1 ipv6 ++ uint8_t ip_version; ++ struct hinic3_key_ip ip; ++ // application ++ hinic3_be16 port_src; ++ hinic3_be16 port_dst; ++ uint16_t tcp_udp_flag; ++ // input_port ++ uint32_t input_port; ++}; ++ ++enum { ++ HINIC3_DUMP_TCP_UDP_INVALID, ++ HINIC3_DUMP_TCP_FLAG, ++ HINIC3_DUMP_UDP_FLAG ++}; ++ ++int hinic3_get_full_key(struct hinic3_flow_dump_keys* row_keys, const struct hinic3_nlattr *key); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c +new file mode 100644 +index 0000000..59d5d85 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c +@@ -0,0 +1,154 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++#include "rte_flow.h" ++#include "hinic3_flow_dump_item.h" ++#include "hinic3_flow_dump_action.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_message.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_flow_dump_public.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_flow_emc_dump.h" ++static int hinic3_flow_dump_format(struct hinic3_dump_flow_mem* memory, struct hinic3_dpif_flow_for_get* dump_for_get, ++ struct rte_flow_error *error) ++{ ++ int ret = hinic3_hinic3_flow_info_item_build(&memory->flows[memory->cur_flow_num], ++ dump_for_get ->key, dump_for_get->key_len); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_flow_dump_format build flow item failed"); ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC, ++ NULL, "Dump flow item spec failed"); ++ } ++ ++ ret = hinic3_hinic3_flow_info_action_build(&memory->flows[memory->cur_flow_num], ++ dump_for_get->actions, dump_for_get ->action_len); ++ if (ret != 0) { ++ hinic3_free_one_flow_items(memory->flows[memory->cur_flow_num].items, ++ memory->flows[memory->cur_flow_num].useful_item_index); ++ HINIC3_LOG(ERR, FLOW, "hinic3_flow_dump_format build flow action failed"); ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ NULL, "Dump flow item action conf failed"); ++ } ++ ++ return ret; ++} ++ ++static int hinic3_flow_dump_to_context(struct hinic3_flow_dump_context* dump_context, struct rte_flow_error *error) ++{ ++ if (dump_context == NULL) { ++ return -1; ++ } ++ struct hinic3_dpif_flow_for_get dump_for_get; ++ ++ struct hinic3_nlattr_obj keys[HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE]; ++ struct hinic3_nlattr_obj actions[HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE]; ++ struct hinic3_nlattr_obj masks[HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE]; ++ ++ dump_for_get.key = keys; ++ dump_for_get.actions = actions; ++ dump_for_get.mask = masks; ++ ++ int ret = hinic3_flow_dump_next(dump_context->hiovs_state, &dump_for_get); ++ if (ret != 0) { ++ if (ret != HIOVS_EEMPTY) { ++ HINIC3_LOG(ERR, FLOW, "hiovs_state dump next error error code is %d", ret); ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_STATE, ++ NULL, "Dump flow hovs failed"); ++ } ++ return ret; ++ } ++ ++ ret = hinic3_flow_dump_format(&(dump_context->context_mem), &dump_for_get, error); ++ return ret; ++} ++ ++static int hinic3_emc_flow_dump_next_sub(struct hinic3_flow_dump_context* dump_context, int count, ++ struct rte_flow_error *error) ++{ ++ int ret = 0; ++ for (int i = 0; i < count; ++i) { ++ ret = hinic3_flow_dump_to_context(dump_context, error); ++ if (ret != 0) { ++ ret = ret == HIOVS_EEMPTY ? 0 : ret; ++ break; ++ } ++ dump_context->context_mem.cur_flow_num++; ++ } ++ ++ return ret; ++} ++ ++static int hinic3_emc_flow_dump_start_sub(struct hinic3_flow_dump_context *context) ++{ ++ int ret = 0; ++ ret = hinic3_flow_dump_start(&(context->hiovs_state)); ++ if (ret != HIOVS_OK && ret != HIOVS_EEMPTY) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_START_HARD, 1); ++ return ret; ++ } ++ return 0; ++} ++ ++int hinic3_emc_flow_dump_done_sub(struct hinic3_flow_dump_context *context) ++{ ++ int ret = 0; ++ if (context->hiovs_state != NULL) { ++ ret = hinic3_flow_dump_done(context->hiovs_state); ++ } ++ ++ if (ret != HIOVS_OK) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_DONE_HARD, 1); ++ return ret; ++ } ++ return ret; ++} ++ ++int hinic3_emc_flow_dump_start(struct hinic3_flow_dump_context *context, struct rte_flow_error *error) ++{ ++ if (context == NULL || error == NULL) { ++ return -1; ++ } ++ ++ int ret = 0; ++ ret = hinic3_emc_flow_dump_start_sub(context); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_START, 1); ++ } ++ return ret; ++} ++ ++int hinic3_emc_flow_dump_next(struct hinic3_flow_dump_context *context, int count, struct rte_flow_error *error) ++{ ++ if (context == NULL || error == NULL) { ++ return -1; ++ } ++ ++ int ret = 0; ++ ret = hinic3_emc_flow_dump_next_sub(context, count, error); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_NEXT, 1); ++ } ++ return ret; ++} ++ ++int hinic3_emc_flow_dump_done(struct hinic3_flow_dump_context *context, struct rte_flow_error *error) ++{ ++ if (context == NULL || error == NULL) { ++ return -1; ++ } ++ ++ int ret = 0; ++ ret = hinic3_emc_flow_dump_done_sub(context); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_DONE, 1); ++ } ++ return ret; ++} ++ ++void hinic3_emc_flow_dump_init(void) ++{ ++ hinic3_set_dump_start(HINIC3_FLOW_TYPE_EMC, hinic3_emc_flow_dump_start); ++ hinic3_set_dump_next(HINIC3_FLOW_TYPE_EMC, hinic3_emc_flow_dump_next); ++ hinic3_set_dump_done(HINIC3_FLOW_TYPE_EMC, hinic3_emc_flow_dump_done); ++}; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.h +new file mode 100644 +index 0000000..b2e4614 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.h +@@ -0,0 +1,7 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_EMC_DUMP_H ++#define HINIC3_FLOW_EMC_DUMP_H ++void hinic3_emc_flow_dump_init(void); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c +new file mode 100644 +index 0000000..a7edc6b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c +@@ -0,0 +1,142 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_age_delete_flow.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_provider.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_log.h" ++ ++static int hinic3_flow_destroy_check(struct rte_flow *flow, struct rte_flow_error *error) ++{ ++ int ret = 0; ++ if (flow->flags.is_mem_used == 0) { ++ return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Flow destroy: Duplicate memory used."); ++ } ++ ++ if (flow->flags.is_offload == 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FLOW_NOT_OFFLOADED, 1); ++ return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Flow destroy: Flow not completely offloaded."); ++ } ++ ++ if (flow->flags.is_sample == HINIC3_FLOW_EMC_MIRROR) { ++ ret = hinic3_del_rte_flow_in_session(flow); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DEL_FLOW_IN_SESSION, 1); ++ return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "Flow destroy: Driver interface error."); ++ } ++ } ++ return 0; ++} ++ ++static int hinic3_flow_destroy_sub(struct rte_flow *flow, struct rte_flow_error *error) ++{ ++ int ret; ++ struct hash_table_node *rte_bucket = NULL; ++ ++ rte_bucket = hinic3_get_flow_bucket(flow->flow_hash); ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ ++ ret = hinic3_flow_destroy_check(flow, error); ++ if (ret != 0) { ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return ret; ++ } ++ ++ ret = hinic3_del_rte_flow_in_hmap(rte_bucket, flow); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DEL_RTE_FLOW_IN_HMAP, 1); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Flow destroy: Failed to del flow in hmap."); ++ } ++ ++ ret = hinic3_flow_del_by_ufid(flow->hw_ufid); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DEL_HARD_FLOW, 1); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ (void)rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "Flow destroy: Driver interface error."); ++ return ret; ++ } ++ ++ (void)hinic3_rte_flow_dealloc(flow); ++ ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ if (hinic3_get_offload_flow_nums() > 0) { ++ hinic3_dec_offload_flow_nums(); ++ } ++ return 0; ++} ++ ++int hinic3_flow_emc_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error) ++{ ++ int ret; ++ ret = hinic3_try_rlock_flush_all(); ++ if (ret == EBUSY) { ++ return 0; ++ } ++ ++ if (ret != 0) { ++ return rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Flow destroy: Flush_all rlock failed."); ++ } ++ ++ ret = hinic3_flow_destroy_sub(flow, error); ++ (void)hinic3_runlock_flush_all(); ++ ++ return ret; ++} ++ ++int hinic3_flow_agent_age_callback(uint64_t hw_ufid, const struct hinic3_dpif_flow_for_get *flow, ++ const struct hinic3_nlattr *args) ++{ ++ return 0; ++} ++ ++int hinic3_flow_flush_all(struct rte_flow_error *error) ++{ ++ int ret; ++ (void)hinic3_wlock_flush_all(); ++ ret = hinic3_session_flush_all(HINIC3_EMC_VXLAN_SESSION | HINIC3_EMC_GRE_SESSION); ++ if (ret != 0) { ++ (void)hinic3_wunlock_flush_all(); ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_MIRROR_SESSION_FLUSH, 1); ++ return rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "Flow flush all: Session driver interface error."); ++ } ++ ret = hinic3_flush_rte_flow_mpool(); ++ if (ret != 0) { ++ (void)hinic3_wunlock_flush_all(); ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_EMC_MPOOL_FLUSH, 1); ++ return rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "Flow flush all: Dpak interface error."); ++ } ++ (void)hinic3_ufid_map_flush(); ++ ret = hinic3_flush_ufid_map_mpool(); ++ if (ret != 0) { ++ (void)hinic3_wunlock_flush_all(); ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_UFID_MAP_MPOOL_FLUSH, 1); ++ return rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "Flow flush all: Dpak interface error."); ++ } ++ ret = hinic3_flow_flush(); ++ if (ret != 0) { ++ (void)hinic3_wunlock_flush_all(); ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_EMC_HARD_FLOW_FLUSH, 1); ++ (void)rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "Flow flush all: Driver interface error."); ++ return ret; ++ } ++ ++ hinic3_reset_offload_flow_nums(); ++ (void)hinic3_wunlock_flush_all(); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.h +new file mode 100644 +index 0000000..96aff48 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_AGE_DELETE_FLOW_H ++#define HINIC3_AGE_DELETE_FLOW_H ++ ++#include "hinic3_age_delete_flow_public.h" ++ ++int hinic3_flow_emc_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error); ++int hinic3_flow_agent_age_callback(uint64_t hw_ufid, const struct hinic3_dpif_flow_for_get *flow, ++ const struct hinic3_nlattr *args); ++int hinic3_flow_flush_all(struct rte_flow_error *error); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +new file mode 100644 +index 0000000..48d89ea +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +@@ -0,0 +1,153 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "rte_log.h" ++#include "rte_ethdev.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_packet_key_public.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_drv.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_flow_dump_action.h" ++#include "hinic3_mpool_rte_flow.h" ++#include "hinic3_check_thread_health_state.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_iface_flow_api_record.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_agent_flow_cmd_dump.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_offload_flow.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_ovs_adapter.h" ++#include "hinic3_iface_flow.h" ++#endif ++ ++#define HINIC3_NO_FOUND_FLOW (-4) ++uint64_t g_get_related_ufid; ++ ++ ++struct hinic3_query_flow_buf { ++ uint8_t *put_key_buf; ++ uint8_t *actions_buf; ++ uint8_t *get_key_buf; ++}; ++ ++static void hinic3_init_dpif_flow(struct hinic3_dpif_flow *put_flow, struct hinic3_nlattr *hinic3_get_key, ++ struct hinic3_nlattr *hinic3_action) ++{ ++ put_flow->key = (struct hinic3_nlattr_obj *)hinic3_get_key->data; ++ put_flow->key_len = hinic3_get_key->used_len; ++ put_flow->actions = (struct hinic3_nlattr_obj *)hinic3_action->data; ++ put_flow->action_len = hinic3_action->used_len; ++} ++ ++static int hinic3_init_query_mem(struct hinic3_query_flow_buf *buf) ++{ ++ buf->put_key_buf = (uint8_t *)hinic3_calloc(1, HINIC3_MSG_MAX_BUF, HINIC3_FLOWS); ++ if (buf->put_key_buf == NULL) { ++ return -ENOMEM; ++ } ++ ++ buf->actions_buf = (uint8_t *)hinic3_calloc(1, HINIC3_MSG_MAX_BUF, HINIC3_FLOWS); ++ if (buf->actions_buf == NULL) { ++ hinic3_free(buf->put_key_buf); ++ return -ENOMEM; ++ } ++ ++ buf->get_key_buf = (uint8_t *)hinic3_calloc(1, HINIC3_MSG_MAX_BUF, HINIC3_FLOWS); ++ if (buf->get_key_buf == NULL) { ++ hinic3_free(buf->put_key_buf); ++ hinic3_free(buf->actions_buf); ++ return -ENOMEM; ++ } ++ return 0; ++} ++ ++static void hinic3_free_query_mem(struct hinic3_query_flow_buf *buf) ++{ ++ if (buf->put_key_buf != NULL) { ++ hinic3_free(buf->put_key_buf); ++ buf->put_key_buf = NULL; ++ } ++ ++ if (buf->actions_buf != NULL) { ++ hinic3_free(buf->actions_buf); ++ buf->actions_buf = NULL; ++ } ++ ++ if (buf->get_key_buf != NULL) { ++ hinic3_free(buf->get_key_buf); ++ buf->get_key_buf = NULL; ++ } ++} ++ ++static void hinic3_flow_ouput(struct hinic3_dpif_flow *flow, struct ds *ds) ++{ ++ struct hinic3_dpif_flow_for_get get_flow = {0}; ++ ++ get_flow.key = flow->key; ++ get_flow.key_len = flow->key_len; ++ get_flow.action_len = flow->action_len; ++ get_flow.actions = flow->actions; ++ memcpy(&get_flow.mask, &flow->mask, sizeof(struct hinic3_nlattr_obj)); ++ get_flow.mask_len = flow->mask_len; ++ get_flow.mask_present = flow->mask_present; ++ get_flow.ol_ufid = flow->hw_ufid; ++ get_flow.related_hw_ufid = g_get_related_ufid; ++ get_flow.stats = flow->stats; ++ ++ hinic3_agent_dump_hinic3_flow_init(); ++ hinic3_agent_flow_format_output(&get_flow, ds); ++} ++ ++int hinic3_flow_query_ufid(const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, uint64_t *ufid, ++ struct hinic3_conntrack_full_key *full_key, struct ds *ds) ++{ ++ int ret; ++ uint8_t has_vxlan_item; ++ struct hinic3_nlattr hinic3_put_key; ++ struct hinic3_nlattr hinic3_get_key; ++ struct hinic3_nlattr hinic3_action; ++ struct hinic3_dpif_flow put_flow = { 0 }; ++ struct hinic3_query_flow_buf buf; ++ ++ ret = hinic3_init_query_mem(&buf); ++ if (ret != 0) { ++ return -ENOMEM; ++ } ++ ++ full_key->key.meta.key_len = sizeof(struct hinic3_conntrack_full_key) - sizeof(struct hinic3_conntrack_key); ++ hinic3_nlattr_init(&hinic3_put_key, buf.put_key_buf, HINIC3_MSG_MAX_BUF); ++ hinic3_nlattr_init(&hinic3_action, buf.actions_buf, HINIC3_MSG_MAX_BUF); ++ hinic3_nlattr_init(&hinic3_get_key, buf.get_key_buf, HINIC3_MSG_MAX_BUF); ++ ++ hinic3_init_dpif_flow(&put_flow, &hinic3_get_key, &hinic3_action); ++ ret = hinic3_offload_parse_key(pattern, full_key, &has_vxlan_item); ++ if (ret != 0) { ++ goto err; ++ } ++ hinic3_offload_flow_construct_key(&full_key->key, &hinic3_put_key); ++ ret = hinic3_flow_mgmt_get_by_key(hinic3_put_key.data, hinic3_put_key.used_len, &put_flow, g_get_related_ufid); ++ if (ret == 0) { ++ *ufid = put_flow.hw_ufid; ++ if (ds != NULL) { ++ hinic3_flow_ouput(&put_flow, ds); ++ } ++ ++ hinic3_free_query_mem(&buf); ++ return 0; ++ } ++ ++ if (ret == HINIC3_NO_FOUND_FLOW) { ++ hinic3_free_query_mem(&buf); ++ return -EPERM; ++ } ++err: ++ hinic3_free_query_mem(&buf); ++ return -EPERM; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c +new file mode 100644 +index 0000000..4cd75d0 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c +@@ -0,0 +1,338 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++ ++#include "hinic3_mutex.h" ++#include ++#include "hinic3_eth_packets.h" ++#include "hinic3_flow_dump_public.h" ++#include "hinic3_flow_dump_item.h" ++#include "hinic3_flow_dump_action.h" ++#include "hinic3_flow_emc_dump.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_packets_types.h" ++#include "hinic3_message.h" ++#include "hinic3_types.h" ++#include "hinic3_init.h" ++#include "hinic3_log.h" ++#include "hinic3_timeval.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_nlattr.h" ++#include "hinic3_util.h" ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_iface_flow_api_record.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ds.h" ++#include "hinic3_flow_dump.h" ++ ++#define HINIC3_FLOW_DUMP_THREAD_NUM 10 ++#define HINIC3_DUMP_CONTEXT_EMPTY 1 ++#define HINIC3_FLOW_TYPE_SHIFT 30 ++#define HINIC3_ONCE_FLOW_DUMP_MAX_NUM 10000 // 6M ++ ++static struct hinic3_flow_dump_context g_hinic3_dump_contexts[HINIC3_FLOW_DUMP_THREAD_NUM]; ++static struct hinic3_mutex g_dump_contexts_lock; ++ ++void hinic3_dump_flow_init(void) ++{ ++ hinic3_emc_flow_dump_init(); ++ hinic3_pthread_mutex_init(&g_dump_contexts_lock); ++} ++ ++static int hinic3_dump_flow_start_by_hiovs(struct hinic3_flow_dump_context *context, uint32_t type, ++ struct rte_flow_error *error) ++{ ++ int ret = 0; ++ dump_start start = hinic3_get_dump_start(type); ++ if (start == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 dump start: unsupported flow type %u", type); ++ return -1; ++ } ++ ++ ret = start(context, error); ++ if (ret != HIOVS_OK && ret != HIOVS_EEMPTY) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump: hiovs flow error, error code is %d, flow type is %u", ret, type); ++ } ++ ++ return ret; ++} ++ ++static int hinic3_flow_dump_context_get(struct hinic3_flow_dump_context** context) ++{ ++ for (int i = 0; i < HINIC3_FLOW_DUMP_THREAD_NUM; ++i) { ++ if (g_hinic3_dump_contexts[i].dumping == HINIC3_FLOW_DUMPING_READY) { ++ *context = &(g_hinic3_dump_contexts[i]); ++ return 0; ++ } ++ } ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump: too much dump task, a maximum of three tasks are supported"); ++ return -1; ++} ++ ++static void hinic3_flow_cump_context_init(uint32_t type, struct hinic3_flow_dump_context *dump_context) ++{ ++ dump_context->dumping = HINIC3_FLOW_DUMPING; ++ dump_context->thread_id = pthread_self(); ++ dump_context->context_mem.start_timestamp = hinic3_time_msec(); ++ dump_context->type = type >> HINIC3_FLOW_TYPE_SHIFT; ++} ++ ++static int hinic3_accurate_flow_dump_start_sub(void **context, uint32_t type, struct rte_flow_error *error) ++{ ++ if (context == NULL || error == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump: context or error is null"); ++ return -EINVAL; ++ } ++ struct hinic3_flow_dump_context *dump_context = NULL; ++ error->message = NULL; ++ ++ hinic3_pthread_mutex_lock(&g_dump_contexts_lock); ++ int ret = hinic3_flow_dump_context_get(&dump_context); ++ if (ret != 0) { ++ hinic3_pthread_mutex_unlock(&g_dump_contexts_lock); ++ return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Dump context is busy"); ++ } ++ ret = hinic3_dump_flow_start_by_hiovs(dump_context, type >> HINIC3_FLOW_TYPE_SHIFT, error); ++ if (ret != 0) { ++ hinic3_pthread_mutex_unlock(&g_dump_contexts_lock); ++ (void)rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Hiovs dump start failed"); ++ return ret; ++ } ++ ++ (void)hinic3_flow_cump_context_init(type, dump_context); ++ *context = (void*)dump_context; ++ ++ hinic3_pthread_mutex_unlock(&g_dump_contexts_lock); ++ return 0; ++} ++ ++static struct hinic3_dump_flow_info* hinic3_dump_flow_infos_construct(uint32_t count) ++{ ++ struct hinic3_dump_flow_info* flows = hinic3_calloc(count, sizeof(struct hinic3_dump_flow_info), HINIC3_FLOWS); ++ if (flows == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump: malloc for dump memory failed"); ++ } ++ return flows; ++} ++ ++int hinic3_eth_flow_dump_start(void **context, uint32_t type, struct rte_flow_error *error) ++{ ++ int ret = 0; ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_RTE_FLOW_DUMP_START, ++ hinic3_accurate_flow_dump_start_sub(context, type, error)); ++ return ret; ++} ++ ++static void hinic3_free_dump_flow_info(struct hinic3_dump_flow_info* flow) ++{ ++ if (flow == NULL) { ++ return; ++ } ++ hinic3_free_one_flow_actions(flow->actions, HINIC3_FLOW_DUMP_MAX_ACTION); ++ hinic3_free_one_flow_items(flow->items, HINIC3_FLOW_DUMP_MAX_PATTERN); ++} ++ ++static void hinic3_free_dump_flow_info_arr(struct hinic3_dump_flow_info* flow, unsigned int flow_num) ++{ ++ for (unsigned int i = 0; i < flow_num; ++i) { ++ hinic3_free_dump_flow_info(&flow[i]); ++ } ++} ++ ++static void hinic3_dump_flow_mem_destruct(struct hinic3_dump_flow_mem *dump_flow_mem) ++{ ++ if (dump_flow_mem == NULL) { ++ return; ++ } ++ ++ hinic3_free_dump_flow_info_arr(dump_flow_mem->flows, dump_flow_mem->max_flow_num); ++ hinic3_free(dump_flow_mem->flows); ++ dump_flow_mem->flows = NULL; ++ ++ dump_flow_mem->cur_flow_num = 0; ++ dump_flow_mem->max_flow_num = 0; ++} ++ ++static void hinic3_dump_next_output(const struct hinic3_dump_flow_mem* context_mem, uint32_t dumped_count, ++ struct rte_flow_item **pattern[], struct rte_flow_action **actions[]) ++{ ++ for (uint32_t i = 0; i < dumped_count; ++i) { ++ struct hinic3_dump_flow_info* flow = &context_mem->flows[i]; ++ pattern[i] = (struct rte_flow_item**)(flow->items); ++ actions[i] = (struct rte_flow_action**)(flow->actions); ++ } ++ ++ return; ++} ++ ++int hinic3_dump_context_input_check(const struct hinic3_flow_dump_context* context, ++ enum hinic3_dump_context_status type) ++{ ++ if (context->thread_id != pthread_self()) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_INPUT_CHECK_PTHREAD, 1); ++ return -1; ++ } ++ ++ if (context->dumping != type) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_INPUT_CHECK_TYPE, 1); ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_accurate_flow_dump_next_sub(void *context, uint32_t count, uint32_t *dumped_count, ++ struct rte_flow_item **pattern[], struct rte_flow_action **actions[], struct rte_flow_error *error) ++{ ++ if (context == NULL || dumped_count == NULL || error == NULL || pattern == NULL || actions == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_dump_next input NULL pointer"); ++ return -EINVAL; ++ } ++ if (count > HINIC3_ONCE_FLOW_DUMP_MAX_NUM || count == 0) { ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "count cannot exceed 10000 or equal to 0"); ++ } ++ ++ struct hinic3_flow_dump_context *dump_context = (struct hinic3_flow_dump_context *)context; ++ ++ dump_next dump_func = NULL; ++ dump_func = hinic3_get_dump_next(dump_context->type); ++ if (dump_func == NULL) { ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_STATE, NULL, "dump next input unsupported type"); ++ } ++ ++ int ret = hinic3_dump_context_input_check(dump_context, HINIC3_FLOW_DUMPING); ++ if (ret != 0) { ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_STATE, NULL, NULL); ++ } ++ ++ if (dump_context->type != HINIC3_FLOW_TYPE_ACL) { ++ if (dump_context->hiovs_state == NULL) { ++ *dumped_count = 0; ++ return 0; ++ } ++ } ++ ++ struct hinic3_dump_flow_info *flows = hinic3_dump_flow_infos_construct(count); ++ if (flows == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DUMP_NEXT_MEM, 1); ++ return rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM, ++ NULL, "malloc for dump flow failed"); ++ } ++ ++ if (dump_context->context_mem.flows != NULL) { ++ hinic3_free_dump_flow_info_arr(dump_context->context_mem.flows, dump_context->context_mem.max_flow_num); ++ dump_context->context_mem.cur_flow_num = 0; ++ hinic3_free(dump_context->context_mem.flows); ++ } ++ ++ dump_context->context_mem.flows = flows; ++ dump_context->context_mem.max_flow_num = count; ++ ++ ret = dump_func(dump_context, count, error); ++ if (ret != HIOVS_OK && ret != HIOVS_EEMPTY) { ++ return ret; ++ } ++ ++ *dumped_count = dump_context->context_mem.cur_flow_num; ++ hinic3_dump_next_output(&dump_context->context_mem, count, pattern, actions); ++ ++ return ret; ++} ++ ++int hinic3_eth_flow_dump_next(void *context, uint32_t count, uint32_t *dumped_count, ++ struct rte_flow_item **pattern[], struct rte_flow_action **actions[], struct rte_flow_error *error) ++{ ++ int ret = 0; ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_RTE_FLOW_DUMP_NEXT, ++ hinic3_accurate_flow_dump_next_sub(context, count, dumped_count, pattern, actions, error)); ++ return ret; ++} ++ ++static void hinic3_flow_dump_context_reset(struct hinic3_flow_dump_context *context) ++{ ++ if (context == NULL) { ++ return; ++ } ++ ++ hinic3_dump_flow_mem_destruct(&context->context_mem); ++ context->dumping = HINIC3_FLOW_DUMPING_READY; ++ return; ++} ++ ++int hinic3_accurate_flow_dump_done_sub(void *context, struct rte_flow_error *error) ++{ ++ if (context == NULL || error == NULL) { ++ return -EINVAL; ++ } ++ ++ struct hinic3_flow_dump_context *dump_context = (struct hinic3_flow_dump_context*)context; ++ int ret = hinic3_dump_context_input_check(dump_context, HINIC3_FLOW_DUMPING); ++ if (ret != 0) { ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "hinic3 flow dump: hinic3 dump done input error"); ++ } ++ ++ dump_done done_func = NULL; ++ done_func = hinic3_get_dump_done(dump_context->type); ++ if (done_func == NULL) { ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, ++ NULL, "hinic3 dump done input unsupported type"); ++ } ++ ++ ret = done_func(dump_context, error); ++ if (ret != HIOVS_OK) { ++ rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_STATE, NULL, ++ "flow dump : dump done failed"); ++ } else { ++ dump_context->hiovs_state = NULL; ++ } ++ ++ hinic3_flow_dump_context_reset(dump_context); ++ return ret; ++} ++ ++int hinic3_eth_flow_dump_done(void *context, struct rte_flow_error *error) ++{ ++ int ret = 0; ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_RTE_FLOW_DUMP_END, ++ hinic3_accurate_flow_dump_done_sub(context, error)); ++ return ret; ++} ++ ++void hinic3_dump_context(struct ds *ds) ++{ ++ if (ds == NULL) { ++ return; ++ } ++ ++ struct hinic3_flow_dump_context *context = g_hinic3_dump_contexts; ++ hinic3_pthread_mutex_lock(&g_dump_contexts_lock); ++ for (int i = 0; i < HINIC3_FLOW_DUMP_THREAD_NUM; i++, context++) { ++ if (i != 0) { ++ hinic3_ds_put_format(ds, "\n"); ++ } ++ enum hinic3_dump_context_status status = context->dumping; ++ hinic3_ds_put_format(ds, "%2s%-15s%d\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_DUMP_CONTEXT_INDEX_STRING, i); ++ if (status == HINIC3_FLOW_DUMPING_READY) { ++ hinic3_ds_put_format(ds, "%2s%-15s%s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_DUMP_CONTEXT_STATUS_STRING, HINIC3_UI_DUMP_CONTEXT_IDLE_STRING); ++ continue; ++ } ++ long long int start_timestamp = context->context_mem.start_timestamp; ++ char start_time_buf[HINIC3_MS_STR_SIZE] = {'\0'}; ++ time_msec_to_str(start_timestamp, start_time_buf, HINIC3_MS_STR_SIZE); ++ hinic3_ds_put_format(ds, "%2s%-15s%s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_DUMP_CONTEXT_STATUS_STRING, HINIC3_UI_DUMP_CONTEXT_DUMPING_STRING); ++ hinic3_ds_put_format(ds, "%2s%-15s%llu\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_DUMP_CONTEXT_THREAD_ID_STRING, context->thread_id); ++ hinic3_ds_put_format(ds, "%2s%-15s%u\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_DUMP_CONTEXT_COUNT_STRING, context->context_mem.cur_flow_num); ++ hinic3_ds_put_format(ds, "%2s%-15s%s\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_DUMP_CONTEXT_START_TIME_STRING, start_time_buf); ++ hinic3_ds_put_format(ds, "%2s%-15s%lld ms\n", HINIC3_UI_INDENT_SPACE, ++ HINIC3_UI_DUMP_CONTEXT_RUNNING_TIME_STRING, hinic3_time_msec() - start_timestamp); ++ } ++ hinic3_pthread_mutex_unlock(&g_dump_contexts_lock); ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.h +new file mode 100644 +index 0000000..f0d003b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_DUMP_H ++#define HINIC3_FLOW_DUMP_H ++#include "rte_flow.h" ++#include "hinic3_util.h" ++#include "hinic3_ds.h" ++#include "hinic3_packet_key_public.h" ++ ++void hinic3_dump_flow_init(void); ++int hinic3_eth_flow_dump_start(void **context, uint32_t type, struct rte_flow_error *error); ++int hinic3_eth_flow_dump_next(void *context, uint32_t count, uint32_t *dumped_count, struct rte_flow_item **pattern[], ++ struct rte_flow_action **actions[], struct rte_flow_error *error); ++int hinic3_eth_flow_dump_done(void *context, struct rte_flow_error *error); ++void hinic3_dump_context(struct ds *ds); ++int hinic3_flow_query_ufid(const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, uint64_t *ufid, ++ struct hinic3_conntrack_full_key *full_key, struct ds *ds); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c +new file mode 100644 +index 0000000..87c9a70 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c +@@ -0,0 +1,549 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. ++ * Description:rte flow format to string ++ * Create: 2023-10-07 ++ */ ++#include "hinic3_flow_format.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_log.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_vxlan.h" ++#include "hinic3_eth_packets.h" ++#include "hinic3_ds.h" ++#include "hinic3_packets.h" ++ ++enum hinic3_key_type { ++ HINIC3_ITEM_SPEC, ++ HINIC3_ITEM_MASK, ++ HINIC3_ITEM_LAST ++}; ++ ++typedef int (*hinic3_flow_item_format_callback)(const struct rte_flow_item *, enum hinic3_key_type, struct ds *); ++typedef int (*hinic3_flow_action_format_callback)(const struct rte_flow_action *, struct ds *); ++ ++struct hinic3_item_format_info { ++ enum rte_flow_item_type type; ++ hinic3_flow_item_format_callback call_back; ++}; ++ ++struct hinic3_action_format_info { ++ enum rte_flow_action_type type; ++ hinic3_flow_action_format_callback call_back; ++}; ++ ++static int hinic3_process_eth(const struct rte_flow_item *item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_eth *eth = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (eth == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_eth: Invalid eth item ptr"); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%s(" HINIC3_MAC_FMT "),", HINIC3_UI_KEY_SRC_MAC_STR, HINIC3_OUTPUT_MAC(eth->src.addr_bytes)); ++ hinic3_ds_put_format(ds, "%s(" HINIC3_MAC_FMT "),", HINIC3_UI_KEY_DST_MAC_STR, HINIC3_OUTPUT_MAC(eth->dst.addr_bytes)); ++ hinic3_ds_put_format(ds, "%s(%#hx),", HINIC3_UI_ETH_TYPE_STR, ntohs(eth->type)); ++ return 0; ++} ++ ++static int hinic3_process_vlan(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_vlan *vlan = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (vlan == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_vlan: Invalid vlan item ptr"); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%s(%#hx),", HINIC3_UI_KEY_INNER_VLAN_STR, ntohs(vlan->inner_type)); ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_KEY_VID_STR, ntohs(vlan->tci)); ++ return 0; ++} ++ ++static int hinic3_process_ipv4(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_ipv4 *ipv4 = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (ipv4 == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_ipv4: Invalid ipv4 item ptr"); ++ return -1; ++ } ++ ++ char *src_str = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_SRC_OUT_IP_STR; ++ char *dst_str = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ? HINIC3_UI_KEY_DST_IP_STR : HINIC3_UI_KEY_DST_OUT_IP_STR; ++ ++ hinic3_ds_put_format(ds, "%s(" IP_FMT "),", src_str, IP_ARGS(ipv4->hdr.src_addr)); ++ hinic3_ds_put_format(ds, "%s(" IP_FMT "),", dst_str, IP_ARGS(ipv4->hdr.dst_addr)); ++ ++ if (item->type == RTE_FLOW_ITEM_TYPE_IPV4) { ++ hinic3_ds_put_format(ds, "%s(%hhu),", HINIC3_UI_TOS_STR, ipv4->hdr.type_of_service); ++ hinic3_ds_put_format(ds, "%s(%hhu),", HINIC3_UI_KEY_NW_PROTO_STR, ipv4->hdr.next_proto_id); ++ } ++ return 0; ++} ++ ++static int hinic3_process_ipv6(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_ipv6 *ipv6 = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (ipv6 == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_ipv6: Invalid ipv6 item ptr"); ++ return -1; ++ } ++ char *src_str = item->type == RTE_FLOW_ITEM_TYPE_IPV6 ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_SRC_OUT_IP_STR; ++ char *dst_str = item->type == RTE_FLOW_ITEM_TYPE_IPV6 ? HINIC3_UI_KEY_DST_IP_STR : HINIC3_UI_KEY_DST_OUT_IP_STR; ++ ++ hinic3_ds_put_format(ds, "%s(", src_str); ++ hinic3_ipv6_format_addr((struct in6_addr*)ipv6->hdr.src_addr, ds); ++ hinic3_ds_put_format(ds, "),"); ++ ++ hinic3_ds_put_format(ds, "%s(", dst_str); ++ hinic3_ipv6_format_addr((struct in6_addr*)ipv6->hdr.dst_addr, ds); ++ hinic3_ds_put_format(ds, "),"); ++ ++ if (item->type == RTE_FLOW_ITEM_TYPE_IPV6) { ++ hinic3_ds_put_format(ds, "%s(%u),", HINIC3_UI_VTC_STR, ntohl(ipv6->hdr.vtc_flow)); ++ hinic3_ds_put_format(ds, "%s(%hhu),", HINIC3_UI_KEY_NW_PROTO_STR, ipv6->hdr.proto); ++ } ++ return 0; ++} ++ ++static int hinic3_process_tcp(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_tcp *tcp = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (tcp == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_tcp: Invalid tcp item ptr"); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_KEY_SRC_PORT_STR, ntohs(tcp->hdr.src_port)); ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_KEY_DST_PORT_STR, ntohs(tcp->hdr.dst_port)); ++ return 0; ++} ++ ++static int hinic3_process_udp(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_udp *udp = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (udp == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_udp: Invalid udp item ptr"); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_KEY_SRC_PORT_STR, ntohs(udp->hdr.src_port)); ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_KEY_DST_PORT_STR, ntohs(udp->hdr.dst_port)); ++ return 0; ++} ++ ++static int hinic3_process_sctp(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_sctp *sctp = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (sctp == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_sctp: Invalid sctp item ptr"); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_KEY_SRC_PORT_STR, ntohs(sctp->hdr.src_port)); ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_KEY_DST_PORT_STR, ntohs(sctp->hdr.dst_port)); ++ return 0; ++} ++ ++static int hinic3_process_icmp(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_icmp *icmp = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (icmp == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_icmp: Invalid icmp item ptr"); ++ return -1; ++ } ++ ++ char *icmp_type_str = item->type == RTE_FLOW_ITEM_TYPE_ICMP ? HINIC3_UI_KEY_ICMP_TYPE_STR : ++ HINIC3_UI_KEY_ICMP6_TYPE_STR; ++ char *icmp_code_str = item->type == RTE_FLOW_ITEM_TYPE_ICMP ? HINIC3_UI_KEY_ICMP_CODE_STR : ++ HINIC3_UI_KEY_ICMP6_CODE_STR; ++ ++ hinic3_ds_put_format(ds, "%s(%hhu),", icmp_type_str, icmp->hdr.icmp_type); ++ hinic3_ds_put_format(ds, "%s(%hhu),", icmp_code_str, icmp->hdr.icmp_code); ++ return 0; ++} ++ ++static int hinic3_process_arp(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_arp_eth_ipv4 *arp = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (arp == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_icmp: Invalid arp item ptr"); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%s(%hu),", HINIC3_UI_ARP_OP_STR, ntohs(arp->op)); ++ return 0; ++} ++ ++static int hinic3_process_tag_item(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_tag *tag = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (tag == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_tag_item: Invalid tag item ptr"); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%s(%u),", HINIC3_UI_TAG_DATA_STR, tag->data); ++ hinic3_ds_put_format(ds, "%s(%hhu),", HINIC3_UI_TAG_INDEX_STR, tag->index); ++ return 0; ++} ++ ++static int hinic3_process_vxlan(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_vxlan *vxlan = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ uint32_t vni; ++ uint32_t rsvd; ++ if (vxlan == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_vxlan: Invalid tag item ptr"); ++ return -1; ++ } ++ ++ vni = hinic3_get_hiovs_vni(vxlan->vni); ++ rsvd = hinic3_get_hiovs_vni(vxlan->rsvd0); ++ hinic3_ds_put_format(ds, "vni(%u),rsvd(%#hhx),", ntohl(vni), ntohl(rsvd)); ++ return 0; ++} ++ ++static int hinic3_process_input_port(const struct rte_flow_item* item, enum hinic3_key_type type, struct ds *ds) ++{ ++ const struct rte_flow_item_port_id *port = type == HINIC3_ITEM_SPEC ? item->spec : item->mask; ++ if (port == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_input_port: Invalid port id ptr"); ++ return -1; ++ } ++ ++ hinic3_ds_put_format(ds, "%s(%u),", HINIC3_UI_KEY_VPORT_STR, port->id); ++ return 0; ++} ++ ++static struct hinic3_item_format_info item_callback_info[] = { ++ {RTE_FLOW_ITEM_TYPE_PORT_ID, hinic3_process_input_port}, ++ {RTE_FLOW_ITEM_TYPE_ETH, hinic3_process_eth}, ++ {RTE_FLOW_ITEM_TYPE_VLAN, hinic3_process_vlan}, ++ {RTE_FLOW_ITEM_TYPE_IPV4, hinic3_process_ipv4}, ++ {RTE_FLOW_ITEM_TYPE_IPV6, hinic3_process_ipv6}, ++ {RTE_FLOW_ITEM_TYPE_VXLAN, hinic3_process_vxlan}, ++ {RTE_FLOW_ITEM_TYPE_TCP, hinic3_process_tcp}, ++ {RTE_FLOW_ITEM_TYPE_UDP, hinic3_process_udp}, ++ {RTE_FLOW_ITEM_TYPE_SCTP, hinic3_process_sctp}, ++ {RTE_FLOW_ITEM_TYPE_TAG, hinic3_process_tag_item}, ++ {RTE_FLOW_ITEM_TYPE_ICMP, hinic3_process_icmp}, ++ {RTE_FLOW_ITEM_TYPE_ICMP6, hinic3_process_icmp}, ++ {RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4, hinic3_process_arp}, ++ {RTE_FLOW_ITEM_TYPE_END, NULL} ++}; ++ ++static int hinic3_process_count(const struct rte_flow_action* action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", HINIC3_UI_COUNT_ACTION); ++ return 0; ++} ++ ++static int hinic3_process_set_tag(const struct rte_flow_action* action, struct ds *ds) ++{ ++ const struct rte_flow_action_set_tag *tag = action->conf; ++ if (action->conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_set_tag: Invalid tag action ptr"); ++ return -1; ++ } ++ hinic3_ds_put_format(ds, "%s(%u),", HINIC3_UI_TAG_DATA_STR, tag->data); ++ hinic3_ds_put_format(ds, "%s(%hhu),", HINIC3_UI_TAG_INDEX_STR, tag->index); ++ return 0; ++} ++ ++static int hinic3_process_acl_remark(const struct rte_flow_action *action, struct ds *ds) ++{ ++ const struct rte_flow_action_modify_field *modify_field = action->conf; ++ if (modify_field == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_process_acl_remark: Invalid modify field ptr"); ++ return -1; ++ } ++ ++ uint8_t remark_value = modify_field->src.value[0]; ++ hinic3_ds_put_format(ds, "%s(%hhu),", HINIC3_UI_REMARK_ACTION, remark_value); ++ return 0; ++} ++ ++static int hinic3_process_acl_sample(const struct rte_flow_action *action, struct ds *ds) ++{ ++ if (action == NULL || action->conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 process acl sample is null."); ++ return -1; ++ } ++ ++ const struct rte_flow_action_sample *sample = action->conf; ++ const struct rte_flow_action *act = sample->actions; ++ if (act == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 process acl sample action is null."); ++ return -1; ++ } ++ ++ const struct rte_flow_action_port_id *output_port = (struct rte_flow_action_port_id *)act->conf; ++ if (output_port == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 process acl sample port id conf is null."); ++ return -1; ++ } ++ ++ uint32_t session_id = output_port->reserved; ++ ++ hinic3_ds_put_format(ds, "%s(%u),", HINIC3_UI_SESSION_ID, session_id); ++ return 0; ++} ++ ++static int hinic3_process_push_vlan(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "push_vlan"); ++ return 0; ++} ++ ++static int hinic3_process_pop_vlan(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "pop_vlan"); ++ return 0; ++} ++ ++static int hinic3_process_vxlan_encape(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "vxlan_encap"); ++ return 0; ++} ++ ++static int hinic3_process_vxlan_decape(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "vxlan_decap"); ++ return 0; ++} ++ ++static int hinic3_process_drop(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "drop"); ++ return 0; ++} ++ ++static int hinic3_process_port_id(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "port_id"); ++ return 0; ++} ++ ++static int hinic3_process_set_vid(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "set vid"); ++ return 0; ++} ++ ++static int hinic3_process_set_pcp(const struct rte_flow_action *action, struct ds *ds) ++{ ++ hinic3_ds_put_format(ds, "%s,", "set pcp"); ++ return 0; ++} ++ ++static struct hinic3_action_format_info action_callback_info[] = { ++ {RTE_FLOW_ACTION_TYPE_COUNT, hinic3_process_count}, ++ {RTE_FLOW_ACTION_TYPE_SET_TAG, hinic3_process_set_tag}, ++ {RTE_FLOW_ACTION_TYPE_MODIFY_FIELD, hinic3_process_acl_remark}, ++ {RTE_FLOW_ACTION_TYPE_SAMPLE, hinic3_process_acl_sample}, ++ {RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN, hinic3_process_push_vlan}, ++ {RTE_FLOW_ACTION_TYPE_OF_POP_VLAN, hinic3_process_pop_vlan}, ++ {RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID, hinic3_process_set_vid}, ++ {RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP, hinic3_process_set_pcp}, ++ {RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, hinic3_process_vxlan_encape}, ++ {RTE_FLOW_ACTION_TYPE_VXLAN_DECAP, hinic3_process_vxlan_decape}, ++ {RTE_FLOW_ACTION_TYPE_DROP, hinic3_process_drop}, ++ {RTE_FLOW_ACTION_TYPE_PORT_ID, hinic3_process_port_id}, ++ {RTE_FLOW_ACTION_TYPE_END, NULL} ++}; ++ ++static int hinic3_get_item_callback(enum rte_flow_item_type type, struct hinic3_item_format_info *item) ++{ ++ int i = 0; ++ while (item_callback_info[i].type != RTE_FLOW_ITEM_TYPE_END) { ++ if (item_callback_info[i].type == type) { ++ *item = item_callback_info[i]; ++ return 0; ++ } ++ ++i; ++ } ++ return -1; ++} ++ ++static int hinic3_get_action_callback(enum rte_flow_action_type type, struct hinic3_action_format_info *action) ++{ ++ int i = 0; ++ while (action_callback_info[i].type != RTE_FLOW_ACTION_TYPE_END) { ++ if (action_callback_info[i].type == type) { ++ *action = action_callback_info[i]; ++ return 0; ++ } ++ ++i; ++ } ++ return -1; ++} ++ ++static int hinic3_format_keys(const struct hinic3_flow *flow, enum hinic3_key_type type, struct ds *ds) ++{ ++ int ret; ++ struct rte_flow_item item; ++ struct hinic3_item_format_info item_info; ++ ++ if (type == HINIC3_ITEM_SPEC) { ++ hinic3_ds_put_format(ds, "%s", HINIC3_UI_FLOW_KEY_STRING); ++ } else if (type == HINIC3_ITEM_MASK) { ++ hinic3_ds_put_format(ds, "%s", HINIC3_UI_ITEM_MASK_STRING); ++ } ++ ++ for (int i = 0; i < HINIC3_FLOW_ITEMS_NUM && flow->items[i].type != RTE_FLOW_ITEM_TYPE_END; ++i) { ++ item = flow->items[i]; ++ ret = hinic3_get_item_callback(item.type, &item_info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "dump invalid rte_item_type, type code %d", item.type); ++ return -1; ++ } ++ ++ if (item_info.call_back != NULL) { ++ ret = item_info.call_back(&item, type, ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 format keys: format call back failed, item type code %d", item.type); ++ return -1; ++ } ++ } ++ } ++ hinic3_ds_put_format(ds, "%s ", HINIC3_UI_END); ++ return 0; ++} ++ ++static int hinic3_format_actions(const struct hinic3_flow *flow, struct ds *ds) ++{ ++ int ret; ++ struct rte_flow_action action; ++ struct hinic3_action_format_info action_info; ++ ++ hinic3_ds_put_format(ds, "%s", HINIC3_UI_FLOW_ACTION_STRING); ++ for (int i = 0; i < HINIC3_FLOW_ACTIONS_NUM && flow->actions[i].type != RTE_FLOW_ACTION_TYPE_END; ++i) { ++ action = flow->actions[i]; ++ ret = hinic3_get_action_callback(action.type, &action_info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "dump invalid rte_action_type, type code %d", action.type); ++ return -1; ++ } ++ ++ if (action_info.call_back != NULL) { ++ ret = action_info.call_back(&action, ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 format keys: format call back failed, action type code %d", action.type); ++ return -1; ++ } ++ } ++ } ++ hinic3_ds_put_format(ds, "%s ", HINIC3_UI_END); ++ return 0; ++} ++ ++int hinic3_format_flow(const struct hinic3_flow *flow, bool need_mask, struct ds *ds) ++{ ++ int ret; ++ ++ ret = hinic3_format_keys(flow, HINIC3_ITEM_SPEC, ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_format_one_flow, format item key failed"); ++ return -1; ++ } ++ ++ if (need_mask == true) { ++ ret = hinic3_format_keys(flow, HINIC3_ITEM_MASK, ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_format_one_flow, format item mask failed"); ++ return -1; ++ } ++ } ++ ++ ret = hinic3_format_actions(flow, ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_format_one_flow, format actions failed"); ++ return -1; ++ } ++ return 0; ++} ++ ++int hinic3_flow_construct_key(struct hinic3_flow *flow, enum rte_flow_item_type type, void *spec) ++{ ++ for (int i = 0; i < HINIC3_FLOW_ITEMS_NUM; ++i) { ++ if (flow->items[i].type != RTE_FLOW_ITEM_TYPE_END) { ++ continue; ++ } ++ flow->items[i].type = type; ++ flow->items[i].spec = spec; ++ flow->items[i].mask = NULL; ++ return 0; ++ } ++ return -1; ++} ++ ++int hinic3_rte_action_insert(struct rte_flow_action dst_actions[], int dst_size, ++ const struct rte_flow_action src_actions[], int src_size) ++{ ++ for (int j = 0; j < src_size && src_actions[j].type != RTE_FLOW_ACTION_TYPE_END; ++j) { ++ int location = -1; ++ for (int i = 0; i < dst_size - 1; ++i) { ++ if (dst_actions[i].type == RTE_FLOW_ACTION_TYPE_END) { ++ location = i; ++ break; ++ } ++ } ++ ++ if (location == -1) { ++ return -1; ++ } ++ ++ dst_actions[location].conf = src_actions[j].conf; ++ dst_actions[location].type = src_actions[j].type; ++ } ++ return 0; ++} ++ ++int hinic3_rte_item_insert(struct rte_flow_item dst_items[], int dst_size, ++ const struct rte_flow_item src_items[], int src_size) ++{ ++ int location = -1; ++ for (int j = 0; j < src_size && src_items[j].type != RTE_FLOW_ITEM_TYPE_END; ++j) { ++ for (int i = 0; i < dst_size - 1 ; ++i) { // array is end with RTE_FLOW_ITEM_TYPE_END ++ if (dst_items[i].type == RTE_FLOW_ITEM_TYPE_END) { ++ location = i; ++ break; ++ } ++ } ++ ++ if (location == -1) { ++ return -1; ++ } ++ ++ dst_items[location].last = src_items[j].last; ++ dst_items[location].mask = src_items[j].mask; ++ dst_items[location].spec = src_items[j].spec; ++ dst_items[location].type = src_items[j].type; ++ } ++ return 0; ++} ++ ++void hinic3_free_flow(struct hinic3_flow *flow) ++{ ++ for (int i = 0; i < HINIC3_FLOW_ITEMS_NUM; ++i) { ++ if (flow->items[i].type != RTE_FLOW_ITEM_TYPE_END) { ++ if (flow->items[i].spec != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void *, flow->items[i].spec)); ++ flow->items[i].spec = NULL; ++ } ++ if (flow->items[i].mask != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void *, flow->items[i].mask)); ++ flow->items[i].mask = NULL; ++ } ++ flow->items[i].type = RTE_FLOW_ITEM_TYPE_END; ++ } ++ } ++ ++ for (int i = 0; i < HINIC3_FLOW_ACTIONS_NUM; ++i) { ++ if (flow->actions[i].type == RTE_FLOW_ACTION_TYPE_CONNTRACK) { ++ if (flow->actions[i].conf != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void *, flow->actions[i].conf)); ++ flow->actions[i].conf = NULL; ++ } ++ flow->actions[i].type = RTE_FLOW_ACTION_TYPE_END; ++ } ++ } ++ return; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.h +new file mode 100644 +index 0000000..7da6752 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. ++ * Description: hinic3_flow结构体工具模块 ++ * Create: 2023-10-07 ++ */ ++#ifndef HINIC3_FLOW_FORMAT_H ++#define HINIC3_FLOW_FORMAT_H ++#include "hinic3_ds.h" ++#include "rte_flow.h" ++ ++#define HINIC3_FLOW_ITEMS_NUM 15 ++#define HINIC3_FLOW_ACTIONS_NUM 15 ++struct hinic3_flow { ++ struct rte_flow_item items[HINIC3_FLOW_ITEMS_NUM]; ++ struct rte_flow_action actions[HINIC3_FLOW_ACTIONS_NUM]; ++}; ++ ++int hinic3_format_flow(const struct hinic3_flow *flow, bool need_mask, struct ds *ds); ++ ++int hinic3_flow_construct_key(struct hinic3_flow *flow, enum rte_flow_item_type type, void *spec); ++int hinic3_rte_action_insert(struct rte_flow_action dst_actions[], int dst_size, ++ const struct rte_flow_action src_actions[], int src_size); ++int hinic3_rte_item_insert(struct rte_flow_item dst_items[], int dst_size, ++ const struct rte_flow_item src_items[], int src_size); ++void hinic3_free_flow(struct hinic3_flow *flow); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c +new file mode 100644 +index 0000000..65ebe6e +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c +@@ -0,0 +1,306 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_flow_mirror.h" ++#include "rte_flow.h" ++#include "hiovs_api.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_offload_action.h" ++ ++#define HINIC3_SESSION_CUTOFF_OFFSET 24 ++ ++static int hinic3_parse_mirror_IPv4_item(const struct rte_flow_item *item, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ const struct rte_flow_item_ipv4 *ip = (struct rte_flow_item_ipv4 *)item->spec; ++ if (ip == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV4_ITEM, 1); ++ return -1; ++ } ++ session_info->key.sip[0] = ip->hdr.src_addr; ++ session_info->key.dip[0] = ip->hdr.dst_addr; ++ session_info->key.proto = ip->hdr.next_proto_id; ++ session_info->ip_type_flag |= HINIC3_FLG_MIRROR_IPV4; ++ return 0; ++} ++ ++static int hinic3_parse_mirror_vlan_item(const struct rte_flow_item *item, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ const struct rte_flow_item_vlan *vlan = (struct rte_flow_item_vlan *)item->spec; ++ if (vlan == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_VLAN_ITEM, 1); ++ return -1; ++ } ++ session_info->key.tci = vlan->tci; ++ session_info->key.inner_type = vlan->inner_type; ++ session_info->ip_type_flag |= HINIC3_FLG_MIRROR_VLAN; ++ return 0; ++} ++ ++static int hinic3_parse_mirror_eth_item(const struct rte_flow_item *item, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ const struct rte_flow_item_eth *eth = (struct rte_flow_item_eth *)item->spec; ++ if (eth == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_ETH_ITEM, 1); ++ return -1; ++ } ++ memcpy(session_info->key.dmac, ð->dst, ETH_ALEN); ++ memcpy(session_info->key.smac, ð->src, ETH_ALEN); ++ session_info->key.type = eth->type; ++ session_info->ip_type_flag |= HINIC3_FLG_MIRROR_ETH; ++ return 0; ++} ++ ++static int hinic3_parse_mirror_IPv6_item(const struct rte_flow_item *item, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ const struct rte_flow_item_ipv6 *ip = (struct rte_flow_item_ipv6 *)item->spec; ++ if (ip == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV6_ITEM, 1); ++ return -1; ++ } ++ ++ for (int i = 0; i < HINIC3_IPV6_ADDR_UINT32_LEN; i++) { ++ session_info->key.sip[i] = hinic3_convert_u8_to_u32(&ip->hdr.src_addr[i * HINIC3_IPV6_ADDR_UINT32_LEN], ++ HINIC3_IPV6_ADDR_UINT32_LEN); ++ session_info->key.dip[i] = hinic3_convert_u8_to_u32(&ip->hdr.dst_addr[i * HINIC3_IPV6_ADDR_UINT32_LEN], ++ HINIC3_IPV6_ADDR_UINT32_LEN); ++ } ++ ++ session_info->key.proto = ip->hdr.proto; ++ session_info->ip_type_flag |= HINIC3_FLG_MIRROR_IPV6; ++ return 0; ++} ++ ++static int hinic3_parse_mirror_vxlan_item(const struct rte_flow_item *item, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ const struct rte_flow_item_vxlan *vxlan = (struct rte_flow_item_vxlan *)item->spec; ++ if (vxlan == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_VXLAN_ITEM, 1); ++ return -1; ++ } ++ session_info->key.tunnel.vxlan.flags = 0; ++ session_info->key.tunnel.vxlan.rsvd1 = 0; ++ memcpy(session_info->key.tunnel.vxlan.vxlan_rsvd0, vxlan->rsvd0, sizeof(vxlan->rsvd0)); ++ memcpy(session_info->key.tunnel.vxlan.vni, vxlan->vni, sizeof(vxlan->vni)); ++ session_info->ip_type_flag |= HINIC3_FLG_MIRROR_VXLAN; ++ ++ session_info->type = HINIC3_EMC_VXLAN_SESSION; ++ return 0; ++} ++ ++static int hinic3_parse_mirror_udp_item(const struct rte_flow_item *item, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ const struct rte_flow_item_udp *udp = (struct rte_flow_item_udp *)item->spec; ++ if (udp == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_UDP_ITEM, 1); ++ return -1; ++ } ++ ++ session_info->key.tunnel.vxlan.dst_port = udp->hdr.dst_port; ++ session_info->key.tunnel.vxlan.src_port = udp->hdr.src_port; ++ session_info->ip_type_flag |= HINIC3_FLG_MIRROR_UDP; ++ return 0; ++} ++ ++static int hinic3_parse_mirror_gre_item(const struct rte_flow_item *item, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ const struct rte_flow_item_gre *gre = (struct rte_flow_item_gre *)item->spec; ++ if (gre == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_NVGRE_ITEM, 1); ++ return -1; ++ } ++ ++ session_info->key.tunnel.gre.c_rsvd0_ver = gre->c_rsvd0_ver; ++ session_info->key.tunnel.gre.protocol = gre->protocol; ++ session_info->ip_type_flag |= HINIC3_FLG_MIRROR_GRE; ++ ++ if (flow_type == HINIC3_FLOW_EMC_MIRROR) { ++ session_info->type = HINIC3_EMC_GRE_SESSION; ++ } else if (flow_type == HINIC3_FLOW_ACL_MIRROR) { ++ session_info->type = HINIC3_ACL_GRE_SESSION; ++ } else { ++ session_info->type = HINIC3_MEGA_GRE_SESSION; ++ } ++ return 0; ++} ++ ++static struct hinic3_mirror_vxlan_item_func_map hinic3_mirror_vxlan_item_func_array[] = { ++ {RTE_FLOW_ITEM_TYPE_ETH, hinic3_parse_mirror_eth_item}, ++ {RTE_FLOW_ITEM_TYPE_VLAN, hinic3_parse_mirror_vlan_item}, ++ {RTE_FLOW_ITEM_TYPE_IPV4, hinic3_parse_mirror_IPv4_item}, ++ {RTE_FLOW_ITEM_TYPE_IPV6, hinic3_parse_mirror_IPv6_item}, ++ {RTE_FLOW_ITEM_TYPE_VXLAN, hinic3_parse_mirror_vxlan_item}, ++ {RTE_FLOW_ITEM_TYPE_UDP, hinic3_parse_mirror_udp_item}, ++ {RTE_FLOW_ITEM_TYPE_GRE, hinic3_parse_mirror_gre_item}, ++}; ++ ++bool hinic3_check_session_ip_type_flag(uint32_t ip_type_flag) ++{ ++ switch (ip_type_flag) { ++ case HINIC3_FLG_MIRROR_IPV4_VLAN: ++ case HINIC3_FLG_MIRROR_IPV6_VLAN: ++ case HINIC3_FLG_MIRROR_IPV4_VXLAN: ++ case HINIC3_FLG_MIRROR_IPV6_VXLAN: ++ case HINIC3_FLG_MIRROR_IPV4_GRE: ++ case HINIC3_FLG_MIRROR_IPV6_GRE: ++ case HINIC3_FLG_MIRROR_IPV4_VLAN_GRE: ++ case HINIC3_FLG_MIRROR_IPV6_VLAN_GRE: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static int hinic3_parse_mirror_vxlan_nvgre_act(const struct rte_flow_action *act, ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++{ ++ int ret = 0; ++ const struct rte_flow_action_vxlan_encap *encap_info = (struct rte_flow_action_vxlan_encap *)act->conf; ++ if (encap_info == NULL || encap_info->definition == NULL) { ++ return -1; ++ } ++ const struct rte_flow_item *item = NULL; ++ ++ item = next_no_end_pattern(encap_info->definition, NULL); ++ while (item) { ++ for (int i = 0; i < HINIC3_MIRROR_VXLAN_ITEM_LEN; i++) { ++ if (item->type == hinic3_mirror_vxlan_item_func_array[i].item) { ++ ret = hinic3_mirror_vxlan_item_func_array[i].func(item, session_info, flow_type); ++ break; ++ } ++ } ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_VXLAN_ENCAP, 1); ++ return -1; ++ } ++ item = next_no_end_pattern(encap_info->definition, item); ++ } ++ ++ if (hinic3_check_session_ip_type_flag(session_info->ip_type_flag)) { ++ return 0; ++ } ++ return -1; ++} ++ ++static int hinic3_parse_mirror_port_id_act(const struct rte_flow_action *act, ++ struct hinic3_mirror_session_info *session_info) ++{ ++ const struct rte_flow_action_port_id *output_port = (struct rte_flow_action_port_id *)act->conf; ++ if (output_port == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_PORT_ID, 1); ++ return -1; ++ } ++ uint32_t output_port_id; ++ output_port_id = hinic3_process_port_id(output_port->id); ++ session_info->key.outer_port_id = output_port_id; ++ return 0; ++} ++ ++static int hinic3_set_mirror_act(struct hinic3_nlattr *act_nla, const struct hinic3_mirror_session_info *session_info) ++{ ++ struct hiovs_mirror_info *hiovs_info = NULL; ++ ++ hiovs_info = hinic3_nlattr_put_unspec_uninit(act_nla, HINIC3_FLOW_ACT_MIRROR, ++ sizeof(struct hiovs_mirror_info)); ++ if (hiovs_info == NULL) { ++ return -1; ++ } ++ if (session_info->direction == HINIC3_SESSION_RX) { ++ hiovs_info->sessions[0] = session_info->session_id; ++ hiovs_info->ws.mirror_rx = 1; ++ hiovs_info->ws.mirror_tx = 0; ++ } else { ++ hiovs_info->sessions[1] = session_info->session_id; ++ hiovs_info->ws.mirror_rx = 0; ++ hiovs_info->ws.mirror_tx = 1; ++ } ++ hiovs_info->ws.rsvd = 0; ++ hiovs_info->ws.sport = 0; ++ hiovs_info->ws.sampling_interval = session_info->sampling_interval; ++ return 0; ++} ++ ++static int hinic3_set_acl_mirror_act(struct hinic3_nlattr *act_nla, uint8_t session_id, uint8_t dir_flag) ++{ ++ uint16_t set_session_id = (uint16_t)session_id; ++ if (dir_flag == HINIC3_SESSION_TX) { ++ return hinic3_nlattr_put_u16(act_nla, HINIC3_ACL_ACT_MIRROR_TX, set_session_id); ++ } else { ++ return hinic3_nlattr_put_u16(act_nla, HINIC3_ACL_ACT_MIRROR_RX, set_session_id); ++ } ++} ++ ++static int hinic3_set_mega_mirror_act(struct hinic3_nlattr *act_nla, uint8_t session_id) ++{ ++ uint16_t set_session_id = (uint16_t)session_id; ++ return hinic3_nlattr_put_u16(act_nla, HINIC3_FLOW_ACT_MIRROR, set_session_id); ++} ++ ++static void hinic3_init_session_info(struct hinic3_mirror_session_info *session_info, uint32_t ratio) ++{ ++ session_info->is_used = 1; ++ ++ session_info->sampling_interval = ratio; ++} ++ ++int hinic3_offload_parse_sample_act(const struct rte_flow_action *act, struct hinic3_nlattr *act_nla, ++ struct rte_flow *flow, uint8_t mirror_dir_flag) ++{ ++ int ret = 0; ++ struct rte_flow_action_sample *sample_info = (struct rte_flow_action_sample *)act->conf; ++ if (sample_info == NULL || sample_info->actions == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION, 1); ++ return -1; ++ } ++ struct hinic3_mirror_session_info session_info = {0}; ++ hinic3_init_session_info(&session_info, sample_info->ratio); ++ const struct rte_flow_action *action = next_no_void_action(sample_info->actions, NULL); ++ while (action && (action->type != RTE_FLOW_ACTION_TYPE_END)) { ++ ret = 0; ++ switch (action->type) { ++ case RTE_FLOW_ACTION_TYPE_PORT_ID: ++ ret = hinic3_parse_mirror_port_id_act(action, &session_info); ++ break; ++ case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: ++ case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: ++ ret = hinic3_parse_mirror_vxlan_nvgre_act(action, &session_info, flow->flags.is_sample); ++ break; ++ default: ++ break; ++ } ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION, 1); ++ return -1; ++ } ++ action = next_no_void_action(sample_info->actions, action); ++ } ++ ++ (void)ovs_mutex_lock_session(); ++ ret = hinic3_deal_with_session_info(&session_info, flow, mirror_dir_flag); ++ (void)ovs_mutex_unlock_session(); ++ if (ret != 0) { ++ return -1; ++ } ++ if (flow->flags.is_sample == HINIC3_FLOW_EMC_MIRROR) { ++ ret = hinic3_set_mirror_act(act_nla, &session_info); ++ } else if (flow->flags.is_sample == HINIC3_FLOW_ACL_MIRROR) { ++ ret = hinic3_set_acl_mirror_act(act_nla, session_info.session_id, mirror_dir_flag); ++ } else { ++ ret = hinic3_set_mega_mirror_act(act_nla, session_info.session_id); ++ } ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION_SET, 1); ++ return -1; ++ } ++ flow->session_id = session_info.session_id; ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.h +new file mode 100644 +index 0000000..39bc950 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.h +@@ -0,0 +1,72 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FLOW_MIRROR_H ++#define HINIC3_FLOW_MIRROR_H ++ ++#include "rte_flow.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_offload_flow_public.h" ++ ++#define HINIC3_MIRROR_VXLAN_ITEM_LEN sizeof(hinic3_mirror_vxlan_item_func_array) \ ++ / sizeof(struct hinic3_mirror_vxlan_item_func_map) ++ ++#define HINIC3_FLG_MIRROR_ETH (1LLU << 0) ++#define HINIC3_FLG_MIRROR_IPV4 (1LLU << 1) ++#define HINIC3_FLG_MIRROR_IPV6 (1LLU << 2) ++#define HINIC3_FLG_MIRROR_VLAN (1LLU << 3) ++#define HINIC3_FLG_MIRROR_VXLAN (1LLU << 4) ++#define HINIC3_FLG_MIRROR_UDP (1LLU << 5) ++#define HINIC3_FLG_MIRROR_GRE (1LLU << 6) ++ ++#define HINIC3_FLG_MIRROR_IPV4_VLAN (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV4 | \ ++ HINIC3_FLG_MIRROR_VLAN | \ ++ HINIC3_FLG_MIRROR_VXLAN | \ ++ HINIC3_FLG_MIRROR_UDP) ++ ++#define HINIC3_FLG_MIRROR_IPV6_VLAN (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV6 | \ ++ HINIC3_FLG_MIRROR_VLAN | \ ++ HINIC3_FLG_MIRROR_VXLAN | \ ++ HINIC3_FLG_MIRROR_UDP) ++ ++#define HINIC3_FLG_MIRROR_IPV4_VXLAN (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV4 | \ ++ HINIC3_FLG_MIRROR_VXLAN | \ ++ HINIC3_FLG_MIRROR_UDP) ++ ++#define HINIC3_FLG_MIRROR_IPV6_VXLAN (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV6 | \ ++ HINIC3_FLG_MIRROR_VXLAN | \ ++ HINIC3_FLG_MIRROR_UDP) ++ ++#define HINIC3_FLG_MIRROR_IPV4_GRE (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV4 | \ ++ HINIC3_FLG_MIRROR_GRE) ++ ++#define HINIC3_FLG_MIRROR_IPV6_GRE (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV6 | \ ++ HINIC3_FLG_MIRROR_GRE) ++ ++#define HINIC3_FLG_MIRROR_IPV4_VLAN_GRE (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV4 | \ ++ HINIC3_FLG_MIRROR_VLAN | \ ++ HINIC3_FLG_MIRROR_GRE) ++ ++#define HINIC3_FLG_MIRROR_IPV6_VLAN_GRE (HINIC3_FLG_MIRROR_ETH | \ ++ HINIC3_FLG_MIRROR_IPV6 | \ ++ HINIC3_FLG_MIRROR_VLAN | \ ++ HINIC3_FLG_MIRROR_GRE) ++ ++struct hinic3_mirror_vxlan_item_func_map { ++ enum rte_flow_item_type item; ++ int (*func)(const struct rte_flow_item *item, struct hinic3_mirror_session_info *session_info, ++ const uint8_t flow_tpye); ++}; ++ ++int hinic3_offload_parse_sample_act(const struct rte_flow_action *act, struct hinic3_nlattr *act_nla, ++ struct rte_flow *mega_flow, uint8_t mirror_dir_flag); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c +new file mode 100644 +index 0000000..73e3885 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c +@@ -0,0 +1,569 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_list.h" ++#include "hinic3_init.h" ++#include "hinic3_bond_controller.h" ++#include "hinic3_packet_key_public.h" ++#include "hinic3_flow_mirror.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ds.h" ++#include "hinic3_command.h" ++#include "hinic3_flow_session.h" ++ ++#define HINIC3_DUMP_NVGRE_MAX_ITEMS 5 ++#define HINIC3_SAMPLING_INTERVAL_MAX 1023 ++ ++static struct hinic3_mirror_session_info_list g_mirror_session_info; ++ ++static uint32_t hinic3_show_session_u8_to_u32(uint8_t *src_array, int length) ++{ ++ uint32_t target_value = 0; ++ ++ for (int i = 0; i < length; i++) { ++ target_value <<= HINIC3_UINT8_SHIFT; ++ target_value += src_array[i]; ++ } ++ return target_value; ++} ++ ++void ovs_mutex_unlock_session(void) ++{ ++ hinic3_spinlock_unlock(&g_mirror_session_info.mutex); ++} ++ ++void ovs_mutex_lock_session(void) ++{ ++ hinic3_spinlock_lock(&g_mirror_session_info.mutex); ++} ++ ++enum hinic3_session_tpye hinic3_get_session_type(uint8_t session_id) ++{ ++ return g_mirror_session_info.session_info[session_id].type; ++} ++ ++static int hinic3_dump_nvgre_vlan_item(struct rte_flow_item *item, uint8_t session_id) ++{ ++ struct hinic3_mirror_session_info session_info = g_mirror_session_info.session_info[session_id]; ++ struct rte_flow_item_vlan *vlan = hinic3_calloc(1, sizeof(struct rte_flow_item_vlan), HINIC3_FLOWS); ++ if (vlan == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, calloc vlan item fail."); ++ return -1; ++ } ++ vlan->tci = session_info.key.tci; ++ vlan->inner_type = session_info.key.inner_type; ++ ++ item->type = RTE_FLOW_ITEM_TYPE_VLAN; ++ item->spec = vlan; ++ item->last = NULL; ++ item->mask = NULL; ++ return 0; ++} ++ ++static int hinic3_dump_nvgre_ipv4_item(struct rte_flow_item *item, uint8_t session_id) ++{ ++ struct hinic3_mirror_session_info session_info = g_mirror_session_info.session_info[session_id]; ++ struct rte_flow_item_ipv4 *ipv4 = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv4), HINIC3_FLOWS); ++ if (ipv4 == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, calloc ipv4 item fail."); ++ return -1; ++ } ++ ipv4->hdr.dst_addr = session_info.key.dip[0]; ++ ipv4->hdr.src_addr = session_info.key.sip[0]; ++ ipv4->hdr.next_proto_id = session_info.key.proto; ++ ++ item->type = RTE_FLOW_ITEM_TYPE_IPV4; ++ item->spec = ipv4; ++ item->last = NULL; ++ item->mask = NULL; ++ return 0; ++} ++ ++static int hinic3_dump_nvgre_ipv6_item(struct rte_flow_item *item, uint8_t session_id) ++{ ++ struct hinic3_mirror_session_info session_info = g_mirror_session_info.session_info[session_id]; ++ struct rte_flow_item_ipv6 *ipv6 = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv6), HINIC3_FLOWS); ++ if (ipv6 == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, calloc ipv6 item fail."); ++ return -1; ++ } ++ ++ memcpy(ipv6->hdr.dst_addr, session_info.key.dip, HINIC3_IPV6_ADDR_UINT8_LEN); ++ memcpy(ipv6->hdr.src_addr, session_info.key.sip, HINIC3_IPV6_ADDR_UINT8_LEN); ++ ipv6->hdr.proto = session_info.key.proto; ++ ++ item->type = RTE_FLOW_ITEM_TYPE_IPV6; ++ item->spec = ipv6; ++ item->last = NULL; ++ item->mask = NULL; ++ ++ return 0; ++} ++ ++static int hinic3_dump_nvgre_eth_item(struct rte_flow_item *item, uint8_t session_id) ++{ ++ struct hinic3_mirror_session_info session_info = g_mirror_session_info.session_info[session_id]; ++ struct rte_flow_item_eth *eth = hinic3_calloc(1, sizeof(struct rte_flow_item_eth), HINIC3_FLOWS); ++ if (eth == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, calloc eth item fail."); ++ return -1; ++ } ++ ++ memcpy(ð->dst, session_info.key.dmac, ETH_ALEN); ++ memcpy(ð->src, session_info.key.smac, ETH_ALEN); ++ eth->type = session_info.key.type; ++ ++ item->type = RTE_FLOW_ITEM_TYPE_ETH; ++ item->spec = eth; ++ item->last = NULL; ++ item->mask = NULL; ++ ++ return 0; ++} ++ ++static int hinic3_dump_nvgre_gre_item(struct rte_flow_item *item, uint8_t session_id) ++{ ++ struct hinic3_mirror_session_info session_info = g_mirror_session_info.session_info[session_id]; ++ struct rte_flow_item_gre *gre = hinic3_calloc(1, sizeof(struct rte_flow_item_gre), HINIC3_FLOWS); ++ if (gre == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, calloc nvgre item fail."); ++ return -1; ++ } ++ ++ gre->c_rsvd0_ver = session_info.key.tunnel.gre.c_rsvd0_ver; ++ gre->protocol = session_info.key.tunnel.gre.protocol; ++ ++ item->type = RTE_FLOW_ITEM_TYPE_GRE; ++ item->spec = gre; ++ item->last = NULL; ++ item->mask = NULL; ++ ++ return 0; ++} ++ ++static int hinic3_flow_dump_construct_nvgre_item(struct rte_flow_item *items, uint8_t session_id) ++{ ++ int ret; ++ struct hinic3_mirror_session_info session_info = g_mirror_session_info.session_info[session_id]; ++ if (session_info.ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VLAN_GRE || ++ session_info.ip_type_flag == HINIC3_FLG_MIRROR_IPV6_VLAN_GRE) { ++ ret = hinic3_dump_nvgre_vlan_item(items, session_id); ++ if (ret != 0) { ++ return -1; ++ } ++ items++; ++ } ++ ++ if (session_info.ip_type_flag == HINIC3_FLG_MIRROR_IPV4_GRE || ++ session_info.ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VLAN_GRE) { ++ ret = hinic3_dump_nvgre_ipv4_item(items, session_id); ++ if (ret != 0) { ++ return -1; ++ } ++ items++; ++ } else { ++ ret = hinic3_dump_nvgre_ipv6_item(items, session_id); ++ if (ret != 0) { ++ return -1; ++ } ++ items++; ++ } ++ ++ ret = hinic3_dump_nvgre_eth_item(items, session_id); ++ if (ret != 0) { ++ return -1; ++ } ++ items++; ++ ++ ret = hinic3_dump_nvgre_gre_item(items, session_id); ++ if (ret != 0) { ++ return -1; ++ } ++ items++; ++ items->type = RTE_FLOW_ITEM_TYPE_END; ++ ++ return 0; ++} ++ ++struct rte_flow_action_vxlan_encap *hinic3_flow_dump_sample_nvgre_encap_conf(uint8_t session_id) ++{ ++ int ret; ++ struct rte_flow_action_vxlan_encap *nvgre_encap = hinic3_calloc(1, ++ sizeof(struct rte_flow_action_vxlan_encap), HINIC3_FLOWS); ++ if (nvgre_encap == NULL) { ++ HINIC3_LOG(ERR, FLOW, "FLOW DUMP: malloc for nvgre encap failed."); ++ return NULL; ++ } ++ ++ struct rte_flow_item *nvgre_items = ++ hinic3_calloc(HINIC3_DUMP_NVGRE_MAX_ITEMS, sizeof(struct rte_flow_item), HINIC3_FLOWS); ++ if (nvgre_items == NULL) { ++ hinic3_free(nvgre_encap); ++ HINIC3_LOG(ERR, FLOW, "FLOW DUMP: malloc for nvgre_items failed"); ++ return NULL; ++ } ++ ++ ret = hinic3_flow_dump_construct_nvgre_item(nvgre_items, session_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "FLOW DUMP: get nvgre encap failed"); ++ goto err; ++ } ++ ++ nvgre_encap->definition = nvgre_items; ++ return nvgre_encap; ++ ++err: ++ for (int i = 0; i < HINIC3_DUMP_NVGRE_MAX_ITEMS; i++) { ++ if (nvgre_items[i].spec != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void*, nvgre_items[i].spec)); ++ } ++ } ++ hinic3_free(nvgre_items); ++ hinic3_free(nvgre_encap); ++ return NULL; ++} ++ ++static void hinic3_show_session_key(struct ds *ds, struct session_key *key) ++{ ++ hinic3_ds_put_format(ds, "%2ssmac:(" HINIC3_MAC_FMT ")\n", HINIC3_UI_INDENT_SPACE, HINIC3_OUTPUT_MAC(&key->smac[0])); ++ hinic3_ds_put_format(ds, "%2sdmac:(" HINIC3_MAC_FMT ")\n", HINIC3_UI_INDENT_SPACE, HINIC3_OUTPUT_MAC(&key->dmac[0])); ++ hinic3_ds_put_format(ds, "%2souter_port_id:%u\n", HINIC3_UI_INDENT_SPACE, key->outer_port_id); ++ hinic3_ds_put_format(ds, "%2seth_type:%X\n", HINIC3_UI_INDENT_SPACE, htons(key->type)); ++ hinic3_ds_put_format(ds, "%2svlan_tci:%u\n", HINIC3_UI_INDENT_SPACE, htons(key->tci)); ++ hinic3_ds_put_format(ds, "%2svlan_type:%X\n", HINIC3_UI_INDENT_SPACE, htons(key->inner_type)); ++} ++ ++static void hinic3_show_session_ipv4(struct ds *ds, struct session_key *key) ++{ ++ hinic3_ds_put_format(ds, "%2ssip:(" IP_FMT ")\n", HINIC3_UI_INDENT_SPACE, IP_ARGS(key->sip[0])); ++ hinic3_ds_put_format(ds, "%2sdip:(" IP_FMT ")\n", HINIC3_UI_INDENT_SPACE, IP_ARGS(key->dip[0])); ++ hinic3_ds_put_format(ds, "%2snext_proto_id:%u\n", HINIC3_UI_INDENT_SPACE, key->proto); ++} ++ ++static void hinic3_show_session_ipv6(struct ds *ds, struct session_key *key) ++{ ++ hinic3_ds_put_format(ds, "%2ssip:(" IPV6_FMT ")\n", HINIC3_UI_INDENT_SPACE, IPV6_ARGS(key->sip)); ++ hinic3_ds_put_format(ds, "%2sdip:(" IPV6_FMT ")\n", HINIC3_UI_INDENT_SPACE, IPV6_ARGS(key->dip)); ++ hinic3_ds_put_format(ds, "%2sproto:%u\n", HINIC3_UI_INDENT_SPACE, key->proto); ++} ++ ++static void hinic3_show_session_vxlan(struct ds *ds, struct session_key *key) ++{ ++ uint32_t vni; ++ uint32_t vxlan_rsvd0; ++ vni = hinic3_show_session_u8_to_u32(key->tunnel.vxlan.vni, HINIC3_VNI_LEN); ++ vxlan_rsvd0 = hinic3_show_session_u8_to_u32(key->tunnel.vxlan.vxlan_rsvd0, HINIC3_RSVD0_LEN); ++ hinic3_ds_put_format(ds, "%2svxlan_vni:%u\n", HINIC3_UI_INDENT_SPACE, vni); ++ hinic3_ds_put_format(ds, "%2svxlan_rsvd0:%u\n", HINIC3_UI_INDENT_SPACE, vxlan_rsvd0); ++} ++ ++static void hinic3_show_session_gre(struct ds *ds, struct session_key *key) ++{ ++ hinic3_ds_put_format(ds, "%2sc_k_s_rsvd0_ver:%u\n", HINIC3_UI_INDENT_SPACE, key->tunnel.gre.c_rsvd0_ver); ++ hinic3_ds_put_format(ds, "%2sprotocol:%X\n", HINIC3_UI_INDENT_SPACE, htons(key->tunnel.gre.protocol)); ++} ++ ++static void hinic3_show_session_type(struct ds *ds, enum hinic3_session_tpye type) ++{ ++ switch (type) { ++ case HINIC3_EMC_VXLAN_SESSION : ++ hinic3_ds_put_format(ds, "%2ssession_type:HINIC3_EMC_VXLAN_SESSION\n", HINIC3_UI_INDENT_SPACE); ++ break; ++ case HINIC3_EMC_GRE_SESSION: ++ hinic3_ds_put_format(ds, "%2ssession_type:HINIC3_EMC_GRE_SESSION\n", HINIC3_UI_INDENT_SPACE); ++ break; ++ case HINIC3_ACL_GRE_SESSION: ++ hinic3_ds_put_format(ds, "%2ssession_type:HINIC3_ACL_GRE_SESSION\n", HINIC3_UI_INDENT_SPACE); ++ break; ++ case HINIC3_MEGA_GRE_SESSION: ++ hinic3_ds_put_format(ds, "%2ssession_type:HINIC3_MEGA_GRE_SESSION\n", HINIC3_UI_INDENT_SPACE); ++ break; ++ default: ++ break; ++ } ++} ++ ++void hinic3_show_sample_session(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct session_key *key = NULL; ++ ++ ovs_mutex_lock_session(); ++ for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ if (g_mirror_session_info.session_info[i].is_used == 0) { ++ continue; ++ } ++ key = &g_mirror_session_info.session_info[i].key; ++ hinic3_ds_put_format(&ds, "*************session_id:%u*************\n", ++ g_mirror_session_info.session_info[i].session_id); ++ hinic3_show_session_type(&ds, g_mirror_session_info.session_info[i].type); ++ hinic3_ds_put_format(&ds, "%2scutoff_len:%u\n", HINIC3_UI_INDENT_SPACE, ++ g_mirror_session_info.session_info[i].key.cutoff_len); ++ hinic3_ds_put_format(&ds, "%2sflow_list_len:%d\n", HINIC3_UI_INDENT_SPACE, ++ g_mirror_session_info.session_info[i].flow_list_len); ++ hinic3_ds_put_format(&ds, "%2sdirection:%u\n", HINIC3_UI_INDENT_SPACE, ++ g_mirror_session_info.session_info[i].direction); ++ hinic3_ds_put_format(&ds, "%2ssampling_interval:%u\n", HINIC3_UI_INDENT_SPACE, ++ g_mirror_session_info.session_info[i].sampling_interval); ++ if ((g_mirror_session_info.session_info[i].ip_type_flag & HINIC3_FLG_MIRROR_IPV4) == HINIC3_FLG_MIRROR_IPV4) { ++ hinic3_show_session_ipv4(&ds, key); ++ } else { ++ hinic3_show_session_ipv6(&ds, key); ++ } ++ if (g_mirror_session_info.session_info[i].type == HINIC3_EMC_VXLAN_SESSION) { ++ hinic3_show_session_vxlan(&ds, key); ++ } else { ++ hinic3_show_session_gre(&ds, key); ++ } ++ hinic3_show_session_key(&ds, key); ++ } ++ ovs_mutex_unlock_session(); ++ if (ds.length == 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_INFO HINIC3_UI_FLOW_DUMP_NO_SESSION_STRING); ++ } ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++} ++ ++int hinic3_flow_get_port_id_by_session(uint8_t session_id, uint16_t *port_id) ++{ ++ if (session_id >= HINIC3_MIRROR_MAX_SESSION || port_id == NULL) { ++ return -1; ++ } ++ *port_id = g_mirror_session_info.session_info[session_id].key.outer_port_id; ++ return 0; ++} ++ ++int hinic3_flow_dump_construct_vxlan_header(uint8_t session_id, struct hinic3_flow_act_vxlan_gpe_header *meta_header) ++{ ++ if (g_mirror_session_info.session_info[session_id].is_used == 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SESSION_UNUSED, 1); ++ return -1; ++ } ++ struct hinic3_mirror_session_info session_info = g_mirror_session_info.session_info[session_id]; ++ if (session_info.ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VLAN || ++ session_info.ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VXLAN) { ++ meta_header->ip_version = 0; ++ } else { ++ meta_header->ip_version = 1; ++ } ++ memcpy(meta_header->dmac, session_info.key.dmac, sizeof(session_info.key.dmac)); ++ memcpy(meta_header->smac, session_info.key.smac, sizeof(session_info.key.smac)); ++ memcpy(meta_header->dip, session_info.key.dip, sizeof(session_info.key.dip)); ++ memcpy(meta_header->sip, session_info.key.sip, sizeof(session_info.key.sip)); ++ ++ meta_header->vlan_id = session_info.key.tci; ++ meta_header->sport = session_info.key.tunnel.vxlan.src_port; ++ meta_header->dport = session_info.key.tunnel.vxlan.dst_port; ++ meta_header->vxlan.flag = session_info.key.tunnel.vxlan.flags; ++ ++ meta_header->vxlan.vni = hinic3_convert_u8_to_u32(session_info.key.tunnel.vxlan.vni, HINIC3_VNI_LEN); ++ meta_header->vxlan.rsvd1 = hinic3_convert_u8_to_u32(session_info.key.tunnel.vxlan.vxlan_rsvd0, HINIC3_RSVD0_LEN); ++ ++ return 0; ++} ++ ++static int hinic3_del_session(uint8_t session_id) ++{ ++ int ret; ++ if (session_id >= HINIC3_MIRROR_MAX_SESSION) { ++ return -1; ++ } ++ size_t size = sizeof(struct hinic3_mirror_session_info); ++ struct hiovs_mirror_session_info hiovs_session_info = {0}; ++ hiovs_session_info.session_id = session_id; ++ ret = hinic3_iface_global_cfg_set(&hiovs_session_info, HINIC3_GLOBAL_CFG_ARG_MIRROR_SESSION_DEL); ++ if (ret != 0) { ++ return -1; ++ } ++ memset(&g_mirror_session_info.session_info[session_id], 0, size); ++ g_mirror_session_info.used_session_len--; ++ return 0; ++} ++ ++/* 支持以组合的形式flush不同类型的镜像会话 */ ++int hinic3_session_flush_all(uint32_t type) ++{ ++ int ret; ++ ovs_mutex_lock_session(); ++ for (uint8_t i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ if (g_mirror_session_info.session_info[i].is_used == 0) { ++ continue; ++ } ++ if ((type & g_mirror_session_info.session_info[i].type) != 0) { ++ ret = hinic3_del_session(i); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow session delete failed."); ++ ovs_mutex_unlock_session(); ++ return -1; ++ } ++ g_mirror_session_info.session_info[i].flow_list_len = 0; ++ g_mirror_session_info.used_session_len--; ++ } ++ } ++ ovs_mutex_unlock_session(); ++ return 0; ++} ++ ++int hinic3_del_rte_flow_in_session(struct rte_flow *flow) ++{ ++ ovs_mutex_lock_session(); ++ int ret; ++ uint8_t session_id = flow->session_id; ++ if (g_mirror_session_info.session_info[session_id].flow_list_len > 0) { ++ g_mirror_session_info.session_info[session_id].flow_list_len--; ++ if (g_mirror_session_info.session_info[session_id].flow_list_len == 0) { ++ ret = hinic3_del_session(session_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow session delete failed."); ++ g_mirror_session_info.session_info[session_id].flow_list_len++; ++ ovs_mutex_unlock_session(); ++ return -1; ++ } ++ } ++ ovs_mutex_unlock_session(); ++ return 0; ++ } else { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow session flow list is error."); ++ ovs_mutex_unlock_session(); ++ return -1; ++ } ++} ++ ++static uint8_t hinic3_find_mirror_session(struct hinic3_mirror_session_info *session_info) ++{ ++ for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ struct hinic3_mirror_session_info *cur_session_info = &g_mirror_session_info.session_info[i]; ++ if (cur_session_info->is_used == 0) { ++ continue; ++ } ++ if (memcmp(&cur_session_info->key, &session_info->key, sizeof(struct session_key)) == 0 && ++ session_info->type == cur_session_info->type) { ++ return cur_session_info->session_id; ++ } ++ } ++ ++ return HINIC3_MIRROR_MAX_SESSION; ++} ++ ++static void hinic3_insert_session_in_list(struct hinic3_mirror_session_info *session_info, ++ struct rte_flow *flow) ++{ ++ memcpy(&g_mirror_session_info.session_info[session_info->session_id], session_info, sizeof(struct hinic3_mirror_session_info)); ++ g_mirror_session_info.session_info[session_info->session_id].flow_list_len = 1; ++ g_mirror_session_info.used_session_len++; ++} ++ ++static void hinic3_construct_hiovs_session_info(const struct hinic3_mirror_session_info *session_info, ++ struct hiovs_mirror_session_info *hiovs_session_info) ++{ ++ hiovs_session_info->cutoff_len = session_info->key.cutoff_len; ++ hiovs_session_info->session_id = session_info->session_id; ++ if (session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VLAN || ++ session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VXLAN || ++ session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV4_GRE || ++ session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VLAN_GRE) { ++ hiovs_session_info->is_ipv4 = 1; ++ } else { ++ hiovs_session_info->is_ipv4 = 0; ++ } ++ if (session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VLAN || ++ session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV6_VLAN || ++ session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV4_VLAN_GRE || ++ session_info->ip_type_flag == HINIC3_FLG_MIRROR_IPV6_VLAN_GRE) { ++ hiovs_session_info->is_vlan = 1; ++ } else { ++ hiovs_session_info->is_vlan = 0; ++ } ++ hiovs_session_info->dest_port = htons((uint16_t)session_info->key.outer_port_id); ++ hiovs_session_info->vlan_tag = session_info->key.tci; ++ memcpy(hiovs_session_info->smac, session_info->key.smac, ETH_ALEN); ++ memcpy(hiovs_session_info->dmac, session_info->key.dmac, ETH_ALEN); ++ memcpy(hiovs_session_info->sip, session_info->key.sip, HINIC3_MIRROR_IP_LEN); ++ memcpy(hiovs_session_info->dip, session_info->key.dip, HINIC3_MIRROR_IP_LEN); ++ ++ if (session_info->type == HINIC3_EMC_VXLAN_SESSION) { ++ hiovs_session_info->tunnel.vxlan.vxlan_rsvd0 = hinic3_convert_u8_to_u32( ++ session_info->key.tunnel.vxlan.vxlan_rsvd0, HINIC3_RSVD0_LEN); ++ hiovs_session_info->tunnel.vxlan.vni = hinic3_convert_u8_to_u32( ++ session_info->key.tunnel.vxlan.vni, HINIC3_VNI_LEN); ++ hiovs_session_info->type = 0; // 0:vxlan镜像 1:GRE镜像 ++ } else { ++ hiovs_session_info->tunnel.gre.c_rsvd0_ver = session_info->key.tunnel.gre.c_rsvd0_ver; ++ hiovs_session_info->tunnel.gre.protocol = session_info->key.tunnel.gre.protocol; ++ hiovs_session_info->type = 1; // 0:vxlan镜像 1:GRE镜像 ++ } ++ hiovs_session_info->enabled = 1; ++} ++ ++static int hinic3_mirror_set_session_to_hovs(struct hinic3_mirror_session_info *session_info) ++{ ++ if (session_info->sampling_interval > HINIC3_SAMPLING_INTERVAL_MAX) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SESSION_RATIO, 1); ++ return -1; ++ } ++ ++ int ret = 0; ++ struct hiovs_mirror_session_info hiovs_session_info = { 0 }; ++ ++ hinic3_construct_hiovs_session_info(session_info, &hiovs_session_info); ++ ++ ret = hinic3_iface_global_cfg_set(&hiovs_session_info, HINIC3_GLOBAL_CFG_ARG_MIRROR_SESSION_SET); ++ if (ret != 0) { ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_get_session_id(struct hinic3_mirror_session_info *session_info) ++{ ++ for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ if (g_mirror_session_info.session_info[i].is_used == 0) { ++ session_info->session_id = i; ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++int hinic3_deal_with_session_info(struct hinic3_mirror_session_info *session_info, ++ struct rte_flow *flow, uint8_t mirror_dir_flag) ++{ ++ int ret; ++ uint8_t session_id = hinic3_find_mirror_session(session_info); ++ ++ session_info->direction = mirror_dir_flag; ++ ++ if (session_id != HINIC3_MIRROR_MAX_SESSION) { ++ session_info->session_id = session_id; ++ g_mirror_session_info.session_info[session_id].flow_list_len++; ++ } else { ++ ret = hinic3_get_session_id(session_info); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SESSION_FULLED, 1); ++ return -1; ++ } ++ ret = hinic3_mirror_set_session_to_hovs(session_info); ++ if (ret != 0) { ++ return -1; ++ } ++ hinic3_insert_session_in_list(session_info, flow); ++ } ++ return 0; ++} ++ ++void hinic3_mirror_session_info_list_init(void) ++{ ++ g_mirror_session_info.used_session_len = 0; ++ hinic3_spinlock_init(&g_mirror_session_info.mutex, PTHREAD_PROCESS_PRIVATE); ++ for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ g_mirror_session_info.session_info[i].is_used = 0; ++ g_mirror_session_info.session_info[i].session_id = (uint8_t)i; ++ } ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.h +new file mode 100644 +index 0000000..dbcec92 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.h +@@ -0,0 +1,102 @@ ++ /* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FLOW_SESSION_H ++#define HINIC3_FLOW_SESSION_H ++ ++#include "rte_byteorder.h" ++#include "hinic3_message.h" ++#include "hinic3_command.h" ++#include "hinic3_mutex.h" ++#include "hinic3_mpool_rte_flow.h" ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_packet_key_public.h" ++#include "hinic3_packets_types.h" ++ ++#define HINIC3_MIRROR_MAX_SESSION 128u ++ ++enum hinic3_session_flow_type { ++ HINIC3_FLOW_NO_MIRROR, ++ HINIC3_FLOW_EMC_MIRROR, ++ HINIC3_FLOW_ACL_MIRROR, ++ HINIC3_FLOW_MEGA_MIRROR, ++}; ++ ++enum hinic3_session_direction { ++ HINIC3_SESSION_RX, ++ HINIC3_SESSION_TX, ++}; ++ ++enum hinic3_session_tpye { ++ HINIC3_EMC_VXLAN_SESSION = 1, ++ HINIC3_EMC_GRE_SESSION = 1 << 1, ++ HINIC3_ACL_GRE_SESSION = 1 << 2, ++ HINIC3_MEGA_GRE_SESSION = 1 << 3, ++}; ++ ++struct session_key { ++ uint8_t cutoff_len; // 镜像报文截断长度,0代表不截断 ++ ++ uint32_t outer_port_id; ++ ++ uint8_t smac[ETH_ALEN]; ++ uint8_t dmac[ETH_ALEN]; ++ rte_be16_t type; ++ ++ rte_be16_t tci; ++ rte_be16_t inner_type; ++ ++ uint32_t sip[4]; ++ uint32_t dip[4]; ++ uint8_t proto; ++ union { ++ struct { ++ uint8_t flags; ++ uint8_t rsvd1; ++ uint8_t vxlan_rsvd0[3]; ++ uint8_t vni[3]; ++ ++ rte_be16_t src_port; ++ rte_be16_t dst_port; ++ } vxlan; ++ struct { ++ rte_be16_t c_rsvd0_ver; ++ rte_be16_t protocol; ++ } gre; ++ } tunnel; ++}; ++ ++struct hinic3_mirror_session_info { ++ uint8_t is_used; ++ uint8_t session_id; ++ enum hinic3_session_direction direction; ++ uint32_t sampling_interval; ++ struct session_key key; ++ int flow_list_len; ++ ++ enum hinic3_session_tpye type; ++ uint32_t ip_type_flag; ++}; ++ ++struct hinic3_mirror_session_info_list { ++ struct hinic3_mirror_session_info session_info[HINIC3_MIRROR_MAX_SESSION]; ++ struct hinic3_spinlock mutex; ++ uint8_t used_session_len; ++}; ++ ++void ovs_mutex_lock_session(void); ++void ovs_mutex_unlock_session(void); ++int hinic3_session_flush_all(uint32_t type); ++void hinic3_mirror_session_info_list_init(void); ++int hinic3_del_rte_flow_in_session(struct rte_flow *flow); ++enum hinic3_session_tpye hinic3_get_session_type(uint8_t session_id); ++struct rte_flow_action_vxlan_encap *hinic3_flow_dump_sample_nvgre_encap_conf(uint8_t session_id); ++int hinic3_deal_with_session_info(struct hinic3_mirror_session_info *session_info, struct rte_flow *flow, ++ uint8_t mirror_dir_flag); ++int hinic3_flow_get_port_id_by_session(uint8_t session_id, uint16_t *port_id); ++int hinic3_flow_dump_construct_vxlan_header(uint8_t session_id, struct hinic3_flow_act_vxlan_gpe_header *meta_header); ++void hinic3_show_sample_session(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c +new file mode 100644 +index 0000000..f74e297 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c +@@ -0,0 +1,71 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "rte_log.h" ++#include "rte_ethdev.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_offload_action_public.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_dump_flow.h" ++ ++#define MAX_LEN 255 ++#define SUDO_PATH "/usr/bin/sudo" ++#define HINICADMIN_PATH "/usr/sbin/hinicadm3" ++ ++static int hinic3_info_need(char *buf, int buffer_size) ++{ ++ static char *infos[] = { ++ "Card information", ++ "card type", ++ "port num", ++ "port speed", ++ "pcie width", ++ "pf num", ++ "vf total num", ++ "hardware id" ++ }; ++ int flag = 0; ++ size_t size = sizeof(infos) / sizeof(infos[0]); ++ for (size_t i = 0; i < size; i++) { ++ if (strncmp(buf, infos[i], strlen(infos[i])) == 0) { ++ flag = 1; ++ break; ++ } ++ } ++ return flag; ++} ++ ++int hinic3_eth_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow, FILE *file, struct rte_flow_error *error) ++{ ++ if ((dev == NULL) || (file == NULL) || (error == NULL)) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DEV_DUMP_NULL, 1); ++ return -EINVAL; ++ } ++ ++ if (access(HINICADMIN_PATH, F_OK) != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_eth_flow_dev_dump: hinicadm3 not exist.\n"); ++ return -EINVAL; ++ } ++ ++ char cmd[MAX_LEN] = {0}; ++ if (sprintf(cmd, "%s %s info -i hinic0", SUDO_PATH, HINICADMIN_PATH) <= 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_eth_flow_dev_dump: sprintf error.\n"); ++ return -EINVAL; ++ } ++ ++ FILE *f = popen(cmd, "r"); ++ if (f == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_eth_flow_dev_dump: popen fail.\n"); ++ return -EINVAL; ++ } ++ char buff[MAX_LEN + 1] = {0}; ++ while (fgets(buff, MAX_LEN + 1, f) != NULL) { ++ if (hinic3_info_need(buff, MAX_LEN + 1)) { ++ fputs(buff, file); ++ } ++ } ++ pclose(f); ++ ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.h +new file mode 100644 +index 0000000..f5c1da6 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.h +@@ -0,0 +1,23 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_DUMP_FLOW_H ++#define HINIC3_DUMP_FLOW_H ++ ++#include ++#include ++#include "rte_log.h" ++#include "rte_ethdev.h" ++#include "rte_cycles.h" ++#include "hinic3_init.h" ++#include "hinic3_message.h" ++#include "hinic3_log.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_offload_action_public.h" ++#include "hinic3_iface_flow.h" ++ ++int hinic3_eth_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow, FILE *file, struct rte_flow_error *error); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c +new file mode 100644 +index 0000000..5d198b8 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c +@@ -0,0 +1,128 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#include "rte_log.h" ++#include "rte_ethdev.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_offload_action_public.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_flow_mirror.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_port_util.h" ++ ++#define HINIC3_RTE_VLAN_PCP_MASK 0xe0 ++#define VLAN_PCP_MOVE 8 ++#define HWOF_DEFALUT_DP_HASH_OUT_PORT 0X0080 ++ ++static inline void hinic3_offload_parse_vlan_act(struct hinic3_offload_action *offload_action, ++ const struct rte_flow_action_of_set_vlan_pcp *rte_vlan_pcp, ++ const struct rte_flow_action_of_set_vlan_vid *rte_vlan_vid) ++{ ++ uint16_t vlan_id = 0; ++ struct hinic3_nlattr *hinic3_actions = &offload_action->act_nla; ++ uint16_t vlan_tci = ntohs(rte_vlan_vid->vlan_vid); ++ ++ vlan_id = (rte_vlan_pcp->vlan_pcp & HINIC3_RTE_VLAN_PCP_MASK) << VLAN_PCP_MOVE; ++ vlan_id = (vlan_id | vlan_tci); ++ ++ offload_action->has_vlan_push = true; ++ offload_action->vlan_id = htons(vlan_id); ++ hinic3_nlattr_put_u16(hinic3_actions, HINIC3_FLOW_ACT_VLAN_PUSH, htons(vlan_id)); ++} ++ ++/* 此处取端口私有数据的首个uint16_t的数据作为端口的vport_id */ ++uint32_t hinic3_process_port_id(uint32_t port_id) ++{ ++ void *data = NULL; ++ data = hinic3_get_private_data(port_id); ++ if (data == NULL) { ++ return UINT32_MAX; ++ } ++ return *(uint16_t*)data; ++} ++ ++static void hinic3_add_simple_ct_action(struct hinic3_offload_action *offload_action, ++ struct hinic3_conntrack_full_key *key) ++{ ++ struct hinic3_ct_tcp_state ct_state = {0}; ++ ct_state.max_win = HINIC3_DEFAULT_WINDOW; ++ if (hinic3_status_packet_upcall_get() == DEFAULT_PUT) { ++ hinic3_nlattr_put_unspec(&offload_action->act_nla, HINIC3_FLOW_ACT_CT, &ct_state, sizeof(ct_state)); ++ } else if (hinic3_status_packet_upcall_get() == SELECT_PUT) { ++ if (key->key.meta.need_ct_action == 1) { ++ hinic3_nlattr_put_unspec(&offload_action->act_nla, HINIC3_FLOW_ACT_CT, &ct_state, sizeof(ct_state)); ++ } ++ } ++} ++ ++static int hinic3_add_port_id_action(const struct rte_flow_action *act, struct hinic3_offload_action *offload_action) ++{ ++ if (act->conf == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3load port id action is null."); ++ return -1; ++ } ++ ++ const struct rte_flow_action_port_id *output_port = NULL; ++ uint32_t output_port_id; ++ output_port = (struct rte_flow_action_port_id *)act->conf; ++ output_port_id = hinic3_process_port_id(output_port->id); ++ if (output_port_id > UINT16_MAX) { ++ HINIC3_LOG(ERR, FLOW, "port_id exceeds the maximum range of driver."); ++ return -1; ++ } ++ hinic3_nlattr_put_u16(&offload_action->act_nla, HINIC3_FLOW_ACT_OUTPUT, htons((uint16_t)output_port_id)); ++ offload_action->has_output = true; ++ return 0; ++} ++ ++int hinic3_offload_parse_action(const struct rte_flow_action actions[], struct rte_flow *mega_flow, ++ struct hinic3_flow_offload_param *param, uint8_t mirror_dir_flag) ++{ ++ int ret; ++ const struct rte_flow_action_of_set_vlan_pcp *rte_vlan_pcp = NULL; ++ const struct rte_flow_action *act = next_no_void_action(actions, NULL); ++ const struct rte_flow_action_of_set_vlan_vid *rte_vlan_vid = NULL; ++ bool has_set_vlan_pcp = false; ++ bool has_set_vlan_vid = false; ++ struct hinic3_offload_action *offload_action = ¶m->cur_actions; ++ ++ if (actions == NULL) { ++ return -1; ++ } ++ while (act && (act->type != RTE_FLOW_ACTION_TYPE_END)) { ++ ret = 0; ++ switch (act->type) { ++ case RTE_FLOW_ACTION_TYPE_PORT_ID: ++ ret = hinic3_add_port_id_action(act, offload_action); ++ break; ++ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: ++ has_set_vlan_pcp = true; ++ rte_vlan_pcp = act->conf; ++ if (has_set_vlan_pcp && has_set_vlan_vid) { ++ hinic3_offload_parse_vlan_act(offload_action, rte_vlan_pcp, rte_vlan_vid); ++ } ++ break; ++ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: ++ has_set_vlan_vid = true; ++ rte_vlan_vid = act->conf; ++ if (has_set_vlan_pcp && has_set_vlan_vid) { ++ hinic3_offload_parse_vlan_act(offload_action, rte_vlan_pcp, rte_vlan_vid); ++ } ++ break; ++ case RTE_FLOW_ACTION_TYPE_SAMPLE: ++ mega_flow->flags.is_sample = HINIC3_FLOW_EMC_MIRROR; ++ ret = hinic3_offload_parse_sample_act(act, &offload_action->act_nla, mega_flow, mirror_dir_flag); ++ break; ++ default: ++ ret = hinic3_offload_parse_action_sub(act, offload_action); ++ break; ++ } ++ if (ret != 0) { ++ return -1; ++ } ++ act = next_no_void_action(actions, act); ++ } ++ (void)hinic3_add_simple_ct_action(offload_action, &mega_flow->key); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.h +new file mode 100644 +index 0000000..aeb0914 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_OFFLOAD_ACTION_H ++#define HINIC3_OFFLOAD_ACTION_H ++ ++#include ++#include "hinic3_offload_flow.h" ++ ++int hinic3_offload_parse_action(const struct rte_flow_action actions[], struct rte_flow *mega_flow, ++ struct hinic3_flow_offload_param *param, uint8_t mirror_dir_flag); ++uint32_t hinic3_process_port_id(uint32_t port_id); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c +new file mode 100644 +index 0000000..d193d8f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c +@@ -0,0 +1,587 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_offload_flow.h" ++#include "rte_lcore.h" ++#include "rte_flow.h" ++#include "hinic3_message.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_log.h" ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_timeval.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_agent_cmd_time.h" ++#include "hinic3_iface_flow_api_record.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_trace_flow.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_offload_action.h" ++#include "hinic3_offload_action_public.h" ++ ++#define TCI_OFFSET 0xF000 ++#define RTE_TCP_FIN_SYN_RST_FLAG 0x07 ++#define VXLAN_VNI_LAST_INDEX 2 ++#define HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE 2048 ++#define HINIC3_NO_FOUND_FLOW (-4) ++#define HINIC3_BIT_MID_MOVE_INDEX 8 ++#define HINIC3_ICMP_ECHO_REQUEST_TYPE 8 ++#define HINIC3_ICMP_ECHO_REPLY_TYPE 0 ++#define HINIC3_ICMP_ECHO_NORMAL_CODE 0 ++ ++static void hinic3_flow_agent_construct_5tuple(struct hinic3_nlattr *hinic3_key, ++ const struct hinic3_conntrack_key *key) ++{ ++ struct hinic3_key_5tuple *tuple = (struct hinic3_key_5tuple *)key->key; ++ struct hinic3_key_raw_ip *raw_ip = (struct hinic3_key_raw_ip *)key->key; ++ hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_DL_TYPE, tuple->ip.ether_type); ++ if (tuple->ip.ether_type == htons(ETH_TYPE_IP)) { ++ hinic3_nlattr_put_u32(hinic3_key, HINIC3_FLOW_KEY_SRC_IP, tuple->ip.src.ipv4); ++ hinic3_nlattr_put_u32(hinic3_key, HINIC3_FLOW_KEY_DST_IP, tuple->ip.dst.ipv4); ++ } else if (tuple->ip.ether_type == htons(ETH_TYPE_IPV6)) { ++ hinic3_nlattr_put_unspec(hinic3_key, HINIC3_FLOW_KEY_SRC_IPV6, &tuple->ip.src.ipv6, sizeof(tuple->ip.src.ipv6)); ++ hinic3_nlattr_put_unspec(hinic3_key, HINIC3_FLOW_KEY_DST_IPV6, &tuple->ip.dst.ipv6, sizeof(tuple->ip.dst.ipv6)); ++ } ++ ++ ++ if (key->meta.tcp_udp_flag == HINIC3_CT_DEFAULT_FLAG) { ++ hinic3_nlattr_put_u8(hinic3_key, HINIC3_FLOW_KEY_PROTOCOL, raw_ip->protocol); ++ } else { ++ hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_SRC_PORT, tuple->port_src); ++ hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_DST_PORT, tuple->port_dst); ++ hinic3_nlattr_put_u8(hinic3_key, HINIC3_FLOW_KEY_PROTOCOL, hinic3_ct_get_proto_by_flag(key->meta.tcp_udp_flag)); ++ } ++} ++ ++void hinic3_offload_flow_construct_key(const struct hinic3_conntrack_key *key, struct hinic3_nlattr *hinic3_key) ++{ ++ struct hinic3_key_mac *mac_tuple = (struct hinic3_key_mac *)key->key; ++ struct hinic3_key_vxlan_vid_5tuple *port_key = (struct hinic3_key_vxlan_vid_5tuple *)key->key; ++ ++ hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_IN_PORT, port_key->input_port); ++ hinic3_nlattr_put_unspec(hinic3_key, HINIC3_FLOW_KEY_DST_MAC, mac_tuple->dmac, sizeof(mac_tuple->dmac)); ++ hinic3_nlattr_put_unspec(hinic3_key, HINIC3_FLOW_KEY_SRC_MAC, mac_tuple->smac, sizeof(mac_tuple->smac)); ++ ++ struct hinic3_key_vxlan *vxlan = &(((struct hinic3_key_vxlan_vid_5tuple *)key->key)->vxlan); ++ hinic3_nlattr_put_u32(hinic3_key, HINIC3_FLOW_KEY_VNI, vxlan->vni); ++ ++ uint16_t outer_vid = ((struct hinic3_key_vid_5tuple *)key->key)->outer_vid; ++ hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_OUTER_VID, outer_vid); ++ ++ hinic3_flow_agent_construct_5tuple(hinic3_key, key); ++ hinic3_trace_flow_info_update(HINIC3_FLOW_CONSTRUCT_KEY_DONE_TRACE, key); ++ return; ++} ++ ++static void hinic3_parse_vlan_key(const struct rte_flow_item *item, struct hinic3_key_ip *ip, ++ struct hinic3_conntrack_full_key *key) ++{ ++ const struct rte_flow_item_vlan *vlan = item->spec; ++ uint16_t *outer_vid = &(((struct hinic3_key_vid_5tuple *)key->key.key)->outer_vid); ++ *outer_vid = vlan->tci; ++ if (vlan->inner_type != 0) { ++ ip->ether_type = vlan->inner_type; ++ } ++} ++ ++static void hinic3_parse_tcp_key(const struct rte_flow_item *item, hinic3_be16 *port_src, hinic3_be16 *port_dst, ++ struct hinic3_conntrack_full_key *key) ++{ ++ const struct rte_flow_item_tcp *tcp_spec = item->spec; ++ const struct rte_flow_item_tcp *tcp_mask = item->mask; ++ ++ *port_src = tcp_spec->hdr.src_port; ++ *port_dst = tcp_spec->hdr.dst_port; ++ key->key.meta.tcp_udp_flag = HINIC3_CT_TCP_FLAG; ++ if (tcp_mask == NULL) { ++ return; ++ } ++ if (tcp_spec->hdr.tcp_flags == 0 && tcp_mask->hdr.tcp_flags == RTE_TCP_FIN_SYN_RST_FLAG) { ++ key->key.meta.need_ct_action = 1; ++ } ++} ++ ++static void hinic3_parese_ipv4_key(const struct rte_flow_item *item, struct hinic3_conntrack_full_key *key) ++{ ++ const struct rte_flow_item_ipv4 *ipv4 = item->spec; ++ struct hinic3_key_5tuple *tuple = NULL; ++ struct hinic3_key_raw_ip *raw_ip = NULL; ++ ++ uint8_t protocol = ipv4->hdr.next_proto_id; ++ if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) { ++ tuple = (struct hinic3_key_5tuple *)key->key.key; ++ memcpy(&tuple->ip.src, &ipv4->hdr.src_addr, sizeof(ipv4->hdr.src_addr)); ++ memcpy(&tuple->ip.dst, &ipv4->hdr.dst_addr, sizeof(ipv4->hdr.dst_addr)); ++ } else { ++ raw_ip = (struct hinic3_key_raw_ip *)key->key.key; ++ memcpy(&raw_ip->ip.src, &ipv4->hdr.src_addr, sizeof(ipv4->hdr.src_addr)); ++ memcpy(&raw_ip->ip.dst, &ipv4->hdr.dst_addr, sizeof(ipv4->hdr.dst_addr)); ++ raw_ip->protocol = ipv4->hdr.next_proto_id; ++ } ++ return; ++} ++ ++static void howff_parse_ipv6_key(const struct rte_flow_item *item, struct hinic3_conntrack_full_key *key) ++{ ++ const struct rte_flow_item_ipv6 *ipv6 = item->spec; ++ struct hinic3_key_5tuple *tuple = NULL; ++ struct hinic3_key_raw_ip *raw_ip = NULL; ++ ++ uint8_t protocol = ipv6->hdr.proto; ++ if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP || protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) { ++ tuple = (struct hinic3_key_5tuple *)key->key.key; ++ memcpy(&tuple->ip.src, ipv6->hdr.src_addr, sizeof(ipv6->hdr.src_addr)); ++ memcpy(&tuple->ip.dst, ipv6->hdr.dst_addr, sizeof(ipv6->hdr.dst_addr)); ++ } else { ++ raw_ip = (struct hinic3_key_raw_ip *)key->key.key; ++ memcpy(&raw_ip->ip.src, ipv6->hdr.src_addr, sizeof(ipv6->hdr.src_addr)); ++ memcpy(&raw_ip->ip.dst, ipv6->hdr.dst_addr, sizeof(ipv6->hdr.dst_addr)); ++ raw_ip->protocol = ipv6->hdr.proto; ++ } ++ return; ++} ++ ++static void hinic3_parse_ip_key(const struct rte_flow_item *item, struct hinic3_conntrack_full_key *key) ++{ ++ switch (item->type) { ++ case RTE_FLOW_ITEM_TYPE_IPV4: ++ hinic3_parese_ipv4_key(item, key); ++ break; ++ case RTE_FLOW_ITEM_TYPE_IPV6: ++ howff_parse_ipv6_key(item, key); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void hinic3_clear_ip_key(struct hinic3_key_ip *ip) ++{ ++ memset(&ip->src, 0, sizeof(ip->src)); ++ memset(&ip->dst, 0, sizeof(ip->dst)); ++} ++ ++static void hinic3_parse_vxlan_key(const struct rte_flow_item *item, struct hinic3_conntrack_full_key *key) ++{ ++ const struct rte_flow_item_vxlan *vxlan = NULL; ++ ++ vxlan = item->spec; ++ uint32_t *vxlan_vni = &(((struct hinic3_key_vxlan_vid_5tuple *)key->key.key)->vxlan.vni); ++ *vxlan_vni = vxlan->vni[0] + (vxlan->vni[1] << HINIC3_BYTE_BITS) + ++ (vxlan->vni[VXLAN_VNI_LAST_INDEX] << HINIC3_SHORT_BITS); ++ *vxlan_vni <<= HINIC3_BYTE_BITS; ++} ++ ++static int hinic3_parse_in_port_id(const struct rte_flow_item *item, struct hinic3_key_vxlan_vid_5tuple *port_key) ++{ ++ uint16_t port_id; ++ const struct rte_flow_item_port_id *port_id_item = NULL; ++ ++ port_id_item = item->spec; ++ port_id = (uint16_t)hinic3_process_port_id(port_id_item->id); ++ if (port_id > UINT16_MAX) { ++ return -1; ++ } ++ port_key->input_port = htons(port_id); ++ return 0; ++} ++ ++static void hinic3_parse_udp_key(const struct rte_flow_item *item, hinic3_be16 *port_src, hinic3_be16 *port_dst, ++ struct hinic3_conntrack_full_key *key) ++{ ++ const struct rte_flow_item_udp *udp = item->spec; ++ ++ *port_src = udp->hdr.src_port; ++ *port_dst = udp->hdr.dst_port; ++ key->key.meta.tcp_udp_flag = HINIC3_CT_UDP_FLAG; ++} ++ ++static void hinic3_clear_udp_key(hinic3_be16 *port_src, hinic3_be16 *port_dst, struct hinic3_conntrack_full_key *key) ++{ ++ *port_src = 0; ++ *port_dst = 0; ++ key->key.meta.tcp_udp_flag = HINIC3_CT_DEFAULT_FLAG; ++} ++ ++static int hinic3_parse_icmp_key(const struct rte_flow_item *item, hinic3_be16 *port_src, hinic3_be16 *port_dst, ++ struct hinic3_conntrack_full_key *key) ++{ ++ const struct rte_flow_item_icmp *icmp = item->spec; ++ uint8_t icmp_type = icmp->hdr.icmp_type; ++ uint8_t icmp_code = icmp->hdr.icmp_code; ++ uint16_t icmp_ident = icmp->hdr.icmp_ident; ++ ++ *port_src = ((icmp_type) << HINIC3_BIT_MID_MOVE_INDEX) | icmp_code; ++ *port_dst = icmp_ident; ++ ++ switch (item->type) { ++ case RTE_FLOW_ITEM_TYPE_ICMP: ++ key->key.meta.tcp_udp_flag = HINIC3_CT_ICMP_FLAG; ++ break; ++ case RTE_FLOW_ITEM_TYPE_ICMP6: ++ key->key.meta.tcp_udp_flag = HINIC3_CT_ICMPV6_FLAG; ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static void hinic3_parse_eth_key(const struct rte_flow_item *item, struct hinic3_key_mac *mac, struct hinic3_key_ip *ip) ++{ ++ const struct rte_flow_item_eth *eth = NULL; ++ ++ eth = item->spec; ++ memcpy(mac->dmac, ð->dst, ETH_ALEN); ++ memcpy(mac->smac, ð->src, ETH_ALEN); ++ ip->ether_type = eth->type; ++} ++ ++static void hinic3_clear_eth_key(struct hinic3_key_mac *mac, struct hinic3_key_ip *ip) ++{ ++ memset(mac->dmac, 0, ETH_ALEN); ++ memset(mac->smac, 0, ETH_ALEN); ++ ip->ether_type = 0; ++} ++ ++static int hinic3_offload_parse_key_sub(const struct rte_flow_item *item, struct hinic3_conntrack_full_key *key, ++ uint8_t *has_vxlan_item) ++{ ++ struct hinic3_key_mac *mac = (struct hinic3_key_mac *)key->key.key; ++ struct hinic3_key_vxlan_vid_5tuple *port_key = (struct hinic3_key_vxlan_vid_5tuple *)key->key.key; ++ struct hinic3_key_ip *ip = (struct hinic3_key_ip *)((uint8_t *)mac + sizeof(struct hinic3_key_mac)); ++ hinic3_be16 *port_src = (hinic3_be16 *)((uint8_t *)ip + sizeof(struct hinic3_key_ip)); ++ hinic3_be16 *port_dst = (hinic3_be16 *)((uint8_t *)port_src + sizeof(hinic3_be16)); ++ ++ switch (item->type) { ++ case RTE_FLOW_ITEM_TYPE_ETH: ++ (void)hinic3_parse_eth_key(item, mac, ip); ++ break; ++ case RTE_FLOW_ITEM_TYPE_VLAN: ++ (void)hinic3_parse_vlan_key(item, ip, key); ++ break; ++ case RTE_FLOW_ITEM_TYPE_IPV4: ++ case RTE_FLOW_ITEM_TYPE_IPV6: ++ (void)hinic3_parse_ip_key(item, key); ++ break; ++ case RTE_FLOW_ITEM_TYPE_VXLAN: ++ /* 报文外层key忽略不下发。 ++ * 当item遍历到item vxlan时,说明此前解析的key为外层key,将已解析的内容清零。 */ ++ (void)hinic3_clear_eth_key(mac, ip); ++ (void)hinic3_clear_ip_key(ip); ++ (void)hinic3_clear_udp_key(port_src, port_dst, key); ++ (void)hinic3_parse_vxlan_key(item, key); ++ *has_vxlan_item = 1; ++ break; ++ case RTE_FLOW_ITEM_TYPE_UDP: ++ (void)hinic3_parse_udp_key(item, port_src, port_dst, key); ++ break; ++ case RTE_FLOW_ITEM_TYPE_TCP: ++ (void)hinic3_parse_tcp_key(item, port_src, port_dst, key); ++ break; ++ case RTE_FLOW_ITEM_TYPE_PORT_ID: ++ if (hinic3_parse_in_port_id(item, port_key) != 0) { ++ return -1; ++ } ++ break; ++ case RTE_FLOW_ITEM_TYPE_ICMP: ++ case RTE_FLOW_ITEM_TYPE_ICMP6: ++ (void)hinic3_parse_icmp_key(item, port_src, port_dst, key); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++int hinic3_offload_parse_key(const struct rte_flow_item pattern[], struct hinic3_conntrack_full_key *key, ++ uint8_t *has_vxlan_item) ++{ ++ const struct rte_flow_item *item = NULL; ++ int ret = 0; ++ ++ item = next_no_end_pattern(pattern, NULL); ++ while (item) { ++ if (item->spec == NULL) { ++ HINIC3_LOG(INFO, FLOW, "rte_flow_item->spec is NULL.\n"); ++ item = next_no_end_pattern(pattern, item); ++ continue; ++ } ++ ++ ret = hinic3_offload_parse_key_sub(item, key, has_vxlan_item); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3_offload_parse_key_sub failed."); ++ return -1; ++ } ++ item = next_no_end_pattern(pattern, item); ++ } ++ hinic3_trace_flow_info_update(HINIC3_FLOW_PKT_KEY_RESOLVE_DONE_TRACE, &key->key); ++ return 0; ++} ++ ++static void hinic3_offload_parse_args(struct hinic3_nlattr *hinic3_args, const struct hinic3_conntrack_full_key *key, ++ clock_t time, uint32_t flow_hash) ++{ ++ hinic3_nlattr_put_unspec(hinic3_args, HINIC3_FLOW_ARG_NO_CT_UFID, key, sizeof(struct hinic3_conntrack_full_key)); ++ hinic3_nlattr_put_u64(hinic3_args, HINIC3_FLOW_ARG_TIME, time); ++ hinic3_nlattr_put_u32(hinic3_args, HINIC3_FLOW_ARG_FLOW_HASH, flow_hash); ++} ++ ++static int hinic3_process_flow_key(const struct rte_flow_item pattern[], struct hinic3_flow_offload_param *param, ++ struct rte_flow *mega_flow, struct hinic3_dpif_flow *flow, uint8_t *has_vxlan_item) ++{ ++ int ret; ++ struct hinic3_conntrack_full_key *key = &mega_flow->key; ++ ++ key->key.meta.key_len = sizeof(struct hinic3_conntrack_full_key) - sizeof(struct hinic3_conntrack_key); ++ key->key.meta.tcp_udp_flag = HINIC3_CT_DEFAULT_FLAG; ++ ++ ret = hinic3_offload_parse_key(pattern, key, has_vxlan_item); ++ if (ret != 0) { ++ return -1; ++ } ++ flow->key = param->hinic3_key.data; ++ (void)hinic3_offload_flow_construct_key(&key->key, ¶m->hinic3_key); ++ flow->key_len = param->hinic3_key.used_len; ++ ++ hinic3_trace_flow_info_update(HINIC3_FLOW_OFFLOAD_KEY_PROCESS_DONE_TRACE, &key->key); ++ return ret; ++} ++ ++static int hinic3_offload_parse_flow_action(const struct rte_flow_action actions[], ++ struct hinic3_flow_offload_param *param, struct rte_flow *mega_flow, struct hinic3_dpif_flow *flow, ++ uint8_t has_vxlan_item) ++{ ++ int ret; ++ uint8_t mirror_dir_flag = (has_vxlan_item == 0) ? HINIC3_SESSION_TX : HINIC3_SESSION_RX; ++ ++ ret = hinic3_offload_parse_action(actions, mega_flow, param, mirror_dir_flag); ++ if (ret != 0) { ++ hinic3_trace_flow_info_update(HINIC3_FLOW_PROCESS_OFFLOAD_ACTION_ERROR_TRACE, &mega_flow->key.key); ++ return ret; ++ } ++ ++ if (param->cur_actions.has_output == false && param->cur_actions.has_dp_hash == false) { ++ return -EINVAL; ++ } ++ ++ flow->actions = param->cur_actions.act_nla.data; ++ flow->action_len = param->cur_actions.act_nla.used_len; ++ ++ hinic3_trace_flow_info_update(HINIC3_FLOW_PROCESS_OFFLOAD_ACTION_DONE_TRACE, &mega_flow->key.key); ++ return ret; ++} ++ ++static void hinic3_offload_parse_flow_args(struct hinic3_flow_offload_param *param, struct rte_flow *flow, ++ clock_t time, uint32_t flow_hash) ++{ ++ hinic3_offload_parse_args(¶m->hinic3_args, &flow->key, time, flow_hash); ++ hinic3_trace_flow_info_update(HINIC3_AGENT_IS_FLOW_READY_PUT_DONE_TRACE, &flow->key.key); ++} ++ ++static void hinic3_offload_parse_modify_flow_args(struct hinic3_flow_offload_param *param, struct rte_flow *flow, ++ uint32_t flow_hash) ++{ ++ hinic3_nlattr_init(¶m->hinic3_args, param->offload_buff.args_buf, HINIC3_MSG_MAX_BUF); ++ hinic3_nlattr_put_unspec(¶m->hinic3_args, HINIC3_FLOW_ARG_NO_CT_UFID, ++ &flow->key, sizeof(struct hinic3_conntrack_full_key)); ++ hinic3_nlattr_put_flag(¶m->hinic3_args, HINIC3_FLOW_ARG_MODIFY); ++ hinic3_nlattr_put_u32(¶m->hinic3_args, HINIC3_FLOW_ARG_FLOW_HASH, flow_hash); ++} ++ ++static int hinic3_alloc_get_f(struct hinic3_dpif_flow_for_get *f) ++{ ++ f->key = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); ++ if (f->key == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "calloc memory for hw flow key error\n"); ++ return -1; ++ } ++ ++ f->actions = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); ++ if (f->actions == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "calloc memory for hw flow actions error\n"); ++ hinic3_free(f->key); ++ f->key = NULL; ++ return -1; ++ } ++ ++ f->mask = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); ++ if (f->mask == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "calloc memory for hw flow mask error\n"); ++ hinic3_free(f->key); ++ f->key = NULL; ++ hinic3_free(f->actions); ++ f->actions = NULL; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void hinic3_free_get_f(struct hinic3_dpif_flow_for_get *f) ++{ ++ if (f->key != NULL) { ++ hinic3_free(f->key); ++ f->key = NULL; ++ } ++ f->key_len = 0; ++ ++ if (f->actions != NULL) { ++ hinic3_free(f->actions); ++ f->actions = NULL; ++ } ++ f->action_len = 0; ++ ++ if (f->mask != NULL) { ++ hinic3_free(f->mask); ++ f->mask = NULL; ++ } ++ f->mask_len = 0; ++} ++ ++static int hinic3_insert_rte_flow(struct hash_table_node *rte_bucket, struct rte_flow *mega_flow, ++ struct rte_flow_error *error) ++{ ++ int ret = 0; ++ struct rte_flow *flow = NULL; ++ struct hinic3_dpif_flow_for_get hiovs_get = { 0 }; ++ ++ flow = hinic3_get_offloaded_rte_flow(rte_bucket, &mega_flow->key, mega_flow->flow_hash); ++ if (flow != NULL) { ++ if (flow->flags.is_offload == 1) { ++ ret = hinic3_alloc_get_f(&hiovs_get); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3load insert rte flow alloc failed."); ++ return -1; ++ } ++ ret = hinic3_flow_get_by_ufid(flow->hw_ufid, &hiovs_get); ++ hinic3_free_get_f(&hiovs_get); ++ if (ret == 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_REPEATED, 1); ++ return rte_flow_error_set(error, EEXIST, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, ++ NULL, HINIC3_EMC_ERROR_MSG_REPEATED); ++ } else if (ret == HINIC3_NO_FOUND_FLOW) { ++ // 如果dpak流表卸载完成,但是硬件流表不存在,则再下一遍流表给硬件 ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_EXIST_GAP, 1); ++ return 0; ++ } ++ } else { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CHECK_OFFLOADING_ONGOING, 1); ++ return rte_flow_error_set(error, EEXIST, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, ++ NULL, HINIC3_EMC_ERROR_MSG_REPEATED); ++ } ++ } ++ ++ ret = hinic3_insert_rte_flow_in_hmap(rte_bucket, mega_flow); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_INSERT_RTE_FLOW_IN_HMAP, 1); ++ return rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, HINIC3_EMC_ERROR_MSG_ITEM); ++ } ++ ++ hinic3_trace_flow_info_update(HINIC3_FLOW_OFFLOAD_KEY_INSERT_TABLE_DONE_TRACE, &mega_flow->key.key); ++ return 0; ++} ++ ++static void hinic3_init_param_buff(struct hinic3_flow_offload_param *param) ++{ ++ hinic3_nlattr_init(¶m->hinic3_key, param->offload_buff.key_buf, HINIC3_MSG_MAX_BUF); ++ hinic3_nlattr_init(¶m->cur_actions.act_nla, param->offload_buff.actions_buf, HINIC3_MSG_MAX_BUF); ++ hinic3_nlattr_init(¶m->hinic3_args, param->offload_buff.args_buf, HINIC3_MSG_MAX_BUF); ++} ++ ++static void hinic3_proces_put_args(struct hinic3_flow_offload_param *param, const struct rte_flow_item pattern[], ++ struct rte_flow *flow, clock_t start_t) ++{ ++ (void)hinic3_offload_parse_flow_args(param, flow, start_t, flow->flow_hash); ++} ++ ++static int hinic3_process_offload_flow(const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], struct rte_flow *mega_flow, struct hinic3_flow_agent_db *hw_offload, ++ struct rte_flow_error *error) ++{ ++ uint32_t flow_hash; ++ uint8_t has_vxlan_item = 0; ++ clock_t start_t = { 0 }; ++ struct hinic3_flow_offload_param param = { 0 }; ++ struct hinic3_dpif_flow flow = { 0 }; ++ param.hw_offload = hw_offload; ++ struct hash_table_node *rte_bucket = NULL; ++ hinic3_init_param_buff(¶m); ++ ++ if (HINIC3_UNLIKELY(hinic3_is_offload_measure_alive() == true)) { ++ start_t = clock(); ++ } ++ ++ /* deal with key */ ++ int ret = hinic3_process_flow_key(pattern, ¶m, mega_flow, &flow, &has_vxlan_item); ++ if (HINIC3_UNLIKELY(ret != 0)) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_PROCESS_FLOW_KEY, 1); ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL, HINIC3_EMC_ERROR_MSG_FLOW); ++ } ++ ++ flow_hash = hinic3_hash_generate(&mega_flow->key.key); ++ rte_bucket = hinic3_get_flow_bucket(flow_hash); ++ hinic3_trace_flow_info_update(HINIC3_FLOW_OFFLOAD_KEY_HASH_DONE_TRACE, &mega_flow->key.key); ++ ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ mega_flow->flow_hash = flow_hash; ++ /* Check whether the offloading is repeated. If yes, a failure message is returned. */ ++ ret = hinic3_insert_rte_flow(rte_bucket, mega_flow, error); ++ if (ret != 0) { ++ hinic3_trace_flow_info_update(HINIC3_FLOW_OFFLOAD_KEY_INSERT_TABLE_ERROR_TRACE, &mega_flow->key.key); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return ret; ++ } ++ ++ /* deal with action */ ++ ret = hinic3_offload_parse_flow_action(actions, ¶m, mega_flow, &flow, has_vxlan_item); ++ if (HINIC3_UNLIKELY(ret != 0)) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_PARSE_FLOW_ACTION, 1); ++ ret = rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, HINIC3_EMC_ERROR_MSG_ACTION); ++ goto fail; ++ } ++ ++ /* deal with args */ ++ (void)hinic3_proces_put_args(¶m, pattern, mega_flow, start_t); ++ ++ ret = hinic3_flow_put(&flow, param.hinic3_args.data, param.hinic3_args.used_len); ++ if (ret != 0) { ++ hinic3_trace_flow_info_update(HINIC3_FLOW_AGENT_ERROR_HARDWARE_FAIL_TRACE, &mega_flow->key.key); ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_CALL_HARDWARE_FUNC, 1); ++ (void)rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_STATE, NULL, HINIC3_EMC_ERROR_MSG_OFFLOAD_HOVS); ++ goto fail; ++ } ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ ++ hinic3_trace_flow_info_update(HINIC3_AGENT_FLOW_PUT_DONE_TRACE, &mega_flow->key.key); ++ return 0; ++fail: ++ hinic3_del_rte_flow_if_offload_fail(rte_bucket, mega_flow); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return ret; ++} ++ ++struct rte_flow *hinic3_offload_flow(const struct rte_flow_item pattern[], const struct rte_flow_action actions[], ++ struct hinic3_flow_agent_db *hw_offload, struct rte_flow_error *error) ++{ ++ int ret; ++ ++ struct rte_flow *alloc_flow = hinic3_rte_flow_alloc(); ++ if (HINIC3_UNLIKELY(alloc_flow == NULL)) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_EMC_FLOW_ALLOC, 1); ++ rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "alloc mem failed"); ++ return NULL; ++ } ++ ++ ret = hinic3_process_offload_flow(pattern, actions, alloc_flow, hw_offload, error); ++ if (ret != 0) { ++ hinic3_rte_flow_dealloc(alloc_flow); ++ return NULL; ++ } ++ ++ return alloc_flow; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.h +new file mode 100644 +index 0000000..d1e8115 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_OFFLOAD_FLOW_H ++#define HINIC3_OFFLOAD_FLOW_H ++ ++#include ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_ufid_map_rte_flow.h" ++ ++struct rte_flow *hinic3_offload_flow(const struct rte_flow_item pattern[], const struct rte_flow_action actions[], ++ struct hinic3_flow_agent_db *hw_offload, struct rte_flow_error *error); ++int hinic3_offload_parse_key(const struct rte_flow_item pattern[], struct hinic3_conntrack_full_key *key, ++ uint8_t *has_vxlan_item); ++void hinic3_offload_flow_construct_key(const struct hinic3_conntrack_key *key, struct hinic3_nlattr *hinic3_key); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.c +new file mode 100644 +index 0000000..1a9f08a +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.c +@@ -0,0 +1,192 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_flow_agent_sync_stats.h" ++#include ++#include "hinic3_util.h" ++#include "rte_ethdev.h" ++#include "rte_cycles.h" ++#include "rte_flow.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_log.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_timeval.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_error_stats.h" ++ ++#define SEC_TO_MSEC_BASE 1000 ++#define LIVE_TIME_SHIFT 13u ++#define MAX_LIVE_TIME ((1 << LIVE_TIME_SHIFT) - 1) ++ ++static bool hinic3_check_offload_extend_info(struct hinic3_dp_extend_info *dp_info, long long now, ++ uint32_t thread_id) ++{ ++ struct hinic3_flow_agent_db *hw_offload = NULL; ++ ++ bool is_hmap_empty = hinic3_is_rte_hmap_empty(); ++ if (is_hmap_empty) { ++ return false; ++ } ++ ++ hw_offload = dp_info->hw_offload; ++ if (hw_offload == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "hinic3_check_offload_extend_info hw_offload is null."); ++ return false; ++ } ++ ++ bool is_push_mode = hinic3_stats_sync_push_mode(hw_offload); ++ if (!is_push_mode) { ++ HINIC3_LOG(WARNING, FLOW, "offload thread is not in sync pull mode."); ++ return false; ++ } ++ ++ ++ if (hw_offload->next_hw_stats_sync[thread_id] > now) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static void hinic3_flow_agent_sync_hw_flow_stats(const struct hinic3_dp_extend_info *dp_info, uint64_t hw_ufid, ++ struct rte_flow *flow, struct hinic3_flow_stats *stats) ++{ ++ if (dp_info == NULL || dp_info->hw_offload == NULL) { ++ HINIC3_LOG(WARNING, FLOW, "sync single flow pointer is null."); ++ return; ++ } ++ ++ struct hinic3_flow_stats stats_buf; ++ ++ if (flow == NULL || flow->flags.is_offload == 0) { ++ return; ++ } ++ ++ if (stats == NULL) { ++ stats = &stats_buf; ++ /* Get stats from hardware */ ++ if (hinic3_statistics_flow_get_by_ufid(&hw_ufid, 1, stats) != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_GET_HW_STATS_BY_UFID, 1); ++ return; ++ } ++ } ++ ++ flow->hw_packets = stats->packet_count; ++ flow->hw_bytes = stats->byte_count; ++ ++ if (stats->live_time / SEC_TO_MSEC_BASE > MAX_LIVE_TIME) { ++ flow->flags.live_time = MAX_LIVE_TIME; ++ } else { ++ flow->flags.live_time = (uint16_t)(stats->live_time / SEC_TO_MSEC_BASE); ++ } ++ ++ return; ++} ++ ++static int hinic3_sync_hardware_flow_statistics(const uint64_t *ufid, const size_t cnt, ++ struct hinic3_stats_dump_context *sync_ctx) ++{ ++ if (hinic3_statistics_flow_get_by_ufid(ufid, cnt, sync_ctx->stats) != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_GET_HW_STATS_BY_UFID, 1); ++ return -1; ++ } ++ ++ for (size_t idx = 0; idx < cnt; idx++) { ++ hinic3_flow_agent_sync_hw_flow_stats(sync_ctx->dp_info, sync_ctx->ufids[idx], sync_ctx->priv_data[idx], ++ &sync_ctx->stats[idx]); ++ } ++ return 0; ++} ++ ++static int hinic3_flow_agent_hw_iterate_cb(struct rte_flow *flow_data, ++ struct traverse_data *cur_traverse_data) ++{ ++ struct hinic3_stats_dump_context *sync_ctx = NULL; ++ struct rte_flow *flow = NULL; ++ bool is_end; ++ ++ if (cur_traverse_data == NULL) { ++ return -1; ++ } ++ ++ sync_ctx = (struct hinic3_stats_dump_context *)cur_traverse_data->para; ++ is_end = cur_traverse_data->is_end; ++ ++ if (is_end == true) { ++ hinic3_sync_hardware_flow_statistics(sync_ctx->ufids, sync_ctx->num_entries, sync_ctx); ++ sync_ctx->num_entries = 0; ++ return 0; ++ } ++ ++ if (flow_data == NULL) { ++ return -1; ++ } ++ flow = flow_data; ++ if (flow->flags.is_offload == 0) { ++ return 0; ++ } ++ ++ sync_ctx->priv_data[sync_ctx->num_entries] = flow; ++ sync_ctx->ufids[sync_ctx->num_entries] = flow->hw_ufid; ++ if ((++sync_ctx->num_entries) < HINIC3_MAX_ENTRY_PER_STATS_DUMP) { ++ return 0; ++ } ++ ++ /* Get stats from hardware */ ++ hinic3_sync_hardware_flow_statistics(sync_ctx->ufids, sync_ctx->num_entries, sync_ctx); ++ ++ sync_ctx->num_entries = 0; ++ sync_ctx->total_hw_num += HINIC3_MAX_ENTRY_PER_STATS_DUMP; ++ return 0; ++} ++ ++int hinic3_sync_flow_statistics(uint32_t thread_id, struct hinic3_dp_extend_info *dp_info) ++{ ++ struct hinic3_flow_agent_db *hw_offload = NULL; ++ struct hinic3_stats_dump_context *sync_ctx = NULL; ++ struct hinic3_offload_thread_data *thread_data = NULL; ++ ++ long long now = hinic3_time_msec(); ++ if (dp_info == NULL) { ++ HINIC3_LOG(ERR, FLOW, "offload thread :%" PRIu32 " sync operate parameter point is null.", thread_id); ++ return -1; ++ } ++ ++ if (!hinic3_check_offload_extend_info(dp_info, now, thread_id)) { ++ return -1; ++ } ++ ++ hw_offload = dp_info->hw_offload; ++ sync_ctx = (struct hinic3_stats_dump_context *)hinic3_calloc(1, sizeof(struct hinic3_stats_dump_context), HINIC3_FLOWS); ++ if (sync_ctx == NULL) { ++ HINIC3_LOG(ERR, FLOW, "alloc sync_ctx failed."); ++ return -1; ++ } ++ sync_ctx->dp_info = dp_info; ++ sync_ctx->num_entries = 0; ++ sync_ctx->total_hw_num = 0; ++ sync_ctx->start_time = now; ++ thread_data = &dp_info->offload_threads[thread_id]; ++ ++ /* get time stamps */ ++ if (thread_data->cur_buk_idx == thread_data->min_buk_idx) { ++ if (hinic3_statistics_flow_get_by_ufid(NULL, thread_id, NULL) != 0) { ++ hinic3_free(sync_ctx); ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_GET_TIME_STAMP, 1); ++ return -1; ++ } ++ } ++ ++ hinic3_dump_rte_flow_by_hw_ufid(thread_id, &thread_data->cur_buk_idx, thread_data->max_buk_idx, ++ (uint8_t *)sync_ctx, hinic3_flow_agent_hw_iterate_cb); ++ ++ if (thread_data->cur_buk_idx >= thread_data->max_buk_idx) { ++ now = hinic3_time_msec(); ++ hw_offload->next_hw_stats_sync[thread_id] = now + HINIC3_STATS_SYNC_INTERVAL; ++ thread_data->cur_buk_idx = thread_data->min_buk_idx; ++ } ++ hinic3_free(sync_ctx); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.h +new file mode 100644 +index 0000000..b7b5080 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_flow_agent_sync_stats.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_FLOW_AGENT_SYNC_STATS_H ++#define HINIC3_FLOW_AGENT_SYNC_STATS_H ++ ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_flow_agent_sync_stats_public.h" ++ ++int hinic3_sync_flow_statistics(uint32_t thread_id, struct hinic3_dp_extend_info *dp_info); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c +new file mode 100644 +index 0000000..76fc7b4 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c +@@ -0,0 +1,737 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_capture_filter.h" ++#include "hinic3_age_delete_flow.h" ++#include "hinic3_command.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_capture_utils.h" ++#include "hinic3_flow_dump_item.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_packet_key_public.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_agent_flow_cmd.h" ++#include "hinic3_string_format.h" ++#include "hinic3_key_query.h" ++ ++struct input_key g_input_key = { 0 }; ++ ++ ++void hinic3_dpak_query_ufid(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_input_key_help(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++void hinic3_parse_cmd_exec(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++ ++static struct pcap_cmd_t g_query_main_commands = { "hwoff/query-offloaded-flow", ++ "{ start -sip ENUM,IPV6> " ++ "-dip ENUM,IPV6> " ++ "-smac MAC -dmac MAC " ++ "-eth_type ENUM<0x0800,0x86dd> " ++ "-ip_proto ENUM " ++ "-vlan INTEGER<0-4095> " ++ "{ -sport INTEGER<0-65535> -dport INTEGER<0-65535> | " ++ "-icmp_type INTEGER<0-255> -icmp_code INTEGER<0-255> " ++ "-icmp_id INTEGER<0-65535> } " ++ "-vxlan_vni INTEGER<0-16777215> " ++ "{ -h | --help } }", ++ hinic3_parse_cmd_exec, ++ QUERY_CMD_MIN_PARAM, ++ QUERY_CMD_MAX_PARAM, ++ " Usage: dpak-ovs-ctl hwoff/query-offloaded-flow { start -sip ENUM,IPV6> \n" ++ " -dip ENUM,IPV6> \n" ++ " -smac MAC -dmac MAC \n" ++ " -eth_type ENUM<0x0800,0x86dd> \n" ++ " -ip_proto ENUM \n" ++ " -vlan INTEGER<0-4095>\n" ++ " { -sport INTEGER<0-65535> -dport INTEGER<0-65535> | \n" ++ " -icmp_type INTEGER<0-255> -icmp_code INTEGER<0-255>" ++ " -icmp_id INTEGER<0-65535> } \n" ++ " -vxlan_vni INTEGER<0-16777215> | \n" ++ " { -h | --help } }\n\n" ++ " Options list:\n" ++ " start Start a flow query task by a specified key\n" ++ " -sip Source IP address\n" ++ " -dip Destination IP address\n" ++ " -smac Source MAC address\n" ++ " -dmac Destination MAC address\n" ++ " -eth_type Data type, in hexadecimal format. The value is an ENUM<0x0800, 0x86dd>\n" ++ " -ip_proto Layer 4 protocol type, ENUM\n" ++ " -vlan Identifier for a specific VLAN in the network, INTEGER <0-4095>\n" ++ " -sport Source port ID\n" ++ " -dport Destination port ID\n" ++ " -icmp_type ICMP message type\n" ++ " -icmp_code ICMP code\n" ++ " -icmp_id ICMP echo request and reply identifier\n" ++ " -vxlan_vni VXLAN ID, INTEGER<0-16777215>\n" ++ " -h, --help Display the help information\n"}; ++ ++static void query_cmd_usage_print(struct ds *ds) ++{ ++ struct pcap_cmd_t *q_cmd = &g_query_main_commands; ++ hinic3_ds_put_format(ds, q_cmd->desc); ++} ++ ++static struct pcap_cmd_t g_query_sub_commands[] = { ++ {"start", NULL, hinic3_dpak_query_ufid, 22, 24, NULL}, ++ {"-h", NULL, hinic3_input_key_help, 1, 1, NULL}, ++ {"--help", NULL, hinic3_input_key_help, 1, 1, NULL}, ++}; ++ ++void hinic3_parse_cmd_exec(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int work_argc; ++ const char **work_argv = argv + 1; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ const char *sub_cmd_name = NULL; ++ struct pcap_cmd_t *dst_sub_cmd = NULL; ++ work_argc = argc - 1; ++ sub_cmd_name = work_argv[0]; ++ for (size_t i = 0; i < ARRAY_SIZE(g_query_sub_commands); i++) { ++ if (strcmp(sub_cmd_name, g_query_sub_commands[i].cmd) == 0) { ++ dst_sub_cmd = &g_query_sub_commands[i]; ++ break; ++ } ++ } ++ ++ if (!dst_sub_cmd) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Unknown command, input -h or --help to get help info.\n"); ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ *(int *)aux = -1; ++ hinic3_ds_destroy(&ds); ++ return; ++ } ++ ++ dst_sub_cmd->cb(conn, work_argc, work_argv, aux); ++ *(int *)aux = 0; ++ hinic3_ds_destroy(&ds); ++} ++ ++static struct pcap_sub_key_parser g_input_key_parser[] = { ++ {"-sip", sizeof("-sip"), hinic3_key_sip_parse}, ++ {"-dip", sizeof("-dip"), hinic3_key_dip_parse}, ++ {"-smac", sizeof("-smac"), hinic3_key_smac_parse}, ++ {"-dmac", sizeof("-dmac"), hinic3_key_dmac_parse}, ++ {"-ip_proto", sizeof("-ip_proto"), hinic3_key_ip_proto_parse}, ++ {"-sport", sizeof("-sport"), hinic3_key_sport_parse}, ++ {"-dport", sizeof("-dport"), hinic3_key_dport_parse}, ++ {"-eth_type", sizeof("-eth_type"), hinic3_key_eth_type_parse}, ++ {"-vlan", sizeof("-vlan"), hinic3_key_vlan_parse}, ++ {"-vxlan_vni", sizeof("-vxlan_vni"), hinic3_key_vni_parse}, ++ {"-port_id", sizeof("-port_id"), hinic3_key_port_id_parse}, ++ {"-icmp_type", sizeof("-icmp_type"), hinic3_key_icmp_type_parse}, ++ {"-icmp_code", sizeof("-icmp_code"), hinic3_key_icmp_code_parse}, ++ {"-icmp_id", sizeof("-icmp_id"), hinic3_key_icmp_id_parse}, ++}; ++ ++struct hinic3_input_key { ++ char *key; ++ bool is_input_key; ++}; ++ ++static struct hinic3_input_key g_hinic3_query_flow_input_keys[] = { ++ {"-sip", false}, ++ {"-dip", false}, ++ {"-smac", false}, ++ {"-dmac", false}, ++ {"-sport", false}, ++ {"-dport", false}, ++ {"-ip_proto", false}, ++ {"-eth_type", false}, ++ {"-vlan", false}, ++ {"-vxlan_vni", false}, ++ {"-port_id", false}, ++ {"-icmp_type", false}, ++ {"-icmp_code", false}, ++ {"-icmp_id", false} ++}; ++ ++static void hinic3_init_input_key_stats(void) ++{ ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_query_flow_input_keys); i++) { ++ g_hinic3_query_flow_input_keys[i].is_input_key = false; ++ } ++} ++ ++static void hinic3_update_input_key_stats(const char *key) ++{ ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_query_flow_input_keys); i++) { ++ if (strcmp(key, g_hinic3_query_flow_input_keys[i].key) == 0) { ++ g_hinic3_query_flow_input_keys[i].is_input_key = true; ++ } ++ } ++} ++ ++static bool hinic3_get_input_key_stats(const char *key) ++{ ++ bool key_status = false; ++ for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_query_flow_input_keys); i++) { ++ if (strcmp(key, g_hinic3_query_flow_input_keys[i].key) == 0) { ++ key_status = g_hinic3_query_flow_input_keys[i].is_input_key; ++ return key_status; ++ } ++ } ++ return key_status; ++} ++ ++static bool hinic3_check_key_udp_is_complete(void) ++{ ++ bool is_valid = false; ++ const char* udp_key[] = {"-sport", "-dport"}; ++ for (size_t i = 0; i < ARRAY_SIZE(udp_key); i++) { ++ is_valid = hinic3_get_input_key_stats(udp_key[i]); ++ if (!is_valid) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static int hinic3_check_key_tcp_is_complete(void) ++{ ++ bool is_valid = false; ++ const char* tcp_key[] = {"-sport", "-dport"}; ++ for (size_t i = 0; i < ARRAY_SIZE(tcp_key); i++) { ++ is_valid = hinic3_get_input_key_stats(tcp_key[i]); ++ if (!is_valid) { ++ return false; ++ } ++ } ++ return true; ++} ++static bool hinic3_check_key_icmp_is_complete(void) ++{ ++ bool is_valid = false; ++ const char* icmp_key[] = {"-icmp_type", "-icmp_code", "-icmp_id"}; ++ for (size_t i = 0; i < ARRAY_SIZE(icmp_key); i++) { ++ is_valid = hinic3_get_input_key_stats(icmp_key[i]); ++ if (!is_valid) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static bool hinic3_check_key_icmp6_is_complete(void) ++{ ++ bool is_valid = false; ++ const char* icmp6_key[] = {"-icmp_type", "-icmp_code", "-icmp_id"}; ++ for (size_t i = 0; i < ARRAY_SIZE(icmp6_key); i++) { ++ is_valid = hinic3_get_input_key_stats(icmp6_key[i]); ++ if (!is_valid) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static bool hinic3_check_port_key_is_complete(uint8_t ip_proto) ++{ ++ switch (ip_proto) { ++ case IPPROTO_UDP: ++ return hinic3_check_key_udp_is_complete(); ++ case IPPROTO_TCP: ++ return hinic3_check_key_tcp_is_complete(); ++ case IPPROTO_ICMP: ++ return hinic3_check_key_icmp_is_complete(); ++ case IPPROTO_ICMPV6: ++ return hinic3_check_key_icmp6_is_complete(); ++ default: ++ return false; ++ } ++ return false; ++} ++ ++static bool hinic3_check_querry_flow_key_is_complete(uint8_t ip_proto) ++{ ++ bool is_valid = false; ++ const char* required_keys[] = { ++ "-sip", "-dip", "-smac", "-dmac", "-ip_proto", "-eth_type", ++ "-vlan", "-vxlan_vni" ++ }; ++ ++ for (size_t i = 0; i < ARRAY_SIZE(required_keys); i++) { ++ is_valid = hinic3_get_input_key_stats(required_keys[i]); ++ if (!is_valid) { ++ return false; ++ } ++ } ++ ++ is_valid = hinic3_check_port_key_is_complete(ip_proto); ++ if (!is_valid) { ++ return false; ++ } ++ return true; ++} ++ ++static int hinic3_sub_key_parse(struct unixctl_conn *conn, struct pcap_key_t *cap_key, ++ const char *key_name, char *value, struct ds *ds) ++{ ++ size_t i = 0; ++ int ret = 0; ++ pcap_sub_key_parse_func func = NULL; ++ for (i = 0; i < ARRAY_SIZE(g_input_key_parser); i++) { ++ struct pcap_sub_key_parser *item = &g_input_key_parser[i]; ++ if (strcmp(key_name, item->key_name) == 0) { ++ hinic3_update_input_key_stats(key_name); ++ func = item->func; ++ break; ++ } ++ } ++ ++ if (!func) { ++ hinic3_ds_put_format(ds, "%sIllegal parameter %s.\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); ++ return -1; ++ } ++ ++ ret = func(cap_key, key_name, value, ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "Parse %s failed!\n", key_name); ++ return -1; ++ } ++ return ret; ++} ++ ++ ++static int get_dmac_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ memcpy(g_input_key->dmac, cap_key->dmac, RTE_ETHER_ADDR_LEN); ++ return 0; ++} ++ ++static int get_smac_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ memcpy(g_input_key->smac, cap_key->smac, RTE_ETHER_ADDR_LEN); ++ return 0; ++} ++ ++static int get_eth_type_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->eth_type = cap_key->eth_type; ++ return 0; ++} ++ ++static int get_vxlan_vni_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->vni = cap_key->vxlan_vni; ++ return 0; ++} ++ ++static int get_icmp_type_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->icmp_type = cap_key->icmp_type; ++ return 0; ++} ++ ++static int get_icmp_code_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->icmp_code = cap_key->icmp_code; ++ return 0; ++} ++ ++static int get_icmp_id_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->icmp_id = cap_key->icmp_id; ++ return 0; ++} ++ ++static int get_sip_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->sip = cap_key->sip; ++ return 0; ++} ++ ++static int get_dip_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->dip = cap_key->dip; ++ return 0; ++} ++ ++static int get_sport_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->sport = cap_key->sport; ++ return 0; ++} ++ ++static int get_dport_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->dport = cap_key->dport; ++ return 0; ++} ++ ++static int get_ip_proto_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->ip_proto = cap_key->ip_proto; ++ return 0; ++} ++ ++static int get_vlan_key(struct input_key *g_input_key, struct pcap_key_t *cap_key) ++{ ++ g_input_key->vlan_id = cap_key->vlan_id; ++ return 0; ++} ++ ++static struct query_key_parse g_get_input_key[] = { ++ {"-dmac", get_dmac_key}, ++ {"-smac", get_smac_key}, ++ {"-eth_type", get_eth_type_key}, ++ {"-vlan", get_vlan_key}, ++ {"-sip", get_sip_key}, ++ {"-dip", get_dip_key}, ++ {"-sport", get_sport_key}, ++ {"-dport", get_dport_key}, ++ {"-ip_proto", get_ip_proto_key}, ++ {"-vxlan_vni", get_vxlan_vni_key}, ++ {"-icmp_type", get_icmp_type_key}, ++ {"-icmp_code", get_icmp_code_key}, ++ {"-icmp_id", get_icmp_id_key}, ++}; ++ ++static void get_input_key(const char *key, struct pcap_key_t *cap_key) ++{ ++ int ret; ++ size_t i; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ struct query_key_parse *item = NULL; ++ query_key_func func = NULL; ++ for (i = 0; i < ARRAY_SIZE(g_get_input_key); i++) { ++ item = &g_get_input_key[i]; ++ if (strcmp(key, item->key_name) == 0) { ++ func = item->func; ++ break; ++ } ++ } ++ ++ if (!func) { ++ hinic3_ds_put_format(&ds, "%sIllegal parameter!\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return; ++ } ++ ++ ret = func(&g_input_key, cap_key); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "get_key error\n"); ++ return; ++ } ++ return; ++} ++ ++int hinic3_input_key_parse(struct unixctl_conn *conn, struct pcap_key_t *cap_key, int argc, ++ const char *argv[], struct ds *ds) ++{ ++ int ret; ++ int work_argc = argc - 1; ++ int i = 1; ++ const char **work_argv = argv; ++ ++ memset(cap_key, 0, sizeof(struct pcap_key_t)); ++ if (work_argc < INPUT_KEY_MIN_NUM || work_argc > INPUT_KEY_MAX_NUM) { ++ HINIC3_LOG(ERR, FLOW, "Input parameter nums error.\n"); ++ hinic3_ds_put_format(ds, "%sInput parameter nums error.\n", HINIC3_UI_LEADING_SIGN_ERROR); ++ return -1; ++ } ++ ++ while (i < work_argc) { ++ ret = hinic3_sub_key_parse(conn, cap_key, (char *)work_argv[i], (char *)work_argv[i + 1], ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "key_parse error\n"); ++ return -1; ++ } ++ get_input_key(work_argv[i], cap_key); ++ i += ARGC_ADD_DOUBLE; ++ } ++ ++ return 0; ++} ++ ++static int get_mac_pattern(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_eth *eth_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_eth), HINIC3_COMMAND); ++ if (eth_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc eth_spec failed"); ++ return -1; ++ } ++ ++ memcpy(ð_spec->src, item_key->smac, RTE_ETHER_ADDR_LEN); ++ memcpy(ð_spec->dst, item_key->dmac, RTE_ETHER_ADDR_LEN); ++ eth_spec->type = item_key->eth_type; ++ ++ item->spec = eth_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_ETH; ++ ++ return 0; ++} ++ ++static int get_ip_pattern_ipv4(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_ipv4 *ipv4_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv4), HINIC3_COMMAND); ++ if (ipv4_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc ip_spec failed"); ++ return -1; ++ } ++ memcpy(&ipv4_spec->hdr.src_addr, &item_key->sip, sizeof(ipv4_spec->hdr.src_addr)); ++ memcpy(&ipv4_spec->hdr.dst_addr, &item_key->dip, sizeof(ipv4_spec->hdr.dst_addr)); ++ ipv4_spec->hdr.next_proto_id = item_key->ip_proto; ++ ++ item->spec = ipv4_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_IPV4; ++ ++ return 0; ++} ++ ++static int get_ip_pattern_ipv6(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_ipv6 *ipv6_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv6), HINIC3_COMMAND); ++ if (ipv6_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc ip_spec failed"); ++ return -1; ++ } ++ ++ memcpy(&ipv6_spec->hdr.src_addr, &item_key->sip, sizeof(item_key->sip)); ++ memcpy(&ipv6_spec->hdr.dst_addr, &item_key->dip, sizeof(item_key->dip)); ++ ipv6_spec->hdr.proto = item_key->ip_proto; ++ ++ item->spec = ipv6_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_IPV6; ++ ++ return 0; ++} ++ ++static int get_ip_pattern(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ if (item_key->eth_type == htons(ETH_TYPE_IP)) { ++ return get_ip_pattern_ipv4(item, item_key); ++ } else if (item_key->eth_type == htons(ETH_TYPE_IPV6)) { ++ return get_ip_pattern_ipv6(item, item_key); ++ } ++ return -1; ++} ++ ++static int get_port_pattern_udp(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_udp *udp_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_udp), HINIC3_COMMAND); ++ if (udp_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc port pattern udp_spec failed"); ++ return -1; ++ } ++ ++ udp_spec->hdr.dst_port = item_key->dport; ++ udp_spec->hdr.src_port = item_key->sport; ++ ++ item->spec = udp_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_UDP; ++ ++ return 0; ++} ++ ++static int get_port_pattern_tcp(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_tcp *tcp_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_tcp), HINIC3_COMMAND); ++ if (tcp_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc port pattern tcp_spec failed"); ++ return -1; ++ } ++ ++ tcp_spec->hdr.dst_port = item_key->dport; ++ tcp_spec->hdr.src_port = item_key->sport; ++ ++ item->spec = tcp_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_TCP; ++ ++ return 0; ++} ++ ++static int get_port_pattern_icmp(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_icmp *icmp_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_icmp), HINIC3_COMMAND); ++ if (icmp_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc port pattern icmp_spec failed"); ++ return -1; ++ } ++ ++ icmp_spec->hdr.icmp_type = item_key->icmp_type; ++ icmp_spec->hdr.icmp_code = item_key->icmp_code; ++ icmp_spec->hdr.icmp_ident = item_key->icmp_id; ++ ++ item->spec = icmp_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_ICMP; ++ ++ return 0; ++} ++ ++static int get_port_pattern_icmp6(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_icmp *icmp6_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_icmp), HINIC3_COMMAND); ++ if (icmp6_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc port pattern icmp6_spec failed"); ++ return -1; ++ } ++ ++ icmp6_spec->hdr.icmp_type = item_key->icmp_type; ++ icmp6_spec->hdr.icmp_code = item_key->icmp_code; ++ icmp6_spec->hdr.icmp_ident = item_key->icmp_id; ++ ++ item->spec = icmp6_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_ICMP6; ++ ++ return 0; ++} ++ ++static int get_port_pattern(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ switch (item_key->ip_proto) { ++ case IPPROTO_UDP: ++ return get_port_pattern_udp(item, item_key); ++ case IPPROTO_TCP: ++ return get_port_pattern_tcp(item, item_key); ++ case IPPROTO_ICMP: ++ return get_port_pattern_icmp(item, item_key); ++ case IPPROTO_ICMPV6: ++ return get_port_pattern_icmp6(item, item_key); ++ default: ++ return -1; ++ } ++ return -1; ++} ++ ++static int get_vxlan_pattern(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_vxlan *vxlan_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_vxlan), HINIC3_COMMAND); ++ if (vxlan_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc vlan_spec failed"); ++ return -1; ++ } ++ ++ uint8_t vni[HINIC3_VNI_ARR_SIZE]; ++ vni[HINIC3_VNI_ARR_HIGH] = (uint8_t)(item_key->vni & HINIC3_LOW_EIGHT_BIT_MASK); ++ vni[HINIC3_VNI_ARR_MID] = (uint8_t)(((item_key->vni) & HINIC3_MID_EIGHT_BIT_MASK) >> HINIC3_BIT_MID_MOVE_INDEX); ++ vni[HINIC3_VNI_ARR_LOW] = (uint8_t)(((item_key->vni) & HINIC3_HIGH_EIGHT_BIT_MASK) >> HINIC3_BIT_HIGH_MOVE_INDEX); ++ memcpy(vxlan_spec->vni, vni, sizeof(uint8_t) * HINIC3_VNI_ARR_SIZE); ++ ++ item->spec = vxlan_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_VXLAN; ++ ++ return 0; ++} ++ ++static int get_vlan_pattern(struct rte_flow_item *item, struct input_key *item_key) ++{ ++ struct rte_flow_item_vlan *vlan_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_vlan), HINIC3_COMMAND); ++ if (vlan_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "malloc vlan_spec failed"); ++ return -1; ++ } ++ ++ if (item_key->vlan_id == 0) { ++ vlan_spec->inner_type = 0; ++ } else { ++ vlan_spec->inner_type = item_key->inner_type; ++ vlan_spec->tci = htons(item_key->vlan_id); ++ } ++ ++ item->spec = vlan_spec; ++ item->type = RTE_FLOW_ITEM_TYPE_VLAN; ++ ++ return 0; ++} ++ ++pattern_func g_get_query_pattern[] = {get_vxlan_pattern, ++ get_mac_pattern, ++ get_ip_pattern, ++ get_port_pattern, ++ get_vlan_pattern, }; ++ ++static void hinic3_query_pattern_free(struct rte_flow_item *pattern) ++{ ++ int i = 0; ++ for (i = 0; i < HINIC3_INPUT_ITEM_MAX_NUM; i++) { ++ if (pattern[i].type != RTE_FLOW_ITEM_TYPE_END && pattern[i].spec == NULL) { ++ hinic3_free((void*)pattern[i].spec); ++ pattern[i].spec = NULL; ++ } ++ } ++} ++ ++int hinic3_get_pattern(struct rte_flow_item *pattern, struct input_key *item_key) ++{ ++ int i = 0; ++ int ret = 0; ++ for (i = 0; i < HINIC3_INPUT_ITEM_MAX_NUM; i++) { ++ ret = g_get_query_pattern[i](&pattern[i], item_key); ++ if (ret != 0) { ++ hinic3_query_pattern_free(pattern); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++void hinic3_dpak_query_ufid(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ int ret; ++ bool keys_is_complete; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ const struct rte_flow_attr *attr = NULL; ++ struct pcap_key_t cap_key = { 0 }; ++ struct rte_flow_item pattern[HINIC3_INPUT_ITEM_MAX_NUM] = {0}; ++ ++ struct hinic3_conntrack_full_key full_key = { 0 }; ++ uint64_t ufid = 0; ++ hinic3_init_input_key_stats(); ++ ret = hinic3_input_key_parse(conn, &cap_key, argc, argv, &ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "key parse failed\n"); ++ goto err_out; ++ } ++ g_input_key.inner_type = hinic3_get_inter_type(); ++ keys_is_complete = hinic3_check_querry_flow_key_is_complete(g_input_key.ip_proto); ++ if (!keys_is_complete) { ++ HINIC3_LOG(ERR, FLOW, "Query flow input keys are incomplete!\n"); ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Query flow input keys are incomplete!\n"); ++ goto err_out; ++ } ++ ret = hinic3_get_pattern(pattern, &g_input_key); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Get pattern failed.\n"); ++ goto err_out; ++ } ++ ++ ret = hinic3_flow_query_ufid(attr, pattern, &ufid, &full_key, &ds); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "query flow failed."); ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "Query flow failed.\n"); ++ hinic3_query_pattern_free(pattern); ++ goto err_out; ++ } ++ ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ hinic3_query_pattern_free(pattern); ++ *(int *)aux = 0; ++ return; ++ ++err_out: ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = -1; ++ return; ++} ++ ++void hinic3_input_key_help(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ query_cmd_usage_print(&ds); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} ++ ++void unixctl_hinic3_query_cmd_init(void) ++{ ++ struct pcap_cmd_t *p_cmd = &g_query_main_commands; ++ ++ hinic3_command_register(p_cmd->cmd, p_cmd->usage, p_cmd->min_args, p_cmd->max_args, p_cmd->cb, NULL); ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.h +new file mode 100644 +index 0000000..f797e1a +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_QUERY_FLOW_H ++#define HINIC3_QUERY_FLOW_H ++#include "hinic3_capture_utils.h" ++#include "rte_flow.h" ++ ++#define INPUT_KEY_MIN_NUM 20 ++#define INPUT_KEY_MAX_NUM 22 ++#define ARGC_ADD_DOUBLE 2 ++#define HINIC3_INPUT_ITEM_MAX_NUM 5 ++#define PCAP_MAX_PORT_ID 65535 ++#define QUERY_CMD_MIN_PARAM 1 ++#define QUERY_CMD_MAX_PARAM 28 ++#define HINIC3_ICMP_FLOW_MASK 8 ++ ++typedef int (*query_key_func)(struct input_key *g_input_key, struct pcap_key_t *cap_key); ++typedef int(*pattern_func)(struct rte_flow_item *, struct input_key *); ++ ++struct query_key_parse { ++ const char *key_name; ++ query_key_func func; ++}; ++ ++ ++void unixctl_hinic3_query_cmd_init(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c +new file mode 100644 +index 0000000..35fedef +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_log.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_iface_flow_api_record.h" ++#include "hinic3_query_flow.h" ++ ++#define HINIC3_LIVE_TIME_SHIFT 16u ++ ++static int hinic3_flow_query_sub(struct rte_flow *flow, const struct rte_flow_action actions[], void *data, ++ struct rte_flow_error *error) ++{ ++ struct rte_flow_query_count *stat = NULL; ++ stat = (struct rte_flow_query_count *)data; ++ stat->hits_set = 1; ++ stat->bytes_set = 1; ++ stat->hits = 0; ++ stat->bytes = 0; ++ stat->reserved = 0; ++ struct hash_table_node *rte_bucket = hinic3_get_flow_bucket(flow->flow_hash); ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ ++ if (flow->flags.is_mem_used == 0) { ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Flow query: Duplicate memory used."); ++ } ++ if (flow->flags.is_offload == 0) { ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Flow query: Flow not completely offload."); ++ } ++ if (stat->reset == 1) { ++ if (flow->sw_packets < flow->hw_packets) { ++ stat->hits = flow->hw_packets - flow->sw_packets; ++ } ++ ++ if (flow->sw_bytes < flow->hw_bytes) { ++ stat->bytes = flow->hw_bytes - flow->sw_bytes; ++ } ++ ++ flow->sw_packets = flow->hw_packets; ++ flow->sw_bytes = flow->hw_bytes; ++ } else { ++ stat->hits = flow->hw_packets; ++ stat->bytes = flow->hw_bytes; ++ } ++ ++ stat->reserved = flow->flags.live_time; ++ stat->reserved = stat->reserved << HINIC3_LIVE_TIME_SHIFT; ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return 0; ++} ++ ++int hinic3_flow_query_emc(struct rte_eth_dev *dev, struct rte_flow *flow, const struct rte_flow_action actions[], ++ void *data, struct rte_flow_error *error) ++{ ++ int ret; ++ hinic3_rlock_flush_all(); ++ ret = hinic3_flow_query_sub(flow, actions, data, error); ++ hinic3_runlock_flush_all(); ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.h +new file mode 100644 +index 0000000..653150e +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_QUERY_FLOW_H ++#define HINIC3_QUERY_FLOW_H ++#include "rte_ethdev.h" ++#include "rte_flow.h" ++#include "hinic3_flow_agent_public.h" ++ ++int hinic3_flow_query_emc(struct rte_eth_dev *dev, struct rte_flow *flow, const struct rte_flow_action actions[], ++ void *data, struct rte_flow_error *error); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c +new file mode 100644 +index 0000000..3349adf +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c +@@ -0,0 +1,68 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_vxlan.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++#define HINIC3_IPV6_ADDR_SIZE 4 ++#define HINIC3_VNI_LOW 0 ++#define HINIC3_VNI_MID 1 ++#define HINIC3_VNI_HIGH 2 ++#define HINIC3_VNI_LOW_MOVE 8 ++#define HINIC3_VNI_MID_MOVE 16 ++#define HINIC3_VNI_HIGH_MOVE 24 ++ ++static int hinic3_check_tunnel_decap_para(struct rte_flow_tunnel *tunnel, struct rte_flow_error *error) ++{ ++ if (error == NULL) { ++ HINIC3_LOG(ERR, FLOW, "Flow tunnel decap set: Invalid input parameter: error.\n"); ++ return -EINVAL; ++ } ++ ++ if (tunnel == NULL || tunnel->type != RTE_FLOW_ITEM_TYPE_VXLAN) { ++ HINIC3_LOG(ERR, FLOW, "Flow tunnel decap set: Invalid input parameter: tunnel.\n"); ++ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL, ++ "Flow tunnel decap set: Invalid input parameter: tunnel."); ++ } ++ ++ return 0; ++} ++ ++int hinic3_flow_tunnel_decap_set(struct rte_eth_dev *eth_dev, struct rte_flow_tunnel *tunnel, ++ struct rte_flow_action **pmd_actions, uint32_t *num_of_actions, struct rte_flow_error *error) ++{ ++ int ret; ++ struct hinic3_vtep_ip_set_args add_vxlan_args = { 0 }; ++ ++ ret = hinic3_check_tunnel_decap_para(tunnel, error); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ add_vxlan_args.ops = HINIC3_VTEP_ADD; ++ if (tunnel->is_ipv6) { ++ add_vxlan_args.dip.is_ipv6 = 1; ++ memcpy(add_vxlan_args.dip.ip_addr, tunnel->ipv6.dst_addr, sizeof(tunnel->ipv6.dst_addr)); ++ } else { ++ add_vxlan_args.dip.is_ipv6 = 0; ++ add_vxlan_args.dip.ip_addr[0] = tunnel->ipv4.dst_addr; ++ } ++ ++ ret = hinic3_global_set_vxlan_vtep(&add_vxlan_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "Flow tunnel decap set: Driver interface error.\n"); ++ return rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Flow tunnel decap set: Driver interface error."); ++ } ++ return 0; ++} ++ ++uint32_t hinic3_get_hiovs_vni(const uint8_t *vni) ++{ ++ uint32_t vni_dst = 0; ++ vni_dst = (vni[HINIC3_VNI_HIGH] << HINIC3_VNI_HIGH_MOVE) | ++ (vni[HINIC3_VNI_MID] << HINIC3_VNI_MID_MOVE) | ++ (vni[HINIC3_VNI_LOW] << HINIC3_VNI_LOW_MOVE); ++ return vni_dst; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.h +new file mode 100644 +index 0000000..2d920bf +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_VXLAN_H ++#define HINIC3_VXLAN_H ++ ++#include ++#include "rte_flow_driver.h" ++#include "rte_flow.h" ++#include "hinic3_log.h" ++#include "hinic3_iface_global.h" ++ ++int hinic3_flow_tunnel_decap_set(struct rte_eth_dev *eth_dev, struct rte_flow_tunnel *tunnel, ++ struct rte_flow_action **pmd_actions, uint32_t *num_of_actions, struct rte_flow_error *error); ++uint32_t hinic3_get_hiovs_vni(const uint8_t *vni); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c +new file mode 100644 +index 0000000..c995bee +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c +@@ -0,0 +1,256 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#include "hinic3_vxlan_dump.h" ++#include "hinic3_flow_dump_item.h" ++#include "hinic3_log.h" ++#include "hinic3_eth_packets.h" ++#include "hinic3_meminfo.h" ++ ++#define HINIC3_VXLAN_HEAD_MAX_ITEMS 6 ++#define HINIC3_VXLAN_IPV4_FLAG 0 ++#define HINIC3_VXLAN_IPV6_FLAG 1 ++ ++static int hinic3_vxlan_header_items_insert(struct rte_flow_item *vxlan_header_items, int header_max_length, ++ const struct rte_flow_item *src_item) ++{ ++ for (int i = 0; i < header_max_length - 1; ++i) { ++ if (vxlan_header_items[i].type == RTE_FLOW_ITEM_TYPE_END) { ++ memcpy(&vxlan_header_items[i], src_item, sizeof(struct rte_flow_item)); ++ return 0; ++ } ++ } ++ HINIC3_LOG(ERR, FLOW, "hinic3 vxlan dump: insert item into vxlan header failed"); ++ return -1; ++} ++ ++static int hinic3_get_eth_vxlan_items(struct rte_flow_item *vxlan_header_items, ++ const struct hinic3_flow_act_vxlan_gpe_header *vxlan_header) ++{ ++ struct rte_flow_item eth = { 0 }; ++ eth.type = RTE_FLOW_ITEM_TYPE_ETH; ++ ++ struct rte_flow_item_eth *mac = hinic3_calloc(1, sizeof(struct rte_flow_item_eth), HINIC3_FLOWS); ++ if (mac == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 vxlan dump: malloc eth memory failed"); ++ return -1; ++ } ++ ++ memcpy(&(mac->src), vxlan_header->smac, sizeof(uint8_t) * ETH_ALEN); ++ memcpy(&(mac->dst), vxlan_header->dmac, sizeof(uint8_t) * ETH_ALEN); ++ ++ if (vxlan_header->vlan_id != 0) { ++ mac->type = htons(ETH_TYPE_VLAN); ++ } else { ++ mac->type = vxlan_header->ip_version == 0 ? htons(ETH_TYPE_IP) : htons(ETH_TYPE_IPV6); ++ } ++ ++ eth.spec = (void *)mac; ++ int ret = hinic3_vxlan_header_items_insert(vxlan_header_items, HINIC3_VXLAN_HEAD_MAX_ITEMS, ð); ++ if (ret != 0) { ++ hinic3_free(mac); ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_get_vlan_vxlan_items(struct rte_flow_item *vxlan_header_items, ++ const struct hinic3_flow_act_vxlan_gpe_header *vxlan_header) ++{ ++ struct rte_flow_item vlan; ++ struct rte_flow_item_vlan *vlan_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_vlan), HINIC3_FLOWS); ++ if (vlan_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 vxlan dump: malloc vlan item memory failed"); ++ return -1; ++ } ++ ++ vlan_spec->tci = vxlan_header->vlan_id; ++ if (vxlan_header->ip_version == 0) { ++ vlan_spec->inner_type = htons(ETH_TYPE_IP); ++ } else if (vxlan_header->ip_version == 1) { ++ vlan_spec->inner_type = htons(ETH_TYPE_IPV6); ++ } ++ ++ vlan.spec = (void *)vlan_spec; ++ vlan.type = RTE_FLOW_ITEM_TYPE_VLAN; ++ int ret = hinic3_vxlan_header_items_insert(vxlan_header_items, HINIC3_VXLAN_HEAD_MAX_ITEMS, &vlan); ++ if (ret != 0) { ++ hinic3_free(vlan_spec); ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_get_ip_vxlan_items(struct rte_flow_item *vxlan_header_items, ++ const struct hinic3_flow_act_vxlan_gpe_header *vxlan_header) ++{ ++ struct rte_flow_item_ipv4 *ipv4 = NULL; ++ struct rte_flow_item_ipv6 *ipv6 = NULL; ++ struct rte_flow_item ip; ++ ++ if (vxlan_header->ip_version == 0) { ++ ipv4 = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv4), HINIC3_FLOWS); ++ if (ipv4 == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 vxlan dump: malloc ipv4 memory failed"); ++ return -1; ++ } ++ ipv4->hdr.dst_addr = vxlan_header->dip[0]; ++ ipv4->hdr.src_addr = vxlan_header->sip[0]; ++ ipv4->hdr.next_proto_id = IPPROTO_UDP; ++ ++ ip.type = RTE_FLOW_ITEM_TYPE_IPV4; ++ ip.spec = (void *)ipv4; ++ } else if (vxlan_header->ip_version == 1) { ++ ipv6 = hinic3_calloc(1, sizeof(struct rte_flow_item_ipv6), HINIC3_FLOWS); ++ if (ipv6 == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 vxlan dump: malloc ipv6 memory failed"); ++ return -1; ++ } ++ memcpy(&ipv6->hdr.src_addr, vxlan_header->sip, sizeof(vxlan_header->sip)); ++ memcpy(&ipv6->hdr.dst_addr, vxlan_header->dip, sizeof(vxlan_header->dip)); ++ ipv6->hdr.proto = IPPROTO_UDP; ++ ip.type = RTE_FLOW_ITEM_TYPE_IPV6; ++ ip.spec = (void *)ipv6; ++ } ++ ++ int ret = hinic3_vxlan_header_items_insert(vxlan_header_items, HINIC3_VXLAN_HEAD_MAX_ITEMS, &ip); ++ if (ret != 0) { ++ if (vxlan_header->ip_version == 0) { ++ hinic3_free(ipv4); ++ } else if (vxlan_header->ip_version == 1) { ++ hinic3_free(ipv6); ++ } ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_get_vlxan_header_udp_item(struct rte_flow_item *vxlan_header_items, ++ const struct hinic3_flow_act_vxlan_gpe_header *vxlan_header) ++{ ++ struct rte_flow_item udp; ++ struct rte_flow_item_udp *udp_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_udp), HINIC3_FLOWS); ++ if (udp_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 vxlan dump: malloc udp memory failed"); ++ return -1; ++ } ++ ++ udp_spec->hdr.dst_port = vxlan_header->dport; ++ udp_spec->hdr.src_port = vxlan_header->sport; ++ ++ udp.type = RTE_FLOW_ITEM_TYPE_UDP; ++ udp.spec = (void *)udp_spec; ++ ++ int ret = hinic3_vxlan_header_items_insert(vxlan_header_items, HINIC3_VXLAN_HEAD_MAX_ITEMS, &udp); ++ if (ret != 0) { ++ hinic3_free(udp_spec); ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_get_vlxan_header_vxlan_item(struct rte_flow_item *vxlan_header_items, ++ const struct hinic3_flow_act_vxlan_gpe_header *vxlan_header) ++{ ++ struct rte_flow_item vxlan; ++ vxlan.type = RTE_FLOW_ITEM_TYPE_VXLAN; ++ int ret; ++ struct rte_flow_item_vxlan *vxlan_spec = hinic3_calloc(1, sizeof(struct rte_flow_item_vxlan), HINIC3_FLOWS); ++ if (vxlan_spec == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 vxlan dump: malloc vxlan memory failed"); ++ return -1; ++ } ++ ++ memcpy(vxlan_spec, &vxlan_header->vxlan, sizeof(vxlan_header->vxlan)); ++ ++ vxlan.spec = (void *)vxlan_spec; ++ ++ ret = hinic3_vxlan_header_items_insert(vxlan_header_items, HINIC3_VXLAN_HEAD_MAX_ITEMS, &vxlan); ++ if (ret != 0) { ++ hinic3_free(vxlan_spec); ++ return -1; ++ } ++ return 0; ++} ++ ++rte_vxlan_encap hinic3_get_vxlan_gpe_header_items(struct hinic3_flow_act_vxlan_gpe_header *vxlan_header) ++{ ++ rte_vxlan_encap vxlan_headr = hinic3_calloc(1, sizeof(struct rte_flow_action_vxlan_encap), HINIC3_FLOWS); ++ if (vxlan_headr == NULL) { ++ HINIC3_LOG(ERR, FLOW, "FLOW DUMP: malloc for vxlan_headr failed"); ++ return NULL; ++ } ++ ++ struct rte_flow_item *vxlan_header_items = ++ hinic3_calloc(HINIC3_VXLAN_HEAD_MAX_ITEMS, sizeof(struct rte_flow_item), HINIC3_FLOWS); ++ if (vxlan_header_items == NULL) { ++ hinic3_free(vxlan_headr); ++ HINIC3_LOG(ERR, FLOW, "FLOW DUMP: malloc for vxlan_header_items failed"); ++ return NULL; ++ } ++ ++ int ret = 0; ++ ret = hinic3_get_eth_vxlan_items(vxlan_header_items, vxlan_header); ++ if (ret != 0) { ++ goto err; ++ } ++ ++ if (vxlan_header->vlan_id != 0) { ++ ret = hinic3_get_vlan_vxlan_items(vxlan_header_items, vxlan_header); ++ if (ret != 0) { ++ goto err; ++ } ++ } ++ ++ ret = hinic3_get_ip_vxlan_items(vxlan_header_items, vxlan_header); ++ if (ret != 0) { ++ goto err; ++ } ++ ++ ret = hinic3_get_vlxan_header_udp_item(vxlan_header_items, vxlan_header); ++ if (ret != 0) { ++ goto err; ++ } ++ ++ ret = hinic3_get_vlxan_header_vxlan_item(vxlan_header_items, vxlan_header); ++ if (ret != 0) { ++ goto err; ++ } ++ vxlan_headr->definition = vxlan_header_items; ++ return vxlan_headr; ++err: ++ HINIC3_LOG(ERR, FLOW, "FLOW DUMP: get vxlan headers failed"); ++ hinic3_free_one_flow_items(vxlan_header_items, HINIC3_VXLAN_HEAD_MAX_ITEMS); ++ hinic3_free(vxlan_header_items); ++ hinic3_free(vxlan_headr); ++ return NULL; ++} ++ ++void hinic3_free_vxlan_header(struct rte_flow_action_vxlan_encap *vxlan_header) ++{ ++ if (vxlan_header == NULL) { ++ return; ++ } ++ ++ struct rte_flow_item *vxlan_header_items = vxlan_header->definition; ++ if (vxlan_header_items == NULL) { ++ hinic3_free(vxlan_header); ++ return; ++ } ++ ++ for (int i = 0; i < HINIC3_VXLAN_HEAD_MAX_ITEMS; ++i) { ++ if (vxlan_header_items[i].type == RTE_FLOW_ITEM_TYPE_END) { ++ break; ++ } ++ if (vxlan_header_items[i].spec != NULL) { ++ hinic3_free(HINIC3_CONST_CAST(void *, vxlan_header_items[i].spec)); ++ vxlan_header_items[i].spec = NULL; ++ } ++ } ++ ++ hinic3_free(vxlan_header_items); ++ hinic3_free(vxlan_header); ++ vxlan_header = NULL; ++ ++ return; ++} +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.h +new file mode 100644 +index 0000000..ecb99c2 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_VXLAN_DUMP ++#define HINIC3_VXLAN_DUMP ++#include "rte_flow.h" ++#include "hinic3_message.h" ++typedef struct rte_flow_action_vxlan_encap* rte_vxlan_encap; ++rte_vxlan_encap hinic3_get_vxlan_gpe_header_items(struct hinic3_flow_act_vxlan_gpe_header *vxlan_header); ++void hinic3_free_vxlan_header(struct rte_flow_action_vxlan_encap *vxlan_header); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c +new file mode 100644 +index 0000000..a7d57b4 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c +@@ -0,0 +1,335 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "rte_log.h" ++#include "hinic3_util.h" ++#include "hinic3_init.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_set_userdata.h" ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_capture_main.h" ++#include "hinic3_check_thread_health_state.h" ++#include "hinic3_mtr.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_hugepage_meminfo.h" ++#include "hinic3_smap.h" ++#include "hinic3_string_util.h" ++#include "hinic3_vxlan.h" ++#include "hinic3_command.h" ++#include "hinic3_ds.h" ++#include "hinic3_mutex.h" ++#include "hinic3_packets.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_string_util.h" ++#include "hinic3_thread.h" ++#include "hinic3_smap.h" ++#include "hinic3_hmap.h" ++#include "hinic3_shash.h" ++#include "hinic3_unaligned.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_vdev.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_mpool_rte_flow.h" ++#include "hinic3_agent_cmd.h" ++#include "hinic3_error_stats.h" ++#include "hinic3_agent.h" ++ ++static bool g_agent_construct_init = false; ++ ++bool hinic3_get_agent_construct_init(void) ++{ ++ return g_agent_construct_init; ++} ++ ++struct rte_cfgfile *hinic3_cfgfile_load(const char *cfg_file) ++{ ++ if (cfg_file == NULL) { ++ return NULL; ++ } ++ ++ return rte_cfgfile_load(cfg_file, 0); ++} ++ ++int hinic3_is_softlink(const char *cfg_file) ++{ ++ int len = 0; ++ char file_buf[PATH_MAX] = {0}; ++ ++ len = readlink(cfg_file, file_buf, PATH_MAX); ++ if (len > 0) { ++ HINIC3_LOG(ERR, AGENT, "failed to init agent info dur to %s is a softlink file.", cfg_file); ++ return -1; ++ } ++ return 0; ++} ++ ++static void hinic3_solution_vitrio_wait() ++{ ++ int ret; ++ FILE *fp = NULL; ++ char net_ready_path[] = "/proc/sdi_net/net_ready"; ++ char value[] = "1"; ++ ++ fp = fopen(net_ready_path, "w+"); ++ if (fp == NULL) { ++ HINIC3_LOG(ERR, AGENT, "can not open net ready file"); ++ return; ++ } ++ ++ ret = fputs(value, fp); ++ if (ret <= 0) { ++ HINIC3_LOG(ERR, AGENT, "can not wirte net ready file, %d", ret); ++ } else { ++ HINIC3_LOG(INFO, AGENT, "solution vitrio net wait success, %d", ret); ++ } ++ ++ (void)fclose(fp); ++ return; ++} ++ ++static int hinic3_agent_init_mpool(void) ++{ ++ int ret; ++ ++ ret = hinic3_init_rte_flow_mpool(); ++ ++ return ret; ++} ++ ++static int hinic3_ops_init(void) ++{ ++ int ret; ++ ++ ret = hinic3_get_agent_value_from_config(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: get_agent_value_from_config failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ ret = hinic3_drv_ops_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: driver ops sysmbols init failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_pre_init(void) ++{ ++ int ret; ++ ++ ret = hinic3_log_init(); ++ if (ret != 0) { ++ perror("Agent_construct: log system init failed."); ++ return -1; ++ } ++ ++ (void)hinic3_meminfo_init(); ++ ret = hinic3_hugepage_meminfo_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: hugepage_meminfo_init failed, ret is %d.", ret); ++ return -1; ++ } ++ (void)hinic3_dev_init(); ++ ret = hinic3_ops_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: ops init failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ (void)hinic3_command_hmap_init(); ++ (void)hinic3_show_version(); ++ ++ ret = hinic3_driver_class_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: adaptor class init failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ ret = hinic3_agent_init_mpool(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: mpool init failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ (void)hinic3_rte_mbuf_dynfield_register(); ++ return 0; ++} ++ ++static void hinic3_pre_uninit(void) ++{ ++ hinic3_uninit_rte_flow_mpool(); ++ hinic3_driver_class_uninit(); ++ hinic3_dev_uninit(); ++ hinic3_hugepage_meminfo_uninit(); ++ hinic3_meminfo_uninit(); ++} ++ ++static int hinic3_driver_init(void) ++{ ++ int ret; ++ (void)hinic3_driver_log_init(); ++ ret = hinic3_pf_vdev_enable(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: pf enable failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ if (hinic3_device_mode_get() == DPU_MODE) { ++ (void)hinic3_solution_vitrio_wait(); ++ } ++ ++ (void)hinic3_global_cfg_set_when_restart(); ++ ++ return 0; ++} ++ ++static int hinic3_flow_module_init(void) ++{ ++ int ret; ++ ++ ret = hinic3_flow_agent_construct(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: flow agent construct failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ (void)hinic3_mirror_session_info_list_init(); ++ (void)hinic3_dump_flow_init(); ++ ++ return 0; ++} ++ ++static int hinic3_components_init(void) ++{ ++ int ret; ++ ++ ret = hinic3_flow_module_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: flow init failed, ret is %d.", ret); ++ return -1; ++ } ++ ++ ret = hinic3_pcap_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: pcap init failed with %d", ret); ++ return -1; ++ } ++ ++ ret = hinic3_queue_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: queue init failed with %d", ret); ++ return -1; ++ } ++ ++ (void)hinic3_ifindex_port_map_init(); ++ (void)hinic3_multi_meter_init(); ++ ++ return 0; ++} ++ ++static void hinic3_components_uninit(void) ++{ ++ (void)hinic3_flow_agent_destruct(); ++ ++ (void)hinic3_queue_uninit(); ++ (void)hinic3_pcap_uninit(); ++ (void)hinic3_ifindex_port_map_uninit(); ++} ++ ++static int hinic3_post_init(void) ++{ ++ int ret; ++ ++ (void)hinic3_agent_cmd_init(); ++ ret = hinic3_command_mgr_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: command mgr init failed with %d", ret); ++ return -1; ++ } ++ ++ ret = hinic3_polling_thread_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: check thread init failed with %d", ret); ++ return -1; ++ } ++ ++ ret = hinic3_forward_mode_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: set forward mode failed"); ++ return -1; ++ } ++ ++ ret = hinic3_bond_hash_policy_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: set hash policy failed"); ++ return -1; ++ } ++ ++ g_agent_construct_init = true; ++ (void)hinic3_vdev_port_module_init(); ++ return 0; ++} ++ ++static void hinic3_post_uninit(void) ++{ ++ (void)hinic3_vdev_port_module_uninit(); ++ g_agent_construct_init = false; ++ (void)hinic3_polling_thread_uninit(); ++ (void)hinic3_command_mgr_uninit(); ++} ++ ++__attribute__((constructor(HINIC3_PRIORITY_LAST))) int hinic3_agent_construct(void) ++{ ++ int ret; ++ ++ ret = hinic3_pre_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: pre init failed, ret is %d.", ret); ++ goto pre_err; ++ } ++ ++ ret = hinic3_driver_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: driver init failed, ret is %d.", ret); ++ goto pre_err; ++ } ++ ++ ret = hinic3_components_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: components init failed, ret is %d.", ret); ++ goto components_err; ++ } ++ ++ ret = hinic3_post_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Agent_construct: post init failed, ret is %d.", ret); ++ goto post_err; ++ } ++ ++ HINIC3_LOG(INFO, AGENT, "hinic3 agent construct finish, status: %u", g_agent_construct_init); ++ return 0; ++ ++post_err: ++ hinic3_post_uninit(); ++components_err: ++ hinic3_components_uninit(); ++pre_err: ++ hinic3_pre_uninit(); ++ return -1; ++} ++ ++__attribute__((destructor(HINIC3_PRIORITY_LAST))) void hinic3_agent_destruct(void) ++{ ++ hinic3_net_qos_clear(); ++ hinic3_post_uninit(); ++ hinic3_components_uninit(); ++ hinic3_pre_uninit(); ++} +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.h b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.h +new file mode 100644 +index 0000000..e256144 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.h +@@ -0,0 +1,57 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_AGENT_H ++#define HINIC3_AGENT_H ++ ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define AGENT_CFG_FILE "/etc/dpak/net/agent_config.ini" ++#define HINIC3_AGENT_COMPONENT_NAME "Component: dpak-runtime" ++#define HINIC3_AGENT_FEATURE_NAME "Feature: dpak-libovs" ++#define HINIC3_COMMAND_FEATURE_NAME "Feature: dpak-libovs/dpak-ovs-ctl" ++#define HINIC3_AGENT_COMPONENT_VERSION "Version: " ++#define HINIC3_AGENT_BUILD_VERSION "Sub version: " ++#define HINIC3_AGENT_PCI_NULL "\"\"" ++ ++#define DP_PACKET_CONTEXT_SIZE 64 ++ ++enum dp_packet_source { ++ DPBUF_MALLOC, ++ DPBUF_STACK, ++ DPBUF_STUB, ++ DPBUF_DPDK, ++ DPBUF_AFXDP, ++ DPBUF_18V = 0x5AA500FF, ++}; ++ ++struct dp_packet { ++ char rte_mbuf[128]; ++ enum dp_packet_source source; ++ uint16_t l2_pad_size; ++ uint16_t l2_5_ofs; ++ uint16_t l3_ofs; ++ uint16_t l4_ofs; ++ uint32_t cutlen; ++ uint32_t packet_type; ++ union { ++ char pkt_metadata[512]; ++ uint64_t data[DP_PACKET_CONTEXT_SIZE / 8]; ++ }; ++}; ++ ++int hinic3_is_softlink(const char *cfg_file); ++struct rte_cfgfile *hinic3_cfgfile_load(const char *cfg_file); ++bool hinic3_get_agent_construct_init(void); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c +new file mode 100644 +index 0000000..bfd4ac0 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c +@@ -0,0 +1,659 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_flow_agent.h" ++#include ++#include "rte_lcore.h" ++#include "rte_bus_vdev.h" ++#include "hinic3_util.h" ++#include "hiovs_api.h" ++#include "hinic3_log.h" ++#include "hinic3_init.h" ++#include "hinic3_message.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_thread.h" ++#include "hinic3_check_thread_health_state.h" ++#include ++#include "hinic3_iface_global.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_flow_agent_sync_stats.h" ++#include "hinic3_age_delete_flow.h" ++#include "hinic3_offload_flow.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_capture_main.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_agent_cmd_time.h" ++#include "hinic3_map.h" ++#include "hinic3_flow_agent_sync_stats.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_offload_flow.h" ++#include "hinic3_util.h" ++#include "hinic3_error_stats.h" ++ ++#define HINIC3_MAX_CORE_LENGTH 1024 ++#define NO_ENV_CORE_ERR (-2) ++#define MAX_PMD_CORE 32 ++ ++enum hinic3_thread_type { ++ HINIC3_OFFLOAD_THREAD_TYPE, ++ HINIC3_CONTROL_THREAD_TYPE, ++}; ++ ++struct hinic3_thread_type_in_env { ++ enum hinic3_thread_type type; ++ char thread_name[30]; ++}; ++ ++static struct hinic3_thread_type_in_env g_hinic3_thread_type[] = { ++ {HINIC3_OFFLOAD_THREAD_TYPE, "HINIC3_NIC_CORE_ISOLATION"}, ++ {HINIC3_CONTROL_THREAD_TYPE, "HINIC3_NIC_CTL_CORE_ISOLATION"}, ++}; ++ ++uint32_t g_offload_core_cnt = 0; ++uint32_t g_offload_core_list[HINIC3_MAX_OFFLOAD_CORE_CNT] = { 0 }; ++static struct hinic3_dp_extend_info *g_offload_extend_info = NULL; ++struct hinic3_flow_time g_flow_offload_time = { 0 }; ++static struct hinic3_rx_thread_ops g_rx_thread_ops; ++ ++static void hinic3_agent_init_thread_ops(void) ++{ ++ g_rx_thread_ops.rx_put_ack = hinic3_offload_thread_rx_put_ack; ++ g_rx_thread_ops.rx_age_notice = hinic3_thread_rx_hw_age_info; ++ g_rx_thread_ops.sync_stats = hinic3_sync_flow_statistics; ++ g_rx_thread_ops.del_sw_flow = NULL; ++} ++ ++static int hinic3_get_thread_core_from_env(enum hinic3_thread_type type, uint32_t thread_core[], ++ uint32_t max_core, uint32_t *active_num) ++{ ++ char *core_value = NULL; ++ char *saveptr = NULL; ++ char *endPtr = NULL; ++ char delim[] = ","; ++ uint32_t index = 0; ++ long nprocessors; ++ char core_values[HINIC3_MAX_CORE_LENGTH] = { 0 }; ++ ++ char *env_value = getenv(g_hinic3_thread_type[type].thread_name); ++ if (env_value == NULL) { ++ HINIC3_LOG(INFO, AGENT, "No offload cpu info in environment variables."); ++ return NO_ENV_CORE_ERR; ++ } ++ ++ nprocessors = sysconf(_SC_NPROCESSORS_ONLN); ++ if (nprocessors == -1) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get the number of processors."); ++ return -1; ++ } ++ ++ strcpy(core_values, env_value); ++ ++ core_value = strtok_r(core_values, delim, &saveptr); ++ while (core_value != NULL) { ++ thread_core[index] = strtoul(core_value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ HINIC3_LOG(ERR, AGENT, "Failed to parse CPU index."); ++ return -1; ++ } ++ ++ if (thread_core[index] >= nprocessors) { ++ HINIC3_LOG(ERR, AGENT, "Illegal CPU index %u.", thread_core[index]); ++ return -1; ++ } ++ ++ index++; ++ if (index >= max_core) { ++ HINIC3_LOG(WARNING, AGENT, "The num of offload cores for environment variables is out of Range %u.", max_core); ++ break; ++ } ++ core_value = strtok_r(NULL, delim, &saveptr); ++ } ++ *active_num = index; ++ return 0; ++} ++ ++static void *hinic3_offload_thread_main(void *args) ++{ ++ struct hinic3_offload_thread_data *thread = args; ++ struct hinic3_rx_thread_ops *ops = thread->dp_info->offload_thread_ops; ++ ++ enum check_thread_item_type check_thread = thread->thread_id + CONST_THREAD_NUM; ++ long long start = hinic3_time_msec(); ++ while (thread->exit == HINIC3_THREAD_NORMAL_STATUS) { ++ start = hinic3_thread_signal_increase(start, check_thread, HINIC3LOAD_THREAD_SIGNAL_INCREASE_INTER); ++ if (ops->rx_put_ack) { ++ ops->rx_put_ack(thread->thread_id, thread->dp_info); ++ } ++ if (ops->del_sw_flow) { ++ ops->del_sw_flow(thread->thread_id, thread->dp_info); ++ } ++ if (ops->sync_stats) { ++ ops->sync_stats(thread->thread_id, thread->dp_info); ++ } ++ ++ if (ops->rx_age_notice) { ++ ops->rx_age_notice(thread->thread_id, thread->dp_info); ++ } ++ } ++ return NULL; ++} ++ ++static void hinic3_stop_remain_offload_threads(struct hinic3_offload_thread_data *threads, uint32_t index) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < index; i++) { ++ threads[i].exit = HINIC3_THREAD_EXIT_STATUS; ++ pthread_join(threads[i].thread, NULL); ++ } ++} ++ ++static int hinic3_set_offload_thread_affinity(struct hinic3_dp_extend_info *dp_info, ++ struct hinic3_offload_thread_data *threads, uint32_t index) ++{ ++ int ret; ++ struct hinic3_cpu_mask forward_cpu_mask = hinic3_forward_cpu_mask_get(); ++ ++ if (dp_info->offload_num_in_env > 0) { ++ ret = hinic3_set_single_cpu_affinity(&threads[index].thread, dp_info->offload_thread_core[index]); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to bind offload cores based on environment variables."); ++ return -1; ++ } ++ } else { ++ ret = hinic3_set_single_cpu_affinity(&threads[index].thread, forward_cpu_mask.cpu_mask[index]); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to bind offload cores based on config."); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static void hinic3_set_thread_sync_index(uint32_t thread_num, uint32_t thread_index, ++ struct hinic3_offload_thread_data *thread) ++{ ++ if (thread_num == 0) { ++ return; ++ } ++ uint32_t scope = OFFLOAD_FLOW_BUCKETS / thread_num; ++ thread->cur_buk_idx = scope * thread_index; ++ thread->min_buk_idx = thread->cur_buk_idx; ++ thread->max_buk_idx = thread->min_buk_idx + scope; ++ if (thread->max_buk_idx > OFFLOAD_FLOW_BUCKETS) { ++ thread->max_buk_idx = OFFLOAD_FLOW_BUCKETS; ++ } ++} ++ ++static int hinic3_create_offload_threads(struct hinic3_dp_extend_info *dp_info) ++{ ++ int ret; ++ struct hinic3_flow_agent_db *hw_offload = dp_info->hw_offload; ++ uint32_t thread_num = hw_offload->forward_engine.cap.rx_thread_num; ++ ++ struct hinic3_offload_thread_data *threads = (struct hinic3_offload_thread_data *)hinic3_calloc(thread_num, ++ sizeof(struct hinic3_offload_thread_data), HINIC3_INIT); ++ if (threads == NULL) { ++ HINIC3_LOG(ERR, AGENT, "Flow agent create offload threads allocate failed."); ++ return -1; ++ } ++ ++ for (uint32_t index = 0; index < thread_num; index++) { ++ snprintf(threads[index].name, sizeof(threads[index].name), "hinic3_offload%u", index); ++ threads[index].exit = HINIC3_THREAD_NORMAL_STATUS; ++ threads[index].thread_id = index; ++ threads[index].dp_info = dp_info; ++ hinic3_set_thread_sync_index(thread_num, index, &threads[index]); ++ ++ ret = hinic3_thread_create(&threads[index].thread, threads[index].name, hinic3_offload_thread_main, ++ &threads[index], HINIC3_INIT); ++ if (ret != 0) { ++ hinic3_stop_remain_offload_threads(threads, index); ++ HINIC3_LOG(ERR, AGENT, "Flow offload thread create fail. index is %u, errno is %d", index, ret); ++ goto err; ++ } ++ ++ ret = hinic3_set_offload_thread_affinity(dp_info, threads, index); ++ if (ret != 0) { ++ hinic3_stop_remain_offload_threads(threads, index + 1); ++ goto err; ++ } ++ } ++ ++ dp_info->offload_threads = threads; ++ return 0; ++err: ++ hinic3_free(threads); ++ return -1; ++} ++ ++static void hinic3_stop_offload_threads(struct hinic3_dp_extend_info *dp_info) ++{ ++ if (dp_info == NULL) { ++ return; ++ } ++ ++ struct hinic3_flow_agent_db *hw_offload = dp_info->hw_offload; ++ uint32_t thread_num = hw_offload->forward_engine.cap.rx_thread_num; ++ struct hinic3_offload_thread_data *threads = dp_info->offload_threads; ++ uint32_t index; ++ ++ if (threads == NULL) { ++ return; ++ } ++ ++ for (index = 0; index < thread_num; index++) { ++ threads[index].exit = HINIC3_THREAD_EXIT_STATUS; ++ } ++ ++ for (index = 0; index < thread_num; index++) { ++ pthread_join(threads[index].thread, NULL); ++ } ++ ++ hinic3_free(threads); ++ dp_info->offload_threads = NULL; ++} ++ ++ ++static bool hinic3_flow_agent_init_forward_engine(struct hinic3_flow_agent_db *hw_offload) ++{ ++ if (hw_offload == NULL) { ++ return false; ++ } ++ ++ struct hinic3_forward_engine *engine = &hw_offload->forward_engine; ++ struct hinic3_flow_capability *cap = &engine->cap; ++ rte_atomic32_init(&engine->current_flow_size); ++ int ret = hinic3_flow_get_capability(cap); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Flow agent failed to get cap!"); ++ return false; ++ } ++ if (cap->rx_thread_num > HINIC3_RX_THREAD_MAX) { ++ HINIC3_LOG(ERR, AGENT, "rx thread num: %u is greater than max num: %d!", cap->rx_thread_num, ++ HINIC3_RX_THREAD_MAX); ++ return false; ++ } ++ ++ return true; ++} ++ ++static int hinic3_flow_agent_set_forward_mode(void) ++{ ++ uint8_t mode; ++ uint8_t hinic3_version = HINIC3_MODE_VERSION_01; ++ uint8_t escape_mode = HINIC3_ESCAPE_MODE_ALL_OFFLOAD; ++ uint8_t forward_mode = hinic3_forward_mode_get(); ++ ++ mode = (hinic3_version << HINIC3_MODE_VERSION_OFFSET) | (forward_mode << HINIC3_FORWARD_MODE_OFFSET) | ++ (escape_mode << HINIC3_ESCAPE_MODE_OFFSET); ++ ++ /* Set flow forward mode to hardware */ ++ int ret = hinic3_flow_set_forward_mode(mode); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to set forward mode to 0x%x", mode); ++ return ret; ++ } ++ return 0; ++} ++ ++static void hinic3_process_flow_put_callback_info(const struct hinic3_nlattr *args, ++ struct hinic3_flow_callback_info *callback_info) ++{ ++ hinic3_nlattr_itr nla = NULL; ++ ++ HINIC3_NLATTR_FOR_EACH(nla, args) { ++ int type = hinic3_nlattr_get_itr_type(nla); ++ switch (type) { ++ case HINIC3_FLOW_ARG_PUT_RESULT: ++ callback_info->flow_put_result = hinic3_nlattr_get_itr_u8(nla); ++ break; ++ case HINIC3_FLOW_ARG_NO_CT_UFID: ++ memcpy(&callback_info->no_ct_key, hinic3_nlattr_get_itr_data(nla), ++ sizeof(callback_info->no_ct_key)); ++ break; ++ case HINIC3_FLOW_ARG_TIME: ++ callback_info->start_t = hinic3_nlattr_get_itr_u64(nla); ++ break; ++ case HINIC3_FLOW_ARG_DP_HASH: ++ callback_info->is_dp_hash = true; ++ break; ++ case HINIC3_FLOW_ARG_FLOW_HASH: ++ callback_info->flow_hash = hinic3_nlattr_get_itr_u32(nla); ++ break; ++ case HINIC3_FLOW_ARG_MODIFY: ++ callback_info->is_modify = true; ++ break; ++ case HINIC3_FLOW_ARG_CT_UFID: ++ memcpy(&callback_info->ct_key, hinic3_nlattr_get_itr_data(nla), ++ sizeof(callback_info->ct_key)); ++ callback_info->is_ct = true; ++ break; ++ case HINIC3_FLOW_ARG_CT_DIRECT: ++ callback_info->reply = *(bool*)hinic3_nlattr_get_itr_data(nla); ++ break; ++ case HINIC3_FLOW_ARG_SW_UFID: ++ callback_info->mega_ufid = ++ *(hinic3_u128 *)hinic3_nlattr_get_itr_unspec(nla, sizeof(hinic3_u128)); ++ break; ++ default: ++ break; ++ } ++ } ++ return; ++} ++ ++static int hinic3_flow_agent_put_flow_callback(uint64_t ufid, struct hinic3_flow_callback_info *callback_info) ++{ ++ int ret; ++ ++ if (callback_info->flow_put_result != HINIC3_PUT_FLOW_SUCCESS) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_CALLBACK_FLOW_PUT_INFO, 1); ++ return -1; ++ } ++ ++ ret = hinic3_try_rlock_flush_all(); ++ if (ret == EBUSY) { ++ return 0; ++ } ++ if (ret != 0) { ++ return -1; ++ } ++ ++ ret = hinic3_set_ufid_in_rte_flow(callback_info, ufid); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_CALLBACK_SET_UFID_IN_RTE_FLOW, 1); ++ (void)hinic3_runlock_flush_all(); ++ return -1; ++ } ++ ++ (void)hinic3_runlock_flush_all(); ++ if (HINIC3_UNLIKELY(hinic3_is_offload_measure_alive() == true)) { ++ clock_t finish_t = clock(); ++ g_flow_offload_time.time = ((double)(finish_t - callback_info->start_t)) / CLOCKS_PER_SEC; ++ g_flow_offload_time.update = 1; ++ } ++ ++ hinic3_inc_offload_flow_nums(); ++ return 0; ++} ++ ++static int hinic3_flow_agent_modify_flow_callback(struct hinic3_flow_callback_info *callback_info) ++{ ++ if (callback_info->flow_put_result != HINIC3_PUT_FLOW_SUCCESS) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_CALLBACK_MODIFY_FLOW_PUT, 1); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_flow_agent_put_callback(uint64_t ufid, const struct hinic3_nlattr *args) ++{ ++ struct hinic3_flow_callback_info callback_info = { 0 }; ++ ++ hinic3_process_flow_put_callback_info(args, &callback_info); ++ ++ if (callback_info.is_modify) { ++ return hinic3_flow_agent_modify_flow_callback(&callback_info); ++ } ++ ++ return hinic3_flow_agent_put_flow_callback(ufid, &callback_info); ++} ++ ++static void hinic3_flow_agent_init_db(struct hinic3_flow_agent_db *hinic3_db) ++{ ++ rte_spinlock_init(&hinic3_db->forward_engine.lock); ++ rte_spinlock_init(&hinic3_db->operate_disable_lock); ++ hinic3_db->operate_disable = 0; ++ hinic3_db->max_block_num = UINT16_MAX; ++ hinic3_db->escape_mode = HINIC3_ESCAPE_MODE_ALL_OFFLOAD; ++ hinic3_db->vxlan_dst_port = DEFAULT_VXLAN_PORT; ++ hinic3_db->queue_num.total_count = hinic3_support_virtio_queue_get(); ++} ++ ++static int hinic3_flow_agent_init_common(struct hinic3_flow_agent_db *hinic3_db) ++{ ++ int ret = 0; ++ ++ (void)hinic3_flow_agent_init_db(hinic3_db); ++ if (!hinic3_flow_agent_init_forward_engine(hinic3_db)) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FORWARD_ENGINE_NOT_READY, 1); ++ HINIC3_LOG(ERR, AGENT, "Flow agent init forward engine failed."); ++ return -1; ++ } ++ ++ ret = hinic3_flow_agent_set_forward_mode(); ++ if (ret != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FORWARD_ENGINE_NOT_READY, 1); ++ HINIC3_LOG(ERR, AGENT, "Flow agent set forward_mode failed."); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static struct hinic3_flow_agent_db *hinic3_flow_agent_init_database() ++{ ++ int ret = 0; ++ struct hinic3_flow_agent_db *hinic3_db = hinic3_calloc(1, sizeof(struct hinic3_flow_agent_db), HINIC3_INIT); ++ if (hinic3_db == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "Flow agent init database allocate failed"); ++ return NULL; ++ } ++ ++ ret = hinic3_flow_agent_init_common(hinic3_db); ++ if (ret != 0) { ++ HINIC3_LOG(WARNING, AGENT, "Flow agent init common failed"); ++ ++ goto err; ++ } ++ ++ (void)hinic3_ufid_map_rte_flow_init(); ++ return hinic3_db; ++err: ++ hinic3_free(hinic3_db); ++ return NULL; ++} ++ ++static int hinic3_flow_callback(uint64_t ufid, const struct hinic3_dpif_flow_for_get *flow, ++ const struct hinic3_nlattr_obj *args, size_t args_len) ++{ ++ struct hinic3_nlattr nla_args; ++ hinic3_nlattr_itr nla = NULL; ++ uint8_t age = 0; ++ uint8_t flush_ret = 0xff; ++ int ret; ++ ++ hinic3_nlattr_init(&nla_args, HINIC3_CONST_CAST(struct hinic3_nlattr_obj *, args), args_len); ++ hinic3_nlattr_reset_itr(&nla_args, args_len); ++ HINIC3_NLATTR_FOR_EACH(nla, &nla_args) ++ { ++ int type = hinic3_nlattr_get_itr_type(nla); ++ switch (type) { ++ case HINIC3_FLOW_ARG_AGE: ++ age = hinic3_nlattr_get_itr_u8(nla); ++ break; ++ case HINIC3_FLOW_ARG_FLUSH_RESULT: ++ flush_ret = hinic3_nlattr_get_itr_u8(nla); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if (flush_ret != 0xff) { ++ ret = 0; ++ } else if (age != 0) { ++ ret = hinic3_flow_agent_age_callback(ufid, flow, &nla_args); ++ } else { ++ ret = hinic3_flow_agent_put_callback(ufid, &nla_args); ++ } ++ ++ return ret; ++} ++ ++int hinic3_flow_callback_register(void) ++{ ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_callback_register, HINIC3_DRV_FUNC_NO_PTR); ++ ops->hovs_flow_callback_register((hovs_flow_callback_t)hinic3_flow_callback); ++ return 0; ++} ++ ++int hinic3_get_thread_core_isolation(struct hinic3_dp_extend_info *dp_info) ++{ ++ int ret; ++ struct hinic3_cpu_mask forward_cpu_mask = hinic3_forward_cpu_mask_get(); ++ uint32_t offload_core_cnt = forward_cpu_mask.cpu_mask_invalid_num; ++ uint32_t offload_thread_num = hinic3_offload_thread_num_get(); ++ ++ /* 解析环境变量中的绑核信息,如果信息存在且解析失败则直接退出,如果绑核信息不存在,则使用配置文件进行绑核 */ ++ ret = hinic3_get_thread_core_from_env(HINIC3_OFFLOAD_THREAD_TYPE, dp_info->offload_thread_core, ++ HINIC3_RX_THREAD_NUM_MAX, &dp_info->offload_num_in_env); ++ if (ret != 0 && ret != NO_ENV_CORE_ERR) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get offload cores from environment variables."); ++ return -1; ++ } else if (ret == NO_ENV_CORE_ERR) { ++ HINIC3_LOG(INFO, AGENT, "No offload cores in environment variables."); ++ if (offload_core_cnt < offload_thread_num) { ++ HINIC3_LOG(ERR, AGENT, "Offload cores num in config %u is less than offload threads %u.", ++ offload_core_cnt, offload_thread_num); ++ return -1; ++ } ++ } else { ++ if (dp_info->offload_num_in_env < offload_thread_num) { ++ HINIC3_LOG(ERR, AGENT, "Offload cores num in environment variables %u is less than offload threads num %u.", ++ dp_info->offload_num_in_env, offload_thread_num); ++ return -1; ++ } ++ } ++ ++ ret = hinic3_get_thread_core_from_env(HINIC3_CONTROL_THREAD_TYPE, dp_info->control_thread_core, ++ HINIC3_RX_THREAD_NUM_MAX, &dp_info->control_num_in_env); ++ if (ret != 0 && ret != NO_ENV_CORE_ERR) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get control cores from environment variables."); ++ return -1; ++ } ++ ++ if (ret == NO_ENV_CORE_ERR) { ++ HINIC3_LOG(INFO, AGENT, "No control cores in environment variables."); ++ } ++ return 0; ++} ++ ++static int hinic3_flow_agent_init(struct hinic3_dp_extend_info *dp_info) ++{ ++ if (dp_info->hw_offload) { ++ HINIC3_LOG(WARNING, AGENT, "Flow agent database already initialized"); ++ return 0; ++ } ++ ++ int ret; ++ struct hinic3_flow_agent_db *hinic3_db = hinic3_flow_agent_init_database(); ++ if (hinic3_db == NULL) { ++ HINIC3_LOG(WARNING, AGENT, "Flow agent init database failed"); ++ return -1; ++ } ++ ++ hinic3_flow_callback_register(); ++ hinic3_agent_init_thread_ops(); ++ dp_info->offload_thread_ops = &g_rx_thread_ops; ++ dp_info->hw_offload = hinic3_db; ++ ++ ret = hinic3_get_thread_core_isolation(dp_info); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ HINIC3_LOG(INFO, AGENT, "Flow agent init successfully"); ++ return 0; ++} ++ ++int hinic3_flow_agent_construct(void) ++{ ++ int ret; ++ ++ g_offload_extend_info = (struct hinic3_dp_extend_info *)hinic3_calloc(1, sizeof(*g_offload_extend_info), HINIC3_INIT); ++ if (g_offload_extend_info == NULL) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 flow agent construct calloc memory failed."); ++ return -1; ++ } ++ ++ ret = hinic3_flow_agent_init(g_offload_extend_info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 flow agent init failed"); ++ goto err; ++ } ++ ++ ret = hinic3_create_offload_threads(g_offload_extend_info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "flow agent component construct failed"); ++ goto err; ++ } ++ return 0; ++err: ++ hinic3_free(g_offload_extend_info); ++ g_offload_extend_info = NULL; ++ return ret; ++} ++ ++void hinic3_flow_agent_destruct(void) ++{ ++ struct hinic3_flow_agent_db *hinic3_db = NULL; ++ if (g_offload_extend_info != NULL) { ++ hinic3_stop_offload_threads(g_offload_extend_info); ++ hinic3_db = g_offload_extend_info->hw_offload; ++ hinic3_free(hinic3_db); ++ g_offload_extend_info->hw_offload = NULL; ++ hinic3_free(g_offload_extend_info); ++ g_offload_extend_info = NULL; ++ } ++} ++ ++struct hinic3_dp_extend_info *hinic3_get_offload_extend_info(void) ++{ ++ return g_offload_extend_info; ++} ++ ++void hinic3_inc_offload_flow_nums(void) ++{ ++ if (g_offload_extend_info == NULL || g_offload_extend_info->hw_offload == NULL) { ++ return; ++ } ++ struct hinic3_flow_agent_db *hinic3_db = (struct hinic3_flow_agent_db *)(g_offload_extend_info->hw_offload); ++ rte_atomic32_inc(&hinic3_db->forward_engine.current_flow_size); ++ return; ++} ++ ++void hinic3_dec_offload_flow_nums(void) ++{ ++ if (g_offload_extend_info == NULL || g_offload_extend_info->hw_offload == NULL) { ++ return; ++ } ++ struct hinic3_flow_agent_db *hinic3_db = (struct hinic3_flow_agent_db *)(g_offload_extend_info->hw_offload); ++ rte_atomic32_dec(&hinic3_db->forward_engine.current_flow_size); ++ return; ++} ++ ++int32_t hinic3_get_offload_flow_nums(void) ++{ ++ struct hinic3_flow_agent_db *hinic3_db = (struct hinic3_flow_agent_db *)(g_offload_extend_info->hw_offload); ++ return rte_atomic32_read(&hinic3_db->forward_engine.current_flow_size); ++} ++ ++void hinic3_reset_offload_flow_nums(void) ++{ ++ struct hinic3_flow_agent_db *hinic3_db = (struct hinic3_flow_agent_db *)(g_offload_extend_info->hw_offload); ++ rte_atomic32_set(&hinic3_db->forward_engine.current_flow_size, 0); ++ return; ++} ++ ++struct hinic3_flow_time *hinic3_get_flow_offload_time(void) ++{ ++ return &g_flow_offload_time; ++} +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.h b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.h +new file mode 100644 +index 0000000..185caf0 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.h +@@ -0,0 +1,48 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FLOW_AGENT_H ++#define HINIC3_FLOW_AGENT_H ++ ++#include ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_error_stats.h" ++ ++#define HINIC3_THREAD_NAME_MAX 16 ++#define HINIC3_FLOW_LIVE_TIME 10000 /* ms */ ++#define HINIC3_MSEC_TO_SEC(XMS) ((XMS) / 1000) ++ ++#define CFG_INT_LEN 10 ++#define AGENT_SECTION "hwoff_agent" ++ ++struct hinic3_agent_hw_flow_del_context { ++ uint32_t target_flow_pps; ++ struct hinic3_flow_agent_db *hinic3_db; ++}; ++ ++struct hinic3_flow_time { ++ double time; /* 记录流表卸载时长 单位为s */ ++ uint32_t update; /* 更新标记,1表示更新,0表示此时间数据已被采集过,不是最新数据 */ ++}; ++ ++struct hinic3_ct_tcp_state { ++ uint32_t seqlo; /* Max sequence number sent, network order */ ++ uint32_t seqhi; /* Max the other end ACKd + win, network order */ ++ uint16_t max_win; /* Largest window (pre scaling), network order */ ++ uint8_t wscale; /* Window scaling factor */ ++ uint8_t state; /* see enum hinic3_ct_tcp_state_type */ ++ uint32_t r_seqhi; /* Max allowed seqence of reverse, network order */ ++}; ++ ++struct hinic3_dp_extend_info *hinic3_get_offload_extend_info(void); ++void hinic3_inc_offload_flow_nums(void); ++int hinic3_flow_agent_construct(void); ++void hinic3_flow_agent_destruct(void); ++void hinic3_dec_offload_flow_nums(void); ++int32_t hinic3_get_offload_flow_nums(void); ++void hinic3_reset_offload_flow_nums(void); ++int hinic3_flow_callback_register(void); ++struct hinic3_flow_time *hinic3_get_flow_offload_time(void); ++int hinic3_get_thread_core_isolation(struct hinic3_dp_extend_info *dp_info); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c +new file mode 100644 +index 0000000..8b76577 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c +@@ -0,0 +1,294 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include "rte_pci.h" ++#include "rte_bus.h" ++#include "rte_bus_pci.h" ++#include "hinic3_util.h" ++#include "hinic3_map.h" ++ ++#include "hinic3_log.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_message.h" ++#include "hinic3_vf_mgmt.h" ++#include "hinic3_agent.h" ++#include "hinic3_smap.h" ++#include "hinic3_parse_agent_config.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++#define HINIC3_DRV_SHARD_LIBRARY "/usr/lib64/libhiovs3.so" ++#define HINIC3_PF_ADDR_NULL_STR "XXXX:XX:XX.X" ++ ++static hinic3_lib_dlsym_uninit_cb_t g_hinic3_lib_dlsym_uninit_cb = NULL; ++static void *g_hinic3_drv_handler = NULL; ++static struct hinic3_drv_ops g_hinic3_drv_ops = {0}; ++ ++static struct hinic3_drv_ops_map g_hinic3_drv_ops_map[] = { ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_add), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_add_dynamic), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_del), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_get_capability), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_get_upcall_info), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_setup_upcall_queue), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_release_upcall_queue), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bond_mgmt_create), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bond_mgmt_delete), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bond_mgmt_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_etheraddr_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_etheraddr_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_mtu_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_statistics_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_statistics_flush), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bum_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bum_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bum_remove), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bum_clear), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_get_forward_mode), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_set_forward_mode), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_put), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_get_by_key), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_get_by_ufid), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_del_by_key), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_del_by_ufid), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_del_by_batch), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_flush), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_dump_start), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_dump_next), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_dump_done), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_get_maxflows), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_get_capability), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_statistics_flow_get_by_ufid), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_statistics_flow_flush_by_ufid), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_callback_register), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_cfg_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_cfg_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_statistics_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_statistics_flush), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_mml_lib), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_lib_init), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_lib_deinit), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_open_log), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_set_log_level), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_statistics_get_batch), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_statistics_get_all_batch), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_statistics_clear_batch), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_hqos_statistics_get_all_batch), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_hqos_statistics_clear_batch), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_vm_limit_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_vm_limit_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_vport_limit_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_vport_limit_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_rte_tx_burst), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_rte_rx_burst), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_pcie_list_query), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_vm_srtcm_limit_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_vm_srtcm_limit_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_net_limit_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_net_limit_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_set_upcall_priority), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_flow_limit_set), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_qos_flow_limit_get), ++ ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_bond_slave_statistics_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_set_usage_state), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_port_mgmt_get_usage_state), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_upcall_mtu_set), ++ ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_get_block_table_size), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_update), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_set_block_version), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_mgmt_get_block_version), ++}; ++ ++struct hinic3_drv_ops* hinic3_get_drv_ops(void) ++{ ++ return &g_hinic3_drv_ops; ++} ++ ++static void hinic3_drv_ops_uninit(void) ++{ ++ if (g_hinic3_drv_handler != NULL) { ++ memset(&g_hinic3_drv_ops, 0, sizeof(struct hinic3_drv_ops)); ++ dlclose(g_hinic3_drv_handler); ++ } ++} ++ ++static int hinic3_drv_ops_init_sub(void *handler, struct hinic3_drv_ops_map driver_map[], int size) ++{ ++ for (int index = 0; index < size; index++) { ++ if (*driver_map[index].func != NULL) { ++ continue; ++ } ++ ++ *driver_map[index].func = dlsym(handler, driver_map[index].name); ++ if (*driver_map[index].func == NULL) { ++ HINIC3_LOG(ERR, AGENT, "%s load func %s fail: %s", HINIC3_DRV_SHARD_LIBRARY, ++ driver_map[index].name, dlerror()); ++ ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++int hinic3_drv_ops_init(void) ++{ ++ int ret = 0; ++ void *handler = dlopen(HINIC3_DRV_SHARD_LIBRARY, RTLD_NOW); ++ if (handler == NULL) { ++ HINIC3_LOG(ERR, AGENT, "%s load err %s \n", HINIC3_DRV_SHARD_LIBRARY, dlerror()); ++ return -1; ++ } ++ ++ ret = hinic3_drv_ops_init_sub(handler, g_hinic3_drv_ops_map, ARRAY_SIZE(g_hinic3_drv_ops_map)); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 drv ops init: common api load failed"); ++ goto err; ++ } ++ ++ g_hinic3_drv_handler = handler; ++ hinic3_lib_dlsym_uninit_cb_register(hinic3_drv_ops_uninit); ++ return 0; ++err: ++ dlclose(handler); ++ return -1; ++} ++ ++/* this function will be called (ife & hinic) component load */ ++int hinic3_driver_class_init(void) ++{ ++ int ret; ++ ++ ret = hinic3_global_class_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_resource_init: hinic3_global_class_init failed with %d", ret); ++ return ret; ++ } ++ ++ ret = hinic3_flow_class_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_resource_init: hinic3_flow_class_init failed with %d", ret); ++ goto rollback_global; ++ } ++ ret = hinic3_port_class_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_resource_init: hinic3_port_class_init failed with %d", ret); ++ goto rollback_flow; ++ } ++ return 0; ++rollback_flow: ++ hinic3_flow_class_uninit(); ++rollback_global: ++ hinic3_global_class_uninit(); ++ HINIC3_LOG(ERR, AGENT, "hinic3_driver_class_init failed"); ++ return ret; ++} ++ ++/* this function will be called when thread stop and (ife & hinic) component unload */ ++void hinic3_driver_class_uninit(void) ++{ ++ hinic3_flow_class_uninit(); ++ hinic3_port_class_uninit(); ++ /* hiovs lib deinit */ ++ hinic3_global_class_uninit(); ++ ++ if (g_hinic3_lib_dlsym_uninit_cb != NULL) { ++ g_hinic3_lib_dlsym_uninit_cb(); ++ hinic3_lib_dlsym_uninit_cb_unregister(); ++ } ++} ++ ++void hinic3_lib_dlsym_uninit_cb_register(hinic3_lib_dlsym_uninit_cb_t cb) ++{ ++ g_hinic3_lib_dlsym_uninit_cb = cb; ++} ++ ++void hinic3_lib_dlsym_uninit_cb_unregister(void) ++{ ++ g_hinic3_lib_dlsym_uninit_cb = NULL; ++} ++ ++static int hinic3_pf_pci_length_check(const char *pf_pci_addr_str, struct rte_pci_addr *pf_pci_addr) ++{ ++ int pf_pci_addr_str_len = strlen(pf_pci_addr_str); ++ if ((pf_pci_addr_str_len != PCI_ID_DOMAIN_LENGTH) && (pf_pci_addr_str_len != PCI_ID_LENGTH)) { ++ HINIC3_LOG(ERR, AGENT, "the PCI address length is incorrect."); ++ return -1; ++ } ++ ++ int ret = rte_pci_addr_parse(pf_pci_addr_str, pf_pci_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "%s is not a valid pci address!", pf_pci_addr_str); ++ return -1; ++ } ++ ++ if ((pf_pci_addr->domain == 0) && (pf_pci_addr->bus == 0) && (pf_pci_addr->devid == 0) && ++ (pf_pci_addr->function == 0)) { ++ HINIC3_LOG(ERR, AGENT, "incorrect PCI address, pci addr is %s", pf_pci_addr_str); ++ return -1; ++ } ++ return 0; ++} ++ ++int hinic3_pf_vdev_enable(void) ++{ ++ int ret; ++ struct rte_pci_addr pf_pci_addr = { 0 }; ++ struct smap config; ++ struct smap unset_config; ++ char pci_str_buf[BUFSIZE_SHORT] = { 0 }; ++ const char *pf_pci_addr_str = hinic3_pf_pci_addr_get(); ++ ++ hinic3_smap_init(&config); ++ hinic3_smap_init(&unset_config); ++ if (pf_pci_addr_str[0] == '\0') { ++ hinic3_smap_add(&config, HINIC3_GLOBAL_CFG_ARG_VF_ENABLE_STR, HINIC3_PF_ADDR_NULL_STR, HINIC3_INIT); ++ } else { ++ ret = hinic3_pf_pci_length_check(pf_pci_addr_str, &pf_pci_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_pf_vdev_enable invalid pf %s", pf_pci_addr_str); ++ goto out; ++ } ++ ret = pci_addr_format(&pf_pci_addr, pci_str_buf, sizeof(pci_str_buf)); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "pf pco addr parse failed."); ++ goto out; ++ } ++ hinic3_smap_add(&config, HINIC3_GLOBAL_CFG_ARG_VF_ENABLE_STR, pci_str_buf, HINIC3_INIT); ++ } ++ ++ ret = hinic3_global_cfg_set(&config, &unset_config); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_pf_vdev_enable : fail to enable pf sriov"); ++ goto out; ++ } ++ ret = hinic3_hwpt_flavor_mgmt_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3_hwpt_flavor_mgmt_init : fail to init vf lists"); ++ goto out; ++ } ++ ++out: ++ hinic3_smap_destroy(&config); ++ hinic3_smap_destroy(&unset_config); ++ return ret; ++} ++ ++void hinic3_show_version(void) ++{ ++ HINIC3_LOG(INFO, AGENT, "%s", HINIC3_AGENT_COMPONENT_NAME); ++ HINIC3_LOG(INFO, AGENT, "%s", HINIC3_AGENT_FEATURE_NAME); ++ HINIC3_LOG(INFO, AGENT, "%s%s", HINIC3_AGENT_COMPONENT_VERSION, HINIC3_BUILD_MAJOR_VERSION); ++} +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.h b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.h +new file mode 100644 +index 0000000..94155f2 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2021 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_INIT_H ++#define HINIC3_INIT_H ++ ++#include ++#include ++#include "rte_pci.h" ++#include "rte_common.h" ++#include "rte_mempool.h" ++ ++#include "hinic3_drv.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef void (*hinic3_lib_dlsym_uninit_cb_t)(void); ++ ++int hinic3_drv_ops_init(void); ++struct hinic3_drv_ops* hinic3_get_drv_ops(void); ++int hinic3_driver_class_init(void); ++int hinic3_pf_vdev_enable(void); ++void hinic3_driver_class_uninit(void); ++void hinic3_lib_dlsym_uninit_cb_register(hinic3_lib_dlsym_uninit_cb_t cb); ++void hinic3_lib_dlsym_uninit_cb_unregister(void); ++void hinic3_show_version(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HINIC3_INIT_H */ +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c +new file mode 100644 +index 0000000..1098375 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c +@@ -0,0 +1,649 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_util.h" ++#include ++#include ++#include ++#include "hinic3_log.h" ++#include "hinic3_util.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_file_util.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_capture_utils.h" ++#include "hinic3_parse_agent_config.h" ++ ++#define QOS_SECTION "hwoff_QoS" ++#define AGENT_SECTION "hwoff_agent" ++#define AGENT_SECTION_OFFLOAD_THREAD_NUM_KEY "offload_thread_num" ++#define AGENT_SECTION_MAX_FLOW_NUM_KEY "max_flow_num" ++#define AGENT_SECTION_RUN_TIME_MODE "run_time_mode" ++#define AGENT_SECTION_BOND_HASH_POLICY "bond_hash_policy" ++#define AGENT_SECTION_FORWARD_CPU_MASK_KEY "forward_cpu_mask" ++#define AGENT_SECTION_CONTROL_CPU_MASK_KEY "control_cpu_mask" ++#define AGENT_SECTION_PF_PCI_ADDR_KEY "pf_pci_addr" ++#define AGENT_SECTION_DISK_USAGE_KEY "disk_usage" ++#define AGENT_SECTION_PCAP_CPU_KEY "pcap_cpu" ++#define MEMINFO_SECTION_ENABLE_HUGEPAGE_MEMINFO "hugepage_meminfo_statistic" ++#define PORT_SECTION "hwoff_port" ++#define PORT_SECTION_MAX_QUEUE_NUM_KEY "max_queue_num" ++#define PORT_SECTION_UPCALL_QUEUE_NUM_KEY "upcall_queue_num" ++#define PORT_SECTION_MBUF_SIZE_KEY "mbuf_size" ++#define PORT_SECTION_VDPA_FEATURE_KEY "vdpa_virtio_feature" ++#define PORT_SECTION_BOND_RX_DEPTH "bond_rx_depth" ++#define PORT_SECTION_BOND_TX_DEPTH "bond_tx_depth" ++#define PORT_SECTION_VPORT_RX_DEPTH "vport_rx_depth" ++#define PORT_SECTION_VPORT_TX_DEPTH "vport_tx_depth" ++#define PORT_SECTION_VIRTUAL_QUEUE_MULTIPLEX "virtual_queue_multiplex" ++#define FLOW_SECTION "hwoff_flow" ++#define FLOW_SECTION_FLOW_MAX_IDLE_KEY "flow_max_idle" ++#define FLOW_SECTION_AGENT_FORWARD_MOD_KEY "packet_forward_mode" ++#define PORT_VIRTIO_QUEUE_DEPTH "virtio_queue_depth" ++#define QOS_SECTION_QOS_LEVEL_KEY "qos_level" ++#define HINIC3_FORWARD_CPU_MASK_DEFAULT_NUM 0 ++#define HINIC3_CONTROL_CPU_MASK_DEFAULT_NUM 0 ++#define HINIC3F_MAX_CPU_MASK_LENGTH 1024 ++#define HINIC3_OFFLOAD_THREAD_INVALID_NUM 3 ++#define HINIC3_OFFLOAD_THREAD_DEFAULT_NUM 2 ++#define HINIC3_OFFLOAD_THREAD_NUM_MIN 1 ++#define HINIC3_OFFLOAD_THREAD_NUM_MAX 4 ++#define HINIC3_RUN_TIME_MODE_MIN 0 ++#define HINIC3_RUN_TIME_MODE_MAX 1 ++#define HINIC3_BOND_HASH_POLICY_MIN 0 ++#define HINIC3_BOND_HASH_POLICY_MAX 1 ++#define HINIC3_MAX_FLOW_DEFAULT_NUM 2 ++#define HINIC3_MAX_FLOW_NUM_MIN 1 ++#define HINIC3_MAX_FLOW_NUM_MAX 4 ++#define HINIC3_MAX_FLOW_NUM_INVALID 3 ++#define HINIC3_MAX_QUEUE_DEFAULT_NUM 4 ++#define HINIC3_MAX_QUEUE_LIMIT_DEFAULT_NUM 32 ++#define HINIC3_MAX_QUEUE_NUM_MIN 1 ++#define HINIC3_MAX_QUEUE_NUM_MAX 64 ++#define HINIC3_UPCALL_QUEUE_DEFAULT_NUM 4 ++#define HINIC3_UPCALL_QUEUE_NUM_MIN 1 ++#define HINIC3_UPCALL_QUEUE_NUM_MAX 16 ++#define HINIC3_MBUF_DEFAULT_SIZE 2176 ++#define HINIC3_FLOW_MAX_IDLE_MIN 30000 ++#define HINIC3_FLOW_MAX_IDLE_MAX 500000 ++#define HINIC3_DISK_USAGE_MIN 10 ++#define HINIC3_DISK_USAGE_MAX 10240 ++#define HINIC3_PCAP_CPU_MAX 23U ++ ++#define STR_TO_DEC_NUM 10 ++#define STR_U64_HEX_MAX_LENGTH 19 // 0XFFFFFFFFFFFFFFFF + '\0 ++#define HINIC3_MIN_BOND_DEPTH 256 ++#define HINIC3_MAX_BOND_DEPTH 8192 ++#define HINIC3_DEFAULT_BOND_DEPTH_OVS 1024 ++#define HINIC3_DEFAULT_BOND_DEPTH 2048 ++#define HINIC3_MIN_VPORT_DEPTH 256 ++#define HINIC3_MAX_VPORT_DEPTH 8192 ++#define HINIC3_DEFAULT_VPORT_DEPTH_OVS 512 ++#define HINIC3_DEFAULT_VPORT_DEPTH 1024 ++#define HINIC3_DEFAULT_DISK_USAGE 1024 ++#define HINIC3_DEFAULT_PORT_QUEUE_DEPTH 1024 ++#define HINIC3_PORT_QUEUE_DEPTH_USAGE_MIN 256 ++#define HINIC3_PORT_QUEUE_DEPTH_USAGE_MAX 4096 ++ ++static struct hinic3_init_arg g_agent_config_init_arg = { ++ .offload_thread_num = HINIC3_OFFLOAD_THREAD_DEFAULT_NUM, ++ .max_flow_num = HINIC3_MAX_FLOW_DEFAULT_NUM, ++ .forward_cpu_mask.cpu_mask = {0}, ++ .forward_cpu_mask.cpu_mask_invalid_num = HINIC3_FORWARD_CPU_MASK_DEFAULT_NUM, ++ .control_cpu_mask.cpu_mask = {0}, ++ .control_cpu_mask.cpu_mask_invalid_num = HINIC3_CONTROL_CPU_MASK_DEFAULT_NUM, ++ .pf_pci_addr = {0}, ++ .max_queue_num = HINIC3_MAX_QUEUE_DEFAULT_NUM, ++ .max_queue_num_limit = HINIC3_MAX_QUEUE_LIMIT_DEFAULT_NUM, ++ .upcall_queue_num = HINIC3_UPCALL_QUEUE_DEFAULT_NUM, ++ .mbuf_size = HINIC3_MBUF_DEFAULT_SIZE, ++ .flow_max_idle = HINIC3_FLOW_MAX_IDLE_DEFAULT, ++ .disk_usage = HINIC3_DEFAULT_DISK_USAGE, ++ .enable_hugepage_meminfo_statistic = false, ++ .virtual_queue_multiplex = 0, ++ .packet_forward_mode = 0, ++ .run_time_mode = 1, // 没有配置运行模式的情况下,默认为ovs模式 ++ .bond_hash_policy = 0, // 没有配置hash模式的情况下,默认为高效hash算法模式 ++ .pcap_cpu = 0, ++ .qos_level = {0}, ++ .virtio_queue_depth = HINIC3_DEFAULT_PORT_QUEUE_DEPTH ++}; ++ ++static struct hinic3_parse_num_type g_num_table[] = { ++ { ++ AGENT_SECTION, ++ AGENT_SECTION_OFFLOAD_THREAD_NUM_KEY, ++ HINIC3_OFFLOAD_THREAD_NUM_MIN, ++ HINIC3_OFFLOAD_THREAD_NUM_MAX, ++ &g_agent_config_init_arg.offload_thread_num, ++ }, ++ { ++ AGENT_SECTION, ++ AGENT_SECTION_MAX_FLOW_NUM_KEY, ++ HINIC3_MAX_FLOW_NUM_MIN, ++ HINIC3_MAX_FLOW_NUM_MAX, ++ &g_agent_config_init_arg.max_flow_num, ++ }, ++ { ++ AGENT_SECTION, ++ AGENT_SECTION_RUN_TIME_MODE, ++ HINIC3_RUN_TIME_MODE_MIN, ++ HINIC3_RUN_TIME_MODE_MAX, ++ &g_agent_config_init_arg.run_time_mode, ++ }, ++ { ++ AGENT_SECTION, ++ AGENT_SECTION_BOND_HASH_POLICY, ++ HINIC3_BOND_HASH_POLICY_MIN, ++ HINIC3_BOND_HASH_POLICY_MAX, ++ &g_agent_config_init_arg.bond_hash_policy, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_MAX_QUEUE_NUM_KEY, ++ HINIC3_MAX_QUEUE_NUM_MIN, ++ HINIC3_MAX_QUEUE_NUM_MAX, ++ &g_agent_config_init_arg.max_queue_num, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_UPCALL_QUEUE_NUM_KEY, ++ HINIC3_UPCALL_QUEUE_NUM_MIN, ++ HINIC3_UPCALL_QUEUE_NUM_MAX, ++ &g_agent_config_init_arg.upcall_queue_num, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_MBUF_SIZE_KEY, ++ 0, ++ UINT16_MAX, ++ &g_agent_config_init_arg.mbuf_size, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_BOND_RX_DEPTH, ++ HINIC3_MIN_BOND_DEPTH, ++ HINIC3_MAX_BOND_DEPTH, ++ &g_agent_config_init_arg.bond_rx_depth, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_BOND_TX_DEPTH, ++ HINIC3_MIN_BOND_DEPTH, ++ HINIC3_MAX_BOND_DEPTH, ++ &g_agent_config_init_arg.bond_tx_depth, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_VPORT_RX_DEPTH, ++ HINIC3_MIN_VPORT_DEPTH, ++ HINIC3_MAX_VPORT_DEPTH, ++ &g_agent_config_init_arg.vport_rx_depth, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_VPORT_TX_DEPTH, ++ HINIC3_MIN_VPORT_DEPTH, ++ HINIC3_MAX_VPORT_DEPTH, ++ &g_agent_config_init_arg.vport_tx_depth, ++ }, ++ { ++ PORT_SECTION, ++ PORT_SECTION_VIRTUAL_QUEUE_MULTIPLEX, ++ HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MIN, ++ HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MAX, ++ &g_agent_config_init_arg.virtual_queue_multiplex, ++ }, ++ { ++ FLOW_SECTION, ++ FLOW_SECTION_FLOW_MAX_IDLE_KEY, ++ HINIC3_FLOW_MAX_IDLE_MIN, ++ HINIC3_FLOW_MAX_IDLE_MAX, ++ &g_agent_config_init_arg.flow_max_idle, ++ }, ++ { ++ AGENT_SECTION, ++ FLOW_SECTION_AGENT_FORWARD_MOD_KEY, ++ HINIC3_FORWARD_MODE_BANDWIDTH, ++ HINIC3_FORWARD_MODE_LATENCY, ++ &g_agent_config_init_arg.packet_forward_mode, ++ }, ++}; ++ ++static int hinic3_parse_virtio_queue_depth(struct rte_cfgfile *rte_file) ++{ ++ char* end_ptr = NULL; ++ uint16_t virtio_queue_depth = 0; ++ const char *queue_depth_str = rte_cfgfile_get_entry(rte_file, PORT_SECTION, PORT_VIRTIO_QUEUE_DEPTH); ++ if (queue_depth_str == NULL) { ++ HINIC3_LOG(INFO, AGENT, "%s is not set", PORT_VIRTIO_QUEUE_DEPTH); ++ return 0; ++ } ++ ++ virtio_queue_depth = (uint16_t)strtoul(queue_depth_str, &end_ptr, STR_TO_DEC_NUM); ++ if (end_ptr == NULL || *end_ptr != '\0') { ++ HINIC3_LOG(INFO, AGENT, ++ "port_queue_depth value %u is invalid, use default value 1024.\n", virtio_queue_depth); ++ return -1; ++ } ++ ++ if (virtio_queue_depth < HINIC3_PORT_QUEUE_DEPTH_USAGE_MIN || ++ virtio_queue_depth > HINIC3_PORT_QUEUE_DEPTH_USAGE_MAX) { ++ HINIC3_LOG(INFO, AGENT, ++ "port_queue_depth value %u is out of range, use default value 1024.\n", virtio_queue_depth); ++ return -1; ++ } ++ ++ g_agent_config_init_arg.virtio_queue_depth = virtio_queue_depth; ++ return 0; ++} ++ ++static void hinic3_parse_config_num(struct rte_cfgfile *rte_file, uint32_t mod_id) ++{ ++ uint32_t config_num; ++ const char *config_num_str = NULL; ++ char *end_ptr = NULL; ++ config_num_str = rte_cfgfile_get_entry(rte_file, g_num_table[mod_id].section_name, g_num_table[mod_id].name); ++ if (config_num_str == NULL) { ++ HINIC3_LOG(INFO, AGENT, "%s not set, use default value %u \n", g_num_table[mod_id].name, ++ *g_num_table[mod_id].num); ++ return; ++ } ++ ++ config_num = (uint32_t)strtoul(config_num_str, &end_ptr, STR_TO_DEC_NUM); ++ if (end_ptr == NULL || *end_ptr != '\0' || (config_num < g_num_table[mod_id].min_num) || ++ (config_num > g_num_table[mod_id].max_num)) { ++ HINIC3_LOG(INFO, AGENT, "%s %u is invalid, use default value %u \n", g_num_table[mod_id].name, config_num, ++ *g_num_table[mod_id].num); ++ return; ++ } ++ ++ *g_num_table[mod_id].num = config_num; ++ HINIC3_LOG(INFO, AGENT, "%s set, value %u \n", g_num_table[mod_id].name, *g_num_table[mod_id].num); ++} ++ ++static int hinic3_split_cpu_mask(const char *cpu_mask_type, uint32_t *cpu_mask_num, uint32_t *invalid_size) ++{ ++ char *core_value = NULL; ++ char *saveptr = NULL; ++ char *endPtr = NULL; ++ char delim[] = ","; ++ char core_values[HINIC3F_MAX_CPU_MASK_LENGTH] = { 0 }; ++ int index = 0; ++ uint32_t config_num; ++ ++ if (strlen(cpu_mask_type) > sizeof(core_values)) { ++ HINIC3_LOG(ERR, AGENT, "cpu_mask_type is too long."); ++ return -1; ++ } ++ strcpy(core_values, cpu_mask_type); ++ ++ core_value = strtok_r(core_values, delim, &saveptr); ++ while (core_value != NULL) { ++ config_num = strtoul(core_value, &endPtr, STR_TO_DEC_NUM); ++ if (endPtr == NULL || *endPtr != '\0') { ++ HINIC3_LOG(ERR, AGENT, "Failed to parse CPU index."); ++ return -1; ++ } ++ cpu_mask_num[index] = config_num; ++ core_value = strtok_r(NULL, delim, &saveptr); ++ *invalid_size = ++index; ++ if (*invalid_size > HINIC3_CPU_MASK_NUM) { ++ *invalid_size = HINIC3_CPU_MASK_NUM; ++ HINIC3_LOG(INFO, AGENT, "The num of cpu_mask is out of Range"); ++ return 0; ++ } ++ } ++ ++ return 0; ++} ++ ++static int hinic3_prase_cpu_mask(struct rte_cfgfile *inifile, const char *name, struct hinic3_cpu_mask *cpu_mask_type) ++{ ++ int ret = 0; ++ long nprocessors; ++ nprocessors = sysconf(_SC_NPROCESSORS_ONLN); ++ if (nprocessors == -1) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get the number of processors."); ++ return -1; ++ } ++ ++ const char *config_num_str = NULL; ++ config_num_str = rte_cfgfile_get_entry(inifile, AGENT_SECTION, name); ++ if (config_num_str == NULL) { ++ HINIC3_LOG(INFO, AGENT, "%s not set, use default value\n", name); ++ return 0; ++ } ++ ++ ret = hinic3_split_cpu_mask(config_num_str, cpu_mask_type->cpu_mask, &cpu_mask_type->cpu_mask_invalid_num); ++ if (ret != 0) { ++ HINIC3_LOG(INFO, AGENT, "%s not set, use default value\n", name); ++ return 0; ++ } ++ ++ for (uint32_t index = 0; index < cpu_mask_type->cpu_mask_invalid_num; index++) { ++ if (cpu_mask_type->cpu_mask[index] >= nprocessors) { ++ HINIC3_LOG(ERR, AGENT, "Illegal CPU index %u.", cpu_mask_type->cpu_mask[index]); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int hinic3_init_cpu_mask(struct rte_cfgfile *inifile) ++{ ++ int ret = 0; ++ ret = hinic3_prase_cpu_mask(inifile, AGENT_SECTION_FORWARD_CPU_MASK_KEY, &g_agent_config_init_arg.forward_cpu_mask); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ ret = hinic3_prase_cpu_mask(inifile, AGENT_SECTION_CONTROL_CPU_MASK_KEY, &g_agent_config_init_arg.control_cpu_mask); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_parse_pf_pci_addr(struct rte_cfgfile *inifile) ++{ ++ const char *pci_addr = rte_cfgfile_get_entry(inifile, AGENT_SECTION, AGENT_SECTION_PF_PCI_ADDR_KEY); ++ if (pci_addr == NULL || strlen(pci_addr) > HINIC3_PCI_MAX_LEN) { ++ memset(g_agent_config_init_arg.pf_pci_addr, '\0', HINIC3_PCI_MAX_LEN); ++ HINIC3_LOG(INFO, AGENT, "pf_pci_addr is NULL"); ++ return 0; ++ } ++ ++ if ((strncmp(pci_addr, HINIC3_AGENT_PCI_NULL, strlen(pci_addr) + 1) == 0)) { ++ memset(g_agent_config_init_arg.pf_pci_addr, '\0', HINIC3_PCI_MAX_LEN); ++ HINIC3_LOG(INFO, AGENT, "pf_pci_addr is NULL"); ++ return 0; ++ } ++ ++ if (strlen(pci_addr) != PCI_ADDR_LEN) { ++ HINIC3_LOG(ERR, AGENT, "the pci address length is %lu!", strlen(pci_addr)); ++ return -1; ++ } ++ strcpy(g_agent_config_init_arg.pf_pci_addr, pci_addr); ++ return 0; ++} ++ ++static int hinic3_parse_vpda_feature(struct rte_cfgfile *inifile) ++{ ++ char* end_ptr = NULL; ++ uint64_t vpda_feature = 0; ++ const char *vdpa_feature_str = rte_cfgfile_get_entry(inifile, PORT_SECTION, PORT_SECTION_VDPA_FEATURE_KEY); ++ if (vdpa_feature_str == NULL) { ++ HINIC3_LOG(INFO, AGENT, "%s is not set", PORT_SECTION_VDPA_FEATURE_KEY); ++ return 0; ++ } ++ ++ vpda_feature = strtoull(vdpa_feature_str, &end_ptr, STR_TO_HEX_BASE); ++ if (!end_ptr || *end_ptr != '\0' || errno == ERANGE || vpda_feature == 0 || ++ vdpa_feature_str[0] == '-') { ++ HINIC3_LOG(ERR, AGENT, "Failed to parse %s, please check agent_config", PORT_SECTION_VDPA_FEATURE_KEY); ++ return -1; ++ } ++ ++ g_agent_config_init_arg.vdpa_virtio_feature = vpda_feature; ++ return 0; ++} ++ ++static int hinic3_parse_disk_usage(struct rte_cfgfile *rte_file) ++{ ++ uint32_t disk_usage_config; ++ const char *disk_usage_str = NULL; ++ char *end_ptr = NULL; ++ uint64_t available_size; ++ ++ available_size = hinic3_get_partition_free_space_size(); ++ if (available_size < HINIC3_DISK_USAGE_MIN) { ++ HINIC3_LOG(ERR, AGENT, "Disk space is not enough, available size is %lu, need %u", available_size, ++ HINIC3_DISK_USAGE_MIN); ++ return -1; ++ } ++ ++ disk_usage_str = rte_cfgfile_get_entry(rte_file, AGENT_SECTION, AGENT_SECTION_DISK_USAGE_KEY); ++ if (disk_usage_str == NULL) { ++ g_agent_config_init_arg.disk_usage = ++ available_size > HINIC3_DEFAULT_DISK_USAGE ? HINIC3_DEFAULT_DISK_USAGE : available_size; ++ HINIC3_LOG(INFO, AGENT, "disk_usage not set, use value %u.\n", g_agent_config_init_arg.disk_usage); ++ return 0; ++ } ++ ++ disk_usage_config = (uint32_t)strtoul(disk_usage_str, &end_ptr, STR_TO_DEC_NUM); ++ if (end_ptr == NULL || *end_ptr != '\0' || (disk_usage_config < HINIC3_DISK_USAGE_MIN) || ++ (disk_usage_config > HINIC3_DISK_USAGE_MAX)) { ++ g_agent_config_init_arg.disk_usage = ++ available_size > HINIC3_DEFAULT_DISK_USAGE ? HINIC3_DEFAULT_DISK_USAGE : available_size; ++ HINIC3_LOG(INFO, AGENT, "disk_usage %u is invalid, use value %u.\n", disk_usage_config, ++ g_agent_config_init_arg.disk_usage); ++ return 0; ++ } ++ ++ if (disk_usage_config > available_size) { ++ g_agent_config_init_arg.disk_usage = available_size; ++ HINIC3_LOG(WARNING, AGENT, ++ "The partition does not have enough space left, use available size %lu as disk_usage.\n", available_size); ++ return 0; ++ } ++ ++ g_agent_config_init_arg.disk_usage = disk_usage_config; ++ ++ HINIC3_LOG(INFO, AGENT, "disk_usage set, value %u \n", disk_usage_config); ++ return 0; ++} ++ ++static int hinic3_parse_pcap_cpu_config(struct rte_cfgfile *rte_file) ++{ ++ char *end_ptr = NULL; ++ const char *pcap_cpu_str = NULL; ++ uint32_t pcap_cpu = 0; ++ long nprocessors; ++ ++ nprocessors = sysconf(_SC_NPROCESSORS_ONLN); ++ if (nprocessors == -1) { ++ HINIC3_LOG(ERR, AGENT, "Failed to get the number of processors."); ++ return -1; ++ } ++ ++ pcap_cpu_str = rte_cfgfile_get_entry(rte_file, AGENT_SECTION, AGENT_SECTION_PCAP_CPU_KEY); ++ if (pcap_cpu_str == NULL) { ++ HINIC3_LOG(INFO, AGENT, "%s not set, use default value\n", AGENT_SECTION_PCAP_CPU_KEY); ++ return 0; ++ } ++ ++ pcap_cpu = (uint32_t)strtoul(pcap_cpu_str, &end_ptr, STR_TO_DEC_NUM); ++ if (end_ptr == NULL || *end_ptr != '\0' || (pcap_cpu > HINIC3_PCAP_CPU_MAX)) { ++ HINIC3_LOG(INFO, AGENT, "pcap_cpu value %u is invalid or out of range, use default value.\n", pcap_cpu); ++ return 0; ++ } ++ ++ if (pcap_cpu >= nprocessors) { ++ HINIC3_LOG(INFO, AGENT, "Ilegal cpu core id %u for pcap_cpu, use default value.\n", pcap_cpu); ++ return 0; ++ } ++ ++ g_agent_config_init_arg.pcap_cpu = pcap_cpu; ++ HINIC3_LOG(INFO, AGENT, "pcap_cpu set, value %u \n", pcap_cpu); ++ return 0; ++} ++ ++struct hinic3_init_arg *hinic3_get_init_arg(void) ++{ ++ return &g_agent_config_init_arg; ++} ++ ++void hinic3_set_config_value(void) ++{ ++ struct hinic3_init_arg *arg = hinic3_get_fixed_config(); ++ g_agent_config_init_arg.add_port_when_init = arg->add_port_when_init; ++ g_agent_config_init_arg.is_dpu = arg->is_dpu; ++ g_agent_config_init_arg.hiovs_mode = arg->hiovs_mode; ++ g_agent_config_init_arg.forward_mode = arg->forward_mode; ++ g_agent_config_init_arg.vdpa_virtio_feature = arg->vdpa_virtio_feature; ++ g_agent_config_init_arg.status_packet_upcall = arg->status_packet_upcall; ++ g_agent_config_init_arg.support_virtio_queue = arg->support_virtio_queue; ++ g_agent_config_init_arg.max_flow_num_limit = arg->max_flow_num_limit; ++ g_agent_config_init_arg.max_queue_num_limit = arg->max_queue_num_limit; ++ g_agent_config_init_arg.query_bdf_type = arg->query_bdf_type; ++ g_agent_config_init_arg.support_port_hot_plug = arg->support_port_hot_plug; ++ g_agent_config_init_arg.support_pf_port = arg->support_pf_port; ++ g_agent_config_init_arg.support_vf_port = arg->support_vf_port; ++ g_agent_config_init_arg.is_virtio_queue_depth_set = arg->is_virtio_queue_depth_set; ++} ++ ++static void hinic3_parse_meminfo_feature(struct rte_cfgfile *inifile) ++{ ++ const char *stage = rte_cfgfile_get_entry(inifile, AGENT_SECTION, MEMINFO_SECTION_ENABLE_HUGEPAGE_MEMINFO); ++ if (stage == NULL) { ++ HINIC3_LOG(INFO, AGENT, "%s is not set, use default value enable", MEMINFO_SECTION_ENABLE_HUGEPAGE_MEMINFO); ++ return; ++ } ++ ++ if (strcmp(stage, "enable") == 0) { ++ g_agent_config_init_arg.enable_hugepage_meminfo_statistic = true; ++ } else if (strcmp(stage, "disable") == 0) { ++ g_agent_config_init_arg.enable_hugepage_meminfo_statistic = false; ++ } else { ++ HINIC3_LOG(WARNING, AGENT, "%s parse wrong value, use default value enable", ++ MEMINFO_SECTION_ENABLE_HUGEPAGE_MEMINFO); ++ } ++} ++ ++static void hinic3_init_agent_config_arg(void) ++{ ++ g_agent_config_init_arg.bond_rx_depth = HINIC3_DEFAULT_BOND_DEPTH_OVS; ++ g_agent_config_init_arg.bond_tx_depth = HINIC3_DEFAULT_BOND_DEPTH_OVS; ++ g_agent_config_init_arg.vport_rx_depth = HINIC3_DEFAULT_VPORT_DEPTH_OVS; ++ g_agent_config_init_arg.vport_tx_depth = HINIC3_DEFAULT_VPORT_DEPTH_OVS; ++} ++ ++static void hinic3_check_config(void) ++{ ++ if (g_agent_config_init_arg.offload_thread_num == HINIC3_OFFLOAD_THREAD_INVALID_NUM) { ++ HINIC3_LOG(INFO, AGENT, "illegal %s %u, use default value %u\n", AGENT_SECTION_OFFLOAD_THREAD_NUM_KEY, ++ g_agent_config_init_arg.offload_thread_num, HINIC3_OFFLOAD_THREAD_DEFAULT_NUM); ++ g_agent_config_init_arg.offload_thread_num = HINIC3_OFFLOAD_THREAD_DEFAULT_NUM; ++ } ++ ++ if (g_agent_config_init_arg.max_flow_num == HINIC3_MAX_FLOW_NUM_INVALID || ++ g_agent_config_init_arg.max_flow_num > hinic3_max_flow_num_limit_get()) { ++ HINIC3_LOG(INFO, AGENT, "illegal %s %u, use default value %u\n", AGENT_SECTION_MAX_FLOW_NUM_KEY, ++ g_agent_config_init_arg.max_flow_num, HINIC3_MAX_FLOW_DEFAULT_NUM); ++ g_agent_config_init_arg.max_flow_num = HINIC3_MAX_FLOW_DEFAULT_NUM; ++ } ++ ++ if (g_agent_config_init_arg.max_queue_num > hinic3_max_queue_num_limit_get()) { ++ HINIC3_LOG(INFO, AGENT, "illegal %s %u, use default value %u\n", PORT_SECTION_MAX_QUEUE_NUM_KEY, ++ g_agent_config_init_arg.max_queue_num, HINIC3_MAX_QUEUE_DEFAULT_NUM); ++ g_agent_config_init_arg.max_queue_num = HINIC3_MAX_QUEUE_DEFAULT_NUM; ++ } ++} ++ ++static int hinic3_parse_value_from_cfg(struct rte_cfgfile *inifile) ++{ ++ int ret; ++ const char *qos_level = NULL; ++ bool is_virtio_queue_depth_set = false; ++ ++ for (uint32_t index = 0; index < sizeof(g_num_table) / sizeof(struct hinic3_parse_num_type); index++) { ++ hinic3_parse_config_num(inifile, index); ++ } ++ hinic3_set_config_value(); ++ hinic3_check_config(); ++ hinic3_init_agent_config_arg(); ++ ++ // 在hinic3_get_agent_value_from_config中解析参数会有超大函数门禁不过问题,所以在这里解析 ++ is_virtio_queue_depth_set = hinic3_check_virtio_queue_depth_set(); ++ if (is_virtio_queue_depth_set) { ++ ret = hinic3_parse_virtio_queue_depth(inifile); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 virtio port_queue_depth init fail with %d", ret); ++ return -1; ++ } ++ } ++ ++ qos_level = rte_cfgfile_get_entry(inifile, QOS_SECTION, QOS_SECTION_QOS_LEVEL_KEY); ++ if (qos_level == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: qos level not find."); ++ return -1; ++ } ++ ++ if (strlen(qos_level) > QOS_LEVEL_MAX_LENGTH) { ++ HINIC3_LOG(ERR, QOS, "qos_level is too long"); ++ return -1; ++ } ++ ++ strcpy(g_agent_config_init_arg.qos_level, qos_level); ++ return 0; ++} ++ ++int hinic3_get_agent_value_from_config(void) ++{ ++ int ret; ++ struct rte_cfgfile *inifile = NULL; ++ ++ ret = hinic3_is_softlink(AGENT_CFG_FILE); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ inifile = hinic3_cfgfile_load(AGENT_CFG_FILE); ++ if (inifile == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Faild to load agent config file: %s", AGENT_CFG_FILE); ++ return -1; ++ } ++ ++ ret = hinic3_parse_value_from_cfg(inifile); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "Failed to parse value from config file."); ++ goto out; ++ } ++ ++ ret = hinic3_init_cpu_mask(inifile); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 cpu_mask init fail with %d", ret); ++ goto out; ++ } ++ ++ ret = hinic3_parse_pf_pci_addr(inifile); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 pf_pci_addr init fail with %d", ret); ++ goto out; ++ } ++ ++ ret = hinic3_parse_vpda_feature(inifile); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 vdpa_virtio_feature init fail with %d", ret); ++ goto out; ++ } ++ ++ ret = hinic3_parse_disk_usage(inifile); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 disk_usage init fail with %d", ret); ++ goto out; ++ } ++ ++ hinic3_parse_meminfo_feature(inifile); ++ ++ if (hinic3_check_masked_to_exact_switch() == true) { ++ if (hinic3_parse_pcap_cpu_config(inifile) != 0) { ++ HINIC3_LOG(ERR, AGENT, "hinic3 pcap_cpu init fail with %d", ret); ++ goto out; ++ } ++ } ++ ++ rte_cfgfile_close(inifile); ++ return 0; ++ ++out: ++ rte_cfgfile_close(inifile); ++ return -1; ++} ++ ++bool hinic3_get_enable_hugepage_meminfo_statistic(void) ++{ ++ return g_agent_config_init_arg.enable_hugepage_meminfo_statistic; ++} +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h +new file mode 100644 +index 0000000..a52d63e +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h +@@ -0,0 +1,238 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_PARSE_AGENT_CONFIG_H ++#define HINIC3_PARSE_AGENT_CONFIG_H ++ ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_util.h" ++#include "rte_log.h" ++#include "rte_cfgfile.h" ++#include "hinic3_agent.h" ++#include "hinic3_ds.h" ++#include "dpak_cfg.h" ++ ++#define HINIC3_ARGS_NAME_MAX_LEN 50 ++#define HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MIN 0 ++#define HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MAX 16 ++ ++struct hinic3_parse_num_type { ++ char section_name[HINIC3_ARGS_NAME_MAX_LEN]; ++ char name[HINIC3_ARGS_NAME_MAX_LEN]; ++ uint32_t min_num; ++ uint32_t max_num; ++ uint32_t *num; ++}; ++ ++struct hinic3_init_arg *hinic3_get_init_arg(void); ++int hinic3_get_agent_value_from_config(void); ++bool hinic3_get_enable_hugepage_meminfo_statistic(void); ++ ++static inline char *hinic3_get_multi_qos_level(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->qos_level; ++} ++ ++static inline char *hinic3_pf_pci_addr_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->pf_pci_addr; ++} ++ ++static inline struct hinic3_cpu_mask hinic3_forward_cpu_mask_get() ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->forward_cpu_mask; ++} ++ ++static inline struct hinic3_cpu_mask hinic3_control_cpu_mask_get() ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->control_cpu_mask; ++} ++ ++static inline uint32_t hinic3_disk_usage_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->disk_usage; ++} ++ ++static inline bool hinic3_check_masked_to_exact_switch(void) ++{ ++ return true; ++}; ++ ++static inline uint16_t hinic3_virtio_queue_depth(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->virtio_queue_depth; ++}; ++ ++static inline bool hinic3_check_virtio_queue_depth_set(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->is_virtio_queue_depth_set; ++}; ++ ++static inline int hinic3_device_mode_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->is_dpu ? DPU_MODE : SMART_NIC_MODE; ++} ++ ++static inline bool hinic3_need_init_port(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->add_port_when_init; ++} ++ ++static inline int hinic3_forward_mode_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->forward_mode; ++} ++ ++static inline int hinic3_hiovs_mode_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->hiovs_mode; ++} ++ ++static inline uint16_t hinic3_bond_rx_depth_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->bond_rx_depth; ++} ++ ++static inline uint16_t hinic3_bond_tx_depth_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->bond_tx_depth; ++} ++ ++static inline uint16_t hinic3_vport_rx_depth(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->vport_rx_depth; ++} ++ ++static inline uint16_t hinic3_vport_tx_depth(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->vport_tx_depth; ++} ++ ++static inline uint8_t hinic3_virtual_queue_multiplex_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->virtual_queue_multiplex; ++} ++ ++static inline uint32_t hinic3_offload_thread_num_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->offload_thread_num; ++} ++ ++static inline uint32_t hinic3_max_flow_num_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->max_flow_num; ++} ++ ++static inline uint32_t hinic3_max_queue_num_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->max_queue_num; ++} ++ ++static inline uint32_t hinic3_upcall_queue_num_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->upcall_queue_num; ++} ++ ++static inline uint32_t hinic3_mbuf_size_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->mbuf_size; ++} ++ ++static inline uint32_t hinic3_flow_max_idle_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->flow_max_idle; ++} ++ ++static inline uint64_t hinic3_vdpa_feature_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->vdpa_virtio_feature; ++} ++ ++static inline enum tcp_ct_action_switch hinic3_status_packet_upcall_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->status_packet_upcall; ++} ++ ++static inline uint32_t hinic3_support_virtio_queue_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->support_virtio_queue; ++} ++ ++static inline uint32_t hinic3_packet_forward_mod_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->packet_forward_mode; ++} ++ ++static inline uint32_t hinic3_packet_bond_hash_policy_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->bond_hash_policy; ++} ++ ++static inline uint32_t hinic3_max_flow_num_limit_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->max_flow_num_limit; ++} ++ ++static inline uint32_t hinic3_max_queue_num_limit_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->max_queue_num_limit; ++} ++ ++static inline enum hinic3_query_bdf_type hinic3_query_bdf_type_get(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->query_bdf_type; ++} ++ ++static inline bool hinic3_support_port_hot_plug(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->support_port_hot_plug; ++} ++ ++static inline bool hinic3_is_support_vf_port(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->support_vf_port; ++} ++ ++static inline bool hinic3_is_support_pf_port(void) ++{ ++ struct hinic3_init_arg *conf = hinic3_get_init_arg(); ++ return conf->support_pf_port; ++} ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.c b/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.c +new file mode 100644 +index 0000000..5c9bc9f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.c +@@ -0,0 +1,202 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "ethdev_driver.h" ++#include "hinic3_port_util.h" ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_flow_agent_enum.h" ++ ++static const struct hinic3_port_stats_name_off { ++ const char name[ETH_XSTATS_NAME_SIZE]; ++} g_hinic3_port_stats_strings[] = { ++ {"upcall_tx_pkt_num"}, // 网卡往upcall队列发包给vswitch,发成功的数目 ++ {"upcall_rx_pkt_num"}, // 网卡从reinject队列发包收到包数 ++ {"upcall_tx_drop_num"}, // 网卡往upcall队列发包给vswitch,丢包数 ++}; ++ ++bool ++hinic3_is_ethdev_valid(struct rte_eth_dev *dev) ++{ ++ if (dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "rte eth dev is NULL.\n"); ++ return false; ++ } ++ ++ if (dev->data == NULL) { ++ HINIC3_LOG(ERR, VPORT, "rte eth dev data is NULL.\n"); ++ return false; ++ } ++ ++ if (dev->data->dev_private == NULL) { ++ HINIC3_LOG(ERR, VPORT, "rte eth dev data private is NULL.\n"); ++ return false; ++ } ++ ++ return true; ++} ++ ++void * ++hinic3_get_private_data(uint16_t dpdk_index_id) ++{ ++ struct rte_eth_dev *dev; ++ RTE_ETH_VALID_PORTID_OR_ERR_RET(dpdk_index_id, NULL); ++ dev = &rte_eth_devices[dpdk_index_id]; ++ return dev->data->dev_private; ++} ++ ++int ++hinic3_get_id_from_dev(struct rte_eth_dev *dev, uint16_t *port_id) ++{ ++ struct rte_device *device = dev->device; ++ const char *name = device->name; ++ ++ return rte_eth_dev_get_port_by_name(name, port_id); ++} ++ ++int ++hinic3_port_xstats_get_names(struct rte_eth_dev *dev __rte_unused, ++ struct rte_eth_xstat_name *xstats_names, unsigned int limit) ++{ ++ int count = 0; ++ if (xstats_names == NULL) ++ return HW_NB_XSTATS; ++ ++ if (limit < HW_NB_XSTATS) { ++ HINIC3_LOG(ERR, BOND, "The maximum number is less than the expected number"); ++ return -1; ++ } ++ ++ for (int i = 0; i < HW_NB_XSTATS; i++) { ++ strcpy(xstats_names[count].name, g_hinic3_port_stats_strings[i].name); ++ count++; ++ } ++ return count; ++} ++ ++static int ++hinic3_upcall_queue_parse(const char *queues, uint16_t *upcall_queues, int *n_ques) ++{ ++ int i = 0; ++ int cnt = 0; ++ const int decimal = 10; ++ char *arg = NULL; ++ char *next = NULL; ++ char *qid = NULL; ++ ++ if (queues == NULL || upcall_queues == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Invalid que_ids or upcall_queues.\n"); ++ return -EINVAL; ++ } ++ ++ arg = hinic3_strdup(queues, HINIC3_DRIVER_ADAPTER); ++ if (arg == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Alloc memory error.\n"); ++ return -ENOMEM; ++ } ++ ++ next = arg; ++ for (i = 0; i < MAX_RX_QUEUE_PER_VPORT; i++) { ++ qid = strsep(&next, ","); ++ if (qid == NULL) { ++ break; ++ } ++ char *endPtr = NULL; ++ upcall_queues[i] = (uint32_t)strtoul(qid, &endPtr, decimal); ++ if (endPtr == NULL || *endPtr != '\0') { ++ hinic3_free(arg); ++ return -EINVAL; ++ } ++ ++cnt; ++ } ++ ++ *n_ques = cnt; ++ hinic3_free(arg); ++ return 0; ++} ++ ++int ++hinic3_eth_get_upcall_queue_map(uint16_t vport_id, uint8_t n_upcall_queue, uint16_t *upcall_queue_id) ++{ ++ int ret = 0; ++ int n_ques = 0; ++ struct smap smap_args = {0}; ++ const char *upcall_queues_str = NULL; ++ ++ if (vport_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, VPORT, "invalid vport id!\n"); ++ return -EINVAL; ++ } ++ ++ if (upcall_queue_id == NULL) { ++ HINIC3_LOG(ERR, VPORT, "pointer of upcall queue id is NULL!\n"); ++ return -EINVAL; ++ } ++ ++ hinic3_smap_init(&smap_args); ++ ret = hinic3_port_mgmt_get(vport_id, &smap_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to get port mgmt info!\n"); ++ goto err; ++ } ++ upcall_queues_str = hinic3_smap_get(&smap_args, HINIC3_PORT_UPCALL_QUEUE_MAP); ++ if (upcall_queues_str != NULL) { ++ ret = hinic3_upcall_queue_parse(upcall_queues_str, upcall_queue_id, &n_ques); ++ if (ret != 0 || n_upcall_queue > n_ques) { ++ HINIC3_LOG(ERR, VPORT, "rxq:%u is greater than max queues: %d\n", n_upcall_queue, n_ques); ++ ret = -EINVAL; ++ } ++ } else { ++ ret = -ENOENT; ++ } ++ ++err: ++ hinic3_smap_destroy(&smap_args); ++ return ret; ++} ++ ++ ++int ++hinic3_eth_get_dpdk_port_id(uint16_t vport_id, uint8_t *dpdk_port_id) ++{ ++ int ret = 0; ++ struct smap smap_args = {0}; ++ const char *dpdk_port_id_str = NULL; ++ uintmax_t dpdk_port_id_ul = 0; ++ ++ if (vport_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, VPORT, "invalid vport id!"); ++ return -EINVAL; ++ } ++ ++ if (dpdk_port_id == NULL) { ++ HINIC3_LOG(ERR, VPORT, "point of dpdk port id is NULL!"); ++ return -EINVAL; ++ } ++ ++ hinic3_smap_init(&smap_args); ++ ret = hinic3_port_mgmt_get(vport_id, &smap_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to get port mgmt info!"); ++ goto err; ++ } ++ ++ dpdk_port_id_str = hinic3_smap_get(&smap_args, HINIC3_DPDK_PORT_ID); ++ if (dpdk_port_id_str == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to get dpdk port id!"); ++ ret = -ENOENT; ++ goto err; ++ } ++ ++ dpdk_port_id_ul = strtoul(dpdk_port_id_str, NULL, STR_TO_DEC_NUM); ++ if (dpdk_port_id_ul > UINT8_MAX) { ++ HINIC3_LOG(ERR, VPORT, "dpdk port id out of range!"); ++ ret = -ERANGE; ++ goto err; ++ } ++ *dpdk_port_id = dpdk_port_id_ul; ++ ++err: ++ hinic3_smap_destroy(&smap_args); ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h b/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h +new file mode 100644 +index 0000000..5e48ee4 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h +@@ -0,0 +1,44 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_PORT_UTIL_H ++#define HINIC3_PORT_UTIL_H ++ ++#include "hinic3_tlv_key.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_hugepage_meminfo.h" ++#include "hinic3_iface_port.h" ++ ++#define HINIC3_DEV_STATE_STOP 0 ++#define HINIC3_DEV_STATE_START 1 ++#define HINIC3_INVALID_QUEUE_NUM 0 ++#define HINIC3_MAX_UC_MAC_ADDRS 1 ++ ++#define HINIC3_ETH_VDEV_DRV_NAME "net_hwsp" ++ ++#define INVALID_UPCALL_QUEUE_ID 0xff ++#define MAX_RX_QUEUE_PER_VPORT 16 ++#define MAX_TX_QUEUE_PER_VPORT 16 ++ ++#define HW_NB_XSTATS 3 ++#define ETH_XSTATS_NAME_SIZE 64 ++#define XSTATS_UPCALL_PKT_INDEX 0 ++#define XSTATS_REINJECT_PKT_INDEX 1 ++#define XSTATS_UPCALL_DROP_INDEX 2 ++ ++/* 端口有效性校验 */ ++bool hinic3_is_ethdev_valid(struct rte_eth_dev *dev); ++ ++void *hinic3_get_private_data(uint16_t dpdk_index_id); ++/* 获取端口id */ ++int hinic3_get_id_from_dev(struct rte_eth_dev *dev, uint16_t *port_id); ++/* 获取端口xstats名称 */ ++int hinic3_port_xstats_get_names(struct rte_eth_dev *dev __rte_unused, ++ struct rte_eth_xstat_name *xstats_names, unsigned int limit); ++ ++/* 从网卡驱动获取端口队列id列表 */ ++int hinic3_eth_get_upcall_queue_map(uint16_t vport_id, uint8_t n_upcall_queue, uint16_t *upcall_queue_id); ++/* 从网卡驱动获取端口vport id到dpdk port id映射 */ ++int hinic3_eth_get_dpdk_port_id(uint16_t vport_id, uint8_t *dpdk_port_id); ++#endif /* HINIC3_PORT_UTIL_H */ +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +new file mode 100644 +index 0000000..e626a5d +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +@@ -0,0 +1,930 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "rte_lcore.h" ++#include "hinic3_util.h" ++#include "hinic3_capture_main.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_vxlan.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_tlv_key.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++#include "hinic3_bond_controller.h" ++ ++#define PRIORITY_UPCALL_MAX_NUM 2 ++#define HINIC3_BOND_MODE_ANY 0 ++#define ETH_XSTATS_NAME_SIZE 64 ++#define STATUS_NAME 4 ++#define STATUS_LEN (STATUS_NAME * 2) ++#define SPEED_LEN 10 ++#define MODE_MAX_LEN 32 ++#define BOND_SLAVES_MAX_LEN 128 ++#define SYSFS_CLASS_NET_PATH "/sys/class/net/" ++ ++static rte_atomic32_t g_bond_active = RTE_ATOMIC16_INIT(0); ++ ++struct rte_flow_ops *g_hinic3_pf_flow_ops = NULL; ++ ++void ++hinic3_bond_flow_ops_construct(void) ++{ ++ struct rte_flow_ops *flow_ops = hinic3_calloc(1, sizeof(struct rte_flow_ops), HINIC3_PORTS); ++ if (flow_ops == NULL) ++ return; ++ ++ rte_flow_ops_set_validate(flow_ops, hinic3_eth_flow_validate); ++ rte_flow_ops_set_create(flow_ops, hinic3_eth_flow_create); ++ rte_flow_ops_set_destroy(flow_ops, hinic3_eth_flow_destroy); ++ rte_flow_ops_set_flush(flow_ops, hinic3_eth_flow_flush); ++ rte_flow_ops_set_query(flow_ops, hinic3_eth_flow_query); ++ rte_flow_ops_set_dev_dump(flow_ops, hinic3_eth_flow_dev_dump); ++ rte_flow_ops_tunnel_decap_set(flow_ops, hinic3_flow_tunnel_decap_set); ++ rte_flow_ops_flow_dump_start(flow_ops, hinic3_eth_flow_dump_start); ++ rte_flow_ops_flow_dump_next(flow_ops, hinic3_eth_flow_dump_next); ++ rte_flow_ops_flow_dump_done(flow_ops, hinic3_eth_flow_dump_done); ++ g_hinic3_pf_flow_ops = flow_ops; ++} ++ ++void ++hinic3_bond_flow_ops_destroy(void) ++{ ++ if (g_hinic3_pf_flow_ops == NULL) ++ return; ++ ++ hinic3_free(g_hinic3_pf_flow_ops); ++ ++ g_hinic3_pf_flow_ops = NULL; ++} ++ ++static int ++hinic3_bond_update_numa_node(struct rte_eth_dev *eth_dev) ++{ ++ struct rte_eth_dev_data *data = eth_dev->data; ++ ++ int numa_node = rte_socket_id(); ++ if (data->numa_node != numa_node) { ++ HINIC3_LOG(DEBUG, BOND, "update numa node %d to %d!", data->numa_node, numa_node); ++ data->numa_node = numa_node; ++ } ++ return 0; ++} ++ ++static void ++hinic3_bond_release_upcall_queue(struct hinic3_bond_dev *bond_dev, uint16_t queue_id) ++{ ++ int ret = 0; ++ if (bond_dev->upcall_queue.is_queue_valid[queue_id] == true) { ++ ret = hinic3_port_mgmt_release_upcall_queue(bond_dev->vport_id, queue_id); ++ if (ret != 0) ++ HINIC3_LOG(ERR, BOND, "bond port release upcall queue error"); ++ ++ bond_dev->upcall_queue.is_queue_valid[queue_id] = false; ++ } ++} ++ ++static void ++hinic3_bond_release_reinject_queue(struct hinic3_bond_dev *bond_dev, uint16_t queue_id) ++{ ++ if (bond_dev->reinject_queue.is_queue_valid[queue_id] == true) ++ bond_dev->reinject_queue.is_queue_valid[queue_id] = false; ++} ++ ++static int ++hinic3_bond_uplink_pci_get(uint16_t bond_id, struct rte_pci_addr *uplink_pci) ++{ ++ int ret = 0; ++ struct smap bond_info = {0}; ++ const char *uplink_pci_addr = NULL; ++ ++ if (uplink_pci == NULL) { ++ HINIC3_LOG(ERR, BOND, "point of uplink_pci is NULL!"); ++ return -EINVAL; ++ } ++ ++ if (bond_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, BOND, "invalid bond id!"); ++ return -EINVAL; ++ } ++ ++ hinic3_smap_init(&bond_info); ++ ret = hinic3_bond_mgmt_get(bond_id, &bond_info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "failed to get bond info by id"); ++ goto end; ++ } ++ ++ uplink_pci_addr = hinic3_smap_get(&bond_info, HINIC3_BOND_UPLINK_PCI_ID); ++ if (uplink_pci_addr == NULL) { ++ HINIC3_LOG(ERR, BOND, "failed to get uplink pci from bond info"); ++ ret = -EPERM; ++ goto end; ++ } ++ ret = rte_pci_addr_parse(uplink_pci_addr, uplink_pci); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "failed to parse uplink pci from str"); ++ ret = -EPERM; ++ goto end; ++ } ++end: ++ hinic3_smap_destroy(&bond_info); ++ return ret; ++} ++ ++static int ++hinic3_bond_add(struct rte_eth_dev *eth_dev) ++{ ++ int ret = 0; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(eth_dev); ++ ++ if (bond_dev->bond_id != HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, BOND, "bond already created!"); ++ return 0; ++ } ++ ++ ret = hinic3_bond_mgmt_create(HINIC3_BOND_MODE_ANY, bond_dev->bond_name, &bond_dev->bond_id); ++ if (ret != 0 || bond_dev->bond_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, BOND, "failed to create bond, return: %d", ret); ++ if (ret == 0) ++ return -EPERM; ++ ++ return ret; ++ } ++ return 0; ++} ++ ++static int ++hinic3_bond_port_add(struct rte_eth_dev *eth_dev) ++{ ++ int ret = 0; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(eth_dev); ++ ++ if (bond_dev->vport_id != HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, BOND, "bond vport already created!"); ++ return 0; ++ } ++ ++ ret = hinic3_bond_uplink_pci_get(bond_dev->bond_id, &bond_dev->uplink_pci_addr); ++ if (ret != 0) ++ return ret; ++ ++ ret = hinic3_bond_update_numa_node(eth_dev); ++ if (ret != 0) ++ return ret; ++ ++ bond_dev->vport_id = bond_dev->n_upcall_queue; ++ ret = hinic3_port_mgmt_add(&bond_dev->vport_id, &bond_dev->uplink_pci_addr); ++ if (ret != 0) { ++ bond_dev->vport_id = HINIC3_PORT_ID_INVALID; ++ HINIC3_LOG(ERR, BOND, "failed to create vport, return: %d", ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static int ++hinic3_bond_dev_add(struct rte_eth_dev *dev) ++{ ++ int ret = 0; ++ uint32_t bond_alive = 0; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ ++ bond_alive = rte_atomic32_read(&g_bond_active); ++ if (bond_alive != 0) { ++ HINIC3_LOG(ERR, BOND, "more than one bond is not supported by hinic3!"); ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ ret = hinic3_bond_add(dev); ++ if (ret != 0) ++ goto end; ++ ++ ret = hinic3_bond_port_add(dev); ++ if (ret != 0) ++ goto clean_bond; ++ ++ ret = hinic3_eth_get_dpdk_port_id(bond_dev->vport_id, &bond_dev->dpdk_port_id); ++ if (ret != 0) ++ goto clean_port; ++ ++ HINIC3_LOG(INFO, BOND, "hinic3 pf bond port add success, port_id: %u, upcall_queue: %u", ++ bond_dev->vport_id, bond_dev->n_upcall_queue); ++ HINIC3_LOG(INFO, BOND, "vport pci is %.4x:%.2x:%.2x.%x", bond_dev->uplink_pci_addr.domain, ++ bond_dev->uplink_pci_addr.bus, bond_dev->uplink_pci_addr.devid, bond_dev->uplink_pci_addr.function); ++ rte_atomic32_set(&g_bond_active, 1); ++ return ret; ++ ++clean_port: ++ hinic3_port_mgmt_del(bond_dev->vport_id); ++ bond_dev->vport_id = HINIC3_PORT_ID_INVALID; ++ ++clean_bond: ++ hinic3_bond_mgmt_delete(bond_dev->bond_id); ++ bond_dev->bond_id = HINIC3_PORT_ID_INVALID; ++ ++end: ++ return ret; ++} ++ ++static void ++hinic3_bond_dev_del(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return; ++ ++ uint16_t nb_rx_queues = 0; ++ uint16_t nb_tx_queues = 0; ++ uint32_t bond_alive = 0; ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ ++ nb_rx_queues = data->nb_rx_queues; ++ for (uint16_t index = 0; index < nb_rx_queues; index++) ++ hinic3_bond_rx_queue_release(dev, index); ++ ++ nb_tx_queues = data->nb_tx_queues; ++ for (uint16_t index = 0; index < nb_tx_queues; index++) ++ hinic3_bond_tx_queue_release(dev, index); ++ ++ if (bond_dev->vport_id != HINIC3_PORT_ID_INVALID) { ++ /* 端口删除前,清理抓包信息 */ ++ pcap_task_stop_as_eth_port_del(bond_dev->vport_id); ++ hinic3_port_mgmt_del(bond_dev->vport_id); ++ bond_dev->vport_id = HINIC3_PORT_ID_INVALID; ++ } ++ ++ if (bond_dev->bond_id != HINIC3_PORT_ID_INVALID) { ++ hinic3_bond_mgmt_delete(bond_dev->bond_id); ++ bond_dev->bond_id = HINIC3_PORT_ID_INVALID; ++ bond_alive = rte_atomic32_read(&g_bond_active); ++ if (bond_alive == 1) ++ rte_atomic32_set(&g_bond_active, 0); ++ } ++ ++ if (bond_dev->dpdk_port_id != INVALID_DPDK_PORT_ID) ++ bond_dev->dpdk_port_id = INVALID_DPDK_PORT_ID; ++} ++ ++int ++hinic3_bond_set_link_up(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ dev_link->link_status = RTE_ETH_LINK_UP; ++ ++ return 0; ++} ++ ++int ++hinic3_bond_set_link_down(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ dev_link->link_status = RTE_ETH_LINK_DOWN; ++ ++ return 0; ++} ++ ++int ++hinic3_bond_dev_start(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ if (bond_dev->bond_id == HINIC3_PORT_ID_INVALID || bond_dev->vport_id == HINIC3_PORT_ID_INVALID) { ++ return -1; ++ } ++ ++ dev_link->link_status = RTE_ETH_LINK_UP; ++ data->dev_started = HINIC3_DEV_STATE_START; ++ ++ return 0; ++} ++ ++int ++hinic3_bond_dev_stop(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ dev_link->link_status = RTE_ETH_LINK_DOWN; ++ data->dev_started = HINIC3_DEV_STATE_STOP; ++ ++ return 0; ++} ++ ++int ++hinic3_bond_dev_close(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ struct rte_eth_dev_data *data = dev->data; ++ if (data->mac_addrs != NULL) { ++ hinic3_rte_free(data->mac_addrs); ++ data->mac_addrs = NULL; ++ } ++ hinic3_bond_dev_del(dev); ++ return 0; ++} ++ ++int ++hinic3_bond_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ if (info == NULL) { ++ HINIC3_LOG(ERR, BOND, "eth dev info is NULL"); ++ return -EINVAL; ++ } ++ ++ int ret = 0; ++ struct hinic3_port_capability cap = {0}; ++ ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ struct rte_device *device = dev->device; ++ const struct rte_driver *driver = device->driver; ++ ++ info->driver_name = driver->name; ++ ret = hinic3_port_mgmt_get_capability(&cap); ++ if (ret != 0) ++ return ret; ++ ++ if (cap.supported_upcall_qnum != MAX_RX_QUEUE_PER_VPORT) ++ info->max_rx_queues = HINIC3_PF_DEFAULT_NB_QUEUES; ++ else ++ info->max_rx_queues = MAX_RX_QUEUE_PER_VPORT; ++ ++ info->min_mtu = HINIC3_PF_MTU_MIN; ++ info->max_mtu = HINIC3_PF_MTU_MAX; ++ info->max_rx_pktlen = HINIC3_PF_MTU_MAX + HINIC3_PF_SIEZ_OFFSET; ++ info->max_tx_queues = MAX_RX_QUEUE_PER_VPORT; ++ info->if_index = bond_dev->vport_id; ++ ++ return 0; ++} ++ ++void ++hinic3_bond_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return; ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *rxq = NULL; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ ++ if (queue_id >= data->nb_rx_queues) { ++ HINIC3_LOG(ERR, BOND, "queue index invalid, max queue is:%u", data->nb_rx_queues); ++ return; ++ } ++ rxq = data->rx_queues[queue_id]; ++ if (rxq != NULL) { ++ hinic3_bond_release_upcall_queue(bond_dev, queue_id); ++ hinic3_rte_free(rxq); ++ bond_dev->upcall_queue.rx_queue[queue_id] = NULL; ++ data->rx_queues[queue_id] = NULL; ++ } ++} ++ ++void ++hinic3_bond_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return; ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *txq = NULL; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ if (queue_id >= data->nb_tx_queues) { ++ HINIC3_LOG(ERR, BOND, "queue index invalid, max queue is:%u", data->nb_tx_queues); ++ return; ++ } ++ ++ txq = data->tx_queues[queue_id]; ++ if (txq != NULL) { ++ hinic3_bond_release_reinject_queue(bond_dev, queue_id); ++ hinic3_rte_free(txq); ++ bond_dev->reinject_queue.tx_queues[queue_id] = NULL; ++ data->tx_queues[queue_id] = NULL; ++ } ++} ++ ++static void ++hinic3_bond_get_rx_queue_info(struct hinic3_standard_queue *rxq, struct rte_mempool *mp, uint16_t idx, ++ struct hinic3_bond_dev *bond_dev, uint16_t dpdk_index_id) ++{ ++ rxq->mp = mp; ++ rxq->queue_id = idx; ++ rxq->info.type = HINIC3_RX_QUEUE; ++ rxq->vport_id = bond_dev->vport_id; ++ rxq->dpdk_port_id = bond_dev->dpdk_port_id; ++ rxq->upcall_queue_id = bond_dev->upcall_queue.upcall_queue_id[idx]; ++ rxq->dpdk_index_id = dpdk_index_id; ++} ++ ++int ++hinic3_bond_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_rxconf *conf __rte_unused, ++ struct rte_mempool *mp) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ if (mp == NULL) { ++ HINIC3_LOG(ERR, BOND, "mp is NULL"); ++ return -EINVAL; ++ } ++ ++ int ret = 0; ++ uint16_t bond_rx_depth = hinic3_bond_rx_depth_get(); ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *rxq = NULL; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ uint16_t dpdk_index_id = 0; ++ bool is_open_ovs = hinic3_check_masked_to_exact_switch(); ++ ++ if (bond_dev == NULL) { ++ HINIC3_LOG(ERR, BOND, "The current pf rx device private_data is NULL."); ++ return -EPERM; ++ } ++ ++ if (bond_rx_depth != desc && !is_open_ovs) { ++ HINIC3_LOG(ERR, BOND, "bond_rx_depth differences. desc is %u, bond_rx_depth is %u", desc, bond_rx_depth); ++ return -EINVAL; ++ } ++ ++ if (idx >= data->nb_rx_queues) { ++ HINIC3_LOG(ERR, BOND, "queue index invalid, max queue is:%u", data->nb_rx_queues); ++ return -EINVAL; ++ } ++ ++ ret = hinic3_get_port_index_by_dev(dev, &dpdk_index_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "hinic3_get_port_index_by_dev error"); ++ return -EPERM; ++ } ++ ++ ret = hinic3_port_mgmt_setup_upcall_queue(bond_dev->vport_id, idx, socket_id, mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "port setup upcall queue error"); ++ return -EPERM; ++ } ++ ++ rxq = hinic3_rte_zmalloc_socket(HINIC3_PORTS, sizeof(struct hinic3_standard_queue), RTE_CACHE_LINE_SIZE, socket_id); ++ if (rxq == NULL) ++ return -ENOMEM; ++ ++ bond_dev->upcall_queue.rx_queue[idx] = rxq; ++ bond_dev->upcall_queue.is_queue_valid[idx] = true; ++ /* 获取upcall_queue信息 */ ++ hinic3_bond_get_rx_queue_info(rxq, mp, idx, bond_dev, dpdk_index_id); ++ data->rx_queues[idx] = rxq; ++ ++ return 0; ++} ++ ++int ++hinic3_bond_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_txconf *conf __rte_unused) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ int ret = 0; ++ uint16_t bond_tx_depth = hinic3_bond_tx_depth_get(); ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *txq; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ uint16_t dpdk_index_id = 0; ++ bool is_open_ovs = hinic3_check_masked_to_exact_switch(); ++ ++ if (bond_dev == NULL) { ++ HINIC3_LOG(ERR, BOND, "The current pf tx device private_data is NULL."); ++ return -EPERM; ++ } ++ ++ if (bond_tx_depth != desc && !is_open_ovs) { ++ HINIC3_LOG(ERR, BOND, "bond_tx_depth differences. desc is %u, bond_tx_depth is %u", desc, bond_tx_depth); ++ return -EINVAL; ++ } ++ ++ if (idx >= data->nb_tx_queues) { ++ HINIC3_LOG(ERR, BOND, "queue index invalid, max queue is:%u", data->nb_tx_queues); ++ return -EINVAL; ++ } ++ ++ ret = hinic3_get_port_index_by_dev(dev, &dpdk_index_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "hinic3_get_port_index_by_dev error"); ++ return -EPERM; ++ } ++ ++ txq = hinic3_rte_zmalloc_socket(HINIC3_PORTS, sizeof(struct hinic3_standard_queue), ++ RTE_CACHE_LINE_SIZE, socket_id); ++ if (txq == NULL) ++ return -ENOMEM; ++ ++ bond_dev->reinject_queue.tx_queues[idx] = txq; ++ bond_dev->reinject_queue.is_queue_valid[idx] = true; ++ txq->queue_id = idx; ++ txq->info.type = HINIC3_TX_QUEUE; ++ txq->vport_id = bond_dev->vport_id; ++ txq->dpdk_port_id = bond_dev->dpdk_port_id; ++ txq->dpdk_index_id = dpdk_index_id; ++ data->tx_queues[idx] = txq; ++ ++ return 0; ++} ++ ++void ++hinic3_construct_priority_upcall_cfgs(struct hinic3_high_priority_cfgs *cfgs) ++{ ++ cfgs->cfgs_len = PRIORITY_UPCALL_MAX_NUM; ++ ++ cfgs->hovs_cfgs[0].protocol_l2 = ETH_TYPE_IPV6; ++ cfgs->hovs_cfgs[0].protocol_l3 = HINIC3_NEXTHDR_ICMP; ++ cfgs->hovs_cfgs[0].reserve0 = 0; ++ cfgs->hovs_cfgs[0].reserve1 = 0; ++ ++ cfgs->hovs_cfgs[1].protocol_l2 = ETH_TYPE_ARP; ++ cfgs->hovs_cfgs[1].protocol_l3 = 0; ++ cfgs->hovs_cfgs[1].reserve0 = 0; ++ cfgs->hovs_cfgs[1].reserve1 = 0; ++} ++ ++static int ++hinic3_bond_dev_configure_sub(struct hinic3_bond_dev *bond_dev, struct rte_eth_dev *dev, ++ struct rte_eth_dev_data *data) ++{ ++ int ret = hinic3_bond_dev_add(dev); ++ if (ret != 0) ++ return -EPERM; ++ ++ if (bond_dev->priority_upcall == true) { ++ struct hinic3_high_priority_cfgs cfgs = {0}; ++ hinic3_construct_priority_upcall_cfgs(&cfgs); ++ ret = hinic3_iface_high_priority_upcall_set(bond_dev->vport_id, &cfgs); ++ if (ret != 0) { ++ hinic3_bond_dev_del(dev); ++ return -EPERM; ++ } ++ } ++ ++ ret = hinic3_eth_get_upcall_queue_map(bond_dev->vport_id, bond_dev->n_upcall_queue, ++ bond_dev->upcall_queue.upcall_queue_id); ++ if (ret != 0) { ++ hinic3_bond_dev_del(dev); ++ return -EPERM; ++ } ++ ++ bond_dev->port_ifindex = data->port_id; ++ ret = hinic3_set_port_map_by_ifindex(bond_dev->vport_id, bond_dev->port_ifindex); ++ if (ret != 0) { ++ hinic3_bond_dev_del(dev); ++ return -EPERM; ++ } ++ return 0; ++} ++ ++int ++hinic3_bond_dev_configure(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ int ret = 0; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ struct rte_eth_dev_data *data = dev->data; ++ ++ if (data->dev_started != HINIC3_DEV_STATE_STOP) { ++ HINIC3_LOG(ERR, BOND, "the device must be stopped when the port is configured!"); ++ return -EPERM; ++ } ++ ++ // rebuild the port only when the rx queue is changed. ++ if (data->nb_rx_queues != bond_dev->n_upcall_queue) { ++ if (data->nb_rx_queues == 0) { ++ HINIC3_LOG(ERR, BOND, "number of rx queue can't be zero!"); ++ return -EPERM; ++ } ++ hinic3_bond_dev_del(dev); ++ bond_dev->n_upcall_queue = data->nb_rx_queues; ++ } ++ ++ bond_dev->n_txq = data->nb_tx_queues; ++ // create hwbond ++ if (bond_dev->bond_id == HINIC3_PORT_ID_INVALID && bond_dev->vport_id == HINIC3_PORT_ID_INVALID) { ++ ret = hinic3_bond_dev_configure_sub(bond_dev, dev, data); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "pf dev configure failed!"); ++ return ret; ++ } ++ } ++ ++ if (data->mtu != bond_dev->mtu) { ++ ret = hinic3_bond_dev_set_mtu(dev, bond_dev->mtu); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "failed to set dev mtu to %u", bond_dev->mtu); ++ hinic3_bond_dev_del(dev); ++ return -EPERM; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_read_file(const char *path, char *file_data, int date_len) ++{ ++ int ret = 0; ++ int ch = 0; ++ int i = 0; ++ FILE *fp = fopen(path, "r"); ++ if (fp == NULL) { ++ HINIC3_LOG(ERR, BOND, "Can not open file."); ++ return -EPERM; ++ } ++ ++ for (i = 0; i < date_len - 1; i++) { ++ ch = fgetc(fp); ++ if ((ch != '\n') && (ch != EOF)) ++ file_data[i] = ch; ++ else ++ break; ++ } ++ ++ file_data[i] = '\0'; ++ ret = fclose(fp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "Can not close file."); ++ return -EPERM; ++ } ++ return 0; ++} ++ ++int ++hinic3_get_bond_link_status(const char *bond_name, uint32_t *status) ++{ ++ int ret = 0; ++ char bond_status[STATUS_LEN] = {0}; ++ char bond_status_path[PATH_MAX] = {0}; ++ char relative_path[PATH_MAX] = {0}; ++ ++ if (bond_name == NULL) ++ return -EINVAL; ++ ++ ret = snprintf(relative_path, PATH_MAX, "%s%s%s", SYSFS_CLASS_NET_PATH, bond_name, "/bonding/mii_status"); ++ if (ret < 0 || ret >= PATH_MAX) { ++ HINIC3_LOG(ERR, BOND, "bond status file name error"); ++ return -EPERM; ++ } ++ ++ if (realpath(relative_path, bond_status_path) == NULL) { ++ HINIC3_LOG(ERR, BOND, "file not exist!"); ++ return -1; ++ } ++ ++ ret = hinic3_read_file(bond_status_path, bond_status, STATUS_LEN); ++ if (ret != 0) ++ return -EPERM; ++ ++ if (strcmp(bond_status, "up") == 0) ++ *status = RTE_ETH_LINK_UP; ++ else if (strcmp(bond_status, "down") == 0) ++ *status = RTE_ETH_LINK_DOWN; ++ else { ++ HINIC3_LOG(ERR, BOND, "Failed to obtain the bond status"); ++ return -EPERM; ++ } ++ return 0; ++} ++ ++static int ++hinic3_set_bond_link_speed(uint32_t *speed, const char *bond_name) ++{ ++ int ret = 0; ++ char bond_speed[SPEED_LEN] = {0}; ++ char bond_speed_path[PATH_MAX] = {0}; ++ char slaves[BOND_SLAVES_MAX_LEN] = {0}; ++ char slaves_path[PATH_MAX] = {0}; ++ char slaves_relative_path[PATH_MAX] = {0}; ++ char delim[] = " "; ++ char *slave = NULL; ++ char *saveptr = NULL; ++ char *end_ptr = NULL; ++ ret = snprintf(slaves_relative_path, PATH_MAX, "%s%s%s", SYSFS_CLASS_NET_PATH, bond_name, "/bonding/slaves"); ++ if (ret < 0 || ret >= PATH_MAX) ++ return -EPERM; ++ ++ if (realpath(slaves_relative_path, slaves_path) == NULL) { ++ HINIC3_LOG(ERR, BOND, "file not exist!"); ++ return -1; ++ } ++ ++ ret = hinic3_read_file(slaves_path, slaves, BOND_SLAVES_MAX_LEN); ++ if (ret != 0) ++ return -EPERM; ++ ++ slave = strtok_r(slaves, delim, &saveptr); ++ while (slave != NULL) { ++ ret = snprintf(bond_speed_path, PATH_MAX, "%s%s%s%s%s", SYSFS_CLASS_NET_PATH, ++ bond_name, "/lower_", slave, "/speed"); ++ if (ret < 0 || ret >= PATH_MAX) ++ return -EPERM; ++ ++ ret = hinic3_read_file(bond_speed_path, bond_speed, SPEED_LEN); ++ if (ret != 0) ++ return -EPERM; ++ ++ uint32_t slave_speed = strtoul(bond_speed, &end_ptr, HWPT_DEC_BASE); ++ if (end_ptr == NULL || *end_ptr != '\0') { ++ HINIC3_LOG(ERR, BOND, "Speed outof range. speed is %u \n", slave_speed); ++ return -EPERM; ++ } ++ *speed += slave_speed; ++ slave = strtok_r(NULL, delim, &saveptr); ++ } ++ return 0; ++} ++ ++static int ++hinic3_set_active_backup_speed(uint32_t *speed, const char *bond_name) ++{ ++ int ret = 0; ++ char active_slave[BOND_SLAVES_MAX_LEN] = {0}; ++ char active_slave_path[PATH_MAX] = {0}; ++ char slaves_relative_path[PATH_MAX] = {0}; ++ char active_slave_speed_path[PATH_MAX] = {0}; ++ char active_slave_speed[SPEED_LEN] = {0}; ++ char *end_ptr = NULL; ++ ret = snprintf(slaves_relative_path, PATH_MAX, "%s%s%s", SYSFS_CLASS_NET_PATH, bond_name, "/bonding/active_slave"); ++ if (ret < 0 || ret >= PATH_MAX) ++ return -EPERM; ++ ++ if (realpath(slaves_relative_path, active_slave_path) == NULL) { ++ HINIC3_LOG(ERR, BOND, "file not exist!"); ++ return -1; ++ } ++ ++ ret = hinic3_read_file(active_slave_path, active_slave, BOND_SLAVES_MAX_LEN); ++ if (ret != 0) ++ return -EPERM; ++ ++ ret = snprintf(active_slave_speed_path, PATH_MAX, "%s%s%s%s%s", SYSFS_CLASS_NET_PATH, ++ bond_name, "/lower_", active_slave, "/speed"); ++ if (ret < 0 || ret >= PATH_MAX) ++ return -EPERM; ++ ++ ret = hinic3_read_file(active_slave_speed_path, active_slave_speed, SPEED_LEN); ++ if (ret != 0) ++ return -EPERM; ++ ++ *speed = strtoul(active_slave_speed, &end_ptr, HWPT_DEC_BASE); ++ if (end_ptr == NULL || *end_ptr != '\0') { ++ HINIC3_LOG(ERR, BOND, "Speed outof range. speed is %u \n", *speed); ++ *speed = 0; ++ return -EPERM; ++ } ++ return 0; ++} ++ ++static int ++hinic3_get_bond_link_speed(const struct hinic3_bond_dev *bond_dev, uint32_t *speed) ++{ ++ int ret = 0; ++ char bond_mode[MODE_MAX_LEN] = {0}; ++ char bond_mode_path[PATH_MAX] = {0}; ++ char relative_path[PATH_MAX] = {0}; ++ ++ ret = snprintf(relative_path, PATH_MAX, "%s%s%s", SYSFS_CLASS_NET_PATH, bond_dev->bond_name, "/bonding/mode"); ++ if (ret < 0 || ret >= PATH_MAX) ++ return -EPERM; ++ ++ if (realpath(relative_path, bond_mode_path) == NULL) { ++ HINIC3_LOG(ERR, BOND, "file not exist!"); ++ return -1; ++ } ++ ++ ret = hinic3_read_file(bond_mode_path, bond_mode, MODE_MAX_LEN); ++ if (ret != 0) ++ return -EPERM; ++ ++ if (strcmp(bond_mode, "balance-rr 0") == 0 || strcmp(bond_mode, "802.3ad 4") == 0 || ++ strcmp(bond_mode, "balance-xor 2") == 0) ++ ret = hinic3_set_bond_link_speed(speed, bond_dev->bond_name); ++ else if (strcmp(bond_mode, "active-backup 1") == 0) ++ ret = hinic3_set_active_backup_speed(speed, bond_dev->bond_name); ++ else { ++ HINIC3_LOG(WARNING, BOND, "Get bond link speed failed, unknow bond mode.\n"); ++ *speed = 0; ++ } ++ return ret; ++} ++ ++int ++hinic3_bond_link_update(struct rte_eth_dev *dev, int wait_to_complete) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ int ret = 0; ++ uint32_t status = 0; ++ uint32_t speed = 0; ++ struct rte_eth_link bond_dev_link = { ++ .link_speed = RTE_ETH_SPEED_NUM_NONE, ++ .link_duplex = RTE_ETH_LINK_FULL_DUPLEX, ++ .link_status = RTE_ETH_LINK_DOWN, ++ .link_autoneg = RTE_ETH_LINK_FIXED, ++ }; ++ ++ const struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ struct rte_eth_dev_data *data = dev->data; ++ ++ ret = hinic3_get_bond_link_status(bond_dev->bond_name, &status); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "Failed to obtain the link status"); ++ return ret; ++ } ++ ++ bond_dev_link.link_status = status; ++ if (status == RTE_ETH_LINK_DOWN) { ++ data->dev_link = bond_dev_link; ++ return 0; ++ } ++ ++ ret = hinic3_get_bond_link_speed(bond_dev, &speed); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "Failed to obtain the bond speed"); ++ data->dev_link = bond_dev_link; ++ return ret; ++ } ++ ++ bond_dev_link.link_speed = speed; ++ ++ data->dev_link = bond_dev_link; ++ return 0; ++} ++ ++int ++hinic3_bond_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ int ret = 0; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ struct rte_eth_dev_data *data = dev->data; ++ ++ if (bond_dev->mtu == mtu) ++ return 0; ++ ++ if (mtu > HINIC3_PF_MTU_MAX || mtu < HINIC3_PF_MTU_MIN) { ++ HINIC3_LOG(ERR, BOND, "the MTU value range is incorrect"); ++ return -ERANGE; ++ } ++ ++ if (bond_dev->vport_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, BOND, "invalid vport id!"); ++ return -EPERM; ++ } ++ ++ ret = hinic3_port_upcall_mtu_set(OVS_VPORT_TYPE_BOND, HINIC3_BOND_MTU_MAX); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "hinic3 pf set mtu failed, vport:%u!", bond_dev->vport_id); ++ return ret; ++ } ++ ++ bond_dev->mtu = mtu; ++ data->mtu = mtu; ++ ++ return ret; ++} ++ ++int ++hinic3_bond_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, const struct rte_flow_ops **ops) ++{ ++ *ops = g_hinic3_pf_flow_ops; ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h +new file mode 100644 +index 0000000..d145013 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h +@@ -0,0 +1,91 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_BOND_CONTROLLER_H ++#define HINIC3_BOND_CONTROLLER_H ++ ++#include ++#include "hinic3_queue.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++#define HINIC3_PF_DEFAULT_MTU 9058 ++#define HINIC3_PF_DEFAULT_NB_QUEUES 1 ++#define HINIC3_MAX_JUMBO_FRAME_SIZE 9626 ++#define HINIC3_PF_MTU_MAX 9058 ++#define HINIC3_PF_MTU_MIN 1500 ++#define HINIC3_PF_SIEZ_OFFSET 96 /* vxlan头(74) + 内层eth头(14) + 内层vlan(4) + FCS(4) */ ++ ++#define MAX_NAME 32 ++#define HW_PTR_ADD(ptr, x) ((void *)((uintptr_t)(ptr) + (x))) ++ ++#define HINIC3_PORTS_MEM_NAME "hinic3_ports" ++ ++/* 此处将bond口及VF端口私有数据的首个uint16数据作为端口的vport_id,注意不要更换vport_id的位置 */ ++struct hinic3_bond_dev { ++ uint16_t vport_id; ++ uint16_t bond_id; ++ char bond_name[MAX_NAME]; ++ uint16_t port_ifindex; ++ struct rte_pci_addr uplink_pci_addr; ++ uint8_t dpdk_port_id; ++ uint32_t mtu; ++ struct hinic3_upcall_queue upcall_queue; ++ struct hinic3_reinject_queue reinject_queue; ++ uint8_t n_upcall_queue; ++ uint8_t n_txq; ++ rte_atomic64_t pf_upcall_pk_num; ++ rte_atomic64_t pf_upcall_pk_byt; ++ rte_atomic64_t pf_reinject_pk_num; ++ rte_atomic64_t pf_reinject_pk_byt; ++ bool priority_upcall; ++}; ++ ++static inline struct hinic3_bond_dev *hinic3_ethdev_get_bond_private(struct rte_eth_dev *dev) ++{ ++ return (struct hinic3_bond_dev *)dev->data->dev_private; ++} ++ ++typedef struct hinic3_port_stats_ hinic3_port_stats; ++ ++/* bond控制器类初始化 */ ++void hinic3_bond_flow_ops_construct(void); ++/* bond控制器类逆初始化 */ ++void hinic3_bond_flow_ops_destroy(void); ++/* 获取设备信息 */ ++int hinic3_bond_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info); ++/* 对设备进行同步设置 */ ++int hinic3_bond_dev_configure(struct rte_eth_dev *dev); ++/* 设备启动 */ ++int hinic3_bond_dev_start(struct rte_eth_dev *dev); ++/* 设备停止 */ ++int hinic3_bond_dev_stop(struct rte_eth_dev *dev); ++/* 设置设备的连接状态为down */ ++int hinic3_bond_set_link_down(struct rte_eth_dev *dev); ++/* 设置设备的连接状态为up */ ++int hinic3_bond_set_link_up(struct rte_eth_dev *dev); ++/* 设备退出 */ ++int hinic3_bond_dev_close(struct rte_eth_dev *dev); ++/* 更新设备连接状态 */ ++int hinic3_bond_link_update(struct rte_eth_dev *dev, int wait_to_complete); ++/* 设置设备的mtu */ ++int hinic3_bond_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu); ++ ++/* 释放设备的rx队列 */ ++void hinic3_bond_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id); ++/* 释放设备的tx队列 */ ++void hinic3_bond_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id); ++ ++/* 设置设备的rx队列 */ ++int hinic3_bond_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_rxconf *conf, struct rte_mempool *mp); ++/* 设置设备的tx队列 */ ++int hinic3_bond_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_txconf *conf); ++/* rte_flow接口 */ ++int hinic3_bond_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, const struct rte_flow_ops **ops); ++/* 获取bond口 link状态 */ ++int hinic3_get_bond_link_status(const char *bond_name, uint32_t *status); ++#endif /* HINIC3_BOND_CONTROLLER_H */ +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c +new file mode 100644 +index 0000000..6f48552 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c +@@ -0,0 +1,135 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_dfx_port.h" ++#include "hinic3_port_util.h" ++#include "hinic3_bond_controller.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++#include "hinic3_bond_statistics.h" ++ ++int ++hinic3_bond_dev_stats_reset(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ int ret = 0; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ ++ ret = hinic3_port_statistics_flush(bond_dev->vport_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 bond stats reset failed, vport:%hu!", bond_dev->vport_id); ++ return ret; ++ } ++ return 0; ++} ++ ++int ++hinic3_bond_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned int n) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ if (xstats == NULL) { ++ HINIC3_LOG(ERR, BOND, "xstats is null"); ++ return -EINVAL; ++ } ++ ++ int ret = 0; ++ hinic3_port_stats port_xstats = { 0 }; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ ++ if (n < HW_NB_XSTATS) { ++ HINIC3_LOG(ERR, BOND, "The maximum number is less than the expected number"); ++ return -ERANGE; ++ } ++ ++ for (int i = 0; i < HW_NB_XSTATS; i++) ++ xstats[i].id = i; ++ ++ ret = hinic3_port_statistics_get(bond_dev->vport_id, &port_xstats); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "Failed to obtain port information from the hovs"); ++ return ret; ++ } ++ ++ xstats[XSTATS_UPCALL_PKT_INDEX].value = rte_atomic64_read(&bond_dev->pf_upcall_pk_num); ++ xstats[XSTATS_REINJECT_PKT_INDEX].value = rte_atomic64_read(&bond_dev->pf_reinject_pk_num); ++ xstats[XSTATS_UPCALL_DROP_INDEX].value = port_xstats.upcall_wqe_fail_dropped; ++ return HW_NB_XSTATS; ++} ++ ++int ++hinic3_bond_dev_xstats_reset(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ int ret = 0; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ ++ ret = hinic3_port_statistics_flush(bond_dev->vport_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 pf xstats reset failed, vport:%hu!", bond_dev->vport_id); ++ return -1; ++ } ++ ++ rte_atomic64_set(&bond_dev->pf_upcall_pk_num, 0); ++ rte_atomic64_set(&bond_dev->pf_reinject_pk_num, 0); ++ return 0; ++} ++ ++int ++hinic3_bond_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned int limit) ++{ ++ return hinic3_port_xstats_get_names(dev, xstats_names, limit); ++} ++ ++int ++hinic3_bond_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) ++ return -EINVAL; ++ ++ if (stats == NULL) { ++ HINIC3_LOG(ERR, BOND, "The dev or stats is NULL"); ++ return -EINVAL; ++ } ++ ++ int ret = 0; ++ hinic3_port_stats hinic3_stats = {0}; ++ struct hovs_bond_slave_stats bond_slave_info = {0}; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(dev); ++ ++ ret = hinic3_port_statistics_get(bond_dev->vport_id, &hinic3_stats); ++ if (ret != 0) ++ return ret; ++ ++ ret = hinic3_port_mgmt_get_bond_slave_info(bond_dev->vport_id, &bond_slave_info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "can't dump bond slave info, errno is %d\n", ret); ++ return -1; ++ } ++ ++ for (uint8_t index = 1; index < HINIC3_BOND_SLAVE_NUM; index++) { ++ bond_slave_info.rx_pkts[0] += bond_slave_info.rx_pkts[index]; ++ bond_slave_info.tx_pkts[0] += bond_slave_info.tx_pkts[index]; ++ bond_slave_info.rx_bytes[0] += bond_slave_info.rx_bytes[index]; ++ bond_slave_info.tx_bytes[0] += bond_slave_info.tx_bytes[index]; ++ } ++ ++ // 端口报文统计信息,只统计慢路径的数据 ++ stats->ipackets = rte_atomic64_read(&bond_dev->pf_upcall_pk_num); ++ stats->opackets = rte_atomic64_read(&bond_dev->pf_reinject_pk_num); ++ stats->ibytes = rte_atomic64_read(&bond_dev->pf_upcall_pk_byt); ++ stats->obytes = rte_atomic64_read(&bond_dev->pf_reinject_pk_byt); ++ stats->imissed = hinic3_stats.rx_wqe_fail_dropped + hinic3_stats.ovs_port_stats.rx_dropped; ++ stats->ierrors = hinic3_stats.ovs_port_stats.rx_errors; ++ stats->oerrors = hinic3_stats.ovs_port_stats.tx_errors + hinic3_stats.ovs_port_stats.tx_dropped; ++ stats->rx_nombuf = hinic3_stats.rx_wqe_fail_dropped; ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.h +new file mode 100644 +index 0000000..2d6677e +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_BOND_STATISTICS_H ++#define HINIC3_BOND_STATISTICS_H ++ ++/* 网卡收发包简要统计清空 */ ++int hinic3_bond_dev_stats_reset(struct rte_eth_dev *dev); ++/* 网卡收发包简要信息统计 */ ++int hinic3_bond_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); ++/* 网卡收发包详细信息统计 */ ++int hinic3_bond_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned int n); ++/* 网卡收发包详细统计清空 */ ++int hinic3_bond_dev_xstats_reset(struct rte_eth_dev *dev); ++/* 网卡收发包详细统计条目名称 */ ++int hinic3_bond_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, ++ unsigned int limit); ++#endif /* HINIC3_BOND_STATISTICS_H */ +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.c +new file mode 100644 +index 0000000..a7a0a12 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.c +@@ -0,0 +1,128 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_iface_global.h" ++#include "hinic3_command.h" ++#include "hinic3_queue.h" ++ ++static bool g_virtual_queue_mode_enabled = false; ++ ++bool ++hinic3_get_virtual_queue_mode_enabled(void) ++{ ++ return g_virtual_queue_mode_enabled; ++} ++ ++int ++hinic3_queue_init(void) ++{ ++ int ret = -EPERM; ++ ++ hinic3_eth_dev_tx_lock_init(); ++ ++ if (hinic3_virtual_queue_multiplex_get() <= 1) { // 读配置文件判断软件模拟功能是否开启 ++ ret = 0; ++ g_virtual_queue_mode_enabled = false; ++ HINIC3_LOG(INFO, VPORT, "queue module is on standard mode.\n"); ++ } else { ++ ret = hinic3_virtual_queue_init(); ++ g_virtual_queue_mode_enabled = true; ++ HINIC3_LOG(INFO, VPORT, "queue module is on virtual mode.\n"); ++ } ++ ++ return ret; ++} ++ ++void ++hinic3_queue_uninit(void) ++{ ++ if (g_virtual_queue_mode_enabled == false) ++ return; ++ else ++ hinic3_virtual_queue_uninit(); ++} ++ ++int ++hinic3_queue_valid(struct hinic3_queue *queue) ++{ ++ if (HINIC3_UNLIKELY(queue->vport_id == HINIC3_PORT_ID_INVALID)) ++ return -EINVAL; ++ ++ if (HINIC3_UNLIKELY(queue->dpdk_port_id == INVALID_DPDK_PORT_ID)) ++ return -EINVAL; ++ ++ if (queue->type == HINIC3_TX_QUEUE) ++ return 0; ++ ++ if (g_virtual_queue_mode_enabled == false) ++ return hinic3_standard_queue_valid(queue->variant.standard_queue); ++ else ++ return hinic3_virtual_queue_valid(queue->variant.virtual_queue); ++} ++ ++int ++hinic3_alloc_queues_to_port(struct hinic3_upcall_queue *upcall_queue, uint8_t upcall_queue_num) ++{ ++ if (upcall_queue_num > MAX_RX_QUEUE_PER_VPORT || upcall_queue_num == 0) { ++ HINIC3_LOG(ERR, VPORT, "alloc queues failed, invalid argument.\n"); ++ return -EINVAL; ++ } ++ ++ int ret = -EPERM; ++ struct hinic3_virtual_queue *virtual_queues[MAX_RX_QUEUE_PER_VPORT] = {0}; ++ struct hinic3_queue *queue_array = ++ (struct hinic3_queue *)hinic3_calloc(upcall_queue_num, sizeof(struct hinic3_queue), HINIC3_PORTS); ++ if (queue_array == NULL) { ++ HINIC3_LOG(ERR, VPORT, "alloc queues failed, no enough memory.\n"); ++ return -ENOMEM; ++ } ++ ++ if (g_virtual_queue_mode_enabled == false) ++ return 0; ++ else { ++ ret = hinic3_take_virtual_queue_to_vf(upcall_queue_num, ++ upcall_queue->upcall_queue_id, virtual_queues, MAX_RX_QUEUE_PER_VPORT); ++ if (ret != 0) ++ return ret; ++ ++ for (int i = 0; i < upcall_queue_num; ++i) { ++ queue_array[i].variant.virtual_queue = virtual_queues[i]; ++ upcall_queue->rx_queues[i] = &queue_array[i]; ++ } ++ } ++ ++ return 0; ++} ++ ++void hinic3_free_queues_from_port(struct hinic3_upcall_queue *upcall_queue, uint8_t upcall_queue_num) ++{ ++ if (upcall_queue_num > MAX_RX_QUEUE_PER_VPORT || upcall_queue_num == 0) ++ return; ++ ++ struct hinic3_queue *queue = NULL; ++ struct hinic3_queue *queue_array = NULL; ++ if (g_virtual_queue_mode_enabled == false) ++ return; ++ else { ++ queue_array = upcall_queue->rx_queues[0]; ++ for (int i = 0; i < upcall_queue_num; ++i) { ++ queue = upcall_queue->rx_queues[i]; ++ hinic3_take_virtual_queue_back_manager(queue->variant.virtual_queue); ++ upcall_queue->rx_queues[i] = NULL; ++ } ++ } ++ ++ hinic3_free(queue_array); ++} ++ ++void hinic3_reset_queue_info(struct hinic3_queue *queue) ++{ ++ queue->queue_id = INVALID_UPCALL_QUEUE_ID; ++ queue->vport_id = HINIC3_PORT_ID_INVALID; ++ queue->dpdk_port_id = INVALID_DPDK_PORT_ID; ++ queue->dpdk_index_id = INVALID_DPDK_PORT_ID; ++ queue->type = HINIC3_UNKNOWN_QUEUE_TYPE; ++ rte_atomic64_set(&queue->statistic.pkts, 0); ++ rte_atomic64_set(&queue->statistic.pkts_drop, 0); ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.h +new file mode 100644 +index 0000000..cfd8217 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_queue.h +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_QUEUE_H ++#define HINIC3_QUEUE_H ++ ++#include "hinic3_port_util.h" ++#include "hinic3_standard_queue.h" ++#include "hinic3_virtual_queue.h" ++ ++struct hinic3_queue { ++ uint16_t queue_id; /* 端口上的队列编号 */ ++ uint16_t vport_id; /* 队列绑定的端口vport id */ ++ uint16_t dpdk_port_id; /* vport id对应的dpdk port id */ ++ uint16_t dpdk_index_id; /* 收发包统计时用于获取到vf_dev */ ++ enum queue_type type; ++ struct hinic3_queue_statistic statistic; /* 队列级收包统计 */ ++ union { /* 该联合体表示队列的具象变体 */ ++ struct hinic3_standard_queue *standard_queue; /* 硬件标准upcall队列standard_queue有效 */ ++ struct hinic3_virtual_queue *virtual_queue; /* 软件模拟upcall队列virtual_queue有效 */ ++ } variant; /* reinject队列无需访问该联合体 */ ++}; ++ ++struct hinic3_upcall_queue { ++ bool is_queue_valid[MAX_RX_QUEUE_PER_VPORT]; ++ uint16_t upcall_queue_id[MAX_RX_QUEUE_PER_VPORT]; ++ struct hinic3_queue *rx_queues[MAX_RX_QUEUE_PER_VPORT]; ++ struct hinic3_standard_queue *rx_queue[MAX_RX_QUEUE_PER_VPORT]; ++ struct hinic3_virtual_queue *virtual_upcall_queue[MAX_RX_QUEUE_PER_VPORT]; ++}; ++ ++struct hinic3_reinject_queue { ++ bool is_queue_valid[MAX_TX_QUEUE_PER_VPORT]; ++ struct hinic3_standard_queue *tx_queues[MAX_TX_QUEUE_PER_VPORT]; ++}; ++ ++/* 获取 硬件标准/软件模拟 upcall特性开关 */ ++bool hinic3_get_virtual_queue_mode_enabled(void); ++/* 队列模块初始化 */ ++int hinic3_queue_init(void); ++/* 队列模块逆初始化 */ ++void hinic3_queue_uninit(void); ++/* 队列有效性检测 */ ++int hinic3_queue_valid(struct hinic3_queue *queue); ++/* 从队列资源池分配队列到端口 */ ++int hinic3_alloc_queues_to_port(struct hinic3_upcall_queue *upcall_queue, uint8_t upcall_queue_num); ++/* 从端口释放队列回队列资源池 */ ++void hinic3_free_queues_from_port(struct hinic3_upcall_queue *upcall_queue, uint8_t upcall_queue_num); ++/* 初始化队列结构体 */ ++void hinic3_reset_queue_info(struct hinic3_queue *queue); ++#endif /* HINIC3_QUEUE_H */ +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.c +new file mode 100644 +index 0000000..2801dea +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.c +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_port_util.h" ++#include "hinic3_standard_queue.h" ++ ++int ++hinic3_standard_queue_valid(const struct hinic3_standard_queue *queue) ++{ ++ if (HINIC3_UNLIKELY(queue->vport_id == HINIC3_PORT_ID_INVALID)) ++ return -EINVAL; ++ ++ if (HINIC3_UNLIKELY(queue->dpdk_port_id == INVALID_DPDK_PORT_ID)) ++ return -EINVAL; ++ ++ if (HINIC3_UNLIKELY(queue->upcall_queue_id == INVALID_UPCALL_QUEUE_ID)) ++ return -EINVAL; ++ ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.h +new file mode 100644 +index 0000000..5c0fafa +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_standard_queue.h +@@ -0,0 +1,36 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_STANDARD_QUEUE_H ++#define HINIC3_STANDARD_QUEUE_H ++ ++#include ++ ++enum queue_type { ++ HINIC3_RX_QUEUE, ++ HINIC3_TX_QUEUE, ++ HINIC3_STANDARD_RX_QUEUE, ++ HINIC3_VIRTUAL_RX_QUEUE, ++ HINIC3_UNKNOWN_QUEUE_TYPE, ++}; ++ ++struct hinic3_queue_statistic { ++ enum queue_type type; ++ rte_atomic64_t pkts; ++ rte_atomic64_t pkts_drop; ++}; ++ ++struct hinic3_standard_queue { ++ uint8_t dpdk_port_id; ++ uint16_t queue_id; ++ uint16_t upcall_queue_id; ++ uint16_t vport_id; ++ uint16_t dpdk_index_id; ++ struct rte_mempool *mp; ++ struct hinic3_queue_statistic info; ++}; ++ ++/* 硬件标准队列有效性检测 */ ++int hinic3_standard_queue_valid(const struct hinic3_standard_queue *queue); ++#endif /* HINIC3_STANDARD_QUEUE_H */ +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.c +new file mode 100644 +index 0000000..dd83f58 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.c +@@ -0,0 +1,300 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_port_util.h" ++#include "hinic3_virtual_queue.h" ++ ++static struct hinic3_virtual_queue_manager g_virtual_queue_manager = { 0 }; ++ ++static int ++hinic3_create_physical_and_virtual_queue_all(void) ++{ ++ struct hinic3_virtual_queue *virtual_queue = NULL; ++ struct hinic3_physical_queue *physical_queue = NULL; ++ uint8_t group_num = g_virtual_queue_manager.virtual_queue_group_num; ++ uint16_t physical_queue_num = g_virtual_queue_manager.physical_queue_num; ++ ++ /* 初始化硬件队列内存结构的值 */ ++ for (uint16_t physical_queue_index = 0; physical_queue_index < physical_queue_num; ++physical_queue_index) { ++ physical_queue = &g_virtual_queue_manager.physical_queues[physical_queue_index]; ++ physical_queue->virtual_queue_valid_cnt = 0; ++ physical_queue->hinic3_queue_id = physical_queue_index; ++ physical_queue->hiovs_queue_id = INVALID_UPCALL_QUEUE_ID; // 该值在端口configure后赋值为从组件侧获取的id ++ physical_queue->mp = NULL; ++ rte_spinlock_init(&physical_queue->physical_queue_lock); ++ } ++ /* 创初始化软件队列内存结构的值 */ ++ for (uint8_t group_index = 0; group_index < group_num; ++group_index) { ++ hinic3_list_init(&g_virtual_queue_manager.virtual_queue_groups[group_index]); ++ for (uint16_t physical_queue_index = 0; physical_queue_index < physical_queue_num; ++physical_queue_index) { ++ /* 为软件队列节点赋初始值 */ ++ virtual_queue = ++ &g_virtual_queue_manager.virtual_queues[physical_queue_index + group_index * physical_queue_num]; ++ virtual_queue->physical_queue_index = physical_queue_index; ++ virtual_queue->virtual_queue_group_index = group_index; ++ int ret = snprintf(virtual_queue->ring_name, HINIC3_VIRTUAL_QUEUE_RING_NAME_MAX, ++ "group%u-rx%u", group_index, physical_queue_index); ++ if (ret <= 0 || ret >= HINIC3_VIRTUAL_QUEUE_RING_NAME_MAX) { ++ HINIC3_LOG(ERR, VPORT, "The virtual queue ring name is misspelled."); ++ return -ERANGE; ++ } ++ hinic3_list_init(&virtual_queue->node); ++ hinic3_list_insert(&g_virtual_queue_manager.virtual_queue_groups[group_index], &virtual_queue->node); ++ /* 建立硬件队列与软件队列的映射关系 */ ++ physical_queue = &g_virtual_queue_manager.physical_queues[physical_queue_index]; ++ physical_queue->virtual_queues[group_index] = virtual_queue; ++ physical_queue->is_virtual_queue_valids[group_index] = false; ++ virtual_queue->physical_queue = physical_queue; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_virtual_queue_malloc_manager_mem(struct hinic3_port_upcall_info *info) ++{ ++ uint16_t virtual_queue_num = 0; ++ ++ g_virtual_queue_manager.physical_queue_num = info->total_upcall_qnum; ++ g_virtual_queue_manager.physical_queues = (struct hinic3_physical_queue *)hinic3_calloc( ++ g_virtual_queue_manager.physical_queue_num, sizeof(struct hinic3_physical_queue), HINIC3_PORTS); ++ if (g_virtual_queue_manager.physical_queues == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to create physical queues."); ++ goto fail; ++ }; ++ ++ g_virtual_queue_manager.virtual_queue_group_num = hinic3_virtual_queue_multiplex_get(); ++ g_virtual_queue_manager.virtual_queue_groups = (struct hinic3_list *)hinic3_calloc( ++ g_virtual_queue_manager.virtual_queue_group_num, sizeof(struct hinic3_list), HINIC3_PORTS); ++ if (g_virtual_queue_manager.virtual_queue_groups == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to create virtual queue groups."); ++ goto fail; ++ }; ++ ++ virtual_queue_num = g_virtual_queue_manager.physical_queue_num * g_virtual_queue_manager.virtual_queue_group_num; ++ g_virtual_queue_manager.virtual_queues = ++ (struct hinic3_virtual_queue *)hinic3_calloc(virtual_queue_num, sizeof(struct hinic3_virtual_queue), HINIC3_PORTS); ++ if (g_virtual_queue_manager.virtual_queues == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to create virtual queues."); ++ goto fail; ++ } ++ ++ return 0; ++fail: ++ hinic3_virtual_queue_uninit(); ++ return -ENOMEM; ++} ++ ++int ++hinic3_virtual_queue_init(void) ++{ ++ int ret = 0; ++ struct hinic3_port_upcall_info info = {0}; ++ ++ ret = hinic3_port_mgmt_get_upcall_info(&info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to get mgmt upcall queue info."); ++ return ret; ++ } ++ ++ ret = hinic3_pthread_mutex_init(&g_virtual_queue_manager.mutex); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to init virtual queue manager mutex."); ++ return ret; ++ } ++ ++ ret = hinic3_virtual_queue_malloc_manager_mem(&info); ++ if (ret != 0) ++ return ret; ++ ++ ret = hinic3_create_physical_and_virtual_queue_all(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to init virtual queue"); ++ hinic3_virtual_queue_uninit(); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++void ++hinic3_virtual_queue_uninit(void) ++{ ++ // 先释放端口,返还所有软件队列到链表 ++ if (g_virtual_queue_manager.virtual_queues != NULL) ++ hinic3_free(g_virtual_queue_manager.virtual_queues); ++ ++ if (g_virtual_queue_manager.virtual_queue_groups != NULL) ++ hinic3_free(g_virtual_queue_manager.virtual_queue_groups); ++ ++ if (g_virtual_queue_manager.physical_queues != NULL) ++ hinic3_free(g_virtual_queue_manager.physical_queues); ++ ++ hinic3_pthread_mutex_destroy(&g_virtual_queue_manager.mutex); ++ return; ++} ++ ++static void ++hinic3_move_node_to_other_list(struct hinic3_list *src_list, struct hinic3_list *dst_list) ++{ ++ struct hinic3_list *node; ++ node = src_list->next; ++ hinic3_list_remove(src_list->next); ++ hinic3_list_init(node); ++ hinic3_list_insert(dst_list->next, node); ++} ++ ++static struct hinic3_virtual_queue * ++hinic3_check_virtual_queue_available(uint8_t group_index, bool *is_physical_queue_selected, struct hinic3_list *buffer) ++{ ++ struct hinic3_virtual_queue *virtual_queue = NULL; ++ ++ while (hinic3_list_is_empty(&g_virtual_queue_manager.virtual_queue_groups[group_index]) == false) { ++ virtual_queue = HINIC3_CONTAINER_OF( ++ g_virtual_queue_manager.virtual_queue_groups[group_index].next, struct hinic3_virtual_queue, node); ++ if (is_physical_queue_selected[virtual_queue->physical_queue_index] == true) ++ hinic3_move_node_to_other_list(&g_virtual_queue_manager.virtual_queue_groups[group_index], buffer); ++ else ++ break; // 不允许跨group取的软件队列映射到同一个硬件队列上 ++ } ++ ++ return virtual_queue; ++} ++ ++int ++hinic3_take_virtual_queue_to_vf(uint8_t upcall_queue_num, uint16_t upcall_queue_ids[], ++ struct hinic3_virtual_queue *virtual_queues[], uint8_t virtual_queue_size) ++{ ++ int alloced_queue_num = 0; ++ struct hinic3_virtual_queue *virtual_queue = NULL; ++ bool *is_physical_queue_selected = NULL; ++ uint16_t physical_queue_num = g_virtual_queue_manager.physical_queue_num; ++ struct hinic3_list buffer; ++ ++ hinic3_list_init(&buffer); ++ is_physical_queue_selected = (bool *)hinic3_calloc(physical_queue_num, sizeof(bool), HINIC3_PORTS); ++ if (is_physical_queue_selected == NULL) { ++ HINIC3_LOG(ERR, VPORT, "take virtual queues failed, no enough memory.\n"); ++ return -ENOMEM; ++ } ++ ++ upcall_queue_num = upcall_queue_num > virtual_queue_size ? virtual_queue_size : upcall_queue_num; ++ hinic3_pthread_mutex_lock(&g_virtual_queue_manager.mutex); ++ for (uint8_t idx = 0; idx < upcall_queue_num; ++idx) { ++ for (uint8_t group_index = 0; group_index < g_virtual_queue_manager.virtual_queue_group_num; ++group_index) { ++ virtual_queue = hinic3_check_virtual_queue_available(group_index, is_physical_queue_selected, &buffer); ++ if (virtual_queue == NULL) ++ continue; ++ ++ hinic3_list_remove(&virtual_queue->node); ++ virtual_queues[idx] = virtual_queue; ++ upcall_queue_ids[idx] = virtual_queue->physical_queue->hinic3_queue_id; ++ is_physical_queue_selected[virtual_queue->physical_queue_index] = true; ++ ++alloced_queue_num; ++ break; ++ } ++ } ++ ++ while (hinic3_list_is_empty(&buffer) == false) { ++ virtual_queue = HINIC3_CONTAINER_OF(buffer.next, struct hinic3_virtual_queue, node); ++ hinic3_move_node_to_other_list( ++ &buffer, &g_virtual_queue_manager.virtual_queue_groups[virtual_queue->virtual_queue_group_index]); ++ } ++ hinic3_pthread_mutex_unlock(&g_virtual_queue_manager.mutex); ++ ++ hinic3_free(is_physical_queue_selected); ++ if (alloced_queue_num != upcall_queue_num) { ++ for (uint8_t idx = 0; idx < alloced_queue_num; ++idx) { ++ hinic3_take_virtual_queue_back_manager(virtual_queues[idx]); ++ upcall_queue_ids[idx] = INVALID_UPCALL_QUEUE_ID; ++ } ++ HINIC3_LOG(ERR, VPORT, "virtual rx queues is not enough"); ++ return -ENOSPC; ++ } ++ return 0; ++} ++ ++void ++hinic3_take_virtual_queue_back_manager(struct hinic3_virtual_queue *virtual_queue) ++{ ++ if (virtual_queue->ring != NULL) { ++ rte_ring_free(virtual_queue->ring); ++ virtual_queue->ring = NULL; ++ } ++ virtual_queue->queue_info = NULL; ++ hinic3_list_init(&virtual_queue->node); ++ hinic3_list_insert( ++ &g_virtual_queue_manager.virtual_queue_groups[virtual_queue->virtual_queue_group_index], &virtual_queue->node); ++ virtual_queue = NULL; ++} ++ ++int ++hinic3_virtual_queue_valid(const struct hinic3_virtual_queue *virtual_queue) ++{ ++ struct hinic3_physical_queue *physical_queue = virtual_queue->physical_queue; ++ ++ if (HINIC3_UNLIKELY(virtual_queue->queue_info == NULL)) ++ return -EINVAL; ++ ++ if (HINIC3_UNLIKELY(physical_queue->hiovs_queue_id == INVALID_UPCALL_QUEUE_ID)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++int ++hinic3_virtual_queue_get_upcall_info(struct hinic3_virtual_queue_info *info) ++{ ++ if (info == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to get virtual queues info."); ++ return -EINVAL; ++ } ++ hinic3_pthread_mutex_lock(&g_virtual_queue_manager.mutex); ++ info->physical_queue_num = g_virtual_queue_manager.physical_queue_num; ++ info->virtual_queue_group_num = g_virtual_queue_manager.virtual_queue_group_num; ++ info->total_virtual_queue_num = info->physical_queue_num * info->virtual_queue_group_num; ++ info->left_virtual_queue_num = 0; ++ for (uint8_t group_index = 0; group_index < info->virtual_queue_group_num; ++group_index) { ++ info->left_group_queue_num[group_index] = ++ hinic3_list_size(&g_virtual_queue_manager.virtual_queue_groups[group_index]); ++ info->left_virtual_queue_num += info->left_group_queue_num[group_index]; ++ } ++ hinic3_pthread_mutex_unlock(&g_virtual_queue_manager.mutex); ++ return 0; ++} ++ ++struct hinic3_virtual_queue * ++hinic3_get_virtual_queue_by_ring(const char *ring_name) ++{ ++ if (ring_name == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to get virtual queues by ring name."); ++ return NULL; ++ } ++ ++ uint16_t total_virtual_queue_num = ++ g_virtual_queue_manager.physical_queue_num * g_virtual_queue_manager.virtual_queue_group_num; ++ struct hinic3_virtual_queue *virtual_queue = NULL; ++ ++ hinic3_pthread_mutex_lock(&g_virtual_queue_manager.mutex); ++ for (uint16_t idx = 0; idx < total_virtual_queue_num; ++idx) { ++ virtual_queue = &g_virtual_queue_manager.virtual_queues[idx]; ++ if (strcmp(virtual_queue->ring_name, ring_name) == 0) { ++ hinic3_pthread_mutex_unlock(&g_virtual_queue_manager.mutex); ++ return virtual_queue; ++ } ++ } ++ ++ hinic3_pthread_mutex_unlock(&g_virtual_queue_manager.mutex); ++ return NULL; ++} ++ ++struct hinic3_physical_queue * ++hinic3_get_physical_queue_by_index(uint16_t index) ++{ ++ if (index >= g_virtual_queue_manager.physical_queue_num) ++ return NULL; ++ ++ return &g_virtual_queue_manager.physical_queues[index]; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.h +new file mode 100644 +index 0000000..15fcb10 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_queue/hinic3_virtual_queue.h +@@ -0,0 +1,72 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VIRTUAL_QUEUE_H ++#define HINIC3_VIRTUAL_QUEUE_H ++ ++#include "rte_ring.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_standard_queue.h" ++ ++#define HINIC3_VIRTUAL_QUEUE_RING_NAME_MAX 16 ++ ++struct hinic3_virtual_queue { ++ /* 静态成员,赋初始值后只读取不变更 */ ++ struct hinic3_list node; /* 链表节点 */ ++ uint8_t virtual_queue_group_index; /* 描述该软件队列属于第几组 */ ++ uint16_t physical_queue_index; /* 软件队列的队列id,值与其映射的硬件队列id相等 */ ++ struct hinic3_physical_queue *physical_queue; /* 该软件队列映射的硬件队列指针 */ ++ char ring_name[HINIC3_VIRTUAL_QUEUE_RING_NAME_MAX]; /* 环形队列name,可通过lookup接口获取队列指针 */ ++ /* 动态成员,队列分配返还时变更 */ ++ struct rte_ring *ring; /* 环形队列,存mbuf指针 */ ++ struct hinic3_queue *queue_info; /* 软件队列映射的抽象部分数据 */ ++}; ++ ++struct hinic3_physical_queue { ++ /* 静态成员,赋初始值后只读取不变更 */ ++ rte_spinlock_t physical_queue_lock; /* 硬件队列自旋锁 */ ++ uint16_t hinic3_queue_id; /* 硬件队列id,0——队列最大值 */ ++ uint16_t hiovs_queue_id; /* 硬件队列组件侧id,与硬件队列id一对一映射 */ ++ struct hinic3_virtual_queue *virtual_queues[HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MAX]; /* 硬件队列映射的软件队列的列表 */ ++ /* 动态成员,队列分配返还时变更 */ ++ bool is_virtual_queue_valids[HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MAX]; /* 标记映射的软件队列是否激活到某端口 */ ++ uint8_t virtual_queue_valid_cnt; /* 硬件队列在被几个激活的软件队列共享 */ ++ struct rte_mempool *mp; /* 硬件队列要取包的内存池 */ ++}; ++ ++struct hinic3_virtual_queue_manager { /* 软件模拟队列资源池 */ ++ struct hinic3_list *virtual_queue_groups; /* 软件队列组链表头节点的数组 */ ++ uint8_t virtual_queue_group_num; /* 软件队列组链表头节点的数组大小 */ ++ struct hinic3_physical_queue *physical_queues; /* 硬件队列动态数组指针 */ ++ uint16_t physical_queue_num; /* 硬件队列动态数组大小 */ ++ struct hinic3_virtual_queue *virtual_queues; /* 软件队列数组指针,大小为physical_queue_num * virtual_queue_group_num */ ++ struct hinic3_mutex mutex; ++}; ++ ++struct hinic3_virtual_queue_info { ++ uint8_t virtual_queue_group_num; ++ uint16_t physical_queue_num; ++ uint16_t total_virtual_queue_num; ++ uint16_t left_group_queue_num[HINIC3_VIRTUAL_QUEUE_MULTIPLEX_MAX]; ++ uint16_t left_virtual_queue_num; ++}; ++ ++/* 软件模拟初始化 */ ++int hinic3_virtual_queue_init(void); ++/* 软件模拟逆初始化 */ ++void hinic3_virtual_queue_uninit(void); ++/* 分配软件模拟队列 */ ++int hinic3_take_virtual_queue_to_vf(uint8_t upcall_queue_num, uint16_t upcall_queue_ids[], ++ struct hinic3_virtual_queue *virtual_queues[], uint8_t virtual_queue_size); ++/* 释放软件模拟队列 */ ++void hinic3_take_virtual_queue_back_manager(struct hinic3_virtual_queue *virtual_queue); ++/* 软件模拟队列有效性检测 */ ++int hinic3_virtual_queue_valid(const struct hinic3_virtual_queue *virtual_queue); ++/* 获取软件模拟队列使用情况 */ ++int hinic3_virtual_queue_get_upcall_info(struct hinic3_virtual_queue_info *info); ++/* 用软件模拟队列id查询软件队列 */ ++struct hinic3_virtual_queue *hinic3_get_virtual_queue_by_ring(const char *ring_name); ++/* 使用硬件队列id查询硬件队列 */ ++struct hinic3_physical_queue *hinic3_get_physical_queue_by_index(uint16_t index); ++#endif /* HINIC3_VIRTUAL_QUEUE_H */ +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c +new file mode 100644 +index 0000000..e4d4432 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c +@@ -0,0 +1,1111 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "rte_kvargs.h" ++#include "rte_devargs.h" ++#include "hinic3_bond_statistics.h" ++#include "hinic3_bond_controller.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_function_statistics.h" ++#include "hinic3_offload_flow.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_qos.h" ++#include "hinic3_set_userdata.h" ++#include "hinic3_vdev.h" ++ ++#define MAX_NAME 32 ++#define PRIORITY_ENABLE_LEN 10 ++#define HINIC3_VF_MAX_QUEUE_DEFAULT_NUM 1 ++#define HINIC3_VF_DEFAULT_MTU 1500 ++#define HINIC3_VF_MIN_FUNCTION_ID 0 ++#define HINIC3_METER_RTE_MBUF_GET_PTR 8 ++#define HINIC3_NETDEV_MAX_BURST 32 ++ ++#define HINIC3_ETH_DEV_FLOW_OPS_THREAD_SAFE 0x0001 ++#define HINIC3_REPRESENTOR_FLAG (1 << 4) ++ ++static const char * const hinic3_vdev_valid_arguments[] = { ++ HINIC3_BOND_NAME, ++ HINIC3_PORT_PCI_ID, ++ HINIC3_PORT_MAC, ++ HINIC3_MAX_QUEUE_NUM, ++ HINIC3_REPRESENTOR_ID, ++ HINIC3_PRIORITY_UPCALL, ++ NULL ++}; ++ ++static struct rte_eth_link g_hinic3_pf_vdev_link = { ++ .link_speed = RTE_ETH_SPEED_NUM_10G, ++ .link_duplex = RTE_ETH_LINK_FULL_DUPLEX, ++ .link_status = RTE_ETH_LINK_UP, ++ .link_autoneg = RTE_ETH_LINK_FIXED, ++}; ++ ++static struct rte_eth_link g_hinic3_vf_dev_link = { ++ .link_speed = RTE_ETH_SPEED_NUM_10G, ++ .link_duplex = RTE_ETH_LINK_FULL_DUPLEX, ++ .link_status = RTE_ETH_LINK_DOWN, ++ .link_autoneg = RTE_ETH_LINK_FIXED, ++}; ++ ++static struct eth_dev_ops *g_hinic3_vf_vdev_ops = NULL; ++static struct eth_dev_ops *g_hinic3_bond_vdev_ops = NULL; ++ ++struct open_str_extra_args { ++ size_t extra_args_str_len; ++ char* extra_args_str; ++}; ++ ++static void ++hinic3_vf_dev_ops_construct(void) ++{ ++ struct eth_dev_ops *edev_ops = NULL; ++ ++ edev_ops = hinic3_calloc(1, sizeof(struct eth_dev_ops), HINIC3_PORTS); ++ if (edev_ops == NULL) ++ return; ++ ++ if (hinic3_get_virtual_queue_mode_enabled() == true) { ++ edev_ops->rx_queue_setup = hinic3_vf_virtual_rx_queue_setup; ++ edev_ops->rx_queue_release = hinic3_vf_virtual_rx_queue_release; ++ } else { ++ edev_ops->rx_queue_setup = hinic3_vf_rx_queue_setup; ++ edev_ops->rx_queue_release = hinic3_vf_rx_queue_release; ++ } ++ edev_ops->dev_configure = hinic3_vf_dev_configure; ++ edev_ops->dev_start = hinic3_vf_dev_start; ++ edev_ops->dev_stop = hinic3_vf_dev_stop; ++ edev_ops->dev_close = hinic3_vf_dev_close; ++ edev_ops->dev_set_link_down = hinic3_vf_set_link_down; ++ edev_ops->dev_set_link_up = hinic3_vf_set_link_up; ++ edev_ops->dev_infos_get = hinic3_vf_dev_infos_get; ++ edev_ops->stats_get = hinic3_vf_dev_stats_get; ++ edev_ops->stats_reset = hinic3_vf_dev_stats_reset; ++ edev_ops->xstats_get = hinic3_vf_dev_xstats_get; ++ edev_ops->xstats_reset = hinic3_vf_dev_xstats_reset; ++ edev_ops->xstats_get_names = hinic3_vf_dev_xstats_get_names; ++ edev_ops->link_update = hinic3_vf_link_update; ++ edev_ops->mtu_set = hinic3_vf_dev_set_mtu; ++ edev_ops->tx_queue_setup = hinic3_vf_tx_queue_setup; ++ edev_ops->tx_queue_release = hinic3_vf_tx_queue_release; ++ edev_ops->flow_ops_get = hinic3_vf_dev_flow_ops_get; ++ edev_ops->mac_addr_set = hinic3_vf_dev_mac_addr_set; ++ edev_ops->mtr_ops_get = hinic3_mtr_ops_get; ++ ++ g_hinic3_vf_vdev_ops = edev_ops; ++} ++ ++static void ++hinic3_vf_dev_ops_destroy(void) ++{ ++ if (g_hinic3_vf_vdev_ops == NULL) ++ return; ++ ++ hinic3_free(g_hinic3_vf_vdev_ops); ++ g_hinic3_vf_vdev_ops = NULL; ++} ++ ++static void ++hinic3_bond_dev_ops_construct(void) ++{ ++ struct eth_dev_ops *edev_ops = NULL; ++ ++ edev_ops = hinic3_calloc(1, sizeof(struct eth_dev_ops), HINIC3_PORTS); ++ if (edev_ops == NULL) ++ return; ++ ++ edev_ops->dev_configure = hinic3_bond_dev_configure; ++ edev_ops->dev_start = hinic3_bond_dev_start; ++ edev_ops->dev_stop = hinic3_bond_dev_stop; ++ edev_ops->dev_close = hinic3_bond_dev_close; ++ edev_ops->dev_set_link_down = hinic3_bond_set_link_down; ++ edev_ops->dev_set_link_up = hinic3_bond_set_link_up; ++ edev_ops->dev_infos_get = hinic3_bond_dev_infos_get; ++ edev_ops->stats_get = hinic3_bond_dev_stats_get; ++ edev_ops->stats_reset = hinic3_bond_dev_stats_reset; ++ edev_ops->xstats_get = hinic3_bond_dev_xstats_get; ++ edev_ops->xstats_reset = hinic3_bond_dev_xstats_reset; ++ edev_ops->xstats_get_names = hinic3_bond_dev_xstats_get_names; ++ edev_ops->link_update = hinic3_bond_link_update; ++ edev_ops->mtu_set = hinic3_bond_dev_set_mtu; ++ edev_ops->rx_queue_setup = hinic3_bond_rx_queue_setup; ++ edev_ops->tx_queue_setup = hinic3_bond_tx_queue_setup; ++ edev_ops->rx_queue_release = hinic3_bond_rx_queue_release; ++ edev_ops->tx_queue_release = hinic3_bond_tx_queue_release; ++ edev_ops->flow_ops_get = hinic3_bond_dev_flow_ops_get; ++ edev_ops->mtr_ops_get = hinic3_mtr_ops_get; ++ ++ g_hinic3_bond_vdev_ops = edev_ops; ++} ++ ++static void ++hinic3_bond_dev_ops_destroy(void) ++{ ++ if (g_hinic3_bond_vdev_ops == NULL) ++ return; ++ ++ hinic3_free(g_hinic3_bond_vdev_ops); ++ g_hinic3_bond_vdev_ops = NULL; ++} ++ ++ ++static int ++open_u32(const char *key __rte_unused, const char *value, void *extra_args) ++{ ++ uint32_t *n = extra_args; ++ char *endPtr = NULL; ++ ++ if (value == NULL || extra_args == NULL) ++ return -EINVAL; ++ ++ *n = (uint32_t)strtoul(value, &endPtr, 0); ++ if (endPtr == NULL || *endPtr != '\0') ++ return -1; ++ ++ if (*n == USHRT_MAX && errno == ERANGE) ++ return -1; ++ ++ return 0; ++} ++ ++static int ++open_mac(const char *key __rte_unused, const char *value, void *extra_args) ++{ ++ struct eth_addr *n = extra_args; ++ ++ if (value == NULL || extra_args == NULL) ++ return -EINVAL; ++ ++ if (rte_ether_unformat_addr(value, (struct rte_ether_addr *)n) != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to parse mac addr from str!"); ++ return -1; ++ } ++ if (eth_addr_is_zero(*n) == true) { ++ HINIC3_LOG(ERR, VPORT, "mac addr is zero!"); ++ return -1; ++ } ++ if (eth_addr_is_multicast(*n) == true) { ++ HINIC3_LOG(ERR, VPORT, "mac addr can't be multicast!"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++open_pci(const char *key __rte_unused, const char *value, void *extra_args) ++{ ++ struct rte_pci_addr *n = extra_args; ++ ++ if (value == NULL || extra_args == NULL) ++ return -1; ++ ++ if (rte_pci_addr_parse(value, n) != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to parse pci addr from str!"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++open_function_id(const char *key __rte_unused, const char *value, void *extra_args) ++{ ++ int *id = extra_args; ++ char *end_ptr = NULL; ++ ++ if (value == NULL || id == NULL) ++ return -1; ++ ++ *id = strtoul(value, &end_ptr, STR_TO_DEC_NUM); ++ if (*id < HINIC3_VF_MIN_FUNCTION_ID || end_ptr == NULL || *end_ptr != '\0') { ++ HINIC3_LOG(ERR, VPORT, "failed to parse function id str, id is %d.", *id); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int hinic3_vf_parse_max_queue(struct rte_kvargs *kvlist, uint32_t *max_queue_num) ++{ ++ int ret = 0; ++ uint32_t count = 0; ++ if (kvlist == NULL) ++ return -1; ++ ++ count = rte_kvargs_count(kvlist, HINIC3_MAX_QUEUE_NUM); ++ if (count > 1) { ++ HINIC3_LOG(ERR, VPORT, "multi max queue num found!"); ++ return -1; ++ } else if (count == 1) { ++ ret = rte_kvargs_process(kvlist, HINIC3_MAX_QUEUE_NUM, open_u32, max_queue_num); ++ if (ret != 0 || *max_queue_num == 0) { ++ HINIC3_LOG(ERR, VPORT, "max queue num parse failed!"); ++ return -1; ++ } ++ if (*max_queue_num > hinic3_max_queue_num_limit_get()) { ++ HINIC3_LOG(ERR, VPORT, "max queue num exceeds the max support value: %u", hinic3_max_queue_num_limit_get()); ++ return -1; ++ } ++ } else ++ *max_queue_num = HINIC3_VF_MAX_QUEUE_DEFAULT_NUM; ++ ++ return 0; ++} ++ ++static int ++hinic3_vf_parse_mac_addr(struct rte_kvargs *kvlist, struct eth_addr *mac_addr) ++{ ++ int ret = 0; ++ uint32_t count = 0; ++ if (kvlist == NULL) ++ return -1; ++ ++ count = rte_kvargs_count(kvlist, HINIC3_PORT_MAC); ++ if (count > 1) { ++ HINIC3_LOG(ERR, VPORT, "multi vf mac found!"); ++ return -1; ++ } else if (count == 1) { ++ ret = rte_kvargs_process(kvlist, HINIC3_PORT_MAC, open_mac, mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to parse mac addr!"); ++ return -1; ++ } ++ } else { ++ if (rte_ether_unformat_addr(HINIC3_VF_MAC_ADDR_DEFAULT, (struct rte_ether_addr *)mac_addr) != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to set default zero mac addr!"); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++int hinic3_vf_parse_function_id(struct rte_kvargs *kvlist, int *function_id) ++{ ++ int ret = 0; ++ uint32_t count = 0; ++ if (kvlist == NULL) ++ return -1; ++ ++ count = rte_kvargs_count(kvlist, HINIC3_REPRESENTOR_ID); ++ if (count != 1) { ++ HINIC3_LOG(ERR, VPORT, "failed to obtain the number of vf function id."); ++ return -1; ++ } ++ ++ ret = rte_kvargs_process(kvlist, HINIC3_REPRESENTOR_ID, open_function_id, function_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to parse vf function id!"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_vf_parse_pci_addr(struct rte_kvargs *kvlist, struct rte_pci_addr *pci_addr) ++{ ++ int ret = 0; ++ uint32_t count = 0; ++ if (kvlist == NULL) ++ return -1; ++ ++ count = rte_kvargs_count(kvlist, HINIC3_PORT_PCI_ID); ++ if (count == 1) { ++ ret = rte_kvargs_process(kvlist, HINIC3_PORT_PCI_ID, open_pci, pci_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to parse pci addr!"); ++ return -1; ++ } ++ } else { ++ if (count > 1) ++ HINIC3_LOG(ERR, VPORT, "The number of VF PCIs is too large"); ++ else ++ HINIC3_LOG(ERR, VPORT, "vf pci not found!"); ++ ++ return -1; ++ } ++ ++ ret = hinic3_set_port_conf_type(PORT_CONF_PCI); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_set_port_conf_type error"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_check_vf_args_valid(const struct rte_pci_addr *pci_addr, uint32_t max_queue_num) ++{ ++ int ret = 0; ++ struct hinic3_dp_extend_info *dp_info = hinic3_get_offload_extend_info(); ++ if ((dp_info == NULL) || (dp_info->hw_offload == NULL)) ++ return -1; ++ ++ if (hinic3_device_mode_get() == DPU_MODE && hinic3_get_port_list_init() == false) { ++ ret = hinic3_dpu_vf_flavor_add(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_dpu_vf_flavor_add err, ret is %d\n", ret); ++ return -1; ++ } ++ hinic3_set_port_list_init(true); ++ } ++ ++ struct hinic3_flow_agent_db *hw_offload = dp_info->hw_offload; ++ /* 检查该pci地址是否已被使用 */ ++ enum hinic3_bdf_status bdf_status = hinic3_vf_flavor_get_phy_dev_refcnt(pci_addr); ++ if (bdf_status == HINIC3_VF_BDF_USED) { ++ HINIC3_LOG(ERR, VPORT, "The BDF number is occupied"); ++ return -1; ++ } else if (bdf_status == HINIC3_VF_BDF_INVALID) { ++ HINIC3_LOG(ERR, VPORT, "The BDF number is invalid"); ++ return -1; ++ } else if (bdf_status == HINIC3_VF_BDF_LIST_NULL) { ++ HINIC3_LOG(ERR, VPORT, "The BDF number is not found"); ++ return -1; ++ } ++ ++ /* 判断将要分配的max_queue_num是否超过总容量,每个VF需要再占用一个控制队列 */ ++ if (hw_offload->queue_num.used_now + max_queue_num + 1 > hw_offload->queue_num.total_count) { ++ HINIC3_LOG(ERR, VPORT, "Queue resources are insufficient."); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_mbuf_set_common_port(uint16_t upcall_num, struct hinic3_standard_queue *rxq, struct rte_mbuf **rx_pkts) ++{ ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct rte_mbuf *mbuf = NULL; ++ int64_t upcall_byt = 0; ++ ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(rxq->dpdk_index_id); ++ if (vf_dev == NULL) { ++ hinic3_add_error_stats(HINIC3_VPORT_DEV_PRIVATE_DATA_NULL, 1); ++ return -1; ++ } ++ ++ rte_atomic64_add(&vf_dev->vf_upcall_pk_num, upcall_num); ++ rte_atomic64_add(&rxq->info.pkts, upcall_num); ++ for (uint16_t i = 0; i < upcall_num; i++) { ++ mbuf = rx_pkts[i]; ++ if (HINIC3_LIKELY(mbuf != NULL)) ++ rte_mbuf_set_port_id(mbuf, rxq->dpdk_index_id); ++ upcall_byt += rte_pktmbuf_pkt_len(mbuf); ++ } ++ rte_atomic64_add(&vf_dev->vf_upcall_pk_byt, upcall_byt); ++ ++ return 0; ++} ++ ++static uint16_t ++hinic3_vf_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) ++{ ++ struct hinic3_standard_queue *rxq = rx_queue; ++ uint16_t upcall_num; ++ ++ if (hinic3_standard_queue_valid(rxq) != 0) { ++ hinic3_add_error_stats(HINIC3_VPORT_RX_QUEUE_INVALID, 1); ++ return 0; ++ } ++ ++ upcall_num = hinic3_global_rte_eth_rx_burst(rxq->dpdk_port_id, rxq->upcall_queue_id, rx_pkts, nb_pkts); ++ if (upcall_num > 0) { ++ int ret = hinic3_mbuf_set_common_port(upcall_num, rxq, rx_pkts); ++ if (ret != 0) ++ return 0; ++ } ++ ++ return upcall_num; ++} ++ ++static int ++hinic3_mbuf_set_virtual_queue_port(uint16_t upcall_num, struct hinic3_queue *rxq, struct rte_mbuf **rx_pkts) ++{ ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct rte_mbuf *mbuf = NULL; ++ int64_t upcall_byt = 0; ++ ++ vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(rxq->dpdk_index_id); ++ if (vf_dev == NULL) { ++ hinic3_add_error_stats(HINIC3_VPORT_DEV_PRIVATE_DATA_NULL, 1); ++ return -1; ++ } ++ ++ rte_atomic64_add(&vf_dev->vf_upcall_pk_num, upcall_num); ++ rte_atomic64_add(&rxq->statistic.pkts, upcall_num); ++ for (uint16_t i = 0; i < upcall_num; i++) { ++ mbuf = rx_pkts[i]; ++ if (HINIC3_LIKELY(mbuf != NULL)) ++ rte_mbuf_set_port_id(mbuf, rxq->dpdk_index_id); ++ upcall_byt += rte_pktmbuf_pkt_len(mbuf); ++ } ++ rte_atomic64_add(&vf_dev->vf_upcall_pk_byt, upcall_byt); ++ ++ return 0; ++} ++ ++static uint16_t ++hinic3_virtual_queue_recv_pkts_distribute(struct hinic3_queue *rxq, ++ struct rte_mbuf **buffer, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint16_t upcall_num) ++{ ++ struct hinic3_queue *rxq_neighbor = NULL; ++ struct hinic3_virtual_queue *virtual_rxq = rxq->variant.virtual_queue; ++ struct hinic3_physical_queue *physical_rxq = virtual_rxq->physical_queue; ++ struct hinic3_pkt_user_data *hinic3_metadata = NULL; ++ uint8_t vgroup_num = hinic3_virtual_queue_multiplex_get(); ++ uint16_t pkt_vport_id = 0; ++ ++ for (uint16_t i = 0; i < nb_pkts; i++) { ++ hinic3_metadata = (struct hinic3_pkt_user_data *)rte_mbuf_get_udata64_ptr(buffer[i]); ++ pkt_vport_id = hinic3_metadata->vport_id; ++ ++ for (uint8_t vgroup_id = 0; vgroup_id < vgroup_num; ++vgroup_id) { ++ /* 未激活的队列不处理 */ ++ if (physical_rxq->is_virtual_queue_valids[vgroup_id] == false) ++ continue; ++ ++ /* 属于当前软件队列的包直接放入返回区 */ ++ if (pkt_vport_id == rxq->vport_id) { ++ rx_pkts[upcall_num] = buffer[i]; ++ ++upcall_num; ++ buffer[i] = NULL; ++ break; ++ } ++ /* 属于相邻软件队列的包放入对应的软件队列环中 */ ++ rxq_neighbor = physical_rxq->virtual_queues[vgroup_id]->queue_info; ++ if (pkt_vport_id == rxq_neighbor->vport_id) { ++ rte_ring_enqueue_burst(rxq_neighbor->variant.virtual_queue->ring, (void **)&buffer[i], 1, NULL); ++ buffer[i] = NULL; ++ break; ++ } ++ } ++ /* 未匹配到去向的包丢弃 */ ++ if (HINIC3_UNLIKELY(buffer[i] != NULL)) { ++ rte_pktmbuf_free(buffer[i]); ++ buffer[i] = NULL; ++ rte_atomic64_add(&rxq->statistic.pkts_drop, 1); ++ hinic3_add_error_stats(HINIC3_VPORT_VIRTUAL_QUEUE_RECV_PKTS_DISTRIBUTE_DROP, 1); ++ break; ++ } ++ } ++ ++ return upcall_num; ++} ++ ++static uint16_t ++hinic3_vf_recv_pkts_in_virtual_queue(void *virtual_rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) ++{ ++ struct hinic3_queue *rxq = (struct hinic3_queue *)virtual_rx_queue; ++ struct hinic3_virtual_queue *virtual_rxq = rxq->variant.virtual_queue; ++ struct hinic3_physical_queue *physical_rxq = virtual_rxq->physical_queue; ++ uint16_t upcall_num = 0; ++ uint16_t distribute_num = 0; ++ struct rte_mbuf *buffer[HINIC3_NETDEV_MAX_BURST] = {0}; ++ ++ if (nb_pkts > HINIC3_NETDEV_MAX_BURST) ++ nb_pkts = HINIC3_NETDEV_MAX_BURST; ++ ++ if (hinic3_queue_valid(rxq) != 0) { ++ hinic3_add_error_stats(HINIC3_VPORT_VIRTUAL_RX_QUEUE_INVALID, 1); ++ return 0; ++ } ++ ++ /* 先取软件队列中的包,缓存区不满则取硬件队列,并分发至对应的软件队列 */ ++ if (rte_ring_count(virtual_rxq->ring) != 0) ++ upcall_num = rte_ring_dequeue_burst(virtual_rxq->ring, (void **)rx_pkts, nb_pkts, NULL); ++ ++ /* 硬件队列读取分发过程加锁,防止线程竞争导致报文乱序 */ ++ if (upcall_num != nb_pkts) { ++ rte_spinlock_lock(&physical_rxq->physical_queue_lock); ++ distribute_num = hinic3_global_rte_eth_rx_burst( ++ rxq->dpdk_port_id, physical_rxq->hiovs_queue_id, buffer, nb_pkts - upcall_num); ++ upcall_num = hinic3_virtual_queue_recv_pkts_distribute(rxq, buffer, rx_pkts, distribute_num, upcall_num); ++ rte_spinlock_unlock(&physical_rxq->physical_queue_lock); ++ } ++ ++ if (upcall_num > 0) { ++ int ret = hinic3_mbuf_set_virtual_queue_port(upcall_num, rxq, rx_pkts); ++ if (ret != 0) ++ return 0; ++ } ++ ++ return upcall_num; ++} ++ ++static uint16_t ++hinic3_vf_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) ++{ ++ struct hinic3_standard_queue *txq = tx_queue; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ uint16_t reinject_num = 0; ++ int64_t reinject_byt = 0; ++ if (hinic3_standard_queue_valid(txq) != 0) { ++ hinic3_add_error_stats(HINIC3_VPORT_TX_QUEUE_INVALID, 1); ++ return 0; ++ } ++ hinic3_set_vport_id_into_userdata(txq->vport_id, tx_pkts, nb_pkts); ++ ++ reinject_num = hinic3_global_rte_eth_tx_burst(txq->dpdk_port_id, txq->queue_id, tx_pkts, nb_pkts); ++ if (reinject_num > 0) { ++ vf_dev = (struct hinic3_vf_dev*)hinic3_get_private_data(txq->dpdk_index_id); ++ if (HINIC3_UNLIKELY(vf_dev == NULL)) { ++ hinic3_add_error_stats(HINIC3_VPORT_DEV_PRIVATE_DATA_NULL, 1); ++ return 0; ++ } ++ rte_atomic64_add(&txq->info.pkts, reinject_num); ++ rte_atomic64_add(&vf_dev->vf_reinject_pk_num, reinject_num); ++ for (int i = 0; i < reinject_num; i++) ++ reinject_byt += rte_pktmbuf_pkt_len(tx_pkts[i]); ++ rte_atomic64_add(&vf_dev->vf_reinject_pk_byt, reinject_byt); ++ } ++ return reinject_num; ++} ++ ++static void ++hinic3_vf_dev_init(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) ++{ ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(eth_dev); ++ struct rte_eth_dev_data *data = eth_dev->data; ++ ++ data->mac_addrs = mac_addr; ++ data->dev_link = g_hinic3_vf_dev_link; ++ data->dev_flags |= HINIC3_ETH_DEV_FLOW_OPS_THREAD_SAFE; ++ data->dev_started = HINIC3_DEV_STATE_STOP; ++ data->nb_rx_queues = HINIC3_INVALID_QUEUE_NUM; ++ data->nb_tx_queues = HINIC3_INVALID_QUEUE_NUM; ++ ++ vf_dev->n_txq = data->nb_tx_queues; ++ vf_dev->n_upcall_queue = data->nb_rx_queues; ++ vf_dev->src_mac_num = HINIC3_VF_SECURITY_SMAC_INVALID; ++ vf_dev->eth_type_group_id = HINIC3_VF_SECURITY_ETH_GROUP_INVALID; ++ vf_dev->brd_rate_limit = HINIC3_VF_SECURITY_BRD_LIMIT_INVALID; ++ memset(vf_dev->src_mac_list, 0, sizeof(vf_dev->src_mac_list)); ++ vf_dev->vni = VNI_INVALID; ++ hinic3_list_init(&vf_dev->profiles); ++ for (uint8_t i = 0; i < HINIC3_MTR_NUM; i++) { ++ vf_dev->mtr[i].is_used = false; ++ vf_dev->mtr[i].mtr_id = INVALID_MTR_ID; ++ vf_dev->mtr[i].direction = INVALID_MTR_DIR; ++ } ++ for (int i = 0; i < HINIC3_VF_CONFIG_MAX; i++) ++ vf_dev->state[i] = HINIC3_VF_CONFIG_NONE; ++ ++ for (int i = 0; i < MAX_RX_QUEUE_PER_VPORT; i++) { ++ vf_dev->upcall_queue.upcall_queue_id[i] = INVALID_UPCALL_QUEUE_ID; ++ vf_dev->upcall_queue.is_queue_valid[i] = false; ++ } ++ rte_atomic64_init(&vf_dev->vf_upcall_pk_num); ++ rte_atomic64_init(&vf_dev->vf_upcall_pk_byt); ++ rte_atomic64_init(&vf_dev->vf_reinject_pk_num); ++ rte_atomic64_init(&vf_dev->vf_reinject_pk_byt); ++ if (hinic3_get_virtual_queue_mode_enabled() == true) ++ eth_dev->rx_pkt_burst = hinic3_vf_recv_pkts_in_virtual_queue; ++ else ++ eth_dev->rx_pkt_burst = hinic3_vf_recv_pkts; ++ ++ eth_dev->tx_pkt_burst = hinic3_vf_xmit_pkts; ++ /* bind ops to eth_dev */ ++ eth_dev->dev_ops = g_hinic3_vf_vdev_ops; ++ hinic3_smap_init(&vf_dev->qos_options); ++ rte_eth_dev_probing_finish(eth_dev); ++} ++ ++static int ++hinic3_vf_pci_by_function_id(int function_id, struct rte_pci_addr *pci_addr) ++{ ++ int ret = 0; ++ struct hovs_phy_dev_info dev = { 0 }; ++ struct hovs_pci_addr_info *info = NULL; ++ union bdf_info_u bdf_info; ++ ++ if (hinic3_query_bdf_type_get() == QUERY_BDF_TYPE_REAL) ++ bdf_info.bs.bdf_type = BDF_TYPE_REAL; ++ else ++ bdf_info.bs.bdf_type = BDF_TYPE_FAKE; ++ ++ bdf_info.bs.func_id_flag = 1; ++ ++ ret = hinic3_global_pcie_list_query(1, bdf_info.value, &dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 get global pcie list err"); ++ return -1; ++ } ++ ++ for (uint32_t i = 0; i < dev.phy_dev_num; i++) { ++ info = &dev.pci_info[i]; ++ if (function_id == info->glb_func_inx) { ++ memcpy(pci_addr, (struct rte_pci_addr *)&info->pci_addr, sizeof(struct rte_pci_addr)); ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++static int ++hinic3_vf_parse_representor_id(struct rte_kvargs *kvlist, struct rte_pci_addr *pci_addr, struct rte_eth_dev_data *data) ++{ ++ int function_id = 0; ++ int ret = 0; ++ ++ ret = hinic3_vf_parse_function_id(kvlist, &function_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_parse_function_id error"); ++ return -1; ++ } ++ ++ ret = hinic3_vf_pci_by_function_id(function_id, pci_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_pci_by_function_id error"); ++ return -1; ++ } ++ ++ ret = hinic3_set_port_conf_type(PORT_CONF_FUNC); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_set_port_conf_type error"); ++ return -1; ++ } ++ ++ data->representor_id = function_id; ++ data->dev_flags |= HINIC3_REPRESENTOR_FLAG; ++ data->backer_port_id = data->port_id; ++ ++ return 0; ++} ++ ++static int ++hinic3_port_parse_pci_addr(struct rte_kvargs *kvlist, struct rte_pci_addr *pci_addr, struct rte_eth_dev_data *data) ++{ ++ int pci_cnt = rte_kvargs_count(kvlist, HINIC3_PORT_PCI_ID); ++ int func_cnt = rte_kvargs_count(kvlist, HINIC3_REPRESENTOR_ID); ++ if ((func_cnt == 1) && (pci_cnt == 0)) ++ return hinic3_vf_parse_representor_id(kvlist, pci_addr, data); ++ else if ((func_cnt == 0) && (pci_cnt == 1)) ++ return hinic3_vf_parse_pci_addr(kvlist, pci_addr); ++ else { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_arg_parse bad pci or representor arg"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_vf_arg_parse(struct rte_kvargs *kvlist, struct hinic3_vf_dev *vf_dev, struct rte_eth_dev_data *data) ++{ ++ int ret = 0; ++ ++ ret = hinic3_vf_parse_max_queue(kvlist, &vf_dev->max_queue_num); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_parse_max_queue error"); ++ return -1; ++ } ++ ++ ret = hinic3_vf_parse_mac_addr(kvlist, &vf_dev->mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_parse_mac_addr error"); ++ return -1; ++ } ++ ++ ret = hinic3_port_parse_pci_addr(kvlist, &vf_dev->pci_addr, data); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_port_parse_pci_addr error"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++hinic3_vf_vdev_init(struct rte_eth_dev *eth_dev, struct rte_kvargs *kvlist) ++{ ++ int ret = 0; ++ struct rte_ether_addr *mac_addr = NULL; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(eth_dev); ++ struct rte_eth_dev_data *data = eth_dev->data; ++ ++ ret = hinic3_vf_arg_parse(kvlist, vf_dev, data); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf arg parse error!"); ++ return -EPERM; ++ } ++ ++ if ((hinic3_need_init_port() == true) && (vf_dev->max_queue_num != hinic3_get_max_queue_num())) { ++ vf_dev->max_queue_num = hinic3_get_max_queue_num(); ++ HINIC3_LOG(INFO, VPORT, "reset vf_dev max_queue_num is %u", vf_dev->max_queue_num); ++ } ++ ++ ret = hinic3_check_vf_args_valid(&vf_dev->pci_addr, vf_dev->max_queue_num); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_parse_vf_args error"); ++ return -EPERM; ++ } ++ ++ mac_addr = hinic3_rte_zmalloc(HINIC3_PORTS, HINIC3_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr), 0); ++ if (!mac_addr) { ++ HINIC3_LOG(ERR, VPORT, "Allocate ethernet addresses' memory failed."); ++ return -ENOMEM; ++ } ++ hinic3_vf_dev_init(eth_dev, mac_addr); ++ return ret; ++} ++ ++static inline int ++open_str(const char *key __rte_unused, const char *value, void *extra_args) ++{ ++ if (value == NULL || extra_args == NULL) ++ return -1; ++ ++ struct open_str_extra_args *op_args = (struct open_str_extra_args *)extra_args; ++ char *extra_args_str = op_args->extra_args_str; ++ size_t extra_args_str_len = op_args->extra_args_str_len; ++ size_t value_len = strlen(value); ++ ++ if (value_len + 1 > extra_args_str_len) { ++ HINIC3_LOG(ERR, BOND, "open str failed, extra args buffer overflow.\n"); ++ return -1; ++ } ++ ++ strcpy(extra_args_str, value); ++ if (extra_args_str[0] == '\0') { ++ HINIC3_LOG(ERR, BOND, "strcpy error"); ++ return -1; ++ } ++ return 0; ++} ++ ++static uint16_t ++hinic3_bond_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) ++{ ++ struct hinic3_standard_queue *rxq = rx_queue; ++ struct hinic3_bond_dev *bond_dev = NULL; ++ struct rte_mbuf *mbuf = NULL; ++ uint16_t upcall_num = 0; ++ int64_t upcall_byt = 0; ++ ++ if (hinic3_standard_queue_valid(rxq) != 0) { ++ hinic3_add_error_stats(HINIC3_VPORT_RX_QUEUE_INVALID, 1); ++ return 0; ++ } ++ ++ upcall_num = hinic3_global_rte_eth_rx_burst(rxq->dpdk_port_id, rxq->upcall_queue_id, rx_pkts, nb_pkts); ++ if (upcall_num > 0) { ++ bond_dev = (struct hinic3_bond_dev *)hinic3_get_private_data(rxq->dpdk_index_id); ++ if (bond_dev == NULL) { ++ hinic3_add_error_stats(HINIC3_VPORT_DEV_PRIVATE_DATA_NULL, 1); ++ return 0; ++ } ++ rte_atomic64_add(&rxq->info.pkts, upcall_num); ++ rte_atomic64_add(&bond_dev->pf_upcall_pk_num, upcall_num); ++ for (uint16_t i = 0; i < upcall_num; i++) { ++ mbuf = rx_pkts[i]; ++ if (mbuf != NULL) ++ rte_mbuf_set_port_id(mbuf, rxq->dpdk_index_id); ++ } ++ for (uint16_t i = 0; i < upcall_num; i++) ++ upcall_byt += rte_pktmbuf_pkt_len(rx_pkts[i]); ++ rte_atomic64_add(&bond_dev->pf_upcall_pk_byt, upcall_byt); ++ } ++ ++ return upcall_num; ++} ++ ++static uint16_t ++hinic3_bond_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) ++{ ++ struct hinic3_standard_queue *txq = tx_queue; ++ struct hinic3_bond_dev *bond_dev = NULL; ++ uint16_t reinject_num = 0; ++ int64_t reinject_bty = 0; ++ ++ if (hinic3_standard_queue_valid(txq) != 0) { ++ hinic3_add_error_stats(HINIC3_VPORT_TX_QUEUE_INVALID, 1); ++ return 0; ++ } ++ hinic3_set_vport_id_into_userdata(txq->vport_id, tx_pkts, nb_pkts); ++ ++ reinject_num = hinic3_global_rte_eth_tx_burst(txq->dpdk_port_id, txq->queue_id, tx_pkts, nb_pkts); ++ if (reinject_num > 0) { ++ bond_dev = (struct hinic3_bond_dev *)hinic3_get_private_data(txq->dpdk_index_id); ++ if (bond_dev == NULL) { ++ hinic3_add_error_stats(HINIC3_VPORT_DEV_PRIVATE_DATA_NULL, 1); ++ return 0; ++ } ++ rte_atomic64_add(&txq->info.pkts, reinject_num); ++ rte_atomic64_add(&bond_dev->pf_reinject_pk_num, reinject_num); ++ for (uint16_t i = 0; i < reinject_num; i++) ++ reinject_bty += rte_pktmbuf_pkt_len(tx_pkts[i]); ++ rte_atomic64_add(&bond_dev->pf_reinject_pk_byt, reinject_bty); ++ } ++ return reinject_num; ++} ++ ++static void ++hinic3_bond_dev_init(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr) ++{ ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(eth_dev); ++ struct rte_eth_dev_data *data = eth_dev->data; ++ ++ bond_dev->bond_id = HINIC3_PORT_ID_INVALID; ++ bond_dev->vport_id = HINIC3_PORT_ID_INVALID; ++ bond_dev->dpdk_port_id = INVALID_DPDK_PORT_ID; ++ memset(&bond_dev->uplink_pci_addr, 0, sizeof(struct rte_pci_addr)); ++ ++ data->mac_addrs = mac_addr; ++ ++ bond_dev->mtu = HINIC3_PF_DEFAULT_MTU; ++ data->mtu = HINIC3_PF_DEFAULT_MTU; ++ ++ data->dev_started = HINIC3_DEV_STATE_STOP; ++ data->dev_link = g_hinic3_pf_vdev_link; ++ data->dev_flags |= HINIC3_ETH_DEV_FLOW_OPS_THREAD_SAFE; ++ data->nb_rx_queues = HINIC3_INVALID_QUEUE_NUM; ++ data->nb_tx_queues = HINIC3_INVALID_QUEUE_NUM; ++ ++ bond_dev->n_txq = data->nb_tx_queues; ++ bond_dev->n_upcall_queue = data->nb_rx_queues; ++ /* set all upcall queue id invalid */ ++ for (int i = 0; i < MAX_RX_QUEUE_PER_VPORT; i++) { ++ bond_dev->upcall_queue.upcall_queue_id[i] = INVALID_UPCALL_QUEUE_ID; ++ bond_dev->upcall_queue.is_queue_valid[i] = false; ++ } ++ ++ rte_atomic64_init(&bond_dev->pf_upcall_pk_num); ++ rte_atomic64_init(&bond_dev->pf_upcall_pk_byt); ++ rte_atomic64_init(&bond_dev->pf_reinject_pk_num); ++ rte_atomic64_init(&bond_dev->pf_reinject_pk_byt); ++ /* bind rx/tx burst to eth_dev */ ++ eth_dev->rx_pkt_burst = hinic3_bond_recv_pkts; ++ eth_dev->tx_pkt_burst = hinic3_bond_xmit_pkts; ++ /* bind ops to eth_dev */ ++ eth_dev->dev_ops = g_hinic3_bond_vdev_ops; ++ rte_eth_dev_probing_finish(eth_dev); ++} ++ ++static int ++hinic3_bond_vdev_init(struct rte_eth_dev *eth_dev, struct rte_kvargs *kvlist) ++{ ++ int ret = 0; ++ char priority_upcall_str[PRIORITY_ENABLE_LEN] = {0}; ++ uint32_t mac_size = 0; ++ struct rte_ether_addr *mac_addr = NULL; ++ struct hinic3_bond_dev *bond_dev = hinic3_ethdev_get_bond_private(eth_dev); ++ ++ if (bond_dev == NULL) { ++ HINIC3_LOG(ERR, BOND, "Failed to get pf dev!"); ++ return -EPERM; ++ } ++ ++ struct open_str_extra_args bond_name = {0}; ++ bond_name.extra_args_str = bond_dev->bond_name; ++ bond_name.extra_args_str_len = MAX_NAME; ++ struct open_str_extra_args priority_upcall; ++ priority_upcall.extra_args_str = priority_upcall_str; ++ priority_upcall.extra_args_str_len = PRIORITY_ENABLE_LEN; ++ ++ ret = rte_kvargs_process(kvlist, HINIC3_BOND_NAME, &open_str, &bond_name); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "Failed to obtain the bond_name!"); ++ return -EPERM; ++ } ++ ++ ret = rte_kvargs_process(kvlist, HINIC3_PRIORITY_UPCALL, &open_str, &priority_upcall); ++ if (ret == 0 && strcmp(priority_upcall_str, "enable") == 0) ++ bond_dev->priority_upcall = true; ++ ++ /* bond_name is 0 or more than max_name */ ++ if ((strnlen(bond_dev->bond_name, MAX_NAME) == 0) || (strnlen(bond_dev->bond_name, MAX_NAME) >= MAX_NAME)) { ++ HINIC3_LOG(ERR, BOND, "bond name invalid length!"); ++ return -EPERM; ++ } ++ ++ mac_size = HINIC3_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr); ++ mac_addr = hinic3_rte_zmalloc(HINIC3_PORTS, mac_size, 0); ++ if (!mac_addr) { ++ HINIC3_LOG(ERR, BOND, "Allocate ethernet addresses' memory failed."); ++ return -ENOMEM; ++ } ++ ++ hinic3_bond_dev_init(eth_dev, mac_addr); ++ return ret; ++} ++ ++static int ++hinic3_vdev_probe(struct rte_vdev_device *vdev_dev) ++{ ++ int ret = 0; ++ struct rte_eth_dev *eth_dev = NULL; ++ struct rte_kvargs *kvlist = NULL; ++ if (vdev_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "vdev_dev is null!"); ++ return -EINVAL; ++ } ++ ++ struct rte_device *device = rte_vdev_device_get_device_ptr(vdev_dev); ++ struct rte_devargs *devargs = device->devargs; ++ kvlist = rte_kvargs_parse(devargs->args, hinic3_vdev_valid_arguments); ++ if (kvlist == NULL) { ++ HINIC3_LOG(ERR, VPORT, "kvargs parse failed!"); ++ return -EPERM; ++ } ++ ++ if (rte_kvargs_count(kvlist, HINIC3_BOND_NAME) != 0) { ++ eth_dev = rte_eth_vdev_allocate(vdev_dev, sizeof(struct hinic3_bond_dev)); ++ if (eth_dev == NULL) { ++ HINIC3_LOG(ERR, BOND, "Failed to allocate the new eth dev for bond"); ++ ret = -ENOMEM; ++ goto free; ++ } ++ ret = hinic3_bond_vdev_init(eth_dev, kvlist); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, BOND, "pf_vdev_init ERROR"); ++ rte_eth_dev_release_port(eth_dev); ++ goto free; ++ } ++ } else { ++ eth_dev = rte_eth_vdev_allocate(vdev_dev, sizeof(struct hinic3_vf_dev)); ++ if (eth_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Failed to allocate the new eth dev for vf"); ++ ret = -ENOMEM; ++ goto free; ++ } ++ ret = hinic3_vf_vdev_init(eth_dev, kvlist); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "vf_vdev_init ERROR"); ++ rte_eth_dev_release_port(eth_dev); ++ goto free; ++ } ++ } ++ ++free: ++ rte_kvargs_free(kvlist); ++ return ret; ++} ++ ++static void ++hinic3_bond_vdev_uninit(struct rte_eth_dev *dev) ++{ ++ hinic3_bond_dev_close(dev); ++ ++ dev->dev_ops = NULL; ++ dev->rx_pkt_burst = NULL; ++ dev->tx_pkt_burst = NULL; ++} ++ ++static void ++hinic3_vf_vdev_uninit(struct rte_eth_dev *dev) ++{ ++ struct rte_eth_dev_data *data = dev->data; ++ ++ dev->rx_pkt_burst = NULL; ++ dev->tx_pkt_burst = NULL; ++ dev->dev_ops = NULL; ++ ++ data->dev_started = HINIC3_DEV_STATE_STOP; ++ ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ hinic3_smap_destroy(&vf_dev->qos_options); ++ ++ if (data->mac_addrs != NULL) { ++ hinic3_rte_free(data->mac_addrs); ++ data->mac_addrs = NULL; ++ } ++} ++ ++static int ++hinic3_vdev_remove(struct rte_vdev_device *vdev_dev) ++{ ++ struct rte_eth_dev *eth_dev = NULL; ++ struct rte_kvargs *kvlist = NULL; ++ struct rte_device *device = rte_vdev_device_get_device_ptr(vdev_dev); ++ struct rte_devargs *devargs = device->devargs; ++ ++ eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev_dev)); ++ if (eth_dev == NULL) ++ return 0; ++ ++ kvlist = rte_kvargs_parse(devargs->args, hinic3_vdev_valid_arguments); ++ if (kvlist == NULL) { ++ rte_eth_dev_release_port(eth_dev); ++ HINIC3_LOG(ERR, BOND, "kvargs parse failed!"); ++ return -EPERM; ++ } ++ ++ bool is_bond_dev = (rte_kvargs_count(kvlist, HINIC3_BOND_NAME) == 0) ? false : true; ++ rte_kvargs_free(kvlist); ++ ++ if (is_bond_dev) ++ hinic3_bond_vdev_uninit(eth_dev); ++ else ++ hinic3_vf_vdev_uninit(eth_dev); ++ ++ rte_eth_dev_release_port(eth_dev); ++ return 0; ++} ++ ++static struct rte_vdev_driver *g_vdev_driver = NULL; ++ ++static void ++hinic3_vdev_driver_construct(void) ++{ ++ struct rte_vdev_driver *driver = NULL; ++ ++ driver = rte_vdev_driver_allocate(); ++ if (driver == NULL) ++ return; ++ ++ rte_vdev_driver_set_probe(driver, hinic3_vdev_probe); ++ rte_vdev_driver_set_remove(driver, hinic3_vdev_remove); ++ ++ g_vdev_driver = driver; ++} ++ ++static void ++hinic3_vdev_driver_destroy(void) ++{ ++ if (g_vdev_driver == NULL) ++ return; ++ ++ rte_vdev_driver_free(g_vdev_driver); ++ ++ g_vdev_driver = NULL; ++} ++ ++static const char *vdrvinit_net_vdev_alias; ++ ++static void ++hinic3_rte_register_vdev(void) ++{ ++ rte_vdev_driver_set_name(g_vdev_driver, RTE_STR(net_hwsp)); ++ rte_vdev_driver_set_alias(g_vdev_driver, vdrvinit_net_vdev_alias); ++ if (hinic3_get_agent_construct_init() == false) ++ rte_vdev_unregister(g_vdev_driver); ++ else ++ rte_vdev_register(g_vdev_driver); ++} ++ ++void ++hinic3_vdev_port_module_init(void) ++{ ++ hinic3_bond_flow_ops_construct(); ++ hinic3_vf_flow_ops_construct(); ++ hinic3_bond_dev_ops_construct(); ++ hinic3_vf_dev_ops_construct(); ++ hinic3_vdev_driver_construct(); ++ ++ hinic3_rte_register_vdev(); ++} ++ ++void ++hinic3_vdev_port_module_uninit(void) ++{ ++ hinic3_bond_flow_ops_destroy(); ++ hinic3_bond_dev_ops_destroy(); ++ hinic3_vf_flow_ops_destroy(); ++ hinic3_vf_dev_ops_destroy(); ++ hinic3_vdev_driver_destroy(); ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.h +new file mode 100644 +index 0000000..5fb1170 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VDEV_H ++#define HINIC3_VDEV_H ++ ++/* 端口模块初始化 */ ++void hinic3_vdev_port_module_init(void); ++/* 端口模块逆初始化 */ ++void hinic3_vdev_port_module_uninit(void); ++ ++#endif /* HINIC3_VDEV_H */ +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.c +new file mode 100644 +index 0000000..65dd980 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.c +@@ -0,0 +1,174 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_mtr.h" ++#include "hinic3_bond_controller.h" ++#include "hinic3_iface_flow_api_record.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_offload_flow.h" ++ ++int hinic3_eth_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, ++ const struct rte_flow_item *pattern, const struct rte_flow_action *actions, struct rte_flow_error *error) ++{ ++ (void)dev; ++ (void)attr; ++ (void)pattern; ++ (void)actions; ++ (void)error; ++ ++ return 0; ++} ++ ++static int hinic3_eth_flow_query_ecology(struct rte_eth_dev *dev, struct rte_flow *flow, ++ const struct rte_flow_action *actions, void *data, struct rte_flow_error *error) ++{ ++ if (flow->flags.is_dumb == 1) { ++ HINIC3_LOG(WARNING, FLOW, "classify flow query not support."); ++ return 0; ++ } ++ ++ return hinic3_flow_query_emc(dev, flow, actions, data, error); ++} ++ ++int hinic3_eth_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error) ++{ ++ if (dev == NULL) { ++ HINIC3_LOG(ERR, FLOW, "Invalid parameter, dev is NULL.\n"); ++ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Invalid parameter, dev is NULL."); ++ return -EINVAL; ++ } ++ ++ int ret; ++ uint16_t port_id; ++ ++ ret = hinic3_get_id_from_dev(dev, &port_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "rte flow flush: Get port id failed."); ++ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Get port id failed."); ++ return -EINVAL; ++ } ++ ++ ret = hinic3_del_flow_in_hmap_by_port(port_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "flush flow by port error\n"); ++ rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "flush flow by port error."); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_eth_flow_destroy_ecology(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error) ++{ ++ int ret; ++ if (flow->flags.is_dumb == 1) { ++ hinic3_rte_flow_dealloc(flow); ++ return 0; ++ } else if (flow->flags.is_qos == 1) { ++ ret = hinic3_qos_flow_delete(dev, flow, error); ++ if (ret != 0) { ++ return rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "del multi qos error."); ++ } ++ return 0; ++ } ++ ++ return hinic3_flow_emc_destroy(dev, flow, error); ++} ++ ++int hinic3_eth_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error) ++{ ++ int ret = 0; ++ if (dev == NULL || flow == NULL || error == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FLOW_DEL_INPUT_NULL, 1); ++ return -EINVAL; ++ } ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_RTE_FLOW_DELETE, ++ hinic3_eth_flow_destroy_ecology(dev, flow, error)); ++ return ret; ++} ++ ++static bool hinic3_check_offload_disable(const struct hinic3_flow_agent_db *hinic3_db) ++{ ++ if (hinic3_db->operate_disable == 1) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_OFFLOAD_DISABLE, 1); ++ return true; ++ } ++ return false; ++} ++ ++static struct rte_flow *hinic3_eth_flow_create_ecology(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, ++ const struct rte_flow_item *pattern, const struct rte_flow_action *actions, struct rte_flow_error *error) ++{ ++ uint16_t port_id; ++ struct rte_flow *flow = NULL; ++ if (attr->ingress == 1) { ++ flow = hinic3_rte_flow_alloc(); ++ if (flow == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_EMC_FLOW_ALLOC, 1); ++ return NULL; ++ } ++ flow->flags.is_dumb = 1; ++ return flow; ++ } else if (actions->type == RTE_FLOW_ACTION_TYPE_METER) { ++ flow = hinic3_set_multi_qos(pattern, actions); ++ if (flow == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SET_MULTI_QOS, 1); ++ rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "set multi qos error."); ++ } ++ return flow; ++ } ++ ++ if (hinic3_get_id_from_dev(dev, &port_id) != 0) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FLOW_GET_PORT_ID, 1); ++ rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "get port id by dev error."); ++ return NULL; ++ } ++ ++ struct hinic3_dp_extend_info *offload_extend_info = hinic3_get_offload_extend_info(); ++ if (HINIC3_UNLIKELY(offload_extend_info == NULL || offload_extend_info->hw_offload == NULL)) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_NO_INIT, 1); ++ rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "get emc db info failed"); ++ return NULL; ++ } ++ ++ if (hinic3_check_offload_disable(offload_extend_info->hw_offload) == true) { ++ rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "flow offload disable"); ++ return NULL; ++ } ++ flow = hinic3_offload_flow(pattern, actions, offload_extend_info->hw_offload, error); ++ if (flow != NULL) { ++ flow->port_id = port_id; ++ } ++ return flow; ++} ++ ++struct rte_flow *hinic3_eth_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, ++ const struct rte_flow_item *pattern, const struct rte_flow_action *actions, struct rte_flow_error *error) ++{ ++ struct rte_flow *flow = NULL; ++ if (dev == NULL || pattern == NULL || actions == NULL || error == NULL || attr == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FLOW_CREATE_INPUT_NULL, 1); ++ return NULL; ++ } ++ ++ HINIC3_LOG_HINIC_FLOW_ISNULL_API_LOG_NO_LOG(flow, HINIC3_RTE_FLOW_CREATE, ++ hinic3_eth_flow_create_ecology(dev, attr, pattern, actions, error)); ++ return flow; ++} ++ ++int hinic3_eth_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow, const struct rte_flow_action *actions, ++ void *data, struct rte_flow_error *error) ++{ ++ int ret = 0; ++ if (dev == NULL || flow == NULL || data == NULL || actions == NULL || error == NULL) { ++ hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_FLOW_QUERY_INPUT_NULL, 1); ++ return -EINVAL; ++ } ++ ++ HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_RTE_FLOW_QUERY, ++ hinic3_eth_flow_query_ecology(dev, flow, actions, data, error)); ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.h +new file mode 100644 +index 0000000..5dd897e +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_eth_util.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_ETH_UTIL_H ++#define HINIC3_ETH_UTIL_H ++ ++#include "hinic3_iface_global.h" ++#include "hinic3_query_flow.h" ++#include "hinic3_age_delete_flow.h" ++#include "hinic3_dump_flow.h" ++#include "hinic3_parse_agent_config.h" ++ ++int hinic3_eth_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, ++ const struct rte_flow_item *pattern, const struct rte_flow_action *actions, struct rte_flow_error *error); ++ ++struct rte_flow *hinic3_eth_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, ++ const struct rte_flow_item *pattern, const struct rte_flow_action *actions, struct rte_flow_error *error); ++ ++int hinic3_eth_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error); ++ ++int hinic3_eth_flow_flush(struct rte_eth_dev *dev, __rte_unused struct rte_flow_error *error); ++ ++int hinic3_eth_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow, const struct rte_flow_action *actions, ++ void *data, struct rte_flow_error *error); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c +new file mode 100644 +index 0000000..7e3d7aa +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c +@@ -0,0 +1,144 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "rte_dev.h" ++#include "rte_devargs.h" ++#include ++#include "hinic3_tlv_key.h" ++#include "hinic3_bond_controller.h" ++#include "hinic3_util.h" ++#include "hinic3_capture_main.h" ++#include "hinic3_agent.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_qos.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_vxlan.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_offload_flow_port.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++int hinic3_vf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) ++{ ++ if (dev == NULL || stats == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ int ret; ++ hinic3_port_stats hinic3_stats = { 0 }; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The current device private_data is NULL."); ++ return -EINVAL; ++ } ++ ++ ret = hinic3_port_statistics_get(vf_dev->vport_id, &hinic3_stats); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ // 端口报文统计信息,只统计慢路径的数据 ++ stats->ipackets = rte_atomic64_read(&vf_dev->vf_upcall_pk_num); ++ stats->opackets = rte_atomic64_read(&vf_dev->vf_reinject_pk_num); ++ stats->ibytes = rte_atomic64_read(&vf_dev->vf_upcall_pk_byt); ++ stats->obytes = rte_atomic64_read(&vf_dev->vf_reinject_pk_byt); ++ stats->imissed = hinic3_stats.rx_wqe_fail_dropped + hinic3_stats.ovs_port_stats.tx_dropped; ++ stats->ierrors = hinic3_stats.ovs_port_stats.tx_errors; ++ stats->oerrors = hinic3_stats.ovs_port_stats.rx_errors + hinic3_stats.ovs_port_stats.rx_dropped; ++ stats->rx_nombuf = hinic3_stats.rx_wqe_fail_dropped; ++ return 0; ++} ++ ++int hinic3_vf_dev_stats_reset(struct rte_eth_dev *dev) ++{ ++ if (dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The eth_dev is NULL"); ++ return -EINVAL; ++ } ++ ++ int ret; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The private data is NULL"); ++ return -EPERM; ++ } ++ ++ ret = hinic3_port_statistics_flush(vf_dev->vport_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf stats reset failed, vport:%hu!", vf_dev->vport_id); ++ return ret; ++ } ++ return 0; ++} ++ ++int hinic3_vf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned int n) ++{ ++ if (dev == NULL || xstats == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The parameter is NULL"); ++ return -EINVAL; ++ } ++ ++ int ret = 0; ++ hinic3_port_stats port_xstats = { 0 }; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The private data is NULL"); ++ return -EINVAL; ++ } ++ ++ if (n < HW_NB_XSTATS) { ++ HINIC3_LOG(ERR, VPORT, "The maximum number is less than the expected number"); ++ return -ERANGE; ++ } ++ ++ ret = hinic3_port_statistics_get(vf_dev->vport_id, &port_xstats); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "Failed to obtain port information from the hovs"); ++ return ret; ++ } ++ ++ for (int i = 0; i < HW_NB_XSTATS; i++) { ++ xstats[i].id = i; ++ } ++ xstats[XSTATS_UPCALL_PKT_INDEX].value = rte_atomic64_read(&vf_dev->vf_upcall_pk_num); ++ xstats[XSTATS_REINJECT_PKT_INDEX].value = rte_atomic64_read(&vf_dev->vf_reinject_pk_num); ++ xstats[XSTATS_UPCALL_DROP_INDEX].value = port_xstats.upcall_wqe_fail_dropped; ++ return HW_NB_XSTATS; ++} ++ ++int hinic3_vf_dev_xstats_reset(struct rte_eth_dev *dev) ++{ ++ if (dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The eth_dev is NULL"); ++ return -1; ++ } ++ int ret; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The private data is NULL"); ++ return -1; ++ } ++ ++ ret = hinic3_port_statistics_flush(vf_dev->vport_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf stats reset failed, vport:%hu!", vf_dev->vport_id); ++ return -1; ++ } ++ ++ rte_atomic64_set(&vf_dev->vf_upcall_pk_num, 0); ++ rte_atomic64_set(&vf_dev->vf_reinject_pk_num, 0); ++ return 0; ++} ++ ++int hinic3_vf_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, ++ unsigned int limit) ++{ ++ return hinic3_port_xstats_get_names(dev, xstats_names, limit); ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.h +new file mode 100644 +index 0000000..345d924 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.h +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_FUNCTION_STATISTICS_H ++#define HINIC3_FUNCTION_STATISTICS_H ++ ++/* 网卡收发包简要信息统计 */ ++int hinic3_vf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); ++/* 网卡收发包简要统计清空 */ ++int hinic3_vf_dev_stats_reset(struct rte_eth_dev *dev); ++/* 网卡收发包详细信息统计 */ ++int hinic3_vf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned int n); ++/* 网卡收发包详细统计清空 */ ++int hinic3_vf_dev_xstats_reset(struct rte_eth_dev *dev); ++/* 网卡收发包详细统计条目名称 */ ++int hinic3_vf_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, ++ unsigned int limit); ++ ++#endif // HINIC3_FUNCTION_STATISTICS_H +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c +new file mode 100644 +index 0000000..fc182de +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c +@@ -0,0 +1,1325 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "rte_dev.h" ++#include "rte_devargs.h" ++#include ++#include "hinic3_tlv_key.h" ++#include "hinic3_bond_controller.h" ++#include "hinic3_util.h" ++#include "hinic3_capture_main.h" ++#include "hinic3_agent.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_qos.h" ++#include "hinic3_mtr.h" ++#include "hinic3_smap.h" ++#include "hinic3_vxlan.h" ++#include "hinic3_flow_dump.h" ++#include "hinic3_offload_flow_port.h" ++#include "hinic3_dpdk_adapter.h" ++#include "hinic3_vf_controller.h" ++ ++#define BITMAP_NUM 64 ++#define HINIC3_VF_CONFIG_VNI_STR "vni" ++#define HINIC3_VF_CONFIG_BUCKET_ID_STR "bucket_id" ++#define HINIC3_USED_DRIVER_NAME "vfio-pci" ++#define HINIC3_DRIVER_STR "driver" ++#define DEFAULT_MAX_QUEUE_NUM 4 ++#define DEFAULT_UPCALL_QUEUE_NUM 4 ++#define PORT_SECTION "hwoff_port" ++ ++typedef int (*hinic3_vf_extra_config_cb)(struct hinic3_vf_dev *vf_dev, const char* conf); ++ ++static int hinic3_vf_config_set_vni(struct hinic3_vf_dev *vf_dev, const char* conf); ++ ++uint8_t g_n_upcall_queue = 0; ++uint32_t g_max_queue_num = 0; ++ ++struct hinic3_vf_extra_config_info { ++ const char *args; ++ hinic3_vf_extra_config_cb func; ++}; ++ ++static struct hinic3_vf_extra_config_info g_vf_extra_config_info[] = { ++ {HINIC3_VF_CONFIG_VNI_STR, hinic3_vf_config_set_vni}, ++}; ++ ++struct rte_flow_ops *g_hinic3_vf_flow_ops = NULL; ++ ++void hinic3_vf_flow_ops_construct(void) ++{ ++ struct rte_flow_ops *flow_ops = hinic3_calloc(1, sizeof(struct rte_flow_ops), HINIC3_PORTS); ++ if (flow_ops == NULL) ++ return; ++ ++ rte_flow_ops_set_validate(flow_ops, hinic3_eth_flow_validate); ++ rte_flow_ops_set_create(flow_ops, hinic3_eth_flow_create); ++ rte_flow_ops_set_destroy(flow_ops, hinic3_eth_flow_destroy); ++ rte_flow_ops_set_flush(flow_ops, hinic3_eth_flow_flush); ++ rte_flow_ops_set_query(flow_ops, hinic3_eth_flow_query); ++ rte_flow_ops_set_dev_dump(flow_ops, hinic3_eth_flow_dev_dump); ++ rte_flow_ops_tunnel_decap_set(flow_ops, hinic3_flow_tunnel_decap_set); ++ rte_flow_ops_flow_dump_start(flow_ops, hinic3_eth_flow_dump_start); ++ rte_flow_ops_flow_dump_next(flow_ops, hinic3_eth_flow_dump_next); ++ rte_flow_ops_flow_dump_done(flow_ops, hinic3_eth_flow_dump_done); ++ g_hinic3_vf_flow_ops = flow_ops; ++} ++ ++void hinic3_vf_flow_ops_destroy(void) ++{ ++ if (g_hinic3_vf_flow_ops == NULL) { ++ return; ++ } ++ ++ hinic3_free(g_hinic3_vf_flow_ops); ++ ++ g_hinic3_vf_flow_ops = NULL; ++} ++ ++static void hinic3_vf_release_upcall_queue(struct hinic3_vf_dev *vf_dev, uint16_t queue_id) ++{ ++ int ret; ++ if (vf_dev->upcall_queue.is_queue_valid[queue_id] == true) { ++ ret = hinic3_port_mgmt_release_upcall_queue(vf_dev->vport_id, queue_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "bond port release upcall queue error"); ++ } ++ vf_dev->upcall_queue.is_queue_valid[queue_id] = false; ++ } ++} ++ ++static void hinic3_vf_release_reinject_queue(struct hinic3_vf_dev *vf_dev, uint16_t queue_id) ++{ ++ if (vf_dev->reinject_queue.is_queue_valid[queue_id] == true) { ++ vf_dev->reinject_queue.is_queue_valid[queue_id] = false; ++ } ++} ++ ++static int hinic3_vf_get_used_status(const struct hinic3_vf_dev *vf_dev, bool *is_used) ++{ ++ int err; ++ ssize_t len; ++ char *device_driver = NULL; ++ char filename[PATH_MAX] = {0}; ++ char link_buf[PATH_MAX] = {0}; ++ ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "device is NULL"); ++ return -1; ++ } ++ ++ err = snprintf(filename, sizeof(filename), "%s/%.4x:%.2x:%.2x.%x/%s", SYSFS_PCI_DEVICES, ++ vf_dev->pci_addr.domain, vf_dev->pci_addr.bus, vf_dev->pci_addr.devid, vf_dev->pci_addr.function, ++ HINIC3_DRIVER_STR); ++ if (err <= 0 || err >= PATH_MAX) { ++ HINIC3_LOG(ERR, VPORT, "Get device driver path err"); ++ return -1; ++ } ++ ++ HINIC3_LOG(DEBUG, VPORT, "Device dirver path: %s", filename); ++ len = readlink(filename, link_buf, PATH_MAX); ++ if (len < 0 || len >= PATH_MAX) { ++ HINIC3_LOG(INFO, VPORT, "Device driver soft link not exist"); ++ return 0; ++ } ++ link_buf[len] = '\0'; ++ HINIC3_LOG(DEBUG, VPORT, "Device driver soft link: %s", link_buf); ++ ++ device_driver = strrchr(link_buf, '/'); ++ if (device_driver == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Get device driver err"); ++ return -1; ++ } ++ ++ if (strcmp(device_driver + 1, HINIC3_USED_DRIVER_NAME) == 0) { ++ *is_used = true; ++ HINIC3_LOG(INFO, VPORT, " :The current device %.4x:%.2x:%.2x.%x is occupied by a virtual machine", ++ vf_dev->pci_addr.domain, vf_dev->pci_addr.bus, vf_dev->pci_addr.devid, vf_dev->pci_addr.function); ++ } ++ return 0; ++} ++ ++static int hinic3_vf_config_set_vni(struct hinic3_vf_dev *vf_dev, const char* conf) ++{ ++ int vni; ++ char *endp = NULL; ++ enum hinic3_vf_config_state old_state = vf_dev->state[HINIC3_VF_CONFIG_VNI]; ++ vf_dev->state[HINIC3_VF_CONFIG_VNI] = HINIC3_VF_CONFIG_NONE; ++ ++ vni = strtoul(conf, &endp, BASE_DECIMAL); ++ if (vf_dev->vni == vni) { ++ vf_dev->state[HINIC3_VF_CONFIG_VNI] = HINIC3_VF_CONFIG_STABLE; ++ return 1; ++ } ++ ++ if (vni >= VNI_INVALID || vni < 0 || *endp != '\0') { ++ HINIC3_LOG(ERR, VPORT, "invalid vxlan network identifier: %d!", vni); ++ vf_dev->state[HINIC3_VF_CONFIG_VNI] = old_state; ++ return -1; ++ } ++ vf_dev->vni = vni; ++ vf_dev->state[HINIC3_VF_CONFIG_VNI] = HINIC3_VF_CONFIG_ADD; ++ return 0; ++} ++ ++static int hinic3_vf_vni_update(struct hinic3_vf_dev *vf_dev) ++{ ++ int ret = 0; ++ struct smap smap_args, unset_args; ++ hinic3_smap_init(&smap_args); ++ hinic3_smap_init(&unset_args); ++ switch (vf_dev->state[HINIC3_VF_CONFIG_VNI]) { ++ case HINIC3_VF_CONFIG_ADD: ++ hinic3_smap_add_format(HINIC3_PORTS, &smap_args, HINIC3_VF_CONFIG_VNI_STR, "%u", vf_dev->vni); ++ ret = hinic3_port_mgmt_set(vf_dev->vport_id, &smap_args, &unset_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_port_mgmt_set VNI failed, port %u", vf_dev->vport_id); ++ vf_dev->vni = VNI_INVALID; ++ } ++ break; ++ case HINIC3_VF_CONFIG_DEL: ++ if (vf_dev->vni == VNI_INVALID) { ++ break; ++ } ++ hinic3_smap_add_format(HINIC3_PORTS, &smap_args, HINIC3_VF_CONFIG_VNI_STR, "%u", HINIC3_VF_VNI_DEFAULT); ++ ret = hinic3_port_mgmt_set(vf_dev->vport_id, &smap_args, &unset_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_port_mgmt_set VNI failed, port %u", vf_dev->vport_id); ++ } ++ vf_dev->vni = VNI_INVALID; ++ break; ++ case HINIC3_VF_CONFIG_STABLE: ++ break; ++ default: ++ break; ++ } ++ hinic3_smap_destroy(&smap_args); ++ hinic3_smap_destroy(&unset_args); ++ vf_dev->state[HINIC3_VF_CONFIG_VNI] = (vf_dev->vni == VNI_INVALID ? ++ HINIC3_VF_CONFIG_NONE : HINIC3_VF_CONFIG_DEL); ++ return ret; ++} ++ ++static int hinic3_vf_dynamic_port_add(struct hinic3_vf_dev *vf_dev) ++{ ++ int ret; ++ struct smap args; ++ uint16_t virtio_queue_depth; ++ bool is_virtio_queue_depth_set; ++ ++ if (vf_dev->vport_id != HINIC3_PORT_ID_INVALID) { ++ return 0; ++ } ++ ++ hinic3_smap_init(&args); ++ ++ virtio_queue_depth = hinic3_virtio_queue_depth(); ++ ++ is_virtio_queue_depth_set = hinic3_check_virtio_queue_depth_set(); ++ if (is_virtio_queue_depth_set) { ++ hinic3_smap_add_format(HINIC3_PORTS, &args, HINIC3_PORT_QUEUE_DEPTH, "%u", virtio_queue_depth); ++ } ++ ++ hinic3_smap_add_format(HINIC3_PORTS, &args, HINIC3_PORT_PCI_ADDR, "%" PRIuPTR, (uintptr_t)&vf_dev->pci_addr); ++ hinic3_smap_add_format(HINIC3_PORTS, &args, HINIC3_PORT_BLOCK_SIZE, "%u", vf_dev->max_queue_num); ++ hinic3_smap_add_format(HINIC3_PORTS, &args, HINIC3_PORT_UPCALL_QUEUE_NUM, "%u", vf_dev->n_upcall_queue); ++ ++ ret = hinic3_port_mgmt_add_dynamic(&vf_dev->vport_id, &args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to add dynamic port of the vf!"); ++ } ++ ++ hinic3_smap_destroy(&args); ++ ++ return ret; ++} ++ ++static int hinic3_vf_virtual_queue_port_add(struct hinic3_vf_dev *vf_dev) ++{ ++ int ret; ++ struct smap args; ++ ++ if (vf_dev->vport_id != HINIC3_PORT_ID_INVALID) { ++ return 0; ++ } ++ ++ ret = hinic3_alloc_queues_to_port(&vf_dev->upcall_queue, vf_dev->n_upcall_queue); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to alloc virtual queue to vf"); ++ return ret; ++ } ++ ++ hinic3_smap_init(&args); ++ hinic3_smap_add_format(HINIC3_PORTS, &args, HINIC3_PORT_PCI_ADDR, "%" PRIuPTR, (uintptr_t)&vf_dev->pci_addr); ++ hinic3_smap_add_format(HINIC3_PORTS, &args, HINIC3_PORT_BLOCK_SIZE, "%u", vf_dev->max_queue_num); ++ hinic3_smap_add_format(HINIC3_PORTS, &args, HINIC3_PORT_UPCALL_QUEUE_NUM, "%u", vf_dev->n_upcall_queue); ++ hinic3_smap_add_format( ++ HINIC3_PORTS, &args, HINIC3_PORT_UPCALL_QUEUE_MAP, "%" PRIuPTR, (uintptr_t)vf_dev->upcall_queue.upcall_queue_id); ++ ++ ret = hinic3_port_mgmt_add_dynamic(&vf_dev->vport_id, &args); ++ if (ret != 0) { ++ hinic3_free_queues_from_port(&vf_dev->upcall_queue, vf_dev->n_upcall_queue); ++ HINIC3_LOG(ERR, VPORT, "failed to add virtual queue port of the vf!\n"); ++ } ++ ++ hinic3_smap_destroy(&args); ++ ++ return ret; ++} ++ ++void hinic3_clear_vf_port_info(struct hinic3_vf_dev *vf_dev) ++{ ++ int ret = 0; ++ ++ ret = hinic3_mtu_set(vf_dev->vport_id, HINIC3_DEFAULT_MTU); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf set mtu failed, vport:%u!", vf_dev->vport_id); ++ } ++ ++ if (vf_dev->qos_type == VF_PORT_QOS_FLAG) { ++ hinic3_port_meter_clear(vf_dev, vf_dev->vport_id); ++ } ++ if (vf_dev->group_qos_id != 0) { ++ ret = hinic3_group_meter_remove(vf_dev->vport_id, vf_dev->group_qos_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf clear group meter failed, vport:%u!", vf_dev->vport_id); ++ } ++ } ++ ++ ret = hinic3_port_statistics_flush(vf_dev->vport_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf clear port statistics info failed, vport:%u!", vf_dev->vport_id); ++ } ++ rte_atomic64_set(&vf_dev->vf_upcall_pk_num, 0); ++ rte_atomic64_set(&vf_dev->vf_upcall_pk_byt, 0); ++ rte_atomic64_set(&vf_dev->vf_reinject_pk_num, 0); ++ rte_atomic64_set(&vf_dev->vf_reinject_pk_byt, 0); ++ ++ ret = hinic3_port_mgmt_set_usage_state(vf_dev->vport_id, HINIC3_SET_VF_STATE_DOWN); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "port mgmt set vf state down err, ret is %d", ret); ++ } ++ return; ++} ++ ++static void hinic3_vf_dev_del(struct rte_eth_dev *dev) ++{ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ uint16_t nb_tx_queues = data->nb_tx_queues; ++ uint16_t nb_rx_queues = data->nb_rx_queues; ++ ++ for (uint16_t index = 0; index < nb_tx_queues; index++) { ++ hinic3_vf_tx_queue_release(dev, index); ++ } ++ ++ for (uint16_t index = 0; index < nb_rx_queues; index++) { ++ if (hinic3_get_virtual_queue_mode_enabled() == true) { ++ hinic3_vf_virtual_rx_queue_release(dev, index); ++ } else { ++ hinic3_vf_rx_queue_release(dev, index); ++ } ++ } ++ hinic3_free_queues_from_port(&vf_dev->upcall_queue, vf_dev->n_upcall_queue); ++ ++ if (vf_dev->vport_id != HINIC3_PORT_ID_INVALID) { ++ /* 端口删除前,清理端口信息 */ ++ hinic3_clear_vf_port_info(vf_dev); ++ /* 端口删除前,清理抓包信息 */ ++ pcap_task_stop_as_eth_port_del(vf_dev->vport_id); ++ if (hinic3_need_init_port() == false) { ++ hinic3_port_mgmt_del(vf_dev->vport_id); ++ } ++ mgmt_vf_virtio_queue(vf_dev->max_queue_num, true); ++ hinic3_ifindex_port_remove(vf_dev->vport_id); ++ vf_dev->vport_id = HINIC3_PORT_ID_INVALID; ++ ++ int ret = ++ hinic3_hwpt_flavor_set_phy_dev_refcnt(&vf_dev->pci_addr, HWPT_FLAVOR_REFCNT_UNUSED); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to reset flavor of the vport"); ++ } ++ ++ vf_dev->dpdk_port_id = INVALID_DPDK_PORT_ID; ++ } ++} ++ ++static int hinic3_set_mac_to_vf(struct hinic3_vf_dev *vf_dev) ++{ ++ int ret = 0; ++ ++ if (!eth_addr_is_zero(vf_dev->mac_addr)) { ++ ret = hinic3_etheraddr_set(vf_dev->vport_id, vf_dev->mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to set mac for vf!"); ++ } ++ } else { ++ ret = hinic3_etheraddr_get(vf_dev->vport_id, (struct eth_address*)&vf_dev->mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to get vf's default mac!"); ++ } ++ /* vf热插拔场景中,端口管理不设置mac的情况下需要调用hovs_etheraddr_set接口以触发热插拔功能 */ ++ if (hinic3_support_port_hot_plug()) { ++ ret = hinic3_etheraddr_set(vf_dev->vport_id, vf_dev->mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "port hot plug failed to set mac for vf!\n"); ++ } ++ } ++ } ++ return ret; ++} ++ ++static int hinic3_vf_dev_update(struct hinic3_vf_dev *vf_dev, struct rte_eth_dev_data *data) ++{ ++ int ret; ++ struct rte_ether_addr* mac_addrs = NULL; ++ ++ mgmt_vf_virtio_queue(vf_dev->max_queue_num, false); ++ /* set mac to vf */ ++ ret = hinic3_set_mac_to_vf(vf_dev); ++ if (ret != 0) { ++ return ret; ++ } ++ mac_addrs = data->mac_addrs; ++ if (mac_addrs == NULL) { ++ return -1; ++ } ++ rte_ether_addr_copy((struct rte_ether_addr *)&vf_dev->mac_addr.ea, mac_addrs); ++ ++ ret = hinic3_eth_get_dpdk_port_id(vf_dev->vport_id, &vf_dev->dpdk_port_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to get dpdk port id of vport:%u", vf_dev->vport_id); ++ return ret; ++ } ++ ++ ret = hinic3_hwpt_flavor_set_phy_dev_refcnt(&vf_dev->pci_addr, HWPT_FLAVOR_REFCNT_USED); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to set flavor of the vport:%u", vf_dev->vport_id); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_vf_dev_add(struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ bool is_used = false; ++ enum hinic3_work_mode work_mode = hinic3_device_mode_get(); ++ struct rte_eth_dev_data *data = dev->data; ++ ++ if (work_mode == SMART_NIC_MODE) { ++ (void)hinic3_vf_get_used_status((const struct hinic3_vf_dev*)vf_dev, &is_used); ++ } ++ ++ if (hinic3_get_virtual_queue_mode_enabled() == true) { ++ ret = hinic3_vf_virtual_queue_port_add(vf_dev); ++ } else { ++ ret = hinic3_vf_dynamic_port_add(vf_dev); ++ } ++ if (ret != 0) { ++ if ((ret == ENOMEM) && is_used) { ++ HINIC3_LOG(ERR, VPORT, ++ "The port is occupied by a virtual machine, please shut down the virtual machine and re-add the port"); ++ } ++ goto end; ++ } ++ ++ ret = hinic3_vf_dev_update(vf_dev, data); ++ if (ret != 0) { ++ goto clean; ++ } ++ ++ HINIC3_LOG(INFO, VPORT, "hinic3 vf port add success,port_id: %u, upcall_queue: %u\n", ++ vf_dev->vport_id, vf_dev->n_upcall_queue); ++ return 0; ++ ++clean: ++ hinic3_vf_dev_del(dev); ++end: ++ return ret; ++} ++ ++int hinic3_vf_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ if (info == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The dev info is NULL."); ++ return -EINVAL; ++ } ++ ++ int ret; ++ uint16_t max_rx_tx_queue = 0; ++ struct hinic3_port_capability cap = {0}; ++ ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ struct rte_device *device = dev->device; ++ const struct rte_driver *driver = device->driver; ++ ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The current device private_data or info is NULL."); ++ return -EINVAL; ++ } ++ ++ info->driver_name = driver->name; ++ ret = hinic3_port_mgmt_get_capability(&cap); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ if (hinic3_need_init_port() == true) { ++ max_rx_tx_queue = hinic3_get_upcall_queue_num(); ++ info->max_rx_queues = max_rx_tx_queue; ++ info->max_tx_queues = max_rx_tx_queue; ++ } else { ++ if (cap.supported_upcall_qnum != MAX_RX_QUEUE_PER_VPORT) { ++ info->max_rx_queues = HINIC3_VF_DEFAULT_NB_QUEUES; ++ } else { ++ info->max_rx_queues = MAX_RX_QUEUE_PER_VPORT; ++ } ++ info->max_tx_queues = MAX_RX_QUEUE_PER_VPORT; ++ } ++ ++ info->max_rx_pktlen = HINIC3_VF_MTU_MAX + HINIC3_VF_SIZE_OFFSET; ++ info->min_mtu = HINIC3_VF_MTU_MIN; ++ info->max_mtu = HINIC3_VF_MTU_MAX; ++ info->if_index = vf_dev->vport_id; ++ info->max_mac_addrs = HINIC3_MAX_MAC_ADDRS; ++ info->max_hash_mac_addrs = HINIC3_MAX_HASH_MAC_ADDRS; ++ info->max_vfs = HINIC3_MAX_VFS; ++ info->max_vmdq_pools = HINIC3_MAX_VMDQ_POOLS; ++ info->rx_offload_capa = HINIC3_ETH_RX_OFFLOAD_SCATTER; ++ info->tx_offload_capa = HINIC3_ETH_TX_OFFLOAD_MULTI_SEGS; ++ info->flow_type_rss_offloads = HINIC3_ETH_SUPPORT_RSS; ++ ++ return 0; ++} ++ ++int hinic3_vf_set_link_up(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ dev_link->link_status = RTE_ETH_LINK_UP; ++ ++ return 0; ++} ++ ++int hinic3_vf_set_link_down(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ dev_link->link_status = RTE_ETH_LINK_DOWN; ++ ++ return 0; ++} ++ ++int hinic3_vf_dev_start(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "The current device private_data is NULL."); ++ return -1; ++ } ++ if (vf_dev->vport_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, VPORT, "can't start device: invalid vport id"); ++ return -1; ++ } ++ ++ dev_link->link_status = RTE_ETH_LINK_UP; ++ data->dev_started = HINIC3_DEV_STATE_START; ++ ++ return 0; ++} ++ ++int hinic3_vf_dev_stop(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct rte_eth_link *dev_link = &data->dev_link; ++ ++ dev_link->link_status = RTE_ETH_LINK_DOWN; ++ data->dev_started = HINIC3_DEV_STATE_STOP; ++ ++ return 0; ++} ++ ++int hinic3_vf_dev_close(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ ++ if (data->mac_addrs != NULL) { ++ hinic3_rte_free(data->mac_addrs); ++ data->mac_addrs = NULL; ++ } ++ ++ hinic3_vf_dev_del(dev); ++ return 0; ++} ++ ++void hinic3_vf_rx_queue_release_dpdk2011(void *rxq) ++{ ++ if (rxq != NULL) { ++ hinic3_rte_free(rxq); ++ } ++} ++ ++void hinic3_vf_tx_queue_release_dpdk2011(void *txq) ++{ ++ if (txq != NULL) { ++ hinic3_rte_free(txq); ++ } ++} ++ ++void hinic3_vf_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *rxq = NULL; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ ++ if (queue_id >= data->nb_rx_queues) { ++ HINIC3_LOG(ERR, VPORT, "queue index invalid, max queue is:%u", data->nb_rx_queues); ++ return; ++ } ++ rxq = data->rx_queues[queue_id]; ++ if (rxq != NULL) { ++ hinic3_vf_release_upcall_queue(vf_dev, queue_id); ++ hinic3_rte_free(rxq); ++ vf_dev->upcall_queue.rx_queue[queue_id] = NULL; ++ data->rx_queues[queue_id] = NULL; ++ } ++} ++ ++void hinic3_vf_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *txq; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ ++ if (queue_id >= data->nb_tx_queues) { ++ HINIC3_LOG(ERR, VPORT, "queue index invalid, max queue is:%u", data->nb_tx_queues); ++ return; ++ } ++ ++ txq = data->tx_queues[queue_id]; ++ if (txq != NULL) { ++ hinic3_vf_release_reinject_queue(vf_dev, queue_id); ++ hinic3_rte_free(txq); ++ vf_dev->reinject_queue.tx_queues[queue_id] = NULL; ++ data->tx_queues[queue_id] = NULL; ++ } ++} ++int hinic3_get_port_index_by_dev(struct rte_eth_dev *dev, uint16_t *port_index) ++{ ++ struct rte_device *device = dev->device; ++ const char *name = device->name; ++ int ret = rte_eth_dev_get_port_by_name(name, port_index); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "rte_eth_dev_get_port_by_name error"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_vf_rx_queue_setup_check(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, struct rte_mempool *mp) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ if (mp == NULL) { ++ HINIC3_LOG(ERR, VPORT, "mp is NULL"); ++ return -EINVAL; ++ } ++ ++ uint16_t vport_rx_depth = hinic3_vport_rx_depth(); ++ struct rte_eth_dev_data *data = dev->data; ++ bool is_open_ovs = hinic3_check_masked_to_exact_switch(); ++ if (vport_rx_depth != desc && !is_open_ovs) { ++ HINIC3_LOG(ERR, BOND, "vport_rx_depth differences. desc is %u, vport_rx_depth is %u", desc, vport_rx_depth); ++ return -EINVAL; ++ } ++ ++ if (idx >= data->nb_rx_queues) { ++ HINIC3_LOG(ERR, VPORT, "queue index invalid, max queue is:%u", data->nb_rx_queues); ++ return -EINVAL; ++ } ++ ++ if (idx >= MAX_RX_QUEUE_PER_VPORT) { ++ HINIC3_LOG(ERR, VPORT, "port upcall index greater than max"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int hinic3_vf_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc __rte_unused, unsigned int socket_id, ++ const struct rte_eth_rxconf *conf __rte_unused, struct rte_mempool *mp) ++{ ++ int ret = hinic3_vf_rx_queue_setup_check(dev, idx, desc, mp); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *rxq = NULL; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ uint16_t dpdk_index_id = 0; ++ ++ ret = hinic3_get_port_index_by_dev(dev, &dpdk_index_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_get_port_index_by_dev error"); ++ return -EPERM; ++ } ++ ++ ret = hinic3_port_mgmt_setup_upcall_queue(vf_dev->vport_id, idx, socket_id, mp); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "port setup upcall queue error"); ++ return -EPERM; ++ } ++ ++ rxq = hinic3_rte_zmalloc_socket(HINIC3_PORTS, sizeof(struct hinic3_standard_queue), RTE_CACHE_LINE_SIZE, socket_id); ++ if (rxq == NULL) { ++ return -ENOMEM; ++ } ++ ++ vf_dev->upcall_queue.rx_queue[idx] = rxq; ++ vf_dev->upcall_queue.is_queue_valid[idx] = true; ++ /* 获取upcall_queue信息 */ ++ rxq->mp = mp; ++ rxq->queue_id = idx; ++ rxq->info.type = HINIC3_RX_QUEUE; ++ rxq->vport_id = vf_dev->vport_id; ++ rxq->dpdk_port_id = vf_dev->dpdk_port_id; ++ rxq->upcall_queue_id = vf_dev->upcall_queue.upcall_queue_id[idx]; ++ rxq->dpdk_index_id = dpdk_index_id; ++ data->rx_queues[idx] = rxq; ++ ++ HINIC3_LOG(INFO, VPORT, ++ "rxq %u setup success, vport id: %u, upcall queue id: %u.", ++ rxq->queue_id, rxq->vport_id, rxq->upcall_queue_id); ++ return 0; ++} ++ ++int hinic3_vf_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, unsigned int socket_id, ++ const struct rte_eth_txconf *conf __rte_unused) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ int ret = 0; ++ uint16_t vport_tx_depth = hinic3_vport_tx_depth(); ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_standard_queue *txq; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ uint16_t dpdk_index_id = 0; ++ bool is_open_ovs = hinic3_check_masked_to_exact_switch(); ++ ++ if (vport_tx_depth != desc && !is_open_ovs) { ++ HINIC3_LOG(ERR, BOND, "vport_tx_depth differences. desc is %u, vport_tx_depth is %u", desc, vport_tx_depth); ++ return -EINVAL; ++ } ++ ++ if (idx >= data->nb_tx_queues) { ++ HINIC3_LOG(ERR, VPORT, "queue index invalid, max queue is:%u", data->nb_tx_queues); ++ return -EINVAL; ++ } ++ ++ ret = hinic3_get_port_index_by_dev(dev, &dpdk_index_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_get_port_index_by_dev error"); ++ return -EPERM; ++ } ++ ++ txq = hinic3_rte_zmalloc_socket(HINIC3_PORTS, sizeof(struct hinic3_standard_queue), RTE_CACHE_LINE_SIZE, socket_id); ++ if (txq == NULL) { ++ return -ENOMEM; ++ } ++ ++ vf_dev->reinject_queue.tx_queues[idx] = txq; ++ vf_dev->reinject_queue.is_queue_valid[idx] = true; ++ txq->queue_id = idx; ++ txq->info.type = HINIC3_TX_QUEUE; ++ txq->vport_id = vf_dev->vport_id; ++ txq->dpdk_port_id = vf_dev->dpdk_port_id; ++ txq->dpdk_index_id = dpdk_index_id; ++ ++ data->tx_queues[idx] = txq; ++ ++ return 0; ++} ++ ++static int hinic3_vf_info_update(struct hinic3_vf_dev *vf_dev) ++{ ++ int ret; ++ ret = hinic3_port_mgmt_set_usage_state(vf_dev->vport_id, HINIC3_SET_VF_STATE_UP); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "port mgmt set vf state up err, ret is %d", ret); ++ return -EPERM; ++ } ++ ++ ret = hinic3_vf_vni_update(vf_dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "vni set failed!"); ++ return -EPERM; ++ } ++ return 0; ++} ++ ++static int hinic3_vf_dev_set_ifindex(struct hinic3_vf_dev *dev, struct rte_eth_dev_data *data) ++{ ++ int ret; ++ ++ dev->port_ifindex = data->port_id; ++ ret = hinic3_set_port_map_by_ifindex(dev->vport_id, dev->port_ifindex); ++ return ret; ++} ++ ++static int hinic3_set_vf_dev(struct hinic3_vf_dev *vf_dev, struct rte_eth_dev_data *data) ++{ ++ int ret; ++ ++ ret = hinic3_eth_get_upcall_queue_map(vf_dev->vport_id, vf_dev->n_upcall_queue, ++ vf_dev->upcall_queue.upcall_queue_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_eth_get_upcall_queue_map error"); ++ return -EPERM; ++ } ++ ++ ret = hinic3_vf_dev_set_ifindex(vf_dev, data); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_dev_set_ifindex error"); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_vf_dev_configure_check(struct rte_eth_dev *dev) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ if (data->dev_started != HINIC3_DEV_STATE_STOP) { ++ HINIC3_LOG(ERR, VPORT, "the device must be stopped when the port is configured!"); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_check_vf_upcall_queue(struct hinic3_vf_dev *vf_dev) ++{ ++ /* 裸金属场景需要判断是否与配置文件一致 */ ++ if (hinic3_need_init_port() == true) { ++ if (vf_dev->n_upcall_queue != hinic3_get_upcall_queue_num()) { ++ HINIC3_LOG(ERR, VPORT, "vf upcall queue(%u) is not equal to configuration file num(%u)", ++ vf_dev->n_upcall_queue, hinic3_get_upcall_queue_num()); ++ return -EPERM; ++ } ++ vf_dev->n_upcall_queue = hinic3_get_upcall_queue_num(); ++ } ++ ++ /* 软件模拟upcall队列模式下不可使用共享upcall队列 */ ++ if (hinic3_get_virtual_queue_mode_enabled() == true) { ++ if (vf_dev->n_upcall_queue > MAX_RX_QUEUE_PER_VPORT) { ++ HINIC3_LOG(ERR, VPORT, "vf upcall queue(%u) cant be greater than (%u)", ++ vf_dev->n_upcall_queue, MAX_RX_QUEUE_PER_VPORT); ++ return -EPERM; ++ } ++ } ++ ++ return 0; ++} ++ ++int hinic3_vf_dev_configure(struct rte_eth_dev *dev) ++{ ++ int ret = hinic3_vf_dev_configure_check(dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "vf dev configure: input invalid dev"); ++ return ret; ++ } ++ ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ struct rte_eth_dev_data *data = dev->data; ++ uint64_t vdpa_feature = hinic3_vdpa_feature_get(); ++ ++ vf_dev->dev = dev; ++ if (data->nb_rx_queues != vf_dev->n_upcall_queue) { ++ if (data->nb_rx_queues == 0) { ++ HINIC3_LOG(ERR, VPORT, "number of rx queue can't be zero!"); ++ return -EPERM; ++ } ++ if (hinic3_get_virtual_queue_mode_enabled() == false) { ++ hinic3_vf_dev_del(dev); ++ } ++ vf_dev->n_upcall_queue = data->nb_rx_queues; ++ } ++ ++ ret = hinic3_check_vf_upcall_queue(vf_dev); ++ if (ret != 0) { ++ return -EPERM; ++ } ++ ++ vf_dev->n_txq = data->nb_tx_queues; ++ if (vf_dev->vport_id == HINIC3_PORT_ID_INVALID) { ++ ret = hinic3_vf_dev_add(dev); ++ if (ret != 0) { ++ return ret; ++ } ++ HINIC3_LOG(INFO, VPORT, "vport pci is %.4x:%.2x:%.2x.%x, maxqueue is %u, vdpa feature: %#llx", ++ vf_dev->pci_addr.domain, vf_dev->pci_addr.bus, vf_dev->pci_addr.devid, ++ vf_dev->pci_addr.function, vf_dev->max_queue_num, vdpa_feature); ++ ++ ret = hinic3_set_vf_dev(vf_dev, data); ++ if (ret != 0) { ++ hinic3_vf_dev_del(dev); ++ return -EPERM; ++ } ++ } ++ ++ ret = hinic3_vf_info_update(vf_dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "vf port info set update err, ret is %d", ret); ++ hinic3_vf_dev_del(dev); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int hinic3_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ int ret; ++ uint32_t status = 0; ++ bool is_ovs = 0; ++ struct rte_eth_dev_data *data = NULL; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ struct rte_eth_link hinic3_vf_dev_link = { ++ .link_speed = RTE_ETH_SPEED_NUM_100G, ++ .link_duplex = RTE_ETH_LINK_FULL_DUPLEX, ++ .link_status = RTE_ETH_LINK_UP, ++ .link_autoneg = RTE_ETH_LINK_FIXED, ++ }; ++ ++ is_ovs = hinic3_check_masked_to_exact_switch(); ++ data = dev->data; ++ vf_dev = hinic3_ethdev_get_vf_private(dev); ++ ++ if (is_ovs == false) { ++ ret = hinic3_port_mgmt_get_usage_state(vf_dev->vport_id, &status); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "port mgmt get vf state err, ret is %d", ret); ++ return ret; ++ } ++ } else { ++ status = HW_ETH_DEVICE_STATUS; ++ } ++ ++ if ((status & HW_ETH_DEVICE_STATUS) != 0) { ++ hinic3_vf_dev_link.link_status = RTE_ETH_LINK_UP; ++ } else { ++ hinic3_vf_dev_link.link_status = RTE_ETH_LINK_DOWN; ++ } ++ ++ data->dev_link = hinic3_vf_dev_link; ++ return 0; ++} ++ ++int hinic3_vf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ int ret; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ struct rte_eth_dev_data *data = dev->data; ++ ++ if (vf_dev->mtu == mtu) { ++ return 0; ++ } ++ ++ if (mtu > HINIC3_VF_MTU_MAX || mtu < HINIC3_VF_MTU_MIN) { ++ HINIC3_LOG(ERR, VPORT, "the MTU value range is incorrect"); ++ return -ERANGE; ++ } ++ ++ if (vf_dev->vport_id == HINIC3_PORT_ID_INVALID) { ++ HINIC3_LOG(ERR, VPORT, "invalid vport id!"); ++ return -EPERM; ++ } ++ ++ ret = hinic3_mtu_set(vf_dev->vport_id, mtu); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf set mtu failed, vport:%u!", vf_dev->vport_id); ++ return ret; ++ } ++ ++ vf_dev->mtu = mtu; ++ data->mtu = mtu; ++ ++ return ret; ++} ++ ++int hinic3_vf_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, const struct rte_flow_ops **ops) ++{ ++ *ops = g_hinic3_vf_flow_ops; ++ return 0; ++} ++ ++int hinic3_vf_extra_config_set_by_port_id(uint16_t port_id, char* conf_type, char* conf) ++{ ++ int ret; ++ struct hinic3_vf_dev *vf_dev = hinic3_get_private_data(port_id); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Failed to obtain the vf_dev"); ++ return -1; ++ } ++ for (size_t i = 0; i < ARRAY_SIZE(g_vf_extra_config_info); i++) { ++ if (strcmp(conf_type, g_vf_extra_config_info[i].args) == 0) { ++ if (conf == NULL) { ++ HINIC3_LOG(ERR, VPORT, "config can't be null"); ++ return -1; ++ } ++ ret = g_vf_extra_config_info[i].func(vf_dev, conf); ++ if (ret != 0) { ++ return ret; ++ } ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++int hinic3_vf_extra_config_check_by_port_id(uint16_t port_id) ++{ ++ struct hinic3_vf_dev *vf_dev = hinic3_get_private_data(port_id); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Failed to obtain the vf_dev"); ++ return -1; ++ } ++ for (int i = 0; i < HINIC3_VF_CONFIG_MAX; i++) { ++ if (vf_dev->state[i] != HINIC3_VF_CONFIG_NONE) { ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++int hinic3_vf_dev_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr) ++{ ++ int ret = 0; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ if (mac_addr == NULL) { ++ HINIC3_LOG(ERR, VPORT, "the mac_addr is NULL"); ++ return -EINVAL; ++ } ++ ++ if (eth_addr_is_zero(*(struct eth_addr *)mac_addr) == true) { ++ HINIC3_LOG(ERR, VPORT, "mac_addr is zero"); ++ return -EINVAL; ++ } ++ ++ vf_dev = hinic3_ethdev_get_vf_private(dev); ++ memcpy(&vf_dev->mac_addr, (struct eth_addr *)mac_addr, sizeof(struct eth_addr)); ++ ++ ret = hinic3_etheraddr_set(vf_dev->vport_id, vf_dev->mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to set mac for vf!"); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_port_set_mac(struct hinic3_vf_dev *vf_dev, struct hovs_pci_addr_info *info) ++{ ++ struct rte_cfgfile *inifile = NULL; ++ int ret = 0; ++ char port_name[HINIC3_MAX_PORT_NAME_LEN] = {0}; ++ const char *mac_addr = NULL; ++ ++ inifile = hinic3_cfgfile_load(AGENT_CFG_FILE); ++ if (inifile == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Faild to load agent config file: %s", AGENT_CFG_FILE); ++ return -1; ++ } ++ ++ ret = snprintf(port_name, HINIC3_MAX_PORT_NAME_LEN, "representor%d_mac", info->glb_func_inx); ++ if (ret < 0 || ret >= HINIC3_MAX_PORT_NAME_LEN) { ++ HINIC3_LOG(ERR, VPORT, "sprintf_s fail, ret is %d", ret); ++ rte_cfgfile_close(inifile); ++ return -1; ++ } ++ ++ mac_addr = rte_cfgfile_get_entry(inifile, AGENT_SECTION, port_name); ++ if (mac_addr == NULL) { ++ HINIC3_LOG(INFO, VPORT, "%s mac addr not set.", port_name); ++ rte_cfgfile_close(inifile); ++ return 0; ++ } ++ rte_cfgfile_close(inifile); ++ ++ ret = rte_ether_unformat_addr(mac_addr, (struct rte_ether_addr *)&vf_dev->mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "port mac unformat fail, ret is %d", ret); ++ return -1; ++ } ++ ++ if (!eth_addr_is_zero(vf_dev->mac_addr)) { ++ ret = hinic3_etheraddr_set(vf_dev->vport_id, vf_dev->mac_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to set mac for vf! ret is %d", ret); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++int hinic3_init_pci_list(struct hovs_phy_dev_info *dev, struct hinic3_vf_dev *vf_dev, uint32_t dev_num) ++{ ++ int ret = 0; ++ uint32_t max_queue_num = hinic3_max_queue_num_get(); ++ uint8_t n_upcall_queue = hinic3_upcall_queue_num_get(); ++ g_max_queue_num = max_queue_num; ++ g_n_upcall_queue = n_upcall_queue; ++ ++ for (uint32_t i = 0; i < dev_num; i++) { ++ struct hovs_pci_addr_info *info = &dev->pci_info[i]; ++ if ((info->type & HINIC3_DEVICE_DRIVER_TYPE) != HINIC3_DEVICE_DRIVER_TYPE) { ++ HINIC3_LOG(ERR, VPORT, "port type error!"); ++ return -1; ++ } ++ vf_dev[i].max_queue_num = max_queue_num; ++ vf_dev[i].n_upcall_queue = n_upcall_queue; ++ vf_dev[i].vport_id = HINIC3_PORT_ID_INVALID; ++ memcpy(&vf_dev[i].pci_addr, (struct rte_pci_addr *)&info->pci_addr, sizeof(struct rte_pci_addr)); ++ ++ ret = hinic3_vf_dynamic_port_add(&vf_dev[i]); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_dynamic_port_add err, ret is %d", ret); ++ return -1; ++ } ++ ++ ret = hinic3_port_mgmt_set_usage_state(vf_dev[i].vport_id, HINIC3_SET_VF_STATE_DOWN); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "port mgmt set vf state down err, ret is %d", ret); ++ return -1; ++ } ++ ++ ret = hinic3_port_set_mac(&vf_dev[i], info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "vf_dev set mac err, i is %d, ret is %d", i, ret); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++uint32_t hinic3_get_max_queue_num(void) ++{ ++ return g_max_queue_num; ++} ++ ++uint8_t hinic3_get_upcall_queue_num(void) ++{ ++ return g_n_upcall_queue; ++} ++ ++struct hinic3_vf_dev *hinic3_ethdev_get_vf_private(struct rte_eth_dev *dev) ++{ ++ return (struct hinic3_vf_dev *)dev->data->dev_private; ++} ++ ++static int hinic3_vf_virtual_rx_queue_setup_check(struct rte_eth_dev *dev, uint16_t idx, struct rte_mempool *mp) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return -EINVAL; ++ } ++ ++ if (mp == NULL) { ++ HINIC3_LOG(ERR, VPORT, "mp is NULL.\n"); ++ return -EINVAL; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ ++ if (idx >= data->nb_rx_queues) { ++ HINIC3_LOG(ERR, VPORT, "queue index invalid, max queue is:%u", data->nb_rx_queues); ++ return -EINVAL; ++ } ++ ++ if (idx >= MAX_RX_QUEUE_PER_VPORT) { ++ HINIC3_LOG(ERR, VPORT, "port upcall index greater than max"); ++ return -EINVAL; ++ } ++ ++ if (vf_dev->upcall_queue.rx_queues[idx] == NULL) { ++ HINIC3_LOG(ERR, VPORT, "this port hasn't alloc queue(s).\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_virtual_queue_setup( ++ struct hinic3_queue *rxq, uint16_t upcall_queue_id, uint16_t desc, unsigned int socket_id, struct rte_mempool *mp) ++{ ++ int ret = ~0; ++ struct hinic3_virtual_queue *virtual_rxq = rxq->variant.virtual_queue; ++ struct hinic3_physical_queue *physical_rxq = virtual_rxq->physical_queue; ++ ++ rxq->type = HINIC3_VIRTUAL_RX_QUEUE; ++ ++ virtual_rxq->ring = rte_ring_create(virtual_rxq->ring_name, desc, socket_id, 0); ++ if (virtual_rxq->ring == NULL) { ++ HINIC3_LOG(ERR, VPORT, "virtual queue ring create failed.\n"); ++ return -ENOMEM; ++ } ++ virtual_rxq->queue_info = rxq; ++ ++ if (physical_rxq->virtual_queue_valid_cnt == 0) { ++ ret = hinic3_port_mgmt_setup_upcall_queue(rxq->vport_id, rxq->queue_id, socket_id, mp); ++ if (ret != 0) { ++ rte_ring_free(virtual_rxq->ring); ++ virtual_rxq->ring = NULL; ++ HINIC3_LOG(ERR, VPORT, "port mgmt setup upcall queue error.\n"); ++ return ret; ++ } ++ physical_rxq->hiovs_queue_id = upcall_queue_id; ++ physical_rxq->mp = mp; ++ } ++ physical_rxq->is_virtual_queue_valids[virtual_rxq->virtual_queue_group_index] = true; ++ physical_rxq->virtual_queue_valid_cnt += 1; ++ ++ HINIC3_LOG(INFO, VPORT, ++ "virtual rxq %s setup success, vport id: %u, hiovs queue id: %u, physical rxq shared cnt: %u.\n", ++ virtual_rxq->ring_name, rxq->vport_id, ++ physical_rxq->hiovs_queue_id, physical_rxq->virtual_queue_valid_cnt); ++ return 0; ++} ++ ++int hinic3_vf_virtual_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_rxconf *conf __rte_unused, struct rte_mempool *mp) ++{ ++ int ret = hinic3_vf_virtual_rx_queue_setup_check(dev, idx, mp); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ struct hinic3_queue *rxq = vf_dev->upcall_queue.rx_queues[idx]; ++ uint16_t dpdk_index_id = 0; ++ ret = hinic3_get_port_index_by_dev(dev, &dpdk_index_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_get_port_index_by_dev error.\n"); ++ return ret; ++ } ++ ++ rxq->queue_id = idx; ++ rxq->vport_id = vf_dev->vport_id; ++ rxq->dpdk_port_id = vf_dev->dpdk_port_id; ++ rxq->dpdk_index_id = dpdk_index_id; ++ rxq->type = HINIC3_VIRTUAL_RX_QUEUE; ++ rte_atomic64_set(&rxq->statistic.pkts, 0); ++ rte_atomic64_set(&rxq->statistic.pkts_drop, 0); ++ ++ ret = hinic3_virtual_queue_setup(rxq, vf_dev->upcall_queue.upcall_queue_id[idx], desc, socket_id, mp); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ vf_dev->upcall_queue.is_queue_valid[idx] = true; ++ data->rx_queues[idx] = rxq; ++ ++ return 0; ++} ++ ++void hinic3_vf_virtual_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) ++{ ++ if (hinic3_is_ethdev_valid(dev) == false) { ++ return; ++ } ++ ++ struct rte_eth_dev_data *data = dev->data; ++ struct hinic3_vf_dev *vf_dev = hinic3_ethdev_get_vf_private(dev); ++ struct hinic3_queue *rxq = NULL; ++ struct hinic3_virtual_queue *virtual_rxq = NULL; ++ struct hinic3_physical_queue *physical_rxq = NULL; ++ ++ if (queue_id >= data->nb_rx_queues) { ++ HINIC3_LOG(ERR, VPORT, "queue index invalid, max queue is:%u.\n", data->nb_rx_queues); ++ return; ++ } ++ ++ rxq = vf_dev->upcall_queue.rx_queues[queue_id]; ++ virtual_rxq = rxq->variant.virtual_queue; ++ physical_rxq = virtual_rxq->physical_queue; ++ ++ physical_rxq->is_virtual_queue_valids[virtual_rxq->virtual_queue_group_index] = false; ++ physical_rxq->virtual_queue_valid_cnt -= 1; ++ if (vf_dev->upcall_queue.is_queue_valid[queue_id] == true && physical_rxq->virtual_queue_valid_cnt == 0) { ++ if (hinic3_port_mgmt_release_upcall_queue(vf_dev->vport_id, queue_id) != 0) { ++ HINIC3_LOG(ERR, VPORT, "port mgmt release upcall queue error.\n"); ++ } ++ physical_rxq->hiovs_queue_id = INVALID_UPCALL_QUEUE_ID; ++ physical_rxq->mp = NULL; ++ } ++ ++ vf_dev->upcall_queue.is_queue_valid[queue_id] = false; ++ data->rx_queues[queue_id] = NULL; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h +new file mode 100644 +index 0000000..7c2acb0 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h +@@ -0,0 +1,196 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VF_UTIL_H ++#define HINIC3_VF_UTIL_H ++ ++#include ++#include ++#include ++#include "rte_log.h" ++#include "rte_ring.h" ++#include "rte_malloc.h" ++#include "rte_ethdev.h" ++#include "rte_bus_pci.h" ++#include "hinic3_eth_util.h" ++#include "hinic3_vf_mgmt.h" ++#include "hinic3_queue.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++#define HINIC3_VF_DEFAULT_NB_QUEUES 1 ++#define HINIC3_MAX_JUMBO_FRAME_SIZE 9626 ++#define HINIC3_MAX_QOS_GROUP_NAME 512 ++#define HINIC3_VF_VNI_DEFAULT 0 ++#define HINIC3_VF_SECURITY_SMAC_INVALID 0 ++#define HINIC3_VF_SECURITY_SMAC_SINGLE 1 ++#define HINIC3_VF_SECURITY_BRD_LIMIT_INVALID 0 ++#define HINIC3_VF_SECURITY_ETH_GROUP_INVALID 0 ++#define HINIC3_BOND_MTU_MAX 9076 ++#define HINIC3_VF_MTU_MAX 9216 ++#define HINIC3_VF_MTU_MIN 256 ++#define HINIC3_VF_MAX_QUEUE_NUM 32 ++#define HINIC3_VF_UPCALL_NUM 16 ++#define VNI_INVALID (1UL << 24) ++#define HINIC3_DEFAULT_MTU 1500 ++#define HINIC3_VF_SIZE_OFFSET 26 /* eth头(14) + 内层vlan(4) * 2 + FCS(4) */ ++#define HINIC3_SET_VF_STATE_DOWN 0 ++#define HINIC3_SET_VF_STATE_UP 1 ++#define HINIC3_MAX_PORT_NAME_LEN 32 ++#define HINIC3_MAX_MAC_ADDR_LEN 18 ++#define INVALID_MTR_ID 0xFFFF ++#define INVALID_MTR_DIR 4 ++#define HINIC3_MTR_NUM 4 ++#define HINIC3_PORT_TYPE_NO_QOS (-2) ++#define HINIC3_MAX_MAC_ADDRS 1 ++#define HINIC3_MAX_HASH_MAC_ADDRS 0 ++#define HINIC3_MAX_VFS 0 ++#define HINIC3_MAX_VMDQ_POOLS 0 ++#define HW_ETH_DEVICE_STATUS (1U << 2) ++ ++#define HINIC3_ETH_RX_OFFLOAD_SCATTER (1UL << 13) ++#define HINIC3_ETH_TX_OFFLOAD_MULTI_SEGS (1UL << 15) ++ ++#define HINIC3_ETH_RSS_IPV4 (1UL << 2) ++#define HINIC3_ETH_RSS_FRAG_IPV4 (1UL << 3) ++#define HINIC3_ETH_RSS_NONFRAG_IPV4_TCP (1UL << 4) ++#define HINIC3_ETH_RSS_NONFRAG_IPV4_UDP (1UL << 5) ++#define HINIC3_ETH_RSS_IPV6 (1UL << 8) ++#define HINIC3_ETH_RSS_FRAG_IPV6 (1UL << 9) ++#define HINIC3_ETH_RSS_NONFRAG_IPV6_TCP (1UL << 10) ++#define HINIC3_ETH_RSS_NONFRAG_IPV6_UDP (1UL << 11) ++#define HINIC3_ETH_RSS_IPV6_EX (1UL << 15) ++#define HINIC3_ETH_RSS_IPV6_TCP_EX (1UL << 16) ++#define HINIC3_ETH_RSS_VXLAN (1UL << 19) ++ ++#define HINIC3_ETH_SUPPORT_RSS ( \ ++ HINIC3_ETH_RSS_IPV4 | \ ++ HINIC3_ETH_RSS_FRAG_IPV4 | \ ++ HINIC3_ETH_RSS_NONFRAG_IPV4_TCP | \ ++ HINIC3_ETH_RSS_NONFRAG_IPV4_UDP | \ ++ HINIC3_ETH_RSS_IPV6 | \ ++ HINIC3_ETH_RSS_FRAG_IPV6 | \ ++ HINIC3_ETH_RSS_NONFRAG_IPV6_TCP | \ ++ HINIC3_ETH_RSS_NONFRAG_IPV6_UDP | \ ++ HINIC3_ETH_RSS_IPV6_EX | \ ++ HINIC3_ETH_RSS_IPV6_TCP_EX | \ ++ HINIC3_ETH_RSS_VXLAN) ++ ++enum hinic3_vf_config_state { ++ HINIC3_VF_CONFIG_ADD, ++ HINIC3_VF_CONFIG_DEL, ++ HINIC3_VF_CONFIG_STABLE, ++ HINIC3_VF_CONFIG_NONE, ++}; ++ ++enum hinic3_vf_config { ++ HINIC3_VF_CONFIG_VNI, ++ HINIC3_VF_CONFIG_BUCKET_ID, ++ HINIC3_VF_CONFIG_SMAC, ++ HINIC3_VF_CONFIG_ETH_GROUP, ++ HINIC3_VF_CONFIG_BRD_RATE_LIMIT, ++ HINIC3_VF_CONFIG_MAX, ++}; ++ ++struct hinic3_mtr { ++ uint32_t direction; ++ uint32_t mtr_id; ++ bool is_used; ++}; ++ ++/* 此处将bond口及VF端口私有数据的首个uint16数据作为端口的vport_id,注意不要更换vport_id的位置 */ ++struct hinic3_vf_dev { ++ uint16_t vport_id; ++ uint8_t n_txq; ++ uint8_t n_upcall_queue; ++ uint8_t dpdk_port_id; ++ uint16_t port_ifindex; ++ uint32_t vni; ++ uint32_t mtu; ++ uint32_t max_queue_num; ++ struct hinic3_upcall_queue upcall_queue; ++ struct hinic3_reinject_queue reinject_queue; ++ struct eth_addr mac_addr; ++ struct rte_pci_addr pci_addr; ++ uint32_t qos_type; ++ char group_qos_name[HINIC3_MAX_QOS_GROUP_NAME + 1]; ++ struct smap qos_options; ++ uint16_t qos_id; ++ uint16_t group_qos_id; ++ struct hinic3_list profiles; ++ struct hinic3_mtr mtr[HINIC3_MTR_NUM]; ++ uint32_t brd_rate_limit; ++ uint16_t eth_type_group_id; ++ struct eth_addr src_mac_list[BUM_SMAC_MAX_COUNT]; ++ uint16_t src_mac_num; ++ enum hinic3_vf_config_state state[HINIC3_VF_CONFIG_MAX]; ++ rte_atomic64_t vf_upcall_pk_num; ++ rte_atomic64_t vf_upcall_pk_byt; ++ rte_atomic64_t vf_reinject_pk_num; ++ rte_atomic64_t vf_reinject_pk_byt; ++ struct rte_eth_dev *dev; ++}; ++ ++void hinic3_vf_flow_ops_construct(void); ++void hinic3_vf_flow_ops_destroy(void); ++ ++/* 获取设备信息 */ ++int hinic3_vf_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info); ++/* 对设备进行同步设置 */ ++int hinic3_vf_dev_configure(struct rte_eth_dev *dev); ++/* 设备启动 */ ++int hinic3_vf_dev_start(struct rte_eth_dev *dev); ++/* 设备停止 */ ++int hinic3_vf_dev_stop(struct rte_eth_dev *dev); ++/* 设置设备的连接状态为down */ ++int hinic3_vf_set_link_down(struct rte_eth_dev *dev); ++/* 设置设备的连接状态为up */ ++int hinic3_vf_set_link_up(struct rte_eth_dev *dev); ++/* 设备退出 */ ++int hinic3_vf_dev_close(struct rte_eth_dev *dev); ++/* 更新设备连接状态 */ ++int hinic3_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete); ++/* 设置设备的mtu */ ++int hinic3_vf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu); ++ ++/* 释放设备的rx队列 */ ++void hinic3_vf_rx_queue_release_dpdk2011(void *rxq); ++/* 释放设备的tx队列 */ ++void hinic3_vf_tx_queue_release_dpdk2011(void *txq); ++ ++/* 释放设备的rx队列 */ ++void hinic3_vf_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id); ++/* 释放设备的tx队列 */ ++void hinic3_vf_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id); ++ ++/* 设置设备的rx队列 */ ++int hinic3_vf_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_rxconf *conf, struct rte_mempool *mp); ++/* 设置设备的tx队列 */ ++int hinic3_vf_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_txconf *conf); ++/* rte_flow接口 */ ++int hinic3_vf_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused, const struct rte_flow_ops **ops); ++/* vf额外参数设置接口 */ ++int hinic3_vf_extra_config_set_by_port_id(uint16_t port_id, char* conf_type, char* conf); ++ ++int hinic3_vf_extra_config_check_by_port_id(uint16_t port_id); ++/* 获取dpdk-dev设备索引 */ ++int hinic3_get_port_index_by_dev(struct rte_eth_dev *dev, uint16_t *port_index); ++/* 设置端口mac地址 */ ++int hinic3_vf_dev_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr); ++/* 初始化PCI设备列表 */ ++int hinic3_init_pci_list(struct hovs_phy_dev_info *dev, struct hinic3_vf_dev *vf_dev, uint32_t dev_num); ++uint32_t hinic3_get_max_queue_num(void); ++uint8_t hinic3_get_upcall_queue_num(void); ++ ++/* 设置设备的软件rx队列 */ ++int hinic3_vf_virtual_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, ++ unsigned int socket_id, const struct rte_eth_rxconf *conf, struct rte_mempool *mp); ++/* 释放设备的软件rx队列 */ ++void hinic3_vf_virtual_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id); ++ ++struct hinic3_vf_dev *hinic3_ethdev_get_vf_private(struct rte_eth_dev *dev); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c +new file mode 100644 +index 0000000..91a82d6 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c +@@ -0,0 +1,643 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_vf_mgmt.h" ++#include ++#include ++#include "rte_pci.h" ++#include "rte_bus_pci.h" ++#include "rte_dev.h" ++#include "rte_string_fns.h" ++#include "hinic3_util.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_iface_port.h" ++#include "hinic3_util.h" ++#include "hinic3_log.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_mutex.h" ++#include "hinic3_mutex.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_smap.h" ++#include "hinic3_thread.h" ++#include "hinic3_mutex.h" ++#include "hinic3_vf_mgmt_virtual.h" ++#include "hinic3_vf_mgmt_baremetal.h" ++ ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++struct hinic3_mutex hwpt_phy_dev_mutex; ++static int g_port_conf_type = PORT_CONF_NULL; ++static bool g_port_list_init = true; ++ ++int hinic3_get_port_conf_type(void) ++{ ++ return g_port_conf_type; ++} ++ ++bool hinic3_get_port_list_init(void) ++{ ++ return g_port_list_init; ++} ++ ++void hinic3_set_port_list_init(bool value) ++{ ++ g_port_list_init = value; ++} ++ ++int hinic3_set_port_conf_type(int conf_type) ++{ ++ if ((conf_type != PORT_CONF_PCI) && (conf_type != PORT_CONF_FUNC)) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_set_port_conf_type bad type"); ++ return -1; ++ } ++ if (g_port_conf_type == PORT_CONF_NULL) { ++ g_port_conf_type = conf_type; ++ } else if (g_port_conf_type != conf_type) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_set_port_conf_type type conflict"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void hinic3_dev_mutex_init(void) ++{ ++ hinic3_pthread_mutex_init(&hwpt_phy_dev_mutex); ++} ++ ++static void hinic3_dev_mutex_uninit(void) ++{ ++ hinic3_pthread_mutex_destroy(&hwpt_phy_dev_mutex); ++} ++ ++struct dev_mgmt g_dev_list = {0}; ++ ++struct hinic3_dev_node *hinic3_alloc_dev_node(void) ++{ ++ struct hinic3_dev_node *rc = NULL; ++ ++ rc = hinic3_calloc(1, sizeof(struct hinic3_dev_node), HINIC3_PORTS); ++ if (rc == NULL) { ++ return NULL; ++ } ++ ++ return rc; ++} ++ ++int hinic3_hwpt_flavor_set_phy_dev_refcnt(const struct rte_pci_addr *pci_addr, uint8_t refcnt) ++{ ++ struct hinic3_dev_node *iter = NULL; ++ ++ if (pci_addr == NULL) { ++ return -1; ++ } ++ ++ if (hinic3_list_is_empty(&g_dev_list.pf_list) == true && hinic3_list_is_empty(&g_dev_list.vf_list) == true) { ++ HINIC3_LOG(ERR, VPORT, "dev_list is empty!"); ++ return -1; ++ } ++ ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ LIST_FOR_EACH(iter, node, &g_dev_list.pf_list) { ++ if (rte_pci_addr_cmp(pci_addr, &(iter->phy_dev.pci_addr)) == 0) { ++ iter->phy_dev.refcnt = refcnt; ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ HINIC3_LOG(INFO, VPORT, "Assigned PCI Address is %04x:%02x:%02x.%d choose %d", ++ pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function, refcnt); ++ return 0; ++ } ++ } ++ LIST_FOR_EACH(iter, node, &g_dev_list.vf_list) { ++ if (rte_pci_addr_cmp(pci_addr, &(iter->phy_dev.pci_addr)) == 0) { ++ iter->phy_dev.refcnt = refcnt; ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ HINIC3_LOG(INFO, VPORT, "Assigned PCI Address is %04x:%02x:%02x.%d choose %d", ++ pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function, refcnt); ++ return 0; ++ } ++ } ++ ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ HINIC3_LOG(ERR, VPORT, "invalid hw_type, cannot reset flavor, pci %04x:%02x:%02x.%u", ++ pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function); ++ return -1; ++} ++ ++enum hinic3_bdf_status hinic3_vf_flavor_get_phy_dev_refcnt(const struct rte_pci_addr *pci_addr) ++{ ++ enum hinic3_bdf_status bdf_status = HINIC3_VF_BDF_LIST_NULL; ++ struct hinic3_dev_node *iter_pf = NULL; ++ struct hinic3_dev_node *iter_vf = NULL; ++ ++ if (hinic3_device_mode_get() == SMART_NIC_MODE) { ++ hinic3_updata_netdev_hwpt_flavor(); ++ } ++ ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ if (hinic3_list_is_empty(&g_dev_list.pf_list) == false) { ++ LIST_FOR_EACH(iter_pf, node, &g_dev_list.pf_list) { ++ if (rte_pci_addr_cmp(pci_addr, &(iter_pf->phy_dev.pci_addr)) == 0) { ++ bdf_status = iter_pf->phy_dev.refcnt; ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ return bdf_status; ++ } ++ } ++ } ++ ++ if (hinic3_list_is_empty(&g_dev_list.vf_list) == false) { ++ LIST_FOR_EACH(iter_vf, node, &g_dev_list.vf_list) { ++ if (rte_pci_addr_cmp(pci_addr, &(iter_vf->phy_dev.pci_addr)) == 0) { ++ bdf_status = iter_vf->phy_dev.refcnt; ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ return bdf_status; ++ } ++ } ++ } ++ ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ return bdf_status; ++} ++ ++static void hinic3_hwpt_flavor_destroy_list(struct hinic3_list *list) ++{ ++ struct hinic3_dev_node *iter = NULL; ++ struct hinic3_dev_node *next = NULL; ++ ++ LIST_FOR_EACH_SAFE(iter, next, node, list) { ++ hinic3_list_remove(&(iter->node)); ++ hinic3_free(iter); ++ iter = NULL; ++ } ++} ++ ++void hinic3_hwpt_flavor_destroy_flavors(void) ++{ ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ if (!hinic3_list_is_empty(&g_dev_list.vf_list)) { ++ hinic3_hwpt_flavor_destroy_list(&g_dev_list.vf_list); ++ } ++ if (!hinic3_list_is_empty(&g_dev_list.pf_list)) { ++ hinic3_hwpt_flavor_destroy_list(&g_dev_list.pf_list); ++ } ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++} ++ ++int get_queue_pci_addr_from_str(const char *pci_addr_str, struct rte_pci_addr *pci_addr, uint8_t *queue_num_max) ++{ ++ int ret = -1; ++ union splitaddr hwpt_splitaddr; ++ char *endPtr = NULL; ++ char *new_pci_addr_str = hinic3_xstrdup(pci_addr_str, HINIC3_PORTS); ++ if (new_pci_addr_str == NULL) { ++ return -1; ++ } ++ ++ if (rte_strsplit(new_pci_addr_str, BUFSIZE_SHORT, hwpt_splitaddr.str, QUEUE_PCI_FMT_NVAL, ':') != ++ (QUEUE_PCI_FMT_NVAL - 1)) { ++ HINIC3_LOG(ERR, VPORT, "queue and pci address error!"); ++ goto free_exit; ++ } ++ ++ hwpt_splitaddr.function = strchr(hwpt_splitaddr.devid, '.'); ++ if (hwpt_splitaddr.function == NULL) { ++ HINIC3_LOG(ERR, VPORT, "pci address error! no function found!"); ++ goto free_exit; ++ } ++ ++ *hwpt_splitaddr.function++ = '\0'; ++ ++ *queue_num_max = (uint8_t)strtol(hwpt_splitaddr.queue_num, &endPtr, HWPT_HEX_BASE); ++ if (endPtr == NULL || *endPtr != '\0') { ++ goto free_exit; ++ } ++ pci_addr->domain = (uint16_t)strtoul(hwpt_splitaddr.domain, &endPtr, HWPT_HEX_BASE); ++ if (endPtr == NULL || *endPtr != '\0') { ++ goto free_exit; ++ } ++ pci_addr->bus = (uint8_t)strtoul(hwpt_splitaddr.bus, &endPtr, HWPT_HEX_BASE); ++ if (endPtr == NULL || *endPtr != '\0') { ++ goto free_exit; ++ } ++ pci_addr->devid = (uint8_t)strtoul(hwpt_splitaddr.devid, &endPtr, HWPT_HEX_BASE); ++ if (endPtr == NULL || *endPtr != '\0') { ++ goto free_exit; ++ } ++ pci_addr->function = (uint8_t)strtoul(hwpt_splitaddr.function, &endPtr, HWPT_DEC_BASE); ++ if (endPtr == NULL || *endPtr != '\0') { ++ goto free_exit; ++ } ++ ret = 0; ++ ++free_exit: ++ hinic3_free(new_pci_addr_str); ++ return ret; ++} ++ ++int hinic3_vf_check_pci(const struct rte_pci_addr *vf_pci_addr) ++{ ++ int ret; ++ char buf[BUFSIZE_SHORT] = {0}; ++ struct smap cfg; ++ struct rte_pci_addr real_pci_addr; ++ const char *ret_buf = NULL; ++ uint8_t queue_num_max; ++ ++ if (memset(&real_pci_addr, 0, sizeof(struct rte_pci_addr)) != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_vf_check_pci memset_s failed"); ++ return -1; ++ } ++ ++ hinic3_smap_init(&cfg); ++ ret = pci_addr_format(vf_pci_addr, buf, BUFSIZE_SHORT); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "check pci addr parse failed."); ++ goto err; ++ } ++ hinic3_smap_add(&cfg, HINIC3_GLOBAL_CFG_ARG_VF_INFO_STR, buf, HINIC3_PORTS); ++ ++ ret = hinic3_global_cfg_get(&cfg); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "Global cfg get error, errno is %d\n", ret); ++ goto err; ++ } ++ ++ ret_buf = hinic3_smap_get(&cfg, HINIC3_GLOBAL_CFG_ARG_VF_INFO_STR); ++ if (ret_buf == NULL) { ++ HINIC3_LOG(ERR, VPORT, "vf_info is empty for %s", buf); ++ ret = -1; ++ goto err; ++ } ++ ++ ret = get_queue_pci_addr_from_str(ret_buf, &real_pci_addr, &queue_num_max); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "getting pci_addr from hiovs for vm failed, errno is %d\n", ret); ++ goto err; ++ } ++ ++err: ++ hinic3_smap_destroy(&cfg); ++ return ret; ++} ++ ++void hinic3_hwpt_flavor_phy_dev_construct_one(const struct rte_pci_addr *pci_addr, ++ int function_id, enum hiovs_hwpt_phy_dev_type dev_type) ++{ ++ struct hinic3_dev_node *rc = NULL; ++ ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ rc = hinic3_alloc_dev_node(); ++ if (rc == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to aclloc hwpt_phy_dev node"); ++ goto unlock_exit; ++ } ++ ++ memcpy(&(rc->phy_dev.pci_addr), pci_addr, sizeof(struct rte_pci_addr)); ++ rc->phy_dev.type = dev_type; ++ rc->phy_dev.refcnt = HWPT_FLAVOR_REFCNT_UNUSED; ++ rc->phy_dev.function_id = function_id; ++ ++ if (dev_type == HWPT_PHY_DEV_TYPE_PF) { ++ hinic3_list_insert(&g_dev_list.pf_list, &(rc->node)); ++ } else if (dev_type == HWPT_PHY_DEV_TYPE_VF) { ++ hinic3_list_insert(&g_dev_list.vf_list, &(rc->node)); ++ } else { ++ HINIC3_LOG(WARNING, VPORT, "unknown phy dev type %u", rc->phy_dev.type); ++ hinic3_free(rc); ++ } ++ ++unlock_exit: ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++} ++ ++int hinic3_get_function_id_by_pci(struct rte_pci_addr *pci_addr) ++{ ++ int ret = 0; ++ struct hovs_phy_dev_info dev = { 0 }; ++ union bdf_info_u bdf_info; ++ if (hinic3_query_bdf_type_get() == QUERY_BDF_TYPE_REAL) { ++ bdf_info.bs.bdf_type = BDF_TYPE_REAL; ++ } else { ++ bdf_info.bs.bdf_type = BDF_TYPE_FAKE; ++ } ++ bdf_info.bs.func_id_flag = 1; ++ ++ ret = hinic3_global_pcie_list_query(1, bdf_info.value, &dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 get global pcie list err "); ++ return -1; ++ } ++ ++ for (uint32_t i = 0; i < dev.phy_dev_num; i++) { ++ struct hovs_pci_addr_info *info = &dev.pci_info[i]; ++ if (rte_pci_addr_cmp((struct rte_pci_addr *)&info->pci_addr, pci_addr) == 0) { ++ return info->glb_func_inx; ++ } ++ } ++ ++ return -1; ++} ++int hinic3_get_pci_by_function_id(uint16_t func_id, struct rte_pci_addr *pci_addr) ++{ ++ int ret = 0; ++ struct hovs_phy_dev_info dev = { 0 }; ++ union bdf_info_u bdf_info; ++ ++ bdf_info.bs.bdf_type = BDF_TYPE_FAKE; ++ bdf_info.bs.func_id_flag = 1; ++ ++ ret = hinic3_global_pcie_list_query(HINIC3_FRONT_BACK_FAKE_WITH_FUNC_ID, bdf_info.value, &dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 get global pcie list err "); ++ return -1; ++ } ++ ++ for (uint32_t i = 0; i < dev.phy_dev_num; i++) { ++ struct hovs_pci_addr_info *info = &dev.pci_info[i]; ++ if (func_id == info->glb_func_inx) { ++ memcpy(pci_addr, &info->pci_addr, sizeof(struct rte_pci_addr)); ++ return 0; ++ } ++ } ++ ++ return HINIC3_PORT_TYPE_NO_QOS; ++} ++ ++bool hinic3_check_flavor_phy_dev(const struct rte_pci_addr *pci_addr) ++{ ++ int ret; ++ DIR *dir_devices = NULL; ++ char pci_addr_buf[HWPT_PCI_ADDR_LEN_MAX] = { 0 }; ++ char real_path[PATH_MAX] = {0}; ++ char name_buf[PATH_MAX] = {0}; ++ ++ ret = hinic3_vf_check_pci(pci_addr); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "failed to exec hinic3_vf_check_pci"); ++ return false; ++ } ++ ++ ret = pci_addr_format(pci_addr, pci_addr_buf, HWPT_PCI_ADDR_LEN_MAX); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "pci addr parse failed."); ++ return false; ++ } ++ ++ ret = snprintf(real_path, PATH_MAX, "%s/%s", SYSFS_PCI_DEVICES, pci_addr_buf); ++ if ((ret < 0) || (ret >= PATH_MAX)) { ++ HINIC3_LOG(ERR, VPORT, "File name too long byte_num(%d)", ret); ++ return false; ++ } ++ ++ if (realpath(real_path, name_buf) == NULL) { ++ return false; ++ } ++ /* 检查是否为文件 */ ++ dir_devices = opendir(name_buf); ++ if (dir_devices == NULL) { ++ HINIC3_LOG(ERR, VPORT, "Cannot open %s", name_buf); ++ return false; ++ } ++ closedir(dir_devices); ++ return true; ++} ++ ++int hinic3_dpu_vf_flavor_add(void) ++{ ++ int ret = 0; ++ struct hovs_phy_dev_info dev = { 0 }; ++ union bdf_info_u bdf_info; ++ int query_bdf_type = hinic3_query_bdf_type_get(); ++ if (query_bdf_type == QUERY_BDF_TYPE_REAL) { ++ bdf_info.bs.bdf_type = BDF_TYPE_REAL; ++ } else { ++ bdf_info.bs.bdf_type = BDF_TYPE_FAKE; ++ } ++ bdf_info.bs.func_id_flag = 1; ++ ret = hinic3_global_pcie_list_query(1, bdf_info.value, &dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 get global pcie list err"); ++ return -1; ++ } ++ ++ for (uint32_t i = 0; i < dev.phy_dev_num; i++) { ++ struct hovs_pci_addr_info *info = &dev.pci_info[i]; ++ if (hinic3_is_support_vf_port() && ((info->type & HINIC3_DEVICE_TYPE) == HWPT_PHY_DEV_TYPE_VF)) { ++ hinic3_hwpt_flavor_phy_dev_construct_one((struct rte_pci_addr *)&info->pci_addr, info->glb_func_inx, ++ HWPT_PHY_DEV_TYPE_VF); ++ } else if (hinic3_is_support_pf_port() && ((info->type & HINIC3_DEVICE_TYPE) == HWPT_PHY_DEV_TYPE_PF)) { ++ hinic3_hwpt_flavor_phy_dev_construct_one((struct rte_pci_addr *)&info->pci_addr, info->glb_func_inx, ++ HWPT_PHY_DEV_TYPE_PF); ++ } ++ } ++ ++ return 0; ++} ++ ++int hinic3_hwpt_flavor_mgmt_init(void) ++{ ++ int ret = 0; ++ bool port_init_resources = hinic3_need_init_port(); ++ ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ hinic3_list_init(&(g_dev_list.pf_list)); ++ hinic3_list_init(&(g_dev_list.vf_list)); ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ ++ if (port_init_resources == true) { ++ ret = hinic3_dpu_bare_metal_flavor_mgmt_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 dpu bare metal flavor mgmt init err, ret is %d", ret); ++ return -1; ++ } ++ } else { ++ ret = hinic3_virtual_flavor_mgmt_init(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 virtualized flavor mgmt init err, ret is %d", ret); ++ return -1; ++ } ++ } ++ ++ ret = hinic3_port_upcall_mtu_set(OVS_VPORT_TYPE_VF, HINIC3_VF_MTU_MAX); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 port upcall mtu set err, ret is %d", ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void mgmt_vf_virtio_queue(uint32_t max_queue_num, bool is_del) ++{ ++ struct hinic3_dp_extend_info *dp_info = hinic3_get_offload_extend_info(); ++ if ((dp_info == NULL) || (dp_info->hw_offload == NULL)) { ++ return; ++ } ++ ++ struct hinic3_flow_agent_db *hw_offload = dp_info->hw_offload; ++ uint32_t real_queue_num = max_queue_num + 1; ++ if (!is_del) { ++ hw_offload->queue_num.used_now += real_queue_num; ++ return; ++ } ++ ++ if (hw_offload->queue_num.used_now >= real_queue_num) { ++ hw_offload->queue_num.used_now -= real_queue_num; ++ } else { ++ HINIC3_LOG(ERR, VPORT, "An unexpected problem occurred, virtio queue used_now < real_queue_num"); ++ } ++} ++ ++int hinic3_insert_port_node(struct hinic3_dev_node *dev_node, struct dev_mgmt *dev) ++{ ++ struct hinic3_dev_node *rc = NULL; ++ ++ rc = hinic3_alloc_dev_node(); ++ if (rc == NULL) { ++ HINIC3_LOG(ERR, VPORT, "failed to aclloc hwpt_phy_dev node"); ++ return -1; ++ } ++ ++ memcpy(&(rc->phy_dev.pci_addr), &(dev_node->phy_dev.pci_addr), sizeof(struct rte_pci_addr)); ++ rc->phy_dev.refcnt = dev_node->phy_dev.refcnt; ++ rc->phy_dev.type = dev_node->phy_dev.type; ++ ++ hinic3_list_insert(&(dev->vf_list), &(rc->node)); ++ return 0; ++} ++ ++int hinic3_get_used_port_info(struct dev_mgmt *dev) ++{ ++ int ret; ++ struct hinic3_dev_node *iter = NULL; ++ struct hinic3_list *dev_list = &g_dev_list.vf_list; ++ hinic3_list_init(&(dev->vf_list)); ++ hinic3_list_init(&(dev->pf_list)); ++ ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ if (hinic3_list_is_empty(dev_list) == true) { ++ HINIC3_LOG(INFO, VPORT, "vf flavor dev list is null"); ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ return 0; ++ } ++ ++ LIST_FOR_EACH(iter, node, dev_list) { ++ uint8_t dev_status = iter->phy_dev.refcnt; ++ if (dev_status == HWPT_FLAVOR_REFCNT_USED || dev_status == HWPT_FLAVOR_REFCNT_INVALID) { ++ ret = hinic3_insert_port_node(iter, dev); ++ if (ret != 0) { ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ HINIC3_LOG(ERR, VPORT, "hinic3_insert_port_node err, ret is %d", ret); ++ return -1; ++ } ++ } ++ } ++ ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ return 0; ++} ++ ++bool hinic3_updata_vf_flavor_phy_dev_refcnt(const struct rte_pci_addr *pci_addr) ++{ ++ struct hinic3_dev_node *iter_vf = NULL; ++ bool is_find_node = false; ++ ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ if (hinic3_list_is_empty(&g_dev_list.vf_list) == false) { ++ LIST_FOR_EACH(iter_vf, node, &g_dev_list.vf_list) { ++ if (rte_pci_addr_cmp(pci_addr, &(iter_vf->phy_dev.pci_addr)) == 0) { ++ iter_vf->phy_dev.refcnt = HWPT_FLAVOR_REFCNT_USED; ++ is_find_node = true; ++ break; ++ } ++ } ++ } ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ ++ return is_find_node; ++} ++ ++void hinic3_updata_vf_flavor_dev_info(struct dev_mgmt *dev) ++{ ++ int ret; ++ struct hinic3_dev_node *iter = NULL; ++ struct hinic3_list *dev_list = &(dev->vf_list); ++ ++ if (hinic3_list_is_empty(dev_list) == true) { ++ HINIC3_LOG(ERR, VPORT, "vf flavor dev info dev list is null"); ++ return; ++ } ++ ++ LIST_FOR_EACH(iter, node, dev_list) { ++ bool is_find = hinic3_updata_vf_flavor_phy_dev_refcnt(&(iter->phy_dev.pci_addr)); ++ if (is_find == false) { ++ iter->phy_dev.refcnt = HWPT_FLAVOR_REFCNT_INVALID; ++ hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); ++ ret = hinic3_insert_port_node(iter, &g_dev_list); ++ hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_insert_port_node err, ret is %d", ret); ++ } ++ ++ HINIC3_LOG(ERR, VPORT, "This port should be deleted, PCI Address is %04x:%02x:%02x.%d", ++ iter->phy_dev.pci_addr.domain, iter->phy_dev.pci_addr.bus, iter->phy_dev.pci_addr.devid, ++ iter->phy_dev.pci_addr.function); ++ } ++ } ++ ++ return; ++} ++ ++void hinic3_destroy_used_port_info(struct dev_mgmt *dev) ++{ ++ if (!hinic3_list_is_empty(&(dev->vf_list))) { ++ hinic3_hwpt_flavor_destroy_list(&(dev->vf_list)); ++ } ++ if (!hinic3_list_is_empty(&(dev->pf_list))) { ++ hinic3_hwpt_flavor_destroy_list(&(dev->pf_list)); ++ } ++} ++ ++ ++struct dev_mgmt *hinic3_updata_netdev_hwpt_flavor(void) ++{ ++ int ret; ++ struct dev_mgmt dev_used_list = {0}; ++ ++ ret = hinic3_get_used_port_info(&dev_used_list); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_get_used_port_info err, ret is %d", ret); ++ return NULL; ++ } ++ /* 清空全局链表,重新获取设备信息 */ ++ hinic3_hwpt_flavor_destroy_flavors(); ++ ret = hinic3_smart_vf_flavor_add(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_smart_vf_flavor_add err, ret is %d", ret); ++ return NULL; ++ } ++ /* 更新设备信息 */ ++ hinic3_updata_vf_flavor_dev_info(&dev_used_list); ++ /* 销毁链表 */ ++ hinic3_destroy_used_port_info(&dev_used_list); ++ return &g_dev_list; ++} ++ ++struct dev_mgmt *get_netdev_hwpt_flavor(void) ++{ ++ return &g_dev_list; ++} ++ ++void hinic3_dev_init(void) ++{ ++ hinic3_dev_mutex_init(); ++} ++ ++void hinic3_dev_uninit(void) ++{ ++ hinic3_dev_mutex_uninit(); ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.h +new file mode 100644 +index 0000000..3cacee6 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.h +@@ -0,0 +1,113 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VF_MGMT_H ++#define HINIC3_VF_MGMT_H ++ ++#include ++#include ++#include ++#include ++#include ++#include "rte_pci.h" ++#include "hinic3_list.h" ++#include "hinic3_iface_port.h" ++ ++#define HWPT_FLAVOR_TYPE_NONE 0 ++#define HWPT_FLAVOR_TYPE_MIN 1 ++#define HWPT_FLAVOR_TYPE_MAX 32 ++#define HWPT_PCI_ADDR_LEN_MAX 32 ++#define VF_FLAVOR_QUEUE_NUM_INVALID 0xff ++ ++#define HWPT_DIR_PARRENT_LEV 2 ++#define HWPT_NO_PARRENT_LEV 1 ++ ++#define HWPT_HEX_BASE 16 ++#define HWPT_DEC_BASE 10 ++ ++#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices" ++#define QUEUE_PCI_FMT_NVAL (PCI_FMT_NVAL + 1) ++ ++#define HWPT_HWTYPE_PF_STR "PF" ++#define HWPT_HWTYPE_VF_STR "VF" ++ ++#define HWPT_HWTYPE_VF_BAR_NUM 3 ++#define HWPT_REPRESENTOR_DEV_MAX_CNT 256 ++#define PORT_CONF_NULL 0 ++#define PORT_CONF_PCI 1 ++#define PORT_CONF_FUNC 2 ++ ++#define HWPT_FLAVOR_REFCNT_UNUSED 0 ++#define HWPT_FLAVOR_REFCNT_USED 1 ++#define HWPT_FLAVOR_REFCNT_INVALID 2 ++#define HWPT_FLAVOR_REFCNT_NULL 3 ++struct hwpt_phy_dev { ++ /* phy dev type, pf or vf */ ++ uint8_t type; ++ /* flag of pci is assign */ ++ uint8_t refcnt; ++ /* corresponding phy dev's pci address */ ++ struct rte_pci_addr pci_addr; ++ /* corresponding phy dev's function id */ ++ int function_id; ++}; ++ ++struct hinic3_dev_node { ++ struct hinic3_list node; ++ struct hwpt_phy_dev phy_dev; ++}; ++ ++struct dev_mgmt { ++ struct hinic3_list vf_list; ++ struct hinic3_list pf_list; ++}; ++ ++struct dir_info_input { ++ char name_buf[PATH_MAX]; ++ char parent_name_buf[PATH_MAX]; ++ char pci_addr_buf[HWPT_PCI_ADDR_LEN_MAX]; ++}; ++ ++struct dir_info_output { ++ char *parent; ++ char *parent_parent; ++}; ++ ++union splitaddr { ++ struct { ++ char *queue_num; ++ char *domain; ++ char *bus; ++ char *devid; ++ char *function; ++ }; ++ char *str[QUEUE_PCI_FMT_NVAL]; /* last element-separator is "." not ":" */ ++}; ++ ++enum hinic3_bdf_status { ++ HINIC3_VF_BDF_NOT_USED, ++ HINIC3_VF_BDF_USED, ++ HINIC3_VF_BDF_INVALID, ++ HINIC3_VF_BDF_LIST_NULL, ++}; ++ ++int hinic3_hwpt_flavor_mgmt_init(void); ++enum hinic3_bdf_status hinic3_vf_flavor_get_phy_dev_refcnt(const struct rte_pci_addr *pci_addr); ++int hinic3_hwpt_flavor_set_phy_dev_refcnt(const struct rte_pci_addr *pci_addr, uint8_t refcnt); ++struct dev_mgmt *get_netdev_hwpt_flavor(void); ++struct dev_mgmt *hinic3_updata_netdev_hwpt_flavor(void); ++bool hinic3_check_flavor_phy_dev(const struct rte_pci_addr *pci_addr); ++void mgmt_vf_virtio_queue(uint32_t max_queue_num, bool is_del); ++int hinic3_get_pci_by_function_id(uint16_t func_id, struct rte_pci_addr *pci_addr); ++int hinic3_get_function_id_by_pci(struct rte_pci_addr *pci_addr); ++void hinic3_hwpt_flavor_phy_dev_construct_one(const struct rte_pci_addr *pci_addr, int function_id, ++ enum hiovs_hwpt_phy_dev_type dev_type); ++int hinic3_get_port_conf_type(void); ++int hinic3_set_port_conf_type(int conf_type); ++void hinic3_dev_init(void); ++void hinic3_dev_uninit(void); ++bool hinic3_get_port_list_init(void); ++void hinic3_set_port_list_init(bool value); ++int hinic3_dpu_vf_flavor_add(void); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.c +new file mode 100644 +index 0000000..dbe60c7 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.c +@@ -0,0 +1,72 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_vf_mgmt_baremetal.h" ++#include ++#include "hinic3_util.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_vf_mgmt.h" ++#include "rte_pci.h" ++#include "rte_bus_pci.h" ++#include "rte_dev.h" ++#include "rte_string_fns.h" ++ ++inline static bool hinic3_check_dev_vf(uint8_t type) ++{ ++ return hinic3_is_support_vf_port() && ++ ((type & HINIC3_DEVICE_DRIVER_TYPE) == HINIC3_DEVICE_DRIVER_TYPE) && ++ ((type & HINIC3_DEVICE_TYPE) == HWPT_PHY_DEV_TYPE_VF); ++} ++ ++inline static bool hinic3_check_dev_pf(uint8_t type) ++{ ++ return hinic3_is_support_pf_port() && ++ ((type & HINIC3_DEVICE_DRIVER_TYPE) == HINIC3_DEVICE_DRIVER_TYPE) && ++ ((type & HINIC3_DEVICE_TYPE) == HWPT_PHY_DEV_TYPE_PF); ++} ++ ++int hinic3_dpu_bare_metal_flavor_mgmt_init(void) ++{ ++ int ret = 0; ++ uint32_t dev_num; ++ struct hovs_phy_dev_info dev = { 0 }; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ union bdf_info_u bdf_info; ++ ++ bdf_info.bs.bdf_type = BDF_TYPE_FAKE; ++ bdf_info.bs.func_id_flag = 1; ++ ++ ret = hinic3_global_pcie_list_query(1, bdf_info.value, &dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 get global pcie list err "); ++ return ret; ++ } ++ ++ dev_num = MIN(dev.phy_dev_num, HWPT_REPRESENTOR_DEV_MAX_CNT); ++ for (uint32_t i = 0; i < dev_num; i++) { ++ struct hovs_pci_addr_info *info = &dev.pci_info[i]; ++ if (hinic3_check_dev_vf(info->type)) { ++ hinic3_hwpt_flavor_phy_dev_construct_one((struct rte_pci_addr *)&info->pci_addr, info->glb_func_inx, ++ HWPT_PHY_DEV_TYPE_VF); ++ } else if (hinic3_check_dev_pf(info->type)) { ++ hinic3_hwpt_flavor_phy_dev_construct_one((struct rte_pci_addr *)&info->pci_addr, info->glb_func_inx, ++ HWPT_PHY_DEV_TYPE_PF); ++ } ++ } ++ ++ vf_dev = (struct hinic3_vf_dev *)hinic3_calloc(dev_num, sizeof(struct hinic3_vf_dev), HINIC3_PORTS); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 vf_dev calloc err"); ++ return -1; ++ } ++ ++ ret = hinic3_init_pci_list(&dev, vf_dev, dev_num); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 init pci list err"); ++ hinic3_free(vf_dev); ++ return ret; ++ } ++ hinic3_free(vf_dev); ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.h +new file mode 100644 +index 0000000..b04458b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_baremetal.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VF_MGMT_BAREMETAL_H ++#define HINIC3_VF_MGMT_BAREMETAL_H ++ ++int hinic3_dpu_bare_metal_flavor_mgmt_init(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.c +new file mode 100644 +index 0000000..6f93278 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.c +@@ -0,0 +1,61 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_vf_mgmt_virtual.h" ++#include ++#include ++#include "hinic3_vf_mgmt.h" ++#include "hinic3_vf_controller.h" ++#include "rte_pci.h" ++#include "rte_bus_pci.h" ++#include "rte_dev.h" ++#include "rte_string_fns.h" ++ ++int hinic3_smart_vf_flavor_add(void) ++{ ++ int ret = 0; ++ struct hovs_phy_dev_info dev = { 0 }; ++ union bdf_info_u bdf_info; ++ ++ bdf_info.bs.bdf_type = BDF_TYPE_REAL; ++ bdf_info.bs.func_id_flag = 0; ++ ++ ret = hinic3_global_pcie_list_query(0, bdf_info.value, &dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3 get global pcie list err"); ++ return -1; ++ } ++ ++ for (uint32_t i = 0; i < dev.phy_dev_num; i++) { ++ struct hovs_pci_addr_info *info = &dev.pci_info[i]; ++ /* 检查新增加的PCI有效性 */ ++ if (hinic3_check_flavor_phy_dev((struct rte_pci_addr *)&info->pci_addr) == false) { ++ continue; ++ } ++ /* 添加到全局链表 */ ++ if ((info->type & HINIC3_DEVICE_TYPE) == HWPT_PHY_DEV_TYPE_VF) { ++ hinic3_hwpt_flavor_phy_dev_construct_one((struct rte_pci_addr *)&info->pci_addr, 0, ++ HWPT_PHY_DEV_TYPE_VF); ++ } ++ } ++ ++ return 0; ++} ++ ++int hinic3_virtual_flavor_mgmt_init(void) ++{ ++ int ret = 0; ++ bool nic_type = hinic3_device_mode_get(); ++ if (nic_type == DPU_MODE) { ++ hinic3_set_port_list_init(false); ++ } else { ++ ret = hinic3_smart_vf_flavor_add(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "hinic3_smart_vf_flavor_add err, ret is %d", ret); ++ return -1; ++ } ++ } ++ ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.h +new file mode 100644 +index 0000000..abf54ca +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt_virtual.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2025 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VF_MGMT_VIRTUAL_H ++#define HINIC3_VF_MGMT_VIRTUAL_H ++ ++int hinic3_virtual_flavor_mgmt_init(void); ++int hinic3_smart_vf_flavor_add(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c b/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c +new file mode 100644 +index 0000000..ba5ca31 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c +@@ -0,0 +1,331 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_vf_port_qos_public.h" ++#include ++#include "rte_kvargs.h" ++#include "rte_devargs.h" ++#include "rte_ethdev.h" ++#include "rte_string_fns.h" ++#include "hinic3_util.h" ++#include "hinic3_tlv_key.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_mtr.h" ++#include "hinic3_smap.h" ++ ++static const char *const hinic3_bond_valid_arguments[] = { ++ HINIC3_BOND_NAME, ++ HINIC3_PORT_PCI_ID, ++ HINIC3_PORT_MAC, ++ HINIC3_MAX_QUEUE_NUM, ++ HINIC3_REPRESENTOR_ID, ++ HINIC3_PRIORITY_UPCALL, ++ NULL ++}; ++ ++group_qos_type_key g_group_qos_type_key = { ++ .qos_type_key = { ++ HINIC3_GROUP_QOS_BW_INGRESS, ++ HINIC3_GROUP_QOS_PPS_INGRESS, ++ HINIC3_GROUP_QOS_BW_EGRESS, ++ HINIC3_GROUP_QOS_PPS_EGRESS, ++ } ++}; ++ ++group_qos_type_key *hinic3_get_qos_type_key(void) ++{ ++ return &g_group_qos_type_key; ++} ++ ++int check_vf_bw_args(struct qos_single_value vm_qos) ++{ ++ uint64_t max_rate = vm_qos.max_rate; ++ uint64_t max_burst = vm_qos.max_burst; ++ uint64_t min_rate = vm_qos.min_rate; ++ uint64_t min_burst = vm_qos.min_burst; ++ ++ if (vm_qos.is_RFC2697 == true) { ++ if ((min_rate < MIN_BW_RATE_QOS) || (min_rate >= MAX_BW_RATE_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cir range is incorrect."); ++ return -1; ++ } ++ ++ if ((min_burst < MIN_BW_RATE_QOS) || (min_burst > MAX_BW_BURST_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cbs range is incorrect."); ++ return -1; ++ } ++ ++ if ((max_burst + min_burst) > MAX_BW_BURST_QOS) { ++ HINIC3_LOG(ERR, QOS, "cbs and ebs range is incorrect."); ++ return -1; ++ } ++ } else { ++ if ((min_rate < MIN_BW_RATE_QOS) || (min_burst < MIN_BW_RATE_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cir or cbs range is incorrect."); ++ return -1; ++ } ++ ++ if ((max_rate < min_rate) || (max_rate >= MAX_BW_RATE_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cir or pir range is incorrect."); ++ return -1; ++ } ++ ++ if ((max_burst < min_burst) || (max_burst > MAX_BW_BURST_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cbs or pbs range is incorrect."); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++int check_vf_pps_args(struct qos_single_value vm_qos) ++{ ++ uint64_t max_rate = vm_qos.max_rate; ++ uint64_t max_burst = vm_qos.max_burst; ++ uint64_t min_rate = vm_qos.min_rate; ++ uint64_t min_burst = vm_qos.min_burst; ++ ++ if ((min_rate < MIN_PPS_RATE_QOS) || (min_burst < MIN_PPS_RATE_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cir or cbs range is incorrect."); ++ return -1; ++ } ++ ++ if ((max_rate < min_rate) || (max_rate >= MAX_PPS_RATE_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cir or pir range is incorrect."); ++ return -1; ++ } ++ ++ if ((max_burst < min_burst) || (max_burst > MAX_PPS_BURST_QOS)) { ++ HINIC3_LOG(ERR, QOS, "cbs or pbs range is incorrect."); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int hinic3_port_mgmt_set_qos_id(uint16_t vport_id, uint16_t bucket_id) ++{ ++ int ret; ++ struct smap args; ++ struct smap unset_args; ++ ++ if (bucket_id == UNBIND_QOS_ID) { ++ HINIC3_LOG(DEBUG, QOS, "remove vport_id %u qos_id", vport_id); ++ } else { ++ HINIC3_LOG(DEBUG, QOS, "set vport_id %u qos_id %u", vport_id, bucket_id); ++ } ++ ++ hinic3_smap_init(&args); ++ hinic3_smap_init(&unset_args); ++ ++ hinic3_smap_add_format(HINIC3_QOS, &args, HINIC3_PORT_BUCKET_ID, "%u", bucket_id); ++ ret = hinic3_port_mgmt_set(vport_id, &args, &unset_args); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "failed to set qos id for vport_id (%u)", vport_id); ++ } ++ ++ hinic3_smap_destroy(&args); ++ hinic3_smap_destroy(&unset_args); ++ ++ return ret; ++} ++ ++bool is_hinic3_vf_dev(uint16_t port_id) ++{ ++ struct rte_kvargs *kvlist = NULL; ++ struct rte_eth_dev_info info = {0}; ++ ++ int ret = rte_eth_dev_info_get(port_id, &info); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "when check hinic3 vf dev, get eth dev info fail!"); ++ return false; ++ } ++ const char *driver_name = info.driver_name; ++ if (driver_name == NULL || strlen(driver_name) == 0) { ++ HINIC3_LOG(ERR, QOS, "when check hinic3 vf dev, get driver name fail!"); ++ return false; ++ } ++ ++ struct rte_devargs *devargs = info.device->devargs; ++ kvlist = rte_kvargs_parse(devargs->args, hinic3_bond_valid_arguments); ++ if (kvlist == NULL) { ++ HINIC3_LOG(ERR, QOS, "kvargs parse failed!"); ++ return false; ++ } ++ ++ if (strcmp(driver_name, HINIC3_ETH_VDEV_DRV_NAME) == 0 && ++ rte_kvargs_count(kvlist, HINIC3_BOND_NAME) == 0) { ++ rte_kvargs_free(kvlist); ++ return true; ++ } ++ ++ rte_kvargs_free(kvlist); ++ return false; ++} ++ ++int hinic3_port_qos_limit_set(uint16_t port_id, uint16_t dir, uint16_t type, const struct qos_single_value *qos_value) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (qos_value->max_rate == 0) { ++ HINIC3_LOG(INFO, QOS, "remove config port_id dir %u type %u port_id %u.", dir, type, port_id); ++ } else { ++ HINIC3_LOG(INFO, QOS, "set config port_id dir %u type %u port_id %u value.", dir, type, port_id); ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_vport_limit_set, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_vport_limit_set(port_id, dir, type, qos_value->max_rate, qos_value->max_burst, ++ qos_value->min_rate, qos_value->min_burst); ++ return ret; ++} ++ ++int hinic3_port_qos_limit_get(uint16_t port_id, uint16_t dir, uint16_t type, struct qos_single_value *qos_value) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_vport_limit_get, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_vport_limit_get(port_id, dir, type, &qos_value->max_rate, &qos_value->max_burst, ++ &qos_value->min_rate, &qos_value->min_burst); ++ return ret; ++} ++ ++int hinic3_vm_qos_limit_set(uint16_t qos_id, uint16_t dir, uint16_t type, struct qos_single_value qos_value) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (qos_value.max_rate == 0) { ++ HINIC3_LOG(DEBUG, QOS, "remove config qos_id dir %u type %u qos_id %u.", dir, type, qos_id); ++ } else { ++ HINIC3_LOG(DEBUG, QOS, "set config qos_id dir %u type %u qos_id %u value.", dir, type, qos_id); ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ if (qos_value.is_RFC2697 == true) { ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_vm_srtcm_limit_set, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_vm_srtcm_limit_set(qos_id, dir, type, qos_value.min_rate, qos_value.min_burst, ++ qos_value.max_burst); ++ } else { ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_vm_limit_set, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_vm_limit_set(qos_id, dir, type, qos_value.max_rate, qos_value.max_burst, qos_value.min_rate, ++ qos_value.min_burst); ++ } ++ return ret; ++} ++ ++int hinic3_vm_qos_limit_get(uint16_t qos_id, uint16_t dir, uint16_t type, struct qos_single_value *qos_value) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (qos_value == NULL) { ++ return -1; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ if (qos_value->is_RFC2697 == true) { ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_vm_srtcm_limit_get, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_vm_srtcm_limit_get(qos_id, dir, type, &qos_value->min_rate, &qos_value->min_burst, ++ &qos_value->max_burst); ++ } else { ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_vm_limit_get, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_vm_limit_get(qos_id, dir, type, &qos_value->max_rate, &qos_value->max_burst, ++ &qos_value->min_rate, &qos_value->min_burst); ++ } ++ return ret; ++} ++ ++int hinic3_net_qos_limit_set(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t max_rate, uint64_t max_burst) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ if (max_rate == 0) { ++ HINIC3_LOG(INFO, QOS, "remove config qos_id dir %u type %u.", dir, type); ++ } else { ++ HINIC3_LOG(INFO, QOS, "set config qos_id dir %u type %u value.", dir, type); ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_net_limit_set, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_net_limit_set(0, dir, type, max_rate, max_burst); ++ return ret; ++} ++ ++int hinic3_net_qos_limit_get(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t *max_rate, uint64_t *max_burst) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_net_limit_get, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_net_limit_get(0, dir, type, max_rate, max_burst); ++ return ret; ++} ++ ++int hinic3_vf_qos_statistics_get_all_batch(uint16_t *qos_array, struct hovs_qos_stats_batch_all *stats, size_t cnt) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if ((qos_array == NULL) || (stats == NULL)) { ++ return -1; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_statistics_get_all_batch, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_statistics_get_all_batch(VM_LEVEL, qos_array, stats, cnt); ++ return ret; ++} ++ ++int hinic3_vf_qos_statistics_clear_batch(uint16_t *qos_array, size_t cnt) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ if (qos_array == NULL) { ++ return -1; ++ } ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_statistics_clear_batch, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_statistics_clear_batch(VM_LEVEL, qos_array, cnt); ++ return ret; ++} ++ ++int hinic3_vf_qos_statistics_clear(uint16_t *vport_id) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_qos_statistics_clear_batch, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_qos_statistics_clear_batch(QOS_TYPE_FUNC_LIMIT, vport_id, 1); ++ return ret; ++} ++ ++/* net级,dis参数传0 */ ++int hinic3_hqos_statistics_clear(enum qos_type_limit type, uint16_t dir, uint16_t *ids, size_t cnt) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_hqos_statistics_clear_batch, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_hqos_statistics_clear_batch(type, dir, ids, cnt); ++ return ret; ++} ++ ++int hinic3_hqos_statistics_get_all_batch(enum qos_type_limit type, uint16_t *ids, ++ struct hovs_hqos_stats_batch_all *stats, size_t cnt) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_hqos_statistics_get_all_batch, HINIC3_DRV_FUNC_NO_PTR); ++ ret = ops->hovs_hqos_statistics_get_all_batch(type, ids, stats, cnt); ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.h b/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.h +new file mode 100644 +index 0000000..408387c +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.h +@@ -0,0 +1,79 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_VF_PORT_QOS_PUBLIC_H ++#define HINIC3_VF_PORT_QOS_PUBLIC_H ++ ++#include "hinic3_util.h" ++#include "hinic3_vf_controller.h" ++#include "hinic3_mutex.h" ++#define MAX_GROUP_QOS_TYPE_LEN 64 ++ ++#define HINIC3_GROUP_QOS_BW_INGRESS "ingress_bw" ++#define HINIC3_GROUP_QOS_PPS_INGRESS "ingress_pps" ++#define HINIC3_GROUP_QOS_BW_EGRESS "egress_bw" ++#define HINIC3_GROUP_QOS_PPS_EGRESS "egress_pps" ++ ++#define VF_NONE_QOS_FLAG 0 ++#define VF_PORT_QOS_FLAG 1 ++#define VF_GROUP_QOS_FLAG 2 ++#define VF_QOS_TYPE_MAX_NUM 4 ++ ++#define ARGS_GROUP_QOS_ID_MAX_LEN 512 ++#define MAX_QOS_ID_NUM 1023 ++#define MIN_QOS_ID_NUM 1 ++ ++#define QOS_BW_TYPE 0 ++#define QOS_PPS_TYPE 1 ++ ++#define UNBIND_QOS_ID 0xffff ++#define KB_TO_B 1000 ++#define BYTE_TO_BIT 8 ++ ++#define MAX_BW_BURST_QOS 4096000UL ++#define MAX_BW_RATE_QOS 400000000UL ++#define MIN_BW_RATE_QOS 1000UL ++#define MAX_PPS_BURST_QOS 1000000UL ++#define MAX_PPS_RATE_QOS 128000000UL ++#define MIN_PPS_RATE_QOS 1000UL ++ ++enum hinic3_group_qos_type { ++ HINIC3_ARGS_GROUP_QOS_BW_INGRESS, ++ HINIC3_ARGS_GROUP_QOS_PPS_INGRESS, ++ HINIC3_ARGS_GROUP_QOS_BW_EGRESS, ++ HINIC3_ARGS_GROUP_QOS_PPS_EGRESS, ++ HINIC3_ARGS_GROUP_QOS_MAX_TYPE, ++}; ++ ++typedef struct { ++ char qos_type_key[HINIC3_ARGS_GROUP_QOS_MAX_TYPE][MAX_GROUP_QOS_TYPE_LEN]; ++} group_qos_type_key; ++ ++struct qos_single_value { ++ uint64_t max_rate; ++ uint64_t max_burst; ++ uint64_t min_rate; ++ uint64_t min_burst; ++ bool is_RFC2697; ++ int packet_mode; ++}; ++ ++group_qos_type_key *hinic3_get_qos_type_key(void); ++bool is_hinic3_vf_dev(uint16_t port_id); ++int hinic3_vm_qos_limit_set(uint16_t qos_id, uint16_t dir, uint16_t type, struct qos_single_value qos_value); ++int hinic3_vm_qos_limit_get(uint16_t qos_id, uint16_t dir, uint16_t type, struct qos_single_value *qos_value); ++int hinic3_port_qos_limit_set(uint16_t port_id, uint16_t dir, uint16_t type, const struct qos_single_value *qos_value); ++int hinic3_port_qos_limit_get(uint16_t port_id, uint16_t dir, uint16_t type, struct qos_single_value *qos_value); ++int hinic3_net_qos_limit_set(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t max_rate, uint64_t max_burst); ++int hinic3_net_qos_limit_get(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t *max_rate, uint64_t *max_burst); ++int hinic3_vf_qos_statistics_get_all_batch(uint16_t *qos_array, struct hovs_qos_stats_batch_all *stats, size_t cnt); ++int hinic3_vf_qos_statistics_clear_batch(uint16_t *qos_array, size_t cnt); ++int hinic3_hqos_statistics_clear(enum qos_type_limit type, uint16_t dir, uint16_t *ids, size_t cnt); ++int hinic3_hqos_statistics_get_all_batch(enum qos_type_limit type, uint16_t *ids, ++ struct hovs_hqos_stats_batch_all *stats, size_t cnt); ++int check_vf_bw_args(struct qos_single_value vm_qos); ++int check_vf_pps_args(struct qos_single_value vm_qos); ++int hinic3_port_mgmt_set_qos_id(uint16_t vport_id, uint16_t bucket_id); ++int hinic3_vf_qos_statistics_clear(uint16_t *vport_id); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c +new file mode 100644 +index 0000000..93dc57f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_mtr.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_qos.h" ++#ifdef HAVE_OVS_DPDK ++#include "hinic3_dpdk_adapter.h" ++#endif ++ ++struct rte_mtr_ops *g_hinic3_mtr_ops = NULL; ++ ++int hinic3_mtr_ops_get(struct rte_eth_dev *dev, void *ops) ++{ ++ if (g_hinic3_mtr_ops == NULL) { ++ g_hinic3_mtr_ops = hinic3_mtr_multi_ops_construct(); ++ } ++ ++ if (g_hinic3_mtr_ops == NULL) { ++ return -1; ++ } ++ ++ *(const struct rte_mtr_ops **)ops = g_hinic3_mtr_ops; ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.h b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.h +new file mode 100644 +index 0000000..4c076ef +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_MTR_H ++#define HINIC3_MTR_H ++ ++#define HW_MTR_STATS_N_PKTS_DROPPED (1U << 3) ++#define HW_MTR_STATS_N_BYTES_DROPPED (1U << 7) ++#define HW_MTR_INGRESS_INDEX 0 ++#define HW_MTR_EGRESS_INDEX 1 ++ ++int hinic3_mtr_ops_get(struct rte_eth_dev *dev, void *ops); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c +new file mode 100644 +index 0000000..53b11c5 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c +@@ -0,0 +1,1555 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#include "errno.h" ++#include "hinic3_log.h" ++#include "hinic3_mutex.h" ++#include "hinic3_meminfo.h" ++#include "rte_ethdev.h" ++#include "rte_mtr_driver.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_mtr.h" ++#include "hinic3_offload_action.h" ++ ++#define MAX_UINT32_NUM 0xFFFFFFFF ++#define HWOFF_PORT_TYPE_PREFIX 0xF000 ++#define HWOFF_BOND_TYPE_PREFIX 0x3000 ++ ++#define QOS_PORT_BPS (1LLU << 0) ++#define QOS_PORT_PPS (1LLU << 1) ++#define QOS_VM_BPS (1LLU << 2) ++#define QOS_VM_PPS (1LLU << 3) ++#define QOS_NET_BPS (1LLU << 4) ++#define QOS_NET_PPS (1LLU << 5) ++ ++#define QOS_LEVEL_MAX_NUM 6 ++#define QOS_CFG_FILE "/etc/dpak/net/agent_config.ini" ++ ++uint64_t g_hinic3_qos_mask_array[QOS_LEVEL_MAX_NUM] = { ++ QOS_PORT_BPS, ++ QOS_PORT_PPS, ++ QOS_VM_BPS, ++ QOS_VM_PPS, ++ QOS_NET_BPS, ++ QOS_NET_PPS, ++}; ++ ++struct hinic3_meter_list g_hinic3_meter_list = { 0 }; ++struct hinic3_net_meter_info g_hinic3_net_meter_info[HINIC3_METER_DIR_NUM] = { 0 }; ++ ++/* group 0 作为垃圾桶,如果只有端口限速,需要将端口绑定到group 0上 */ ++struct hinic3_group_info g_hinic3_group_infos[HINIC3_METER_NUM_MAX] = { 0 }; ++ ++struct hinic3_meter_list *hinic3_meter_list_get(void) ++{ ++ return &g_hinic3_meter_list; ++} ++ ++struct hinic3_group_info *hinic3_group_info_get(uint16_t group_id) ++{ ++ return &g_hinic3_group_infos[group_id]; ++} ++ ++struct hinic3_net_meter_info *hinic3_net_meter_info_get(void) ++{ ++ return g_hinic3_net_meter_info; ++} ++ ++void hinic3_meter_list_lock(void) ++{ ++ hinic3_pthread_mutex_lock(&g_hinic3_meter_list.mutex); ++} ++ ++void hinic3_meter_list_unlock(void) ++{ ++ hinic3_pthread_mutex_unlock(&g_hinic3_meter_list.mutex); ++} ++ ++void hinic3_group_info_lock(uint16_t group_id) ++{ ++ hinic3_pthread_mutex_lock(&g_hinic3_group_infos[group_id].mutex); ++} ++ ++void hinic3_group_info_unlock(uint16_t group_id) ++{ ++ hinic3_pthread_mutex_unlock(&g_hinic3_group_infos[group_id].mutex); ++} ++ ++static void hinic3_meter_mutex_all_lock(void) ++{ ++ hinic3_meter_list_lock(); ++ hinic3_mtr_policy_list_lock(); ++ hinic3_mtr_profile_list_lock(); ++} ++ ++static void hinic3_meter_mutex_all_unlock(void) ++{ ++ hinic3_mtr_profile_list_unlock(); ++ hinic3_mtr_policy_list_unlock(); ++ hinic3_meter_list_unlock(); ++} ++ ++bool hinic_is_bond_by_prefix(uint16_t vport_id) ++{ ++ return (vport_id & HWOFF_PORT_TYPE_PREFIX) == HWOFF_BOND_TYPE_PREFIX; ++} ++ ++struct hinic3_meter_node *hinic3_meter_find(uint32_t meter_id) ++{ ++ struct hinic3_meter_node *iter = NULL; ++ ++ LIST_FOR_EACH(iter, node, &g_hinic3_meter_list.node) { ++ if (iter->meter_id == meter_id) { ++ return iter; ++ } ++ } ++ return NULL; ++} ++ ++enum hinic3_qos_tablehead hinic3_get_multi_qos_show_tablehead(uint16_t dir, int packet_mode) ++{ ++ switch (dir) { ++ case HINIC3_TX_METER_QOS: ++ switch (packet_mode) { ++ case QOS_BW_TYPE: ++ return BW_TX_TYPE; ++ case QOS_PPS_TYPE: ++ return PPS_TX_TYPE; ++ default: ++ HINIC3_LOG(ERR, QOS, "Multi qos show: Wrong meter type."); ++ return QOS_TABLEHEAD_NUM; ++ } ++ case HINIC3_RX_METER_QOS: ++ switch (packet_mode) { ++ case QOS_BW_TYPE: ++ return BW_RX_TYPE; ++ case QOS_PPS_TYPE: ++ return PPS_RX_TYPE; ++ default: ++ HINIC3_LOG(ERR, QOS, "Multi qos show: Wrong meter type."); ++ return QOS_TABLEHEAD_NUM; ++ } ++ default: ++ HINIC3_LOG(ERR, QOS, "Multi qos show: Wrong meter dir."); ++ return QOS_TABLEHEAD_NUM; ++ } ++} ++ ++static void hinic3_update_profile(struct hinic3_meter_node *meter, struct hinic3_mtr_profile_node *profile) ++{ ++ if (meter->profile->used_num > 0) { ++ meter->profile->used_num--; ++ } else { ++ HINIC3_LOG(ERR, QOS, "Meter update: meter profile number error."); ++ } ++ meter->profile = profile; ++ profile->used_num++; ++} ++ ++static int hinic3_meter_profile_update(struct rte_eth_dev *dev, uint32_t meter_id, uint32_t meter_profile_id, ++ struct rte_mtr_error *error) ++{ ++ if (dev == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Meter update: Meter parameter is empty."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, "Meter parameter is empty."); ++ } ++ ++ int ret = 0; ++ uint16_t hovs_port_id; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_mtr_profile_node *profile_node = NULL; ++ ++ hinic3_mtr_profile_list_lock(); ++ profile_node = hinic3_mtr_profile_find(meter_profile_id); ++ if (profile_node == NULL) { ++ hinic3_mtr_profile_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Meter update: Profile id is not find."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, "Profile id is not find."); ++ } ++ ++ hinic3_meter_list_lock(); ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ hinic3_meter_list_unlock(); ++ hinic3_mtr_profile_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Meter update: Meter id is not find."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_MTR_ID, NULL, "Meter id is not find."); ++ } ++ hinic3_update_profile(meter, profile_node); ++ ++ switch (meter->type) { ++ case QOS_TYPE_VM_LIMIT: ++ ret = hinic3_vm_qos_limit_set(meter->group_id, meter->dir, ++ profile_node->profile.packet_mode, profile_node->profile); ++ break; ++ case QOS_TYPE_FUNC_LIMIT: ++ hovs_port_id = (uint16_t)hinic3_process_port_id(meter->port_id); ++ ret = hinic3_port_qos_limit_set(hovs_port_id, meter->dir, ++ profile_node->profile.packet_mode, &profile_node->profile); ++ break; ++ case QOS_TYPE_NET_LIMIT: ++ ret = hinic3_net_qos_limit_set(0, meter->dir, profile_node->profile.packet_mode, ++ profile_node->profile.min_rate, profile_node->profile.min_burst); ++ break; ++ default: ++ break; ++ } ++ hinic3_meter_list_unlock(); ++ hinic3_mtr_profile_list_unlock(); ++ ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Meter update: Update limit to hiovs failed."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "Dpak internal error."); ++ } ++ return 0; ++} ++ ++static void hinic3_meter_node_remove(struct hinic3_meter_node *meter) ++{ ++ if (meter->policy->used_num > 0 && meter->profile->used_num > 0) { ++ meter->policy->used_num--; ++ meter->profile->used_num--; ++ } else { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: policy or profile num error."); ++ } ++ ++ hinic3_list_remove(&meter->node); ++ hinic3_free(meter); ++ g_hinic3_meter_list.length--; ++} ++ ++static int hinic3_port_meter_remove_from_group(struct hinic3_group_port_info *port_info) ++{ ++ int ret; ++ ret = hinic3_port_mgmt_set_qos_id(port_info->vport_id, UNBIND_QOS_ID); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: Port unbind failed.port id is %u.", port_info->vport_id); ++ return -1; ++ } ++ ++ hinic3_list_remove(&port_info->node); ++ hinic3_free(port_info); ++ return 0; ++} ++ ++static int hinic3_meter_group_qos_remove(struct hinic3_meter_node *meter) ++{ ++ int ret; ++ struct hinic3_group_port_info *iter = NULL; ++ struct hinic3_group_port_info *next_iter = NULL; ++ struct qos_single_value qos_value = { 0 }; ++ struct hinic3_group_info *group_info = &g_hinic3_group_infos[meter->group_id]; ++ enum hinic3_qos_tablehead index = hinic3_get_multi_qos_show_tablehead(meter->dir, ++ meter->profile->profile.packet_mode); ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: get qos table head failed."); ++ return -1; ++ } ++ qos_value.is_RFC2697 = meter->profile->profile.is_RFC2697; ++ qos_value.packet_mode = meter->profile->profile.packet_mode; ++ hinic3_group_info_lock(meter->group_id); ++ ret = hinic3_vm_qos_limit_set(meter->group_id, meter->dir, meter->profile->profile.packet_mode, qos_value); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: delete group qos failed.\n"); ++ hinic3_group_info_unlock(meter->group_id); ++ return -1; ++ } ++ ++ group_info->meter[index].is_used = false; ++ if (group_info->meter[BW_TX_TYPE].is_used == false && group_info->meter[PPS_TX_TYPE].is_used == false && ++ group_info->meter[BW_RX_TYPE].is_used == false && group_info->meter[PPS_RX_TYPE].is_used == false) { ++ LIST_FOR_EACH_SAFE(iter, next_iter, node, &group_info->node) { ++ ret = hinic3_port_meter_remove_from_group(iter); ++ if (ret != 0) { ++ hinic3_group_info_unlock(meter->group_id); ++ return -1; ++ } ++ group_info->length--; ++ } ++ if (group_info->length != 0) { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: group info length error. group id is %u, length is %u.", ++ meter->group_id, group_info->length); ++ group_info->length = 0; ++ } ++ } ++ ++ hinic3_group_info_unlock(meter->group_id); ++ hinic3_meter_node_remove(meter); ++ return 0; ++} ++ ++static int hinic3_meter_net_qos_remove(struct hinic3_meter_node *meter) ++{ ++ int ret; ++ enum hinic3_qos_tablehead index = hinic3_get_multi_qos_show_tablehead(meter->dir, ++ meter->profile->profile.packet_mode); ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: get qos table head failed."); ++ return -1; ++ } ++ ++ ret = hinic3_net_qos_limit_set(0, meter->dir, meter->profile->profile.packet_mode, 0, 0); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: delete net qos failed."); ++ return -1; ++ } ++ g_hinic3_net_meter_info[index].is_used = false; ++ hinic3_meter_node_remove(meter); ++ return 0; ++} ++ ++static int hinic3_vm_qos_clear(struct hinic3_vf_dev *vf_dev, enum hinic3_qos_tablehead index) ++{ ++ int ret; ++ ++ vf_dev->mtr[index].is_used = false; ++ /* 没有配置VM QOS,不需要清理 */ ++ if (vf_dev->group_qos_id == 0) { ++ return 0; ++ } ++ ++ if (vf_dev->mtr[BW_TX_TYPE].is_used == false && vf_dev->mtr[PPS_TX_TYPE].is_used == false && ++ vf_dev->mtr[BW_RX_TYPE].is_used == false && vf_dev->mtr[PPS_RX_TYPE].is_used == false) { ++ vf_dev->qos_type = VF_NONE_QOS_FLAG; ++ ret = hinic3_group_meter_remove(vf_dev->vport_id, vf_dev->group_qos_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi delete: remove group qos failed."); ++ return -1; ++ } ++ vf_dev->group_qos_id = 0; ++ } ++ return 0; ++} ++ ++static int hinic3_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id, struct rte_mtr_error *error) ++{ ++ if (dev == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Meter destroy: Meter parameter is empty."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, ++ "Meter parameter is empty."); ++ } ++ ++ int ret = 0; ++ struct hinic3_meter_node *meter = NULL; ++ ++ hinic3_meter_list_lock(); ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ hinic3_meter_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Meter destroy: Meter id is not find."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_MTR_ID, NULL, ++ "Meter id is not find."); ++ } ++ ++ switch (meter->type) { ++ case QOS_TYPE_MAX: ++ hinic3_meter_node_remove(meter); ++ break; ++ case QOS_TYPE_VM_LIMIT: ++ ret = hinic3_meter_group_qos_remove(meter); ++ break; ++ case QOS_TYPE_FUNC_LIMIT: ++ HINIC3_LOG(ERR, QOS, "Meter destroy: Meter id is bind port."); ++ ret = -1; ++ break; ++ case QOS_TYPE_NET_LIMIT: ++ ret = hinic3_meter_net_qos_remove(meter); ++ break; ++ default: ++ break; ++ } ++ ++ hinic3_meter_list_unlock(); ++ if (ret != 0) { ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Dpak internal error."); ++ } ++ return 0; ++} ++ ++static int hinic3_get_meter_info(struct rte_mtr_params *params, struct hinic3_meter_node *meter) ++{ ++ struct hinic3_mtr_policy_node *policy = NULL; ++ struct hinic3_mtr_profile_node *profile = NULL; ++ uint32_t policy_id = params->meter_policy_id; ++ uint32_t profile_id = params->meter_profile_id; ++ ++ policy = hinic3_mtr_policy_find(policy_id); ++ if (policy == NULL) { ++ HINIC3_LOG(ERR, QOS, "Meter add: Meter policy id is not find."); ++ return -RTE_MTR_ERROR_TYPE_METER_POLICY_ID; ++ } ++ meter->policy = policy; ++ ++ profile = hinic3_mtr_profile_find(profile_id); ++ if (profile == NULL) { ++ HINIC3_LOG(ERR, QOS, "Meter add: Meter profile id is not find."); ++ return -RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; ++ } ++ meter->profile = profile; ++ return 0; ++} ++ ++static void hinic3_meter_conf_set(struct hinic3_meter_node *meter, uint32_t meter_id) ++{ ++ meter->profile->used_num++; ++ meter->policy->used_num++; ++ meter->type = QOS_TYPE_MAX; ++ meter->group_id = 0; ++ meter->flow = NULL; ++ meter->meter_id = meter_id; ++ meter->dir = HINIC3_NODIR_METER_QOS; ++ g_hinic3_meter_list.length++; ++} ++ ++static int hinic3_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, struct rte_mtr_params *params, ++ int shared, struct rte_mtr_error *error) ++{ ++ if (dev == NULL || params == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Meter add: Meter parameter is empty."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, ++ "Meter parameter is empty."); ++ } ++ ++ int ret; ++ struct hinic3_meter_node *meter = NULL; ++ ++ hinic3_meter_mutex_all_lock(); ++ meter = hinic3_meter_find(meter_id); ++ if (meter != NULL) { ++ hinic3_meter_mutex_all_unlock(); ++ HINIC3_LOG(ERR, QOS, "Meter add: Meter id is exist."); ++ return -rte_mtr_error_set(error, EEXIST, RTE_MTR_ERROR_TYPE_MTR_ID, NULL, ++ "Meter id is exist."); ++ } ++ ++ meter = hinic3_calloc(1, sizeof(struct hinic3_meter_node), HINIC3_QOS); ++ if (meter == NULL) { ++ hinic3_meter_mutex_all_unlock(); ++ HINIC3_LOG(ERR, QOS, "Meter add: Meter memory alloc failed."); ++ return -rte_mtr_error_set(error, ENOMEM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Meter memory alloc failed."); ++ } ++ ++ ret = hinic3_get_meter_info(params, meter); ++ switch (ret) { ++ case -RTE_MTR_ERROR_TYPE_METER_POLICY_ID: ++ hinic3_free(meter); ++ hinic3_meter_mutex_all_unlock(); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, ++ "Meter add: Meter policy id is not find."); ++ case -RTE_MTR_ERROR_TYPE_METER_PROFILE_ID: ++ hinic3_free(meter); ++ hinic3_meter_mutex_all_unlock(); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, ++ "Meter add: Meter profile id is not find."); ++ default: ++ break; ++ } ++ ++ hinic3_list_init(&meter->node); ++ hinic3_meter_conf_set(meter, meter_id); ++ hinic3_list_insert(&g_hinic3_meter_list.node, &meter->node); ++ hinic3_meter_mutex_all_unlock(); ++ return 0; ++} ++ ++static int hinic3_get_qos_stats(uint16_t ids, enum hinic3_meter_qos_direction dir, struct rte_mtr_stats *stats, ++ enum qos_type_limit type, int clear) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ struct hovs_hqos_stats_batch_all hovs_stats = { 0 }; ++ ++ ops = hinic3_get_drv_ops(); ++ if (ops == NULL || ops->hovs_hqos_statistics_get_all_batch == NULL) { ++ HINIC3_LOG(ERR, QOS, "Get ops hovs_qos_statistics_get_all_batch is NULL.\n"); ++ return -1; ++ } ++ ++ ret = ops->hovs_hqos_statistics_get_all_batch(type, &ids, &hovs_stats, 1); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Get %d qos statistics failed. ret = %d, ids = %u.\n", type, ret, ids); ++ return -1; ++ } ++ ++ if (dir == HINIC3_TX_METER_QOS) { ++ stats->n_pkts[RTE_COLOR_GREEN] = hovs_stats.tx_pkts[RTE_COLOR_GREEN]; ++ stats->n_bytes[RTE_COLOR_GREEN] = hovs_stats.tx_bytes[RTE_COLOR_GREEN]; ++ stats->n_bytes_dropped = hovs_stats.tx_drop_bytes; ++ stats->n_pkts_dropped = hovs_stats.tx_drop_pkts; ++ } else { ++ stats->n_pkts[RTE_COLOR_GREEN] = hovs_stats.rx_pkts[RTE_COLOR_GREEN]; ++ stats->n_bytes[RTE_COLOR_GREEN] = hovs_stats.rx_bytes[RTE_COLOR_GREEN]; ++ stats->n_bytes_dropped = hovs_stats.rx_drop_bytes; ++ stats->n_pkts_dropped = hovs_stats.rx_drop_pkts; ++ } ++ ++ if (clear != 0) { ++ ret = hinic3_hqos_statistics_clear(type, dir, &ids, 1); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Clear %d qos statistics failed. ret = %d, ids = %u.\n", type, ret, ids); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int hinic3_get_meter_stats(struct hinic3_meter_node *meter, struct rte_mtr_stats *stats, int clear) ++{ ++ int ret; ++ uint16_t vport_id; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ ++ switch (meter->type) { ++ case QOS_TYPE_VM_LIMIT: ++ ret = hinic3_get_qos_stats(meter->group_id, meter->dir, stats, QOS_TYPE_VM_LIMIT, clear); ++ break; ++ case QOS_TYPE_FUNC_LIMIT: ++ vf_dev = hinic3_get_private_data(meter->port_id); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, QOS, "The current device private_data is NULL.\n"); ++ return -1; ++ } ++ vport_id = vf_dev->vport_id; ++ ret = hinic3_get_qos_stats(vport_id, meter->dir, stats, QOS_TYPE_FUNC_LIMIT, clear); ++ break; ++ case QOS_TYPE_NET_LIMIT: ++ ret = hinic3_get_qos_stats(0, meter->dir, stats, QOS_TYPE_NET_LIMIT, clear); ++ break; ++ default: ++ ret = -1; ++ HINIC3_LOG(ERR, QOS, "Meter type is error.\n"); ++ break; ++ } ++ if (ret != 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int hinic3_meter_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id, struct rte_mtr_stats *stats, ++ uint64_t *stats_mask, int clear, struct rte_mtr_error *error) ++{ ++ int ret; ++ struct hinic3_meter_node *meter = NULL; ++ ++ if (eth_dev == NULL || stats == NULL || stats_mask == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi meter stats read parameter is empty."); ++ return rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Meter stats read parameter is empty."); ++ } ++ ++ meter = hinic3_meter_find(mtr_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Meter id is not find.\n"); ++ return -rte_mtr_error_set(error, EEXIST, RTE_MTR_ERROR_TYPE_MTR_ID, NULL, ++ "Meter id is not find."); ++ } ++ ++ if (meter->type == QOS_TYPE_MAX) { ++ HINIC3_LOG(ERR, QOS, "Meter is not bind port.\n"); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_MTR_ID, NULL, ++ "Meter is not bind port."); ++ } ++ ++ ret = hinic3_get_meter_stats(meter, stats, clear); ++ if (ret != 0) { ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Dpak internal error."); ++ } ++ *stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED | RTE_MTR_STATS_N_PKTS_DROPPED | ++ RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_BYTES_GREEN; ++ return 0; ++} ++ ++static int hinic3_meter_actions_parse(const struct rte_flow_action *actions, uint32_t *meter_id, ++ enum hinic3_meter_qos_direction *direction, uint16_t *port_id) ++{ ++ const struct rte_flow_action *act = next_no_void_action(actions, NULL); ++ ++ while (act && act->type != RTE_FLOW_ACTION_TYPE_END) { ++ if (act->conf == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: rte_flow_action->conf is null."); ++ return -1; ++ } ++ switch (act->type) { ++ case RTE_FLOW_ACTION_TYPE_METER: ++ *meter_id = ((struct rte_flow_action_meter*)act->conf)->mtr_id; ++ break; ++ case RTE_FLOW_ACTION_TYPE_PORT_ID: ++ *direction = HINIC3_RX_METER_QOS; ++ *port_id = ((struct rte_flow_action_port_id*)act->conf)->id; ++ break; ++ default: ++ break; ++ } ++ act = next_no_void_action(actions, act); ++ } ++ return 0; ++} ++ ++static int hinic3_meter_pattern_parse(const struct rte_flow_item *pattern, uint16_t *port_id) ++{ ++ const struct rte_flow_item *item = next_no_end_pattern(pattern, NULL); ++ ++ while (item) { ++ if (item->spec == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: rte_flow_item->spec is null."); ++ return -1; ++ } ++ switch (item->type) { ++ case RTE_FLOW_ITEM_TYPE_PORT_ID: ++ *port_id = ((struct rte_flow_item_port_id*)item->spec)->id; ++ break; ++ default: ++ break; ++ } ++ item = next_no_end_pattern(pattern, item); ++ } ++ return 0; ++} ++ ++static int hinic3_add_port_to_list(uint16_t vport_id, struct hinic3_meter_node *meter) ++{ ++ int ret; ++ struct hinic3_group_port_info *port_info = NULL; ++ ++ if (g_hinic3_group_infos[meter->group_id].length > HINIC3_METER_PORT_NUM_MAX) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: Group port number reached the upper limit. group id is %u.", ++ meter->group_id); ++ return -1; ++ } ++ ++ ret = hinic3_port_mgmt_set_qos_id(vport_id, meter->group_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: Failed to bind the port to the group qos, vport_id is %u.", vport_id); ++ return -1; ++ } ++ ++ port_info = hinic3_calloc(1, sizeof(struct hinic3_group_port_info), HINIC3_QOS); ++ if (port_info == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: Group port info alloc failed."); ++ return -1; ++ } ++ ++ port_info->vport_id = vport_id; ++ hinic3_list_init(&port_info->node); ++ hinic3_list_insert(&g_hinic3_group_infos[meter->group_id].node, &port_info->node); ++ g_hinic3_group_infos[meter->group_id].length++; ++ return 0; ++} ++ ++static uint16_t hinic3_meter_group_find_location() ++{ ++ int i; ++ for (i = 1; i < HINIC3_METER_NUM_MAX; i++) { ++ if (g_hinic3_group_infos[i].length == 0) { ++ return i; ++ } ++ } ++ return 0; ++} ++ ++static int hinic3_qos_set_to_hovs(enum qos_type_limit qos_type, uint16_t ids, enum hinic3_meter_qos_direction dir, ++ struct hinic3_mtr_profile_node *profile_node) ++{ ++ int ret; ++ ++ /* 下发限速前,先清理计数器 */ ++ ret = hinic3_hqos_statistics_clear(qos_type, dir, &ids, 1); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: Failed to clear qos statistics. ids is %u. qos_type is %d. ret is %d.", ++ ids, qos_type, ret); ++ return -1; ++ } ++ ++ switch (qos_type) { ++ case QOS_TYPE_FUNC_LIMIT: ++ ret = hinic3_port_qos_limit_set(ids, dir, profile_node->profile.packet_mode, &profile_node->profile); ++ break; ++ case QOS_TYPE_VM_LIMIT: ++ ret = hinic3_vm_qos_limit_set(ids, dir, profile_node->profile.packet_mode, profile_node->profile); ++ break; ++ case QOS_TYPE_NET_LIMIT: ++ /* 目前net级只支持单速单桶,忽略PIR(max_rate)和PBS(max_burst),传入cir(min_rate)和cbs(min_burst) */ ++ ret = hinic3_net_qos_limit_set(ids, dir, profile_node->profile.packet_mode, ++ profile_node->profile.min_rate, profile_node->profile.min_burst); ++ break; ++ default: ++ break; ++ } ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: set qos failed. ids is %u, qos type is %d.", ids, qos_type); ++ return -1; ++ } ++ return 0; ++} ++ ++static int hinic3_add_group_to_hovs(struct hinic3_vf_dev *vf_dev, struct hinic3_meter_node *meter, ++ enum hinic3_qos_tablehead index, enum hinic3_meter_qos_direction dir) ++{ ++ int ret = 0; ++ struct hinic3_mtr_profile_node *profile_node = NULL; ++ ++ if (vf_dev->group_qos_id > 0 && g_hinic3_group_infos[vf_dev->group_qos_id].meter[index].is_used == false) { ++ /* 如果vf_dev已经绑定group,且group的dir方向没有限速,则正常下发group限速 */ ++ meter->group_id = vf_dev->group_qos_id; ++ hinic3_group_info_lock(meter->group_id); ++ } else if (vf_dev->group_qos_id > 0 && g_hinic3_group_infos[vf_dev->group_qos_id].meter[index].is_used == true) { ++ /* 如果vf_dev已经绑定group,且group的dir方向已经有限速,则返回失败 */ ++ HINIC3_LOG(ERR, QOS, "Multi qos: Group %u index %d is already set meter %u, Please delete or update.", ++ vf_dev->group_qos_id, index, meter->meter_id); ++ return -1; ++ } else { ++ /* 如果vf_dev没有绑定group,则新分配一个group_id,并把端口绑定在group中 */ ++ meter->group_id = hinic3_meter_group_find_location(); ++ if (meter->group_id == 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: Group number reached the upper limit."); ++ return -1; ++ } ++ hinic3_group_info_lock(meter->group_id); ++ ret = hinic3_add_port_to_list(vf_dev->vport_id, meter); ++ if (ret != 0) { ++ hinic3_group_info_unlock(meter->group_id); ++ return -1; ++ } ++ } ++ ++ profile_node = meter->profile; ++ ++ ret = hinic3_qos_set_to_hovs(QOS_TYPE_VM_LIMIT, meter->group_id, dir, profile_node); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ vf_dev->group_qos_id = meter->group_id; ++ meter->type = QOS_TYPE_VM_LIMIT; ++ meter->dir = dir; ++ g_hinic3_group_infos[meter->group_id].meter[index].meter_id = meter->meter_id; ++ g_hinic3_group_infos[meter->group_id].meter[index].is_used = true; ++ hinic3_group_info_unlock(meter->group_id); ++ return 0; ++} ++ ++static int hinic3_get_packet_mode(enum hinic3_qos_tablehead index) ++{ ++ switch (g_hinic3_qos_mask_array[index]) { ++ case QOS_PORT_BPS: ++ case QOS_VM_BPS: ++ case QOS_NET_BPS: ++ return QOS_BW_TYPE; ++ case QOS_PORT_PPS: ++ case QOS_VM_PPS: ++ case QOS_NET_PPS: ++ return QOS_PPS_TYPE; ++ default: ++ return -1; ++ } ++} ++ ++static int hinic3_group_meter_clear(uint32_t meter_id, uint16_t group_id) ++{ ++ int ret; ++ struct hinic3_meter_node *meter = NULL; ++ struct qos_single_value qos_value = {0}; ++ ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Meter clear id is not find.\n"); ++ return -1; ++ } ++ qos_value.is_RFC2697 = meter->profile->profile.is_RFC2697; ++ qos_value.packet_mode = meter->profile->profile.packet_mode; ++ ret = hinic3_vm_qos_limit_set(group_id, meter->dir, meter->profile->profile.packet_mode, qos_value); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Group meter del failed.\n"); ++ return -1; ++ } ++ meter->type = QOS_TYPE_MAX; ++ meter->group_id = 0; ++ meter->dir = HINIC3_NODIR_METER_QOS; ++ return 0; ++} ++ ++static int hinic3_group_meter_remove_sub(struct hinic3_group_info *group_info, uint16_t group_id, int index) ++{ ++ int ret; ++ ++ if (group_info->meter[index].is_used == true) { ++ ret = hinic3_group_meter_clear(group_info->meter[index].meter_id, group_id); ++ if (ret != 0) { ++ return -1; ++ } ++ group_info->meter[index].is_used = false; ++ } ++ return 0; ++} ++ ++int hinic3_group_meter_remove(uint16_t vport_id, uint16_t group_id) ++{ ++ int ret = 0; ++ struct hinic3_group_port_info *iter = NULL; ++ struct hinic3_group_port_info *next_iter = NULL; ++ struct hinic3_group_info *group_info = &g_hinic3_group_infos[group_id]; ++ ++ hinic3_group_info_lock(group_id); ++ LIST_FOR_EACH_SAFE(iter, next_iter, node, &group_info->node) { ++ if (iter->vport_id == vport_id) { ++ ret = hinic3_port_meter_remove_from_group(iter); ++ if (ret != 0) { ++ hinic3_group_info_unlock(group_id); ++ return -1; ++ } ++ group_info->length--; ++ } ++ } ++ if (group_info->length == 0) { ++ for (int i = 0; i < HINIC3_METER_DIR_NUM; i++) { ++ ret = hinic3_group_meter_remove_sub(group_info, group_id, i); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Meter clear failed. group id is %u, index is %d.", group_id, i); ++ } ++ } ++ } ++ hinic3_group_info_unlock(group_id); ++ return ret; ++} ++ ++static int hinic3_add_port_to_group(struct hinic3_vf_dev *vf_dev, struct hinic3_meter_node *meter, ++ enum hinic3_meter_qos_direction dir) ++{ ++ int ret; ++ if (vf_dev->group_qos_id > 0 && vf_dev->group_qos_id != meter->group_id) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: dev and meter is already bind group, please update or delete."); ++ return -1; ++ } else if (vf_dev->group_qos_id > 0 && vf_dev->group_qos_id == meter->group_id) { ++ /* 端口已经绑定在group中,直接返回 */ ++ return 0; ++ } ++ ++ if (dir != meter->dir) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: dir error, meter_id is %u, vport_id is %u, dir is %d", meter->meter_id, ++ vf_dev->vport_id, dir); ++ return -1; ++ } ++ hinic3_group_info_lock(meter->group_id); ++ ret = hinic3_add_port_to_list(vf_dev->vport_id, meter); ++ if (ret != 0) { ++ return -1; ++ } ++ vf_dev->group_qos_id = meter->group_id; ++ hinic3_group_info_unlock(meter->group_id); ++ return 0; ++} ++ ++static int hinic3_update_net_qos(enum hinic3_qos_tablehead index) ++{ ++ struct hinic3_meter_node *meter = NULL; ++ ++ meter = hinic3_meter_find(g_hinic3_net_meter_info[index].meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Muli qos: update net qos failed, meter id is %u.", ++ g_hinic3_net_meter_info[index].meter_id); ++ return -1; ++ } ++ meter->type = QOS_TYPE_MAX; ++ ++ return 0; ++} ++ ++static int hinic3_remove_port_qos(uint32_t meter_id, uint16_t vport_id) ++{ ++ int ret; ++ struct hinic3_meter_node *meter = NULL; ++ struct qos_single_value qos_value = { 0 }; ++ ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi meter: meter id is not find. meter id is %u.", meter_id); ++ return -1; ++ } ++ ++ if (meter->type != QOS_TYPE_FUNC_LIMIT) { ++ HINIC3_LOG(ERR, QOS, "Multi meter: meter type error."); ++ } ++ ++ ret = hinic3_port_qos_limit_set(vport_id, meter->dir, meter->profile->profile.packet_mode, &qos_value); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi delete: remove port tx qos failed."); ++ } ++ meter->type = QOS_TYPE_MAX; ++ hinic3_free(meter->flow); ++ meter->flow = NULL; ++ return 0; ++} ++ ++void hinic3_port_meter_clear(struct hinic3_vf_dev *vf_dev, uint16_t vport_id) ++{ ++ int ret = 0; ++ for (int i = 0; i < QOS_TABLEHEAD_NUM; i++) { ++ if (vf_dev->mtr[i].is_used == true) { ++ if (hinic3_remove_port_qos(vf_dev->mtr[i].mtr_id, vport_id) != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: remove port qos failed. vport id is %u, index is %d.", ++ vport_id, i); ++ } ++ } ++ } ++ ++ ret = hinic3_vf_qos_statistics_clear(&vf_dev->vport_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: group port statistics not clear. vport id is %u", vf_dev->vport_id); ++ } ++} ++ ++static void hinic3_qos_port_clear(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_qos_direction dir, uint64_t *qos_mask) ++{ ++ int ret; ++ enum hinic3_qos_tablehead index; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_mtr_profile_node profile_node = { 0 }; ++ ++ if ((*qos_mask & QOS_PORT_BPS) != 0) { ++ *qos_mask &= ~QOS_PORT_BPS; ++ index = hinic3_get_multi_qos_show_tablehead(dir, QOS_BW_TYPE); ++ } else { ++ *qos_mask &= ~QOS_PORT_PPS; ++ index = hinic3_get_multi_qos_show_tablehead(dir, QOS_PPS_TYPE); ++ } ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: get qos index fail."); ++ return; ++ } ++ ++ meter = hinic3_meter_find(vf_dev->mtr[index].mtr_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: meter not find. meter id is %u.", vf_dev->mtr[index].mtr_id); ++ return; ++ } ++ profile_node.profile.packet_mode = meter->profile->profile.packet_mode; ++ ++ ret = hinic3_qos_set_to_hovs(QOS_TYPE_FUNC_LIMIT, vf_dev->vport_id, dir, &profile_node); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: clear port qos fail. vport id is %u.", vf_dev->vport_id); ++ return; ++ } ++ ++ meter->type = QOS_TYPE_MAX; ++ meter->dir = HINIC3_NODIR_METER_QOS; ++ vf_dev->mtr[index].is_used = false; ++ vf_dev->qos_type = VF_NONE_QOS_FLAG; ++} ++ ++static void hinic3_qos_vm_clear_sub(struct hinic3_group_info *group_info, struct hinic3_meter_node *meter, ++ enum hinic3_qos_tablehead index, uint16_t vport_id) ++{ ++ int ret = 0; ++ struct hinic3_group_port_info *iter = NULL; ++ struct hinic3_group_port_info *next_iter = NULL; ++ ++ /* 如果端口在group中且唯一,则清除相应方向的group限速 */ ++ hinic3_group_info_lock(group_info->group_id); ++ LIST_FOR_EACH_SAFE(iter, next_iter, node, &group_info->node) { ++ if (iter->vport_id == vport_id && group_info->length == 1) { ++ ret = hinic3_group_meter_clear(meter->meter_id, group_info->group_id); ++ group_info->meter[index].is_used = false; ++ } ++ } ++ ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: clear group qos fail. group id is %u.", group_info->group_id); ++ } ++ ++ hinic3_group_info_unlock(group_info->group_id); ++} ++ ++static void hinic3_qos_vm_clear(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_qos_direction dir, uint64_t *qos_mask) ++{ ++ int ret; ++ bool is_unbind = true; ++ enum hinic3_qos_tablehead index; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_group_info *group_info = NULL; ++ ++ if ((*qos_mask & QOS_VM_BPS) != 0) { ++ *qos_mask &= ~QOS_VM_BPS; ++ index = hinic3_get_multi_qos_show_tablehead(dir, QOS_BW_TYPE); ++ } else { ++ *qos_mask &= ~QOS_VM_PPS; ++ index = hinic3_get_multi_qos_show_tablehead(dir, QOS_PPS_TYPE); ++ } ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: get qos index fail."); ++ return; ++ } ++ ++ if (vf_dev->group_qos_id == 0 || g_hinic3_group_infos[vf_dev->group_qos_id].meter[index].is_used == false) { ++ return; ++ } ++ ++ group_info = &g_hinic3_group_infos[vf_dev->group_qos_id]; ++ meter = hinic3_meter_find(group_info->meter[index].meter_id); ++ if (meter == NULL) { ++ return; ++ } ++ ++ if (meter->type != QOS_TYPE_VM_LIMIT) { ++ return; ++ } ++ ++ /* 如果group中还用别的模式、别的方向的限速,则不能将端口移除group */ ++ for (int i = 0; i < HINIC3_METER_DIR_NUM; i++) { ++ if (i != index && group_info->meter[i].is_used == true) { ++ is_unbind = false; ++ } ++ } ++ ++ if (is_unbind == true) { ++ ret = hinic3_group_meter_remove(vf_dev->vport_id, vf_dev->group_qos_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: remove port qos fail. vport id is %u. group id is %u.", ++ vf_dev->vport_id, vf_dev->group_qos_id); ++ return; ++ } ++ vf_dev->group_qos_id = 0; ++ meter->type = QOS_TYPE_MAX; ++ meter->dir = HINIC3_NODIR_METER_QOS; ++ } else { ++ hinic3_qos_vm_clear_sub(group_info, meter, index, vf_dev->vport_id); ++ } ++} ++ ++static void hinic3_qos_net_clear(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_qos_direction dir, uint64_t *qos_mask) ++{ ++ int ret; ++ enum hinic3_qos_tablehead index; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_mtr_profile_node profile_node = { 0 }; ++ ++ if ((*qos_mask & QOS_NET_BPS) != 0) { ++ *qos_mask &= ~QOS_NET_BPS; ++ index = hinic3_get_multi_qos_show_tablehead(dir, QOS_BW_TYPE); ++ } else { ++ *qos_mask &= ~QOS_NET_PPS; ++ index = hinic3_get_multi_qos_show_tablehead(dir, QOS_PPS_TYPE); ++ } ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: get qos index fail."); ++ return; ++ } ++ ++ meter = hinic3_meter_find(g_hinic3_net_meter_info[index].meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: meter not find. meter id is %u.", g_hinic3_net_meter_info[index].meter_id); ++ return; ++ } ++ if (meter->type != QOS_TYPE_NET_LIMIT) { ++ HINIC3_LOG(WARNING, QOS, "Multi qos: net qos meter type is %d.", meter->type); ++ } ++ profile_node.profile.packet_mode = meter->profile->profile.packet_mode; ++ ++ ret = hinic3_qos_set_to_hovs(QOS_TYPE_NET_LIMIT, 0, dir, &profile_node); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: clear net qos fail. ret is %d. dir is %d. packet_mode is %d.", ++ ret, dir, profile_node.profile.packet_mode); ++ return; ++ } ++ ++ g_hinic3_net_meter_info[index].is_used = false; ++ meter->type = QOS_TYPE_MAX; ++ meter->dir = HINIC3_NODIR_METER_QOS; ++} ++ ++static struct hinic3_clear_qos_func_map g_hinic3_clear_qos_func_array[] = { ++ {hinic3_qos_port_clear}, ++ {hinic3_qos_port_clear}, ++ {hinic3_qos_vm_clear}, ++ {hinic3_qos_vm_clear}, ++ {hinic3_qos_net_clear}, ++ {hinic3_qos_net_clear}, ++}; ++ ++static void hinic3_clear_qos(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_qos_direction dir, uint64_t *qos_mask) ++{ ++ for (int i = 0; i < QOS_LEVEL_MAX_NUM; i++) { ++ if ((*qos_mask & g_hinic3_qos_mask_array[i]) != 0) { ++ g_hinic3_clear_qos_func_array[i].func(vf_dev, dir, qos_mask); ++ } ++ } ++} ++ ++static void hinic3_set_next_meter(struct hinic3_mtr_policy_node *policy, uint32_t *next_meter_id) ++{ ++ if (policy->has_next_meter == true) { ++ *next_meter_id = policy->next_meter_id; ++ } else { ++ *next_meter_id = MAX_UINT32_NUM; ++ } ++} ++ ++static int hinic3_qos_port_set(uint16_t port_id, uint32_t meter_id, uint32_t *next_meter_id, ++ enum hinic3_meter_qos_direction dir) ++{ ++ int ret; ++ enum hinic3_qos_tablehead index; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_mtr_profile_node *profile_node = NULL; ++ struct hinic3_vf_dev *vf_dev = (struct hinic3_vf_dev*)hinic3_get_private_data(port_id); ++ ++ meter = hinic3_meter_find(meter_id); ++ if (meter->type != QOS_TYPE_MAX) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: meter type is not right. meter id is %u.", meter_id); ++ return -1; ++ } ++ profile_node = meter->profile; ++ ++ index = hinic3_get_multi_qos_show_tablehead(dir, profile_node->profile.packet_mode); ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: get qos index fail. dir is %d. packet mode is %d.", ++ dir, profile_node->profile.packet_mode); ++ return -1; ++ } ++ ++ if (vf_dev->mtr[index].is_used == true) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: port %u already qos, meter id is %u.", vf_dev->vport_id, ++ vf_dev->mtr[index].mtr_id); ++ return -1; ++ } ++ ++ ret = hinic3_qos_set_to_hovs(QOS_TYPE_FUNC_LIMIT, vf_dev->vport_id, dir, profile_node); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ vf_dev->qos_type = VF_PORT_QOS_FLAG; ++ vf_dev->mtr[index].direction = dir; ++ vf_dev->mtr[index].is_used = true; ++ vf_dev->mtr[index].mtr_id = meter_id; ++ meter->dir = dir; ++ meter->type = QOS_TYPE_FUNC_LIMIT; ++ meter->port_id = port_id; ++ hinic3_set_next_meter(meter->policy, next_meter_id); ++ ++ return 0; ++} ++ ++static int hinic3_qos_vm_set(uint16_t port_id, uint32_t meter_id, uint32_t *next_meter_id, ++ enum hinic3_meter_qos_direction dir) ++{ ++ int ret = -1; ++ enum hinic3_qos_tablehead index; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_mtr_profile_node *profile_node = NULL; ++ struct hinic3_vf_dev *vf_dev = (struct hinic3_vf_dev*)hinic3_get_private_data(port_id); ++ ++ meter = hinic3_meter_find(meter_id); ++ profile_node = meter->profile; ++ ++ index = hinic3_get_multi_qos_show_tablehead(dir, profile_node->profile.packet_mode); ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: get qos index fail. dir is %d. packet mode is %d.", ++ dir, profile_node->profile.packet_mode); ++ return -1; ++ } ++ ++ switch (meter->type) { ++ case QOS_TYPE_MAX: ++ ret = hinic3_add_group_to_hovs(vf_dev, meter, index, dir); ++ break; ++ case QOS_TYPE_VM_LIMIT: ++ ret = hinic3_add_port_to_group(vf_dev, meter, dir); ++ break; ++ case QOS_TYPE_FUNC_LIMIT: ++ HINIC3_LOG(ERR, QOS, "Multi qos: group meter id is already used. meter id is %u", meter->meter_id); ++ break; ++ default: ++ break; ++ } ++ hinic3_set_next_meter(meter->policy, next_meter_id); ++ ++ return ret; ++} ++ ++static int hinic3_qos_net_set(uint16_t port_id, uint32_t meter_id, uint32_t *next_meter_id, ++ enum hinic3_meter_qos_direction dir) ++{ ++ int ret = -1; ++ enum hinic3_qos_tablehead index; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_mtr_profile_node *profile_node = NULL; ++ ++ meter = hinic3_meter_find(meter_id); ++ profile_node = meter->profile; ++ ++ index = hinic3_get_multi_qos_show_tablehead(dir, profile_node->profile.packet_mode); ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: get qos index fail. dir is %d. packet mode is %d.", ++ dir, profile_node->profile.packet_mode); ++ return -1; ++ } ++ ++ if (meter->type == QOS_TYPE_NET_LIMIT && g_hinic3_net_meter_info[index].is_used == true && ++ g_hinic3_net_meter_info[index].meter_id == meter_id) { ++ goto end; ++ } else if (meter->type != QOS_TYPE_MAX) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: net meter id already used."); ++ return -1; ++ } ++ ++ ret = hinic3_qos_set_to_hovs(QOS_TYPE_NET_LIMIT, 0, dir, profile_node); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ if (g_hinic3_net_meter_info[index].is_used == true) { ++ ret = hinic3_update_net_qos(index); ++ if (ret != 0) { ++ return -1; ++ } ++ } ++ g_hinic3_net_meter_info[index].meter_id = meter_id; ++ g_hinic3_net_meter_info[index].is_used = true; ++ meter->dir = dir; ++ meter->type = QOS_TYPE_NET_LIMIT; ++end: ++ hinic3_set_next_meter(meter->policy, next_meter_id); ++ return 0; ++} ++ ++static struct hinic3_qos_func_map g_hinic3_qos_func_array[] = { ++ {"port_bps", hinic3_qos_port_set}, ++ {"port_pps", hinic3_qos_port_set}, ++ {"vm_bps", hinic3_qos_vm_set}, ++ {"vm_pps", hinic3_qos_vm_set}, ++ {"net_bps", hinic3_qos_net_set}, ++ {"net_pps", hinic3_qos_net_set}, ++}; ++ ++static bool hinic3_check_qos_level(uint64_t *qos_mask, int index, uint32_t meter_id, int *ret) ++{ ++ int packet_mode; ++ struct hinic3_meter_node *meter = NULL; ++ ++ if (((*qos_mask) & g_hinic3_qos_mask_array[index]) == g_hinic3_qos_mask_array[index]) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: qos level repeat. Please check configuration."); ++ *ret = -1; ++ return false; ++ } ++ meter = hinic3_meter_find(meter_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: meter not find. meter id is %u.", meter_id); ++ *ret = -1; ++ return false; ++ } ++ packet_mode = hinic3_get_packet_mode(index); ++ if (packet_mode < 0 || packet_mode != meter->profile->profile.packet_mode) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: packet mode wroing. qos level is %d. packet mode is %d. meter id is %u.", ++ index, packet_mode, meter_id); ++ *ret = -1; ++ return false; ++ } ++ *qos_mask |= g_hinic3_qos_mask_array[index]; ++ *ret = 0; ++ return true; ++} ++ ++static int hinic3_set_qos_to_hovs(char *qos_level, uint16_t port_id, uint32_t meter_id, ++ enum hinic3_meter_qos_direction dir) ++{ ++ int ret = 0; ++ bool flag = false; ++ char *token = NULL; ++ char delimiter = ','; ++ char *qos_level_str = NULL; ++ uint32_t next_meter_id = 0; ++ uint32_t cur_meter_id = meter_id; ++ uint64_t qos_mask = 0; ++ void *private_data = NULL; ++ ++ private_data = hinic3_get_private_data(port_id); ++ if (private_data == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: The current device private_data is NULL."); ++ return -1; ++ } ++ ++ if (hinic_is_bond_by_prefix(*(uint16_t*)private_data)) { ++ HINIC3_LOG(ERR, QOS, "Bond device is not support set QoS."); ++ return -1; ++ } ++ ++ token = strtok_r(qos_level, &delimiter, &qos_level_str); ++ while (token != NULL) { ++ for (int i = 0; i < QOS_LEVEL_MAX_NUM; i++) { ++ if (strcmp(token, g_hinic3_qos_func_array[i].qos_level) == 0 && ++ hinic3_check_qos_level(&qos_mask, i, cur_meter_id, &ret) == true) { ++ ret = g_hinic3_qos_func_array[i].func(port_id, cur_meter_id, &next_meter_id, dir); ++ flag = true; ++ } ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: set qos failed. qos level is %s. ret is %d", token, ret); ++ goto clear; ++ } ++ } ++ if (flag == false) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: qos level is wrong. qos level is %s.", token); ++ goto clear; ++ } ++ if (next_meter_id == MAX_UINT32_NUM) { ++ break; ++ } ++ cur_meter_id = next_meter_id; ++ token = strtok_r(NULL, &delimiter, &qos_level_str); ++ flag = false; ++ } ++ return 0; ++clear: ++ hinic3_clear_qos((struct hinic3_vf_dev*)private_data, dir, &qos_mask); ++ return -1; ++} ++ ++static int hinic3_set_meter_conf(struct hinic3_meter_node *meter, struct rte_flow *flow, ++ enum hinic3_meter_qos_direction dir, uint16_t port_id) ++{ ++ enum hinic3_qos_tablehead index; ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: meter is NULL."); ++ return -1; ++ } ++ ++ index = hinic3_get_multi_qos_show_tablehead(dir, meter->profile->profile.packet_mode); ++ if (index >= QOS_TABLEHEAD_NUM) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: get qos index fail. dir is %d. packet mode is %d.", ++ dir, meter->profile->profile.packet_mode); ++ return -1; ++ } ++ ++ flow->flags.is_qos = 1; ++ flow->flags.qos_index = index; ++ flow->flags.is_mem_used = 1; ++ flow->flags.is_offload = 1; ++ flow->port_id = port_id; ++ meter->flow = flow; ++ return 0; ++} ++ ++struct rte_flow *hinic3_set_multi_qos(const struct rte_flow_item *pattern, const struct rte_flow_action *actions) ++{ ++ int ret; ++ uint16_t port_id = 0; ++ uint32_t meter_id = 0; ++ struct rte_flow *flow = NULL; ++ char qos_level[QOS_LEVEL_MAX_LENGTH] = {0}; ++ enum hinic3_meter_qos_direction dir = HINIC3_TX_METER_QOS; ++ ++ strncpy(qos_level, hinic3_get_multi_qos_level(), QOS_LEVEL_MAX_LENGTH - 1); ++ qos_level[QOS_LEVEL_MAX_LENGTH - 1] = '\0'; ++ ++ ret = hinic3_meter_actions_parse(actions, &meter_id, &dir, &port_id); ++ if (ret != 0) { ++ return NULL; ++ } ++ ++ // 当限速为TX方向时,需要去item中解出port_id ++ if (dir == HINIC3_TX_METER_QOS) { ++ ret = hinic3_meter_pattern_parse(pattern, &port_id); ++ if (ret != 0) { ++ return NULL; ++ } ++ } ++ ++ hinic3_meter_list_lock(); ++ ++ ret = hinic3_set_qos_to_hovs(qos_level, port_id, meter_id, dir); ++ if (ret != 0) { ++ goto end; ++ } ++ ++ flow = hinic3_calloc(1, sizeof(struct rte_flow), HINIC3_QOS); ++ if (flow == NULL) { ++ goto end; ++ } ++ ++ ret = hinic3_set_meter_conf(hinic3_meter_find(meter_id), flow, dir, port_id); ++ if (ret != 0) { ++ hinic3_free(flow); ++ } ++end: ++ hinic3_meter_list_unlock(); ++ return flow; ++} ++ ++enum hinic3_meter_qos_direction hinic3_qos_get_dir(enum hinic3_qos_tablehead index) ++{ ++ switch (index) { ++ case BW_TX_TYPE: ++ case PPS_TX_TYPE: ++ return HINIC3_TX_METER_QOS; ++ case BW_RX_TYPE: ++ case PPS_RX_TYPE: ++ return HINIC3_RX_METER_QOS; ++ default: ++ return HINIC3_NODIR_METER_QOS; ++ } ++} ++ ++static int hinic3_meter_clear_by_flow_sub(enum hinic3_qos_tablehead index, struct hinic3_vf_dev *vf_dev) ++{ ++ int ret; ++ struct hinic3_meter_node *meter = NULL; ++ struct hinic3_mtr_profile_node *profile_node = NULL; ++ struct qos_single_value qos_value = { 0 }; ++ enum hinic3_meter_qos_direction dir = hinic3_qos_get_dir(index); ++ ++ meter = hinic3_meter_find(vf_dev->mtr[index].mtr_id); ++ if (meter == NULL) { ++ HINIC3_LOG(ERR, QOS, "Multi delete: meter id is not find."); ++ return -1; ++ } ++ ++ if (meter->type != QOS_TYPE_FUNC_LIMIT) { ++ HINIC3_LOG(ERR, QOS, "Multi delete: meter qos type error. meter id is %u", meter->meter_id); ++ return -1; ++ } ++ ++ profile_node = meter->profile; ++ ret = hinic3_port_qos_limit_set(vf_dev->vport_id, dir, profile_node->profile.packet_mode, &qos_value); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi delete: remove port qos failed."); ++ return -1; ++ } ++ ++ ret = hinic3_vf_qos_statistics_clear(&vf_dev->vport_id); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: group port statistics not clear. vport id is %u", vf_dev->vport_id); ++ } ++ ++ ret = hinic3_vm_qos_clear(vf_dev, index); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ meter->type = QOS_TYPE_MAX; ++ meter->dir = HINIC3_NODIR_METER_QOS; ++ meter->flow = NULL; ++ return 0; ++} ++ ++static int hinic3_meter_clear_by_flow(struct rte_flow *flow, struct hinic3_vf_dev *vf_dev) ++{ ++ int ret; ++ ++ ret = hinic3_meter_clear_by_flow_sub(flow->flags.qos_index, vf_dev); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, QOS, "Multi qos: del meter failed. qos index is %d, vport id is %u", ++ flow->flags.qos_index, vf_dev->vport_id); ++ return -1; ++ } ++ switch (flow->flags.qos_index) { ++ case BW_TX_TYPE: ++ if (vf_dev->mtr[PPS_TX_TYPE].is_used == true) { ++ ret = hinic3_meter_clear_by_flow_sub(PPS_TX_TYPE, vf_dev); ++ } ++ break; ++ case PPS_TX_TYPE: ++ if (vf_dev->mtr[BW_TX_TYPE].is_used == true) { ++ ret = hinic3_meter_clear_by_flow_sub(BW_TX_TYPE, vf_dev); ++ } ++ break; ++ case BW_RX_TYPE: ++ if (vf_dev->mtr[PPS_RX_TYPE].is_used == true) { ++ ret = hinic3_meter_clear_by_flow_sub(PPS_RX_TYPE, vf_dev); ++ } ++ break; ++ case PPS_RX_TYPE: ++ if (vf_dev->mtr[BW_RX_TYPE].is_used == true) { ++ ret = hinic3_meter_clear_by_flow_sub(BW_RX_TYPE, vf_dev); ++ } ++ break; ++ default: ++ break; ++ } ++ if (ret != 0) { ++ return -1; ++ } ++ return 0; ++} ++ ++int hinic3_qos_flow_delete(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error) ++{ ++ int ret; ++ struct hinic3_vf_dev *vf_dev = NULL; ++ ++ vf_dev = (struct hinic3_vf_dev*)hinic3_get_private_data(flow->port_id); ++ if (vf_dev == NULL) { ++ HINIC3_LOG(ERR, QOS, "The current device private_data is NULL."); ++ return -1; ++ } ++ ++ hinic3_meter_list_lock(); ++ ret = hinic3_meter_clear_by_flow(flow, vf_dev); ++ hinic3_meter_list_unlock(); ++ if (ret != 0) { ++ return -1; ++ } ++ hinic3_free(flow); ++ return 0; ++} ++ ++void hinic3_net_qos_clear(void) ++{ ++ /* 清理所有方向,所有类型(pps\bps)的业务平面级限速 */ ++ /* hinic3_net_qos_limit_set(host_id, dir, type, max_rate, max_burst) */ ++ /* host_id暂时无用,传入0即可 */ ++ hinic3_net_qos_limit_set(0, 0, 0, 0, 0); ++ hinic3_net_qos_limit_set(0, 1, 0, 0, 0); ++ hinic3_net_qos_limit_set(0, 0, 1, 0, 0); ++ hinic3_net_qos_limit_set(0, 1, 1, 0, 0); ++} ++ ++void hinic3_meter_list_init(void) ++{ ++ hinic3_pthread_mutex_init(&g_hinic3_meter_list.mutex); ++ hinic3_list_init(&g_hinic3_meter_list.node); ++ g_hinic3_meter_list.length = 0; ++ ++ g_hinic3_net_meter_info[HINIC3_TX_METER_QOS].is_used = false; ++ g_hinic3_net_meter_info[HINIC3_RX_METER_QOS].is_used = false; ++} ++ ++void hinic3_meter_group_info_init(void) ++{ ++ for (int i = 0; i < HINIC3_METER_NUM_MAX; i++) { ++ g_hinic3_group_infos[i].group_id = i; ++ hinic3_list_init(&g_hinic3_group_infos[i].node); ++ hinic3_pthread_mutex_init(&g_hinic3_group_infos[i].mutex); ++ } ++} ++ ++struct rte_mtr_ops *hinic3_mtr_multi_ops_construct(void) ++{ ++ struct rte_mtr_ops *mtr_ops = NULL; ++ mtr_ops = rte_mtr_ops_allocate(); ++ if (mtr_ops == NULL) { ++ return NULL; ++ } ++ ++ rte_eth_mtr_ops_create(mtr_ops, hinic3_meter_create); ++ rte_eth_mtr_ops_destroy(mtr_ops, hinic3_meter_destroy); ++ rte_eth_mtr_ops_meter_profile_add(mtr_ops, hinic3_multi_meter_profile_add); ++ rte_eth_mtr_ops_meter_profile_delete(mtr_ops, hinic3_multi_meter_profile_del); ++ rte_eth_mtr_ops_meter_profile_update(mtr_ops, hinic3_meter_profile_update); ++ rte_eth_mtr_ops_meter_policy_add(mtr_ops, hinic3_meter_policy_add); ++ rte_eth_mtr_ops_meter_policy_delete(mtr_ops, hinic3_meter_policy_delete); ++ rte_eth_mtr_ops_meter_stats_read(mtr_ops, hinic3_meter_stats_read); ++ return mtr_ops; ++} ++ ++void hinic3_multi_meter_init(void) ++{ ++ hinic3_meter_group_info_init(); ++ hinic3_meter_list_init(); ++ hinic3_meter_profile_list_init(); ++ hinic3_mtr_policy_list_init(); ++} +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.h b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.h +new file mode 100644 +index 0000000..0593a63 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.h +@@ -0,0 +1,100 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#ifndef HINIC3_METER_H ++#define HINIC3_METER_H ++ ++#include "ethdev_driver.h" ++#include "hinic3_mtr_policy.h" ++#include "hinic3_mtr_profile.h" ++#include "rte_mtr.h" ++ ++#define HINIC3_METER_NUM_MAX 1024 // 0号位置不用 ++#define HINIC3_METER_PORT_NUM_MAX 64 ++#define HINIC3_METER_DIR_NUM 4 ++ ++enum hinic3_qos_tablehead { ++ BW_TX_TYPE, ++ PPS_TX_TYPE, ++ BW_RX_TYPE, ++ PPS_RX_TYPE, ++ QOS_TABLEHEAD_NUM, ++}; ++ ++enum hinic3_meter_qos_direction { ++ HINIC3_TX_METER_QOS, ++ HINIC3_RX_METER_QOS, ++ HINIC3_NODIR_METER_QOS, ++}; ++ ++struct hinic3_meter_node { ++ uint32_t meter_id; ++ uint32_t port_id; ++ uint16_t group_id; ++ enum qos_type_limit type; ++ enum hinic3_meter_qos_direction dir; ++ struct rte_flow *flow; ++ struct hinic3_mtr_policy_node *policy; ++ struct hinic3_mtr_profile_node *profile; ++ struct hinic3_list node; ++}; ++ ++struct hinic3_meter_list { ++ struct hinic3_mutex mutex; ++ struct hinic3_list node; ++ uint32_t length; ++}; ++ ++struct hinic3_group_port_info { ++ uint16_t vport_id; ++ struct hinic3_list node; ++}; ++ ++struct hinic3_group_meter_info { ++ uint32_t meter_id; ++ bool is_used; ++}; ++ ++struct hinic3_group_info { ++ uint16_t group_id; ++ uint16_t length; ++ struct hinic3_group_meter_info meter[HINIC3_METER_DIR_NUM]; ++ struct hinic3_list node; ++ struct hinic3_mutex mutex; ++}; ++ ++struct hinic3_net_meter_info { ++ uint32_t meter_id; ++ bool is_used; ++}; ++ ++struct hinic3_qos_func_map { ++ const char *qos_level; ++ int (*func)(uint16_t port_id, uint32_t meter_id, uint32_t *next_meter_id, enum hinic3_meter_qos_direction dir); ++}; ++ ++struct hinic3_clear_qos_func_map { ++ void (*func)(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_qos_direction dir, uint64_t *qos_mask); ++}; ++ ++void hinic3_net_qos_clear(void); ++struct hinic3_net_meter_info *hinic3_net_meter_info_get(void); ++void hinic3_meter_list_lock(void); ++void hinic3_meter_list_unlock(void); ++struct hinic3_meter_list *hinic3_meter_list_get(void); ++void hinic3_group_info_lock(uint16_t group_id); ++void hinic3_group_info_unlock(uint16_t group_id); ++struct hinic3_meter_node *hinic3_meter_find(uint32_t meter_id); ++void hinic3_meter_list_init(void); ++void hinic3_meter_group_info_init(void); ++struct hinic3_group_info *hinic3_group_info_get(uint16_t group_id); ++int hinic3_qos_flow_delete(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error); ++struct rte_flow *hinic3_set_multi_qos(const struct rte_flow_item *pattern, const struct rte_flow_action *actions); ++struct rte_mtr_ops *hinic3_mtr_multi_ops_construct(void); ++void hinic3_port_meter_clear(struct hinic3_vf_dev *vf_dev, uint16_t vport_id); ++int hinic3_group_meter_remove(uint16_t vport_id, uint16_t group_id); ++void hinic3_multi_meter_init(void); ++enum hinic3_qos_tablehead hinic3_get_multi_qos_show_tablehead(uint16_t dir, int packet_mode); ++enum hinic3_meter_qos_direction hinic3_qos_get_dir(enum hinic3_qos_tablehead index); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c +new file mode 100644 +index 0000000..d4b80c6 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c +@@ -0,0 +1,165 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "errno.h" ++#include "hinic3_log.h" ++#include "rte_flow.h" ++#include "rte_mtr_driver.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_mutex.h" ++#include "hinic3_mtr_policy.h" ++#include "hinic3_dpdk_adapter.h" ++ ++#define HINIC3_METER_POLICY_MAX 1024 ++ ++struct hinic3_mtr_policy_list g_mtr_policy_list = { 0 }; ++ ++struct hinic3_mtr_policy_list *hinic3_policy_list_get(void) ++{ ++ return &g_mtr_policy_list; ++} ++ ++void hinic3_mtr_policy_list_lock(void) ++{ ++ hinic3_pthread_mutex_lock(&g_mtr_policy_list.mutex); ++} ++ ++void hinic3_mtr_policy_list_unlock(void) ++{ ++ hinic3_pthread_mutex_unlock(&g_mtr_policy_list.mutex); ++} ++ ++struct hinic3_mtr_policy_node *hinic3_mtr_policy_find(uint32_t policy_id) ++{ ++ struct hinic3_mtr_policy_node *iter = NULL; ++ ++ LIST_FOR_EACH(iter, node, &g_mtr_policy_list.node) { ++ if (iter->policy_id == policy_id) { ++ return iter; ++ } ++ } ++ return NULL; ++} ++ ++static void hinic3_meter_color_action_parse(const struct rte_flow_action *actions, struct hinic3_mtr_policy_node *fmp) ++{ ++ const struct rte_flow_action *action = NULL; ++ const struct rte_flow_action_meter *mtr = NULL; ++ ++ for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) { ++ if (action->type == RTE_FLOW_ACTION_TYPE_METER && action->conf != NULL) { ++ mtr = (struct rte_flow_action_meter *)action->conf; ++ fmp->next_meter_id = mtr->mtr_id; ++ fmp->has_next_meter = true; ++ } ++ } ++} ++ ++static int hinic3_fill_policy_actions(struct hinic3_mtr_policy_node *fmp, struct rte_mtr_meter_policy_params *policy) ++{ ++ const struct rte_flow_action **actions = (const struct rte_flow_action**)&policy->actions; ++ for (int i = 0; i < RTE_COLORS; i++) { ++ if (actions[i] != NULL) { ++ hinic3_meter_color_action_parse(actions[i], fmp); ++ } ++ } ++ return 0; ++} ++ ++int hinic3_meter_policy_delete(struct rte_eth_dev *dev, uint32_t policy_id, struct rte_mtr_error *error) ++{ ++ if (dev == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Policy delete: Policy parameter is empty."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, ++ "Policy delete: parameter is empty."); ++ } ++ ++ struct hinic3_mtr_policy_node *policy = NULL; ++ ++ hinic3_mtr_policy_list_lock(); ++ policy = hinic3_mtr_policy_find(policy_id); ++ if (policy == NULL) { ++ hinic3_mtr_policy_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Policy delete: Policy id is no exist."); ++ return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, ++ "Policy id is invalid."); ++ } ++ ++ if (policy->used_num > 0) { ++ hinic3_mtr_policy_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Policy delete: Policy id is being used."); ++ return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, ++ "Policy id is being used."); ++ } ++ ++ hinic3_list_remove(&policy->node); ++ g_mtr_policy_list.length--; ++ hinic3_free(policy); ++ ++ hinic3_mtr_policy_list_unlock(); ++ return 0; ++} ++ ++int hinic3_meter_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id, ++ struct rte_mtr_meter_policy_params *policy, struct rte_mtr_error *error) ++{ ++ if (eth_dev == NULL || policy == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Policy add: Meter policy parameter is empty."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, ++ "Meter policy parameter is empty."); ++ } ++ ++ if (g_mtr_policy_list.length > HINIC3_METER_POLICY_MAX) { ++ HINIC3_LOG(ERR, QOS, "Policy add: Meter policy reaches the upper limit.(1024)"); ++ return -rte_mtr_error_set(error, ENOMEM, RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, ++ "Meter policy reaches the upper limit."); ++ } ++ ++ int ret; ++ struct hinic3_mtr_policy_node *policy_node = NULL; ++ ++ hinic3_mtr_policy_list_lock(); ++ policy_node = hinic3_mtr_policy_find(policy_id); ++ if (policy_node != NULL) { ++ hinic3_mtr_policy_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Policy add: Policy already exist."); ++ return -rte_mtr_error_set(error, EEXIST, RTE_MTR_ERROR_TYPE_METER_POLICY_ID, NULL, ++ "Policy already exist."); ++ } ++ ++ policy_node = hinic3_calloc(1, sizeof(struct hinic3_mtr_policy_node), HINIC3_QOS); ++ if (policy_node == NULL) { ++ hinic3_mtr_policy_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Policy add: Policy memory alloc failed."); ++ return -rte_mtr_error_set(error, ENOMEM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Policy memory failed."); ++ } ++ ++ policy_node->has_next_meter = false; ++ ++ ret = hinic3_fill_policy_actions(policy_node, policy); ++ if (ret != 0) { ++ hinic3_free(policy_node); ++ hinic3_mtr_policy_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Policy add: Polict action is invalid."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, ++ "Polict action is invalid."); ++ } ++ ++ hinic3_list_init(&policy_node->node); ++ policy_node->used_num = 0; ++ policy_node->policy_id = policy_id; ++ hinic3_list_insert(&g_mtr_policy_list.node, &policy_node->node); ++ g_mtr_policy_list.length++; ++ hinic3_mtr_policy_list_unlock(); ++ ++ return 0; ++} ++ ++void hinic3_mtr_policy_list_init(void) ++{ ++ hinic3_pthread_mutex_init(&g_mtr_policy_list.mutex); ++ hinic3_list_init(&g_mtr_policy_list.node); ++ g_mtr_policy_list.length = 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.h b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.h +new file mode 100644 +index 0000000..c06515b +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.h +@@ -0,0 +1,36 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_MTR_POLICY_H ++#define HINIC3_MTR_POLICY_H ++ ++#include "hinic3_list.h" ++#include "hinic3_mutex.h" ++#include "rte_mtr.h" ++#include "ethdev_driver.h" ++ ++struct hinic3_mtr_policy_node { ++ uint32_t used_num; ++ uint32_t policy_id; ++ uint32_t next_meter_id; ++ bool has_next_meter; ++ struct hinic3_list node; ++}; ++ ++struct hinic3_mtr_policy_list { ++ struct hinic3_mutex mutex; ++ struct hinic3_list node; ++ uint32_t length; ++}; ++ ++struct hinic3_mtr_policy_list *hinic3_policy_list_get(void); ++void hinic3_mtr_policy_list_lock(void); ++void hinic3_mtr_policy_list_unlock(void); ++struct hinic3_mtr_policy_node *hinic3_mtr_policy_find(uint32_t policy_id); ++int hinic3_meter_policy_delete(struct rte_eth_dev *dev, uint32_t policy_id, struct rte_mtr_error *error); ++int hinic3_meter_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id, ++ struct rte_mtr_meter_policy_params *policy, struct rte_mtr_error *error); ++void hinic3_mtr_policy_list_init(void); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.c b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.c +new file mode 100644 +index 0000000..731ab21 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.c +@@ -0,0 +1,181 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "errno.h" ++#include "hinic3_log.h" ++#include "hinic3_mutex.h" ++#include "hinic3_meminfo.h" ++#include "rte_mtr_driver.h" ++#include "hinic3_vf_port_qos_public.h" ++#include "hinic3_mtr_profile.h" ++ ++#define HINIC3_METER_PROFILE_MAX 2048 ++ ++struct hinic3_mtr_profile_list g_hinic3_mtr_profile_list = {0}; ++ ++struct hinic3_mtr_profile_list *hinic3_profile_list_get(void) ++{ ++ return &g_hinic3_mtr_profile_list; ++} ++ ++void hinic3_mtr_profile_list_lock(void) ++{ ++ hinic3_pthread_mutex_lock(&g_hinic3_mtr_profile_list.mutex); ++} ++ ++void hinic3_mtr_profile_list_unlock(void) ++{ ++ hinic3_pthread_mutex_unlock(&g_hinic3_mtr_profile_list.mutex); ++} ++ ++struct hinic3_mtr_profile_node *hinic3_mtr_profile_find(uint32_t profile_id) ++{ ++ struct hinic3_mtr_profile_node *iter = NULL; ++ ++ LIST_FOR_EACH(iter, node, &g_hinic3_mtr_profile_list.node) { ++ if (iter->profile_id == profile_id) { ++ return iter; ++ } ++ } ++ return NULL; ++} ++ ++int hinic3_multi_meter_profile_del(struct rte_eth_dev *dev, uint32_t profile_id, struct rte_mtr_error *error) ++{ ++ if (dev == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Profile delete: Profile delete parameter is empty."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, ++ "Profile delete parameter is empty."); ++ } ++ ++ struct hinic3_mtr_profile_node *profile = NULL; ++ ++ hinic3_mtr_profile_list_lock(); ++ profile = hinic3_mtr_profile_find(profile_id); ++ if (profile == NULL) { ++ hinic3_mtr_profile_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Profile delete: Profile id is no exist."); ++ return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, ++ "Profile id is no exist."); ++ } ++ ++ if (profile->used_num > 0) { ++ hinic3_mtr_profile_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Profile delete: Profile id is being used."); ++ return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, ++ "Profile id is being used."); ++ } ++ ++ hinic3_list_remove(&profile->node); ++ g_hinic3_mtr_profile_list.length--; ++ hinic3_free(profile); ++ hinic3_mtr_profile_list_unlock(); ++ return 0; ++} ++ ++static int hinic3_copy_profile(struct qos_single_value *new_profile, ++ struct rte_mtr_meter_profile *old_profile) ++{ ++ int packet_mode = old_profile->packet_mode; ++ if (packet_mode != QOS_BW_TYPE && packet_mode != QOS_PPS_TYPE) { ++ HINIC3_LOG(ERR, QOS, "Profile add: Meter profile packet mode is invalid."); ++ return -1; ++ } ++ /* The unit is converted from large B to kb */ ++ switch (old_profile->alg) { ++ case RTE_MTR_SRTCM_RFC2697: ++ new_profile->min_rate = (old_profile->alg == RTE_MTR_SRTCM_RFC2697) ? (old_profile->srtcm_rfc2697.cir) ++ : (old_profile->trtcm_rfc2698.cir); ++ new_profile->min_burst = (old_profile->alg == RTE_MTR_SRTCM_RFC2697) ? (old_profile->srtcm_rfc2697.cbs) ++ : (old_profile->trtcm_rfc2698.cbs); ++ new_profile->max_rate = (old_profile->alg == RTE_MTR_SRTCM_RFC2697) ? (old_profile->srtcm_rfc2697.cir) ++ : (old_profile->trtcm_rfc2698.cir); ++ new_profile->max_burst = old_profile->srtcm_rfc2697.ebs; ++ new_profile->is_RFC2697 = true; ++ break; ++ case RTE_MTR_TRTCM_RFC2698: ++ new_profile->min_rate = (old_profile->alg == RTE_MTR_SRTCM_RFC2697) ? (old_profile->srtcm_rfc2697.cir) ++ : (old_profile->trtcm_rfc2698.cir); ++ new_profile->min_burst = (old_profile->alg == RTE_MTR_SRTCM_RFC2697) ? (old_profile->srtcm_rfc2697.cbs) ++ : (old_profile->trtcm_rfc2698.cbs); ++ new_profile->max_rate = old_profile->trtcm_rfc2698.pir; ++ new_profile->max_burst = old_profile->trtcm_rfc2698.pbs; ++ new_profile->is_RFC2697 = false; ++ break; ++ default: ++ HINIC3_LOG(ERR, QOS, "Profile add: Meter profile alg type is invalid."); ++ return -1; ++ } ++ new_profile->packet_mode = packet_mode; ++ switch (new_profile->packet_mode) { ++ case QOS_BW_TYPE: ++ new_profile->max_rate = (new_profile->max_rate * BYTE_TO_BIT) / KB_TO_B; ++ new_profile->max_burst = (new_profile->max_burst * BYTE_TO_BIT) / KB_TO_B; ++ new_profile->min_rate = (new_profile->min_rate * BYTE_TO_BIT) / KB_TO_B; ++ new_profile->min_burst = (new_profile->min_burst * BYTE_TO_BIT) / KB_TO_B; ++ return check_vf_bw_args(*new_profile); ++ case QOS_PPS_TYPE: ++ return check_vf_pps_args(*new_profile); ++ default: ++ return -1; ++ } ++} ++ ++int hinic3_multi_meter_profile_add(struct rte_eth_dev *dev, uint32_t meter_profile_id, ++ struct rte_mtr_meter_profile *profile, struct rte_mtr_error *error) ++{ ++ if (dev == NULL || profile == NULL || error == NULL) { ++ HINIC3_LOG(ERR, QOS, "Profile add: Meter profile parameter is empty."); ++ return -rte_mtr_error_set(error, EPERM, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, ++ "Meter profile parameter is empty."); ++ } ++ ++ if (g_hinic3_mtr_profile_list.length > HINIC3_METER_PROFILE_MAX) { ++ HINIC3_LOG(ERR, QOS, "Profile add: Meter profile reaches the upper limit.(2048)"); ++ return -rte_mtr_error_set(error, ENOMEM, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, ++ "Meter profile reaches the upper limit."); ++ } ++ ++ int ret; ++ struct hinic3_mtr_profile_node *profile_node = NULL; ++ ++ hinic3_mtr_profile_list_lock(); ++ profile_node = hinic3_mtr_profile_find(meter_profile_id); ++ if (profile_node != NULL) { ++ hinic3_mtr_profile_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Profile add: Profile already exist."); ++ return -rte_mtr_error_set(error, EEXIST, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, ++ "Profile already exist."); ++ } ++ ++ profile_node = hinic3_calloc(1, sizeof(struct hinic3_mtr_profile_node), HINIC3_QOS); ++ if (profile_node == NULL) { ++ hinic3_mtr_profile_list_unlock(); ++ HINIC3_LOG(ERR, QOS, "Profile add: Profile memory alloc failed."); ++ return -rte_mtr_error_set(error, ENOMEM, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, ++ "Profile memory alloc failed."); ++ } ++ ++ ret = hinic3_copy_profile(&profile_node->profile, profile); ++ if (ret != 0) { ++ hinic3_free(profile_node); ++ hinic3_mtr_profile_list_unlock(); ++ return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, ++ "Meter profile parameter is invalid."); ++ } ++ profile_node->profile_id = meter_profile_id; ++ profile_node->used_num = 0; ++ hinic3_list_init(&profile_node->node); ++ hinic3_list_insert(&g_hinic3_mtr_profile_list.node, &profile_node->node); ++ g_hinic3_mtr_profile_list.length++; ++ hinic3_mtr_profile_list_unlock(); ++ return 0; ++} ++ ++void hinic3_meter_profile_list_init(void) ++{ ++ hinic3_list_init(&g_hinic3_mtr_profile_list.node); ++ hinic3_pthread_mutex_init(&g_hinic3_mtr_profile_list.mutex); ++ g_hinic3_mtr_profile_list.length = 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.h b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.h +new file mode 100644 +index 0000000..9eef841 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_profile.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_MTR_PROFILE_H ++#define HINIC3_MTR_PROFILE_H ++ ++#include "hinic3_list.h" ++#include "hinic3_mutex.h" ++#include "ethdev_driver.h" ++#include "hinic3_vf_port_qos_public.h" ++ ++struct hinic3_mtr_profile_node { ++ uint32_t used_num; ++ struct hinic3_list node; ++ uint32_t profile_id; ++ struct qos_single_value profile; ++}; ++ ++struct hinic3_mtr_profile_list { ++ struct hinic3_list node; ++ struct hinic3_mutex mutex; ++ uint32_t length; ++}; ++ ++void hinic3_mtr_profile_list_lock(void); ++void hinic3_mtr_profile_list_unlock(void); ++struct hinic3_mtr_profile_list *hinic3_profile_list_get(void); ++struct hinic3_mtr_profile_node *hinic3_mtr_profile_find(uint32_t profile_id); ++void hinic3_meter_profile_list_init(void); ++int hinic3_multi_meter_profile_del(struct rte_eth_dev *dev, uint32_t profile_id, struct rte_mtr_error *error); ++int hinic3_multi_meter_profile_add(struct rte_eth_dev *dev, uint32_t meter_profile_id, ++ struct rte_mtr_meter_profile *profile, struct rte_mtr_error *error); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c +new file mode 100644 +index 0000000..ef76e2d +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c +@@ -0,0 +1,105 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_flow_session.h" ++#include "hinic3_ufid_hmap.h" ++#include "hinic3_iface_global.h" ++#include "hinic3_ds.h" ++#include "hinic3_command.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_mpool_rte_flow.h" ++ ++static struct hinic3_mpool_mgmt_rte_flow g_mpool_mgmt = { 0 }; ++ ++void hinic3_uninit_rte_flow_mpool(void) ++{ ++ dpak_mempool_destroy(g_mpool_mgmt.rte_flow_mpool); ++ dpak_mempool_destroy(g_mpool_mgmt.ufid_map_mpool); ++} ++ ++int hinic3_flush_rte_flow_mpool(void) ++{ ++ return dpak_mempool_flush(g_mpool_mgmt.rte_flow_mpool); ++} ++ ++int hinic3_flush_ufid_map_mpool(void) ++{ ++ return dpak_mempool_flush(g_mpool_mgmt.ufid_map_mpool); ++} ++ ++static int hinic3_init_flow_mpool(void) ++{ ++ uint32_t max_flow_num = hinic3_max_flow_num_get(); ++ ++ g_mpool_mgmt.rte_flow_mpool = hinic3_create_single_mpool(HINIC3_RTE_FLOW_ELE_MPOOL_NAME, sizeof(struct rte_flow), ++ max_flow_num * HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM, HINIC3_UFID_MAP); ++ if (g_mpool_mgmt.rte_flow_mpool == NULL) { ++ return -1; ++ } ++ ++ g_mpool_mgmt.ufid_map_mpool = hinic3_create_single_mpool(HINIC3_UFID_MAP_MPOOL_NAME, ++ sizeof(struct hinic3_ufid_hmap_node), max_flow_num * HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM, HINIC3_UFID_MAP); ++ if (g_mpool_mgmt.ufid_map_mpool == NULL) { ++ dpak_mempool_destroy(g_mpool_mgmt.rte_flow_mpool); ++ g_mpool_mgmt.rte_flow_mpool = NULL; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int hinic3_init_rte_flow_mpool(void) ++{ ++ int ret = 0; ++ ++ ret = hinic3_init_flow_mpool(); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "init flow mpool failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void hinic3_free_from_rte_flow_mpool(void *ptr) ++{ ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, FLOW, "ptr is null in rte_flow_mpool.\n"); ++ return; ++ } ++ ++ dpak_mempool_free(g_mpool_mgmt.rte_flow_mpool, ptr); ++} ++ ++void hinic3_free_from_ufid_map_mpool(void *ptr) ++{ ++ if (ptr == NULL) { ++ HINIC3_LOG(ERR, FLOW, "ptr is null in rte_flow_mpool.\n"); ++ return; ++ } ++ ++ dpak_mempool_free(g_mpool_mgmt.ufid_map_mpool, ptr); ++} ++ ++void *hinic3_alloc_from_rte_flow_mpool(void) ++{ ++ return dpak_mempool_alloc(g_mpool_mgmt.rte_flow_mpool, HINIC3_UFID_MAP); ++} ++ ++void *hinic3_alloc_from_ufid_map_mpool(void) ++{ ++ return dpak_mempool_alloc(g_mpool_mgmt.ufid_map_mpool, HINIC3_UFID_MAP); ++} ++ ++void hinic3_dump_mempool_info(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ hinic3_show_one_mpool(g_mpool_mgmt.rte_flow_mpool, &ds, false); ++ hinic3_show_one_mpool(g_mpool_mgmt.ufid_map_mpool, &ds, false); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++ return; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h +new file mode 100644 +index 0000000..a01509f +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_RTE_FLOW_MPOOL_H ++#define HINIC3_RTE_FLOW_MPOOL_H ++ ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_command.h" ++#include "hinic3_mpool.h" ++#include "hinic3_ds.h" ++ ++#define HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM (1 * (1 << 20)) ++#define HINIC3_RTE_FLOW_ELE_MPOOL_NAME "hinic3_rte_flow_ele_pool" ++#define HINIC3_UFID_MAP_MPOOL_NAME "hinic3_ufid_map_pool" ++ ++struct hinic3_mpool_mgmt_rte_flow { ++ struct dpak_mempool *rte_flow_mpool; ++ struct dpak_mempool *ufid_map_mpool; ++}; ++ ++int hinic3_init_rte_flow_mpool(void); ++void hinic3_uninit_rte_flow_mpool(void); ++int hinic3_flush_rte_flow_mpool(void); ++int hinic3_flush_ufid_map_mpool(void); ++void hinic3_free_from_rte_flow_mpool(void *ptr); ++void hinic3_free_from_ufid_map_mpool(void *ptr); ++void *hinic3_alloc_from_rte_flow_mpool(void); ++void *hinic3_alloc_from_ufid_map_mpool(void); ++void hinic3_dump_mempool_info(struct unixctl_conn *conn, int argc, const char *argv[], void *aux); ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c +new file mode 100644 +index 0000000..82eddfb +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c +@@ -0,0 +1,118 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_packet_key_public.h" ++#include "hinic3_util.h" ++#include "hinic3_map.h" ++#include "hinic3_mpool_rte_flow.h" ++#include "hinic3_ufid_hmap.h" ++ ++void hinic3_ufid_hmap_init(struct hmap *ufid_hmap) ++{ ++ hinic3_hmap_init(ufid_hmap); ++} ++ ++static inline void *hinic3_ufid_map_alloc(struct hmap *ufid_hmap, HINIC3_UFID_MAP_TYPE type) ++{ ++ switch (type) { ++ case EMC_UFID_MAP: ++ return hinic3_alloc_from_ufid_map_mpool(); ++ default: ++ return NULL; ++ } ++ ++ return NULL; ++} ++ ++static inline void hinic3_ufid_map_dealloc(struct hmap *ufid_hmap, void *ptr, HINIC3_UFID_MAP_TYPE type) ++{ ++ switch (type) { ++ case EMC_UFID_MAP: ++ return hinic3_free_from_ufid_map_mpool(ptr); ++ default: ++ return; ++ } ++} ++ ++void hinic3_ufid_hmap_destroy(struct hmap *ufid_hmap, HINIC3_UFID_MAP_TYPE type) ++{ ++ if (ufid_hmap) { ++ hinic3_ufid_hmap_clear(ufid_hmap, type); ++ hinic3_hmap_destroy(ufid_hmap); ++ } ++} ++ ++struct hinic3_ufid_hmap_node *hinic3_ufid_hmap_add(struct hmap *ufid_hmap, ++ struct rte_flow *key, uint32_t hash, enum hinic3_module module_id, HINIC3_UFID_MAP_TYPE type) ++{ ++ struct hinic3_ufid_hmap_node *node = NULL; ++ ++ node = hinic3_ufid_map_alloc(ufid_hmap, type); ++ if (HINIC3_UNLIKELY(node == NULL)) { ++ return NULL; ++ } ++ node->key = key; ++ ++ hinic3_hmap_insert(ufid_hmap, &node->node, hash, module_id); ++ return node; ++} ++ ++static bool hinic3_ufid_match_func(const struct hinic3_conntrack_full_key *full_key1, ++ const struct hinic3_conntrack_full_key *full_key2) ++{ ++ if (full_key1->key.meta_num == full_key2->key.meta_num && ++ memcmp(full_key1->key.key, full_key2->key.key, full_key2->key.meta.key_len) == 0) { ++ return true; ++ } ++ ++ return false; ++} ++ ++static struct hinic3_ufid_hmap_node *hinic3_ufid_hmap_get_node(const struct hmap *ufid_hmap, ++ const struct hinic3_conntrack_full_key *full_key, uint32_t hash) ++{ ++ struct hinic3_ufid_hmap_node *ufid_hmap_node; ++ ++ HINIC3_HMAP_FOR_EACH_WITH_HASH(ufid_hmap_node, node, hash, ufid_hmap) { ++ if (hinic3_ufid_match_func(&ufid_hmap_node->key->key, full_key)) { ++ return ufid_hmap_node; ++ } ++ } ++ return NULL; ++} ++ ++struct rte_flow *hinic3_ufid_hmap_get(const struct hmap *ufid_hmap, ++ const struct hinic3_conntrack_full_key *full_key, uint32_t hash) ++{ ++ struct hinic3_ufid_hmap_node *node = hinic3_ufid_hmap_get_node(ufid_hmap, full_key, hash); ++ return node ? node->key : NULL; ++} ++ ++void hinic3_ufid_hmap_remove_node(struct hmap *ufid_hmap, struct hinic3_ufid_hmap_node *node, HINIC3_UFID_MAP_TYPE type) ++{ ++ hinic3_hmap_remove(ufid_hmap, &node->node); ++ hinic3_ufid_map_dealloc(ufid_hmap, node, type); ++ node = NULL; ++} ++ ++void hinic3_ufid_hmap_clear(struct hmap *ufid_hmap, HINIC3_UFID_MAP_TYPE type) ++{ ++ struct hinic3_ufid_hmap_node *node, *next; ++ HINIC3_HMAP_FOR_EACH_SAFE(node, next, node, ufid_hmap) { ++ hinic3_ufid_hmap_remove_node(ufid_hmap, node, type); ++ } ++} ++ ++int hinic3_ufid_hmap_del_by_key(struct hmap *ufid_hmap, const struct hinic3_conntrack_full_key *full_key, ++ uint32_t hash, HINIC3_UFID_MAP_TYPE type) ++{ ++ struct hinic3_ufid_hmap_node *ufid_hmap_node = NULL; ++ ++ ufid_hmap_node = hinic3_ufid_hmap_get_node(ufid_hmap, full_key, hash); ++ if (ufid_hmap_node == NULL) { ++ return -1; ++ } ++ hinic3_ufid_hmap_remove_node(ufid_hmap, ufid_hmap_node, type); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h +new file mode 100644 +index 0000000..4057784 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_UFID_HMAP_H ++#define HINIC3_UFID_HMAP_H ++ ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_hmap.h" ++ ++struct hinic3_ufid_hmap_node { ++ struct hmap_node node; ++ struct rte_flow *key; ++}; ++ ++typedef enum { ++ EMC_UFID_MAP, ++ DP_HASH_UFID_MAP, ++ UFID_MAP_MAX, ++} HINIC3_UFID_MAP_TYPE; ++ ++void hinic3_ufid_hmap_init(struct hmap *ufid_hmap); ++void hinic3_ufid_hmap_destroy(struct hmap *ufid_hmap, HINIC3_UFID_MAP_TYPE type); ++struct hinic3_ufid_hmap_node *hinic3_ufid_hmap_add(struct hmap *ufid_hmap, ++ struct rte_flow *key, uint32_t hash, enum hinic3_module module_id, HINIC3_UFID_MAP_TYPE type); ++struct rte_flow *hinic3_ufid_hmap_get(const struct hmap *ufid_hmap, ++ const struct hinic3_conntrack_full_key *full_key, uint32_t hash); ++void hinic3_ufid_hmap_clear(struct hmap *ufid_hmap, HINIC3_UFID_MAP_TYPE type); ++int hinic3_ufid_hmap_del_by_key(struct hmap *ufid_hmap, const struct hinic3_conntrack_full_key *full_key, uint32_t hash, ++ HINIC3_UFID_MAP_TYPE type); ++ ++#endif +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c +new file mode 100644 +index 0000000..21e66ab +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c +@@ -0,0 +1,466 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++ ++#include "hinic3_command.h" ++#include "hinic3_driver_public.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_log.h" ++#include "hinic3_flow_agent.h" ++#include "hinic3_flow_session.h" ++#include "hinic3_util.h" ++#include "hinic3_agent_cmd_time.h" ++#include "hinic3_iface_flow_api_record.h" ++#include "hinic3_meminfo.h" ++#include "hinic3_ds.h" ++#include "hinic3_command.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_ufid_map_rte_flow.h" ++ ++static struct hinic3_ufid_map_table hinic3_mpool_mgmt; ++struct stat_refresh_time g_stat_ref_time[HINIC3_COMMAND_QUEUES_NUM_MAX] = {0}; ++static struct hinic3_spin_rwlock g_emc_flush_all_lock; ++#define HINIC3_FLOW_NOT_FOUND (-2) ++ ++static inline void hinic3_flush_all_lock_init(void) ++{ ++ rte_rwlock_init(&g_emc_flush_all_lock.lock); ++} ++ ++void hinic3_rlock_flush_all(void) ++{ ++ rte_rwlock_read_lock(&g_emc_flush_all_lock.lock); ++} ++ ++void hinic3_runlock_flush_all(void) ++{ ++ rte_rwlock_read_unlock(&g_emc_flush_all_lock.lock); ++} ++ ++void hinic3_wlock_flush_all(void) ++{ ++ rte_rwlock_write_lock(&g_emc_flush_all_lock.lock); ++} ++ ++void hinic3_wunlock_flush_all(void) ++{ ++ rte_rwlock_write_unlock(&g_emc_flush_all_lock.lock); ++} ++ ++int hinic3_try_rlock_flush_all(void) ++{ ++ return rte_rwlock_read_trylock(&g_emc_flush_all_lock.lock); ++} ++ ++bool hinic3_is_rte_hmap_empty(void) ++{ ++ for (int i = 0; i < OFFLOAD_FLOW_BUCKETS; i++) { ++ if (!hinic3_hmap_is_empty(&hinic3_mpool_mgmt.hash_table_array[i].key_hmap)) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static uint32_t hinic3_rte_flow_hash_to_bucket(uint32_t hash) ++{ ++#define OFFLOAD_BUCKETS_UINT_BIT 32 ++ return (hash >> (OFFLOAD_BUCKETS_UINT_BIT - OFFLOAD_FLOW_BUCKETS_SHIFT)) % OFFLOAD_FLOW_BUCKETS; ++} ++ ++uint32_t hinic3_hash_generate(const struct hinic3_conntrack_key *key) ++{ ++ uint32_t hash = hinic3_mpool_mgmt.hash_base; ++ hash = hinic3_hash_add(hash, key->meta_num); ++ ++ for (int idx = 0; idx < key->meta.key_len / sizeof(uint32_t); idx++) { ++ hash = hinic3_hash_add(hash, ((uint32_t *)key->key)[idx]); ++ } ++ return hash; ++} ++ ++static struct hash_table_node *hinic3_rte_flow_bucket_get(struct hinic3_ufid_map_table *tbl, uint32_t flow_hash) ++{ ++ uint32_t bucket = hinic3_rte_flow_hash_to_bucket(flow_hash); ++ return &tbl->hash_table_array[bucket]; ++} ++ ++struct hash_table_node *hinic3_get_flow_bucket(uint32_t flow_hash) ++{ ++ return hinic3_rte_flow_bucket_get(&hinic3_mpool_mgmt, flow_hash); ++} ++ ++/* 判断是否重复卸载,如果重复卸载直接返回NULL */ ++struct rte_flow *hinic3_get_offloaded_rte_flow(struct hash_table_node *rte_bucket, ++ const struct hinic3_conntrack_full_key *key, uint32_t flow_hash) ++{ ++ return hinic3_ufid_hmap_get(&rte_bucket->key_hmap, key, flow_hash); ++} ++ ++int hinic3_del_rte_flow_if_offload_fail(struct hash_table_node *rte_bucket, struct rte_flow *mega_flow) ++{ ++ int ret; ++ int ret_session; ++ struct hinic3_conntrack_full_key *key = &mega_flow->key; ++ ++ if (mega_flow->flags.is_sample == 1) { ++ ret_session = hinic3_del_rte_flow_in_session(mega_flow); ++ if (ret_session != 0) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 delete session flow failed\n"); ++ } ++ } ++ ++ ret = hinic3_ufid_hmap_del_by_key(&rte_bucket->key_hmap, key, mega_flow->flow_hash, EMC_UFID_MAP); ++ if (ret != 0) { ++ return -1; ++ } ++ return 0; ++} ++ ++int hinic3_del_rte_flow_in_hmap(struct hash_table_node *rte_bucket, struct rte_flow *mega_flow) ++{ ++ int ret; ++ struct hinic3_conntrack_full_key *key = &mega_flow->key; ++ ++ ret = hinic3_ufid_hmap_del_by_key(&rte_bucket->key_hmap, key, mega_flow->flow_hash, EMC_UFID_MAP); ++ if (ret == 0) { ++ return 0; ++ } ++ return -1; ++} ++ ++int hinic3_insert_rte_flow_in_hmap(struct hash_table_node *rte_bucket, struct rte_flow *mega_flow) ++{ ++ struct hinic3_ufid_hmap_node *node = NULL; ++ struct hmap *hash_table = &rte_bucket->key_hmap; ++ ++ node = hinic3_ufid_hmap_add(hash_table, mega_flow, mega_flow->flow_hash, HINIC3_UFID_MAP, EMC_UFID_MAP); ++ if (node == NULL) { ++ return -1; ++ } ++ return 0; ++} ++ ++struct hinic3_flow_del_rte_flow_context *hinic3_del_rte_flow_batch_context_alloc(uint16_t port_id) ++{ ++ struct hinic3_flow_del_rte_flow_context *batch = NULL; ++ struct hinic3_dpif_flow_for_get *flow = NULL; ++ ++ batch = (struct hinic3_flow_del_rte_flow_context *)hinic3_calloc(1, sizeof(struct hinic3_flow_del_rte_flow_context), ++ HINIC3_UFID_MAP); ++ if (batch == NULL) { ++ HINIC3_LOG(ERR, FLOW, "hinic3 flow del batch calloc failed\n"); ++ return NULL; ++ } ++ ++ batch->num_entries = 0; ++ batch->port_id = port_id; ++ for (int idx = 0; idx < HINIC3_MAX_ENTRY_PER_BATCH_DEL; idx++) { ++ flow = &batch->buf[idx].get_flow; ++ flow->key = (struct hinic3_nlattr_obj *)batch->buf[idx].key_buf; ++ flow->key_len = sizeof(batch->buf[idx].actions_buf); ++ flow->mask = NULL; ++ flow->mask_len = 0; ++ flow->mask_present = false; ++ flow->actions = (struct hinic3_nlattr_obj *)batch->buf[idx].actions_buf; ++ flow->action_len = sizeof(batch->buf[idx].actions_buf); ++ batch->flows[idx] = flow; ++ } ++ ++ return batch; ++} ++ ++static void hinic3_del_hw_flows_batch_rte_flow(struct hinic3_flow_del_rte_flow_context *batch, uint64_t hw_ufid) ++{ ++ if (batch->num_entries < HINIC3_MAX_ENTRY_PER_BATCH_DEL) { ++ batch->ufids[batch->num_entries] = hw_ufid; ++ batch->buf[batch->num_entries].get_flow.ol_ufid = hw_ufid; ++ batch->num_entries++; ++ } ++ ++ if (batch->num_entries == HINIC3_MAX_ENTRY_PER_BATCH_DEL) { ++ hinic3_flow_del_batch(batch->ufids, batch->flows, batch->num_entries); ++ batch->num_entries = 0; ++ batch->is_deleted = 1; ++ } ++ return; ++} ++ ++int hinic3_set_ufid_in_rte_flow(struct hinic3_flow_callback_info *callback_info, uint64_t ufid) ++{ ++ struct rte_flow *flow = NULL; ++ struct hash_table_node *rte_bucket = NULL; ++ struct hmap *hash_table = NULL; ++ struct hinic3_conntrack_full_key *key = &callback_info->no_ct_key; ++ uint32_t flow_hash = callback_info->flow_hash; ++ uint8_t sub_table = 0; ++ ++ rte_bucket = hinic3_get_flow_bucket(flow_hash); ++ hash_table = &rte_bucket->key_hmap; ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ ++ flow = hinic3_ufid_hmap_get(hash_table, key, flow_hash); ++ if (flow == NULL) { ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return -1; ++ } ++ flow->hw_ufid = ufid; ++ flow->flags.is_offload = 1; ++ ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ return 0; ++} ++ ++void hinic3_ufid_map_flush(void) ++{ ++ for (uint32_t i = 0; i < OFFLOAD_FLOW_BUCKETS; i++) { ++ struct hash_table_node *rte_bucket = &hinic3_mpool_mgmt.hash_table_array[i]; ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ hinic3_hmap_clear(&rte_bucket->key_hmap); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ } ++} ++ ++void hinic3_dump_rte_flow_by_hw_ufid(uint32_t thread_id, uint32_t *cur_buk_index, uint32_t max_buk_index, uint8_t *para, ++ int (*callback)(struct rte_flow *, struct traverse_data *)) ++{ ++ uint32_t i; ++ clock_t start_t = 0; ++ clock_t finish_t = 0; ++ struct traverse_data cur_node_data; ++ struct hinic3_ufid_hmap_node *ufid_hmap_node = NULL; ++ cur_node_data.para = para; ++ ++ if (HINIC3_UNLIKELY(hinic3_is_stat_scan_measure_alive() == true)) { ++ start_t = clock(); ++ } ++ ++ for (i = *cur_buk_index; i < (*cur_buk_index + SYNC_BUCKET_NUM) && i < max_buk_index; i++) { ++ (void)hinic3_rlock_flush_all(); ++ struct hash_table_node *rte_bucket = &hinic3_mpool_mgmt.hash_table_array[i]; ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ if (hinic3_hmap_is_empty(&rte_bucket->key_hmap)) { ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ (void)hinic3_runlock_flush_all(); ++ continue; ++ } ++ cur_node_data.is_end = false; ++ HINIC3_HMAP_FOR_EACH(ufid_hmap_node, node, &rte_bucket->key_hmap) { ++ callback(ufid_hmap_node->key, &cur_node_data); ++ } ++ cur_node_data.is_end = true; ++ callback(NULL, &cur_node_data); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ (void)hinic3_runlock_flush_all(); ++ } ++ ++ if (i == max_buk_index) { ++ *cur_buk_index = max_buk_index; ++ } else { ++ *cur_buk_index += SYNC_BUCKET_NUM; ++ } ++ ++ if (HINIC3_UNLIKELY(hinic3_is_stat_scan_measure_alive() == true)) { ++ finish_t = clock(); ++ g_stat_ref_time[thread_id].time = ((double)(finish_t - start_t)) / CLOCKS_PER_SEC; ++ g_stat_ref_time[thread_id].update = 1; ++ } ++} ++ ++static void hinic3_release_ufid_map(int index) ++{ ++ for (int i = 0; i < index; ++i) { ++ struct hash_table_node *rte_bucket = &hinic3_mpool_mgmt.hash_table_array[i]; ++ hinic3_spinlock_destroy(&rte_bucket->spinlock); ++ } ++} ++ ++void hinic3_dump_hmap_flow_num(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ uint32_t flow_num = 0; ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ ++ for (int i = 0; i < OFFLOAD_FLOW_BUCKETS; ++i) { ++ struct hash_table_node *rte_bucket = &hinic3_mpool_mgmt.hash_table_array[i]; ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ flow_num += hinic3_hmap_count(&rte_bucket->key_hmap); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ } ++ ++ hinic3_ds_put_format(&ds, "Info: The hmap flow num is %u.\n", flow_num); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ *(int *)aux = 0; ++} ++ ++int hinic3_ufid_map_rte_flow_init(void) ++{ ++ int ret; ++ hinic3_mpool_mgmt.hash_base = 0; ++ ++ hinic3_flush_all_lock_init(); ++ for (int i = 0; i < OFFLOAD_FLOW_BUCKETS; ++i) { ++ struct hash_table_node *rte_bucket = &hinic3_mpool_mgmt.hash_table_array[i]; ++ struct hmap *hash_table = &rte_bucket->key_hmap; ++ ++ hinic3_ufid_hmap_init(hash_table); ++ ret = hinic3_spinlock_init(&rte_bucket->spinlock, PTHREAD_PROCESS_PRIVATE); ++ if (ret != 0) { ++ (void)hinic3_release_ufid_map(i); ++ return -1; ++ } ++ } ++ HINIC3_LOG(INFO, AGENT, "hinic3 hash_map init success"); ++ ++ return 0; ++} ++ ++struct stat_refresh_time *hinic3_get_stat_ref_time(void) ++{ ++ return g_stat_ref_time; ++} ++ ++static void hinic3_batch_del_rte_flow_set_error_code(const struct hinic3_dpif_flow_for_get *flow, int *destroy_result) ++{ ++ switch (flow->ol_ufid) { ++ case HIOVS_UFID_DEL_NO_RESPON: ++ *destroy_result = -EDOM; ++ break; ++ case HIOVS_UFID_INVALID: ++ *destroy_result = -ENOENT; ++ break; ++ case HIOVS_UFID_NO_EXIST: ++ *destroy_result = -ENOENT; ++ break; ++ case HIOVS_UFID_DEL_FAilED: ++ *destroy_result = -EFAULT; ++ break; ++ case HIOVS_FLOW_NO_EXIST: ++ *destroy_result = -ENOENT; ++ break; ++ default: ++ *destroy_result = -EDOM; ++ } ++} ++ ++static void hinic3_batch_del_rte_flow_in_hmap(struct hinic3_flow_del_rte_flow_context *batch, ++ int index, int destroy_result[], int *delete_nums, struct rte_flow **flow) ++{ ++ struct hash_table_node *rte_bucket; ++ uint16_t err_num = 0; ++ int batch_flow_index = batch->is_deleted == 1 ? (HINIC3_MAX_ENTRY_PER_BATCH_DEL - 1) : (batch->num_entries - 1); ++ for (int destroy_result_index = index; destroy_result_index >= 0 && batch_flow_index >= 0; destroy_result_index--) { ++ if (destroy_result[destroy_result_index] == -1) { ++ continue; ++ } ++ if (batch->ufids[batch_flow_index] == batch->flows[batch_flow_index]->ol_ufid) { ++ rte_bucket = hinic3_get_flow_bucket(flow[batch_flow_index]->flow_hash); ++ hinic3_spinlock_lock(&rte_bucket->spinlock); ++ (void)hinic3_del_rte_flow_in_hmap(rte_bucket, flow[batch_flow_index]); ++ hinic3_rte_flow_dealloc(flow[batch_flow_index]); ++ hinic3_spinlock_unlock(&rte_bucket->spinlock); ++ (*delete_nums)++; ++ batch_flow_index--; ++ } else { ++ err_num++; ++ (void)hinic3_batch_del_rte_flow_set_error_code(batch->flows[batch_flow_index], ++ &destroy_result[destroy_result_index]); ++ } ++ } ++ if (err_num != 0) { ++ HINIC3_LOG(ERR, FLOW, "Batch delete flow not cleaned up!\n"); ++ } ++} ++ ++int hinic3_batch_del_flow(struct rte_flow **flow, int flow_num, int destroy_result[]) ++{ ++ int delete_nums = 0; ++ uint16_t port_id = 0; ++ struct hinic3_flow_del_rte_flow_context *batch = hinic3_del_rte_flow_batch_context_alloc(port_id); // 为复用接口,port_id=0为无效参数 ++ if (batch == NULL) { ++ return -ENOMEM; ++ } ++ memset(destroy_result, 0, sizeof(int) * flow_num); ++ for (int i = 0; i < flow_num; i++) { ++ if ((flow[i] != NULL) && (flow[i]->flags.is_offload == 0)) { ++ destroy_result[i] = -1; ++ continue; ++ } ++ ++ if (flow[i] == NULL) { ++ continue; ++ } ++ hinic3_del_hw_flows_batch_rte_flow(batch, flow[i]->hw_ufid); ++ if (batch->is_deleted == 1) { ++ hinic3_batch_del_rte_flow_in_hmap(batch, i % HINIC3_MAX_ENTRY_PER_BATCH_DEL, ++ destroy_result, &delete_nums, flow); ++ batch->is_deleted = 0; ++ } ++ } ++ if (batch->num_entries != 0) { ++ hinic3_flow_del_batch(batch->ufids, batch->flows, batch->num_entries); ++ hinic3_batch_del_rte_flow_in_hmap(batch, flow_num - 1, destroy_result, &delete_nums, flow); ++ } ++ hinic3_free(batch); ++ return delete_nums; ++} ++ ++static int hinic3_release_hmap_node_by_port(struct rte_flow *flow, struct hinic3_flow_del_rte_flow_context *batch, ++ struct hash_table_node *bucket) ++{ ++ int ret; ++ ++ if (flow->port_id != batch->port_id) { ++ return 0; ++ } ++ ++ if (flow->flags.is_sample == 1) { ++ ret = hinic3_del_rte_flow_in_session(flow); ++ if (ret != 0) { ++ return -1; ++ } ++ } ++ ++ ret = hinic3_del_rte_flow_in_hmap(bucket, flow); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, FLOW, "Flow del failed in hmap."); ++ return -1; ++ } ++ hinic3_del_hw_flows_batch_rte_flow(batch, flow->hw_ufid); ++ hinic3_rte_flow_dealloc(flow); ++ ++ return 0; ++} ++ ++int hinic3_del_flow_in_hmap_by_port(uint16_t port_id) ++{ ++ int ret; ++ struct hinic3_ufid_hmap_node *ufid_hmap_node = NULL; ++ struct hinic3_flow_del_rte_flow_context *batch = hinic3_del_rte_flow_batch_context_alloc(port_id); ++ if (batch == NULL) { ++ HINIC3_LOG(ERR, FLOW, "Failed to alloc del batch context."); ++ return -ENOMEM; ++ } ++ ++ for (int idx = 0; idx < OFFLOAD_FLOW_BUCKETS; idx++) { ++ struct hash_table_node *bucket = &hinic3_mpool_mgmt.hash_table_array[idx]; ++ hinic3_spinlock_lock(&bucket->spinlock); ++ HINIC3_HMAP_FOR_EACH(ufid_hmap_node, node, &bucket->key_hmap) { ++ ret = hinic3_release_hmap_node_by_port(ufid_hmap_node->key, batch, bucket); ++ if (ret != 0) { ++ hinic3_free(batch); ++ hinic3_spinlock_unlock(&bucket->spinlock); ++ HINIC3_LOG(ERR, FLOW, "hinic3load delete py port_id failed."); ++ return -1; ++ } ++ } ++ hinic3_spinlock_unlock(&bucket->spinlock); ++ } ++ ++ if (batch->num_entries != 0) { ++ hinic3_flow_del_batch(batch->ufids, batch->flows, batch->num_entries); ++ } ++ hinic3_free(batch); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h +new file mode 100644 +index 0000000..d6a444d +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h +@@ -0,0 +1,122 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2023 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_UFID_MAP_RTE_FLOW_H ++#define HINIC3_UFID_MAP_RTE_FLOW_H ++#include ++#include ++#include ++#include ++#include ++#include "hinic3_mutex.h" ++#include "hinic3_ufid_hmap.h" ++#include "hinic3_flow_agent_public.h" ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_hash.h" ++#include "hinic3_command.h" ++#include "hinic3_mpool_rte_flow.h" ++#include "hiovs_api.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define STAT_REFRESH_MAX_THREAD_NUM 10 ++#define SYNC_BUCKET_NUM 16 ++ ++enum { ++ HIOVS_UFID_DEL_NO_RESPON, ++ HIOVS_UFID_INVALID, ++ HIOVS_UFID_NO_EXIST, ++ HIOVS_UFID_DEL_FAilED, ++ HIOVS_FLOW_NO_EXIST, ++}; ++ ++struct hinic3_flow_del_rte_flow_context { ++ size_t num_entries; ++ uint8_t is_deleted; /* 标记batch中内容是否在硬件中已经删除,在dpak中还没有删除 */ ++ uint16_t port_id; ++ uint64_t ufids[HINIC3_MAX_ENTRY_PER_BATCH_DEL]; ++ struct hinic3_dpif_flow_for_get *flows[HINIC3_MAX_ENTRY_PER_BATCH_DEL]; ++ struct hinic3_flow_del_buf buf[HINIC3_MAX_ENTRY_PER_BATCH_DEL]; ++}; ++ ++struct hash_table_node { ++ struct hinic3_spinlock spinlock; ++ struct hmap key_hmap; ++}; ++ ++struct hinic3_ufid_map_table { ++ uint32_t hash_base; ++ struct hash_table_node hash_table_array[OFFLOAD_FLOW_BUCKETS]; ++}; ++ ++struct traverse_data { ++ uint8_t *para; ++ bool is_end; ++}; ++ ++struct stat_refresh_time { ++ double time; /* 记录统计信息全量刷新时长 单位为s */ ++ uint32_t update; /* 更新标记,1表示更新,0表示此时间数据已被采样过,不是最新数据 */ ++}; ++ ++static inline struct rte_flow *hinic3_rte_flow_alloc(void) ++{ ++ struct rte_flow *flow = NULL; ++ ++ flow = hinic3_alloc_from_rte_flow_mpool(); ++ if (HINIC3_UNLIKELY(flow == NULL)) { ++ return NULL; ++ } ++ memset(flow, 0, sizeof(struct rte_flow)); ++ flow->flags.is_mem_used = 1; ++ return flow; ++} ++ ++static inline void hinic3_rte_flow_dealloc(struct rte_flow *flow) ++{ ++ if (flow == NULL) { ++ return; ++ } ++ ++ if (flow->flags.is_mem_used == 0) { ++ HINIC3_LOG(ERR, FLOW, "flow is unused in mem dealloc"); ++ return; ++ } ++ flow->flags.is_mem_used = 0; ++ hinic3_free_from_rte_flow_mpool(flow); ++ flow = NULL; ++} ++ ++ ++void hinic3_rlock_flush_all(void); ++void hinic3_runlock_flush_all(void); ++void hinic3_wlock_flush_all(void); ++void hinic3_wunlock_flush_all(void); ++int hinic3_try_rlock_flush_all(void); ++int hinic3_ufid_map_rte_flow_init(void); ++void hinic3_ufid_map_flush(void); ++void hinic3_dump_rte_flow_by_hw_ufid(uint32_t thread_id, uint32_t *cur_buk_index, uint32_t max_buk_index, ++ uint8_t *para, int (*callback)(struct rte_flow *, struct traverse_data *)); ++bool hinic3_is_rte_hmap_empty(void); ++void hinic3_dump_hmap_flow_num(struct unixctl_conn *conn, int argc, const char *argv[], ++ void *aux HINIC3_UNUSED); ++ ++int hinic3_del_flow_in_hmap_by_port(uint16_t port_id); ++int hinic3_set_ufid_in_rte_flow(struct hinic3_flow_callback_info *callback_info, uint64_t ufid); ++int hinic3_del_rte_flow_if_offload_fail(struct hash_table_node *rte_bucket, struct rte_flow *mega_flow); ++int hinic3_del_rte_flow_in_hmap(struct hash_table_node *rte_bucket, struct rte_flow *mega_flow); ++struct rte_flow *hinic3_get_offloaded_rte_flow(struct hash_table_node *rte_bucket, ++ const struct hinic3_conntrack_full_key *key, uint32_t flow_hash); ++int hinic3_insert_rte_flow_in_hmap(struct hash_table_node *rte_bucket, struct rte_flow *mega_flow); ++int hinic3_batch_del_flow(struct rte_flow **flow, int flow_num, int destroy_result[]); ++struct stat_refresh_time *hinic3_get_stat_ref_time(void); ++struct hash_table_node *hinic3_get_flow_bucket(uint32_t flow_hash); ++uint32_t hinic3_hash_generate(const struct hinic3_conntrack_key *key); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/meson.build b/drivers/net/meson.build +index 6470bf3..f7fb628 100644 +--- a/drivers/net/meson.build ++++ b/drivers/net/meson.build +@@ -25,6 +25,7 @@ drivers = [ + 'fm10k', + 'gve', + 'hinic', ++ 'hinic3', + 'hns3', + 'i40e', + 'iavf', +-- +2.47.0.windows.2 + diff --git a/0096-remove-macro-HAVE_OVS_DPDK.patch b/0096-remove-macro-HAVE_OVS_DPDK.patch new file mode 100644 index 0000000000000000000000000000000000000000..512135df3ea9567fafb71e7bafaa6fa50dd4deaf --- /dev/null +++ b/0096-remove-macro-HAVE_OVS_DPDK.patch @@ -0,0 +1,588 @@ +From e03dfd213b84df966b38d88ba4a82a7712b03bd8 Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Thu, 26 Jun 2025 16:47:38 +0800 +Subject: [PATCH] remove macro HAVE_OVS_DPDK + +--- + drivers/net/hinic3/meson.build | 7 +++- + .../common/hinic3_utils/hinic3_file_util.c | 41 ------------------- + .../common/hinic3_utils/hinic3_file_util.h | 1 - + .../hinic3_utils/hinic3_packets_types.h | 2 - + .../common/hinic3_utils/hinic3_set_userdata.c | 2 - + .../src/common/hinic3_utils/hinic3_util.c | 3 -- + .../hinic3_capture/hinic3_capture_command.c | 2 - + .../src/hinic3_capture/hinic3_capture_core.c | 2 - + .../hinic3_capture/hinic3_capture_filter.c | 5 --- + .../src/hinic3_capture/hinic3_capture_hooks.c | 2 - + .../src/hinic3_capture/hinic3_capture_main.c | 2 - + .../src/hinic3_capture/hinic3_capture_save.c | 2 - + .../src/hinic3_capture/hinic3_capture_utils.c | 2 - + .../comm/hinic3_agent_flow_cmd_dump_file.c | 6 --- + .../comm/hinic3_dfx_port_bond_slave.c | 2 - + .../comm/hinic3_dfx_port_flush_dump.c | 2 - + .../comm/hinic3_dfx_port_upcall_queue.c | 2 - + .../src/hinic3_cmds/server/hinic3_command.c | 34 --------------- + .../hinic3_iface_global.c | 2 - + .../hinic3_iface_global_api_record.c | 2 - + .../comm/hinic3_offload_flow_public.c | 2 - + .../hinic3_flow_dump/hinic3_flow_api.c | 2 - + .../hinic3_flows/hinic3_vxlan/hinic3_vxlan.c | 2 - + .../hinic3/src/hinic3_init/comm/hinic3_init.c | 2 - + .../hinic3_bond/hinic3_bond_controller.c | 2 - + .../hinic3_bond/hinic3_bond_controller.h | 2 - + .../hinic3_bond/hinic3_bond_statistics.c | 2 - + .../hinic3_vf/hinic3_function_statistics.c | 2 - + .../hinic3_vf/hinic3_vf_controller.h | 2 - + .../hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c | 3 -- + .../hinic3/src/hinic3_qos/meter/hinic3_qos.c | 2 - + 31 files changed, 6 insertions(+), 140 deletions(-) + +diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build +index af0793845f..77916f79e1 100644 +--- a/drivers/net/hinic3/meson.build ++++ b/drivers/net/hinic3/meson.build +@@ -174,7 +174,12 @@ foreach d:deps + static_deps += [get_variable('static_rte_' + d)] + endforeach + +-executable('dpak_ovs_ctl', ++executable('dpak-ovs-ctl', + 'src/hinic3_cmds/client/hinic3_command_client.c', + include_directories: includes, ++ install_rpath: '/usr/bin', ++ install: true + ) ++ ++install_data('cfg/ovs_dpu_virt/agent_config.ini', install_dir: '/etc/dpak/net') ++install_data('scripts/dpak_ovs_completion_ovs.sh', install_dir: '/etc/bash_completion.d') +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c +index 2cefeaafd7..9635cedcbf 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c +@@ -65,8 +65,6 @@ static bool hinic3_check_directory_existence(char *path) + static int hinic3_mkdir(char *path) + { + char dir_path[PATH_MAX]; +- struct passwd *user = NULL; +- struct group *grp = NULL; + int ret; + + ret = snprintf(dir_path, PATH_MAX, "%s", path); +@@ -80,29 +78,6 @@ static int hinic3_mkdir(char *path) + return -1; + } + +- user = getpwnam(HINIC3_FILE_USER); +- if (user == NULL) { +- HINIC3_LOG(ERR, AGENT, "get file directory user fail, path: %s", path); +- return 0; +- } +- grp = getgrnam(HINIC3_FILE_GROUP); +- if (grp == NULL) { +- HINIC3_LOG(ERR, AGENT, "get file directory group fail, path: %s", path); +- return 0; +- } +- +- if (hinic3_check_masked_to_exact_switch() == false) { +- if (chown(path, -1, grp->gr_gid) == -1) { +- HINIC3_LOG(ERR, AGENT, "change file directory group fail, path: %s", path); +- return 0; +- } +- } else { +- if (chown(path, user->pw_uid, grp->gr_gid) == -1) { +- HINIC3_LOG(ERR, AGENT, "change file directory user and group fail, path: %s", path); +- return 0; +- } +- } +- + return 0; + } + +@@ -192,22 +167,6 @@ static bool hinic3_is_directory_reach_limit(void) + return false; + } + +-int hinic3_agent_chown_output_file_path(const char *resolve_path) +-{ +- struct group *grp = getgrnam(HINIC3_OVS_GROUP_NAME); +- if (grp != NULL) { +- gid_t group_id = grp->gr_gid; +- if (chown(resolve_path, -1, group_id) == -1) { +- HINIC3_LOG(ERR, AGENT, "chown fail, errno: %d", errno); +- return -1; +- } +- } else { +- HINIC3_LOG(ERR, AGENT, "getgrnam %s fail", HINIC3_OVS_GROUP_NAME); +- return -1; +- } +- return 0; +-} +- + int hinic3_check_output_file_directory(const char *filename, char *absolute_path, unsigned int path_len, struct ds *ds) + { + int ret; +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h +index 70313bf2cd..806218c8cc 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.h +@@ -11,7 +11,6 @@ + + const char *hinic3_get_default_directory(void); + int hinic3_check_output_file_directory(const char *filename, char *absolute_path, unsigned int path_len, struct ds *ds); +-int hinic3_agent_chown_output_file_path(const char *resolve_path); + uint64_t hinic3_get_default_file_directory_size(bool *is_obtained); + uint64_t hinic3_get_partition_free_space_size(void); + int hinic3_check_file_realpath(const char *absolute_path, char *resolve_path, struct ds *ds); +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h +index aec6355bd4..9f8c1d711d 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_packets_types.h +@@ -323,9 +323,7 @@ struct padding_info { + }; + + struct hinic3_packet { +-#ifdef HAVE_OVS_DPDK + struct rte_mbuf mbuf; +-#endif + /* basic packet info */ + hinic3_be16 dl_type; + uint16_t l3_ofs; /* l3 header offset, or UINT16_MAX. */ +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c +index 1ab68bd1c1..6842024acc 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_set_userdata.c +@@ -18,9 +18,7 @@ + #include "hinic3_offload_flow.h" + #include "hinic3_iface_global.h" + #include "hinic3_set_userdata.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + #define HINIC3_METER_RTE_MBUF_GET_PTR 8 + +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c +index aa7484de07..a4d4c5c98e 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c +@@ -14,10 +14,7 @@ + #include "rte_ethdev.h" + #include "hinic3_meminfo.h" + #include "hinic3_string_util.h" +- +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + #define HINIC3_HEX_PREFIX_LEN 2 + static clockid_t g_monotonic_clock = CLOCK_MONOTONIC; +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +index 099d7b198e..919c5f1484 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +@@ -11,10 +11,8 @@ + #include "rte_cycles.h" + #include "rte_lcore.h" + #include "rte_spinlock.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" +-#endif + + #include "hinic3_ds.h" + #include "hinic3_log.h" +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c +index 328ce6522b..34afa037a8 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_core.c +@@ -13,11 +13,9 @@ + #include "hinic3_iface_global.h" + #include "hinic3_capture_filter.h" + #include "hinic3_capture_save.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" + #include "hinic3_capture_core.h" +-#endif + + static inline void + pcap_hinic3_pkt_summary_init(struct pcap_pkt_summary *buf, struct rte_mbuf *pkt) +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +index 61c36faf0d..d1c44faa20 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +@@ -1116,11 +1116,6 @@ pcap_file_open(const char *file_name, const char *mode) + return NULL; + } + +- if (hinic3_agent_chown_output_file_path(file_name) != 0) { +- fclose(file); +- return NULL; +- } +- + return file; + } + +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c +index 4c38fe7544..b33be8bb7f 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c +@@ -13,10 +13,8 @@ + #include "rte_cycles.h" + #include "rte_lcore.h" + #include "rte_spinlock.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" +-#endif + + #include "hinic3_log.h" + #include "hinic3_init.h" +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c +index a87f38f69a..a66844347f 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c +@@ -12,10 +12,8 @@ + #include "rte_lcore.h" + #include "rte_spinlock.h" + #include "hinic3_thread.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" +-#endif + + #include "hinic3_log.h" + #include "hinic3_init.h" +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +index ffc1c5d40c..75e08f61c5 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +@@ -13,10 +13,8 @@ + #include "rte_cycles.h" + #include "rte_lcore.h" + #include "rte_spinlock.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" +-#endif + + #include "hinic3_log.h" + #include "hinic3_init.h" +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +index dedcaf590b..3dcec18e5b 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +@@ -28,11 +28,9 @@ + #include "hinic3_ds.h" + #include "hinic3_ui_string.h" + #include "hinic3_dpdk_adapter.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" + #include "hinic3_capture_utils.h" +-#endif + + #define HINIC3_EVENT_FD_INVAILD (-1) + uint64_t g_ticks_per_ms; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +index 852ed9486e..1b2cbf763a 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +@@ -115,12 +115,6 @@ hinic3_agent_parse_output_file_path(struct hinic3_dump_all_flows_mgmt_t *m, int + goto fail; + } + +- if (hinic3_agent_chown_output_file_path(resolve_path) != 0) { +- fclose(m->file); +- m->file = NULL; +- goto fail; +- } +- + hinic3_free(resolve_path); + return 0; + +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c +index fd46999cb7..af069cba92 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c +@@ -20,9 +20,7 @@ + #include "hinic3_smap.h" + #include "hinic3_command.h" + #include "hinic3_vf_controller.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + #include "hinic3_dfx_port.h" + + static void +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c +index e9d8f2b99a..471bba5d1d 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c +@@ -14,9 +14,7 @@ + #include "hinic3_bond_controller.h" + #include "hinic3_agent_cmd_format.h" + #include "rte_ethdev.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + #define HINIC3_LINK_STATUS_STR_LEN 10 + #define HINIC3_LINK_STATUS_NUM 2 +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c +index fc6d3f2c71..2f6c76c205 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c +@@ -9,9 +9,7 @@ + #include "hinic3_vf_port_qos_public.h" + #include "hinic3_vf_controller.h" + #include "hinic3_bond_controller.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + static int + hinic3_dump_virtual_upcall_queues_info(struct ds *ds) +diff --git a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +index 9208521eed..7fdf61fc46 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +@@ -480,34 +480,6 @@ hinic3_command_thread(void *arg) + return 0; + } + +-static int +-hinic3_change_group(void) +-{ +- int ret; +- gid_t group_id; +- struct group *grp; +- +- grp = getgrnam(HINIC3_OVS_GROUP_NAME); +- if (grp == NULL) { +- HINIC3_LOG(ERR, AGENT, "getgrnam fail"); +- return -1; +- } +- group_id = grp->gr_gid; +- +- ret = chown(SOCKET_PATH, -1, group_id); +- if (ret == -1) { +- HINIC3_LOG(ERR, AGENT, "chown fail"); +- return -1; +- } +- +- ret = chmod(SOCKET_PATH, HINIC3_SOCKET_RIGHT); +- if (ret == -1) { +- HINIC3_LOG(ERR, AGENT, "chmod fail"); +- return -1; +- } +- return 0; +-} +- + static int + hinic3_command_pre_init(int *listen_socket) + { +@@ -607,12 +579,6 @@ hinic3_command_mgr_init(void) + return ret; + } + +- ret = hinic3_change_group(); +- if (ret != 0) { +- HINIC3_LOG(ERR, AGENT, "change group fail"); +- return ret; +- } +- + HINIC3_LOG(INFO, AGENT, "command mgr init success"); + return 0; + } +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +index 8ee1b5a343..13e1f2cac0 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +@@ -21,10 +21,8 @@ + #include "hinic3_smap.h" + #include "hinic3_ds.h" + #include "hinic3_iface_global.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" +-#endif + #include "hinic3_command.h" + #include "hinic3_parse_agent_config.h" + #include "hinic3_ui_string.h" +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c +index b76c281320..852f9bf23d 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global_api_record.c +@@ -19,10 +19,8 @@ + #include "hinic3_util.h" + #include "hinic3_iface_global.h" + #include "hinic3_ds.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" +-#endif + #include "hinic3_iface_global_api_record.h" + + hiovs_api_record g_global_api_record[HINIC3_GLOBAL_API_MAX]; +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c +index b84961a241..3b817fc4ea 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_flow_public.c +@@ -10,10 +10,8 @@ + #include "hinic3_iface_global.h" + #include "hinic3_iface_flow.h" + #include "hinic3_log.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" +-#endif + + void hinic3_offload_thread_rx_put_ack(uint32_t thread_id, struct hinic3_dp_extend_info *dp_info) + { +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +index 48d89eab81..289d6ed92a 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +@@ -21,11 +21,9 @@ + #include "hinic3_agent_flow_cmd_dump.h" + #include "hinic3_agent_cmd_format.h" + #include "hinic3_offload_flow.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" + #include "hinic3_ovs_adapter.h" + #include "hinic3_iface_flow.h" +-#endif + + #define HINIC3_NO_FOUND_FLOW (-4) + uint64_t g_get_related_ufid; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c +index 3349adfb83..4889c37cf7 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c +@@ -2,9 +2,7 @@ + * Copyright(c) 2023 Huawei Technologies Co., Ltd + */ + #include "hinic3_vxlan.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + #define HINIC3_IPV6_ADDR_SIZE 4 + #define HINIC3_VNI_LOW 0 + #define HINIC3_VNI_MID 1 +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c +index 5abd51cab1..652faad002 100644 +--- a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c +@@ -22,9 +22,7 @@ + #include "hinic3_agent.h" + #include "hinic3_smap.h" + #include "hinic3_parse_agent_config.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + #define HINIC3_DRV_SHARD_LIBRARY "/usr/lib64/libhiovs3.so" + #define HINIC3_PF_ADDR_NULL_STR "XXXX:XX:XX.X" +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +index e626a5dd19..4149684984 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +@@ -10,9 +10,7 @@ + #include "hinic3_vxlan.h" + #include "hinic3_flow_dump.h" + #include "hinic3_tlv_key.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + #include "hinic3_bond_controller.h" + + #define PRIORITY_UPCALL_MAX_NUM 2 +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h +index d145013b54..16b10b4a2f 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.h +@@ -7,9 +7,7 @@ + + #include + #include "hinic3_queue.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + #define HINIC3_PF_DEFAULT_MTU 9058 + #define HINIC3_PF_DEFAULT_NB_QUEUES 1 +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c +index 6f48552b88..c2e767b2d8 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_statistics.c +@@ -6,9 +6,7 @@ + #include "hinic3_dfx_port.h" + #include "hinic3_port_util.h" + #include "hinic3_bond_controller.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + #include "hinic3_bond_statistics.h" + + int +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c +index 7e3d7aa2c0..ea4e2c8d6e 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c +@@ -19,9 +19,7 @@ + #include "hinic3_vxlan.h" + #include "hinic3_flow_dump.h" + #include "hinic3_offload_flow_port.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + int hinic3_vf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) + { +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h +index 7c2acb0719..cc5b2d28cd 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.h +@@ -16,9 +16,7 @@ + #include "hinic3_eth_util.h" + #include "hinic3_vf_mgmt.h" + #include "hinic3_queue.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + #define HINIC3_VF_DEFAULT_NB_QUEUES 1 + #define HINIC3_MAX_JUMBO_FRAME_SIZE 9626 +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c +index 91a82d6727..29116b76ac 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c +@@ -25,10 +25,7 @@ + #include "hinic3_mutex.h" + #include "hinic3_vf_mgmt_virtual.h" + #include "hinic3_vf_mgmt_baremetal.h" +- +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + struct hinic3_mutex hwpt_phy_dev_mutex; + static int g_port_conf_type = PORT_CONF_NULL; +diff --git a/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c +index 93dc57f888..241d8c2072 100644 +--- a/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c ++++ b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c +@@ -5,9 +5,7 @@ + #include "hinic3_mtr.h" + #include "hinic3_meminfo.h" + #include "hinic3_qos.h" +-#ifdef HAVE_OVS_DPDK + #include "hinic3_dpdk_adapter.h" +-#endif + + struct rte_mtr_ops *g_hinic3_mtr_ops = NULL; + +-- +2.47.0.windows.2 + diff --git a/0097-Support-set-mtu-feature.patch b/0097-Support-set-mtu-feature.patch new file mode 100644 index 0000000000000000000000000000000000000000..9793edfd80b5284a800f1bdf1b94489bfc022414 --- /dev/null +++ b/0097-Support-set-mtu-feature.patch @@ -0,0 +1,139 @@ +From e5c13b8eda2557b0961f84357e258fb8b925286c Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Thu, 26 Jun 2025 11:11:29 +0800 +Subject: [PATCH] Support set mtu feature + +--- + .../hinic3/scripts/dpak_ovs_completion_ovs.sh | 1 + + .../src/common/hinic3_utils/hinic3_drv.h | 1 + + .../hinic3_driver_adapter/hinic3_iface_port.c | 31 ++++++++++++++++++- + .../hinic3_driver_adapter/hinic3_iface_port.h | 4 +++ + .../hinic3_driver_adapter/hiovs/hiovs_api.h | 10 ++++++ + .../hinic3/src/hinic3_init/comm/hinic3_init.c | 1 + + 6 files changed, 47 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +index bd7a820d00..f18e1f2c0d 100644 +--- a/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh ++++ b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +@@ -93,6 +93,7 @@ _complete_show_global_api() { + local api_opts=( + hovs_global_cfg_set + hovs_global_cfg_get ++ hovs_global_device_feature_get + hovs_global_statistics_get + hovs_global_statistics_flush + hovs_open_log +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h +index 49aa55403b..cf0ba3bc2b 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h +@@ -65,6 +65,7 @@ struct hinic3_drv_ops { + int (*hovs_global_cfg_set)(const struct nlattr *args, size_t args_len, struct nlattr *unset_args, + size_t *unset_args_len); + int (*hovs_global_cfg_get)(struct nlattr *args, size_t *args_len); ++ int (*hovs_global_device_feature_get)(uint64_t *default_device_feature, uint64_t *support_device_feature); + int (*hovs_global_statistics_get)(struct hovs_global_stats *stats); + int (*hovs_global_statistics_flush)(void); + int (*hovs_mml_lib)(const char *buf_in, uint32_t in_size, char *buf_out, uint32_t *out_len, +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c +index 48635ed641..59d7e92cfe 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c +@@ -628,6 +628,25 @@ const char *hinic3_port_get_api_name(hinic3_port_api api_index) + return NULL; + } + ++static int hinic3_vdpa_feature_add_mtu(uint64_t *vdpa_feature) ++{ ++ int ret; ++ struct hinic3_drv_ops *ops = NULL; ++ uint64_t default_feature = 0; ++ uint64_t support_feature = 0; ++ ++ ops = hinic3_get_drv_ops(); ++ HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_global_device_feature_get, HINIC3_DRV_FUNC_NO_PTR); ++ ++ ret = ops->hovs_global_device_feature_get(&default_feature, &support_feature); ++ if (ret != 0) { ++ return -1; ++ } ++ ++ *vdpa_feature = default_feature | (1 << VIRTIO_NET_F_MTU); ++ return 0; ++} ++ + int hinic3_port_mgmt_add_dynamic(uint16_t *port_id, const struct smap *args) + { + int ret; +@@ -656,8 +675,18 @@ int hinic3_port_mgmt_add_dynamic(uint16_t *port_id, const struct smap *args) + hinic3_nlattr_init(&nla_args, tmp_buff, HOVS_MAX_TLV_BUF_LEN); + /* smap to nlattr */ + port_args_smap_to_nlattr(args, &nla_args); ++ + /* vdpa feature */ +- vdpa_feature = hinic3_vdpa_feature_get(); ++ if (hinic3_hiovs_mode_get() == HIOVS_WORK_MODE_ZERO_VM_PT) { ++ // 只在虚拟化场景下支持 ++ ret = hinic3_vdpa_feature_add_mtu(&vdpa_feature); ++ if (ret != 0) { ++ HINIC3_LOG(ERR, VPORT, "get featrue failed."); ++ return -EPERM; ++ } ++ } else { ++ vdpa_feature = hinic3_vdpa_feature_get(); ++ } + if (vdpa_feature != 0) { + hinic3_nlattr_put_u64(&nla_args, HINIC3_PORT_ARG_DEVICE_FEATURE, vdpa_feature); + } +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h +index 1385e990db..b75b09a336 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h +@@ -13,6 +13,10 @@ + #include "hinic3_map.h" + #include "hinic3_provider.h" + ++#ifndef VIRTIO_NET_F_MTU ++ #define VIRTIO_NET_F_MTU 3 ++#endif ++ + #ifdef __cplusplus + extern "C" { + #endif +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h +index e5caf628a0..df1cfe0e47 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h +@@ -862,6 +862,16 @@ int hovs_global_cfg_set(const struct nlattr *args, size_t args_len, struct nlatt + + int hovs_global_cfg_get(struct nlattr *args, size_t *args_len); + ++/** ++ * Get the the device feature, include default feature, support feature. ++ * ++ * @param[out] stats Output default feature, support feature. ++ * @return ++ * - HIOVS_OK: if successful. ++ * - HIOVS_ERROR: if the parameter check fails or the execute fails. ++ */ ++int hovs_global_device_feature_get(uint64_t *default_device_feature, uint64_t *support_device_feature); ++ + /** + * Get the the global statistics, include offload stats, upcall stats, other drop stats. + * +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c +index 8b76577cb5..5abd51cab1 100644 +--- a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_init.c +@@ -74,6 +74,7 @@ static struct hinic3_drv_ops_map g_hinic3_drv_ops_map[] = { + HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_flow_callback_register), + HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_cfg_set), + HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_cfg_get), ++ HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_device_feature_get), + HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_statistics_get), + HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_global_statistics_flush), + HINIC3_DRV_ADD_FUNC(g_hinic3_drv_ops, hovs_mml_lib), +-- +2.47.0.windows.2 + diff --git a/0098-fix-error-log.patch b/0098-fix-error-log.patch new file mode 100644 index 0000000000000000000000000000000000000000..2f7e49bc69ba98ea75e8ec11ba3c50aafc295664 --- /dev/null +++ b/0098-fix-error-log.patch @@ -0,0 +1,37 @@ +From b03da19934166533e88ffd23642cae80c27be253 Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Thu, 26 Jun 2025 11:27:27 +0800 +Subject: [PATCH] fix_error_log + +--- + .../net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c | 1 + + drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +index c292fc62d1..8ee1b5a343 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +@@ -649,6 +649,7 @@ static void hinic3_lib_arg_init(struct rte_mempool *mempool, uint32_t data_room_ + arg->ext_cb_ops.hovs_memzone_reserve = hinic3_adapt_memzone_reserve; + arg->ext_cb_ops.hovs_memzone_reserve_aligned = hinic3_adapt_memzone_reserve_aligned; + arg->ext_cb_ops.hovs_memzone_free = hinic3_adapt_memzone_free; ++ arg->ext_cb_ops.hovs_memzone_lookup = rte_memzone_lookup; + arg->bond_rx_depth = hinic3_bond_rx_depth_get(); + arg->bond_tx_depth = hinic3_bond_tx_depth_get(); + arg->vport_rx_depth = hinic3_vport_rx_depth(); +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h +index df1cfe0e47..53758e9266 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hiovs/hiovs_api.h +@@ -218,6 +218,7 @@ struct hovs_callback_ext_ops { + const void *(*hovs_memzone_reserve_aligned)(const char *name, size_t len, + int socket_id, uint32_t flags, uint32_t align); + int (*hovs_memzone_free)(void *mz); ++ const struct rte_memzone *(*hovs_memzone_lookup)(const char *name); + }; + + struct hiovs_lib_arg { +-- +2.47.0.windows.2 + diff --git a/0099-add-interface.patch b/0099-add-interface.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8d7d5d94cbea05f413ee3ee9ec048d966922770 --- /dev/null +++ b/0099-add-interface.patch @@ -0,0 +1,148 @@ +From ec181f7fc7f18353b21550299c618424620a9276 Mon Sep 17 00:00:00 2001 +From: Feifei Wang +Date: Wed, 2 Jul 2025 16:44:48 +0800 +Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=8E=A5=E5=8F=A3=E8=B0=83?= + =?UTF-8?q?=E7=94=A8?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + drivers/net/hinic3/include/rte_pmd_hinic3.h | 10 ++++++++++ + drivers/net/hinic3/meson.build | 5 +++++ + drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh | 4 ++-- + .../src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c | 4 ++-- + .../net/hinic3/src/hinic3_cmds/server/hinic3_command.c | 2 +- + drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c | 5 +++-- + 6 files changed, 23 insertions(+), 7 deletions(-) + create mode 100644 drivers/net/hinic3/include/rte_pmd_hinic3.h + +diff --git a/drivers/net/hinic3/include/rte_pmd_hinic3.h b/drivers/net/hinic3/include/rte_pmd_hinic3.h +new file mode 100644 +index 0000000000..c97c01bcb0 +--- /dev/null ++++ b/drivers/net/hinic3/include/rte_pmd_hinic3.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2022 Huawei Technologies Co., Ltd ++ */ ++#ifndef RTE_PMD_HINIC3_H ++#define RTE_PMD_HINIC3_H ++ ++int hinic3_agent_construct(void); ++void hinic3_agent_destruct(void); ++ ++#endif +\ No newline at end of file +diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build +index 77916f79e1..cbb26cdf2f 100644 +--- a/drivers/net/hinic3/meson.build ++++ b/drivers/net/hinic3/meson.build +@@ -109,6 +109,9 @@ sources = files( + ) + + includes += include_directories( ++ '../../../lib/distributor/', ++ '../../../build', ++ '../../../config', + 'include', + 'src/', + 'src/hinic3_capture', +@@ -181,5 +184,7 @@ executable('dpak-ovs-ctl', + install: true + ) + ++install_headers('include/rte_pmd_hinic3.h') ++ + install_data('cfg/ovs_dpu_virt/agent_config.ini', install_dir: '/etc/dpak/net') + install_data('scripts/dpak_ovs_completion_ovs.sh', install_dir: '/etc/bash_completion.d') +diff --git a/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +index f18e1f2c0d..488dc5e2fc 100644 +--- a/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh ++++ b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +@@ -10,7 +10,7 @@ TOP_LEVEL_OPTS=( + hwoff/show-forward-mode + hwoff/set-forward-mode + hwoff/show-global-api +- hwoff/dump-hinic3-flows ++ hwoff/dump-hwoff-flows + hwoff/dump-upcall-queue-info + hwoff/dump-bond-slave-info + hwoff/show-port-api +@@ -649,7 +649,7 @@ _dpak_ovs_ctl() { + _complete_show_global_api + return 0 + ;; +- hwoff/dump-hinic3-flows) ++ hwoff/dump-hwoff-flows) + _complete_dump_hinic3_flows + return 0 + ;; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +index 3e0b10b2a7..4b289dbd54 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +@@ -291,7 +291,7 @@ hinic3_agent_dump_specific_flow(int argc, const char *argv[], struct ds *ds) + static void + hinic3_agent_dump_flows_help(struct ds *ds) + { +- hinic3_ds_put_format(ds, "%2s%sdpak-ovs-ctl hwoff/dump-hinic3-flows [ ufid | -n |" ++ hinic3_ds_put_format(ds, "%2s%sdpak-ovs-ctl hwoff/dump-hwoff-flows [ ufid | -n |" + " -f | -i | check | stop | { -h | --help } ]\n\n", HINIC3_UI_INDENT_SPACE, + HINIC3_UI_CMD_USAGE_STRING); + hinic3_ds_put_format(ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_UI_FLOW_OPTION_LIST_STRING); +@@ -547,7 +547,7 @@ unixctl_hinic3_flow_dump_cmd_init(void) + DUMP_HINIC3_FLOWS_PARAM = 2, + }; + +- hinic3_command_register("hwoff/dump-hinic3-flows", ++ hinic3_command_register("hwoff/dump-hwoff-flows", + "[ ufid | -n | -f | -i | check | stop | { -h | --help } ]", 0, + DUMP_HINIC3_FLOWS_PARAM, hinic3_agent_dump_hinic3_emc_flows, NULL); + hinic3_pthread_mutex_init(&dump_flows_mgmt.mutex_lock); +diff --git a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +index 7fdf61fc46..c120e0c130 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +@@ -310,7 +310,7 @@ static struct hinic3_command_info g_hinic3_command_info[] = { + {"hwoff/exec-cmd", "This command is used to issue or query OVS driver information for debugging."}, + {"hwoff/show-flow-api", "This API is used to query the hardware flow table."}, + {"hwoff/show-error-stats", "Indicates the error information recorded during flow table unloading."}, +- {"hwoff/dump-hinic3-flows", "Queries hardware flow table information."}, ++ {"hwoff/dump-hwoff-flows", "Queries hardware flow table information."}, + {"hwoff/flow-offload-speed-stat", "Collects statistics on or queries the flow table offloading rate."}, + {"hwoff/show-offload-flow-num", + "This command is used to query the number of flow tables that are unloaded (software statistics)."}, +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c +index a7d57b47ff..460a316fd8 100644 +--- a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c +@@ -39,6 +39,7 @@ + #include "hinic3_agent_cmd.h" + #include "hinic3_error_stats.h" + #include "hinic3_agent.h" ++#include "rte_pmd_hinic3.h" + + static bool g_agent_construct_init = false; + +@@ -286,7 +287,7 @@ static void hinic3_post_uninit(void) + (void)hinic3_command_mgr_uninit(); + } + +-__attribute__((constructor(HINIC3_PRIORITY_LAST))) int hinic3_agent_construct(void) ++int hinic3_agent_construct(void) + { + int ret; + +@@ -326,7 +327,7 @@ __attribute__((constructor(HINIC3_PRIORITY_LAST))) int hinic3_agent_construct(vo + return -1; + } + +-__attribute__((destructor(HINIC3_PRIORITY_LAST))) void hinic3_agent_destruct(void) ++void hinic3_agent_destruct(void) + { + hinic3_net_qos_clear(); + hinic3_post_uninit(); +-- +2.47.0.windows.2 + diff --git a/0100-fix-warning.patch b/0100-fix-warning.patch new file mode 100644 index 0000000000000000000000000000000000000000..a468031ec3ffaf051c451b8a4ab0fa22d549298f --- /dev/null +++ b/0100-fix-warning.patch @@ -0,0 +1,3883 @@ +From aa9b3a6f5a359de1af7b1f3282c5fc91f84f00af Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Fri, 4 Jul 2025 19:49:28 +0800 +Subject: [PATCH] fix-warning + +--- + drivers/net/hinic3/include/dpak_cfg.h | 2 +- + drivers/net/hinic3/meson.build | 2 +- + .../hinic3/scripts/dpak_ovs_completion_ovs.sh | 32 +++++----- + .../src/common/hinic3_cfg/ovs_dpu_virt.c | 2 +- + .../hinic3/src/common/hinic3_ds/hinic3_ds.c | 2 +- + .../hinic3/src/common/hinic3_ds/hinic3_ds.h | 2 +- + .../src/common/hinic3_hmap/hinic3_hmap.c | 2 +- + .../hinic3/src/common/hinic3_log/hinic3_log.c | 42 ++++++------ + .../hinic3/src/common/hinic3_log/hinic3_log.h | 6 +- + .../src/common/hinic3_mutex/hinic3_mutex.c | 15 ++--- + .../common/hinic3_packets/hinic3_packets.h | 1 + + .../src/common/hinic3_smap/hinic3_shash.c | 33 +++------- + .../src/common/hinic3_smap/hinic3_shash.h | 2 +- + .../src/common/hinic3_smap/hinic3_smap.c | 6 +- + .../hinic3_string_util/hinic3_string_format.c | 40 ++++-------- + .../hinic3_string_util/hinic3_string_format.h | 28 ++++---- + .../hinic3_check_thread_health_state.h | 2 +- + .../src/common/hinic3_utils/hinic3_drv.h | 2 +- + .../common/hinic3_utils/hinic3_file_util.c | 6 +- + .../hinic3_utils/hinic3_hugepage_meminfo.c | 52 +++++++-------- + .../src/common/hinic3_utils/hinic3_map.h | 2 +- + .../src/common/hinic3_utils/hinic3_mutex.h | 10 +-- + .../src/common/hinic3_utils/hinic3_util.c | 17 +++-- + .../src/common/hinic3_utils/hinic3_util.h | 20 ++---- + .../hinic3_capture/hinic3_capture_command.c | 20 +++--- + .../hinic3_capture/hinic3_capture_filter.c | 36 +++++------ + .../hinic3_capture/hinic3_capture_filter.h | 6 +- + .../src/hinic3_capture/hinic3_capture_hooks.c | 1 + + .../src/hinic3_capture/hinic3_capture_main.c | 2 +- + .../src/hinic3_capture/hinic3_capture_save.c | 2 +- + .../src/hinic3_capture/hinic3_capture_utils.c | 12 ++-- + .../src/hinic3_capture/hinic3_capture_utils.h | 8 +-- + .../client/hinic3_command_client.c | 17 +---- + .../src/hinic3_cmds/comm/hinic3_agent_cmd.c | 5 +- + .../comm/hinic3_agent_cmd_format.c | 26 ++++---- + .../comm/hinic3_agent_flow_cmd_dump.c | 8 +-- + .../comm/hinic3_agent_flow_cmd_dump_file.c | 2 +- + .../comm/hinic3_agent_flow_cmd_speed.c | 4 +- + .../hinic3_cmds/comm/hinic3_cmd_error_stats.c | 2 +- + .../src/hinic3_cmds/comm/hinic3_cmd_forward.c | 2 +- + .../src/hinic3_cmds/comm/hinic3_cmd_version.c | 28 -------- + .../src/hinic3_cmds/comm/hinic3_cmd_version.h | 11 ---- + .../src/hinic3_cmds/comm/hinic3_trace_flow.c | 8 +-- + .../src/hinic3_cmds/comm/hinic3_vf_dfx.c | 50 +-------------- + .../src/hinic3_cmds/comm/hinic3_vf_dfx.h | 2 +- + .../comm/hinic3_vf_dfx_multi_qos.c | 24 +++---- + .../src/hinic3_cmds/server/hinic3_command.c | 37 ++++++----- + .../hinic3_driver_public.h | 2 +- + .../hinic3_driver_adapter/hinic3_iface_flow.c | 18 +++--- + .../hinic3_driver_adapter/hinic3_iface_flow.h | 2 +- + .../hinic3_iface_global.c | 64 ++++++++----------- + .../hinic3_driver_adapter/hinic3_iface_port.c | 14 ++-- + .../hinic3_driver_adapter/hinic3_iface_port.h | 2 +- + .../hinic3_iface_port_util.c | 29 +++++---- + .../comm/hinic3_offload_action_public.c | 9 +-- + .../hinic3_emc_dump/hinic3_flow_dump_action.c | 26 ++++---- + .../hinic3_emc_dump/hinic3_flow_dump_item.c | 6 +- + .../hinic3_flow_dump_item_key.c | 6 +- + .../hinic3_emc_dump/hinic3_flow_emc_dump.c | 8 +-- + .../hinic3_flow_delete/hinic3_ufid_del_flow.c | 63 ++++++++++++++++++ + .../hinic3_flow_delete/hinic3_ufid_del_flow.h | 9 +++ + .../hinic3_flow_dump/hinic3_flow_api.c | 2 +- + .../hinic3_flow_dump/hinic3_flow_dump.c | 4 +- + .../hinic3_flow_format/hinic3_flow_format.c | 24 +++---- + .../hinic3_flow_mirror/hinic3_flow_mirror.c | 22 +++---- + .../hinic3_flow_mirror/hinic3_flow_session.c | 2 +- + .../hinic3_flow_offload/hinic3_dump_flow.c | 2 +- + .../hinic3_offload_action.c | 3 +- + .../hinic3_flow_offload/hinic3_offload_flow.c | 25 ++------ + .../hinic3_flow_query/hinic3_key_query.c | 12 ++-- + .../hinic3_vxlan/hinic3_vxlan_dump.c | 2 +- + .../src/hinic3_init/comm/hinic3_agent.c | 2 +- + .../src/hinic3_init/comm/hinic3_flow_agent.c | 8 +-- + .../comm/hinic3_parse_agent_config.c | 2 +- + .../comm/hinic3_parse_agent_config.h | 4 +- + .../src/hinic3_ports/comm/hinic3_port_util.h | 1 + + .../hinic3_bond/hinic3_bond_controller.c | 2 +- + .../hinic3_ports/hinic3_vdev/hinic3_vdev.c | 4 +- + .../hinic3_vf/hinic3_function_statistics.c | 1 + + .../hinic3_vf/hinic3_vf_controller.c | 2 +- + .../hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c | 18 +++--- + .../hinic3_qos/multilevel_qos/hinic3_mtr.c | 10 +-- + .../multilevel_qos/hinic3_mtr_policy.c | 2 +- + .../hinic3_ufid_map/hinic3_mpool_rte_flow.h | 4 +- + .../src/hinic3_ufid_map/hinic3_ufid_hmap.c | 25 +++++++- + .../src/hinic3_ufid_map/hinic3_ufid_hmap.h | 2 +- + .../hinic3_ufid_map_rte_flow.c | 21 +++++- + .../hinic3_ufid_map_rte_flow.h | 1 + + 88 files changed, 526 insertions(+), 580 deletions(-) + delete mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c + delete mode 100644 drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.c + create mode 100644 drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.h + +diff --git a/drivers/net/hinic3/include/dpak_cfg.h b/drivers/net/hinic3/include/dpak_cfg.h +index 8e8b494490..64d82eb891 100644 +--- a/drivers/net/hinic3/include/dpak_cfg.h ++++ b/drivers/net/hinic3/include/dpak_cfg.h +@@ -92,6 +92,6 @@ struct hinic3_init_arg { + }; + + const char *hinic3_log_prefix_get(void); +-struct hinic3_init_arg *hinic3_get_fixed_config(); ++struct hinic3_init_arg *hinic3_get_fixed_config(void); + + #endif +diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build +index cbb26cdf2f..4eb5f5e76d 100644 +--- a/drivers/net/hinic3/meson.build ++++ b/drivers/net/hinic3/meson.build +@@ -55,7 +55,6 @@ sources = files( + 'src/hinic3_cmds/comm/hinic3_trace_flow.c', + 'src/hinic3_cmds/comm/hinic3_cmd_meminfo.c', + 'src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c', +- 'src/hinic3_cmds/comm/hinic3_cmd_version.c', + 'src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c', + 'src/hinic3_cmds/comm/hinic3_agent_cmd_time.c', + 'src/hinic3_cmds/comm/hinic3_cmd_error_stats.c', +@@ -96,6 +95,7 @@ sources = files( + 'src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c', + 'src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c', + 'src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c', ++ 'src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.c', + 'src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c', + 'src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c', + 'src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c', +diff --git a/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +index 488dc5e2fc..10380cbb94 100644 +--- a/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh ++++ b/drivers/net/hinic3/scripts/dpak_ovs_completion_ovs.sh +@@ -45,7 +45,6 @@ TOP_LEVEL_OPTS=( + hwoff/dump-qos-loss + hwoff/ufid-map-error-stats + hwoff/exec-cmd +- hinic3-agent-version + hwoff/flow-offload-speed-stat + hwoff/show-flow-api + hwoff/show-hmap-flow-num +@@ -55,7 +54,6 @@ TOP_LEVEL_OPTS=( + hwoff/dump-meter + hwoff/dump-flow-qos-loss + -h +- -v + ) + + RUN_TIME_MODE_OPTS=( +@@ -193,21 +191,21 @@ _complete_set_log_level() { + prev="${COMP_WORDS[COMP_CWORD-1]}" + prev2="${COMP_WORDS[COMP_CWORD-2]}" + local module_name=( +- hinic3-agent +- hinic3-vport +- hinic3-bond +- hinic3-flow +- hinic3-bum +- hinic3-qos +- hinic3-packet +- hinic3-driver-vport +- hinic3-driver-bond +- hinic3-driver-flow +- hinic3-driver-bum +- hinic3-driver-qos +- hinic3-driver-chip +- hinic3-driver-packet +- hinic3-offload-policy ++ hwoff-agent ++ hwoff-vport ++ hwoff-bond ++ hwoff-flow ++ hwoff-bum ++ hwoff-qos ++ hwoff-packet ++ hwoff-driver-vport ++ hwoff-driver-bond ++ hwoff-driver-flow ++ hwoff-driver-bum ++ hwoff-driver-qos ++ hwoff-driver-chip ++ hwoff-driver-packet ++ hwoff-offload-policy + ) + + local level=( +diff --git a/drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c b/drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c +index d77b928793..82c6ba6ba5 100644 +--- a/drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c ++++ b/drivers/net/hinic3/src/common/hinic3_cfg/ovs_dpu_virt.c +@@ -31,7 +31,7 @@ const char *hinic3_log_prefix_get(void) + return g_log_prefix; + } + +-struct hinic3_init_arg *hinic3_get_fixed_config() ++struct hinic3_init_arg *hinic3_get_fixed_config(void) + { + return &g_init_arg; + } +diff --git a/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c +index bfdb82d3ba..68dbd2940f 100644 +--- a/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c ++++ b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.c +@@ -19,7 +19,7 @@ void hinic3_ds_destroy(struct ds *ds) + } + } + +-char* hinic3_ds_cstr(struct ds *ds) ++const char* hinic3_ds_cstr(struct ds *ds) + { + if (ds == NULL) { + return "\0"; +diff --git a/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h +index c73810e888..c072074660 100644 +--- a/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h ++++ b/drivers/net/hinic3/src/common/hinic3_ds/hinic3_ds.h +@@ -27,7 +27,7 @@ void hinic3_ds_put_format(struct ds *ds, const char *format, ...); + /* 带缩进和前缀的格式化函数,indent_num为行首缩进数, prefix为前缀字符串 */ + void hinic3_ds_put_format_prefix(struct ds *ds, uint8_t indent_num, const char *prefix, const char *format, ...); + void hinic3_ds_destroy(struct ds *ds); +-char *hinic3_ds_cstr(struct ds *ds); ++const char *hinic3_ds_cstr(struct ds *ds); + + void hinic3_ds_clear(struct ds *ds); + char *hinic3_ds_put_uninit(struct ds *ds, size_t n); +diff --git a/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c +index 2f7c9e1292..7bde0da651 100644 +--- a/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c ++++ b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c +@@ -139,7 +139,7 @@ static size_t hinic3_calc_mask(size_t capacity) + return mask; + } + +-void hinic3_hmap_expand_at(struct hmap *hmap, const char *where, enum hinic3_module module_id) ++static void hinic3_hmap_expand_at(struct hmap *hmap, const char *where, enum hinic3_module module_id) + { + size_t new_mask = hinic3_calc_mask(hmap->n); + if (new_mask > hmap->mask) { +diff --git a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c +index 8a08d5daac..620a2bd696 100644 +--- a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c ++++ b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c +@@ -49,21 +49,21 @@ enum hinic3_log_level { + }; + + static struct hinic3_log_module g_hinic3_log_module_list[] = { +- {"hinic3-agent", HINIC3_LOG_TYPE_UP, HINIC3_LOG_AGENT, RTE_LOG_INFO}, +- {"hinic3-vport", HINIC3_LOG_TYPE_UP, HINIC3_LOG_VPORT, RTE_LOG_INFO}, +- {"hinic3-bond", HINIC3_LOG_TYPE_UP, HINIC3_LOG_BOND, RTE_LOG_INFO}, +- {"hinic3-flow", HINIC3_LOG_TYPE_UP, HINIC3_LOG_FLOW, RTE_LOG_INFO}, +- {"hinic3-bum", HINIC3_LOG_TYPE_UP, HINIC3_LOG_BUM, RTE_LOG_INFO}, +- {"hinic3-qos", HINIC3_LOG_TYPE_UP, HINIC3_LOG_QOS, RTE_LOG_INFO}, +- {"hinic3-packet", HINIC3_LOG_TYPE_UP, HINIC3_LOG_PACKET, RTE_LOG_INFO}, +- {"hinic3-driver-vport", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_VPORT, RTE_LOG_INFO}, +- {"hinic3-driver-bond", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_BOND, RTE_LOG_INFO}, +- {"hinic3-driver-flow", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_FLOW, RTE_LOG_INFO}, +- {"hinic3-driver-bum", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_BUM, RTE_LOG_INFO}, +- {"hinic3-driver-qos", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_QOS, RTE_LOG_INFO}, +- {"hinic3-driver-chip", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_CHIP, RTE_LOG_INFO}, +- {"hinic3-driver-packet", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_PACKET, RTE_LOG_INFO}, +- {"hinic3-offload-policy", HINIC3_LOG_TYPE_UP, HINIC3_LOG_POLICY, RTE_LOG_INFO} ++ {"hwoff-agent", HINIC3_LOG_TYPE_UP, HINIC3_LOG_AGENT, RTE_LOG_INFO}, ++ {"hwoff-vport", HINIC3_LOG_TYPE_UP, HINIC3_LOG_VPORT, RTE_LOG_INFO}, ++ {"hwoff-bond", HINIC3_LOG_TYPE_UP, HINIC3_LOG_BOND, RTE_LOG_INFO}, ++ {"hwoff-flow", HINIC3_LOG_TYPE_UP, HINIC3_LOG_FLOW, RTE_LOG_INFO}, ++ {"hwoff-bum", HINIC3_LOG_TYPE_UP, HINIC3_LOG_BUM, RTE_LOG_INFO}, ++ {"hwoff-qos", HINIC3_LOG_TYPE_UP, HINIC3_LOG_QOS, RTE_LOG_INFO}, ++ {"hwoff-packet", HINIC3_LOG_TYPE_UP, HINIC3_LOG_PACKET, RTE_LOG_INFO}, ++ {"hwoff-driver-vport", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_VPORT, RTE_LOG_INFO}, ++ {"hwoff-driver-bond", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_BOND, RTE_LOG_INFO}, ++ {"hwoff-driver-flow", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_FLOW, RTE_LOG_INFO}, ++ {"hwoff-driver-bum", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_BUM, RTE_LOG_INFO}, ++ {"hwoff-driver-qos", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_QOS, RTE_LOG_INFO}, ++ {"hwoff-driver-chip", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_CHIP, RTE_LOG_INFO}, ++ {"hwoff-driver-packet", HINIC3_LOG_TYPE_DRIVER, HINIC3_DRIVER_LOG_PACKET, RTE_LOG_INFO}, ++ {"hwoff-offload-policy", HINIC3_LOG_TYPE_UP, HINIC3_LOG_POLICY, RTE_LOG_INFO} + }; + + static struct hinic3_log_level_map g_hinic3_log_level_map[] = { +@@ -160,7 +160,7 @@ int hinic3_driver_log_init(void) + + int hinic3_set_module_log_level(struct set_log_level_input_key *g_input_key) + { +- char *module = g_input_key->module_name; ++ const char *module = g_input_key->module_name; + int level = g_input_key->log_level; + + size_t i; +@@ -310,7 +310,7 @@ static void hinic3_show_log_list(struct unixctl_conn *conn, int argc HINIC3_UNUS + return; + } + +-static int hinic3_key_module_name_parse(char *value, struct ds *ds) ++static int hinic3_key_module_name_parse(const char *value, struct ds *ds) + { + struct hinic3_log_module *module = NULL; + module = hinic3_get_log_module_name(value); +@@ -322,7 +322,7 @@ static int hinic3_key_module_name_parse(char *value, struct ds *ds) + return 0; + } + +-static int hinic3_key_log_level_parse(char *value, struct ds *ds) ++static int hinic3_key_log_level_parse(const char *value, struct ds *ds) + { + int log_level; + log_level = hinic3_get_log_level_from_name(value); +@@ -338,7 +338,7 @@ static struct set_log_level_sub_key_parser g_input_key_parser[] = { + {"-l", sizeof("-l"), hinic3_key_log_level_parse}, + }; + static int hinic3_set_log_level_sub_key_parse(struct unixctl_conn *conn, const char *key_name, +- char *value, struct ds *ds) ++ const char *value, struct ds *ds) + { + size_t i = 0; + int ret = 0; +@@ -377,7 +377,7 @@ static int hinic3_set_log_level_input_key_parse(struct unixctl_conn *conn, int a + const char **work_argv = argv; + + while (i < work_argc) { +- ret = hinic3_set_log_level_sub_key_parse(conn, (char *)work_argv[i], (char *)work_argv[i + 1], ds); ++ ret = hinic3_set_log_level_sub_key_parse(conn, (const char *)work_argv[i], (const char *)work_argv[i + 1], ds); + if (ret != 0) { + HINIC3_LOG(ERR, AGENT, "key_parse error\n"); + return -1; +@@ -463,7 +463,7 @@ static bool token_bucket_withdraw(struct token_bucket *tb, unsigned int n) + return true; + } + +-bool hinic3_log_is_enabled(uint32_t level, uint32_t logtype) ++static bool hinic3_log_is_enabled(uint32_t level, uint32_t logtype) + { + for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); ++i) { + if (logtype == g_hinic3_log_module_list[i].index) { +diff --git a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h +index b24b707e57..0ada9223c8 100644 +--- a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h ++++ b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.h +@@ -56,11 +56,11 @@ enum hinic3_log_type_e { + }; + + struct set_log_level_input_key { +- char *module_name; ++ const char *module_name; + int log_level; + }; + +-typedef int (*set_log_level_sub_key_parse_func)(char *value, struct ds *ds); ++typedef int (*set_log_level_sub_key_parse_func)(const char *value, struct ds *ds); + + struct set_log_level_sub_key_parser { + const char *key_name; +@@ -69,7 +69,7 @@ struct set_log_level_sub_key_parser { + }; + + struct hinic3_log_module { +- char *name; ++ const char *name; + int type; + int index; + int def_level; +diff --git a/drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c b/drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c +index ae5972d5d3..da56be61f5 100644 +--- a/drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c ++++ b/drivers/net/hinic3/src/common/hinic3_mutex/hinic3_mutex.c +@@ -89,9 +89,8 @@ int hinic3_rwlock_tryrdlock(struct hinic3_rwlock *lock) + return pthread_rwlock_tryrdlock(&lock->lock); + } + +-int hinic3_mutex_cond_wait(pthread_cond_t *cond, const struct hinic3_mutex *mutex_) ++int hinic3_mutex_cond_wait(pthread_cond_t *cond, struct hinic3_mutex *mutex) + { +- struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); + int ret = pthread_cond_wait(cond, &mutex->lock); + if (ret != 0) { + HINIC3_LOG(INFO, AGENT, "hinic3 cond wait failed, ret is %d\n", ret); +@@ -99,9 +98,8 @@ int hinic3_mutex_cond_wait(pthread_cond_t *cond, const struct hinic3_mutex *mute + return ret; + } + +-int hinic3_pthread_mutex_init(const struct hinic3_mutex *mutex_) ++int hinic3_pthread_mutex_init(struct hinic3_mutex *mutex) + { +- struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); + int ret = pthread_mutex_init(&mutex->lock, NULL); + if (ret != 0) { + HINIC3_LOG(INFO, AGENT, "hinic3 mutex init failed, ret is %d\n", ret); +@@ -109,9 +107,8 @@ int hinic3_pthread_mutex_init(const struct hinic3_mutex *mutex_) + return ret; + } + +-int hinic3_pthread_mutex_lock(const struct hinic3_mutex *mutex_) ++int hinic3_pthread_mutex_lock(struct hinic3_mutex *mutex) + { +- struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); + int ret = pthread_mutex_lock(&mutex->lock); + if (ret != 0) { + HINIC3_LOG(INFO, AGENT, "hinic3 mutex lock failed, ret is %d\n", ret); +@@ -119,9 +116,8 @@ int hinic3_pthread_mutex_lock(const struct hinic3_mutex *mutex_) + return ret; + } + +-int hinic3_pthread_mutex_unlock(const struct hinic3_mutex *mutex_) ++int hinic3_pthread_mutex_unlock(struct hinic3_mutex *mutex) + { +- struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); + int ret = pthread_mutex_unlock(&mutex->lock); + if (ret != 0) { + HINIC3_LOG(INFO, AGENT, "hinic3 mutex unlock failed, ret is %d\n", ret); +@@ -129,9 +125,8 @@ int hinic3_pthread_mutex_unlock(const struct hinic3_mutex *mutex_) + return ret; + } + +-int hinic3_pthread_mutex_destroy(const struct hinic3_mutex *mutex_) ++int hinic3_pthread_mutex_destroy(struct hinic3_mutex *mutex) + { +- struct hinic3_mutex* mutex = HINIC3_CONST_CAST(struct hinic3_mutex*, mutex_); + int ret = pthread_mutex_destroy(&mutex->lock); + if (ret != 0) { + HINIC3_LOG(INFO, AGENT, "hinic3 mutex destroy failed, ret is %d\n", ret); +diff --git a/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h b/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h +index 0351ee9e26..fabc5a55da 100644 +--- a/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h ++++ b/drivers/net/hinic3/src/common/hinic3_packets/hinic3_packets.h +@@ -7,6 +7,7 @@ + + #include "hinic3_packets_types.h" + #include "hinic3_meminfo.h" ++#include "hinic3_ds.h" + + void hinic3_ipv6_format_addr(const struct in6_addr *addr, struct ds *s); + +diff --git a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c +index 771660453f..f045cf3a6e 100644 +--- a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c ++++ b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.c +@@ -26,7 +26,7 @@ void hinic3_shash_init(struct shash *sh) + hinic3_hmap_init(&sh->map); + } + +-void hinic3_shash_clear(struct shash *sh) ++static void hinic3_shash_clear(struct shash *sh) + { + struct shash_node *node, *next; + +@@ -59,14 +59,14 @@ void hinic3_shash_clear_free_data(struct shash *sh) + + HINIC3_SHASH_FOR_EACH_SAFE (node, next, sh) { + hinic3_hmap_remove(&sh->map, &node->node); +- hinic3_free(node->data); ++ hinic3_free((void *)(uintptr_t)node->data); + hinic3_free(node->name); + hinic3_free(node); + } + } + + static struct shash_node* hinic3_shash_add_nocopy__(struct shash *sh, char *name, +- void *data, size_t hash, enum hinic3_module module_id) ++ const void *data, size_t hash, enum hinic3_module module_id) + { + struct shash_node *node = NULL; + +@@ -83,12 +83,12 @@ static struct shash_node* hinic3_shash_add_nocopy__(struct shash *sh, char *name + return node; + } + +-struct shash_node* hinic3_shash_add_nocopy(struct shash *sh, char *name, void *data, enum hinic3_module module_id) ++static struct shash_node* hinic3_shash_add_nocopy(struct shash *sh, char *name, const void *data, enum hinic3_module module_id) + { + return hinic3_shash_add_nocopy__(sh, name, data, hinic3_hash_name(name), module_id); + } + +-struct shash_node* hinic3_shash_add(struct shash *sh, const char *name, void *data, enum hinic3_module module_id) ++static struct shash_node* hinic3_shash_add(struct shash *sh, const char *name, const void *data, enum hinic3_module module_id) + { + return hinic3_shash_add_nocopy(sh, hinic3_xstrdup(name, module_id), data, module_id); + } +@@ -96,7 +96,7 @@ struct shash_node* hinic3_shash_add(struct shash *sh, const char *name, void *da + bool hinic3_shash_add_once(struct shash *sh, const char *name, const void *data, enum hinic3_module module_id) + { + if (!hinic3_shash_find(sh, name)) { +- hinic3_shash_add(sh, name, (void*)data, module_id); ++ hinic3_shash_add(sh, name, data, module_id); + return true; + } else { + return false; +@@ -113,11 +113,6 @@ char* hinic3_shash_steal(struct shash *sh, struct shash_node *node) + return name; + } + +-void hinic3_shash_delete(struct shash *sh, struct shash_node *node) +-{ +- hinic3_free(hinic3_shash_steal(sh, node)); +-} +- + static struct shash_node* hinic3_shash_find__(const struct shash *sh, const char *name, + size_t name_len, size_t hash) + { +@@ -137,20 +132,8 @@ struct shash_node* hinic3_shash_find(const struct shash *sh, const char *name) + return hinic3_shash_find__(sh, name, strlen(name), hinic3_hash_name(name)); + } + +-void* hinic3_shash_find_data(const struct shash *sh, const char *name) ++const void* hinic3_shash_find_data(const struct shash *sh, const char *name) + { + struct shash_node *node = hinic3_shash_find(sh, name); + return node ? node->data : NULL; +-} +- +-void* hinic3_shash_find_and_delete(struct shash *sh, const char *name) +-{ +- struct shash_node *node = hinic3_shash_find(sh, name); +- if (node) { +- void *data = node->data; +- hinic3_shash_delete(sh, node); +- return data; +- } else { +- return NULL; +- } +-} ++} +\ No newline at end of file +diff --git a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h +index 8fce7f84e4..9691bc663e 100644 +--- a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h ++++ b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_shash.h +@@ -21,7 +21,7 @@ + void hinic3_shash_init(struct shash *shash); + void hinic3_shash_destroy(struct shash *shash); + void hinic3_shash_destroy_free_data(struct shash *sh); +-void* hinic3_shash_find_data(const struct shash *shash, const char *name); ++const void* hinic3_shash_find_data(const struct shash *shash, const char *name); + struct shash_node* hinic3_shash_find(const struct shash *sh, const char *name); + bool hinic3_shash_add_once(struct shash *shash, const char *name, const void *data, enum hinic3_module module_id); + char* hinic3_shash_steal(struct shash *sh, struct shash_node *node); +diff --git a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c +index fc62fdee54..3fcd3bed06 100644 +--- a/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c ++++ b/drivers/net/hinic3/src/common/hinic3_smap/hinic3_smap.c +@@ -39,13 +39,13 @@ struct smap_node *hinic3_smap_add(struct smap *smap, const char *key, const char + hinic3_hash_bytes(key, key_len, 0), module_id); + } + +-struct smap_node *hinic3_smap_get_node(const struct smap *smap, const char *key) ++static struct smap_node *hinic3_smap_get_node(const struct smap *smap, const char *key) + { + size_t key_len = strlen(key); + return hinic3_smap_find__(smap, key, key_len, hinic3_hash_bytes(key, key_len, 0)); + } + +-void hinic3_smap_remove_node(struct smap *smap, struct smap_node *node) ++static void hinic3_smap_remove_node(struct smap *smap, struct smap_node *node) + { + hinic3_hmap_remove(&smap->map, &node->node); + hinic3_free(node->key); +@@ -62,7 +62,7 @@ void hinic3_smap_clear(struct smap *smap) + } + } + +-const char* hinic3_smap_get_def(const struct smap *smap, const char *key, const char *def) ++static const char* hinic3_smap_get_def(const struct smap *smap, const char *key, const char *def) + { + struct smap_node *node = hinic3_smap_get_node(smap, key); + return node ? node->value : def; +diff --git a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c +index d4283ff321..a72752f6de 100644 +--- a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c ++++ b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.c +@@ -23,7 +23,7 @@ + + typedef struct rte_flow_item *(*pattern_func)(struct input_key *); + rte_be16_t g_set_inner_type = 0; +-int hinic3_key_sip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_sip_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + +@@ -48,7 +48,7 @@ int hinic3_key_sip_parse(struct pcap_key_t *cap_key, const char *key_name, char + return 0; + } + +-int hinic3_key_dip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_dip_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + +@@ -73,7 +73,7 @@ int hinic3_key_dip_parse(struct pcap_key_t *cap_key, const char *key_name, char + return 0; + } + +-int hinic3_key_smac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_smac_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + struct eth_address addr = { 0 }; +@@ -95,7 +95,7 @@ int hinic3_key_smac_parse(struct pcap_key_t *cap_key, const char *key_name, char + return 0; + } + +-int hinic3_key_dmac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_dmac_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + struct eth_address addr = { 0 }; +@@ -117,7 +117,7 @@ int hinic3_key_dmac_parse(struct pcap_key_t *cap_key, const char *key_name, char + return 0; + } + +-int hinic3_key_eth_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_eth_type_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + uint32_t tmp_value; +@@ -151,7 +151,7 @@ int hinic3_key_eth_type_parse(struct pcap_key_t *cap_key, const char *key_name, + return 0; + } + +-int hinic3_key_ip_proto_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_ip_proto_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + +@@ -170,7 +170,7 @@ int hinic3_key_ip_proto_parse(struct pcap_key_t *cap_key, const char *key_name, + return 0; + } + +-int hinic3_key_sport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_sport_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint32_t sport_value; + char *endPtr = NULL; +@@ -201,7 +201,7 @@ int hinic3_key_sport_parse(struct pcap_key_t *cap_key, const char *key_name, cha + return 0; + } + +-int hinic3_key_dport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_dport_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint32_t dport_value; + char *endPtr = NULL; +@@ -232,7 +232,7 @@ int hinic3_key_dport_parse(struct pcap_key_t *cap_key, const char *key_name, cha + return 0; + } + +-int hinic3_key_vlan_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_vlan_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint32_t vlan_value; + char *endPtr = NULL; +@@ -262,7 +262,7 @@ int hinic3_key_vlan_parse(struct pcap_key_t *cap_key, const char *key_name, char + return 0; + } + +-int hinic3_key_vni_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_vni_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint32_t vni_value; + char *endPtr = NULL; +@@ -298,7 +298,7 @@ rte_be16_t hinic3_get_inter_type(void) + return g_set_inner_type; + } + +-int hinic3_key_port_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_port_id_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint32_t port_id; + char *endPtr = NULL; +@@ -329,7 +329,7 @@ int hinic3_key_port_id_parse(struct pcap_key_t *cap_key, const char *key_name, c + return 0; + } + +-int hinic3_key_icmp_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_icmp_type_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint8_t icmp_type; + char *endPtr = NULL; +@@ -345,15 +345,11 @@ int hinic3_key_icmp_type_parse(struct pcap_key_t *cap_key, const char *key_name, + return -1; + } + +- if (icmp_type > UINT8_MAX) { +- hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); +- return -1; +- } + cap_key->icmp_type = icmp_type; + return 0; + } + +-int hinic3_key_icmp_code_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_icmp_code_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint8_t icmp_code; + char *endPtr = NULL; +@@ -370,15 +366,11 @@ int hinic3_key_icmp_code_parse(struct pcap_key_t *cap_key, const char *key_name, + return -1; + } + +- if (icmp_code > UINT8_MAX) { +- hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); +- return -1; +- } + cap_key->icmp_code = icmp_code; + return 0; + } + +-int hinic3_key_icmp_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++int hinic3_key_icmp_id_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + uint16_t icmp_id; + char *endPtr = NULL; +@@ -394,10 +386,6 @@ int hinic3_key_icmp_id_parse(struct pcap_key_t *cap_key, const char *key_name, c + return -1; + } + +- if (icmp_id > UINT16_MAX) { +- hinic3_ds_put_format(ds, "%sValue of parameter \"%s\" is invalid!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); +- return -1; +- } + cap_key->icmp_id = (uint16_t)htons((uint16_t)icmp_id); + cap_key->icmp_id = htons(icmp_id); + return 0; +diff --git a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h +index ab75cfed55..58d7c6d5ef 100644 +--- a/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h ++++ b/drivers/net/hinic3/src/common/hinic3_string_util/hinic3_string_format.h +@@ -7,19 +7,19 @@ + + #include "hinic3_capture_utils.h" + +-int hinic3_key_sip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_dip_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_smac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_dmac_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_eth_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_ip_proto_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_sport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_dport_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_vlan_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_vni_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_port_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_icmp_type_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_icmp_code_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-int hinic3_key_icmp_id_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++int hinic3_key_sip_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_dip_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_smac_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_dmac_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_eth_type_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_ip_proto_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_sport_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_dport_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_vlan_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_vni_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_port_id_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_icmp_type_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_icmp_code_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++int hinic3_key_icmp_id_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); + rte_be16_t hinic3_get_inter_type(void); + #endif +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h +index 241719f2d9..c366452007 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.h +@@ -30,7 +30,7 @@ enum check_thread_item_type { + + struct hinic3_thread_name { + enum check_thread_item_type thread_id; +- char *thread_name; ++ const char *thread_name; + }; + + int hinic3_check_thread_health_state(void); +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h +index cf0ba3bc2b..6185fc22db 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_drv.h +@@ -17,7 +17,7 @@ + + + struct hinic3_drv_ops_map { +- char *name; ++ const char *name; + void **func; + }; + +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c +index 9635cedcbf..4061c2c15a 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_file_util.c +@@ -44,7 +44,7 @@ static int hinic3_get_absolute_file_path(const char *file_name, char *absolute_p + return 0; + } + +-static bool hinic3_check_directory_existence(char *path) ++static bool hinic3_check_directory_existence(const char *path) + { + struct stat info; + +@@ -62,7 +62,7 @@ static bool hinic3_check_directory_existence(char *path) + return (info.st_mode & S_IFDIR) ? true : false; + } + +-static int hinic3_mkdir(char *path) ++static int hinic3_mkdir(const char *path) + { + char dir_path[PATH_MAX]; + int ret; +@@ -81,7 +81,7 @@ static int hinic3_mkdir(char *path) + return 0; + } + +-static int hinic3_check_directory(char *path) ++static int hinic3_check_directory(const char *path) + { + if (hinic3_check_directory_existence(path) == true) { + return 1; +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c +index 55346db350..2d47eb0e37 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_hugepage_meminfo.c +@@ -10,25 +10,25 @@ + + static struct hinic3_hugepage_mem_statistics g_hugepage_mem_statistics = {0}; + static struct hinic3_module_name g_module_name[] = { +- {HINIC3_COMMON_RESOURCE, "hinic3-common-resource"}, +- {HINIC3_CAPTURE, "hinic3-capture"}, +- {HINIC3_COMMAND, "hinic3-command"}, +- {HINIC3_CT_OFFLOAD, "hinic3-ct-offload"}, +- {HINIC3_DRIVER_ADAPTER, "hinic3-driver-adapter"}, +- {HINIC3_FLOWS, "hinic3-flows"}, +- {HINIC3_OVS_FLOW, "hinic3-ovs-flows"}, +- {HINIC3_INIT, "hinic3-init"}, +- {HINIC3_POLICY, "hinic3-policy"}, +- {HINIC3_PORTS, "hinic3-ports"}, +- {HINIC3_QOS, "hinic3-qos"}, +- {HINIC3_SECURITY_FILTER, "hinic3-security-filter"}, +- {HINIC3_UFID_MAP, "hinic3-ufid-map"}, +- {HINIC3_OVS_MEMPOOL, "hinic3-ovs-mempool"}, +- {HINIC3_OVS_UFID_MEMPOOL, "hinic3-ovs-ufid-mempool"}, +- {HINIC3_OVS_UFID_MAP, "hinic3-ovs-ufid-map"}, +- {HINIC3_PACKET_PARSE, "hinic3-packet-parse"}, +- {HINIC3_OVS_SMAC, "hinic3-ovs-smac"}, +- {HINIC3_OVS_HINIC3_PRIVATE, "hinic3-ovs-private-data"}, ++ {HINIC3_COMMON_RESOURCE, "hwoff-common-resource"}, ++ {HINIC3_CAPTURE, "hwoff-capture"}, ++ {HINIC3_COMMAND, "hwoff-command"}, ++ {HINIC3_CT_OFFLOAD, "hwoff-ct-offload"}, ++ {HINIC3_DRIVER_ADAPTER, "hwoff-driver-adapter"}, ++ {HINIC3_FLOWS, "hwoff-flows"}, ++ {HINIC3_OVS_FLOW, "hwoff-ovs-flows"}, ++ {HINIC3_INIT, "hwoff-init"}, ++ {HINIC3_POLICY, "hwoff-policy"}, ++ {HINIC3_PORTS, "hwoff-ports"}, ++ {HINIC3_QOS, "hwoff-qos"}, ++ {HINIC3_SECURITY_FILTER, "hwoff-security-filter"}, ++ {HINIC3_UFID_MAP, "hwoff-ufid-map"}, ++ {HINIC3_OVS_MEMPOOL, "hwoff-ovs-mempool"}, ++ {HINIC3_OVS_UFID_MEMPOOL, "hwoff-ovs-ufid-mempool"}, ++ {HINIC3_OVS_UFID_MAP, "hwoff-ovs-ufid-map"}, ++ {HINIC3_PACKET_PARSE, "hwoff-packet-parse"}, ++ {HINIC3_OVS_SMAC, "hwoff-ovs-smac"}, ++ {HINIC3_OVS_HINIC3_PRIVATE, "hwoff-ovs-private-data"}, + {HIOVS_MEM, "hiovs-mem"}, + {HINIC3_MODULE_MAX, "unknown module"}, + }; +@@ -129,15 +129,15 @@ void hinic3_hugepage_meminfo_uninit(void) + hinic3_rwlock_destroy(&g_hugepage_mem_statistics.heap_meminfo.rwlock); + } + +-int hinic3_record_hugepage_meminfo(void *addr, enum hinic3_module module_id) ++static int hinic3_record_hugepage_meminfo(void *addr, enum hinic3_module module_id) + { +- void *elem = addr - MALLOC_ELEM_HEADER_LEN; ++ void *elem = (void *)((uintptr_t)addr - MALLOC_ELEM_HEADER_LEN); + size_t elem_size = ((struct malloc_elem *)elem)->size; + if (elem_size < MALLOC_ELEM_TRAILER_LEN + sizeof(struct hinic3_module_id)) { + HINIC3_LOG(ERR, AGENT, "failed to record hugepage meminfo"); + return -EINVAL; + } +- struct hinic3_module_id *module_info = (struct hinic3_module_id *)(elem + ++ struct hinic3_module_id *module_info = (struct hinic3_module_id *)((uintptr_t)elem + + elem_size - MALLOC_ELEM_TRAILER_LEN - sizeof(struct hinic3_module_id)); + + module_info->module_id = module_id; +@@ -251,13 +251,13 @@ void hinic3_rte_free(void *addr) + return; + } + +- void *elem = addr - MALLOC_ELEM_HEADER_LEN; ++ void *elem = (void *)((uintptr_t)addr - MALLOC_ELEM_HEADER_LEN); + size_t elem_size = ((struct malloc_elem *)elem)->size; + if (elem_size < MALLOC_ELEM_TRAILER_LEN + sizeof(struct hinic3_module_id)) { + HINIC3_LOG(ERR, AGENT, "failed to free memory, input wrong addr"); + return; + } +- struct hinic3_module_id *module_info = (struct hinic3_module_id *)(elem + ++ struct hinic3_module_id *module_info = (struct hinic3_module_id *)((uintptr_t)elem + + elem_size - MALLOC_ELEM_TRAILER_LEN - sizeof(struct hinic3_module_id)); + if (module_info->module_id >= HINIC3_MODULE_MAX) { + HINIC3_LOG(ERR, AGENT, "failed to free memory, parse module_id error"); +@@ -276,7 +276,7 @@ void hinic3_rte_free(void *addr) + return; + } + +-int hinic3_record_memzone_info(const struct rte_memzone *mz, const char *name, size_t len, enum hinic3_module module_id) ++static int hinic3_record_memzone_info(const struct rte_memzone *mz, const char *name, size_t len, enum hinic3_module module_id) + { + struct hinic3_rte_memzone_ele *ptr = NULL; + ptr = (struct hinic3_rte_memzone_ele *)hinic3_malloc(sizeof(struct hinic3_rte_memzone_ele), HINIC3_COMMON_RESOURCE); +@@ -380,7 +380,7 @@ int hinic3_rte_memzone_free(const struct rte_memzone *mz) + return -EINVAL; + } + +-int hinic3_record_mempool_info(struct rte_mempool *mp, const char *name, unsigned private_data_size) ++static int hinic3_record_mempool_info(struct rte_mempool *mp, const char *name, unsigned private_data_size) + { + struct hinic3_rte_mempool_ele *ptr = NULL; + uint32_t unit_size = mp->elt_size + mp->header_size + mp->trailer_size; +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h +index b260759e17..f34abf22d7 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_map.h +@@ -33,7 +33,7 @@ struct smap_node { + struct shash_node { + struct hmap_node node; + char *name; +- void *data; ++ const void *data; + }; + + struct shash { +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h +index 39946effbc..c91f6ec625 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_mutex.h +@@ -42,11 +42,11 @@ int hinic3_rwlock_rdunlock(struct hinic3_rwlock *lock); + int hinic3_rwlock_wrlock(struct hinic3_rwlock *lock); + int hinic3_rwlock_wrunlock(struct hinic3_rwlock *lock); + int hinic3_rwlock_tryrdlock(struct hinic3_rwlock *lock); +-int hinic3_mutex_cond_wait(pthread_cond_t *cond, const struct hinic3_mutex *mutex_); +-int hinic3_pthread_mutex_init(const struct hinic3_mutex *mutex_); +-int hinic3_pthread_mutex_lock(const struct hinic3_mutex *mutex_); +-int hinic3_pthread_mutex_unlock(const struct hinic3_mutex *mutex_); +-int hinic3_pthread_mutex_destroy(const struct hinic3_mutex *mutex_); ++int hinic3_mutex_cond_wait(pthread_cond_t *cond, struct hinic3_mutex *mutex); ++int hinic3_pthread_mutex_init(struct hinic3_mutex *mutex); ++int hinic3_pthread_mutex_lock(struct hinic3_mutex *mutex); ++int hinic3_pthread_mutex_unlock(struct hinic3_mutex *mutex); ++int hinic3_pthread_mutex_destroy(struct hinic3_mutex *mutex); + bool hinic3_thread_once_start(struct hinic3_thread_once *once); + void hinic3_thread_once_done(struct hinic3_thread_once *once); + int hinic3_spinlock_init(struct hinic3_spinlock *lock, int pshared); +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c +index a4d4c5c98e..364225b951 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.c +@@ -106,7 +106,7 @@ char* hinic3_xvasprintf(const char *format, va_list args, enum hinic3_module mod + /* + * 功能描述: 将mac地址转换成字符串 + */ +-int smacs_stringfy(const struct eth_addr macs[], int n, char *str_macs, int str_macs_len) ++int smacs_stringfy(const struct eth_address *macs, int n, char *str_macs, int str_macs_len) + { + int off = 0; + int suc_len; +@@ -389,7 +389,7 @@ int check_valid_eth_type(const char *eth_type) + return 0; + } + +-int parse_mac(const char *mac, const struct eth_address *output_mac) ++int parse_mac(const char *mac, struct eth_address *output_mac) + { + int ret = 0; + size_t i; +@@ -398,15 +398,18 @@ int parse_mac(const char *mac, const struct eth_address *output_mac) + + for (i = 0; i < ARRAY_SIZE(g_mac_format); i++) { + ret = check_valid_mac(mac, g_mac_format[i].mac_fmt); +- if (ret == 0 && g_mac_format[i].mac_fmt != HINIC3_MAC_HYPHEN_SHORT_FMT) { +- success_len = sscanf(mac, g_mac_format[i].fmt_str, MAC_SCAN_ARGS(*output_mac)); ++ if (ret == 0 && g_mac_format[i].mac_fmt == HINIC3_MAC_HYPHEN_FMT) { ++ success_len = sscanf(mac, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &(*output_mac).ea[0], &(*output_mac).ea[1], &(*output_mac).ea[2], &(*output_mac).ea[3], &(*output_mac).ea[4], &(*output_mac).ea[5]); ++ break; ++ } else if (ret == 0 && g_mac_format[i].mac_fmt == HINIC3_MAC_COLON_FMT) { ++ success_len = sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &(*output_mac).ea[0], &(*output_mac).ea[1], &(*output_mac).ea[2], &(*output_mac).ea[3], &(*output_mac).ea[4], &(*output_mac).ea[5]); + break; + } else if (ret == 0 && g_mac_format[i].mac_fmt == HINIC3_MAC_HYPHEN_SHORT_FMT) { +- success_len = sscanf(mac, g_mac_format[i].fmt_str, MAC_SCAN_HYPHEN_SHORT_ARGS(eth_addr)); ++ success_len = sscanf(mac, "%hx-%hx-%hx", (short unsigned int *)&(eth_addr).ea[0], (short unsigned int *)&(eth_addr).ea[2], (short unsigned int *)&(eth_addr).ea[4]); + for (size_t j = 0; j < ARRAY_SIZE(output_mac->be16); j++) { + eth_addr.be16[j] = htons(eth_addr.be16[j]); + } +- memcpy((void *)output_mac->ea, (void *)eth_addr.ea, sizeof(uint8_t) * HINIC3_ETH_ADDR_LEN); ++ memcpy((void *)(uintptr_t)output_mac->ea, eth_addr.ea, sizeof(uint8_t) * HINIC3_ETH_ADDR_LEN); + break; + } + } +@@ -501,7 +504,7 @@ void hinic3_set_ctrl_thread_cpu_affinity(pthread_t *thread) + } + } + +-int hinic3_set_thread_name_by_str(char *name) ++int hinic3_set_thread_name_by_str(const char *name) + { + char thread_name[HINIC3_THREAD_NAME_MAX]; + size_t len = strnlen(name, sizeof(thread_name) - 1); +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h +index e355038260..ca5807985a 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_util.h +@@ -23,6 +23,7 @@ + #include "hinic3_packets_types.h" + #include "hinic3_meminfo.h" + #include "hinic3_flow_agent_enum.h" ++#include "hinic3_packets_types.h" + + #define CPUSET_DIGITAL_BASE 10 + #define STR_TO_DEC_NUM 10 +@@ -51,16 +52,10 @@ + #define RTE_LCORE_INDEX_CURRENT (rte_lcore_index(-1) < 0 ? 0 : rte_lcore_index(-1)) + #define HINIC3_OVS_GROUP_NAME "dpak_ovs" + +-#if __GNUC__ && !__CHECKER__ + #define HINIC3_UNUSED __attribute__((__unused__)) + #define HINIC3_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define HINIC3_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1) + #define HINIC3_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0) +-#else +-#define HINIC3_UNUSED +-#define HINIC3_WARN_UNUSED_RESULT +-#define HINIC3_UNLIKELY(CONDITION) (!!(CONDITION)) +-#endif + + #define HINIC3_PRIORITY_SYMBOL 101 + #define HINIC3_PRIORITY_CONFIG 110 +@@ -152,13 +147,6 @@ static inline int parse_str_to_value(const char *str, uint32_t *value) + #define HINIC3_CONTAINER_INIT(OBJECT, POINTER, MEMBER) \ + ((OBJECT) = NULL, HINIC3_CONTAINER_ASSIGN(OBJECT, POINTER, MEMBER)) + +-#define HINIC3_BUILD_ASSERT_TYPE(POINTER, TYPE) \ +- ((void)sizeof((int)((POINTER) == (TYPE)(POINTER)))) +- +-#define HINIC3_CONST_CAST(TYPE, POINTER) \ +- (HINIC3_BUILD_ASSERT_TYPE(POINTER, TYPE), \ +- (TYPE)(POINTER)) +- + #define HINIC3_CONTAINER_OF(POINTER, STRUCT, MEMBER) \ + ((STRUCT *) (void *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER))) + +@@ -195,7 +183,7 @@ struct hinic3_mac_transformat { + const char *fmt_str; + }; + +-int smacs_stringfy(const struct eth_addr macs[], int n, char *str_macs, int str_macs_len); ++int smacs_stringfy(const struct eth_address *macs, int n, char *str_macs, int str_macs_len); + int extra_eth_types_stringfy(const uint16_t types[], int n, char *str_types, int str_types_len); + int parse_src_to_src_macs(const char *str_macs, struct eth_addr macs[], int *n); + int parse_extra_eth_types_str(const char *str_types, uint16_t types[], int *n); +@@ -207,7 +195,7 @@ char *hinic3_strdup(const char *target_str, enum hinic3_module module_id); + char* hinic3_xvasprintf(const char *format, va_list args, enum hinic3_module module_id); + int pci_addr_format(const struct rte_pci_addr *pci_addr, char *buf, int buf_len); + +-int parse_mac(const char *mac, const struct eth_address *output_mac); ++int parse_mac(const char *mac, struct eth_address *output_mac); + int check_valid_mac(const char *mac, enum hinic3_mac_fmt fmt); + int check_valid_eth_type(const char *eth_type); + +@@ -215,6 +203,6 @@ long long int hinic3_time_msec(void); + long long int hinic3_time_sec(void); + void hinic3_set_ctrl_thread_cpu_affinity(pthread_t *thread); + int hinic3_set_single_cpu_affinity(pthread_t *thread, uint32_t core); +-int hinic3_set_thread_name_by_str(char *name); ++int hinic3_set_thread_name_by_str(const char *name); + + #endif +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +index 919c5f1484..e55589c662 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +@@ -100,7 +100,7 @@ static struct pcap_cmd_t g_cap_sub_commands[] = { + {"--help", "", pcap_cmd_help, 0, 0, NULL}, + }; + +-void ++static void + pcap_cmd_usage_print(struct ds *ds) + { + struct pcap_cmd_t *p_cmd = &g_cap_main_command; +@@ -108,7 +108,7 @@ pcap_cmd_usage_print(struct ds *ds) + hinic3_ds_put_cstr(ds, p_cmd->desc); + } + +-void ++static void + pcap_cmd_enable_capture(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, void *aux) + { + struct ds ds = DS_EMPTY_INITIALIZER; +@@ -120,7 +120,7 @@ pcap_cmd_enable_capture(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const + *(int *)aux = 0; + } + +-void ++static void + pcap_cmd_disable_capture(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] HINIC3_UNUSED, void *aux) + { + struct ds ds = DS_EMPTY_INITIALIZER; +@@ -137,7 +137,7 @@ pcap_stop_param_parse(int argc, const char *argv[], struct pcap_stop_param *para + { + int ret; + struct pcap_port_t port_info; +- char *port_name = NULL; ++ const char *port_name = NULL; + + if (strcmp("-pcap_id", argv[0]) == 0 && argc == PCAP_CMD_STOP_MAX_PARAM) { + param->pcap_id = strtoul(argv[PCAP_CMD_STOP_MAX_PARAM - 1], NULL, STR_TO_DEC_NUM); +@@ -149,7 +149,7 @@ pcap_stop_param_parse(int argc, const char *argv[], struct pcap_stop_param *para + } + + if (argc == PCAP_CMD_STOP_MIN_PARAM) { +- port_name = (char *)argv[0]; ++ port_name = (const char *)argv[0]; + memset(&port_info, 0, sizeof(port_info)); + ret = pcap_port_info_get_by_name(port_name, &port_info, ds); + if (ret != 0) +@@ -207,7 +207,7 @@ static int + pcap_task_start_prepare(int argc, const char *argv[], struct pcap_start_param *param, struct ds *ds, struct ds *save_param) + { + int ret; +- char *port_name = (char *)argv[0]; ++ const char *port_name = (const char *)argv[0]; + + ret = pcap_key_parse(¶m->pcap_key, argc, argv, ds, save_param); + if (ret != 0) +@@ -234,7 +234,7 @@ pcap_cmd_start(struct unixctl_conn *conn, int argc, const char *argv[], void *au + { + int ret; + uint32_t pcap_id; +- char *port_name = (char *)argv[0]; ++ const char *port_name = argv[0]; + struct pcap_start_param param; + struct ds ds = DS_EMPTY_INITIALIZER; + struct ds save_param = DS_EMPTY_INITIALIZER; +@@ -326,10 +326,10 @@ pcap_cmd_exec(struct unixctl_conn *conn, int argc, const char *argv[], void *aux + dst_sub_cmd->cb(conn, work_argc, work_argv, aux); + } + +-void ++static void + pcap_task_show_reply_format(struct pcap_task_t *task, struct ds *ds) + { +- char *tmp = NULL; ++ const char *tmp = NULL; + struct pcap_stats_t *stats = &task->stats; + + tmp = task->pcap_port.name; +@@ -343,7 +343,7 @@ pcap_task_show_reply_format(struct pcap_task_t *task, struct ds *ds) + hinic3_ds_put_format(ds, " parameters: %s\n", task->parameter); + } + +-void ++static void + pcap_all_tasks_show(struct ds *ds) + { + int i; +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +index d1c44faa20..61d414e630 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +@@ -24,10 +24,10 @@ + #define PCAP_BYTE_LEN 8 + #define PCAP_BIT_MASK 7 + +-static int pcap_key_count_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-static int pcap_key_dir_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-static int pcap_key_file_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); +-static int pcap_key_host_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++static int pcap_key_count_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++static int pcap_key_dir_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++static int pcap_key_file_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); ++static int pcap_key_host_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); + + static struct pcap_sub_key_parser g_pcap_sub_key_parser[] = { + {"-c", sizeof("-c"), pcap_key_count_parse}, +@@ -128,7 +128,7 @@ pcap_mask_parse(const char *mask_str, uint8_t *mask_len, uint32_t ip_type) + } + + int +-pcap_ip_mask_parse(char *value, struct pcap_ip_t *ip, uint8_t *mask_len, uint32_t *p_ip_type) ++pcap_ip_mask_parse(const char *value, struct pcap_ip_t *ip, uint8_t *mask_len, uint32_t *p_ip_type) + { + int ret; + uint32_t ip_type; +@@ -191,7 +191,7 @@ parse_l4_proto(const char *value, uint8_t *output) + } + + static int +-pcap_key_count_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++pcap_key_count_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + char *endPtr = NULL; + uint64_t count; +@@ -216,7 +216,7 @@ pcap_key_count_parse(struct pcap_key_t *cap_key, const char *key_name, char *val + } + + static int +-pcap_key_file_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++pcap_key_file_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + char *result = NULL; +@@ -272,7 +272,7 @@ pcap_key_file_parse(struct pcap_key_t *cap_key, const char *key_name, char *valu + } + + static int +-pcap_key_dir_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++pcap_key_dir_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + if ((cap_key->flags & PCAP_FLAG_KEY_DIRECTION) != 0) { + hinic3_ds_put_format(ds, "%sDuplicate parameter \"%s\"!\n", HINIC3_UI_LEADING_SIGN_ERROR, key_name); +@@ -295,7 +295,7 @@ pcap_key_dir_parse(struct pcap_key_t *cap_key, const char *key_name, char *value + } + + static int +-pcap_key_host_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++pcap_key_host_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + int ret; + +@@ -326,8 +326,8 @@ pcap_key_host_parse(struct pcap_key_t *cap_key, const char *key_name, char *valu + return 0; + } + +-int +-pcap_sub_key_parse(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds) ++static int ++pcap_sub_key_parse(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds) + { + size_t i; + int ret; +@@ -371,14 +371,14 @@ pcap_key_parse(struct pcap_key_t *cap_key, int argc, const char *argv[], struct + /* -xxx模式的参数 */ + if (strcmp("-vxlan_inner", work_argv[i]) == 0) { + cap_key->vxlan_inner = true; +- hinic3_ds_put_format(save_param, " %s", (char *)work_argv[i]); ++ hinic3_ds_put_format(save_param, " %s", (const char *)work_argv[i]); + i++; + continue; + } + + if (strcmp("-thread", work_argv[i]) == 0) { + cap_key->write_way = WRITE_BY_SEP_THREAD; +- hinic3_ds_put_format(save_param, " %s", (char *)work_argv[i]); ++ hinic3_ds_put_format(save_param, " %s", (const char *)work_argv[i]); + i++; + continue; + } +@@ -389,14 +389,14 @@ pcap_key_parse(struct pcap_key_t *cap_key, int argc, const char *argv[], struct + return -1; + } + +- ret = pcap_sub_key_parse(cap_key, (char *)work_argv[i], (char *)work_argv[i + 1], ds); ++ ret = pcap_sub_key_parse(cap_key, (const char *)work_argv[i], (const char *)work_argv[i + 1], ds); + if (ret != 0) + return -1; + + if (strcmp(work_argv[i], "-w") == 0) +- hinic3_ds_put_format(save_param, " %s %s", (char *)work_argv[i], cap_key->filename); ++ hinic3_ds_put_format(save_param, " %s %s", (const char *)work_argv[i], cap_key->filename); + else +- hinic3_ds_put_format(save_param, " %s %s", (char *)work_argv[i], (char *)work_argv[i + 1]); ++ hinic3_ds_put_format(save_param, " %s %s", (const char *)work_argv[i], (const char *)work_argv[i + 1]); + i += PCAP_DOUBLE; + } + +@@ -937,7 +937,7 @@ pcap_pkt_parse(struct pcap_pkt_summary *pkt_summary) + struct pcap_pkt_header *pkt_hdr = &pkt_summary->pkt_header; + + ctx->pkt_itr = pkt_summary->data; +- ctx->pkt_end = pkt_summary->data + pkt_summary->len; ++ ctx->pkt_end = (uint8_t *)pkt_summary->data + pkt_summary->len; + ctx->parse_result = true; + + /* outer protocol cluster */ +@@ -1120,7 +1120,7 @@ pcap_file_open(const char *file_name, const char *mode) + } + + int +-pcap_file_write_header(const FILE *file) ++pcap_file_write_header(FILE *file) + { + ssize_t ret; + struct pcap_hdr ph; +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h +index 999ea9fdfd..ae4ef52f42 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.h +@@ -136,7 +136,7 @@ struct pcap_pkt_summary { + struct pcap_pkt_header pkt_header; + }; + +-typedef int (*pcap_sub_key_parse_func)(struct pcap_key_t *cap_key, const char *key_name, char *value, struct ds *ds); ++typedef int (*pcap_sub_key_parse_func)(struct pcap_key_t *cap_key, const char *key_name, const char *value, struct ds *ds); + + struct pcap_sub_key_parser { + const char *key_name; +@@ -166,8 +166,8 @@ struct pcap_pkt_save_info { + int parse_l4_proto(const char *value, uint8_t *output); + void pcap_convert_key_to_driver_filter(struct pcap_task_t *task); + FILE *pcap_file_open(const char *file_name, const char *mode); +-int pcap_file_write_header(const FILE *file); +-int pcap_ip_mask_parse(char *value, struct pcap_ip_t *ip, uint8_t *mask_len, uint32_t *p_ip_type); ++int pcap_file_write_header(FILE *file); ++int pcap_ip_mask_parse(const char *value, struct pcap_ip_t *ip, uint8_t *mask_len, uint32_t *p_ip_type); + int pcap_key_parse(struct pcap_key_t *cap_key, int argc, const char *argv[], struct ds *ds, struct ds *save_param); + struct pcap_pkt_sub_hdr *pcap_pkt_dst_hdr_get(struct pcap_pkt_summary *buf, const struct pcap_key_t *key); + bool pcap_pkt_filter(struct pcap_pkt_summary *buf, struct pcap_key_t *key); +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c +index b33be8bb7f..6699f9df71 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_hooks.c +@@ -29,6 +29,7 @@ + #include "hinic3_check_thread_health_state.h" + #include "hinic3_cmd_exec.h" + #include "hinic3_ds.h" ++#include "hinic3_capture_main.h" + + void + pcap_hook_rx_pre(void) +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c +index a66844347f..f61ba9b409 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_main.c +@@ -61,7 +61,7 @@ hinic3_pcap_thread(void) + return 0; + } + +-int ++static int + hinic3_pcap_mem_pool_init(void) + { + int socket_id; +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +index 75e08f61c5..a7a9baec55 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +@@ -124,7 +124,7 @@ pcap_pkt_file_save(struct pcap_task_t *cap_task, uint64_t remain_cnt, struct pca + return; + } + +-void ++static void + pcap_epoll_event_process(uint32_t pcap_id) + { + uint32_t i; +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +index 3dcec18e5b..3f5d15e903 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +@@ -124,7 +124,7 @@ hinic3_get_port_info(uint16_t port_id, struct pcap_port_t *port_info) + } + + int +-pcap_port_info_get_by_name(char *port_name, struct pcap_port_t *port_info, struct ds *ds) ++pcap_port_info_get_by_name(const char *port_name, struct pcap_port_t *port_info, struct ds *ds) + { + int ret; + uint16_t port_id = 0; +@@ -174,7 +174,7 @@ pcap_timeout_check(uint64_t start_tsc, uint64_t timout_ms) + static void + pcap_task_stop_reply_format(struct pcap_task_t *task, struct ds *ds) + { +- char *tmp_str = NULL; ++ const char *tmp_str = NULL; + struct pcap_stats_t *stats = &task->stats; + + hinic3_ds_put_format(ds, "%2sstopped pcap id: %u \n", HINIC3_UI_INDENT_SPACE, task->pcap_id); +@@ -253,7 +253,7 @@ pcap_extract_start_reply(struct pcap_task_t *task, struct hinic3_nlattr *reply_n + int ret; + bool flag = false; + hinic3_nlattr_itr nla_itr = NULL; +- struct hinic3_pcap_probe_rule_q_map *rule_q_map = NULL; ++ const struct hinic3_pcap_probe_rule_q_map *rule_q_map = NULL; + + HINIC3_NLATTR_FOR_EACH (nla_itr, reply_nla) { + if (hinic3_nlattr_get_itr_type(nla_itr) == HINIC3_GLOBAL_CFG_ARG_PCAP_PROBE) { +@@ -266,7 +266,7 @@ pcap_extract_start_reply(struct pcap_task_t *task, struct hinic3_nlattr *reply_n + return -1; + } + +- rule_q_map = (struct hinic3_pcap_probe_rule_q_map *)hinic3_nlattr_get_itr_data(nla_itr); ++ rule_q_map = (const struct hinic3_pcap_probe_rule_q_map *)hinic3_nlattr_get_itr_data(nla_itr); + task->driver.queue_info.hinic3_dpdk_port_id = rule_q_map->hinic3_dpdk_port_id; + task->driver.queue_info.queue_id = rule_q_map->queue_id; + task->driver.queue_info.rule_idx = rule_q_map->rule_idx; +@@ -294,7 +294,7 @@ pcap_extract_stop_reply(struct pcap_task_t *task, struct hinic3_nlattr *reply_nl + int ret; + bool flag = false; + hinic3_nlattr_itr nla_itr = NULL; +- struct hinic3_pcap_probe_stats *hw_stats = NULL; ++ const struct hinic3_pcap_probe_stats *hw_stats = NULL; + + HINIC3_NLATTR_FOR_EACH (nla_itr, reply_nla) { + if (hinic3_nlattr_get_itr_type(nla_itr) == HINIC3_GLOBAL_GET_PCAP_PROBE_STATS) { +@@ -307,7 +307,7 @@ pcap_extract_stop_reply(struct pcap_task_t *task, struct hinic3_nlattr *reply_nl + return -1; + } + +- hw_stats = (struct hinic3_pcap_probe_stats *)hinic3_nlattr_get_itr_data(nla_itr); ++ hw_stats = (const struct hinic3_pcap_probe_stats *)hinic3_nlattr_get_itr_data(nla_itr); + task->stats.hinic3_stats.pkts_pcap_cnt = hw_stats->pkts_pcap_cnt; + task->stats.hinic3_stats.pkts_drop_cnt = hw_stats->pkts_drop_cnt; + +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h +index 7477896cd7..3b44472f78 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.h +@@ -208,12 +208,12 @@ struct pcap_task_batch { + }; + + struct pcap_cmd_t { +- char *cmd; +- char *usage; ++ const char *cmd; ++ const char *usage; + unixctl_cb_func *cb; + int min_args; + int max_args; +- char *desc; ++ const char *desc; + }; + + struct pcap_start_param { +@@ -259,7 +259,7 @@ int pcap_get_cap_switch(void); + struct pcap_task_mgr_t* pcap_get_task_mgr(void); + void pcap_port_tasks_get(struct pcap_task_batch *task_batch, struct pcap_port_t *port_mirror); + int pcap_port_tasks_count_no_lock(uint32_t port_no); +-int pcap_port_info_get_by_name(char *port_name, struct pcap_port_t *port_info, struct ds *ds); ++int pcap_port_info_get_by_name(const char *port_name, struct pcap_port_t *port_info, struct ds *ds); + void pcap_switch_set(int value); + int pcap_task_add(const struct pcap_port_t *port_info, struct pcap_key_t *pcap_key, uint32_t *pcap_id, + struct ds *save_param); +diff --git a/drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c b/drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c +index 6c5a52df3a..3b4926128d 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/client/hinic3_command_client.c +@@ -33,7 +33,7 @@ + #define MAX_REPLY_BUFFER_SIZE 1000 + #define CONNECT_FAILED_TIMEOUT 10 + #define RETRY_TIMES 3 +-#define HINIC3_DEFAULT_MAJOR_VERSION_STRING "(null)" ++#define HINIC3_DEFAULT_MAJOR_VERSION_STRING "25.0" + #define HINIC3_DEFAULT_SUB_VERSION_STRING "(null)" + + #ifdef BUILD_MAJOR_VERSION +@@ -53,15 +53,6 @@ enum command_error { + EXECUTION_ERROR = -3, + }; + +-static void +-hinic3_show_command_version_info(void) +-{ +- printf("%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_COMPONENT_NAME); +- printf("%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_COMMAND_FEATURE_NAME); +- printf("%2s%s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_COMPONENT_VERSION, HINIC3_BUILD_MAJOR_VERSION); +- return; +-} +- + static void + hinic3_show_command_help_info(void) + { +@@ -70,7 +61,6 @@ hinic3_show_command_help_info(void) + printf("%2sCommon commands:\n", HINIC3_UI_INDENT_SPACE); + printf("%4s%-30sList the commands supported by dpak-ovs\n\n", HINIC3_UI_INDENT_SPACE, "list-commands"); + printf("%2sOther options:\n", HINIC3_UI_INDENT_SPACE); +- printf("%4s%-30sDisplay the dpak-ovs-ctl version information\n", HINIC3_UI_INDENT_SPACE, "-v"); + printf("%4s%-30sDisplay the help information\n", HINIC3_UI_INDENT_SPACE, "-h, --help"); + } + +@@ -169,7 +159,7 @@ hinic3_client_print_response(FILE *file) + return res; + } + +-int ++static int + hinic3_get_confirm(const char *warningInfo) + { + char buf[MAX_COMMAND_LENGTH + 1] = {0}; +@@ -203,9 +193,6 @@ hinic3_check_client_args(int argc, char *argv[]) + if ((strcmp(argv[MIN_COMMAND_NUM - 1], "-h") == 0) || (strcmp(argv[MIN_COMMAND_NUM - 1], "--help") == 0)) { + (void)hinic3_show_command_help_info(); + return COMMAND_OPTION_MATCH; +- } else if (strcmp(argv[MIN_COMMAND_NUM - 1], "-v") == 0) { +- (void)hinic3_show_command_version_info(); +- return COMMAND_OPTION_MATCH; + } else { + printf("%s%s\n", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_NOT_SUPPORT_OPTION); + return -1; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c +index 47d04fd836..4d9a6c4371 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd.c +@@ -31,10 +31,11 @@ + #include "hinic3_parse_agent_config.h" + #include "hinic3_agent_flow_cmd_dump.h" + #include "hinic3_cmd_error_stats.h" +-#include "hinic3_cmd_version.h" + #include "hinic3_cmd_forward.h" + #include "hinic3_cmd_exec.h" + #include "hinic3_cmd_meminfo.h" ++#include "hinic3_agent_cmd.h" ++#include "hinic3_ufid_del_flow.h" + + #define HINIC3_BATCH_BOLCK_NUM 128 + #define HINIC3_DUMP_BATCH_MIN_ARGC 1 +@@ -56,7 +57,6 @@ void + hinic3_agent_cmd_init(void) + { + unixctl_hinic3_cmd_error_stats_register(); +- unixctl_hinic3_cmd_version_register(); + unixctl_hinic3_cmd_forward_register(); + unixctl_hinic3_cmd_exec_register(); + unixctl_hinic3_cmd_meminfo_register(); +@@ -71,4 +71,5 @@ hinic3_agent_cmd_init(void) + unixctl_thread_status_dfx_init(); + unixctl_common_cmd_register(); + unixctl_hinic3_query_cmd_init(); ++ unixctl_hinic3_delete_cmd_init(); + } +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c +index c72f3e6495..655370954e 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c +@@ -19,7 +19,7 @@ + #include "hinic3_agent_flow_cmd_dump.h" + #include "hinic3_flow_agent.h" + +-static char *g_ct_tcp_state_str[] = { ++static const char *g_ct_tcp_state_str[] = { + [HINIC3_TCP_STATE_TYPE_CLOSED] = HINIC3_UI_TCP_STATE_TYPE_CLOSE_STR, + [HINIC3_TCP_STATE_TYPE_LISTEN] = HINIC3_UI_TCP_STATE_TYPE_LISTEN_STR, + [HINIC3_TCP_STATE_TYPE_SYN_SENT] = HINIC3_UI_TCP_STATE_TYPE_SYN_SENT_STR, +@@ -95,7 +95,7 @@ static void + hinic3_flow_process_ipv6(const hinic3_nlattr_itr nla, int type, struct ds *ds) + { + const char *ip_string = (type == HINIC3_FLOW_KEY_SRC_IPV6) ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_DST_IP_STR; +- struct in6_addr *ipv6_addr = (struct in6_addr *)hinic3_nlattr_get_itr_data(nla); ++ const struct in6_addr *ipv6_addr = (const struct in6_addr *)hinic3_nlattr_get_itr_data(nla); + hinic3_ds_put_format(ds, "%s(", ip_string); + hinic3_ipv6_format_addr(ipv6_addr, ds); + hinic3_ds_put_format(ds, "), "); +@@ -132,7 +132,7 @@ static void + hinic3_flow_process_mac(const hinic3_nlattr_itr nla, int type, struct ds *ds) + { + const char *mac_string = (type == HINIC3_FLOW_KEY_SRC_MAC) ? HINIC3_UI_KEY_SRC_MAC_STR : HINIC3_UI_KEY_DST_MAC_STR; +- uint8_t *mac = (uint8_t *)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ const uint8_t *mac = (const uint8_t *)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); + hinic3_ds_put_format(ds, "%s(" HINIC3_MAC_FMT "), ", mac_string, HINIC3_OUTPUT_MAC(mac)); + } + +@@ -195,7 +195,7 @@ void hinic3_flow_key_format_output(const struct hinic3_nlattr *key, struct ds *d + static void + hinic3_ct_tcp_state_format_output(struct ds *ds, uint8_t ct_tcp_state) + { +- char *ct_tcp_state_name = NULL; ++ const char *ct_tcp_state_name = NULL; + if (ct_tcp_state <= HINIC3_TCP_STATE_TYPE_TIME_WAIT) { + ct_tcp_state_name = g_ct_tcp_state_str[ct_tcp_state]; + } else { +@@ -209,8 +209,8 @@ static void + hinic3_flow_process_ct_action(const hinic3_nlattr_itr nla, struct ds *ds) + { + struct ds ds_state = DS_EMPTY_INITIALIZER; +- struct hinic3_ct_tcp_state *ct_tcp_state = +- (struct hinic3_ct_tcp_state *)hinic3_nlattr_get_itr_unspec(nla, sizeof(struct hinic3_ct_tcp_state)); ++ const struct hinic3_ct_tcp_state *ct_tcp_state = ++ (const struct hinic3_ct_tcp_state *)hinic3_nlattr_get_itr_unspec(nla, sizeof(struct hinic3_ct_tcp_state)); + hinic3_ct_tcp_state_format_output(&ds_state, ct_tcp_state->state); + + hinic3_ds_put_format(ds, "%s(%s=%u, %s=%u, %s=%u, %s=%u, %s=%s), ", HINIC3_UI_KEY_CT_STR, HINIC3_UI_KEY_CT_SEQ_LOW_STR, +@@ -226,10 +226,10 @@ hinic3_flow_process_vxlan_push_action(const hinic3_nlattr_itr nla, struct ds *ds + { + size_t size; + uint32_t vni; +- struct hinic3_flow_act_vxlan_gpe_header *vxlan_header = NULL; ++ const struct hinic3_flow_act_vxlan_gpe_header *vxlan_header = NULL; + + size = sizeof(struct hinic3_flow_act_vxlan_gpe_header); +- vxlan_header = (struct hinic3_flow_act_vxlan_gpe_header *)hinic3_nlattr_get_itr_unspec(nla, size); ++ vxlan_header = (const struct hinic3_flow_act_vxlan_gpe_header *)hinic3_nlattr_get_itr_unspec(nla, size); + vni = ntohl(vxlan_header->vxlan.vni) >> HINIC3_BYTE_BITS; + + if (vxlan_header->ip_version == HINIC3_IP_ADDR_V4) { +@@ -283,7 +283,7 @@ hinic3_flow_process_set_mac_action(const hinic3_nlattr_itr nla, struct ds *ds) + enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); + const char *mac_string = + (type == HINIC3_FLOW_ACT_SET_SMAC) ? HINIC3_UI_KEY_VLAN_SET_SMAC_STR : HINIC3_UI_KEY_VLAN_SET_DMAC_STR; +- uint8_t *sd_mac = (uint8_t *)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ const uint8_t *sd_mac = (const uint8_t *)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); + hinic3_ds_put_format(ds, "%s(" HINIC3_MAC_FMT "), ", mac_string, HINIC3_OUTPUT_MAC(sd_mac)); + } + +@@ -304,7 +304,7 @@ hinic3_flow_process_set_ipv6_action(const hinic3_nlattr_itr nla, struct ds *ds) + enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); + const char *ip_string = + (type == HINIC3_FLOW_ACT_SET_SIPV6) ? HINIC3_UI_KEY_VLAN_SET_SIP_STR : HINIC3_UI_KEY_VLAN_SET_DIP_STR; +- struct in6_addr *ipv6_addr = (struct in6_addr *)hinic3_nlattr_get_itr_data(nla); ++ const struct in6_addr *ipv6_addr = (const struct in6_addr *)hinic3_nlattr_get_itr_data(nla); + hinic3_ds_put_format(ds, "%s(", ip_string); + hinic3_ipv6_format_addr(ipv6_addr, ds); + hinic3_ds_put_format(ds, "), "); +@@ -314,7 +314,7 @@ static void + hinic3_flow_process_set_u16_action(const hinic3_nlattr_itr nla, struct ds *ds) + { + enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); +- char *print_string = NULL; ++ const char *print_string = NULL; + uint16_t u16_val = hinic3_nlattr_get_itr_u16(nla); + switch (type) { + case HINIC3_FLOW_ACT_SET_SPORT: +@@ -353,7 +353,7 @@ hinic3_flow_process_show_set_priority_action(const hinic3_nlattr_itr nla, struct + static void + hinic3_flow_process_mirror_action(const hinic3_nlattr_itr nla, struct ds *ds) + { +- struct hiovs_mirror_info *mirror_info = (struct hiovs_mirror_info *)hinic3_nlattr_get_itr_data(nla); ++ const struct hiovs_mirror_info *mirror_info = (const struct hiovs_mirror_info *)hinic3_nlattr_get_itr_data(nla); + hinic3_ds_put_format(ds, "%s", HINIC3_UI_KEY_VLAN_MIRROR_STR); + if (mirror_info->ws.mirror_rx == 1) { + hinic3_ds_put_format(ds, "(session_id:%u, sport:%u, ratio:%u), ", mirror_info->sessions[0], +@@ -366,7 +366,7 @@ hinic3_flow_process_mirror_action(const hinic3_nlattr_itr nla, struct ds *ds) + + static void hinic3_flow_process_block_version_action(const hinic3_nlattr_itr nla, struct ds *ds) + { +- struct hinic3_flow_act_block_version *block = (struct hinic3_flow_act_block_version *)hinic3_nlattr_get_itr_data(nla); ++ const struct hinic3_flow_act_block_version *block = (const struct hinic3_flow_act_block_version *)hinic3_nlattr_get_itr_data(nla); + hinic3_ds_put_format(ds, "%s(%u), ", HINIC3_UI_ACTION_BLOCK_ID_STR, block->block_id); + hinic3_ds_put_format(ds, "%s(%u), ", HINIC3_UI_ACTION_BLOCK_VERSION_STR, block->block_version); + } +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +index 4b289dbd54..2a21ec66da 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +@@ -69,7 +69,7 @@ hinic3_cmd_set_flow_ops_status(enum hinic3_flow_type type) + g_hinic3_flow_dump_cmd.type = type; + } + +-void ++static void + hinic3_agent_dump_hinic3_emc_flow_init(void) + { + hinic3_cmd_set_flow_get_maxflows_ops(hinic3_flow_get_maxflows); +@@ -341,7 +341,7 @@ hinic3_agent_get_block_id_from_flow(const struct hinic3_dpif_flow_for_get *f, + { + struct hinic3_nlattr flow_actions; + hinic3_nlattr_itr nla = NULL; +- struct hinic3_flow_act_block_version *block = NULL; ++ const struct hinic3_flow_act_block_version *block = NULL; + + hinic3_nlattr_init(&flow_actions, f->actions, f->action_len); + hinic3_nlattr_reset_itr(&flow_actions, f->action_len); +@@ -349,7 +349,7 @@ hinic3_agent_get_block_id_from_flow(const struct hinic3_dpif_flow_for_get *f, + { + enum hinic3_flow_action_type type = (enum hinic3_flow_action_type)hinic3_nlattr_get_itr_type(nla); + if (type == HINIC3_FLOW_ACT_BLOCK_VERSION) { +- block = (struct hinic3_flow_act_block_version *)hinic3_nlattr_get_itr_data(nla); ++ block = (const struct hinic3_flow_act_block_version *)hinic3_nlattr_get_itr_data(nla); + if (return_block_id != NULL) { + *return_block_id = block->block_id; + } +@@ -436,7 +436,7 @@ hinic3_agent_dump_flows_by_block_id(int argc, const char *argv[], struct ds *ds) + return -1; + } + +- block_id_input = strtoul((char *)argv[ARGC - 1], &endPtr, DEC_BASE_NUM); ++ block_id_input = strtoul(argv[ARGC - 1], &endPtr, DEC_BASE_NUM); + if (block_id_input >= block_num || endPtr == NULL || *endPtr != '\0') { + hinic3_ds_put_format(ds, "%s%s\n", HINIC3_UI_LEADING_SIGN_ERROR, HINIC3_UI_FLOW_DUMP_BLOCK_ID_ERROR_STRING); + return -1; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +index 1b2cbf763a..5331bf27cf 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +@@ -175,7 +175,7 @@ hinic3_dump_flows_running_thread(void *args) + size_t len; + int ret; + +- char *name = "hinic3_dump_flow"; ++ const char *name = "hinic3_dump_flow"; + ret = hinic3_set_thread_name_by_str(name); + if (ret != 0) + HINIC3_LOG(WARNING, AGENT, "set dump flow thread name failed!"); +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c +index ab6c98b2eb..ec1cbb936c 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c +@@ -168,7 +168,7 @@ hinic3_speed_measure_thread(void *args) + { + struct hinic3_speed_measure_task_t *task = (struct hinic3_speed_measure_task_t *)args; + +- char *name = "hinic3_speed_measure"; ++ const char *name = "hinic3_speed_measure"; + int ret = hinic3_set_thread_name_by_str(name); + if (ret != 0) + HINIC3_LOG(WARNING, AGENT, "set speed measure thread name failed!"); +@@ -407,7 +407,7 @@ static int + hinic3_speed_task_cmd_help(struct unixctl_conn *conn, int argc, const char *argv[]) + { + struct ds ds = DS_EMPTY_INITIALIZER; +- char *help_desc = " start Start the offload speed measuring task\n" ++ const char *help_desc = " start Start the offload speed measuring task\n" + " -i Interval, in second. It is an integer with a range <1-10>\n" + " -t Sample number, an integer with a range <1-300>\n" + " restart Restart the offload speed measuring task\n" +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c +index 2114202657..730ddfd55d 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_error_stats.c +@@ -144,7 +144,7 @@ hinic3_flow_agent_error_stats_cmd(struct unixctl_conn *conn, int argc, const cha + } + + void +-unixctl_hinic3_cmd_error_stats_register() ++unixctl_hinic3_cmd_error_stats_register(void) + { + hinic3_command_register("hwoff/show-error-stats", "", 1, 2, + hinic3_flow_agent_error_stats_cmd, NULL); +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c +index 465c57c96b..ee28cecd6e 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c +@@ -199,7 +199,7 @@ hinic3_flow_escape_mode_cmd(struct unixctl_conn *conn, int argc, const char *arg + } + + void +-unixctl_hinic3_cmd_forward_register() ++unixctl_hinic3_cmd_forward_register(void) + { + hinic3_command_register("hwoff/set-forward-mode", "{ low_latency | high_throughput }", 1, 1, + hinic3_forward_mode_set_cmd, NULL); +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c +deleted file mode 100644 +index a96f577468..0000000000 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.c ++++ /dev/null +@@ -1,28 +0,0 @@ +-/* +- * SPDX-License-Identifier: BSD-3-Clause +- * Copyright(c) 2025 Huawei Technologies Co., Ltd +- */ +-#include "hinic3_log.h" +-#include "hinic3_ui_string.h" +-#include "hinic3_cmd_meminfo.h" +-#include "hinic3_cmd_version.h" +- +-void +-hinic3_show_agent_version(struct unixctl_conn *conn, int argc HINIC3_UNUSED, +- const char *argv[] HINIC3_UNUSED, void *aux) +-{ +- struct ds ds = DS_EMPTY_INITIALIZER; +- hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_COMPONENT_NAME); +- hinic3_ds_put_format(&ds, "%2s%s\n", HINIC3_UI_INDENT_SPACE, HINIC3_AGENT_FEATURE_NAME); +- hinic3_ds_put_format(&ds, "%2s%s%s\n", HINIC3_UI_INDENT_SPACE, +- HINIC3_AGENT_COMPONENT_VERSION, HINIC3_BUILD_MAJOR_VERSION); +- hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); +- hinic3_ds_destroy(&ds); +- *(int *)aux = 0; +-} +- +-void +-unixctl_hinic3_cmd_version_register() +-{ +- hinic3_command_register("hinic3-agent-version", "", 0, 0, hinic3_show_agent_version, NULL); +-} +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h +deleted file mode 100644 +index bee862135a..0000000000 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_version.h ++++ /dev/null +@@ -1,11 +0,0 @@ +-/* +- * SPDX-License-Identifier: BSD-3-Clause +- * Copyright(c) 2025 Huawei Technologies Co., Ltd +- */ +-#ifndef HINIC3_CMD_VERSION_H +-#define HINIC3_CMD_VERSION_H +- +-void unixctl_hinic3_cmd_version_register(void); +-void hinic3_show_agent_version(struct unixctl_conn *conn, int argc HINIC3_UNUSED, +- const char *argv[] HINIC3_UNUSED, void *aux HINIC3_UNUSED); +-#endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c +index 14b32d963d..ae8fe942cf 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c +@@ -56,10 +56,10 @@ static const char *g_hinic3_trace_flow_status_string[] = { + "hinic3_agent_flow_put_done", + }; + +-void ++static void + hinic3_trace_flow_current_key_update(struct hinic3_filter_tuple *cur_key, const struct hinic3_conntrack_key *key) + { +- struct hinic3_key_5tuple *tuple = (struct hinic3_key_5tuple *)key->key; ++ const struct hinic3_key_5tuple *tuple = (const struct hinic3_key_5tuple *)key->key; + + cur_key->proto = key->meta.tcp_udp_flag; + cur_key->src_ip = tuple->ip.src; +@@ -266,7 +266,7 @@ hinic3_trace_flow_cmd_para_check(int argc, const char *argv[], struct hinic3_fil + return 0; + } + +-void ++static void + hinic3_agent_trace_flow_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) + { + struct ds reply = DS_EMPTY_INITIALIZER; +@@ -344,7 +344,7 @@ hinic3_dump_filter_info(struct hinic3_trace_flow *trace_flow, struct ds *reply) + } + } + +-void ++static void + hinic3_agent_dump_trace_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) + { + struct ds reply = DS_EMPTY_INITIALIZER; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c +index 63d8969ab2..c42b75d78b 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.c +@@ -20,7 +20,7 @@ + #include "hinic3_command.h" + #include "hinic3_flow_agent.h" + +-static char *g_vm_qos_unit[QOS_UNIT_NUM] = { ++static const char *g_vm_qos_unit[QOS_UNIT_NUM] = { + BW_QOS_UNIT, + PPS_QOS_UNIT, + BW_QOS_UNIT, +@@ -33,7 +33,7 @@ static struct port_status g_port_status[] = { + {HWPT_FLAVOR_REFCNT_INVALID, "invalid"}, + }; + +-char ** ++const char ** + hinic3_vm_qos_unit_get(void) + { + return g_vm_qos_unit; +@@ -56,52 +56,6 @@ hinic3_port_virtio_queue_show(struct ds *ds, struct port_stats *vf_stats, struct + return; + } + +-void +-hinic3_virtual_vf_flavor_show(struct ds *ds) +-{ +- struct hinic3_dev_node *iter = NULL; +- struct dev_mgmt *dev_list = get_netdev_hwpt_flavor(); +- +- if (hinic3_get_port_conf_type() == PORT_CONF_FUNC) { +- hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Failed to port conf.\n"); +- return; +- } +- +- if (hinic3_device_mode_get() == SMART_NIC_MODE) { +- dev_list = hinic3_updata_netdev_hwpt_flavor(); +- if (dev_list == NULL) { +- hinic3_ds_put_format(ds, HINIC3_UI_LEADING_SIGN_ERROR "Failed to update the VF list.\n"); +- return; +- } +- } +- +- if (hinic3_list_is_empty(&dev_list->vf_list) == false) { +- LIST_FOR_EACH(iter, node, &dev_list->vf_list) { +- hinic3_ds_put_format(ds, "%2shost-pci-addr: %04x:%02x:%02x.%u\n%2stype: %11s\n%2sstatus: %s\n", +- HINIC3_UI_INDENT_SPACE, iter->phy_dev.pci_addr.domain, iter->phy_dev.pci_addr.bus, +- iter->phy_dev.pci_addr.devid, iter->phy_dev.pci_addr.function, HINIC3_UI_INDENT_SPACE, +- HWPT_HWTYPE_VF_STR, HINIC3_UI_INDENT_SPACE, g_port_status[iter->phy_dev.refcnt].str); +- if (iter->node.next != &dev_list->vf_list || hinic3_list_is_empty(&dev_list->pf_list) == false) { +- hinic3_ds_put_format(ds, "\n"); +- } +- } +- } +- +- if (hinic3_list_is_empty(&dev_list->pf_list) == false) { +- LIST_FOR_EACH(iter, node, &dev_list->pf_list) { +- hinic3_ds_put_format(ds, "%2shost-pci-addr: %04x:%02x:%02x.%u\n%2stype: %11s\n%2sstatus: %s\n", +- HINIC3_UI_INDENT_SPACE, iter->phy_dev.pci_addr.domain, iter->phy_dev.pci_addr.bus, +- iter->phy_dev.pci_addr.devid, iter->phy_dev.pci_addr.function, HINIC3_UI_INDENT_SPACE, +- HWPT_HWTYPE_PF_STR, HINIC3_UI_INDENT_SPACE, g_port_status[iter->phy_dev.refcnt].str); +- if (iter->node.next != &dev_list->pf_list) { +- hinic3_ds_put_format(ds, "\n"); +- } +- } +- } +- +- return; +-} +- + static const char* + hinic3_get_port_name_by_vport_id(int vport_id) + { +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h +index cb0f1068c2..7b40261eb0 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx.h +@@ -71,6 +71,6 @@ void hinic3_multi_port_qos_stats_show(struct unixctl_conn *conn, int argc, const + int hinic3_get_ifindex_id_by_name(const char **argv, uint16_t *dpdk_index_id); + void hinic3_qos_speed_print(struct unixctl_conn *conn, const struct vm_ports_info *start, + const struct vm_ports_info *end); +-char **hinic3_vm_qos_unit_get(void); ++const char **hinic3_vm_qos_unit_get(void); + + #endif +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c +index fed7659068..ba10f1b5eb 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c +@@ -23,12 +23,12 @@ + #define MULTI_PPS_QOS_SPEACE_NUMS 6 + #define MULTI_KBPS_QOS_SPEACE_NUMS 5 + +-static char *g_profile_unit[PROFILE_UNIT_NUM] = { ++static const char *g_profile_unit[PROFILE_UNIT_NUM] = { + BW_QOS_UNIT, + PPS_QOS_UNIT, + }; + +-static char *g_profile_mode[PROFILE_UNIT_NUM] = { ++static const char *g_profile_mode[PROFILE_UNIT_NUM] = { + BW_QOS_MODE, + PPS_QOS_MODE, + }; +@@ -251,7 +251,7 @@ hinic3_multi_qos_speed_show(struct unixctl_conn *conn, int argc, const char *arg + return; + } + +- group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ group_id = (uint16_t)strtoul((const char *)argv[1], &endPtr, DEC_BASE_NUM); + if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { + hinic3_command_reply_error(conn, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); + *(int *)aux = -1; +@@ -295,7 +295,7 @@ hinic3_show_multi_port_qos(struct ds *ds, enum hinic3_qos_tablehead index, + struct qos_single_value *profile = NULL; + struct qos_single_value qos_value = {0}; + group_qos_type_key *qos_key = hinic3_get_qos_type_key(); +- char **vm_qos_unit = hinic3_vm_qos_unit_get(); ++ const char **vm_qos_unit = hinic3_vm_qos_unit_get(); + enum hinic3_meter_qos_direction dir = hinic3_qos_get_dir(index); + + meter = hinic3_meter_find(meter_id); +@@ -371,7 +371,7 @@ hinic3_show_multi_qos(struct ds *ds, enum hinic3_qos_tablehead index, uint16_t g + int ret; + struct qos_single_value qos_value = {0}; + group_qos_type_key *qos_key = hinic3_get_qos_type_key(); +- char **vm_qos_unit = hinic3_vm_qos_unit_get(); ++ const char **vm_qos_unit = hinic3_vm_qos_unit_get(); + enum hinic3_meter_qos_direction dir = hinic3_qos_get_dir(index); + + ret = hinic3_vm_qos_limit_get(group_id, dir, profile->packet_mode, &qos_value); +@@ -511,7 +511,7 @@ hinic3_multi_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv + if (argc == 1) { + ret = hinic3_multi_qos_dump_show_all(&ds); + } else if (argc == MULTI_QOS_ARG_NUMS) { +- group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ group_id = (uint16_t)strtoul((const char *)argv[1], &endPtr, DEC_BASE_NUM); + if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); + ret = -1; +@@ -622,7 +622,7 @@ hinic3_multi_meter_show(struct unixctl_conn *conn, int argc, const char *argv[], + if (argc == 1) { + hinic3_multi_meter_show_all(&ds); + } else if (argc == MULTI_QOS_ARG_NUMS) { +- meter_id = strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ meter_id = strtoul(argv[1], &endPtr, DEC_BASE_NUM); + if (endPtr == NULL || *endPtr != '\0') { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_METER_ID_STR); + ret = -1; +@@ -692,7 +692,7 @@ hinic3_multi_policy_show(struct unixctl_conn *conn, int argc, const char *argv[] + if (argc == 1) { + hinic3_multi_policy_show_all(&ds); + } else if (argc == MULTI_QOS_ARG_NUMS) { +- policy_id = strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ policy_id = strtoul(argv[1], &endPtr, DEC_BASE_NUM); + if (endPtr == NULL || *endPtr != '\0') { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_POLICY_ID_STR); + ret = -1; +@@ -796,7 +796,7 @@ hinic3_multi_profile_show(struct unixctl_conn *conn, int argc, const char *argv[ + if (argc == 1) { + hinic3_multi_profile_show_all(&ds); + } else if (argc == MULTI_QOS_ARG_NUMS) { +- porfile_id = strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ porfile_id = strtoul(argv[1], &endPtr, DEC_BASE_NUM); + if (endPtr == NULL || *endPtr != '\0') { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_PROFILE_ID_STR); + ret = -1; +@@ -841,7 +841,7 @@ hinic3_multi_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv + goto err; + } + +- group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ group_id = (uint16_t)strtoul(argv[1], &endPtr, DEC_BASE_NUM); + if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); + goto err; +@@ -883,7 +883,7 @@ hinic3_multi_net_qos_show_one(uint32_t meter_id, enum hinic3_qos_tablehead index + struct hinic3_meter_node *meter = NULL; + struct qos_single_value *profile = NULL; + group_qos_type_key *qos_key = hinic3_get_qos_type_key(); +- char **vm_qos_unit = hinic3_vm_qos_unit_get(); ++ const char **vm_qos_unit = hinic3_vm_qos_unit_get(); + + meter = hinic3_meter_find(meter_id); + if (meter == NULL) { +@@ -1013,7 +1013,7 @@ hinic3_multi_qos_stats_show(struct unixctl_conn *conn, int argc, const char *arg + goto err; + } + +- group_id = (uint16_t)strtoul((char *)argv[1], &endPtr, DEC_BASE_NUM); ++ group_id = (uint16_t)strtoul(argv[1], &endPtr, DEC_BASE_NUM); + if (group_id > MAX_QOS_ID_NUM || group_id == 0 || endPtr == NULL || *endPtr != '\0') { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_INVALID_GROUP_ID_STR); + goto err; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +index c120e0c130..d39a65b81f 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +@@ -46,7 +46,7 @@ struct hinic3_command_mgr { + + struct hinic3_command_mgr g_command_mgr = {0}; + +-void ++static void + hinic3_list_commands(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) + { + struct shash_node *node = NULL; +@@ -55,7 +55,7 @@ hinic3_list_commands(struct unixctl_conn *conn, int argc, const char *argv[], vo + hinic3_ds_put_format(&reply, "Available commands:\n"); + + HINIC3_SHASH_FOR_EACH(node, &g_command_mgr.command_map) { +- struct hinic3_command *command = node->data; ++ const struct hinic3_command *command = node->data; + hinic3_ds_put_format(&reply, " %-35s %s\n", node->name, command->usage); + } + +@@ -72,7 +72,7 @@ hinic3_command_register(const char *name, const char *usage, int min_args, int m + char key[HINIC3_COMMAND_STR_MAX_LEN] = {0}; + strcpy(key, name); + +- struct hinic3_command *command_ptr = (struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); ++ const struct hinic3_command *command_ptr = (const struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); + if (command_ptr != NULL) { + HINIC3_LOG(ERR, AGENT, "hinic3 command %s already registered", key); + return; +@@ -99,7 +99,7 @@ hinic3_command_register(const char *name, const char *usage, int min_args, int m + return; + } + +-int ++static int + hinic3_write_str_to_socket(struct unixctl_conn *conn, const char *str) + { + if (str == NULL) +@@ -146,31 +146,31 @@ hinic3_command_reply_error(struct unixctl_conn *conn, const char *error) + hinic3_write_str_to_socket(conn, error); + } + +-unixctl_cb_func *get_cmd_func(const char *command_str) ++static unixctl_cb_func *get_cmd_func(const char *command_str) + { + char key[HINIC3_COMMAND_STR_MAX_LEN] = {0}; + strcpy(key, command_str); + +- struct hinic3_command *command = (struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); ++ const struct hinic3_command *command = (const struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); + if (command == NULL) + return (unixctl_cb_func *)NULL; + + return command->cb_func; + } + +-static struct hinic3_command * ++static const struct hinic3_command * + get_cmd_command(const char *command_str) + { + char key[HINIC3_COMMAND_STR_MAX_LEN] = {0}; + strcpy(key, command_str); +- struct hinic3_command *command = (struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); ++ const struct hinic3_command *command = (const struct hinic3_command *)hinic3_shash_find_data(&g_command_mgr.command_map, key); + return command; + } + + static int + hinic3_cmd_param_check(const char *command_str, int argc) + { +- struct hinic3_command *command = get_cmd_command(command_str); ++ const struct hinic3_command *command = get_cmd_command(command_str); + if (command == NULL) + return HINIC3_COMMAND_ERROR_TYPE_NULL; + if (argc - 1 > command->max_argc) +@@ -180,7 +180,7 @@ hinic3_cmd_param_check(const char *command_str, int argc) + return 0; + } + +-int ++static int + dispatch_command(struct unixctl_conn *conn, int argc, const char *argv[]) + { + if (argc == 0) +@@ -209,12 +209,12 @@ dispatch_command(struct unixctl_conn *conn, int argc, const char *argv[]) + return ret; + } + +-int ++static int + parse_args(struct unixctl_conn *conn, char *command, int *argc_ptr, const char *argv[]) + { + char *cursor = command; + char *str_end = cursor + strlen(command); +- char *delimiters = " "; ++ const char *delimiters = " "; + + *argc_ptr = 0; + +@@ -254,7 +254,7 @@ parse_args(struct unixctl_conn *conn, char *command, int *argc_ptr, const char * + return 0; + } + +-int ++static int + hinic3_server_recv_command(FILE *file, char *start, char *end) + { + long long time_start = hinic3_time_msec(); +@@ -288,7 +288,7 @@ hinic3_server_recv_command(FILE *file, char *start, char *end) + return 0; + } + +-int ++static int + hinic3_set_socket_nonblocking(int fd) + { + int flags = fcntl(fd, F_GETFL, 0); +@@ -306,7 +306,6 @@ hinic3_set_socket_nonblocking(int fd) + + static struct hinic3_command_info g_hinic3_command_info[] = { + {"hwoff/show-hmap-flow-num", "Queries the number of flow tables in the hash table."}, +- {"hinic3-agent-version", "Query the dpak-libovs version."}, + {"hwoff/exec-cmd", "This command is used to issue or query OVS driver information for debugging."}, + {"hwoff/show-flow-api", "This API is used to query the hardware flow table."}, + {"hwoff/show-error-stats", "Indicates the error information recorded during flow table unloading."}, +@@ -397,7 +396,7 @@ hinic3_set_cmd_info_to_log(const char *usr_name, const char *func_name, int resu + hinic3_free(cmd_info); + } + +-int ++static int + proc_conn(int data_socket) + { + int ret = hinic3_set_socket_nonblocking(data_socket); +@@ -438,7 +437,7 @@ proc_conn(int data_socket) + return 0; + } + +-void ++static void + hinic3_command_epoll_process(int fd) + { + int listen_socket = g_command_mgr.listen_socket; +@@ -451,7 +450,7 @@ hinic3_command_epoll_process(int fd) + return; + } + +-void * ++static void * + hinic3_command_thread(void *arg) + { + int listen_socket = g_command_mgr.listen_socket; +@@ -516,7 +515,7 @@ hinic3_command_pre_init(int *listen_socket) + return 0; + } + +-int ++static int + hinic3_command_init(void) + { + int ret; +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h +index 0e882b8e01..e3d65df730 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h +@@ -58,7 +58,7 @@ struct hinic3_dpif_flow { + /* length of key in bytes */ + size_t key_len; + /* mask to put */ +- const struct hinic3_nlattr_obj *mask; ++ struct hinic3_nlattr_obj *mask; + /* length of mask in bytes */ + size_t mask_len; + /* actions to perform on flow */ +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c +index dc1b053676..87549da788 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.c +@@ -103,21 +103,21 @@ int hinic3_flow_put(const struct hinic3_dpif_flow *put, const struct hinic3_nlat + ops = hinic3_get_drv_ops(); + HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_put, HINIC3_DRV_FUNC_NO_PTR); + +- hovs_put.key = (struct nlattr *)put->key; ++ hovs_put.key = (const struct nlattr *)put->key; + hovs_put.key_len = put->key_len; +- hovs_put.mask = (struct nlattr *)put->mask; ++ hovs_put.mask = (const struct nlattr *)put->mask; + hovs_put.mask_len = put->mask_len; +- hovs_put.actions = (struct nlattr *)put->actions; ++ hovs_put.actions = (const struct nlattr *)put->actions; + hovs_put.action_len = put->action_len; + hovs_put.mask_present = put->mask_present; + hovs_put.hw_ufid = put->hw_ufid; + HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_PUT, +- ops->hovs_flow_mgmt_put(&hovs_put, (struct nlattr *)args, args_len)); ++ ops->hovs_flow_mgmt_put(&hovs_put, (const struct nlattr *)args, args_len)); + return hinic3_convert_error_code(ret); + } + + int hinic3_flow_mgmt_get_by_key(const struct hinic3_nlattr *key, size_t key_len, struct hinic3_dpif_flow *put, +- uint64_t get_flow_related_ufid) ++ uint64_t *get_flow_related_ufid) + { + if (key == NULL || put == NULL) { + HINIC3_LOG(WARNING, FLOW, "hinic3_flow_mgmt_get_by_key pointer parameter is NULL"); +@@ -137,7 +137,7 @@ int hinic3_flow_mgmt_get_by_key(const struct hinic3_nlattr *key, size_t key_len, + ops = hinic3_get_drv_ops(); + HINIC3_FUNC_PTR_OR_ERR_RET(ops->hovs_flow_mgmt_get_by_key, HINIC3_DRV_FUNC_NO_PTR); + HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_AGENT_GET_BY_KEY, +- ops->hovs_flow_mgmt_get_by_key((struct nlattr *)key, key_len, &hovs_put)); ++ ops->hovs_flow_mgmt_get_by_key((const struct nlattr *)key, key_len, &hovs_put)); + if (ret == 0) { + put->hw_ufid = hovs_put.hw_ufid; + put->key = (struct hinic3_nlattr_obj*)hovs_put.key; +@@ -147,7 +147,7 @@ int hinic3_flow_mgmt_get_by_key(const struct hinic3_nlattr *key, size_t key_len, + put->actions = (struct hinic3_nlattr_obj*)hovs_put.actions; + put->mask_present = hovs_put.mask_present; + put->action_len = hovs_put.action_len; +- get_flow_related_ufid = hovs_put.related_hw_ufid; ++ *get_flow_related_ufid = hovs_put.related_hw_ufid; + memcpy(&put->stats, &hovs_put.stats, sizeof(struct hovs_flow_stats)); + } + return ret; +@@ -485,14 +485,14 @@ int hinic3_flow_modify(const struct hinic3_dpif_flow *put, const struct hinic3_n + + hovs_put.key = (struct nlattr *)put->key; + hovs_put.key_len = put->key_len; +- hovs_put.mask = (struct nlattr *)put->mask; ++ hovs_put.mask = (const struct nlattr *)put->mask; + hovs_put.mask_len = put->mask_len; + hovs_put.actions = (struct nlattr *)put->actions; + hovs_put.action_len = put->action_len; + hovs_put.mask_present = put->mask_present; + hovs_put.hw_ufid = put->hw_ufid; + HINIC3_LOG_HINIC_FLOW_API_LOG_NO_LOG(ret, HINIC3_FLOW_MODIFY, +- ops->hovs_flow_mgmt_update(&hovs_put, (struct nlattr *)args, args_len)); ++ ops->hovs_flow_mgmt_update(&hovs_put, (const struct nlattr *)args, args_len)); + return hinic3_convert_error_code(ret); + } + +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h +index ea409a7823..52c36006c0 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_flow.h +@@ -90,7 +90,7 @@ int hinic3_flow_del_by_ufid(uint64_t ufid); + int hinic3_flow_get_by_ufid(uint64_t ufid, struct hinic3_dpif_flow_for_get *get); + int hinic3_flow_put(const struct hinic3_dpif_flow *put, const struct hinic3_nlattr *args, size_t args_len); + int hinic3_flow_mgmt_get_by_key(const struct hinic3_nlattr *key, size_t key_len, struct hinic3_dpif_flow *get, +- uint64_t g_get_flow_related_ufid); ++ uint64_t *g_get_flow_related_ufid); + int hinic3_flow_get_capability(struct hinic3_flow_capability *cap); + int hinic3_flow_flush(void); + uint32_t hinic3_get_offload_thread_num(void); +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +index 13e1f2cac0..e17db23c1c 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +@@ -190,7 +190,7 @@ static int hinic3_log_hinic_global_api_log(hinic3_global_api api_index, struct h + exec_time = ((rte_get_tsc_cycles() - time_start) * 1000000UL) / hz; + } + hinic_global_fill_api_record(api_index, exec_time); +- hinic_global_api_record_error(ret, api_index, exec_time); ++ hinic_global_api_record_error(ret, (hinic3_port_api)api_index, exec_time); + } + return ret; + } +@@ -208,7 +208,7 @@ static int global_cfg_parse_action(const char *action, uint8_t *val) + return 0; + } + +-static char *global_cfg_action_stringfy(uint8_t val) ++static const char *global_cfg_action_stringfy(uint8_t val) + { + if (val == GLOBAL_CFG_ACTION_DROP) { + return GLOBAL_CFG_ACTION_DROP_STR; +@@ -220,7 +220,7 @@ static char *global_cfg_action_stringfy(uint8_t val) + } + + +-static char *global_cfg_unage_flag_stringfy(uint8_t val) ++static const char *global_cfg_unage_flag_stringfy(uint8_t val) + { + if (val == 1) { + return HINIC3_FLOW_UNAGE_FLAG; +@@ -257,7 +257,7 @@ static int global_cfg_parse_pmd_mode(const char *mode, uint8_t *val) + return 0; + } + +-static char *global_cfg_thread_mode_stringfy(uint8_t val) ++static const char *global_cfg_thread_mode_stringfy(uint8_t val) + { + if (val == GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN) { + return GLOBAL_CFG_THREAD_MODE_ROUND_ROBIN_STR; +@@ -281,7 +281,7 @@ static int global_cfg_parse_action_check_mode(const char *mode, uint8_t *val) + return 0; + } + +-static char *g_global_smap_key[HINIC3_GLOBAL_CFG_ARG_TYPE_MAX] = { ++static const char *g_global_smap_key[HINIC3_GLOBAL_CFG_ARG_TYPE_MAX] = { + HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE_STR, + HINIC3_GLOBAL_CFG_ARG_RSS_VF_NUM_STR, + HINIC3_GLOBAL_CFG_ARG_VXLAN_LOCAL_IP_STR, +@@ -452,11 +452,11 @@ static int global_cfg_smap_to_nlattr(const struct smap *args, struct hinic3_nlat + return 0; + } + +-static int nla_to_smap_u8(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++static int nla_to_smap_u8(struct smap *args, const hinic3_nlattr_itr nla, const char *key) + { + uint8_t val = hinic3_nlattr_get_itr_u8(nla); + int type = hinic3_nlattr_get_itr_type(nla); +- char *smap_value = NULL; ++ const char *smap_value = NULL; + + if (type == HINIC3_GLOBAL_CFG_ARG_VLAN_ETHTYPE) { + if (val == GLOBAL_VLAN_ETHTYPE_8021Q) { +@@ -492,7 +492,7 @@ static int nla_to_smap_u8(struct smap *args, const hinic3_nlattr_itr nla, char * + return 0; + } + +-static int nla_to_smap_u16(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++static int nla_to_smap_u16(struct smap *args, const hinic3_nlattr_itr nla, const char *key) + { + char *value = NULL; + char value_buf[MAX_ARGS_SIZE] = { 0 }; +@@ -503,7 +503,7 @@ static int nla_to_smap_u16(struct smap *args, const hinic3_nlattr_itr nla, char + return 0; + } + +-static int nla_to_smap_u32(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++static int nla_to_smap_u32(struct smap *args, const hinic3_nlattr_itr nla, const char *key) + { + char *value = NULL; + char value_buf[MAX_ARGS_SIZE] = { 0 }; +@@ -520,7 +520,7 @@ static int nla_to_smap_u32(struct smap *args, const hinic3_nlattr_itr nla, char + return 0; + } + +-static int nla_to_smap_raw(struct smap *args, const hinic3_nlattr_itr nla, char *key) ++static int nla_to_smap_raw(struct smap *args, const hinic3_nlattr_itr nla, const char *key) + { + char *value = NULL; + char value_buf[MAX_ARGS_SIZE] = { 0 }; +@@ -542,7 +542,7 @@ static int nla_to_smap_raw(struct smap *args, const hinic3_nlattr_itr nla, char + return 0; + } + +-static char *global_smap_key_from_nla_type(uint32_t type) ++static const char *global_smap_key_from_nla_type(uint32_t type) + { + if (type >= HINIC3_GLOBAL_CFG_ARG_TYPE_MAX) { + return NULL; +@@ -551,7 +551,7 @@ static char *global_smap_key_from_nla_type(uint32_t type) + return g_global_smap_key[type]; + } + +-static int global_nla_to_smap(const hinic3_nlattr_itr nla_itr, struct smap *args, char *key) ++static int global_nla_to_smap(const hinic3_nlattr_itr nla_itr, struct smap *args, const char *key) + { + const char *vf_info = NULL; + +@@ -582,7 +582,7 @@ static int global_nla_to_smap(const hinic3_nlattr_itr nla_itr, struct smap *args + return nla_to_smap_raw(args, nla_itr, key); + case HINIC3_GLOBAL_CFG_ARG_VF_INFO: + vf_info = hinic3_nlattr_get_itr_string(nla_itr); +- hinic3_smap_add(args, HINIC3_GLOBAL_CFG_ARG_VF_INFO_STR, HINIC3_CONST_CAST(char *, vf_info), ++ hinic3_smap_add(args, HINIC3_GLOBAL_CFG_ARG_VF_INFO_STR, vf_info, + HINIC3_DRIVER_ADAPTER); + break; + case HINIC3_GLOBAL_CFG_ARG_PHY_DEV_INFO: +@@ -596,7 +596,7 @@ static int global_nla_to_smap(const hinic3_nlattr_itr nla_itr, struct smap *args + static int global_cfg_nlattr_to_smap(const struct hinic3_nlattr *args_nla, struct smap *args) + { + hinic3_nlattr_itr nla_itr = NULL; +- char *key = NULL; ++ const char *key = NULL; + + HINIC3_NLATTR_FOR_EACH(nla_itr, args_nla) { + if (hinic3_nlattr_get_itr_size(nla_itr) == 0) { +@@ -721,7 +721,7 @@ void hinic3_global_unit(void) + HINIC3_LOG(WARNING, AGENT, "hinic HWAPI hinic3_global_unit called, return void, cost %" PRIu64 " us.", exec_time); + + if (g_dpdk_shared_mp != NULL) { +- rte_mempool_free((struct rte_mempool *)g_dpdk_shared_mp); ++ rte_mempool_free((struct rte_mempool *)(uintptr_t)g_dpdk_shared_mp); + g_dpdk_shared_mp = NULL; + } + } +@@ -1014,16 +1014,6 @@ static void hinic3_init_flow_unage_flag(struct smap *args) + HINIC3_LOG(INFO, AGENT, "Set the hardware flow not to be aged."); + } + +-static void hinic3_init_flow_age_time(struct smap *args) +-{ +- char age_time_str[HINIC3_FLOW_AGE_TIME_MAX_LEN] = { 0 }; +- uint32_t age_time = hinic3_flow_max_idle_get(); +- +- sprintf(age_time_str, "%u", age_time); +- hinic3_smap_add(args, HINIC3_GLOBAL_CFG_ARG_FLOW_AGE_TIME_STR, age_time_str, HINIC3_DRIVER_ADAPTER); +- HINIC3_LOG(INFO, AGENT, "Set the aging time of the hardware flow table to %s ms.", age_time_str); +-} +- + void hinic3_global_cfg_set_when_restart(void) + { + int ret; +@@ -1048,7 +1038,7 @@ void hinic3_global_cfg_set_when_restart(void) + + struct rte_mempool *dpdk_shared_mp_get(void) + { +- return (struct rte_mempool *)g_dpdk_shared_mp; ++ return (struct rte_mempool *)(uintptr_t)g_dpdk_shared_mp; + } + + static const char *hinic3_global_get_api_name(hinic3_global_api api_index) +@@ -1102,7 +1092,7 @@ static void hinic3_global_format_api(const char *api_name, const hiovs_api_recor + static int hinic3_global_show_one_api(struct unixctl_conn *conn, int argc, const char *argv[]) + { + int ret; +- char *api_name = NULL; ++ const char *api_name = NULL; + hiovs_api_record rec; + struct ds ds = DS_EMPTY_INITIALIZER; + +@@ -1110,7 +1100,7 @@ static int hinic3_global_show_one_api(struct unixctl_conn *conn, int argc, const + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "invalid command format, type -h or --help for help.\n"); + goto err; + } +- api_name = (char *)argv[1]; ++ api_name = argv[1]; + if (hinic3_global_get_api_index(api_name) == HINIC3_GLOBAL_API_MAX) { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "api-name is invalid [%s].\n", api_name); + goto err; +@@ -1136,7 +1126,7 @@ static int hinic3_global_show_all_api(struct unixctl_conn *conn) + { + int i; + int ret; +- char *api_name = NULL; ++ const char *api_name = NULL; + struct ds ds = DS_EMPTY_INITIALIZER; + hiovs_api_record *rec_list = NULL; + +@@ -1155,7 +1145,7 @@ static int hinic3_global_show_all_api(struct unixctl_conn *conn) + + hinic3_ds_put_format(&ds, "%2sAPI Counts: %d\n", HINIC3_UI_INDENT_SPACE, HINIC3_GLOBAL_API_MAX); + for (i = 0; i < HINIC3_GLOBAL_API_MAX; i++) { +- api_name = (char *)hinic3_global_get_api_name(i); ++ api_name = hinic3_global_get_api_name(i); + if (api_name == NULL) { + goto err; + } +@@ -1180,7 +1170,7 @@ static int hinic3_global_clear_api(struct unixctl_conn *conn, int argc, const ch + { + int ret; + struct ds ds = DS_EMPTY_INITIALIZER; +- char *api_name = NULL; ++ const char *api_name = NULL; + hiovs_api_record rec; + + if (argc != CLEAR_GLOBAL_API_ARG_NUM) { +@@ -1198,7 +1188,7 @@ static int hinic3_global_clear_api(struct unixctl_conn *conn, int argc, const ch + HINIC3_LOG(INFO, AGENT, "clear all global api record successful\n"); + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_INFO "Clear global API records successful [all].\n"); + } else { +- api_name = (char *)argv[CLEAR_GLOBAL_API_ARG_NUM - 1]; ++ api_name = argv[CLEAR_GLOBAL_API_ARG_NUM - 1]; + if (hinic3_global_get_api_index(api_name) == HINIC3_GLOBAL_API_MAX) { + hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR "api-name is invalid [%s].\n", api_name); + goto err; +@@ -1358,13 +1348,13 @@ void hinic3_adapt_free(void *addr) + + const void *hinic3_adapt_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) + { +- return (void *)hinic3_rte_memzone_reserve(name, len, socket_id, flags, HIOVS_MEM); ++ return hinic3_rte_memzone_reserve(name, len, socket_id, flags, HIOVS_MEM); + } + + const void *hinic3_adapt_memzone_reserve_aligned(const char *name, size_t len, int socket_id, unsigned flags, + unsigned align) + { +- return (void *)hinic3_rte_memzone_reserve_aligned(name, len, socket_id, flags, align, HIOVS_MEM); ++ return hinic3_rte_memzone_reserve_aligned(name, len, socket_id, flags, align, HIOVS_MEM); + } + + int hinic3_adapt_memzone_free(void *addr) +@@ -1474,7 +1464,7 @@ static int hinic3_bond_hash_policy_set_sub(struct hinic3_nlattr *nla, enum hinic + return ret; + } + +-int hinic3_bond_hash_policy_set(enum hinic3_packet_forward_mod mod) ++static int hinic3_bond_hash_policy_set(enum hinic3_packet_forward_mod mod) + { + struct hinic3_nlattr args_in; + struct hinic3_nlattr args_out; +@@ -1486,7 +1476,7 @@ int hinic3_bond_hash_policy_set(enum hinic3_packet_forward_mod mod) + hinic3_nlattr_init(&args_in, buffer_in, HINIC3_BOND_HASH_POLICY_LEN); + hinic3_nlattr_init(&args_out, buffer_out, HINIC3_BOND_HASH_POLICY_LEN); + +- ret = hinic3_bond_hash_policy_set_sub(&args_in, mod); ++ ret = hinic3_bond_hash_policy_set_sub(&args_in, (enum hinic3_bond_hash_policy)mod); + if (ret != 0) { + HINIC3_LOG(ERR, AGENT, "Failed to bond hash policy."); + return -1; +@@ -1551,7 +1541,7 @@ int hinic3_bond_hash_policy_init(void) + enum hinic3_bond_hash_policy mod = hinic3_packet_bond_hash_policy_get(); + int ret = 0; + +- ret = hinic3_bond_hash_policy_set(mod); ++ ret = hinic3_bond_hash_policy_set((enum hinic3_packet_forward_mod)mod); + if (ret != 0) { + HINIC3_LOG(ERR, AGENT, "Failed to init bond hash policy."); + } +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c +index 59d7e92cfe..0831ffa274 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.c +@@ -109,7 +109,7 @@ static const struct hiovs_port_map g_port_api_arr[HINIC3_PORT_API_MAX] = { + } \ + } while (0) + +-int hinic3_port_mgmt_add(uint16_t *port_id, const struct rte_pci_addr *pci_addr) ++int hinic3_port_mgmt_add(uint16_t *port_id, struct rte_pci_addr *pci_addr) + { + int ret; + uint64_t time_start; +@@ -736,7 +736,7 @@ static void hinic3_port_format_api(const char *api_name, const hiovs_api_record + static int hinic3_port_show_one_api(struct unixctl_conn *conn, int argc, const char *argv[]) + { + int ret; +- char *api_name = NULL; ++ const char *api_name = NULL; + hiovs_api_record rec; + struct ds ds = DS_EMPTY_INITIALIZER; + +@@ -746,7 +746,7 @@ static int hinic3_port_show_one_api(struct unixctl_conn *conn, int argc, const c + goto err; + } + +- api_name = (char *)argv[1]; ++ api_name = argv[1]; + if (hinic3_port_get_api_index(api_name) == HINIC3_PORT_API_MAX) { + hinic3_ds_put_format(&ds, "%sapi-name is invalid [%s].\n", HINIC3_UI_LEADING_SIGN_ERROR, api_name); + goto err; +@@ -772,7 +772,7 @@ static int hinic3_port_show_all_api(struct unixctl_conn *conn) + { + int i; + int ret; +- char *api_name = NULL; ++ const char *api_name = NULL; + struct ds ds = DS_EMPTY_INITIALIZER; + hiovs_api_record *rec_list = NULL; + +@@ -791,7 +791,7 @@ static int hinic3_port_show_all_api(struct unixctl_conn *conn) + + hinic3_ds_put_format(&ds, "%2sAPI Counts: %d\n", HINIC3_UI_INDENT_SPACE, HINIC3_PORT_API_MAX); + for (i = 0; i < HINIC3_PORT_API_MAX; i++) { +- api_name = (char *)hinic3_port_get_api_name(i); ++ api_name = hinic3_port_get_api_name(i); + hinic3_port_format_api(api_name, &rec_list[i], &ds, true); + if (i != HINIC3_PORT_API_MAX - 1) { + hinic3_ds_put_format(&ds, "\n"); +@@ -813,7 +813,7 @@ static int hinic3_port_clear_api(struct unixctl_conn *conn, int argc, const char + { + int ret; + struct ds ds = DS_EMPTY_INITIALIZER; +- char *api_name = NULL; ++ const char *api_name = NULL; + hiovs_api_record rec; + + if (argc != CLEAR_PORT_API_ARG_NUM) { +@@ -832,7 +832,7 @@ static int hinic3_port_clear_api(struct unixctl_conn *conn, int argc, const char + HINIC3_LOG(INFO, AGENT, "clear all port api record successful\n"); + hinic3_ds_put_format(&ds, "%sClear port API records successful [all].\n", HINIC3_UI_LEADING_SIGN_INFO); + } else { +- api_name = (char *)argv[CLEAR_PORT_API_ARG_NUM - 1]; ++ api_name = argv[CLEAR_PORT_API_ARG_NUM - 1]; + if (hinic3_port_get_api_index(api_name) == HINIC3_PORT_API_MAX) { + hinic3_ds_put_format(&ds, "%sapi-name is invalid [%s].\n", HINIC3_UI_LEADING_SIGN_ERROR, api_name); + goto err; +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h +index b75b09a336..cf449403f7 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port.h +@@ -86,7 +86,7 @@ union bdf_info_u { + uint8_t value; + }; + +-int hinic3_port_mgmt_add(uint16_t *port_id, const struct rte_pci_addr *pci_addr); ++int hinic3_port_mgmt_add(uint16_t *port_id, struct rte_pci_addr *pci_addr); + int hinic3_port_mgmt_add_dynamic(uint16_t *port_id, const struct smap *args); + void hinic3_port_mgmt_del(uint16_t port_id); + int hinic3_port_mgmt_get(uint16_t port_id, struct smap *args); +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c +index 86e55d310b..3739ca7640 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_port_util.c +@@ -18,12 +18,13 @@ + #include "hinic3_smap.h" + #include "hinic3_parse_agent_config.h" + #include "hinic3_iface_port_util.h" ++#include "hinic3_packets_types.h" + + #define MAX_ARGS_SIZE (2048) + #define MAX_NAME 32 + #define MAX_RX_QUEUE_PER_VPORT 16 + +-static char *g_port_smap_key[HINIC3_PORT_ARG_TYPE_MAX] = { ++static const char *g_port_smap_key[HINIC3_PORT_ARG_TYPE_MAX] = { + HINIC3_PORT_VLAN_OL, + HINIC3_PORT_VLAN_TAG, + HINIC3_PORT_VLAN_MODE, +@@ -51,7 +52,7 @@ static char *g_port_smap_key[HINIC3_PORT_ARG_TYPE_MAX] = { + HINIC3_PORT_QUEUE_DEPTH + }; + +-static char *g_bond_smap_key[HINIC3_BOND_ARG_TYPE_MAX] = { ++static const char *g_bond_smap_key[HINIC3_BOND_ARG_TYPE_MAX] = { + HINIC3_BOND_UPLINK_PCI_ID, + HINIC3_BOND_LACP_DEACTIVE_SLAVES, + HINIC3_BOND_MODE, +@@ -201,7 +202,7 @@ void port_args_smap_to_nlattr(const struct smap *args, struct hinic3_nlattr *nla + } + } + +-static inline int nla_to_smap_u8(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++static inline int nla_to_smap_u8(struct smap *unset_args, const hinic3_nlattr_itr nla, const char *key) + { + char *value = NULL; + char args_buf[MAX_ARGS_SIZE] = { 0 }; +@@ -211,7 +212,7 @@ static inline int nla_to_smap_u8(struct smap *unset_args, const hinic3_nlattr_it + return 0; + } + +-static inline int nla_to_smap_u16(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++static inline int nla_to_smap_u16(struct smap *unset_args, const hinic3_nlattr_itr nla, const char *key) + { + char *value = NULL; + char args_buf[MAX_ARGS_SIZE] = { 0 }; +@@ -221,7 +222,7 @@ static inline int nla_to_smap_u16(struct smap *unset_args, const hinic3_nlattr_i + return 0; + } + +-static inline int nla_to_smap_u32(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++static inline int nla_to_smap_u32(struct smap *unset_args, const hinic3_nlattr_itr nla, const char *key) + { + char *value = NULL; + char args_buf[MAX_ARGS_SIZE] = { 0 }; +@@ -231,7 +232,7 @@ static inline int nla_to_smap_u32(struct smap *unset_args, const hinic3_nlattr_i + return 0; + } + +-static inline int nla_to_smap_u64(struct smap *unset_args, const hinic3_nlattr_itr nla, char *key) ++static inline int nla_to_smap_u64(struct smap *unset_args, const hinic3_nlattr_itr nla, const char *key) + { + char *value = NULL; + char args_buf[MAX_ARGS_SIZE] = { 0 }; +@@ -241,7 +242,7 @@ static inline int nla_to_smap_u64(struct smap *unset_args, const hinic3_nlattr_i + return 0; + } + +-static inline char *bond_get_smap_key_by_nla_type(uint32_t type) ++static inline const char *bond_get_smap_key_by_nla_type(uint32_t type) + { + if (type >= HINIC3_BOND_ARG_TYPE_MAX) { + return NULL; +@@ -253,7 +254,7 @@ static inline char *bond_get_smap_key_by_nla_type(uint32_t type) + void bond_args_nlattr_to_smap(const struct hinic3_nlattr *nla_config, struct smap *smap_config) + { + const char *pstr = NULL; +- char *smap_key = NULL; ++ const char *smap_key = NULL; + hinic3_nlattr_itr nla_itr = NULL; + + HINIC3_NLATTR_FOR_EACH (nla_itr, nla_config) { +@@ -284,7 +285,7 @@ void bond_args_nlattr_to_smap(const struct hinic3_nlattr *nla_config, struct sma + case HINIC3_BOND_ARG_SLAVE_NAME: + case HINIC3_BOND_ARG_ACTIVE_SLAVE: + pstr = hinic3_nlattr_get_itr_data(nla_itr); +- hinic3_smap_add(smap_config, smap_key, HINIC3_CONST_CAST(char *, pstr), HINIC3_DRIVER_ADAPTER); ++ hinic3_smap_add(smap_config, smap_key, pstr, HINIC3_DRIVER_ADAPTER); + break; + default: + break; +@@ -345,7 +346,7 @@ static int port_nla_to_smap_queue_nr(struct smap *unset_args, const hinic3_nlatt + return 0; + } + +-static char *get_smap_key_by_nla_type(uint32_t type) ++static const char *get_smap_key_by_nla_type(uint32_t type) + { + if (type >= HINIC3_PORT_ARG_TYPE_MAX) { + return NULL; +@@ -356,7 +357,7 @@ static char *get_smap_key_by_nla_type(uint32_t type) + + static int port_nla_to_smap(struct smap *unset_args, const hinic3_nlattr_itr nla) + { +- char *smap_key = get_smap_key_by_nla_type(hinic3_nlattr_get_itr_type(nla)); ++ const char *smap_key = get_smap_key_by_nla_type(hinic3_nlattr_get_itr_type(nla)); + if (smap_key == NULL) { + return 0; + } +@@ -380,7 +381,7 @@ static int port_nla_to_smap(struct smap *unset_args, const hinic3_nlattr_itr nla + return port_nla_to_smap_queue_nr(unset_args, nla); + case HINIC3_PORT_ARG_MIGRATE_TUNNEL_INFO: + case HINIC3_PORT_ARG_MIGRATE_STATE: +- hinic3_smap_add(unset_args, smap_key, (char *)hinic3_nlattr_get_itr_data(nla), HINIC3_DRIVER_ADAPTER); ++ hinic3_smap_add(unset_args, smap_key, (const char *)hinic3_nlattr_get_itr_data(nla), HINIC3_DRIVER_ADAPTER); + break; + default: + break; +@@ -407,9 +408,9 @@ static int nlattr_to_smap_src_mac(struct smap *args_smap, const hinic3_nlattr_it + int ret; + char args_buf[MAX_ARGS_SIZE] = { 0 }; + +- macs = hinic3_nlattr_get_itr_data(nla); ++ macs = (const struct eth_address *)hinic3_nlattr_get_itr_data(nla); + n_macs = hinic3_nlattr_get_itr_size(nla) / sizeof(struct eth_address); +- ret = smacs_stringfy((struct eth_addr*)macs, n_macs, args_buf, MAX_ARGS_SIZE); ++ ret = smacs_stringfy(macs, n_macs, args_buf, MAX_ARGS_SIZE); + if (ret != 0) { + HINIC3_LOG(ERR, BUM, "src macs stringfy error"); + return -EINVAL; +diff --git a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c +index e2467861ef..ebc7d6a3a7 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c ++++ b/drivers/net/hinic3/src/hinic3_flows/comm/hinic3_offload_action_public.c +@@ -64,7 +64,7 @@ int hinic3_offload_fill_vxlan_header(struct hinic3_flow_act_vxlan_gpe_header *of + flags |= HINIC3_FLG_VXLAN_ETH; + break; + case RTE_FLOW_ITEM_TYPE_VLAN: +- offload_vxlan_hdr->vlan_id = *((uint16_t*)item->spec); ++ offload_vxlan_hdr->vlan_id = *((const uint16_t*)item->spec); + flags |= HINIC3_FLG_VXLAN_VLAN; + break; + case RTE_FLOW_ITEM_TYPE_IPV4: +@@ -186,11 +186,6 @@ static int hinic3_offload_set_tag_act(struct hinic3_nlattr *hinic3_actions, cons + return -1; + } + +- if (block.block_version > UINT16_MAX) { +- hinic3_add_error_stats(HINIC3_FLOW_ERROR_FLOW_BLOCK_ERR, 1); +- return -1; +- } +- + return hinic3_nlattr_put_unspec(hinic3_actions, HINIC3_FLOW_ACT_BLOCK_VERSION, + &block, sizeof(struct hinic3_flow_act_block_version)); + } +@@ -252,7 +247,7 @@ int hinic3_offload_copy_current_action(const struct hinic3_nlattr *cur_action, s + if (cur_action->used_len > (final_action->total_len - final_action->used_len)) { + return PROCESS_ACTION_FAIL; + } +- dst_buf_ptr = final_action->data + final_action->used_len; ++ dst_buf_ptr = (void *)((char *)final_action->data + final_action->used_len); + memcpy(dst_buf_ptr, cur_action->data, cur_action->used_len); + final_action->used_len += cur_action->used_len; + final_action->nla_itr = (hinic3_nlattr_itr)((uint8_t *)final_action->data + final_action->used_len); +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c +index 668ce6b100..2b6b0a9aeb 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_action.c +@@ -45,15 +45,15 @@ static void hinic3_free_rte_sample_action(struct rte_flow_action *action) + struct rte_flow_action_vxlan_encap *vxlan_encap = NULL; + + if (sample_action != NULL) { +- port_id = (struct rte_flow_action_port_id *)sample_action[0].conf; +- vxlan_encap = (struct rte_flow_action_vxlan_encap *)sample_action[1].conf; ++ port_id = (struct rte_flow_action_port_id *)(uintptr_t)sample_action[0].conf; ++ vxlan_encap = (struct rte_flow_action_vxlan_encap *)(uintptr_t)sample_action[1].conf; + + hinic3_free_vxlan_header(vxlan_encap); + hinic3_free(port_id); +- hinic3_free(HINIC3_CONST_CAST(void *, sample_action)); ++ hinic3_free((void *)(uintptr_t)sample_action); + } + +- hinic3_free(HINIC3_CONST_CAST(void*, sample)); ++ hinic3_free((void *)(uintptr_t)sample); + return; + } + +@@ -66,13 +66,13 @@ static void hinic3_free_rte_flow_action(struct rte_flow_action *action) + if (action->conf != NULL) { + switch (action->type) { + case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: +- hinic3_free_vxlan_header(HINIC3_CONST_CAST(void *, action->conf)); ++ hinic3_free_vxlan_header((void *)(uintptr_t)action->conf); + break; + case RTE_FLOW_ACTION_TYPE_SAMPLE: + hinic3_free_rte_sample_action(action); + break; + default: +- hinic3_free(HINIC3_CONST_CAST(void *, action->conf)); ++ hinic3_free((void *)(uintptr_t)action->conf); + action->conf = NULL; + break; + } +@@ -179,13 +179,13 @@ static struct rte_flow_action *hinic3_vlan_action_factory(enum rte_flow_action_t + + static int hinic3_flow_dump_mac_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) + { +- void *conf_meta = NULL; ++ const void *conf_meta = NULL; + void *conf = hinic3_calloc(1, sizeof(struct eth_address), HINIC3_FLOWS); + if (conf == NULL) { + HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, build rte flow action conf failed"); + return -1; + } +- conf_meta = (void *)hinic3_nlattr_get_itr_unspec(nla, sizeof(struct eth_address)); ++ conf_meta = (const void *)hinic3_nlattr_get_itr_unspec(nla, sizeof(struct eth_address)); + if (conf_meta == NULL) { + HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get mac conf failed"); + return -1; +@@ -263,7 +263,7 @@ static int hinic3_flow_dump_port_conf(const hinic3_nlattr_itr nla, void **dst_co + static int hinic3_flow_dump_vxlan_conf_get(const hinic3_nlattr_itr nla, void **dst_conf) + { + hinic3_act_vxlan_header *meta_header = +- (hinic3_act_vxlan_header *)hinic3_nlattr_get_itr_unspec(nla, sizeof(hinic3_act_vxlan_header)); ++ (hinic3_act_vxlan_header *)(uintptr_t)hinic3_nlattr_get_itr_unspec(nla, sizeof(hinic3_act_vxlan_header)); + if (meta_header == NULL) { + HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, get vxlan header failed"); + return -1; +@@ -278,7 +278,7 @@ static int hinic3_flow_dump_vxlan_conf_get(const hinic3_nlattr_itr nla, void **d + return 0; + } + +-struct rte_flow_action_port_id *hinic3_flow_dump_sample_port_conf(uint8_t session_id) ++static struct rte_flow_action_port_id *hinic3_flow_dump_sample_port_conf(uint8_t session_id) + { + struct rte_flow_action_port_id *output_port = NULL; + int ret = 0; +@@ -307,7 +307,7 @@ struct rte_flow_action_port_id *hinic3_flow_dump_sample_port_conf(uint8_t sessio + return output_port; + } + +-struct rte_flow_action_vxlan_encap *hinic3_flow_dump_sample_vxlan_encap_conf(uint8_t session_id) ++static struct rte_flow_action_vxlan_encap *hinic3_flow_dump_sample_vxlan_encap_conf(uint8_t session_id) + { + struct hinic3_flow_act_vxlan_gpe_header meta_header = { 0 }; + int ret = hinic3_flow_dump_construct_vxlan_header(session_id, &meta_header); +@@ -318,7 +318,7 @@ struct rte_flow_action_vxlan_encap *hinic3_flow_dump_sample_vxlan_encap_conf(uin + return hinic3_get_vxlan_gpe_header_items(&meta_header); + } + +-struct rte_flow_action *hinic3_flow_dump_construct_sample_actions(const struct hiovs_mirror_info *mirror_info) ++static struct rte_flow_action *hinic3_flow_dump_construct_sample_actions(const struct hiovs_mirror_info *mirror_info) + { + enum hinic3_session_tpye session_type; + struct rte_flow_action *actions = NULL; +@@ -349,7 +349,7 @@ struct rte_flow_action *hinic3_flow_dump_construct_sample_actions(const struct h + vxlan_encap_action->conf = hinic3_flow_dump_sample_nvgre_encap_conf(session_id); + } + if (vxlan_encap_action->conf == NULL) { +- hinic3_free(HINIC3_CONST_CAST(void *, port_id_action->conf)); ++ hinic3_free((void *)(uintptr_t)port_id_action->conf); + hinic3_free(actions); + HINIC3_LOG(ERR, FLOW, "hinic3 flow dump, construct sample port conf filed"); + return NULL; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c +index d056b6cc69..e96e5985e1 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item.c +@@ -15,15 +15,15 @@ static void hinic3_free_rte_flow_item(struct rte_flow_item *item) + return; + } + if (item -> spec != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void*, item -> spec)); ++ hinic3_free((void *)(uintptr_t)item -> spec); + item -> spec = NULL; + } + if (item -> last != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void*, item -> last)); ++ hinic3_free((void *)(uintptr_t)item -> last); + item -> last = NULL; + } + if (item -> mask != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void*, item -> mask)); ++ hinic3_free((void *)(uintptr_t)item -> mask); + item -> mask = NULL; + } + } +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c +index 6cab59b9ca..dfa4ddda31 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c +@@ -68,14 +68,14 @@ static void hinic3_construct_ip_key(enum hinic3_flow_key_type type, const hinic3 + static void hinic3_construct_mac_key(enum hinic3_flow_key_type type, const hinic3_nlattr_itr nla, + struct hinic3_key_mac *mac) + { +- uint8_t *nla_mac = NULL; ++ const uint8_t *nla_mac = NULL; + switch (type) { + case HINIC3_FLOW_KEY_SRC_MAC: +- nla_mac = (uint8_t*)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ nla_mac = (const uint8_t*)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); + memcpy(mac -> smac, nla_mac, sizeof(mac->smac)); + break; + case HINIC3_FLOW_KEY_DST_MAC: +- nla_mac = (uint8_t*)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); ++ nla_mac = (const uint8_t*)hinic3_nlattr_get_itr_unspec(nla, ETH_ALEN); + memcpy(mac -> dmac, nla_mac, sizeof(mac->dmac)); + break; + default: +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c +index 59d5d85a25..8bd4a2b17f 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_emc_dump.c +@@ -90,7 +90,7 @@ static int hinic3_emc_flow_dump_start_sub(struct hinic3_flow_dump_context *conte + return 0; + } + +-int hinic3_emc_flow_dump_done_sub(struct hinic3_flow_dump_context *context) ++static int hinic3_emc_flow_dump_done_sub(struct hinic3_flow_dump_context *context) + { + int ret = 0; + if (context->hiovs_state != NULL) { +@@ -104,7 +104,7 @@ int hinic3_emc_flow_dump_done_sub(struct hinic3_flow_dump_context *context) + return ret; + } + +-int hinic3_emc_flow_dump_start(struct hinic3_flow_dump_context *context, struct rte_flow_error *error) ++static int hinic3_emc_flow_dump_start(struct hinic3_flow_dump_context *context, struct rte_flow_error *error) + { + if (context == NULL || error == NULL) { + return -1; +@@ -118,7 +118,7 @@ int hinic3_emc_flow_dump_start(struct hinic3_flow_dump_context *context, struct + return ret; + } + +-int hinic3_emc_flow_dump_next(struct hinic3_flow_dump_context *context, int count, struct rte_flow_error *error) ++static int hinic3_emc_flow_dump_next(struct hinic3_flow_dump_context *context, int count, struct rte_flow_error *error) + { + if (context == NULL || error == NULL) { + return -1; +@@ -132,7 +132,7 @@ int hinic3_emc_flow_dump_next(struct hinic3_flow_dump_context *context, int coun + return ret; + } + +-int hinic3_emc_flow_dump_done(struct hinic3_flow_dump_context *context, struct rte_flow_error *error) ++static int hinic3_emc_flow_dump_done(struct hinic3_flow_dump_context *context, struct rte_flow_error *error) + { + if (context == NULL || error == NULL) { + return -1; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.c +new file mode 100644 +index 0000000000..5c06667865 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.c +@@ -0,0 +1,63 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#include ++#include "hinic3_command.h" ++#include "hinic3_cmd_exec.h" ++#include "hinic3_capture_utils.h" ++#include "hinic3_agent_cmd_format.h" ++#include "hinic3_iface_flow.h" ++#include "hinic3_ui_string.h" ++#include "hinic3_string_util.h" ++#include "hinic3_parse_agent_config.h" ++#include "hinic3_ds.h" ++#include "hinic3_offload_flow_public.h" ++#include "hinic3_ufid_hmap.h" ++#include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_ufid_del_flow.h" ++#define ARGC 2 ++ ++static void hinic3_flow_del_by_ufid_ovs(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++{ ++ struct ds ds = DS_EMPTY_INITIALIZER; ++ uint64_t ufid; ++ int ret; ++ if (argc != ARGC) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_FLOW_REQUIRES_WRONG_ARGUMENT_STRING, argc - 1); ++ goto out; ++ } ++ ++ ret = hinic3_parse_hw_ufid_from_string(argv[1], &ufid); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_ERROR HINIC3_UI_UFID_MAP_HW_UFID_FORMART_ERROR_STRING); ++ goto out; ++ } ++ ++ ret = hinic3_flow_del_by_ufid(ufid); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, "Failure: Delete hw flow by ufid failed.\n"); ++ goto out; ++ } ++ ++ ret = hinic3_flow_destroy_in_hmap_by_ufid(ufid); ++ if (ret != 0) { ++ hinic3_ds_put_format(&ds, "Failure: Delete rte flow by ufid failed.\n"); ++ goto out; ++ } ++ ++ hinic3_ds_put_format(&ds, HINIC3_UI_LEADING_SIGN_INFO HINIC3_UI_FLOW_DELETE_BY_UFID_SUCCESS); ++ hinic3_command_reply(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++out: ++ *(int*)aux = -1; ++ hinic3_command_reply_error(conn, hinic3_ds_cstr(&ds)); ++ hinic3_ds_destroy(&ds); ++ return; ++} ++ ++void unixctl_hinic3_delete_cmd_init(void) ++{ ++ hinic3_command_register("hwoff/del-flow-by-ufid", "", 1, 1, hinic3_flow_del_by_ufid_ovs, NULL); ++} +\ No newline at end of file +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.h b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.h +new file mode 100644 +index 0000000000..055b98ccd8 +--- /dev/null ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_ufid_del_flow.h +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2024 Huawei Technologies Co., Ltd ++ */ ++ ++#ifndef HINIC3_UFID_DEL_FLOW_H ++#define HINIC3_UFID_DEL_FLOW_H ++ ++void unixctl_hinic3_delete_cmd_init(void); ++#endif +\ No newline at end of file +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +index 289d6ed92a..40ebf14cdf 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +@@ -130,7 +130,7 @@ int hinic3_flow_query_ufid(const struct rte_flow_attr *attr, const struct rte_fl + goto err; + } + hinic3_offload_flow_construct_key(&full_key->key, &hinic3_put_key); +- ret = hinic3_flow_mgmt_get_by_key(hinic3_put_key.data, hinic3_put_key.used_len, &put_flow, g_get_related_ufid); ++ ret = hinic3_flow_mgmt_get_by_key(hinic3_put_key.data, hinic3_put_key.used_len, &put_flow, &g_get_related_ufid); + if (ret == 0) { + *ufid = put_flow.hw_ufid; + if (ds != NULL) { +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c +index 4cd75d0978..6cb873f72a 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_dump.c +@@ -167,7 +167,7 @@ static void hinic3_dump_next_output(const struct hinic3_dump_flow_mem* context_m + return; + } + +-int hinic3_dump_context_input_check(const struct hinic3_flow_dump_context* context, ++static int hinic3_dump_context_input_check(const struct hinic3_flow_dump_context* context, + enum hinic3_dump_context_status type) + { + if (context->thread_id != pthread_self()) { +@@ -261,7 +261,7 @@ static void hinic3_flow_dump_context_reset(struct hinic3_flow_dump_context *cont + return; + } + +-int hinic3_accurate_flow_dump_done_sub(void *context, struct rte_flow_error *error) ++static int hinic3_accurate_flow_dump_done_sub(void *context, struct rte_flow_error *error) + { + if (context == NULL || error == NULL) { + return -EINVAL; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c +index 87c9a7048f..2171abfbac 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c +@@ -66,8 +66,8 @@ static int hinic3_process_ipv4(const struct rte_flow_item* item, enum hinic3_key + return -1; + } + +- char *src_str = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_SRC_OUT_IP_STR; +- char *dst_str = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ? HINIC3_UI_KEY_DST_IP_STR : HINIC3_UI_KEY_DST_OUT_IP_STR; ++ const char *src_str = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_SRC_OUT_IP_STR; ++ const char *dst_str = item->type == RTE_FLOW_ITEM_TYPE_IPV4 ? HINIC3_UI_KEY_DST_IP_STR : HINIC3_UI_KEY_DST_OUT_IP_STR; + + hinic3_ds_put_format(ds, "%s(" IP_FMT "),", src_str, IP_ARGS(ipv4->hdr.src_addr)); + hinic3_ds_put_format(ds, "%s(" IP_FMT "),", dst_str, IP_ARGS(ipv4->hdr.dst_addr)); +@@ -86,15 +86,15 @@ static int hinic3_process_ipv6(const struct rte_flow_item* item, enum hinic3_key + HINIC3_LOG(ERR, FLOW, "hinic3_process_ipv6: Invalid ipv6 item ptr"); + return -1; + } +- char *src_str = item->type == RTE_FLOW_ITEM_TYPE_IPV6 ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_SRC_OUT_IP_STR; +- char *dst_str = item->type == RTE_FLOW_ITEM_TYPE_IPV6 ? HINIC3_UI_KEY_DST_IP_STR : HINIC3_UI_KEY_DST_OUT_IP_STR; ++ const char *src_str = item->type == RTE_FLOW_ITEM_TYPE_IPV6 ? HINIC3_UI_KEY_SRC_IP_STR : HINIC3_UI_KEY_SRC_OUT_IP_STR; ++ const char *dst_str = item->type == RTE_FLOW_ITEM_TYPE_IPV6 ? HINIC3_UI_KEY_DST_IP_STR : HINIC3_UI_KEY_DST_OUT_IP_STR; + + hinic3_ds_put_format(ds, "%s(", src_str); +- hinic3_ipv6_format_addr((struct in6_addr*)ipv6->hdr.src_addr, ds); ++ hinic3_ipv6_format_addr((const struct in6_addr*)ipv6->hdr.src_addr, ds); + hinic3_ds_put_format(ds, "),"); + + hinic3_ds_put_format(ds, "%s(", dst_str); +- hinic3_ipv6_format_addr((struct in6_addr*)ipv6->hdr.dst_addr, ds); ++ hinic3_ipv6_format_addr((const struct in6_addr*)ipv6->hdr.dst_addr, ds); + hinic3_ds_put_format(ds, "),"); + + if (item->type == RTE_FLOW_ITEM_TYPE_IPV6) { +@@ -148,9 +148,9 @@ static int hinic3_process_icmp(const struct rte_flow_item* item, enum hinic3_key + return -1; + } + +- char *icmp_type_str = item->type == RTE_FLOW_ITEM_TYPE_ICMP ? HINIC3_UI_KEY_ICMP_TYPE_STR : ++ const char *icmp_type_str = item->type == RTE_FLOW_ITEM_TYPE_ICMP ? HINIC3_UI_KEY_ICMP_TYPE_STR : + HINIC3_UI_KEY_ICMP6_TYPE_STR; +- char *icmp_code_str = item->type == RTE_FLOW_ITEM_TYPE_ICMP ? HINIC3_UI_KEY_ICMP_CODE_STR : ++ const char *icmp_code_str = item->type == RTE_FLOW_ITEM_TYPE_ICMP ? HINIC3_UI_KEY_ICMP_CODE_STR : + HINIC3_UI_KEY_ICMP6_CODE_STR; + + hinic3_ds_put_format(ds, "%s(%hhu),", icmp_type_str, icmp->hdr.icmp_type); +@@ -273,7 +273,7 @@ static int hinic3_process_acl_sample(const struct rte_flow_action *action, struc + return -1; + } + +- const struct rte_flow_action_port_id *output_port = (struct rte_flow_action_port_id *)act->conf; ++ const struct rte_flow_action_port_id *output_port = (const struct rte_flow_action_port_id *)act->conf; + if (output_port == NULL) { + HINIC3_LOG(ERR, FLOW, "hinic3 process acl sample port id conf is null."); + return -1; +@@ -525,11 +525,11 @@ void hinic3_free_flow(struct hinic3_flow *flow) + for (int i = 0; i < HINIC3_FLOW_ITEMS_NUM; ++i) { + if (flow->items[i].type != RTE_FLOW_ITEM_TYPE_END) { + if (flow->items[i].spec != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void *, flow->items[i].spec)); ++ hinic3_free((void *)(uintptr_t)flow->items[i].spec); + flow->items[i].spec = NULL; + } + if (flow->items[i].mask != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void *, flow->items[i].mask)); ++ hinic3_free((void *)(uintptr_t)flow->items[i].mask); + flow->items[i].mask = NULL; + } + flow->items[i].type = RTE_FLOW_ITEM_TYPE_END; +@@ -539,7 +539,7 @@ void hinic3_free_flow(struct hinic3_flow *flow) + for (int i = 0; i < HINIC3_FLOW_ACTIONS_NUM; ++i) { + if (flow->actions[i].type == RTE_FLOW_ACTION_TYPE_CONNTRACK) { + if (flow->actions[i].conf != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void *, flow->actions[i].conf)); ++ hinic3_free((void *)(uintptr_t)flow->actions[i].conf); + flow->actions[i].conf = NULL; + } + flow->actions[i].type = RTE_FLOW_ACTION_TYPE_END; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c +index 65ebe6edf8..a77cb0760f 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c +@@ -15,7 +15,7 @@ + static int hinic3_parse_mirror_IPv4_item(const struct rte_flow_item *item, + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { +- const struct rte_flow_item_ipv4 *ip = (struct rte_flow_item_ipv4 *)item->spec; ++ const struct rte_flow_item_ipv4 *ip = (const struct rte_flow_item_ipv4 *)item->spec; + if (ip == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV4_ITEM, 1); + return -1; +@@ -30,7 +30,7 @@ static int hinic3_parse_mirror_IPv4_item(const struct rte_flow_item *item, + static int hinic3_parse_mirror_vlan_item(const struct rte_flow_item *item, + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { +- const struct rte_flow_item_vlan *vlan = (struct rte_flow_item_vlan *)item->spec; ++ const struct rte_flow_item_vlan *vlan = (const struct rte_flow_item_vlan *)item->spec; + if (vlan == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_VLAN_ITEM, 1); + return -1; +@@ -44,7 +44,7 @@ static int hinic3_parse_mirror_vlan_item(const struct rte_flow_item *item, + static int hinic3_parse_mirror_eth_item(const struct rte_flow_item *item, + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { +- const struct rte_flow_item_eth *eth = (struct rte_flow_item_eth *)item->spec; ++ const struct rte_flow_item_eth *eth = (const struct rte_flow_item_eth *)item->spec; + if (eth == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_ETH_ITEM, 1); + return -1; +@@ -59,7 +59,7 @@ static int hinic3_parse_mirror_eth_item(const struct rte_flow_item *item, + static int hinic3_parse_mirror_IPv6_item(const struct rte_flow_item *item, + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { +- const struct rte_flow_item_ipv6 *ip = (struct rte_flow_item_ipv6 *)item->spec; ++ const struct rte_flow_item_ipv6 *ip = (const struct rte_flow_item_ipv6 *)item->spec; + if (ip == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_IPV6_ITEM, 1); + return -1; +@@ -80,7 +80,7 @@ static int hinic3_parse_mirror_IPv6_item(const struct rte_flow_item *item, + static int hinic3_parse_mirror_vxlan_item(const struct rte_flow_item *item, + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { +- const struct rte_flow_item_vxlan *vxlan = (struct rte_flow_item_vxlan *)item->spec; ++ const struct rte_flow_item_vxlan *vxlan = (const struct rte_flow_item_vxlan *)item->spec; + if (vxlan == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_VXLAN_ITEM, 1); + return -1; +@@ -98,7 +98,7 @@ static int hinic3_parse_mirror_vxlan_item(const struct rte_flow_item *item, + static int hinic3_parse_mirror_udp_item(const struct rte_flow_item *item, + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { +- const struct rte_flow_item_udp *udp = (struct rte_flow_item_udp *)item->spec; ++ const struct rte_flow_item_udp *udp = (const struct rte_flow_item_udp *)item->spec; + if (udp == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_UDP_ITEM, 1); + return -1; +@@ -113,7 +113,7 @@ static int hinic3_parse_mirror_udp_item(const struct rte_flow_item *item, + static int hinic3_parse_mirror_gre_item(const struct rte_flow_item *item, + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { +- const struct rte_flow_item_gre *gre = (struct rte_flow_item_gre *)item->spec; ++ const struct rte_flow_item_gre *gre = (const struct rte_flow_item_gre *)item->spec; + if (gre == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_NVGRE_ITEM, 1); + return -1; +@@ -143,7 +143,7 @@ static struct hinic3_mirror_vxlan_item_func_map hinic3_mirror_vxlan_item_func_ar + {RTE_FLOW_ITEM_TYPE_GRE, hinic3_parse_mirror_gre_item}, + }; + +-bool hinic3_check_session_ip_type_flag(uint32_t ip_type_flag) ++static bool hinic3_check_session_ip_type_flag(uint32_t ip_type_flag) + { + switch (ip_type_flag) { + case HINIC3_FLG_MIRROR_IPV4_VLAN: +@@ -164,7 +164,7 @@ static int hinic3_parse_mirror_vxlan_nvgre_act(const struct rte_flow_action *act + struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) + { + int ret = 0; +- const struct rte_flow_action_vxlan_encap *encap_info = (struct rte_flow_action_vxlan_encap *)act->conf; ++ const struct rte_flow_action_vxlan_encap *encap_info = (const struct rte_flow_action_vxlan_encap *)act->conf; + if (encap_info == NULL || encap_info->definition == NULL) { + return -1; + } +@@ -194,7 +194,7 @@ static int hinic3_parse_mirror_vxlan_nvgre_act(const struct rte_flow_action *act + static int hinic3_parse_mirror_port_id_act(const struct rte_flow_action *act, + struct hinic3_mirror_session_info *session_info) + { +- const struct rte_flow_action_port_id *output_port = (struct rte_flow_action_port_id *)act->conf; ++ const struct rte_flow_action_port_id *output_port = (const struct rte_flow_action_port_id *)act->conf; + if (output_port == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_PORT_ID, 1); + return -1; +@@ -256,7 +256,7 @@ int hinic3_offload_parse_sample_act(const struct rte_flow_action *act, struct hi + struct rte_flow *flow, uint8_t mirror_dir_flag) + { + int ret = 0; +- struct rte_flow_action_sample *sample_info = (struct rte_flow_action_sample *)act->conf; ++ const struct rte_flow_action_sample *sample_info = (const struct rte_flow_action_sample *)act->conf; + if (sample_info == NULL || sample_info->actions == NULL) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_SAMPLE_ACTION, 1); + return -1; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c +index 73e3885ebf..4b4d32203e 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c +@@ -220,7 +220,7 @@ struct rte_flow_action_vxlan_encap *hinic3_flow_dump_sample_nvgre_encap_conf(uin + err: + for (int i = 0; i < HINIC3_DUMP_NVGRE_MAX_ITEMS; i++) { + if (nvgre_items[i].spec != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void*, nvgre_items[i].spec)); ++ hinic3_free((void*)(uintptr_t)nvgre_items[i].spec); + } + } + hinic3_free(nvgre_items); +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c +index f74e297a49..f67973cdfe 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c +@@ -15,7 +15,7 @@ + + static int hinic3_info_need(char *buf, int buffer_size) + { +- static char *infos[] = { ++ static const char *infos[] = { + "Card information", + "card type", + "port num", +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c +index 5d198b8af0..f84149a73f 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_action.c +@@ -10,6 +10,7 @@ + #include "hinic3_parse_agent_config.h" + #include "hinic3_dpdk_adapter.h" + #include "hinic3_port_util.h" ++#include "hinic3_offload_action.h" + + #define HINIC3_RTE_VLAN_PCP_MASK 0xe0 + #define VLAN_PCP_MOVE 8 +@@ -65,7 +66,7 @@ static int hinic3_add_port_id_action(const struct rte_flow_action *act, struct h + + const struct rte_flow_action_port_id *output_port = NULL; + uint32_t output_port_id; +- output_port = (struct rte_flow_action_port_id *)act->conf; ++ output_port = (const struct rte_flow_action_port_id *)act->conf; + output_port_id = hinic3_process_port_id(output_port->id); + if (output_port_id > UINT16_MAX) { + HINIC3_LOG(ERR, FLOW, "port_id exceeds the maximum range of driver."); +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c +index d193d8f915..d579f1d419 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c +@@ -35,8 +35,8 @@ + static void hinic3_flow_agent_construct_5tuple(struct hinic3_nlattr *hinic3_key, + const struct hinic3_conntrack_key *key) + { +- struct hinic3_key_5tuple *tuple = (struct hinic3_key_5tuple *)key->key; +- struct hinic3_key_raw_ip *raw_ip = (struct hinic3_key_raw_ip *)key->key; ++ const struct hinic3_key_5tuple *tuple = (const struct hinic3_key_5tuple *)key->key; ++ const struct hinic3_key_raw_ip *raw_ip = (const struct hinic3_key_raw_ip *)key->key; + hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_DL_TYPE, tuple->ip.ether_type); + if (tuple->ip.ether_type == htons(ETH_TYPE_IP)) { + hinic3_nlattr_put_u32(hinic3_key, HINIC3_FLOW_KEY_SRC_IP, tuple->ip.src.ipv4); +@@ -58,17 +58,17 @@ static void hinic3_flow_agent_construct_5tuple(struct hinic3_nlattr *hinic3_key, + + void hinic3_offload_flow_construct_key(const struct hinic3_conntrack_key *key, struct hinic3_nlattr *hinic3_key) + { +- struct hinic3_key_mac *mac_tuple = (struct hinic3_key_mac *)key->key; +- struct hinic3_key_vxlan_vid_5tuple *port_key = (struct hinic3_key_vxlan_vid_5tuple *)key->key; ++ const struct hinic3_key_mac *mac_tuple = (const struct hinic3_key_mac *)key->key; ++ const struct hinic3_key_vxlan_vid_5tuple *port_key = (const struct hinic3_key_vxlan_vid_5tuple *)key->key; + + hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_IN_PORT, port_key->input_port); + hinic3_nlattr_put_unspec(hinic3_key, HINIC3_FLOW_KEY_DST_MAC, mac_tuple->dmac, sizeof(mac_tuple->dmac)); + hinic3_nlattr_put_unspec(hinic3_key, HINIC3_FLOW_KEY_SRC_MAC, mac_tuple->smac, sizeof(mac_tuple->smac)); + +- struct hinic3_key_vxlan *vxlan = &(((struct hinic3_key_vxlan_vid_5tuple *)key->key)->vxlan); ++ const struct hinic3_key_vxlan *vxlan = &(((const struct hinic3_key_vxlan_vid_5tuple *)key->key)->vxlan); + hinic3_nlattr_put_u32(hinic3_key, HINIC3_FLOW_KEY_VNI, vxlan->vni); + +- uint16_t outer_vid = ((struct hinic3_key_vid_5tuple *)key->key)->outer_vid; ++ uint16_t outer_vid = ((const struct hinic3_key_vid_5tuple *)key->key)->outer_vid; + hinic3_nlattr_put_u16(hinic3_key, HINIC3_FLOW_KEY_OUTER_VID, outer_vid); + + hinic3_flow_agent_construct_5tuple(hinic3_key, key); +@@ -182,9 +182,6 @@ static int hinic3_parse_in_port_id(const struct rte_flow_item *item, struct hini + + port_id_item = item->spec; + port_id = (uint16_t)hinic3_process_port_id(port_id_item->id); +- if (port_id > UINT16_MAX) { +- return -1; +- } + port_key->input_port = htons(port_id); + return 0; + } +@@ -383,16 +380,6 @@ static void hinic3_offload_parse_flow_args(struct hinic3_flow_offload_param *par + hinic3_trace_flow_info_update(HINIC3_AGENT_IS_FLOW_READY_PUT_DONE_TRACE, &flow->key.key); + } + +-static void hinic3_offload_parse_modify_flow_args(struct hinic3_flow_offload_param *param, struct rte_flow *flow, +- uint32_t flow_hash) +-{ +- hinic3_nlattr_init(¶m->hinic3_args, param->offload_buff.args_buf, HINIC3_MSG_MAX_BUF); +- hinic3_nlattr_put_unspec(¶m->hinic3_args, HINIC3_FLOW_ARG_NO_CT_UFID, +- &flow->key, sizeof(struct hinic3_conntrack_full_key)); +- hinic3_nlattr_put_flag(¶m->hinic3_args, HINIC3_FLOW_ARG_MODIFY); +- hinic3_nlattr_put_u32(¶m->hinic3_args, HINIC3_FLOW_ARG_FLOW_HASH, flow_hash); +-} +- + static int hinic3_alloc_get_f(struct hinic3_dpif_flow_for_get *f) + { + f->key = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c +index 76fc7b4c29..afe95dd539 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c +@@ -127,7 +127,7 @@ static struct pcap_sub_key_parser g_input_key_parser[] = { + }; + + struct hinic3_input_key { +- char *key; ++ const char *key; + bool is_input_key; + }; + +@@ -267,7 +267,7 @@ static bool hinic3_check_querry_flow_key_is_complete(uint8_t ip_proto) + } + + static int hinic3_sub_key_parse(struct unixctl_conn *conn, struct pcap_key_t *cap_key, +- const char *key_name, char *value, struct ds *ds) ++ const char *key_name, const char *value, struct ds *ds) + { + size_t i = 0; + int ret = 0; +@@ -417,7 +417,7 @@ static void get_input_key(const char *key, struct pcap_key_t *cap_key) + return; + } + +-int hinic3_input_key_parse(struct unixctl_conn *conn, struct pcap_key_t *cap_key, int argc, ++static int hinic3_input_key_parse(struct unixctl_conn *conn, struct pcap_key_t *cap_key, int argc, + const char *argv[], struct ds *ds) + { + int ret; +@@ -433,7 +433,7 @@ int hinic3_input_key_parse(struct unixctl_conn *conn, struct pcap_key_t *cap_key + } + + while (i < work_argc) { +- ret = hinic3_sub_key_parse(conn, cap_key, (char *)work_argv[i], (char *)work_argv[i + 1], ds); ++ ret = hinic3_sub_key_parse(conn, cap_key, work_argv[i], (const char *)work_argv[i + 1], ds); + if (ret != 0) { + HINIC3_LOG(ERR, FLOW, "key_parse error\n"); + return -1; +@@ -647,13 +647,13 @@ static void hinic3_query_pattern_free(struct rte_flow_item *pattern) + int i = 0; + for (i = 0; i < HINIC3_INPUT_ITEM_MAX_NUM; i++) { + if (pattern[i].type != RTE_FLOW_ITEM_TYPE_END && pattern[i].spec == NULL) { +- hinic3_free((void*)pattern[i].spec); ++ hinic3_free((void*)(uintptr_t)pattern[i].spec); + pattern[i].spec = NULL; + } + } + } + +-int hinic3_get_pattern(struct rte_flow_item *pattern, struct input_key *item_key) ++static int hinic3_get_pattern(struct rte_flow_item *pattern, struct input_key *item_key) + { + int i = 0; + int ret = 0; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c +index c995bee454..68150810c2 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan_dump.c +@@ -243,7 +243,7 @@ void hinic3_free_vxlan_header(struct rte_flow_action_vxlan_encap *vxlan_header) + break; + } + if (vxlan_header_items[i].spec != NULL) { +- hinic3_free(HINIC3_CONST_CAST(void *, vxlan_header_items[i].spec)); ++ hinic3_free((void *)(uintptr_t)vxlan_header_items[i].spec); + vxlan_header_items[i].spec = NULL; + } + } +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c +index 460a316fd8..720ee55a0e 100644 +--- a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_agent.c +@@ -70,7 +70,7 @@ int hinic3_is_softlink(const char *cfg_file) + return 0; + } + +-static void hinic3_solution_vitrio_wait() ++static void hinic3_solution_vitrio_wait(void) + { + int ret; + FILE *fp = NULL; +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c +index bfd4ac0e0e..befea54f31 100644 +--- a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_flow_agent.c +@@ -332,11 +332,11 @@ static void hinic3_process_flow_put_callback_info(const struct hinic3_nlattr *ar + callback_info->is_ct = true; + break; + case HINIC3_FLOW_ARG_CT_DIRECT: +- callback_info->reply = *(bool*)hinic3_nlattr_get_itr_data(nla); ++ callback_info->reply = *(const bool*)hinic3_nlattr_get_itr_data(nla); + break; + case HINIC3_FLOW_ARG_SW_UFID: + callback_info->mega_ufid = +- *(hinic3_u128 *)hinic3_nlattr_get_itr_unspec(nla, sizeof(hinic3_u128)); ++ *(const hinic3_u128 *)hinic3_nlattr_get_itr_unspec(nla, sizeof(hinic3_u128)); + break; + default: + break; +@@ -435,7 +435,7 @@ static int hinic3_flow_agent_init_common(struct hinic3_flow_agent_db *hinic3_db) + return ret; + } + +-static struct hinic3_flow_agent_db *hinic3_flow_agent_init_database() ++static struct hinic3_flow_agent_db *hinic3_flow_agent_init_database(void) + { + int ret = 0; + struct hinic3_flow_agent_db *hinic3_db = hinic3_calloc(1, sizeof(struct hinic3_flow_agent_db), HINIC3_INIT); +@@ -467,7 +467,7 @@ static int hinic3_flow_callback(uint64_t ufid, const struct hinic3_dpif_flow_for + uint8_t flush_ret = 0xff; + int ret; + +- hinic3_nlattr_init(&nla_args, HINIC3_CONST_CAST(struct hinic3_nlattr_obj *, args), args_len); ++ hinic3_nlattr_init(&nla_args,(void *)(uintptr_t)args, args_len); + hinic3_nlattr_reset_itr(&nla_args, args_len); + HINIC3_NLATTR_FOR_EACH(nla, &nla_args) + { +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c +index 109837523f..d423dc364e 100644 +--- a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.c +@@ -475,7 +475,7 @@ struct hinic3_init_arg *hinic3_get_init_arg(void) + return &g_agent_config_init_arg; + } + +-void hinic3_set_config_value(void) ++static void hinic3_set_config_value(void) + { + struct hinic3_init_arg *arg = hinic3_get_fixed_config(); + g_agent_config_init_arg.add_port_when_init = arg->add_port_when_init; +diff --git a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h +index a52d63e9a0..507d68d3a4 100644 +--- a/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h ++++ b/drivers/net/hinic3/src/hinic3_init/comm/hinic3_parse_agent_config.h +@@ -45,13 +45,13 @@ static inline char *hinic3_pf_pci_addr_get(void) + return conf->pf_pci_addr; + } + +-static inline struct hinic3_cpu_mask hinic3_forward_cpu_mask_get() ++static inline struct hinic3_cpu_mask hinic3_forward_cpu_mask_get(void) + { + struct hinic3_init_arg *conf = hinic3_get_init_arg(); + return conf->forward_cpu_mask; + } + +-static inline struct hinic3_cpu_mask hinic3_control_cpu_mask_get() ++static inline struct hinic3_cpu_mask hinic3_control_cpu_mask_get(void) + { + struct hinic3_init_arg *conf = hinic3_get_init_arg(); + return conf->control_cpu_mask; +diff --git a/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h b/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h +index 5e48ee4ef3..e11c0ebb5f 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h ++++ b/drivers/net/hinic3/src/hinic3_ports/comm/hinic3_port_util.h +@@ -9,6 +9,7 @@ + #include "hinic3_meminfo.h" + #include "hinic3_hugepage_meminfo.h" + #include "hinic3_iface_port.h" ++#include "ethdev_driver.h" + + #define HINIC3_DEV_STATE_STOP 0 + #define HINIC3_DEV_STATE_START 1 +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +index 4149684984..416aecb0b8 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +@@ -556,7 +556,7 @@ hinic3_bond_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, + return 0; + } + +-void ++static void + hinic3_construct_priority_upcall_cfgs(struct hinic3_high_priority_cfgs *cfgs) + { + cfgs->cfgs_len = PRIORITY_UPCALL_MAX_NUM; +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c +index e4d44328a7..54367c76ad 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vdev/hinic3_vdev.c +@@ -228,7 +228,7 @@ open_function_id(const char *key __rte_unused, const char *value, void *extra_ar + return 0; + } + +-int hinic3_vf_parse_max_queue(struct rte_kvargs *kvlist, uint32_t *max_queue_num) ++static int hinic3_vf_parse_max_queue(struct rte_kvargs *kvlist, uint32_t *max_queue_num) + { + int ret = 0; + uint32_t count = 0; +@@ -282,7 +282,7 @@ hinic3_vf_parse_mac_addr(struct rte_kvargs *kvlist, struct eth_addr *mac_addr) + return 0; + } + +-int hinic3_vf_parse_function_id(struct rte_kvargs *kvlist, int *function_id) ++static int hinic3_vf_parse_function_id(struct rte_kvargs *kvlist, int *function_id) + { + int ret = 0; + uint32_t count = 0; +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c +index ea4e2c8d6e..77801df66a 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_function_statistics.c +@@ -20,6 +20,7 @@ + #include "hinic3_flow_dump.h" + #include "hinic3_offload_flow_port.h" + #include "hinic3_dpdk_adapter.h" ++#include "hinic3_function_statistics.h" + + int hinic3_vf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) + { +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c +index fc182deedc..7a65ecd004 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c +@@ -271,7 +271,7 @@ static int hinic3_vf_virtual_queue_port_add(struct hinic3_vf_dev *vf_dev) + return ret; + } + +-void hinic3_clear_vf_port_info(struct hinic3_vf_dev *vf_dev) ++static void hinic3_clear_vf_port_info(struct hinic3_vf_dev *vf_dev) + { + int ret = 0; + +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c +index 29116b76ac..4d8394e1ce 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_mgmt.c +@@ -74,7 +74,7 @@ static void hinic3_dev_mutex_uninit(void) + + struct dev_mgmt g_dev_list = {0}; + +-struct hinic3_dev_node *hinic3_alloc_dev_node(void) ++static struct hinic3_dev_node *hinic3_alloc_dev_node(void) + { + struct hinic3_dev_node *rc = NULL; + +@@ -172,7 +172,7 @@ static void hinic3_hwpt_flavor_destroy_list(struct hinic3_list *list) + } + } + +-void hinic3_hwpt_flavor_destroy_flavors(void) ++static void hinic3_hwpt_flavor_destroy_flavors(void) + { + hinic3_pthread_mutex_lock(&hwpt_phy_dev_mutex); + if (!hinic3_list_is_empty(&g_dev_list.vf_list)) { +@@ -184,7 +184,7 @@ void hinic3_hwpt_flavor_destroy_flavors(void) + hinic3_pthread_mutex_unlock(&hwpt_phy_dev_mutex); + } + +-int get_queue_pci_addr_from_str(const char *pci_addr_str, struct rte_pci_addr *pci_addr, uint8_t *queue_num_max) ++static int get_queue_pci_addr_from_str(const char *pci_addr_str, struct rte_pci_addr *pci_addr, uint8_t *queue_num_max) + { + int ret = -1; + union splitaddr hwpt_splitaddr; +@@ -235,7 +235,7 @@ int get_queue_pci_addr_from_str(const char *pci_addr_str, struct rte_pci_addr *p + return ret; + } + +-int hinic3_vf_check_pci(const struct rte_pci_addr *vf_pci_addr) ++static int hinic3_vf_check_pci(const struct rte_pci_addr *vf_pci_addr) + { + int ret; + char buf[BUFSIZE_SHORT] = {0}; +@@ -489,7 +489,7 @@ void mgmt_vf_virtio_queue(uint32_t max_queue_num, bool is_del) + } + } + +-int hinic3_insert_port_node(struct hinic3_dev_node *dev_node, struct dev_mgmt *dev) ++static int hinic3_insert_port_node(struct hinic3_dev_node *dev_node, struct dev_mgmt *dev) + { + struct hinic3_dev_node *rc = NULL; + +@@ -507,7 +507,7 @@ int hinic3_insert_port_node(struct hinic3_dev_node *dev_node, struct dev_mgmt *d + return 0; + } + +-int hinic3_get_used_port_info(struct dev_mgmt *dev) ++static int hinic3_get_used_port_info(struct dev_mgmt *dev) + { + int ret; + struct hinic3_dev_node *iter = NULL; +@@ -538,7 +538,7 @@ int hinic3_get_used_port_info(struct dev_mgmt *dev) + return 0; + } + +-bool hinic3_updata_vf_flavor_phy_dev_refcnt(const struct rte_pci_addr *pci_addr) ++static bool hinic3_updata_vf_flavor_phy_dev_refcnt(const struct rte_pci_addr *pci_addr) + { + struct hinic3_dev_node *iter_vf = NULL; + bool is_find_node = false; +@@ -558,7 +558,7 @@ bool hinic3_updata_vf_flavor_phy_dev_refcnt(const struct rte_pci_addr *pci_addr) + return is_find_node; + } + +-void hinic3_updata_vf_flavor_dev_info(struct dev_mgmt *dev) ++static void hinic3_updata_vf_flavor_dev_info(struct dev_mgmt *dev) + { + int ret; + struct hinic3_dev_node *iter = NULL; +@@ -589,7 +589,7 @@ void hinic3_updata_vf_flavor_dev_info(struct dev_mgmt *dev) + return; + } + +-void hinic3_destroy_used_port_info(struct dev_mgmt *dev) ++static void hinic3_destroy_used_port_info(struct dev_mgmt *dev) + { + if (!hinic3_list_is_empty(&(dev->vf_list))) { + hinic3_hwpt_flavor_destroy_list(&(dev->vf_list)); +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c +index 53b11c5545..8d31502457 100644 +--- a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c +@@ -90,7 +90,7 @@ static void hinic3_meter_mutex_all_unlock(void) + hinic3_meter_list_unlock(); + } + +-bool hinic_is_bond_by_prefix(uint16_t vport_id) ++static bool hinic_is_bond_by_prefix(uint16_t vport_id) + { + return (vport_id & HWOFF_PORT_TYPE_PREFIX) == HWOFF_BOND_TYPE_PREFIX; + } +@@ -577,11 +577,11 @@ static int hinic3_meter_actions_parse(const struct rte_flow_action *actions, uin + } + switch (act->type) { + case RTE_FLOW_ACTION_TYPE_METER: +- *meter_id = ((struct rte_flow_action_meter*)act->conf)->mtr_id; ++ *meter_id = ((const struct rte_flow_action_meter*)act->conf)->mtr_id; + break; + case RTE_FLOW_ACTION_TYPE_PORT_ID: + *direction = HINIC3_RX_METER_QOS; +- *port_id = ((struct rte_flow_action_port_id*)act->conf)->id; ++ *port_id = ((const struct rte_flow_action_port_id*)act->conf)->id; + break; + default: + break; +@@ -602,7 +602,7 @@ static int hinic3_meter_pattern_parse(const struct rte_flow_item *pattern, uint1 + } + switch (item->type) { + case RTE_FLOW_ITEM_TYPE_PORT_ID: +- *port_id = ((struct rte_flow_item_port_id*)item->spec)->id; ++ *port_id = ((const struct rte_flow_item_port_id*)item->spec)->id; + break; + default: + break; +@@ -642,7 +642,7 @@ static int hinic3_add_port_to_list(uint16_t vport_id, struct hinic3_meter_node * + return 0; + } + +-static uint16_t hinic3_meter_group_find_location() ++static uint16_t hinic3_meter_group_find_location(void) + { + int i; + for (i = 1; i < HINIC3_METER_NUM_MAX; i++) { +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c +index d4b80c6fc5..1a9dde7f2c 100644 +--- a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr_policy.c +@@ -49,7 +49,7 @@ static void hinic3_meter_color_action_parse(const struct rte_flow_action *action + + for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) { + if (action->type == RTE_FLOW_ACTION_TYPE_METER && action->conf != NULL) { +- mtr = (struct rte_flow_action_meter *)action->conf; ++ mtr = (const struct rte_flow_action_meter *)action->conf; + fmp->next_meter_id = mtr->mtr_id; + fmp->has_next_meter = true; + } +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h +index a01509f623..8e74783218 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.h +@@ -11,8 +11,8 @@ + #include "hinic3_ds.h" + + #define HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM (1 * (1 << 20)) +-#define HINIC3_RTE_FLOW_ELE_MPOOL_NAME "hinic3_rte_flow_ele_pool" +-#define HINIC3_UFID_MAP_MPOOL_NAME "hinic3_ufid_map_pool" ++#define HINIC3_RTE_FLOW_ELE_MPOOL_NAME "hwoff_rte_flow_ele_pool" ++#define HINIC3_UFID_MAP_MPOOL_NAME "hwoff_ufid_map_pool" + + struct hinic3_mpool_mgmt_rte_flow { + struct dpak_mempool *rte_flow_mpool; +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c +index 82eddfb411..c6c675d303 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c +@@ -89,7 +89,7 @@ struct rte_flow *hinic3_ufid_hmap_get(const struct hmap *ufid_hmap, + return node ? node->key : NULL; + } + +-void hinic3_ufid_hmap_remove_node(struct hmap *ufid_hmap, struct hinic3_ufid_hmap_node *node, HINIC3_UFID_MAP_TYPE type) ++static void hinic3_ufid_hmap_remove_node(struct hmap *ufid_hmap, struct hinic3_ufid_hmap_node *node, HINIC3_UFID_MAP_TYPE type) + { + hinic3_hmap_remove(ufid_hmap, &node->node); + hinic3_ufid_map_dealloc(ufid_hmap, node, type); +@@ -116,3 +116,26 @@ int hinic3_ufid_hmap_del_by_key(struct hmap *ufid_hmap, const struct hinic3_conn + hinic3_ufid_hmap_remove_node(ufid_hmap, ufid_hmap_node, type); + return 0; + } ++ ++static struct hinic3_ufid_hmap_node *hinic3_ufid_hmap_get_node_by_ufid(struct hmap *ufid_hmap, uint64_t hw_ufid) ++{ ++ struct hinic3_ufid_hmap_node *node, *next; ++ HINIC3_HMAP_FOR_EACH_SAFE(node, next, node, ufid_hmap) { ++ if (node->key->hw_ufid == hw_ufid) { ++ return node; ++ } ++ } ++ return NULL; ++} ++ ++int hinic3_ufid_hmap_del_by_ufid(struct hmap *ufid_hmap, uint64_t hw_ufid, HINIC3_UFID_MAP_TYPE type) ++{ ++ struct hinic3_ufid_hmap_node *ufid_hmap_node = NULL; ++ ++ ufid_hmap_node = hinic3_ufid_hmap_get_node_by_ufid(ufid_hmap, hw_ufid); ++ if (ufid_hmap_node == NULL) { ++ return -1; ++ } ++ hinic3_ufid_hmap_remove_node(ufid_hmap, ufid_hmap_node, type); ++ return 0; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h +index 4057784250..911603b6d4 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.h +@@ -28,5 +28,5 @@ struct rte_flow *hinic3_ufid_hmap_get(const struct hmap *ufid_hmap, + void hinic3_ufid_hmap_clear(struct hmap *ufid_hmap, HINIC3_UFID_MAP_TYPE type); + int hinic3_ufid_hmap_del_by_key(struct hmap *ufid_hmap, const struct hinic3_conntrack_full_key *full_key, uint32_t hash, + HINIC3_UFID_MAP_TYPE type); +- ++int hinic3_ufid_hmap_del_by_ufid(struct hmap *ufid_hmap, uint64_t hw_ufid, HINIC3_UFID_MAP_TYPE type); + #endif +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c +index 21e66abd39..89e7d5b548 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c +@@ -17,6 +17,7 @@ + #include "hinic3_command.h" + #include "hinic3_parse_agent_config.h" + #include "hinic3_ufid_map_rte_flow.h" ++#include "hinic3_ufid_hmap.h" + + static struct hinic3_ufid_map_table hinic3_mpool_mgmt; + struct stat_refresh_time g_stat_ref_time[HINIC3_COMMAND_QUEUES_NUM_MAX] = {0}; +@@ -75,7 +76,7 @@ uint32_t hinic3_hash_generate(const struct hinic3_conntrack_key *key) + hash = hinic3_hash_add(hash, key->meta_num); + + for (int idx = 0; idx < key->meta.key_len / sizeof(uint32_t); idx++) { +- hash = hinic3_hash_add(hash, ((uint32_t *)key->key)[idx]); ++ hash = hinic3_hash_add(hash, ((const uint32_t *)key->key)[idx]); + } + return hash; + } +@@ -142,7 +143,7 @@ int hinic3_insert_rte_flow_in_hmap(struct hash_table_node *rte_bucket, struct rt + return 0; + } + +-struct hinic3_flow_del_rte_flow_context *hinic3_del_rte_flow_batch_context_alloc(uint16_t port_id) ++static struct hinic3_flow_del_rte_flow_context *hinic3_del_rte_flow_batch_context_alloc(uint16_t port_id) + { + struct hinic3_flow_del_rte_flow_context *batch = NULL; + struct hinic3_dpif_flow_for_get *flow = NULL; +@@ -194,7 +195,6 @@ int hinic3_set_ufid_in_rte_flow(struct hinic3_flow_callback_info *callback_info, + struct hmap *hash_table = NULL; + struct hinic3_conntrack_full_key *key = &callback_info->no_ct_key; + uint32_t flow_hash = callback_info->flow_hash; +- uint8_t sub_table = 0; + + rte_bucket = hinic3_get_flow_bucket(flow_hash); + hash_table = &rte_bucket->key_hmap; +@@ -464,3 +464,18 @@ int hinic3_del_flow_in_hmap_by_port(uint16_t port_id) + hinic3_free(batch); + return 0; + } ++ ++int hinic3_flow_destroy_in_hmap_by_ufid(uint64_t hw_ufid) ++{ ++ int ret = -1; ++ ++ for (uint32_t i = 0; i < OFFLOAD_FLOW_BUCKETS; i++) { ++ if (&hinic3_mpool_mgmt.hash_table_array[i] != NULL) { ++ ret = hinic3_ufid_hmap_del_by_ufid(&hinic3_mpool_mgmt.hash_table_array[i].key_hmap, hw_ufid, EMC_UFID_MAP); ++ } ++ if (ret == 0) { ++ return ret; ++ } ++ } ++ return ret; ++} +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h +index d6a444dc3b..fd2344ad3c 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.h +@@ -115,6 +115,7 @@ int hinic3_batch_del_flow(struct rte_flow **flow, int flow_num, int destroy_resu + struct stat_refresh_time *hinic3_get_stat_ref_time(void); + struct hash_table_node *hinic3_get_flow_bucket(uint32_t flow_hash); + uint32_t hinic3_hash_generate(const struct hinic3_conntrack_key *key); ++int hinic3_flow_destroy_in_hmap_by_ufid(uint64_t hw_ufid); + #ifdef __cplusplus + } + #endif +-- +2.47.0.windows.2 + diff --git a/0101-add-collect-info-script.patch b/0101-add-collect-info-script.patch new file mode 100644 index 0000000000000000000000000000000000000000..2cf6c682bbfc53139a62254633752398177ca508 --- /dev/null +++ b/0101-add-collect-info-script.patch @@ -0,0 +1,124 @@ +From 2f3252084c9358b5ab3eca93241b2dab82f8a5c1 Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Tue, 8 Jul 2025 11:13:20 +0800 +Subject: [PATCH] add-collect-info-script + +--- + .../scripts/network_info_collect_ovs.sh | 104 ++++++++++++++++++ + 1 file changed, 104 insertions(+) + create mode 100644 drivers/net/hinic3/scripts/network_info_collect_ovs.sh + +diff --git a/drivers/net/hinic3/scripts/network_info_collect_ovs.sh b/drivers/net/hinic3/scripts/network_info_collect_ovs.sh +new file mode 100644 +index 0000000000..cae772cbb1 +--- /dev/null ++++ b/drivers/net/hinic3/scripts/network_info_collect_ovs.sh +@@ -0,0 +1,104 @@ ++#!/bin/bash ++# Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. ++# Description: 巡检信息收集脚本 ++# Create: 2023-10-19 ++ ++set -e ++function get_info() { ++ #版本号 ++ echo "------------------------------Version info------------------------------" ++ dpak-ovs-ctl hwoff-agent-version ++ echo "" ++ dpak-ovs-ctl -v ++ echo "" ++ ++ #内存占用情况 ++ echo "------------------------------Memory info-------------------------------" ++ cat /proc/$(pidof -s ovs-vswitchd)/status | grep VmRSS 2>/dev/null ++ echo "" ++ ++ #端口个数 ++ echo "------------------------------Port num----------------------------------" ++ dpak-ovs-ctl hwoff/show-function-flavor ++ echo "" ++ ++ #收发队列信息 ++ echo "-------------------------Dump unpcall queue info-------------------------" ++ dpak-ovs-ctl hwoff/dump-upcall-queue-info ++ echo "" ++ ++ #丢包统计信息 ++ echo "---------------------------Dump info------------------------------------" ++ #获取端口大名称 ++ port_name_str=$(ovs-vsctl show | awk '/^ +Port/ { port=$2; getline; getline; \ ++ if ($1 == "type:") { if ($2 == "dpdk") { gsub(/^"|"$/, "", port); print port } } }') ++ # echo "$port_name_str" ++ for i in $port_name_str ++ do ++ port_name=$i ++ # echo $port_name ++ echo "Port $port_name dump info:" ++ dpak-ovs-ctl hwoff/dump-ports $port_name ++ echo "" ++ done ++ echo "" ++ ++ #回调线程个数 ++ echo "--------------------------Flow offload thread num-----------------------" ++ cat /etc/dpak/net/agent_config.ini | grep offload_thread_num ++ echo "" ++ ++ #当前抓包任务列表 ++ echo "-------------------------------Capture probe info-----------------------" ++ dpak-ovs-ctl hwoff/capture-probe show all ++ echo "" ++ ++ #收集网络卸载相关日志 ++ echo "-----------------------------Collecting log-----------------------------" ++ if [ -d "$1/dpak-snic_log" ];then ++ rm -rf $1/dpak-snic_log #收集日志存放位置 ++ fi ++ mkdir -p $1/dpak-snic_log ++ cp $(find /var/log/openvswitch/ -name 'ovs-vswitchd*') $1/dpak-snic_log 2>/dev/null ++ logname=$1/dpak-snic-$(date +%Y_%m_%d_%H_%M_%S).tar.gz ++ tar czvf $logname -C $1 dpak-snic_log --remove-files ++ if [ ! -d "$1/logs" ];then ++ mkdir -p $1/logs ++ fi ++ mv $logname $1/logs ++ echo "Collecting log finished. The log is stored in \"$1/logs\"" ++ echo "" ++ ++ #收集异常分支统计信息 ++ echo "--------------------------Error stats info-------------------------------" ++ dpak-ovs-ctl hwoff/show-error-stats ++ echo "" ++ ++ #已卸载流表个数信息 ++ echo "--------------------------Flow num-----------------------------------------" ++ dpak-ovs-ctl hwoff/show-offload-flow-num #软件流表 ++ dpak-ovs-ctl hwoff/dump-hwoff-flows -n #硬件流表 ++ echo "" ++} ++ ++function check_input() { ++ if [[ $# == 0 || $# > 1]];then ++ echo "Please input a parameter as the output file path." ++ exit 1 ++ fi ++ ++ if [ ! -d "$1" ];then ++ echo "The path does not exist, please input a valid path." ++ exit 1 ++ fi ++} ++ ++function main() { ++ check_input $@ ++ ++ info_file_path=$1 ++ file_name="network_info.txt" ++ get_info $1 > $info_file_path/$file_name ++} ++ ++main $@ +\ No newline at end of file +-- +2.47.0.windows.2 + diff --git a/0102-eliminate-warning.patch b/0102-eliminate-warning.patch new file mode 100644 index 0000000000000000000000000000000000000000..aee0f4f084637b62af3af52039a35e86e19c5f43 --- /dev/null +++ b/0102-eliminate-warning.patch @@ -0,0 +1,1187 @@ +From e32d9f1de2666770a5f0f00080b274c34e2c3eaf Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Wed, 9 Jul 2025 09:30:33 +0800 +Subject: [PATCH] eliminate-warning + +--- + drivers/net/hinic3/meson.build | 5 +++-- + ..._collect_ovs.sh => network_info_collect.sh} | 0 + .../src/common/hinic3_hmap/hinic3_hmap.c | 2 +- + .../hinic3/src/common/hinic3_log/hinic3_log.c | 10 +++++----- + .../common/hinic3_mpool_mgmt/hinic3_mpool.c | 2 +- + .../hinic3_check_thread_health_state.c | 6 +++--- + .../common/hinic3_utils/hinic3_dpdk_adapter.h | 6 +++--- + .../src/common/hinic3_utils/hinic3_nlattr.h | 8 ++++---- + .../src/common/hinic3_utils/hinic3_timeval.h | 2 +- + .../hinic3_capture/hinic3_capture_command.c | 2 +- + .../src/hinic3_capture/hinic3_capture_filter.c | 2 +- + .../src/hinic3_capture/hinic3_capture_save.c | 2 +- + .../src/hinic3_capture/hinic3_capture_utils.c | 4 ++-- + .../hinic3_cmds/comm/hinic3_agent_cmd_format.c | 4 ++-- + .../comm/hinic3_agent_flow_cmd_dump.c | 4 ++-- + .../comm/hinic3_agent_flow_cmd_dump_file.c | 4 ++-- + .../comm/hinic3_agent_flow_cmd_speed.c | 8 ++++---- + .../src/hinic3_cmds/comm/hinic3_cmd_forward.c | 6 +++--- + .../src/hinic3_cmds/comm/hinic3_cmd_meminfo.c | 4 ++-- + .../comm/hinic3_dfx_port_bond_slave.c | 4 ++-- + .../comm/hinic3_dfx_port_flush_dump.c | 4 ++-- + .../comm/hinic3_dfx_port_upcall_queue.c | 4 ++-- + .../src/hinic3_cmds/comm/hinic3_trace_flow.c | 2 +- + .../hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c | 6 +++--- + .../src/hinic3_cmds/server/hinic3_command.c | 6 +++--- + .../hinic3_driver_public.h | 2 +- + .../hinic3_iface_global.c | 8 ++++---- + .../hinic3_flow_dump_item_key.c | 2 +- + .../hinic3_age_delete_flow.c | 6 +++--- + .../hinic3_flow_dump/hinic3_flow_api.c | 2 +- + .../hinic3_flow_format/hinic3_flow_format.c | 18 +++++++++--------- + .../hinic3_flow_mirror/hinic3_flow_mirror.c | 18 +++++++++--------- + .../hinic3_flow_mirror/hinic3_flow_session.c | 12 ++++++------ + .../hinic3_flow_offload/hinic3_dump_flow.c | 4 ++-- + .../hinic3_flow_offload/hinic3_offload_flow.c | 2 +- + .../hinic3_flow_query/hinic3_key_query.c | 4 ++-- + .../hinic3_flow_query/hinic3_query_flow.c | 4 ++-- + .../hinic3_flows/hinic3_vxlan/hinic3_vxlan.c | 4 ++-- + .../hinic3_bond/hinic3_bond_controller.c | 2 +- + .../hinic3_vf/hinic3_vf_controller.c | 6 +++--- + .../comm/hinic3_vf_port_qos_public.c | 4 ++-- + .../hinic3/src/hinic3_qos/meter/hinic3_qos.c | 2 +- + .../src/hinic3_qos/multilevel_qos/hinic3_mtr.c | 10 +++++----- + .../hinic3_ufid_map/hinic3_mpool_rte_flow.c | 2 +- + .../src/hinic3_ufid_map/hinic3_ufid_hmap.c | 4 ++-- + .../hinic3_ufid_map/hinic3_ufid_map_rte_flow.c | 4 ++-- + 46 files changed, 114 insertions(+), 113 deletions(-) + rename drivers/net/hinic3/scripts/{network_info_collect_ovs.sh => network_info_collect.sh} (100%) + +diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build +index 4eb5f5e76d..178e82193b 100644 +--- a/drivers/net/hinic3/meson.build ++++ b/drivers/net/hinic3/meson.build +@@ -186,5 +186,6 @@ executable('dpak-ovs-ctl', + + install_headers('include/rte_pmd_hinic3.h') + +-install_data('cfg/ovs_dpu_virt/agent_config.ini', install_dir: '/etc/dpak/net') +-install_data('scripts/dpak_ovs_completion_ovs.sh', install_dir: '/etc/bash_completion.d') ++install_data('cfg/ovs_dpu_virt/agent_config.ini', install_dir: join_paths(get_option('prefix'),'etc','dpak','net')) ++install_data('scripts/dpak_ovs_completion_ovs.sh', install_dir: join_paths(get_option('prefix'),'etc','bash_completion.d')) ++install_data('scripts/network_info_collect.sh', install_dir: join_paths(get_option('prefix'),'usr','bin')) +\ No newline at end of file +diff --git a/drivers/net/hinic3/scripts/network_info_collect_ovs.sh b/drivers/net/hinic3/scripts/network_info_collect.sh +similarity index 100% +rename from drivers/net/hinic3/scripts/network_info_collect_ovs.sh +rename to drivers/net/hinic3/scripts/network_info_collect.sh +diff --git a/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c +index 7bde0da651..4a143130d1 100644 +--- a/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c ++++ b/drivers/net/hinic3/src/common/hinic3_hmap/hinic3_hmap.c +@@ -94,7 +94,7 @@ static inline void hinic3_hmap_insert_fast(struct hmap *hmap, struct hmap_node * + hmap->n++; + } + +-static void hinic3_resize(struct hmap *hmap, size_t new_mask, const char *where, enum hinic3_module module_id) ++static void hinic3_resize(struct hmap *hmap, size_t new_mask, const char *where __rte_unused, enum hinic3_module module_id) + { + struct hmap tmp; + size_t i; +diff --git a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c +index 620a2bd696..31b73cfe29 100644 +--- a/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c ++++ b/drivers/net/hinic3/src/common/hinic3_log/hinic3_log.c +@@ -185,7 +185,7 @@ int hinic3_set_module_log_level(struct set_log_level_input_key *g_input_key) + return -1; + } + +- if (level > RTE_LOG_DEBUG) { ++ if (level > (int)RTE_LOG_DEBUG) { + HINIC3_LOG(ERR, AGENT, "invalid log level is %d", level); + return -1; + } +@@ -286,7 +286,7 @@ static int hinic3_set_log_level_help_info(struct ds *ds) + return 0; + } + +-static void hinic3_show_log_list(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[], ++static void hinic3_show_log_list(struct unixctl_conn *conn, int argc HINIC3_UNUSED, const char *argv[] __rte_unused, + void *aux) + { + size_t i; +@@ -337,7 +337,7 @@ static struct set_log_level_sub_key_parser g_input_key_parser[] = { + {"-m", sizeof("-m"), hinic3_key_module_name_parse}, + {"-l", sizeof("-l"), hinic3_key_log_level_parse}, + }; +-static int hinic3_set_log_level_sub_key_parse(struct unixctl_conn *conn, const char *key_name, ++static int hinic3_set_log_level_sub_key_parse(struct unixctl_conn *conn __rte_unused, const char *key_name, + const char *value, struct ds *ds) + { + size_t i = 0; +@@ -466,8 +466,8 @@ static bool token_bucket_withdraw(struct token_bucket *tb, unsigned int n) + static bool hinic3_log_is_enabled(uint32_t level, uint32_t logtype) + { + for (size_t i = 0; i < ARRAY_SIZE(g_hinic3_log_module_list); ++i) { +- if (logtype == g_hinic3_log_module_list[i].index) { +- return level >= g_hinic3_log_module_list[i].type; ++ if ((int)logtype == g_hinic3_log_module_list[i].index) { ++ return (int)level >= g_hinic3_log_module_list[i].type; + } + } + return false; +diff --git a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c +index eda2279b79..461ccfa3b8 100644 +--- a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c ++++ b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c +@@ -108,7 +108,7 @@ static int dpak_mempool_create(struct dpak_mempool *mp, uint32_t ele_size, uint3 + return 0; + } + +-static void *dpak_mp_alloc_mem_from_block(struct dpak_mp_block *blk, uint64_t size) ++static void *dpak_mp_alloc_mem_from_block(struct dpak_mp_block *blk, uint64_t size __rte_unused) + { + struct dpak_mp_chunk *allocated = NULL; + char *alloc = NULL; +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c +index 675d708c98..967d8e6888 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_check_thread_health_state.c +@@ -52,7 +52,7 @@ static void hinic3_signal_increase(uint32_t thread_index) + g_check_thread.signal[thread_index]++; + } + +-static void *hinic3_check_thread_main(void *arg) ++static void *hinic3_check_thread_main(void *arg __rte_unused) + { + uint32_t prev_signal[HINIC3_MAX_THREAD_NUMS] = {0}; + uint32_t offload_thread_num = hinic3_offload_thread_num_get(); +@@ -81,7 +81,7 @@ static void *hinic3_check_thread_main(void *arg) + return NULL; + } + +-static void hinic3_thread_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++static void hinic3_thread_stats_show(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + struct ds ds = DS_EMPTY_INITIALIZER; + uint32_t offload_thread_num = hinic3_offload_thread_num_get(); +@@ -130,7 +130,7 @@ int hinic3_check_thread_health_state(void) + return g_check_thread.thread_health; + } + +-static void *hinic3_check_hpd_main(void *arg) ++static void *hinic3_check_hpd_main(void *arg __rte_unused) + { + enum check_thread_item_type check_thread = HPD_THREAD; + long long start = hinic3_time_msec(); +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h +index 20833ae1b1..9f3a2f1da1 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_dpdk_adapter.h +@@ -267,17 +267,17 @@ static inline void rte_eth_dev_ops_set_mac_addr(struct eth_dev_ops *edev_ops, vo + edev_ops->mac_addr_set = arg; + } + +-static inline void rte_flow_ops_flow_dump_start(struct rte_flow_ops *flow_ops, void *arg) ++static inline void rte_flow_ops_flow_dump_start(struct rte_flow_ops *flow_ops __rte_unused, void *arg __rte_unused) + { + return; + } + +-static inline void rte_flow_ops_flow_dump_next(struct rte_flow_ops *flow_ops, void *arg) ++static inline void rte_flow_ops_flow_dump_next(struct rte_flow_ops *flow_ops __rte_unused, void *arg __rte_unused) + { + return; + } + +-static inline void rte_flow_ops_flow_dump_done(struct rte_flow_ops *flow_ops, void *arg) ++static inline void rte_flow_ops_flow_dump_done(struct rte_flow_ops *flow_ops __rte_unused, void *arg __rte_unused) + { + return; + } +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h +index 6263e64203..adf743f2ef 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_nlattr.h +@@ -95,7 +95,7 @@ static inline const void *hinic3_nlattr_get_itr_data(const hinic3_nlattr_itr nla + return nla + 1; + } + +-static inline const void *hinic3_nlattr_get_itr_unspec(const hinic3_nlattr_itr nla, size_t size) ++static inline const void *hinic3_nlattr_get_itr_unspec(const hinic3_nlattr_itr nla, size_t size __rte_unused) + { + return nla + 1; + } +@@ -129,12 +129,12 @@ static inline uint8_t hinic3_nlattr_get_itr_u8(const hinic3_nlattr_itr nla) + return *data_ptr; + } + +-static inline bool hinic3_nlattr_get_itr_flag(const hinic3_nlattr_itr nla) ++static inline bool hinic3_nlattr_get_itr_flag(const hinic3_nlattr_itr nla __rte_unused) + { + return true; + } + +-static inline int hinic3_nlattr_put_unspec(struct hinic3_nlattr *nla, uint16_t type, const void *data, size_t size) ++static inline int hinic3_nlattr_put_unspec(struct hinic3_nlattr *nla, uint16_t type, const void *data, size_t size __rte_unused) + { + void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, size); + if (store_buf == NULL) { +@@ -193,7 +193,7 @@ static inline int hinic3_nlattr_put_u8(struct hinic3_nlattr *nla, uint16_t type, + return 0; + } + +-static inline int hinic3_nlattr_put_flag(struct hinic3_nlattr *nla, uint16_t type) ++static inline int hinic3_nlattr_put_flag(struct hinic3_nlattr *nla __rte_unused, uint16_t type) + { + void *store_buf = hinic3_nlattr_put_unspec_uninit(nla, type, 0); + if (store_buf == NULL) { +diff --git a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h +index 9e282f11c9..2685ebdbd5 100644 +--- a/drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h ++++ b/drivers/net/hinic3/src/common/hinic3_utils/hinic3_timeval.h +@@ -14,7 +14,7 @@ + #define HINIC3_MS_STR_FMT "%04u-%02u-%02u %02u:%02u:%02u.%03u" + #define HINIC3_MS_STR_SIZE 25 // 2000-01-01 00:00:00.000 + +-static inline int time_msec_to_str(long long int msec, char buf[], size_t bufsize) ++static inline int time_msec_to_str(long long int msec, char buf[], size_t bufsize __rte_unused) + { + time_t sec = msec / HINIC3_MS_PER_SEC; + int millisec = (int) (msec % HINIC3_MS_PER_SEC); +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +index e55589c662..3d96aa10a9 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_command.c +@@ -414,7 +414,7 @@ pcap_cmd_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux + } + + void +-pcap_cmd_help(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++pcap_cmd_help(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + struct ds ds = DS_EMPTY_INITIALIZER; + +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +index 61d414e630..d5554dc042 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_filter.c +@@ -571,7 +571,7 @@ pcap_convert_key_to_driver_filter(struct pcap_task_t *task) + } + + static inline void +-pcap_pkt_parse_not_ip(struct pcap_pkt_parse_ctx *ctx, struct pcap_pkt_sub_hdr *sub_hdr) ++pcap_pkt_parse_not_ip(struct pcap_pkt_parse_ctx *ctx __rte_unused, struct pcap_pkt_sub_hdr *sub_hdr) + { + struct pcap_pkt_l2 *l2 = &sub_hdr->l2; + +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +index a7a9baec55..90d2792abf 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_save.c +@@ -233,7 +233,7 @@ pcap_pkt_ring_save(struct pcap_task_t *cap_task, struct pcap_pkt_summary **buf, + } + + void * +-pcap_save_thread(void *args) ++pcap_save_thread(void *args __rte_unused) + { + int i; + int nfds; +diff --git a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +index 3f5d15e903..80f0b96317 100644 +--- a/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c ++++ b/drivers/net/hinic3/src/hinic3_capture/hinic3_capture_utils.c +@@ -746,7 +746,7 @@ pcap_task_find_no_lock(uint32_t pcap_id, uint32_t *index) + } + + void +-pcap_port_tasks_get(struct pcap_task_batch *task_batch, struct pcap_port_t *port_mirror) ++pcap_port_tasks_get(struct pcap_task_batch *task_batch, struct pcap_port_t *port_mirror __rte_unused) + { + int i; + struct pcap_task_t *cap_task = NULL; +@@ -1251,7 +1251,7 @@ pcap_switch_set(int value) + } + + void * +-pcap_thread_main(void *arg) ++pcap_thread_main(void *arg __rte_unused) + { + enum check_thread_item_type check_thread = CAPTURE_THREAD; + long long start = hinic3_time_msec(); +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c +index 655370954e..72968b2918 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_cmd_format.c +@@ -333,13 +333,13 @@ hinic3_flow_process_set_u16_action(const hinic3_nlattr_itr nla, struct ds *ds) + } + + static void +-hinic3_flow_process_drop_action(const hinic3_nlattr_itr nla, struct ds *ds) ++hinic3_flow_process_drop_action(const hinic3_nlattr_itr nla __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s, ", HINIC3_UI_KEY_DROP); + } + + static void +-hinic3_flow_process_ttl_dec_action(const hinic3_nlattr_itr nla, struct ds *ds) ++hinic3_flow_process_ttl_dec_action(const hinic3_nlattr_itr nla __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s, ", HINIC3_UI_KET_TTL_DEC); + } +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +index 2a21ec66da..889a5c3441 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump.c +@@ -106,7 +106,7 @@ hinic3_agent_dump_flows_handle_ret(int ret, struct ds *ds) + } + + int +-hinic3_alloc_mem_for_flow(struct ds *ds, struct hinic3_dpif_flow_for_get *f) ++hinic3_alloc_mem_for_flow(struct ds *ds __rte_unused, struct hinic3_dpif_flow_for_get *f) + { + if (f->key == NULL) { + f->key = hinic3_calloc(1, HINIC3_DFX_FLOW_ALLOC_MEM_BASE_SIZE, HINIC3_COMMAND); +@@ -337,7 +337,7 @@ hinic3_agent_get_flows_cnt(int argc, struct ds *ds) + + static int + hinic3_agent_get_block_id_from_flow(const struct hinic3_dpif_flow_for_get *f, +- uint16_t *return_block_id, struct ds *ds) ++ uint16_t *return_block_id, struct ds *ds __rte_unused) + { + struct hinic3_nlattr flow_actions; + hinic3_nlattr_itr nla = NULL; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +index 5331bf27cf..be95aca077 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_dump_file.c +@@ -13,7 +13,7 @@ + #include "rte_string_fns.h" + + int +-hinic3_agent_force_stop_dump_all_flows_to_file(int argc, const char *argv[], struct ds *ds) ++hinic3_agent_force_stop_dump_all_flows_to_file(int argc, const char *argv[] __rte_unused, struct ds *ds) + { + enum { + ARGC = 2 +@@ -168,7 +168,7 @@ hinic3_dump_flows_run(struct hinic3_dump_all_flows_mgmt_t *m, struct hinic3_dump + } + + static void * +-hinic3_dump_flows_running_thread(void *args) ++hinic3_dump_flows_running_thread(void *args __rte_unused) + { + struct hinic3_dump_all_flows_mgmt_t *m = hinic3_cmd_get_flow_dump_mgmt(); + struct hinic3_dump_flow_count_t flow_count = {0}; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c +index ec1cbb936c..24194a6dae 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_agent_flow_cmd_speed.c +@@ -23,7 +23,7 @@ hinic3_speed_parse_int_arg(const char *str_value, int min, int max, uint32_t *ds + return -1; + + tmp_value = strtoul(str_value, NULL, STR_TO_DEC_NUM); +- if (tmp_value < min || tmp_value > max) ++ if ((int)tmp_value < min || (int)tmp_value > max) + return -1; + + *dst_value = tmp_value; +@@ -325,7 +325,7 @@ hinic3_speed_task_cmd_restart(struct unixctl_conn *conn, int argc, const char *a + } + + static int +-hinic3_speed_task_cmd_stop(struct unixctl_conn *conn, int argc, const char *argv[]) ++hinic3_speed_task_cmd_stop(struct unixctl_conn *conn, int argc, const char *argv[] __rte_unused) + { + int ret; + struct ds ds = DS_EMPTY_INITIALIZER; +@@ -372,7 +372,7 @@ hinic3_speed_task_cmd_stop(struct unixctl_conn *conn, int argc, const char *argv + } + + static int +-hinic3_speed_task_cmd_show(struct unixctl_conn *conn, int argc, const char *argv[]) ++hinic3_speed_task_cmd_show(struct unixctl_conn *conn, int argc, const char *argv[] __rte_unused) + { + struct ds ds = DS_EMPTY_INITIALIZER; + struct hinic3_speed_measure_task_t *task = &g_offload_speed_task; +@@ -404,7 +404,7 @@ hinic3_speed_task_cmd_show(struct unixctl_conn *conn, int argc, const char *argv + } + + static int +-hinic3_speed_task_cmd_help(struct unixctl_conn *conn, int argc, const char *argv[]) ++hinic3_speed_task_cmd_help(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused) + { + struct ds ds = DS_EMPTY_INITIALIZER; + const char *help_desc = " start Start the offload speed measuring task\n" +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c +index ee28cecd6e..6d5d719679 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_forward.c +@@ -11,7 +11,7 @@ + #include "hinic3_command.h" + + static void +-hinic3_forward_mode_set_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++hinic3_forward_mode_set_cmd(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + enum hinic3_packet_forward_mod mode = 0; + int ret = 0; +@@ -42,7 +42,7 @@ hinic3_forward_mode_set_cmd(struct unixctl_conn *conn, int argc, const char *arg + } + + static void +-hinic3_forward_mode_get_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++hinic3_forward_mode_get_cmd(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + struct ds reply = DS_EMPTY_INITIALIZER; + int ret = 0; +@@ -170,7 +170,7 @@ hinic3_set_escape_mode(struct ds *reply, bool escape_mode_enable) + } + + static void +-hinic3_flow_escape_mode_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) ++hinic3_flow_escape_mode_cmd(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[], void *aux HINIC3_UNUSED) + { + struct ds reply = DS_EMPTY_INITIALIZER; + int ret; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c +index 0e9062f4a4..331c50c38c 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_cmd_meminfo.c +@@ -15,7 +15,7 @@ + #define HINIC3_MODULE_NAME_MAX_LEN 30 + + void +-hinic3_show_meminfo_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++hinic3_show_meminfo_command(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux __rte_unused) + { + struct ds ds = DS_EMPTY_INITIALIZER; + struct hinic3_mem_statistics *mem_stats = hinic3_get_meminfo(); +@@ -70,7 +70,7 @@ hinic3_format_hugepage_meminfo(struct ds *ds, struct hinic3_module_hugepage_memi + } + + void +-hinic3_show_hugepage_meminfo_command(struct unixctl_conn *conn, int argc, const char *argv[], void *aux HINIC3_UNUSED) ++hinic3_show_hugepage_meminfo_command(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux HINIC3_UNUSED) + { + struct ds ds = DS_EMPTY_INITIALIZER; + uint64_t total_size = 0; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c +index af069cba92..ac6beb1284 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_bond_slave.c +@@ -44,7 +44,7 @@ hinic3_show_bond_slave_stats(struct ds *output_msg, const struct hovs_bond_slave + + static int + hinic3_split_slave_name(char *slaves, char *slaves_name, +- char bond_slave_name[][HINIC3_BOND_ARG_SLAVE_NAME_LEN], int len) ++ char bond_slave_name[][HINIC3_BOND_ARG_SLAVE_NAME_LEN], int len __rte_unused) + { + int slaves_num = 0; + int slaves_name_num = 0; +@@ -76,7 +76,7 @@ hinic3_split_slave_name(char *slaves, char *slaves_name, + if (index >= HINIC3_BOND_SLAVE_NUM) + return -1; + +- if (i == index) { ++ if (i == (int)index) { + strcpy(bond_slave_name[i], slaves_name_str[j]); + j++; + } +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c +index 471bba5d1d..ac87a717c8 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_flush_dump.c +@@ -92,7 +92,7 @@ hinic3_show_vf_port_info(struct ds *output_msg, uint16_t dpdk_index_id, hinic3_p + } + + int +-hinic3_show_pf_port_info(struct ds *output_msg, uint16_t dpdk_index_id, hinic3_port_stats *port_stats, ++hinic3_show_pf_port_info(struct ds *output_msg __rte_unused, uint16_t dpdk_index_id, hinic3_port_stats *port_stats __rte_unused, + uint32_t link_status) + { + int ret; +@@ -406,7 +406,7 @@ hinic3_flush_vf_port_info(struct ds *output_msg, uint16_t dpdk_index_id) + } + + static void +-hinic3_flush_pf_port_info(struct ds *output_msg, uint16_t dpdk_index_id) ++hinic3_flush_pf_port_info(struct ds *output_msg __rte_unused, uint16_t dpdk_index_id) + { + void *private_data = NULL; + struct hinic3_bond_dev *pf_dev = NULL; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c +index 2f6c76c205..1d204d2caf 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_dfx_port_upcall_queue.c +@@ -458,7 +458,7 @@ hinic3_dump_pf_port_queue_stats_to_screen(struct ds *output_msg, struct hinic3_b + } + + static int +-hinic3_show_vf_port_queue_stats_info(struct ds *output_msg, uint16_t dpdk_index_id, uint32_t link_status) ++hinic3_show_vf_port_queue_stats_info(struct ds *output_msg, uint16_t dpdk_index_id, uint32_t link_status __rte_unused) + { + struct hinic3_vf_dev *vf_dev = NULL; + vf_dev = (struct hinic3_vf_dev *)hinic3_get_private_data(dpdk_index_id); +@@ -472,7 +472,7 @@ hinic3_show_vf_port_queue_stats_info(struct ds *output_msg, uint16_t dpdk_index_ + } + + static int +-hinic3_show_pf_port_queue_stats_info(struct ds *output_msg, uint16_t dpdk_index_id, uint32_t link_status) ++hinic3_show_pf_port_queue_stats_info(struct ds *output_msg, uint16_t dpdk_index_id, uint32_t link_status __rte_unused) + { + struct hinic3_bond_dev *pf_dev = NULL; + pf_dev = (struct hinic3_bond_dev *)hinic3_get_private_data(dpdk_index_id); +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c +index ae8fe942cf..025016c158 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_trace_flow.c +@@ -211,7 +211,7 @@ hinic3_add_trace_flow_filter(struct hinic3_trace_flow *trace_table, struct hinic + } + + static int +-hinic3_trace_flow_cmd_para_check(int argc, const char *argv[], struct hinic3_filter_tuple *key, ++hinic3_trace_flow_cmd_para_check(int argc __rte_unused, const char *argv[], struct hinic3_filter_tuple *key, + struct ds *reply) + { + char *endptr = NULL; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c +index ba10f1b5eb..399d8d37b6 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/comm/hinic3_vf_dfx_multi_qos.c +@@ -909,7 +909,7 @@ hinic3_multi_net_qos_show_one(uint32_t meter_id, enum hinic3_qos_tablehead index + } + + void +-hinic3_multi_net_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++hinic3_multi_net_qos_dump_show(struct unixctl_conn *conn, int argc, const char *argv[] __rte_unused, void *aux) + { + int ret; + struct ds ds = DS_EMPTY_INITIALIZER; +@@ -940,7 +940,7 @@ hinic3_multi_net_qos_dump_show(struct unixctl_conn *conn, int argc, const char * + } + + void +-hinic3_multi_net_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++hinic3_multi_net_qos_dump_loss(struct unixctl_conn *conn, int argc, const char *argv[] __rte_unused, void *aux) + { + uint16_t host_id = 0; + uint16_t stats_mask = 0; +@@ -1087,7 +1087,7 @@ hinic3_multi_port_qos_stats_show(struct unixctl_conn *conn, int argc, const char + } + + void +-hinic3_multi_net_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++hinic3_multi_net_qos_stats_show(struct unixctl_conn *conn, int argc, const char *argv[] __rte_unused, void *aux) + { + uint16_t stats_mask = 0; + uint16_t host_id = 0; +diff --git a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +index d39a65b81f..5f0229b3eb 100644 +--- a/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c ++++ b/drivers/net/hinic3/src/hinic3_cmds/server/hinic3_command.c +@@ -47,7 +47,7 @@ struct hinic3_command_mgr { + struct hinic3_command_mgr g_command_mgr = {0}; + + static void +-hinic3_list_commands(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++hinic3_list_commands(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + struct shash_node *node = NULL; + struct ds reply = DS_EMPTY_INITIALIZER; +@@ -364,7 +364,7 @@ static struct hinic3_command_info g_hinic3_command_info[] = { + static int + get_cmd_info(const char *func_name, char *cmd_info) + { +- for (int i = 0; i < sizeof(g_hinic3_command_info) / sizeof(struct hinic3_command_info); i++) { ++ for (int i = 0; i < (int)(sizeof(g_hinic3_command_info) / sizeof(struct hinic3_command_info)); i++) { + if (strncmp(func_name, g_hinic3_command_info[i].func_name, strlen(g_hinic3_command_info[i].func_name)) == 0) { + memcpy(cmd_info, g_hinic3_command_info[i].info, HINIC3_CMD_INFO_MAX_LEN); + return 0; +@@ -451,7 +451,7 @@ hinic3_command_epoll_process(int fd) + } + + static void * +-hinic3_command_thread(void *arg) ++hinic3_command_thread(void *arg __rte_unused) + { + int listen_socket = g_command_mgr.listen_socket; + int epoll_fd = g_command_mgr.epoll_fd; +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h +index e3d65df730..bceec4ba7f 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_driver_public.h +@@ -129,7 +129,7 @@ static struct hiovs_error_code_map hiovs_error_code_map_array[] = { + + static inline int hinic3_convert_error_code(int error_code) + { +- for (int i = 0; i < HINIC3_ERROR_CODE_LEN; i++) { ++ for (uint32_t i = 0; i < HINIC3_ERROR_CODE_LEN; i++) { + if (error_code == hiovs_error_code_map_array[i].hiovs_err_code) { + return hiovs_error_code_map_array[i].errno_code; + } +diff --git a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +index e17db23c1c..00c8459f27 100644 +--- a/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c ++++ b/drivers/net/hinic3/src/hinic3_driver_adapter/hinic3_iface_global.c +@@ -1325,18 +1325,18 @@ void hinic3_global_class_uninit(void) + memset(global_api_record, 0, sizeof(hiovs_api_record) * HINIC3_GLOBAL_API_MAX); + } + +-int hinic3_adapt_malloc(const char *type, size_t size, int socket_arg, unsigned int flags, size_t align, size_t bound, +- bool contig, struct hovs_melem *mem) ++int hinic3_adapt_malloc(const char *type __rte_unused, size_t size __rte_unused, int socket_arg __rte_unused, unsigned int flags __rte_unused, size_t align __rte_unused, size_t bound __rte_unused, ++ bool contig __rte_unused, struct hovs_melem *mem __rte_unused) + { + return -1; + } + +-int hinic3_adapt_mfree(void *addr) ++int hinic3_adapt_mfree(void *addr __rte_unused) + { + return -1; + } + +-void *hinic3_adapt_malloc_socket(const char *type, size_t size, unsigned int align, int socket_arg) ++void *hinic3_adapt_malloc_socket(const char *type __rte_unused, size_t size, unsigned int align, int socket_arg) + { + return hinic3_rte_malloc_socket(HIOVS_MEM, size, align, socket_arg); + } +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c +index dfa4ddda31..65a6d27c08 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_emc_dump/hinic3_flow_dump_item_key.c +@@ -90,7 +90,7 @@ static void hinic3_construct_vxlan_key(const hinic3_nlattr_itr nla, uint32_t *vn + return; + } + +-static void hinic3_construct_vlan_key(enum hinic3_flow_key_type type, const hinic3_nlattr_itr nla, ++static void hinic3_construct_vlan_key(enum hinic3_flow_key_type type __rte_unused, const hinic3_nlattr_itr nla, + uint32_t *vlan_id) + { + *vlan_id = hinic3_nlattr_get_itr_u16(nla); +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c +index a7edc6b11f..42a58fb5ba 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_delete/hinic3_age_delete_flow.c +@@ -76,7 +76,7 @@ static int hinic3_flow_destroy_sub(struct rte_flow *flow, struct rte_flow_error + return 0; + } + +-int hinic3_flow_emc_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error) ++int hinic3_flow_emc_destroy(struct rte_eth_dev *dev __rte_unused, struct rte_flow *flow, struct rte_flow_error *error) + { + int ret; + ret = hinic3_try_rlock_flush_all(); +@@ -95,8 +95,8 @@ int hinic3_flow_emc_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, stru + return ret; + } + +-int hinic3_flow_agent_age_callback(uint64_t hw_ufid, const struct hinic3_dpif_flow_for_get *flow, +- const struct hinic3_nlattr *args) ++int hinic3_flow_agent_age_callback(uint64_t hw_ufid __rte_unused, const struct hinic3_dpif_flow_for_get *flow __rte_unused, ++ const struct hinic3_nlattr *args __rte_unused) + { + return 0; + } +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +index 40ebf14cdf..888e6da8c9 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_dump/hinic3_flow_api.c +@@ -103,7 +103,7 @@ static void hinic3_flow_ouput(struct hinic3_dpif_flow *flow, struct ds *ds) + hinic3_agent_flow_format_output(&get_flow, ds); + } + +-int hinic3_flow_query_ufid(const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, uint64_t *ufid, ++int hinic3_flow_query_ufid(const struct rte_flow_attr *attr __rte_unused, const struct rte_flow_item *pattern, uint64_t *ufid, + struct hinic3_conntrack_full_key *full_key, struct ds *ds) + { + int ret; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c +index 2171abfbac..ff9f55988a 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_format/hinic3_flow_format.c +@@ -228,7 +228,7 @@ static struct hinic3_item_format_info item_callback_info[] = { + {RTE_FLOW_ITEM_TYPE_END, NULL} + }; + +-static int hinic3_process_count(const struct rte_flow_action* action, struct ds *ds) ++static int hinic3_process_count(const struct rte_flow_action* action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", HINIC3_UI_COUNT_ACTION); + return 0; +@@ -285,49 +285,49 @@ static int hinic3_process_acl_sample(const struct rte_flow_action *action, struc + return 0; + } + +-static int hinic3_process_push_vlan(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_push_vlan(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "push_vlan"); + return 0; + } + +-static int hinic3_process_pop_vlan(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_pop_vlan(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "pop_vlan"); + return 0; + } + +-static int hinic3_process_vxlan_encape(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_vxlan_encape(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "vxlan_encap"); + return 0; + } + +-static int hinic3_process_vxlan_decape(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_vxlan_decape(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "vxlan_decap"); + return 0; + } + +-static int hinic3_process_drop(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_drop(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "drop"); + return 0; + } + +-static int hinic3_process_port_id(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_port_id(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "port_id"); + return 0; + } + +-static int hinic3_process_set_vid(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_set_vid(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "set vid"); + return 0; + } + +-static int hinic3_process_set_pcp(const struct rte_flow_action *action, struct ds *ds) ++static int hinic3_process_set_pcp(const struct rte_flow_action *action __rte_unused, struct ds *ds) + { + hinic3_ds_put_format(ds, "%s,", "set pcp"); + return 0; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c +index a77cb0760f..653b39bf6e 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_mirror.c +@@ -13,7 +13,7 @@ + #define HINIC3_SESSION_CUTOFF_OFFSET 24 + + static int hinic3_parse_mirror_IPv4_item(const struct rte_flow_item *item, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + const struct rte_flow_item_ipv4 *ip = (const struct rte_flow_item_ipv4 *)item->spec; + if (ip == NULL) { +@@ -28,7 +28,7 @@ static int hinic3_parse_mirror_IPv4_item(const struct rte_flow_item *item, + } + + static int hinic3_parse_mirror_vlan_item(const struct rte_flow_item *item, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + const struct rte_flow_item_vlan *vlan = (const struct rte_flow_item_vlan *)item->spec; + if (vlan == NULL) { +@@ -42,7 +42,7 @@ static int hinic3_parse_mirror_vlan_item(const struct rte_flow_item *item, + } + + static int hinic3_parse_mirror_eth_item(const struct rte_flow_item *item, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + const struct rte_flow_item_eth *eth = (const struct rte_flow_item_eth *)item->spec; + if (eth == NULL) { +@@ -57,7 +57,7 @@ static int hinic3_parse_mirror_eth_item(const struct rte_flow_item *item, + } + + static int hinic3_parse_mirror_IPv6_item(const struct rte_flow_item *item, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + const struct rte_flow_item_ipv6 *ip = (const struct rte_flow_item_ipv6 *)item->spec; + if (ip == NULL) { +@@ -78,7 +78,7 @@ static int hinic3_parse_mirror_IPv6_item(const struct rte_flow_item *item, + } + + static int hinic3_parse_mirror_vxlan_item(const struct rte_flow_item *item, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + const struct rte_flow_item_vxlan *vxlan = (const struct rte_flow_item_vxlan *)item->spec; + if (vxlan == NULL) { +@@ -96,7 +96,7 @@ static int hinic3_parse_mirror_vxlan_item(const struct rte_flow_item *item, + } + + static int hinic3_parse_mirror_udp_item(const struct rte_flow_item *item, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + const struct rte_flow_item_udp *udp = (const struct rte_flow_item_udp *)item->spec; + if (udp == NULL) { +@@ -111,7 +111,7 @@ static int hinic3_parse_mirror_udp_item(const struct rte_flow_item *item, + } + + static int hinic3_parse_mirror_gre_item(const struct rte_flow_item *item, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + const struct rte_flow_item_gre *gre = (const struct rte_flow_item_gre *)item->spec; + if (gre == NULL) { +@@ -161,7 +161,7 @@ static bool hinic3_check_session_ip_type_flag(uint32_t ip_type_flag) + } + + static int hinic3_parse_mirror_vxlan_nvgre_act(const struct rte_flow_action *act, +- struct hinic3_mirror_session_info *session_info, const uint8_t flow_type) ++ struct hinic3_mirror_session_info *session_info, const uint8_t flow_type __rte_unused) + { + int ret = 0; + const struct rte_flow_action_vxlan_encap *encap_info = (const struct rte_flow_action_vxlan_encap *)act->conf; +@@ -172,7 +172,7 @@ static int hinic3_parse_mirror_vxlan_nvgre_act(const struct rte_flow_action *act + + item = next_no_end_pattern(encap_info->definition, NULL); + while (item) { +- for (int i = 0; i < HINIC3_MIRROR_VXLAN_ITEM_LEN; i++) { ++ for (uint32_t i = 0; i < HINIC3_MIRROR_VXLAN_ITEM_LEN; i++) { + if (item->type == hinic3_mirror_vxlan_item_func_array[i].item) { + ret = hinic3_mirror_vxlan_item_func_array[i].func(item, session_info, flow_type); + break; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c +index 4b4d32203e..df50ce5214 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_mirror/hinic3_flow_session.c +@@ -288,13 +288,13 @@ static void hinic3_show_session_type(struct ds *ds, enum hinic3_session_tpye typ + } + } + +-void hinic3_show_sample_session(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++void hinic3_show_sample_session(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + struct ds ds = DS_EMPTY_INITIALIZER; + struct session_key *key = NULL; + + ovs_mutex_lock_session(); +- for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ for (int i = 0; i < (int)HINIC3_MIRROR_MAX_SESSION; i++) { + if (g_mirror_session_info.session_info[i].is_used == 0) { + continue; + } +@@ -438,7 +438,7 @@ int hinic3_del_rte_flow_in_session(struct rte_flow *flow) + + static uint8_t hinic3_find_mirror_session(struct hinic3_mirror_session_info *session_info) + { +- for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ for (int i = 0; i < (int)HINIC3_MIRROR_MAX_SESSION; i++) { + struct hinic3_mirror_session_info *cur_session_info = &g_mirror_session_info.session_info[i]; + if (cur_session_info->is_used == 0) { + continue; +@@ -453,7 +453,7 @@ static uint8_t hinic3_find_mirror_session(struct hinic3_mirror_session_info *ses + } + + static void hinic3_insert_session_in_list(struct hinic3_mirror_session_info *session_info, +- struct rte_flow *flow) ++ struct rte_flow *flow __rte_unused) + { + memcpy(&g_mirror_session_info.session_info[session_info->session_id], session_info, sizeof(struct hinic3_mirror_session_info)); + g_mirror_session_info.session_info[session_info->session_id].flow_list_len = 1; +@@ -523,7 +523,7 @@ static int hinic3_mirror_set_session_to_hovs(struct hinic3_mirror_session_info * + + static int hinic3_get_session_id(struct hinic3_mirror_session_info *session_info) + { +- for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ for (int i = 0; i < (int)HINIC3_MIRROR_MAX_SESSION; i++) { + if (g_mirror_session_info.session_info[i].is_used == 0) { + session_info->session_id = i; + return 0; +@@ -562,7 +562,7 @@ void hinic3_mirror_session_info_list_init(void) + { + g_mirror_session_info.used_session_len = 0; + hinic3_spinlock_init(&g_mirror_session_info.mutex, PTHREAD_PROCESS_PRIVATE); +- for (int i = 0; i < HINIC3_MIRROR_MAX_SESSION; i++) { ++ for (int i = 0; i < (int)HINIC3_MIRROR_MAX_SESSION; i++) { + g_mirror_session_info.session_info[i].is_used = 0; + g_mirror_session_info.session_info[i].session_id = (uint8_t)i; + } +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c +index f67973cdfe..5f7f4d1c0d 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_dump_flow.c +@@ -13,7 +13,7 @@ + #define SUDO_PATH "/usr/bin/sudo" + #define HINICADMIN_PATH "/usr/sbin/hinicadm3" + +-static int hinic3_info_need(char *buf, int buffer_size) ++static int hinic3_info_need(char *buf, int buffer_size __rte_unused) + { + static const char *infos[] = { + "Card information", +@@ -36,7 +36,7 @@ static int hinic3_info_need(char *buf, int buffer_size) + return flag; + } + +-int hinic3_eth_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow, FILE *file, struct rte_flow_error *error) ++int hinic3_eth_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow __rte_unused, FILE *file, struct rte_flow_error *error) + { + if ((dev == NULL) || (file == NULL) || (error == NULL)) { + hinic3_add_error_stats(HINIC3_FLOW_AGENT_ERROR_DEV_DUMP_NULL, 1); +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c +index d579f1d419..ba849ff4e9 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_offload/hinic3_offload_flow.c +@@ -480,7 +480,7 @@ static void hinic3_init_param_buff(struct hinic3_flow_offload_param *param) + hinic3_nlattr_init(¶m->hinic3_args, param->offload_buff.args_buf, HINIC3_MSG_MAX_BUF); + } + +-static void hinic3_proces_put_args(struct hinic3_flow_offload_param *param, const struct rte_flow_item pattern[], ++static void hinic3_proces_put_args(struct hinic3_flow_offload_param *param, const struct rte_flow_item pattern[] __rte_unused, + struct rte_flow *flow, clock_t start_t) + { + (void)hinic3_offload_parse_flow_args(param, flow, start_t, flow->flow_hash); +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c +index afe95dd539..7f0974f1dd 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_key_query.c +@@ -266,7 +266,7 @@ static bool hinic3_check_querry_flow_key_is_complete(uint8_t ip_proto) + return true; + } + +-static int hinic3_sub_key_parse(struct unixctl_conn *conn, struct pcap_key_t *cap_key, ++static int hinic3_sub_key_parse(struct unixctl_conn *conn __rte_unused, struct pcap_key_t *cap_key, + const char *key_name, const char *value, struct ds *ds) + { + size_t i = 0; +@@ -718,7 +718,7 @@ void hinic3_dpak_query_ufid(struct unixctl_conn *conn, int argc, const char *arg + return; + } + +-void hinic3_input_key_help(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++void hinic3_input_key_help(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + struct ds ds = DS_EMPTY_INITIALIZER; + +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c +index 35fedefd84..b9c3c1b3e6 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_flow_query/hinic3_query_flow.c +@@ -9,7 +9,7 @@ + + #define HINIC3_LIVE_TIME_SHIFT 16u + +-static int hinic3_flow_query_sub(struct rte_flow *flow, const struct rte_flow_action actions[], void *data, ++static int hinic3_flow_query_sub(struct rte_flow *flow, const struct rte_flow_action actions[] __rte_unused, void *data, + struct rte_flow_error *error) + { + struct rte_flow_query_count *stat = NULL; +@@ -54,7 +54,7 @@ static int hinic3_flow_query_sub(struct rte_flow *flow, const struct rte_flow_ac + return 0; + } + +-int hinic3_flow_query_emc(struct rte_eth_dev *dev, struct rte_flow *flow, const struct rte_flow_action actions[], ++int hinic3_flow_query_emc(struct rte_eth_dev *dev __rte_unused, struct rte_flow *flow, const struct rte_flow_action actions[], + void *data, struct rte_flow_error *error) + { + int ret; +diff --git a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c +index 4889c37cf7..89630cca18 100644 +--- a/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c ++++ b/drivers/net/hinic3/src/hinic3_flows/hinic3_vxlan/hinic3_vxlan.c +@@ -27,8 +27,8 @@ static int hinic3_check_tunnel_decap_para(struct rte_flow_tunnel *tunnel, struct + return 0; + } + +-int hinic3_flow_tunnel_decap_set(struct rte_eth_dev *eth_dev, struct rte_flow_tunnel *tunnel, +- struct rte_flow_action **pmd_actions, uint32_t *num_of_actions, struct rte_flow_error *error) ++int hinic3_flow_tunnel_decap_set(struct rte_eth_dev *eth_dev __rte_unused, struct rte_flow_tunnel *tunnel, ++ struct rte_flow_action **pmd_actions __rte_unused, uint32_t *num_of_actions __rte_unused, struct rte_flow_error *error) + { + int ret; + struct hinic3_vtep_ip_set_args add_vxlan_args = { 0 }; +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +index 416aecb0b8..47fdb056f2 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_bond/hinic3_bond_controller.c +@@ -842,7 +842,7 @@ hinic3_get_bond_link_speed(const struct hinic3_bond_dev *bond_dev, uint32_t *spe + } + + int +-hinic3_bond_link_update(struct rte_eth_dev *dev, int wait_to_complete) ++hinic3_bond_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) + { + if (hinic3_is_ethdev_valid(dev) == false) + return -EINVAL; +diff --git a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c +index 7a65ecd004..b5a7664ce3 100644 +--- a/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c ++++ b/drivers/net/hinic3/src/hinic3_ports/hinic3_vf/hinic3_vf_controller.c +@@ -151,12 +151,12 @@ static int hinic3_vf_config_set_vni(struct hinic3_vf_dev *vf_dev, const char* co + vf_dev->state[HINIC3_VF_CONFIG_VNI] = HINIC3_VF_CONFIG_NONE; + + vni = strtoul(conf, &endp, BASE_DECIMAL); +- if (vf_dev->vni == vni) { ++ if ((int)vf_dev->vni == vni) { + vf_dev->state[HINIC3_VF_CONFIG_VNI] = HINIC3_VF_CONFIG_STABLE; + return 1; + } + +- if (vni >= VNI_INVALID || vni < 0 || *endp != '\0') { ++ if (vni >= (int)VNI_INVALID || vni < 0 || *endp != '\0') { + HINIC3_LOG(ERR, VPORT, "invalid vxlan network identifier: %d!", vni); + vf_dev->state[HINIC3_VF_CONFIG_VNI] = old_state; + return -1; +@@ -928,7 +928,7 @@ int hinic3_vf_dev_configure(struct rte_eth_dev *dev) + return 0; + } + +-int hinic3_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete) ++int hinic3_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) + { + if (hinic3_is_ethdev_valid(dev) == false) { + return -EINVAL; +diff --git a/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c b/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c +index ba5ca31d78..77c79cdc9d 100644 +--- a/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c ++++ b/drivers/net/hinic3/src/hinic3_qos/comm/hinic3_vf_port_qos_public.c +@@ -241,7 +241,7 @@ int hinic3_vm_qos_limit_get(uint16_t qos_id, uint16_t dir, uint16_t type, struct + return ret; + } + +-int hinic3_net_qos_limit_set(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t max_rate, uint64_t max_burst) ++int hinic3_net_qos_limit_set(uint16_t host_id __rte_unused, uint16_t dir, uint16_t type, uint64_t max_rate, uint64_t max_burst) + { + int ret; + struct hinic3_drv_ops *ops = NULL; +@@ -257,7 +257,7 @@ int hinic3_net_qos_limit_set(uint16_t host_id, uint16_t dir, uint16_t type, uint + return ret; + } + +-int hinic3_net_qos_limit_get(uint16_t host_id, uint16_t dir, uint16_t type, uint64_t *max_rate, uint64_t *max_burst) ++int hinic3_net_qos_limit_get(uint16_t host_id __rte_unused, uint16_t dir, uint16_t type, uint64_t *max_rate, uint64_t *max_burst) + { + int ret; + struct hinic3_drv_ops *ops = NULL; +diff --git a/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c +index 241d8c2072..28ea08b6b3 100644 +--- a/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c ++++ b/drivers/net/hinic3/src/hinic3_qos/meter/hinic3_qos.c +@@ -9,7 +9,7 @@ + + struct rte_mtr_ops *g_hinic3_mtr_ops = NULL; + +-int hinic3_mtr_ops_get(struct rte_eth_dev *dev, void *ops) ++int hinic3_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *ops) + { + if (g_hinic3_mtr_ops == NULL) { + g_hinic3_mtr_ops = hinic3_mtr_multi_ops_construct(); +diff --git a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c +index 8d31502457..4bf2fb767b 100644 +--- a/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c ++++ b/drivers/net/hinic3/src/hinic3_qos/multilevel_qos/hinic3_mtr.c +@@ -404,7 +404,7 @@ static void hinic3_meter_conf_set(struct hinic3_meter_node *meter, uint32_t mete + } + + static int hinic3_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, struct rte_mtr_params *params, +- int shared, struct rte_mtr_error *error) ++ int shared __rte_unused, struct rte_mtr_error *error) + { + if (dev == NULL || params == NULL || error == NULL) { + HINIC3_LOG(ERR, QOS, "Meter add: Meter parameter is empty."); +@@ -1001,7 +1001,7 @@ static void hinic3_qos_vm_clear(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_ + + /* 如果group中还用别的模式、别的方向的限速,则不能将端口移除group */ + for (int i = 0; i < HINIC3_METER_DIR_NUM; i++) { +- if (i != index && group_info->meter[i].is_used == true) { ++ if (i != (int)index && group_info->meter[i].is_used == true) { + is_unbind = false; + } + } +@@ -1021,7 +1021,7 @@ static void hinic3_qos_vm_clear(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_ + } + } + +-static void hinic3_qos_net_clear(struct hinic3_vf_dev *vf_dev, enum hinic3_meter_qos_direction dir, uint64_t *qos_mask) ++static void hinic3_qos_net_clear(struct hinic3_vf_dev *vf_dev __rte_unused, enum hinic3_meter_qos_direction dir, uint64_t *qos_mask) + { + int ret; + enum hinic3_qos_tablehead index; +@@ -1172,7 +1172,7 @@ static int hinic3_qos_vm_set(uint16_t port_id, uint32_t meter_id, uint32_t *next + return ret; + } + +-static int hinic3_qos_net_set(uint16_t port_id, uint32_t meter_id, uint32_t *next_meter_id, ++static int hinic3_qos_net_set(uint16_t port_id __rte_unused, uint32_t meter_id, uint32_t *next_meter_id, + enum hinic3_meter_qos_direction dir) + { + int ret = -1; +@@ -1476,7 +1476,7 @@ static int hinic3_meter_clear_by_flow(struct rte_flow *flow, struct hinic3_vf_de + return 0; + } + +-int hinic3_qos_flow_delete(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error) ++int hinic3_qos_flow_delete(struct rte_eth_dev *dev __rte_unused, struct rte_flow *flow, struct rte_flow_error *error __rte_unused) + { + int ret; + struct hinic3_vf_dev *vf_dev = NULL; +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c +index ef76e2d503..6469e95dde 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c +@@ -93,7 +93,7 @@ void *hinic3_alloc_from_ufid_map_mpool(void) + return dpak_mempool_alloc(g_mpool_mgmt.ufid_map_mpool, HINIC3_UFID_MAP); + } + +-void hinic3_dump_mempool_info(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++void hinic3_dump_mempool_info(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + struct ds ds = DS_EMPTY_INITIALIZER; + hinic3_show_one_mpool(g_mpool_mgmt.rte_flow_mpool, &ds, false); +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c +index c6c675d303..ebb95aa733 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_hmap.c +@@ -13,7 +13,7 @@ void hinic3_ufid_hmap_init(struct hmap *ufid_hmap) + hinic3_hmap_init(ufid_hmap); + } + +-static inline void *hinic3_ufid_map_alloc(struct hmap *ufid_hmap, HINIC3_UFID_MAP_TYPE type) ++static inline void *hinic3_ufid_map_alloc(struct hmap *ufid_hmap __rte_unused, HINIC3_UFID_MAP_TYPE type) + { + switch (type) { + case EMC_UFID_MAP: +@@ -25,7 +25,7 @@ static inline void *hinic3_ufid_map_alloc(struct hmap *ufid_hmap, HINIC3_UFID_MA + return NULL; + } + +-static inline void hinic3_ufid_map_dealloc(struct hmap *ufid_hmap, void *ptr, HINIC3_UFID_MAP_TYPE type) ++static inline void hinic3_ufid_map_dealloc(struct hmap *ufid_hmap __rte_unused, void *ptr, HINIC3_UFID_MAP_TYPE type) + { + switch (type) { + case EMC_UFID_MAP: +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c +index 89e7d5b548..5ed099afe6 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_ufid_map_rte_flow.c +@@ -75,7 +75,7 @@ uint32_t hinic3_hash_generate(const struct hinic3_conntrack_key *key) + uint32_t hash = hinic3_mpool_mgmt.hash_base; + hash = hinic3_hash_add(hash, key->meta_num); + +- for (int idx = 0; idx < key->meta.key_len / sizeof(uint32_t); idx++) { ++ for (uint32_t idx = 0; idx < key->meta.key_len / sizeof(uint32_t); idx++) { + hash = hinic3_hash_add(hash, ((const uint32_t *)key->key)[idx]); + } + return hash; +@@ -276,7 +276,7 @@ static void hinic3_release_ufid_map(int index) + } + } + +-void hinic3_dump_hmap_flow_num(struct unixctl_conn *conn, int argc, const char *argv[], void *aux) ++void hinic3_dump_hmap_flow_num(struct unixctl_conn *conn, int argc __rte_unused, const char *argv[] __rte_unused, void *aux) + { + uint32_t flow_num = 0; + struct ds ds = DS_EMPTY_INITIALIZER; +-- +2.47.0.windows.2 + diff --git a/0103-prohibit-mp-extention.patch b/0103-prohibit-mp-extention.patch new file mode 100644 index 0000000000000000000000000000000000000000..14d20770aee4c462f7fe7d43e922cf5c73c0e0c9 --- /dev/null +++ b/0103-prohibit-mp-extention.patch @@ -0,0 +1,87 @@ +From 19d0a807f6e848669858bb23dae54b1493aa2108 Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Mon, 21 Jul 2025 21:07:31 +0800 +Subject: [PATCH] prohibit-mp-extention + +--- + .../hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c | 8 +++++--- + .../hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h | 3 ++- + .../hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c | 4 ++-- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c +index 461ccfa3b8..12b3ee0625 100644 +--- a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c ++++ b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.c +@@ -145,7 +145,9 @@ static void *dpak_mp_alloc_mem_from_blocks(struct dpak_mempool *mp, uint32_t nee + } + + HINIC3_LOG(WARNING, FLOW, "mempool of ele_size %u no enough memory, start alloc new block", need_size); +- (void)dpak_mp_insert_blocks(mp, need_size, mp->per_block_ele_count, module_id); ++ if (mp->is_extend) { ++ (void)dpak_mp_insert_blocks(mp, need_size, mp->per_block_ele_count, module_id); ++ } + return NULL; + } + +@@ -276,7 +278,7 @@ void *dpak_mempool_alloc(struct dpak_mempool *mp, enum hinic3_module module_id) + } + + struct dpak_mempool *hinic3_create_single_mpool(const char *pool_name, uint32_t ele_size, uint32_t ele_num, +- enum hinic3_module module_id) ++ enum hinic3_module module_id, bool is_extend) + { + if (pool_name == NULL) { + HINIC3_LOG(ERR, FLOW, "pool_name is NULL."); +@@ -294,7 +296,7 @@ struct dpak_mempool *hinic3_create_single_mpool(const char *pool_name, uint32_t + hinic3_free(pool); + return NULL; + } +- ++ pool->is_extend = is_extend; + ret = dpak_mempool_create(pool, ele_size, ele_num, module_id); + if (ret != 0) { + dpak_mempool_destroy(pool); +diff --git a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h +index ad40415f5c..2409f4429d 100644 +--- a/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h ++++ b/drivers/net/hinic3/src/common/hinic3_mpool_mgmt/hinic3_mpool.h +@@ -40,13 +40,14 @@ struct dpak_mempool { + struct dpak_mp_block *blk_list; + pthread_mutex_t lock; + bool is_valid; ++ bool is_extend; + }; + + int dpak_mempool_flush(struct dpak_mempool *mp); + void dpak_mempool_free(struct dpak_mempool *mp, void *ptr); + void dpak_mempool_destroy(struct dpak_mempool *mp); + struct dpak_mempool *hinic3_create_single_mpool(const char *pool_name, uint32_t ele_size, uint32_t ele_num, +- enum hinic3_module module_id); ++ enum hinic3_module module_id, bool is_extend); + void *dpak_mempool_alloc(struct dpak_mempool *mp, enum hinic3_module module_id); + void hinic3_show_one_mpool(const struct dpak_mempool *mpool, struct ds *ds, bool is_end); + #endif +diff --git a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c +index 6469e95dde..cd08680120 100644 +--- a/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c ++++ b/drivers/net/hinic3/src/hinic3_ufid_map/hinic3_mpool_rte_flow.c +@@ -34,13 +34,13 @@ static int hinic3_init_flow_mpool(void) + uint32_t max_flow_num = hinic3_max_flow_num_get(); + + g_mpool_mgmt.rte_flow_mpool = hinic3_create_single_mpool(HINIC3_RTE_FLOW_ELE_MPOOL_NAME, sizeof(struct rte_flow), +- max_flow_num * HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM, HINIC3_UFID_MAP); ++ max_flow_num * HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM, HINIC3_UFID_MAP, false); + if (g_mpool_mgmt.rte_flow_mpool == NULL) { + return -1; + } + + g_mpool_mgmt.ufid_map_mpool = hinic3_create_single_mpool(HINIC3_UFID_MAP_MPOOL_NAME, +- sizeof(struct hinic3_ufid_hmap_node), max_flow_num * HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM, HINIC3_UFID_MAP); ++ sizeof(struct hinic3_ufid_hmap_node), max_flow_num * HINIC3_RTE_FLOW_SINGLE_BLOCK_NUM, HINIC3_UFID_MAP, false); + if (g_mpool_mgmt.ufid_map_mpool == NULL) { + dpak_mempool_destroy(g_mpool_mgmt.rte_flow_mpool); + g_mpool_mgmt.rte_flow_mpool = NULL; +-- +2.47.0.windows.2 + diff --git a/0104-fix-build-rpm-problem.patch b/0104-fix-build-rpm-problem.patch new file mode 100644 index 0000000000000000000000000000000000000000..f784bbf5c62441e4afa3b4aaf1567e3c07c4ed1f --- /dev/null +++ b/0104-fix-build-rpm-problem.patch @@ -0,0 +1,26 @@ +From 3ed40b72bfeb8bddbdf977c25a7f8621052c5826 Mon Sep 17 00:00:00 2001 +From: zry6666 +Date: Thu, 24 Jul 2025 21:28:06 +0800 +Subject: [PATCH] fix build rpm problem + +--- + drivers/net/hinic3/meson.build | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build +index 178e82193b..83cce4fbf0 100644 +--- a/drivers/net/hinic3/meson.build ++++ b/drivers/net/hinic3/meson.build +@@ -109,9 +109,6 @@ sources = files( + ) + + includes += include_directories( +- '../../../lib/distributor/', +- '../../../build', +- '../../../config', + 'include', + 'src/', + 'src/hinic3_capture', +-- +2.47.0.windows.2 + diff --git a/dpdk.spec b/dpdk.spec index 80e861882adbf65213ab6adb736627b323ed2d1a..be6bae5581fc6953f545174c4473a013d9b526ce 100644 --- a/dpdk.spec +++ b/dpdk.spec @@ -11,7 +11,7 @@ Name: dpdk Version: 23.11 -Release: 32 +Release: 33 URL: http://dpdk.org Source: https://fast.dpdk.org/rel/dpdk-%{version}.tar.xz @@ -127,6 +127,17 @@ Patch6093: 0093-net-hns3-fix-unrelease-some-resources-on-reset-case.patch Patch6094: 0094-net-xsc-optimize-rx.patch +Patch6095: 0095-Upstream-hinic3-DPDK-driver.patch +Patch6096: 0096-remove-macro-HAVE_OVS_DPDK.patch +Patch6097: 0097-Support-set-mtu-feature.patch +Patch6098: 0098-fix-error-log.patch +Patch6099: 0099-add-interface.patch +Patch6100: 0100-fix-warning.patch +Patch6101: 0101-add-collect-info-script.patch +Patch6102: 0102-eliminate-warning.patch +Patch6103: 0103-prohibit-mp-extention.patch +Patch6104: 0104-fix-build-rpm-problem.patch + BuildRequires: meson BuildRequires: python3-pyelftools BuildRequires: diffutils @@ -330,6 +341,9 @@ fi /usr/sbin/depmod %changelog +* Thu July 24 2025 zhangruiyu - 23.11-33 +- Kunpeng hinic3 patch + * Tue May 27 2025 qianrong - 23.11-32 - optimize xsc rx