diff options
author | Alex Williams <alex.williams@ni.com> | 2019-07-30 19:45:58 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:35 -0800 |
commit | 9f29b9a556634e41d13fa298f9634b67fdd0a749 (patch) | |
tree | 694a38eb03629aec1ea118f6b3cdf63c6cfd7d0d /tools | |
parent | 1c79742231c5cc3609e35bda34c8d9b9e7440f50 (diff) | |
download | uhd-9f29b9a556634e41d13fa298f9634b67fdd0a749.tar.gz uhd-9f29b9a556634e41d13fa298f9634b67fdd0a749.tar.bz2 uhd-9f29b9a556634e41d13fa298f9634b67fdd0a749.zip |
tools: Update dissectors for Wireshark major version 3, new CHDR
Dissectors may now be incompatible with earlier versions.
Fixes ZPU dissector.
Diffstat (limited to 'tools')
16 files changed, 1293 insertions, 973 deletions
diff --git a/tools/dissectors/CMakeLists.txt b/tools/dissectors/CMakeLists.txt index 9f63a356a..6d835aa48 100644 --- a/tools/dissectors/CMakeLists.txt +++ b/tools/dissectors/CMakeLists.txt @@ -1,106 +1,133 @@ # Copyright 2010-2013 Ettus Research LLC -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. +# Copyright 2019 Ettus Research, a National Instruments brand +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +cmake_minimum_required(VERSION 3.1) +cmake_policy(SET CMP0048 NEW) +project(EttusDissectors VERSION 4.0.0 DESCRIPTION "Dissector Plugins" LANGUAGES C CXX) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) +set(UHD_HOST_ROOT ${CMAKE_SOURCE_DIR}/../../host) ######################################################################## -# Project setup +# useful macros ######################################################################## -cmake_minimum_required(VERSION 2.8) -project(ettus-dissector C) -enable_testing() +include(WSComponent) -#select the release build type by default to get optimization flags -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release") - message(STATUS "Build type not specified: defaulting to release.") -endif(NOT CMAKE_BUILD_TYPE) -set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") +set(PLUGIN_C_GENERATOR ${CMAKE_SOURCE_DIR}/make-plugin-reg.py) +macro(register_plugin_files _outputfile _registertype) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) + add_custom_command( + OUTPUT ${_outputfile} + DEPENDS ${ARGN} ${PLUGIN_C_GENERATOR} + COMMAND ${PYTHON_EXECUTABLE} + ${PLUGIN_C_GENERATOR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${_registertype} + ${ARGN} + COMMENT "Generating ${_outputfile}" + ) + +endmacro(register_plugin_files) + +# Plugin name and version info (major minor micro extra) +macro(SET_MODULE_INFO _plugin _ver_major _ver_minor _ver_micro _ver_extra) + if(WIN32) + # Create the Windows .rc file for the plugin. + set(MODULE_NAME ${_plugin}) + set(MODULE_VERSION_MAJOR ${_ver_major}) + set(MODULE_VERSION_MINOR ${_ver_minor}) + set(MODULE_VERSION_MICRO ${_ver_micro}) + set(MODULE_VERSION_EXTRA ${_ver_extra}) + set(MODULE_VERSION "${MODULE_VERSION_MAJOR}.${MODULE_VERSION_MINOR}.${MODULE_VERSION_MICRO}.${MODULE_VERSION_EXTRA}") + set(RC_MODULE_VERSION "${MODULE_VERSION_MAJOR},${MODULE_VERSION_MINOR},${MODULE_VERSION_MICRO},${MODULE_VERSION_EXTRA}") + + set(MSVC_VARIANT "${CMAKE_GENERATOR}") + + # Create the plugin.rc file from the template + set(_plugin_rc_in ${CMAKE_CURRENT_SOURCE_DIR}/plugin.rc.in) + configure_file(${_plugin_rc_in} plugin.rc @ONLY) + set(PLUGIN_RC_FILE ${CMAKE_CURRENT_BINARY_DIR}/plugin.rc) + endif() + + set(PLUGIN_VERSION "${_ver_major}.${_ver_minor}.${_ver_micro}") + add_definitions(-DPLUGIN_VERSION=\"${PLUGIN_VERSION}\") + add_definitions(-DVERSION_MAJOR=${Wireshark_VERSION_MAJOR}) + add_definitions(-DVERSION_MINOR=${Wireshark_VERSION_MINOR}) +endmacro() + +macro(ADD_PLUGIN_LIBRARY _plugin _subfolder) + add_library(${_plugin} MODULE + ${PLUGIN_FILES} + ${PLUGIN_RC_FILE} + ) + + set_target_properties(${_plugin} PROPERTIES + PREFIX "" + LINK_FLAGS "${WS_LINK_FLAGS}" + FOLDER "Plugins" + ) + + set_target_properties(${_plugin} PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${_subfolder} + INSTALL_RPATH "" + ) +endmacro() + +macro(INSTALL_PLUGIN _plugin _subfolder) + install(TARGETS ${_plugin} + LIBRARY DESTINATION ${_subfolder} NAMELINK_SKIP + ) + #LIBRARY DESTINATION ${Wireshark_PLUGIN_INSTALL_DIR}/${_subfolder} NAMELINK_SKIP + #RUNTIME DESTINATION ${Wireshark_PLUGIN_INSTALL_DIR} + #ARCHIVE DESTINATION ${Wireshark_PLUGIN_INSTALL_DIR} +endmacro() -######################################################################## -# Compiler specific setup -######################################################################## -#if(CMAKE_COMPILER_IS_GNUC AND NOT WIN32) -# #http://gcc.gnu.org/wiki/Visibility -# add_definitions(-fvisibility=visible) -#endif() +find_package(Wireshark CONFIG REQUIRED) find_package(GLIB2) -if(NOT GLIB2_FOUND) - message(FATAL_ERROR "Glib not found") -endif() -find_package(Wireshark) -if(NOT WIRESHARK_FOUND) - message(FATAL_ERROR "Wireshark dev package not found") +if(NOT Wireshark_PLUGINS_ENABLED) + message(FATAL_ERROR "Wireshark was compiled without support for plugins") endif() +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX ${Wireshark_PLUGIN_INSTALL_DIR} + CACHE + PATH + "Default installation path for plugins" + FORCE + ) +endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + +set(UHD_INCLUDE_DIR "${UHD_HOST_ROOT}/include") +set(UHDLIB_INCLUDE_DIR "${UHD_HOST_ROOT}/lib/include") -######################################################################## -# Setup the include and linker paths -######################################################################## include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR} + ${UHD_INCLUDE_DIR} + ${UHDLIB_INCLUDE_DIR} ${GLIB2_INCLUDE_DIRS} - ${WIRESHARK_INCLUDE_DIRS} + ${Wireshark_INCLUDE_DIR} ) -set(CMAKE_INSTALL_LIBDIR ~/.wireshark) - -# Set component parameters -set(ETTUS_DISSECTOR_INCLUDE_DIRS ${CMAKE_SOURCE_DIR} CACHE INTERNAL "" FORCE) -set(ETTUS_DISSECTOR_NAME "chdr" CACHE STRING "Select a dissector to build") +WS_REGISTER_COMPONENT("RFNoC" ENABLE_RFNOC ON "" OFF ON) +WS_REGISTER_COMPONENT("Octoclock" ENABLE_OCTOCLOCK ON "" OFF OFF) +WS_REGISTER_COMPONENT("ZPU" ENABLE_ZPU ON "" OFF OFF) -function(generate_ettus_dissector DISSECTOR_NAME) - - set(ETTUS_PLUGIN_SRC ${CMAKE_SOURCE_DIR}/packet-${DISSECTOR_NAME}.c) - - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/moduleinfo.h.in - ${CMAKE_BINARY_DIR}/moduleinfo.h - ) +if(ENABLE_RFNOC) + add_subdirectory(epan/rfnoc) +endif(ENABLE_RFNOC) - set(PLUGIN_C_GENERATOR ${CMAKE_SOURCE_DIR}/make-dissector-reg.py) - set(PLUGIN_C plugin.c) - - add_custom_command( - OUTPUT ${PLUGIN_C} - DEPENDS ${ETTUS_PLUGIN_SRC} - COMMAND ${PLUGIN_C_GENERATOR} ${CMAKE_SOURCE_DIR} plugin ${ETTUS_PLUGIN_SRC} - COMMENT "Generating ${PLUGIN_C}" - ) - - set(ETTUS_TARGET_NAME "${DISSECTOR_NAME}-plugin") - add_library(${ETTUS_TARGET_NAME} MODULE - ${PLUGIN_C} - moduleinfo.h - ${ETTUS_PLUGIN_SRC} - ) - set_target_properties(${ETTUS_TARGET_NAME} PROPERTIES PREFIX "") - set_target_properties(${ETTUS_TARGET_NAME} PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") - target_link_libraries(${ETTUS_TARGET_NAME} wireshark) +if(ENABLE_OCTOCLOCK) + add_subdirectory(epan/octoclock) +endif(ENABLE_OCTOCLOCK) - install(TARGETS ${ETTUS_TARGET_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/plugins NAMELINK_SKIP - ) +if(ENABLE_ZPU) + add_subdirectory(epan/zpu) +endif(ENABLE_ZPU) -endfunction(generate_ettus_dissector) +WS_PRINT_COMPONENT_SUMMARY() -generate_ettus_dissector("${ETTUS_DISSECTOR_NAME}") diff --git a/tools/dissectors/cmake/Modules/WSComponent.cmake b/tools/dissectors/cmake/Modules/WSComponent.cmake new file mode 100644 index 000000000..3e7f14900 --- /dev/null +++ b/tools/dissectors/cmake/Modules/WSComponent.cmake @@ -0,0 +1,104 @@ +# +# Copyright 2019 Ettus Research, a National Instruments brand +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +######################################################################## +set(_ws_enabled_components "" CACHE INTERNAL "" FORCE) +set(_ws_disabled_components "" CACHE INTERNAL "" FORCE) + +######################################################################## +# Register a component into the system +# - name the component string name ("FOO") +# - var the global enable variable (ENABLE_FOO) +# - enb the default enable setting (ON) +# - deps a list of dependencies (DEPENDENCY_FOUND) +# - dis the default disable setting (OFF) +# - req fail if dependencies not met (unless specifically disabled) +# +# In parentheses are examples. If you specify those, we register a component +# "FOO" which is enabled by calling CMake with -DENABLE_FOO=ON. It defaults to +# ON, unless DEPENDENCY_FOUND is false, in which case it becomes false. +######################################################################## +macro(WS_REGISTER_COMPONENT name var enb deps dis req) + message(STATUS "") + message(STATUS "Configuring ${name} support...") + foreach(dep ${deps}) + message(STATUS " Dependency ${dep} = ${${dep}}") + endforeach(dep) + + # If user specified option, store here. Note: If the user doesn't specify + # this option on the cmake command line, both user_enabled and + # user_disabled will be false! + if("${${var}}" STREQUAL "OFF") + set(user_disabled TRUE) + else() + set(user_disabled FALSE) + endif("${${var}}" STREQUAL "OFF") + if("${${var}}" STREQUAL "ON") + set(user_enabled TRUE) + else() + set(user_enabled FALSE) + endif("${${var}}" STREQUAL "ON") + + # Override default if user set + if(user_enabled OR user_disabled) + set(option "${${var}}") + else(user_enabled OR user_disabled) + set(option ${req}) + endif() + + # setup the dependent option for this component + include(CMakeDependentOption) + CMAKE_DEPENDENT_OPTION(${var} "enable ${name} support" ${option} "${deps}" ${dis}) + + # There are two failure cases: + # 1) The user requested this component explicitly (-DENABLE_FOO=ON) but the + # requirements are not met. + # 2) The user did not explicitly turn off this component (-DENABLE_FOO=OFF) + # but it is flagged as required by ${req} + if(NOT ${var} AND user_enabled) # Case 1) + message(FATAL_ERROR "Dependencies for required component ${name} not met.") + endif(NOT ${var} AND user_enabled) + if(NOT ${var} AND ${req} AND NOT user_disabled) # Case 2) + message(FATAL_ERROR "Dependencies for required component ${name} not met.") + endif(NOT ${var} AND ${req} AND NOT user_disabled) + + #append the component into one of the lists + if(${var}) + message(STATUS " Enabling ${name} support.") + list(APPEND _ws_enabled_components ${name}) + else(${var}) + message(STATUS " Disabling ${name} support.") + list(APPEND _ws_disabled_components ${name}) + endif(${var}) + message(STATUS " Override with -D${var}=ON/OFF") + + #make components lists into global variables + set(_ws_enabled_components ${_ws_enabled_components} CACHE INTERNAL "" FORCE) + set(_ws_disabled_components ${_ws_disabled_components} CACHE INTERNAL "" FORCE) +endmacro(WS_REGISTER_COMPONENT) + +######################################################################## +# Print the registered component summary +######################################################################## +function(WS_PRINT_COMPONENT_SUMMARY) + message(STATUS "") + message(STATUS "######################################################") + message(STATUS "# Ettus dissectors enabled ") + message(STATUS "######################################################") + foreach(comp ${_ws_enabled_components}) + message(STATUS " * ${comp}") + endforeach(comp) + + message(STATUS "") + message(STATUS "######################################################") + message(STATUS "# Ettus dissectors disabled ") + message(STATUS "######################################################") + foreach(comp ${_ws_disabled_components}) + message(STATUS " * ${comp}") + endforeach(comp) + + message(STATUS "") +endfunction(WS_PRINT_COMPONENT_SUMMARY) diff --git a/tools/dissectors/epan/octoclock/CMakeLists.txt b/tools/dissectors/epan/octoclock/CMakeLists.txt new file mode 100644 index 000000000..dcc8077c9 --- /dev/null +++ b/tools/dissectors/epan/octoclock/CMakeLists.txt @@ -0,0 +1,25 @@ +set_module_info(octoclock 4 0 0 0) + +set(DISSECTOR_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/packet-octoclock.c +) + +set(PLUGIN_FILES + ${CMAKE_CURRENT_BINARY_DIR}/plugin.c + ${DISSECTOR_SRC} +) + +register_plugin_files(${CMAKE_CURRENT_BINARY_DIR}/plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_plugin_library(octoclock epan) + +set_target_properties(octoclock PROPERTIES PREFIX "") +set_target_properties(octoclock PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") +target_link_libraries(octoclock wireshark epan) + +install_plugin(octoclock epan) + + diff --git a/tools/dissectors/packet-octoclock.c b/tools/dissectors/epan/octoclock/packet-octoclock.c index 453c325d7..e8e5e6858 100644 --- a/tools/dissectors/packet-octoclock.c +++ b/tools/dissectors/epan/octoclock/packet-octoclock.c @@ -2,20 +2,9 @@ * Dissector for Ettus Octoclock packets * * Copyright 2016 Ettus Research + * Copyright 2019 Ettus Research, a National Instruments brand * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" @@ -26,7 +15,7 @@ #include <stdio.h> #include <stddef.h> -#include "../../host/lib/usrp_clock/octoclock/common.h" +#include "../../../../host/lib/usrp_clock/octoclock/common.h" #define LOG_HEADER "[Octoclock] " #define size_mem(t,m) sizeof(((t*)0)->m) @@ -78,9 +67,9 @@ static const value_string packetcodes[] = { /* Forward-declare the dissector functions */ void proto_register_octo(void); void proto_reg_handoff_octo(void); -static void dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +static int dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data); -static void dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static int dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "OCTO"); col_clear(pinfo->cinfo, COL_INFO); @@ -138,7 +127,9 @@ static void dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) packet_offset(len), packet_elem_size(len), ENC_LITTLE_ENDIAN); + return len; } + return 0; } @@ -207,6 +198,6 @@ void proto_reg_handoff_octo(void) { static dissector_handle_t octo_handle; octo_handle = create_dissector_handle(dissect_octo, proto_octo); - dissector_add_uint("udp.port", OCTOCLOCK_PORT, octo_handle); - dissector_add_uint("udp.port", OCTOCLOCK_UDP_GPSDO_PORT, octo_handle); + dissector_add_uint_with_preference("udp.port", OCTOCLOCK_PORT, octo_handle); + dissector_add_uint_with_preference("udp.port", OCTOCLOCK_UDP_GPSDO_PORT, octo_handle); } diff --git a/tools/dissectors/plugin.rc.in b/tools/dissectors/epan/octoclock/plugin.rc.in index 29fcfdc33..eca74e1a7 100644 --- a/tools/dissectors/plugin.rc.in +++ b/tools/dissectors/epan/octoclock/plugin.rc.in @@ -1,4 +1,5 @@ #include "winver.h" +#pragma code_page(65001) VS_VERSION_INFO VERSIONINFO FILEVERSION @RC_MODULE_VERSION@ @@ -17,13 +18,13 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Ettus Research (National Instruments)\0" - VALUE "FileDescription", "@PACKAGE@ dissector\0" + VALUE "FileDescription", "@MODULE_NAME@ dissector\0" VALUE "FileVersion", "@MODULE_VERSION@\0" - VALUE "InternalName", "@PACKAGE@ @MODULE_VERSION@\0" - VALUE "LegalCopyright", "Copyright © 2013 Ettus Research (National Instruments)\0" - VALUE "OriginalFilename", "@PLUGIN_NAME@.dll\0" + VALUE "InternalName", "@MODULE_NAME@ @MODULE_VERSION@\0" + VALUE "LegalCopyright", "Copyright © 2019 Ettus Research (National Instruments)\0" + VALUE "OriginalFilename", "@MODULE_NAME@.dll\0" VALUE "ProductName", "Wireshark\0" - VALUE "ProductVersion", "@VERSION@\0" + VALUE "ProductVersion", "@PROJECT_VERSION@\0" VALUE "Comments", "Build with @MSVC_VARIANT@\0" END END diff --git a/tools/dissectors/epan/rfnoc/CMakeLists.txt b/tools/dissectors/epan/rfnoc/CMakeLists.txt new file mode 100644 index 000000000..3c021a464 --- /dev/null +++ b/tools/dissectors/epan/rfnoc/CMakeLists.txt @@ -0,0 +1,27 @@ +set_module_info(rfnoc 4 0 0 0) + +set(DISSECTOR_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/packet-rfnoc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../host/lib/exception.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../host/lib/rfnoc/chdr_types.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../host/lib/rfnoc/chdr_packet.cpp +) + +set(PLUGIN_FILES + ${CMAKE_CURRENT_BINARY_DIR}/plugin.c + ${DISSECTOR_SRC} +) + +register_plugin_files(${CMAKE_CURRENT_BINARY_DIR}/plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_plugin_library(rfnoc epan) + +set_target_properties(rfnoc PROPERTIES PREFIX "") +set_target_properties(rfnoc PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") +target_link_libraries(rfnoc wireshark epan) + +install_plugin(rfnoc epan) + diff --git a/tools/dissectors/epan/rfnoc/packet-rfnoc.cpp b/tools/dissectors/epan/rfnoc/packet-rfnoc.cpp new file mode 100644 index 000000000..23672793e --- /dev/null +++ b/tools/dissectors/epan/rfnoc/packet-rfnoc.cpp @@ -0,0 +1,705 @@ +/* + * Dissector for UHD RFNoC (CHDR) packets + * + * Copyright 2019 Ettus Research, a National Instruments brand + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glib.h> +#include <epan/packet.h> + +#ifdef __cplusplus +} +#endif + +#include <cstdio> +#include <iostream> + +#include "../../../../host/lib/usrp/x300/x300_fw_common.h" +#include <uhdlib/rfnoc/chdr_packet.hpp> + +constexpr unsigned int RFNOC_PORT = X300_VITA_UDP_PORT; +static const uhd::rfnoc::chdr::chdr_packet_factory pkt_factory(uhd::rfnoc::CHDR_W_64, uhd::ENDIANNESS_BIG); + +static int proto_rfnoc = -1; +static int hf_rfnoc_hdr = -1; +static int hf_rfnoc_hdr_vc = -1; +static int hf_rfnoc_hdr_eob = -1; +static int hf_rfnoc_hdr_eov = -1; +static int hf_rfnoc_hdr_pkttype = -1; +static int hf_rfnoc_hdr_num_mdata = -1; +static int hf_rfnoc_hdr_seqnum = -1; +static int hf_rfnoc_hdr_len = -1; +static int hf_rfnoc_hdr_dst_epid = -1; +static int hf_rfnoc_timestamp = -1; +static int hf_rfnoc_src_epid = -1; +static int hf_rfnoc_ctrl = -1; +static int hf_rfnoc_ctrl_dst_port = -1; +static int hf_rfnoc_ctrl_src_port = -1; +static int hf_rfnoc_ctrl_num_data = -1; +static int hf_rfnoc_ctrl_seqnum = -1; +static int hf_rfnoc_ctrl_is_ack = -1; +static int hf_rfnoc_ctrl_address = -1; +static int hf_rfnoc_ctrl_data0 = -1; +static int hf_rfnoc_ctrl_data = -1; // TODO: Figure out what to do here +static int hf_rfnoc_ctrl_byte_enable = -1; +static int hf_rfnoc_ctrl_opcode = -1; +static int hf_rfnoc_ctrl_status = -1; +static int hf_rfnoc_strs = -1; +static int hf_rfnoc_strs_status = -1; +static int hf_rfnoc_strs_capacity_bytes = -1; +static int hf_rfnoc_strs_capacity_pkts = -1; +static int hf_rfnoc_strs_xfer_bytes = -1; +static int hf_rfnoc_strs_xfer_pkts = -1; +static int hf_rfnoc_strs_buff_info = -1; +static int hf_rfnoc_strs_ext_status = -1; +static int hf_rfnoc_strc = -1; +static int hf_rfnoc_strc_opcode = -1; +static int hf_rfnoc_strc_data = -1; +static int hf_rfnoc_strc_num_pkts = -1; +static int hf_rfnoc_strc_num_bytes = -1; +static int hf_rfnoc_mgmt = -1; +static int hf_rfnoc_mgmt_protover = -1; +static int hf_rfnoc_mgmt_chdr_w = -1; +static int hf_rfnoc_mgmt_num_hops = -1; +static int hf_rfnoc_mgmt_hop = -1; +static int hf_rfnoc_mgmt_op = -1; +static int hf_rfnoc_mgmt_op_code = -1; +static int hf_rfnoc_mgmt_op_dest = -1; +static int hf_rfnoc_mgmt_op_device_id = -1; +static int hf_rfnoc_mgmt_op_node_type = -1; +static int hf_rfnoc_mgmt_op_node_inst = -1; +static int hf_rfnoc_mgmt_op_cfg_address = -1; +static int hf_rfnoc_mgmt_op_cfg_data = -1; + +static const value_string RFNOC_PACKET_TYPES[] = { + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_MGMT, "Management" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_STRS, "Stream Status" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_STRC, "Stream Command" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_CTRL, "Control" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_DATA_NO_TS, "Data" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_DATA_WITH_TS, "Data with Timestamp" }, +}; + +static const value_string RFNOC_PACKET_TYPES_SHORT[] = { + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_MGMT, "mgmt" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_STRS, "strs" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_STRC, "strc" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_CTRL, "ctrl" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_DATA_NO_TS, "data" }, + { uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_DATA_WITH_TS, "data" }, +}; + +static const value_string RFNOC_CTRL_STATUS[] = { + { uhd::rfnoc::chdr::ctrl_status_t::CMD_OKAY, "OK" }, + { uhd::rfnoc::chdr::ctrl_status_t::CMD_CMDERR, "CMDERR" }, + { uhd::rfnoc::chdr::ctrl_status_t::CMD_TSERR, "TSERR" }, + { uhd::rfnoc::chdr::ctrl_status_t::CMD_WARNING, "WARNING" }, +}; + +static const value_string RFNOC_CTRL_OPCODES[] = { + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_SLEEP, "sleep" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_WRITE, "write" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_READ, "read" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_READ_WRITE, "r/w" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_BLOCK_WRITE, "block write" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_BLOCK_READ, "block read" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_POLL, "poll" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_USER1, "user1" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_USER2, "user2" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_USER3, "user3" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_USER4, "user4" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_USER5, "user5" }, + { uhd::rfnoc::chdr::ctrl_opcode_t::OP_USER6, "user6" }, +}; + +static const value_string RFNOC_STRS_STATUS[] = { + { uhd::rfnoc::chdr::strs_status_t::STRS_OKAY, "OK" }, + { uhd::rfnoc::chdr::strs_status_t::STRS_CMDERR, "CMDERR" }, + { uhd::rfnoc::chdr::strs_status_t::STRS_SEQERR, "SEQERR" }, + { uhd::rfnoc::chdr::strs_status_t::STRS_DATAERR, "DATAERR" }, + { uhd::rfnoc::chdr::strs_status_t::STRS_RTERR, "RTERR" }, +}; + +static const value_string RFNOC_STRC_OPCODES[] = { + { uhd::rfnoc::chdr::strc_op_code_t::STRC_INIT, "init" }, + { uhd::rfnoc::chdr::strc_op_code_t::STRC_PING, "ping" }, + { uhd::rfnoc::chdr::strc_op_code_t::STRC_RESYNC, "resync" }, +}; + +static const value_string RFNOC_MGMT_OPCODES[] = { + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_NOP, "nop" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_ADVERTISE, "advertise" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_SEL_DEST, "select_dest" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_RETURN, "return_to_sender" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_INFO_REQ, "node_info_req" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_INFO_RESP, "node_info_resp" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_CFG_WR_REQ, "cfg_wr_req" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_CFG_RD_REQ, "cfg_rd_req" }, + { uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_CFG_RD_RESP, "cfg_rd_resp" }, +}; + +/* the heuristic dissector is called on every packet with payload. + * The warning printed for this should only be printed once. + */ +static int heur_warning_printed = 0; + +/* Subtree handles: set by register_subtree_array */ +static gint ett_rfnoc = -1; +static gint ett_rfnoc_hdr = -1; +static gint ett_rfnoc_ctrl = -1; +static gint ett_rfnoc_strs = -1; +static gint ett_rfnoc_strc = -1; +static gint ett_rfnoc_mgmt = -1; +static gint ett_rfnoc_mgmt_hop = -1; +static gint ett_rfnoc_mgmt_hop_op = -1; + +/* Forward-declare the dissector functions */ +static int dissect_rfnoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data); + +/* The dissector itself */ +static int dissect_rfnoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + // Here are all the variables + proto_item *item; + proto_tree *rfnoc_tree; + proto_item *header_item; + proto_tree *header_tree; + proto_item *ctrl_item; + proto_tree *ctrl_tree; + proto_item *strs_item; + proto_tree *strs_tree; + proto_item *strc_item; + proto_tree *strc_tree; + proto_item *mgmt_item; + proto_tree *mgmt_tree; + proto_item *hop_item; + proto_tree *hop_tree; + proto_item *mgmt_op_item; + proto_tree *mgmt_op_tree; + gint len; + + guint64 hdr; + gint flag_offset; + guint8 *bytes; + guint8 hdr_bits = 0; + uint64_t timestamp; + int chdr_len = 0; + gboolean is_network; + gint endianness; + size_t offset = 0; + /* FIXME: Assuming CHDR_W_64 */ + size_t chdr_w_bytes = 8; + + if (pinfo->match_uint == RFNOC_PORT) { + is_network = TRUE; + flag_offset = 0; + endianness = ENC_BIG_ENDIAN; + } + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFNoC"); + /* Clear out stuff in info column */ + col_clear(pinfo->cinfo, COL_INFO); + + len = tvb_reported_length(tvb); + + if (tree){ + guint64 hdr = tvb_get_ntoh64(tvb, 0); + uhd::rfnoc::chdr::chdr_header chdr_hdr(hdr); + chdr_len = chdr_hdr.get_length(); + len = (len < chdr_len) ? len : chdr_len; + + /* Start with a top-level item to add everything else to */ + item = proto_tree_add_item(tree, proto_rfnoc, tvb, offset, len, ENC_NA); + + if (len >= 4) { + rfnoc_tree = proto_item_add_subtree(item, ett_rfnoc); + proto_item_append_text(item, ", Packet type: %s, Dst EPID: %d", + val_to_str(chdr_hdr.get_pkt_type(), RFNOC_PACKET_TYPES, "Unknown (0x%x)"), chdr_hdr.get_dst_epid() + ); + col_add_fstr(pinfo->cinfo, COL_INFO, "%s dst_epid=%d", + val_to_str(chdr_hdr.get_pkt_type(), RFNOC_PACKET_TYPES_SHORT, "Unknown (0x%x)"), chdr_hdr.get_dst_epid() + ); + + /* Header info. First, a top-level header tree item: */ + header_item = proto_tree_add_item(rfnoc_tree, hf_rfnoc_hdr, tvb, offset, 8, endianness); + header_tree = proto_item_add_subtree(header_item, ett_rfnoc_hdr); + /* Let us query hdr.type */ + proto_tree_add_string( + header_tree, hf_rfnoc_hdr_pkttype, tvb, offset+1, 1, + val_to_str(chdr_hdr.get_pkt_type(), RFNOC_PACKET_TYPES_SHORT, "invalid") + ); + + /* Add Dst EPID */ + proto_item_append_text(header_item, ", Dst EPID: %02x", chdr_hdr.get_dst_epid()); + proto_tree_add_uint(header_tree, hf_rfnoc_hdr_dst_epid, tvb, offset+6, 2, chdr_hdr.get_dst_epid()); + /* Add length */ + proto_tree_add_uint(header_tree, hf_rfnoc_hdr_len, tvb, offset+4, 2, chdr_hdr.get_length()); + /* Add sequence number */ + proto_tree_add_uint(header_tree, hf_rfnoc_hdr_seqnum, tvb, offset+2, 2, chdr_hdr.get_seq_num()); + + if (chdr_hdr.get_num_mdata()) { + /* Can't decode packets with metadata */ + return len; + } + + /* TODO: Update offsets if there is a timestamp. Also update lengths */ + /* Add subtree based on packet type */ + uhd::rfnoc::chdr::packet_type_t pkttype = chdr_hdr.get_pkt_type(); + offset += 8; + if (pkttype == uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_CTRL) { + ctrl_item = proto_tree_add_item(rfnoc_tree, hf_rfnoc_ctrl, tvb, 8, chdr_len-8, endianness); + ctrl_tree = proto_item_add_subtree(ctrl_item, ett_rfnoc_ctrl); + auto pkt = pkt_factory.make_ctrl(); + pkt->refresh(tvb_get_ptr(tvb, 0, chdr_len)); + auto payload = pkt->get_payload(); + + /* Add source EPID */ + proto_tree_add_uint(ctrl_tree, hf_rfnoc_src_epid, tvb, offset+2, 2, payload.src_epid); + /* Add source port */ + proto_tree_add_uint(ctrl_tree, hf_rfnoc_ctrl_src_port, tvb, offset+5, 2, payload.src_port); + /* Add dest port */ + proto_tree_add_uint(ctrl_tree, hf_rfnoc_ctrl_dst_port, tvb, offset+6, 2, payload.dst_port); + /* Add num data */ + proto_tree_add_uint(ctrl_tree, hf_rfnoc_ctrl_num_data, tvb, offset+5, 1, payload.data_vtr.size()); + /* Add is_ack */ + proto_tree_add_boolean(ctrl_tree, hf_rfnoc_ctrl_is_ack, tvb, offset+4, 1, payload.is_ack); + /* Add sequence number */ + proto_tree_add_uint(ctrl_tree, hf_rfnoc_ctrl_seqnum, tvb, offset+4, 1, payload.seq_num); + if (payload.timestamp) { + proto_tree_add_uint64(ctrl_tree, hf_rfnoc_timestamp, tvb, offset+8, 8, *payload.timestamp); + offset += 8; + } + /* Add data0 */ + proto_tree_add_uint(ctrl_tree, hf_rfnoc_ctrl_data0, tvb, offset+8, 4, payload.data_vtr[0]); + /* Add op code */ + proto_tree_add_string( + ctrl_tree, hf_rfnoc_ctrl_opcode, tvb, offset+12, 1, + val_to_str(payload.op_code, RFNOC_CTRL_OPCODES, "reserved") + ); + /* Add address */ + proto_tree_add_uint(ctrl_tree, hf_rfnoc_ctrl_address, tvb, offset+13, 3, payload.address); + } + + if (pkttype == uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_STRS) { + strs_item = proto_tree_add_item(rfnoc_tree, hf_rfnoc_strs, tvb, offset, chdr_len-8, endianness); + strs_tree = proto_item_add_subtree(strs_item, ett_rfnoc_strs); + auto pkt = pkt_factory.make_strs(); + pkt->refresh(tvb_get_ptr(tvb, 0, chdr_len)); + auto payload = pkt->get_payload(); + + proto_tree_add_string( + strs_tree, hf_rfnoc_strs_status, tvb, offset+5, 1, + val_to_str(payload.status, RFNOC_STRS_STATUS, "invalid") + ); + + /* Add source EPID */ + proto_tree_add_uint(strs_tree, hf_rfnoc_src_epid, tvb, offset+6, 2, payload.src_epid); + /* Add capacities */ + proto_tree_add_uint64(strs_tree, hf_rfnoc_strs_capacity_bytes, tvb, offset, 5, payload.capacity_bytes); + proto_tree_add_uint(strs_tree, hf_rfnoc_strs_capacity_pkts, tvb, offset+13, 3, payload.capacity_pkts); + /* Add xfer amounts */ + proto_tree_add_uint64(strs_tree, hf_rfnoc_strs_xfer_bytes, tvb, offset+16, 8, payload.xfer_count_bytes); + proto_tree_add_uint64(strs_tree, hf_rfnoc_strs_xfer_pkts, tvb, offset+8, 5, payload.xfer_count_pkts); + } + + if (pkttype == uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_STRC) { + strc_item = proto_tree_add_item(rfnoc_tree, hf_rfnoc_strc, tvb, 8, chdr_len-8, endianness); + strc_tree = proto_item_add_subtree(strc_item, ett_rfnoc_strc); + auto pkt = pkt_factory.make_strc(); + pkt->refresh(tvb_get_ptr(tvb, 0, chdr_len)); + auto payload = pkt->get_payload(); + + proto_tree_add_string( + strc_tree, hf_rfnoc_strc_opcode, tvb, offset+5, 1, + val_to_str(payload.op_code, RFNOC_STRC_OPCODES, "invalid") + ); + + /* Add source EPID */ + proto_tree_add_uint(strc_tree, hf_rfnoc_src_epid, tvb, offset+6, 2, payload.src_epid); + /* Add transfer amounts */ + proto_tree_add_uint64(strc_tree, hf_rfnoc_strc_num_bytes, tvb, offset+8, 8, payload.num_bytes); + proto_tree_add_uint64(strc_tree, hf_rfnoc_strc_num_pkts, tvb, offset, 5, payload.num_pkts); + } + + if (pkttype == uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_MGMT) { + mgmt_item = proto_tree_add_item(rfnoc_tree, hf_rfnoc_mgmt, tvb, offset, len-8, endianness); + mgmt_tree = proto_item_add_subtree(mgmt_item, ett_rfnoc_mgmt); + auto pkt = pkt_factory.make_mgmt(); + pkt->refresh(tvb_get_ptr(tvb, 0, chdr_len)); + auto payload = pkt->get_payload(); + /* Add source EPID */ + proto_tree_add_uint(mgmt_tree, hf_rfnoc_src_epid, tvb, offset+6, 2, payload.get_src_epid()); + size_t num_hops = payload.get_num_hops(); + offset += 8; + + /* FIXME: Assuming CHDR_W_64 here */ + for (size_t hop_id = 0; hop_id < num_hops; hop_id++) { + auto hop = payload.get_hop(hop_id); + size_t num_ops = hop.get_num_ops(); + hop_item = proto_tree_add_item(mgmt_tree, hf_rfnoc_mgmt_hop, tvb, offset, num_ops*chdr_w_bytes, endianness); + hop_tree = proto_item_add_subtree(hop_item, ett_rfnoc_mgmt_hop); + for (size_t op_id = 0; op_id < num_ops; op_id++) { + auto op = hop.get_op(op_id); + auto opcode = op.get_op_code(); + mgmt_op_item = proto_tree_add_item(hop_tree, hf_rfnoc_mgmt_op, tvb, offset, chdr_w_bytes, endianness); + mgmt_op_tree = proto_item_add_subtree(mgmt_op_item, ett_rfnoc_mgmt_hop_op); + + /* Add op code */ + proto_tree_add_string( + mgmt_op_tree, hf_rfnoc_mgmt_op_code, tvb, offset+6, 1, + val_to_str(opcode, RFNOC_MGMT_OPCODES, "invalid") + ); + + /* Add op payload */ + if (opcode == uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_SEL_DEST) { + auto opdata = uhd::rfnoc::chdr::mgmt_op_t::sel_dest_payload( + op.get_op_payload()); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_dest, tvb, offset+4, 2, opdata.dest); + } else if (opcode == uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_INFO_RESP) { + auto opdata = uhd::rfnoc::chdr::mgmt_op_t::node_info_payload( + op.get_op_payload()); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_device_id, tvb, offset, 6, opdata.device_id); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_node_type, tvb, offset, 6, opdata.node_type); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_node_inst, tvb, offset, 6, opdata.node_inst); + } else if (opcode == uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_CFG_WR_REQ) { + auto opdata = uhd::rfnoc::chdr::mgmt_op_t::cfg_payload( + op.get_op_payload()); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_cfg_address, tvb, offset, 6, opdata.addr); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_cfg_data, tvb, offset, 6, opdata.data); + } else if (opcode == uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_CFG_RD_REQ) { + auto opdata = uhd::rfnoc::chdr::mgmt_op_t::cfg_payload( + op.get_op_payload()); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_cfg_address, tvb, offset, 6, opdata.addr); + } else if (opcode == uhd::rfnoc::chdr::mgmt_op_t::op_code_t::MGMT_OP_CFG_RD_RESP) { + auto opdata = uhd::rfnoc::chdr::mgmt_op_t::cfg_payload( + op.get_op_payload()); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_cfg_address, tvb, offset, 6, opdata.addr); + proto_tree_add_uint(mgmt_op_tree, hf_rfnoc_mgmt_op_cfg_data, tvb, offset, 6, opdata.data); + } + offset += chdr_w_bytes; + } + } + } + if (pkttype == uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_DATA_NO_TS) { + } + if (pkttype == uhd::rfnoc::chdr::packet_type_t::PKT_TYPE_DATA_WITH_TS) { + auto pkt = pkt_factory.make_generic(); + pkt->refresh(tvb_get_ptr(tvb, 0, chdr_len)); + proto_tree_add_uint64(rfnoc_tree, hf_rfnoc_timestamp, tvb, offset+8, 8, *(pkt->get_timestamp())); + } + } + } + return len; +} + +extern "C" +void proto_register_rfnoc(void) +{ + static hf_register_info hf[] = { + { &hf_rfnoc_hdr, + { "Header", "rfnoc.hdr", + FT_NONE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_hdr_pkttype, + { "Packet Type", "rfnoc.hdr.pkttype", + FT_STRINGZ, BASE_NONE, + NULL, 0x00, + "Packet Type", HFILL } + }, + { &hf_rfnoc_hdr_vc, + { "Virtual Channel", "rfnoc.hdr.vc", + FT_UINT8, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_hdr_eob, + { "End Of Burst", "rfnoc.hdr.eob", + FT_BOOLEAN, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_hdr_eov, + { "End Of Vector", "rfnoc.hdr.eov", + FT_BOOLEAN, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_hdr_num_mdata, + { "Num Mdata", "rfnoc.hdr.nummdata", + FT_UINT8, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_hdr_seqnum, + { "Sequence Number", "rfnoc.hdr.seqnum", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_hdr_len, + { "RFNoC Length", "rfnoc.hdr.len", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_hdr_dst_epid, + { "Dst EPID", "rfnoc.hdr.dst_epid", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_timestamp, + { "Timestamp", "rfnoc.timestamp", + FT_UINT64, BASE_HEX, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl, + { "CTRL Payload", "rfnoc.ctrl", + FT_NONE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_dst_port, + { "Dst Port", "rfnoc.ctrl.dst_port", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_src_port, + { "Src Port", "rfnoc.ctrl.src_port", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_num_data, + { "Num Data", "rfnoc.ctrl.num_data", + FT_UINT8, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_data0, + { "Data0", "rfnoc.ctrl.data0", + FT_UINT32, BASE_HEX, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_seqnum, + { "Seq Num", "rfnoc.ctrl.seqnum", + FT_UINT8, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_is_ack, + { "Is ACK", "rfnoc.ctrl.is_ack", + FT_BOOLEAN, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_rfnoc_src_epid, + { "Src EPID", "rfnoc.src_epid", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_address, + { "Address", "rfnoc.ctrl.address", + FT_UINT16, BASE_HEX, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_opcode, + { "Op Code", "rfnoc.ctrl.opcode", + FT_STRINGZ, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_ctrl_status, + { "Status", "rfnoc.ctrl.status", + FT_STRINGZ, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strs, + { "Stream Status", "rfnoc.strs", + FT_NONE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strs_status, + { "Status", "rfnoc.strs.status", + FT_STRINGZ, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strs_capacity_bytes, + { "Capacity Bytes", "rfnoc.strs.capacity_bytes", + FT_UINT64, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strs_capacity_pkts, + { "Capacity Packets", "rfnoc.strs.capacity_pkts", + FT_UINT32, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strs_xfer_bytes, + { "Xfer Count Bytes", "rfnoc.strs.xfer_bytes", + FT_UINT64, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strs_xfer_pkts, + { "Xfer Count Packets", "rfnoc.strs.xfer_pkts", + FT_UINT64, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strc, + { "Stream Command", "rfnoc.strc", + FT_NONE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strc_opcode, + { "Opcode", "rfnoc.strc.opcode", + FT_STRINGZ, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strc_num_bytes, + { "Num Bytes", "rfnoc.strc.num_bytes", + FT_UINT64, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_strc_num_pkts, + { "Num Packets", "rfnoc.strc.num_pkts", + FT_UINT64, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt, + { "Mgmt Xact", "rfnoc.mgmt", + FT_NONE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_protover, + { "Protocol Version", "rfnoc.mgmt.protover", + FT_UINT16, BASE_HEX, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_chdr_w, + { "CHDR Width", "rfnoc.mgmt.chdr_w", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_num_hops, + { "Num Hops", "rfnoc.mgmt.num_hops", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_hop, + { "Hop", "rfnoc.mgmt.hop", + FT_NONE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op, + { "Operation", "rfnoc.mgmt.op", + FT_NONE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op_code, + { "Opcode", "rfnoc.mgmt.op.op_code", + FT_STRINGZ, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op_dest, + { "Destination", "rfnoc.mgmt.op.dest", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op_device_id, + { "Device ID", "rfnoc.mgmt.op.device_id", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op_node_type, + { "Node Type", "rfnoc.mgmt.op.node_type", + FT_UINT8, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op_node_inst, + { "Node Instance", "rfnoc.mgmt.op.node_inst", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op_cfg_address, + { "Address", "rfnoc.mgmt.op.cfg_address", + FT_UINT16, BASE_HEX, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_rfnoc_mgmt_op_cfg_data, + { "Data", "rfnoc.mgmt.op.cfg_data", + FT_UINT32, BASE_HEX, + NULL, 0x00, + NULL, HFILL } + }, + + }; + + static gint *ett[] = { + &ett_rfnoc, + &ett_rfnoc_hdr, + &ett_rfnoc_ctrl, + &ett_rfnoc_strs, + &ett_rfnoc_strc, + &ett_rfnoc_mgmt, + &ett_rfnoc_mgmt_hop, + &ett_rfnoc_mgmt_hop_op, + }; + + module_t *rfnoc_module; + + proto_rfnoc = proto_register_protocol("UHD RFNoC", "RFNoC", "rfnoc"); + proto_register_field_array(proto_rfnoc, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + rfnoc_module = prefs_register_protocol(proto_rfnoc, NULL); +} + +/* Handler registration */ +extern "C" +void proto_reg_handoff_rfnoc(void) +{ + static gboolean initialized = FALSE; + static dissector_handle_t rfnoc_handle; + static uint16_t current_port = RFNOC_PORT; + + rfnoc_handle = create_dissector_handle(dissect_rfnoc, proto_rfnoc); + dissector_add_uint_with_preference("udp.port", current_port, rfnoc_handle); +} diff --git a/tools/dissectors/epan/rfnoc/plugin.rc.in b/tools/dissectors/epan/rfnoc/plugin.rc.in new file mode 100644 index 000000000..eca74e1a7 --- /dev/null +++ b/tools/dissectors/epan/rfnoc/plugin.rc.in @@ -0,0 +1,35 @@ +#include "winver.h" +#pragma code_page(65001) + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @RC_MODULE_VERSION@ + PRODUCTVERSION @RC_VERSION@ + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0 +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Ettus Research (National Instruments)\0" + VALUE "FileDescription", "@MODULE_NAME@ dissector\0" + VALUE "FileVersion", "@MODULE_VERSION@\0" + VALUE "InternalName", "@MODULE_NAME@ @MODULE_VERSION@\0" + VALUE "LegalCopyright", "Copyright © 2019 Ettus Research (National Instruments)\0" + VALUE "OriginalFilename", "@MODULE_NAME@.dll\0" + VALUE "ProductName", "Wireshark\0" + VALUE "ProductVersion", "@PROJECT_VERSION@\0" + VALUE "Comments", "Build with @MSVC_VARIANT@\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/tools/dissectors/epan/zpu/CMakeLists.txt b/tools/dissectors/epan/zpu/CMakeLists.txt new file mode 100644 index 000000000..043ee8a7a --- /dev/null +++ b/tools/dissectors/epan/zpu/CMakeLists.txt @@ -0,0 +1,25 @@ +set_module_info(zpu 4 0 0 0) + +set(DISSECTOR_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/packet-zpu.c +) + +set(PLUGIN_FILES + ${CMAKE_CURRENT_BINARY_DIR}/plugin.c + ${DISSECTOR_SRC} +) + +register_plugin_files(${CMAKE_CURRENT_BINARY_DIR}/plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_plugin_library(zpu epan) + +set_target_properties(zpu PROPERTIES PREFIX "") +set_target_properties(zpu PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") +target_link_libraries(zpu wireshark epan) + +install_plugin(zpu epan) + + diff --git a/tools/dissectors/packet-zpu.c b/tools/dissectors/epan/zpu/packet-zpu.c index 39507165e..3eff36997 100644 --- a/tools/dissectors/packet-zpu.c +++ b/tools/dissectors/epan/zpu/packet-zpu.c @@ -2,20 +2,9 @@ * Dissector for ZPU packets (communication with X300 firmware) * * Copyright 2013-2014 Ettus Research LLC + * Copyright 2019 Ettus Research, a National Instruments brand * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-License-Identifier: GPL-3.0-or-later */ /* Format of ZPU packets is defined in x300_fw_commons.h, @@ -29,15 +18,26 @@ * uint32_t data; */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #include <glib.h> #include <epan/packet.h> + +#ifdef __cplusplus +} +#endif + #include <ctype.h> #include <stdio.h> #include <endian.h> -#include "../../host/lib/usrp/x300/x300_fw_common.h" +#include "../../../../host/lib/usrp/x300/x300_fw_common.h" #include "zpu_addr_names.h" #define LOG_HEADER "[ZPU] " @@ -68,10 +68,10 @@ static gint ett_zpu_flags = -1; /* Forward-declare the dissector functions */ void proto_register_zpu(void); void proto_reg_handoff_zpu(void); -static void dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +static int dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data); /* The dissector itself */ -static void dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static int dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *item; proto_tree *zpu_tree; @@ -127,6 +127,8 @@ static void dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) guint8 *bytes = tvb_get_string(tvb, 8, 4); #elif VERSION_MAJOR == 2 guint8 *bytes = tvb_get_string(wmem_packet_scope(), tvb, 8, 4); +#elif VERSION_MAJOR == 3 + guint8 *bytes = tvb_get_string_enc(wmem_packet_scope(), tvb, 8, 4, ENC_ASCII); #else #error Wireshark version not found or not compatible #endif @@ -159,6 +161,7 @@ static void dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } } } + return len; } void proto_register_zpu(void) @@ -172,26 +175,26 @@ void proto_register_zpu(void) }, { &hf_zpu_flags_ack, { "ACK", "zpu.flags.ack", - FT_BOOLEAN, BASE_NONE, - NULL, 0x1, + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x1, NULL, HFILL } }, { &hf_zpu_flags_error, { "Error", "zpu.flags.error", - FT_BOOLEAN, BASE_NONE, - NULL, 0x2, + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x2, NULL, HFILL } }, { &hf_zpu_flags_poke, { "Poke", "zpu.flags.poke", - FT_BOOLEAN, BASE_NONE, - NULL, 0x4, + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x4, NULL, HFILL } }, { &hf_zpu_flags_peek, { "Peek", "zpu.flags.peek", - FT_BOOLEAN, BASE_NONE, - NULL, 0x8, + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x8, NULL, HFILL } }, { &hf_zpu_seq, diff --git a/tools/dissectors/epan/zpu/plugin.rc.in b/tools/dissectors/epan/zpu/plugin.rc.in new file mode 100644 index 000000000..eca74e1a7 --- /dev/null +++ b/tools/dissectors/epan/zpu/plugin.rc.in @@ -0,0 +1,35 @@ +#include "winver.h" +#pragma code_page(65001) + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @RC_MODULE_VERSION@ + PRODUCTVERSION @RC_VERSION@ + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0 +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Ettus Research (National Instruments)\0" + VALUE "FileDescription", "@MODULE_NAME@ dissector\0" + VALUE "FileVersion", "@MODULE_VERSION@\0" + VALUE "InternalName", "@MODULE_NAME@ @MODULE_VERSION@\0" + VALUE "LegalCopyright", "Copyright © 2019 Ettus Research (National Instruments)\0" + VALUE "OriginalFilename", "@MODULE_NAME@.dll\0" + VALUE "ProductName", "Wireshark\0" + VALUE "ProductVersion", "@PROJECT_VERSION@\0" + VALUE "Comments", "Build with @MSVC_VARIANT@\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/tools/dissectors/zpu_addr_names.h b/tools/dissectors/epan/zpu/zpu_addr_names.h index ebbf423ed..64a1307bc 100644 --- a/tools/dissectors/zpu_addr_names.h +++ b/tools/dissectors/epan/zpu/zpu_addr_names.h @@ -33,6 +33,7 @@ static const value_string X300_SHMEM_NAMES[] = { { 9, "X300_FW_SHMEM_UART_TX_ADDR" }, { 10, "X300_FW_SHMEM_UART_WORDS32" }, { 11, "X300_FW_SHMEM_ROUTE_MAP_ADDR" }, - { 12, "X300_FW_SHMEM_ROUTE_MAP_LEN" } + { 12, "X300_FW_SHMEM_ROUTE_MAP_LEN" }, + { 0, NULL } }; diff --git a/tools/dissectors/make-dissector-reg.py b/tools/dissectors/make-dissector-reg.py deleted file mode 100755 index 37170a84f..000000000 --- a/tools/dissectors/make-dissector-reg.py +++ /dev/null @@ -1,305 +0,0 @@ -#!/usr/bin/env python -# -# Looks for registration routines in the protocol dissectors, -# and assembles C code to call all the routines. -# -# This is a Python version of the make-reg-dotc shell script. -# Running the shell script on Win32 is very very slow because of -# all the process-launching that goes on --- multiple greps and -# seds for each input file. I wrote this python version so that -# less processes would have to be started. -# -# $Id: make-dissector-reg.py 30447 2009-10-09 20:47:18Z krj $ - -import os -import sys -import re -import pickle -from stat import * - -VERSION_KEY = '_VERSION' -CUR_VERSION = '$Id: make-dissector-reg.py 30447 2009-10-09 20:47:18Z krj $' - -# -# The first argument is the directory in which the source files live. -# -srcdir = sys.argv[1] - -# -# The second argument is either "plugin" or "dissectors"; if it's -# "plugin", we build a plugin.c for a plugin, and if it's -# "dissectors", we build a register.c for libwireshark. -# -registertype = sys.argv[2] -if registertype == "plugin" or registertype == "plugin_wtap": - tmp_filename = "plugin.c-tmp" - final_filename = "plugin.c" - cache_filename = None - preamble = """\ -/* - * Do not modify this file. - * - * It is created automatically by Makefile or Makefile.nmake. - */ -""" -elif registertype == "dissectors": - tmp_filename = "register.c-tmp" - final_filename = "register.c" - cache_filename = "register-cache.pkl" - preamble = """\ -/* - * Do not modify this file. - * - * It is created automatically by the "register.c" target in - * epan/dissectors/Makefile or Makefile.nmake using information in - * epan/dissectors/register-cache.pkl. - * - * You can force this file to be regenerated completely by deleting - * it along with epan/dissectors/register-cache.pkl. - */ -""" -else: - print("Unknown output type '%s'" % registertype) - sys.exit(1) - - -# -# All subsequent arguments are the files to scan. -# -files = sys.argv[3:] - -# Create the proper list of filenames -filenames = [] -for file in files: - if os.path.isfile(file): - filenames.append(file) - else: - filenames.append(os.path.join(srcdir, file)) - -if len(filenames) < 1: - print("No files found") - sys.exit(1) - - -# Look through all files, applying the regex to each line. -# If the pattern matches, save the "symbol" section to the -# appropriate array. -regs = { - 'proto_reg': [], - 'handoff_reg': [], - 'wtap_register': [], - } - -# For those that don't know Python, r"" indicates a raw string, -# devoid of Python escapes. -proto_regex0 = r"^(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$" -proto_regex1 = r"void\s+(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$" - -handoff_regex0 = r"^(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$" -handoff_regex1 = r"void\s+(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$" - -wtap_reg_regex0 = r"^(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$" -wtap_reg_regex1 = r"void\s+(?P<symbol>wtap_register_[_A-Za-z0-9]+)\s*\([^;]+$" - -# This table drives the pattern-matching and symbol-harvesting -patterns = [ - ( 'proto_reg', re.compile(proto_regex0) ), - ( 'proto_reg', re.compile(proto_regex1) ), - ( 'handoff_reg', re.compile(handoff_regex0) ), - ( 'handoff_reg', re.compile(handoff_regex1) ), - ( 'wtap_register', re.compile(wtap_reg_regex0) ), - ( 'wtap_register', re.compile(wtap_reg_regex1) ), - ] - -# Open our registration symbol cache -cache = None -if cache_filename: - try: - cache_file = open(cache_filename, 'rb') - cache = pickle.load(cache_file) - cache_file.close() - if (VERSION_KEY not in cache) or cache[VERSION_KEY] != CUR_VERSION: - cache = {VERSION_KEY: CUR_VERSION} - except: - cache = {VERSION_KEY: CUR_VERSION} - -# Grep -for filename in filenames: - file = open(filename) - cur_mtime = os.fstat(file.fileno())[ST_MTIME] - if cache and (filename in cache): - cdict = cache[filename] - if cur_mtime == cdict['mtime']: -# print("Pulling %s from cache" % (filename)) - regs['proto_reg'].extend(cdict['proto_reg']) - regs['handoff_reg'].extend(cdict['handoff_reg']) - regs['wtap_register'].extend(cdict['wtap_register']) - file.close() - continue - # We don't have a cache entry - if cache is not None: - cache[filename] = { - 'mtime': cur_mtime, - 'proto_reg': [], - 'handoff_reg': [], - 'wtap_register': [], - } -# print("Searching %s" % (filename)) - for line in file.readlines(): - for action in patterns: - regex = action[1] - match = regex.search(line) - if match: - symbol = match.group("symbol") - sym_type = action[0] - regs[sym_type].append(symbol) - if cache is not None: -# print("Caching %s for %s: %s" % (sym_type, filename, symbol)) - cache[filename][sym_type].append(symbol) - file.close() - -if cache is not None and cache_filename is not None: - cache_file = open(cache_filename, 'wb') - pickle.dump(cache, cache_file) - cache_file.close() - -# Make sure we actually processed something -if len(regs['proto_reg']) < 1: - print("No protocol registrations found") - sys.exit(1) - -# Sort the lists to make them pretty -regs['proto_reg'].sort() -regs['handoff_reg'].sort() -regs['wtap_register'].sort() - -reg_code = open(tmp_filename, "w") - -reg_code.write(preamble) - -# Make the routine to register all protocols -if registertype == "plugin" or registertype == "plugin_wtap": - reg_code.write(""" -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <gmodule.h> - -#include "moduleinfo.h" - -#ifndef ENABLE_STATIC -G_MODULE_EXPORT const gchar version[] = VERSION; - -/* Start the functions we need for the plugin stuff */ - -G_MODULE_EXPORT void -plugin_register (void) -{ -"""); -else: - reg_code.write(""" -#include "register.h" -void -register_all_protocols(register_cb cb, gpointer client_data) -{ -"""); - -for symbol in regs['proto_reg']: - if registertype == "plugin" or registertype == "plugin_wtap": - line = " {extern void %s (void); %s ();}\n" % (symbol, symbol) - else: - line = " {extern void %s (void); if(cb) (*cb)(RA_REGISTER, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol) - reg_code.write(line) - -reg_code.write("}\n") - - -# Make the routine to register all protocol handoffs -if registertype == "plugin" or registertype == "plugin_wtap": - reg_code.write(""" -G_MODULE_EXPORT void -plugin_reg_handoff(void) -{ -"""); -else: - reg_code.write(""" -void -register_all_protocol_handoffs(register_cb cb, gpointer client_data) -{ -"""); - -for symbol in regs['handoff_reg']: - if registertype == "plugin" or registertype == "plugin_wtap": - line = " {extern void %s (void); %s ();}\n" % (symbol, symbol) - else: - line = " {extern void %s (void); if(cb) (*cb)(RA_HANDOFF, \"%s\", client_data); %s ();}\n" % (symbol, symbol, symbol) - reg_code.write(line) - -reg_code.write("}\n") - -if registertype == "plugin": - reg_code.write("#endif\n"); -elif registertype == "plugin_wtap": - reg_code.write(""" -G_MODULE_EXPORT void -register_wtap_module(void) -{ -"""); - - for symbol in regs['wtap_register']: - line = " {extern void %s (void); %s ();}\n" % (symbol, symbol) - reg_code.write(line) - - reg_code.write("}\n"); - reg_code.write("#endif\n"); -else: - reg_code.write(""" -static gulong proto_reg_count(void) -{ -"""); - - line = " return %d;\n" % len(regs['proto_reg']) - reg_code.write(line) - - reg_code.write(""" -} -"""); - reg_code.write(""" -static gulong handoff_reg_count(void) -{ -"""); - - line = " return %d;\n" % len(regs['handoff_reg']) - reg_code.write(line) - - reg_code.write(""" -} -"""); - reg_code.write(""" -gulong register_count(void) -{ -"""); - - line = " return proto_reg_count() + handoff_reg_count();" - reg_code.write(line) - - reg_code.write(""" -}\n -"""); - - -# Close the file -reg_code.close() - -# Remove the old final_file if it exists. -try: - os.stat(final_filename) - os.remove(final_filename) -except OSError: - pass - -# Move from tmp file to final file -os.rename(tmp_filename, final_filename) - - diff --git a/tools/dissectors/make-plugin-reg.py b/tools/dissectors/make-plugin-reg.py new file mode 100755 index 000000000..6c394da97 --- /dev/null +++ b/tools/dissectors/make-plugin-reg.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Looks for registration routines in the plugins +# and assembles C code to call all the routines. +# + +import os +import sys +import re + +# +# The first argument is the directory in which the source files live. +# +srcdir = sys.argv[1] +# +# The second argument is either "plugin", "plugin_wtap" or "plugin_codec". +# +registertype = sys.argv[2] +# +# All subsequent arguments are the files to scan. +# +files = sys.argv[3:] + +final_filename = "plugin.c" +preamble = """\ +/* + * Do not modify this file. Changes will be overwritten. + * + * Generated automatically from %s. + */ +""" % (sys.argv[0]) + +# Create the proper list of filenames +filenames = [] +for file in files: + if os.path.isfile(file): + filenames.append(file) + else: + filenames.append(os.path.join(srcdir, file)) + +if len(filenames) < 1: + print("No files found") + sys.exit(1) + + +# Look through all files, applying the regex to each line. +# If the pattern matches, save the "symbol" section to the +# appropriate set. +regs = { + 'proto_reg': set(), + 'handoff_reg': set(), + 'wtap_register': set(), + 'codec_register': set(), + } + +# For those that don't know Python, r"" indicates a raw string, +# devoid of Python escapes. +proto_regex = r"\bproto_register_(?P<symbol>[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$" + +handoff_regex = r"\bproto_reg_handoff_(?P<symbol>[_A-Za-z0-9]+)\s*\(\s*void\s*\)[^;]*$" + +wtap_reg_regex = r"\bwtap_register_(?P<symbol>[_A-Za-z0-9]+)\s*\([^;]+$" + +codec_reg_regex = r"\bcodec_register_(?P<symbol>[_A-Za-z0-9]+)\s*\([^;]+$" + +# This table drives the pattern-matching and symbol-harvesting +patterns = [ + ( 'proto_reg', re.compile(proto_regex, re.MULTILINE) ), + ( 'handoff_reg', re.compile(handoff_regex, re.MULTILINE) ), + ( 'wtap_register', re.compile(wtap_reg_regex, re.MULTILINE) ), + ( 'codec_register', re.compile(codec_reg_regex, re.MULTILINE) ), + ] + +# Grep +for filename in filenames: + file = open(filename) + # Read the whole file into memory + contents = file.read() + for action in patterns: + regex = action[1] + for match in regex.finditer(contents): + symbol = match.group("symbol") + sym_type = action[0] + regs[sym_type].add(symbol) + # We're done with the file contents + del contents + file.close() + +# Make sure we actually processed something +if (len(regs['proto_reg']) < 1 and len(regs['wtap_register']) < 1 and len(regs['codec_register']) < 1): + print("No plugin registrations found") + sys.exit(1) + +# Convert the sets into sorted lists to make the output pretty +regs['proto_reg'] = sorted(regs['proto_reg']) +regs['handoff_reg'] = sorted(regs['handoff_reg']) +regs['wtap_register'] = sorted(regs['wtap_register']) +regs['codec_register'] = sorted(regs['codec_register']) + +reg_code = "" + +reg_code += preamble + +reg_code += """ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gmodule.h> + +/* plugins are DLLs */ +#define WS_BUILD_DLL +#include "ws_symbol_export.h" + +""" + +if registertype == "plugin": + reg_code += "#include \"epan/proto.h\"\n\n" +if registertype == "plugin_wtap": + reg_code += "#include \"wiretap/wtap.h\"\n\n" +if registertype == "plugin_codec": + reg_code += "#include \"codecs/codecs.h\"\n\n" + +for symbol in regs['proto_reg']: + reg_code += "void proto_register_%s(void);\n" % (symbol) +for symbol in regs['handoff_reg']: + reg_code += "void proto_reg_handoff_%s(void);\n" % (symbol) +for symbol in regs['wtap_register']: + reg_code += "void wtap_register_%s(void);\n" % (symbol) +for symbol in regs['codec_register']: + reg_code += "void codec_register_%s(void);\n" % (symbol) + +reg_code += """ +WS_DLL_PUBLIC_DEF const gchar plugin_version[] = PLUGIN_VERSION; +WS_DLL_PUBLIC_DEF const int plugin_want_major = VERSION_MAJOR; +WS_DLL_PUBLIC_DEF const int plugin_want_minor = VERSION_MINOR; + +WS_DLL_PUBLIC void plugin_register(void); + +void plugin_register(void) +{ +""" + +if registertype == "plugin": + for symbol in regs['proto_reg']: + reg_code +=" static proto_plugin plug_%s;\n\n" % (symbol) + reg_code +=" plug_%s.register_protoinfo = proto_register_%s;\n" % (symbol, symbol) + if symbol in regs['handoff_reg']: + reg_code +=" plug_%s.register_handoff = proto_reg_handoff_%s;\n" % (symbol, symbol) + else: + reg_code +=" plug_%s.register_handoff = NULL;\n" % (symbol) + reg_code += " proto_register_plugin(&plug_%s);\n" % (symbol) +if registertype == "plugin_wtap": + for symbol in regs['wtap_register']: + reg_code += " static wtap_plugin plug_%s;\n\n" % (symbol) + reg_code += " plug_%s.register_wtap_module = wtap_register_%s;\n" % (symbol, symbol) + reg_code += " wtap_register_plugin(&plug_%s);\n" % (symbol) +if registertype == "plugin_codec": + for symbol in regs['codec_register']: + reg_code += " static codecs_plugin plug_%s;\n\n" % (symbol) + reg_code += " plug_%s.register_codec_module = codec_register_%s;\n" % (symbol, symbol) + reg_code += " codecs_register_plugin(&plug_%s);\n" % (symbol) + +reg_code += "}\n" + +try: + print(('Updating ' + final_filename)) + fh = open(final_filename, 'w') + fh.write(reg_code) + fh.close() +except OSError: + sys.exit('Unable to write ' + final_filename + '.\n') + +# +# Editor modelines - http://www.wireshark.org/tools/modelines.html +# +# Local variables: +# c-basic-offset: 4 +# indent-tabs-mode: nil +# End: +# +# vi: set shiftwidth=4 expandtab: +# :indentSize=4:noTabs=true: +# diff --git a/tools/dissectors/moduleinfo.h.in b/tools/dissectors/moduleinfo.h.in deleted file mode 100644 index 7910c56a3..000000000 --- a/tools/dissectors/moduleinfo.h.in +++ /dev/null @@ -1,10 +0,0 @@ -#ifdef PACKAGE -#undef PACKAGE -#endif -#define PACKAGE "@ETTUS_DISSECTOR_NAME@" - -#ifdef VERSION -#undef VERSION -#endif -#define VERSION "0.0.0.2" - diff --git a/tools/dissectors/packet-chdr.c b/tools/dissectors/packet-chdr.c deleted file mode 100644 index e5dcd6e5e..000000000 --- a/tools/dissectors/packet-chdr.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Dissector for UHD CVITA (CHDR) packets - * - * Copyright 2010-2014 Ettus Research LLC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include "config.h" - -#include <glib.h> -#include <epan/packet.h> -#include <ctype.h> -#include <stdio.h> - -#include "../../host/lib/usrp/x300/x300_fw_common.h" - -#define LOG_HEADER "[UHD CHDR] " - -#ifndef min -#define min(a,b) ((a<b)?a:b) -#endif // min - -const unsigned int CHDR_PORT = X300_VITA_UDP_PORT; - -static int proto_chdr = -1; -static int hf_chdr_hdr = -1; -static int hf_chdr_type = -1; -static int hf_chdr_has_time = -1; -static int hf_chdr_eob = -1; -static int hf_chdr_error = -1; -static int hf_chdr_fc_ack = -1; -static int hf_chdr_fc_pktcount = -1; -static int hf_chdr_fc_bytecount = -1; -static int hf_chdr_sequence = -1; -static int hf_chdr_packet_size = -1; -static int hf_chdr_stream_id = -1; -static int hf_chdr_src_dev = -1; -static int hf_chdr_src_ep = -1; -static int hf_chdr_src_blockport = -1; -static int hf_chdr_dst_dev = -1; -static int hf_chdr_dst_ep = -1; -static int hf_chdr_dst_blockport = -1; -static int hf_chdr_timestamp = -1; -static int hf_chdr_payload = -1; -static int hf_chdr_ext_response = -1; -static int hf_chdr_ext_fc = -1; -static int hf_chdr_ext_status_code = -1; -static int hf_chdr_ext_seq_num = -1; -static int hf_chdr_cmd = -1; -static int hf_chdr_cmd_address = -1; -static int hf_chdr_cmd_value = -1; - -static const value_string CHDR_PACKET_TYPES[] = { - { 0, "Data" }, - { 1, "Data (End-of-Burst)" }, - { 4, "Flow Control" }, - { 5, "Flow Control (ACK)" }, - { 8, "Command" }, - { 12, "Response" }, - { 13, "Error Response" }, -}; - -static const value_string CHDR_PACKET_TYPES_SHORT[] = { - { 0, "data" }, - { 1, "data" }, - { 4, "fc" }, - { 5, "fc" }, - { 8, "cmd" }, - { 12, "resp" }, - { 13, "resp" }, -}; - -/* the heuristic dissector is called on every packet with payload. - * The warning printed for this should only be printed once. - */ -static int heur_warning_printed = 0; - -/* Subtree handles: set by register_subtree_array */ -static gint ett_chdr = -1; -static gint ett_chdr_header = -1; -static gint ett_chdr_id = -1; -static gint ett_chdr_response = -1; -static gint ett_chdr_fc = -1; -static gint ett_chdr_cmd = -1; - -/* Forward-declare the dissector functions */ -void proto_register_chdr(void); -void proto_reg_handoff_chdr(void); -static void dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); - -/* heuristic dissector call. Will always return. */ -static gboolean heur_dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* whatislove) -{ - if(heur_warning_printed < 1){ - printf(LOG_HEADER"heuristic dissector always returns true!\n"); - heur_warning_printed++; - } - dissect_chdr(tvb, pinfo, tree); - return (TRUE); -} - -static void byte_swap(guint8 *bytes, gint len) -{ - guint8 tmp[4]; - - if(len != sizeof(tmp)){ - printf(LOG_HEADER"FATAL! number of bytes don't match 32 bit!\n"); - return; - } - - memcpy(tmp, bytes, sizeof(tmp)); - bytes[0] = tmp[3]; - bytes[1] = tmp[2]; - bytes[2] = tmp[1]; - bytes[3] = tmp[0]; -} - -static unsigned long long get_timestamp(guint8 *bytes, gint len) -{ - unsigned long long ts; - unsigned long long trans; - int it; - - if(len != sizeof(unsigned long long)){ - printf(LOG_HEADER"FATAL! timestamps always consist of 64 bits!\n"); - } - - byte_swap(bytes + 0, 4); - byte_swap(bytes + 4, 4); - - ts = 0; - for(it = 0; it < 8; it++){ - ts = ts << 8; - trans = (guint64) bytes[it]; - ts = ts | trans; - } - - return (ts); -} - -/* The dissector itself */ -static void dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) -{ - // Here are all the variables - proto_item *item; - proto_item *stream_item; - proto_tree *chdr_tree; - proto_item *header_item; - proto_tree *header_tree; - proto_tree *stream_tree; - proto_item *response_item; - proto_tree *response_tree; - proto_item *cmd_item; - proto_tree *cmd_tree; - proto_item *fc_item; - proto_tree *fc_tree; - gint len; - - gint flag_offset; - guint8 *bytes; - guint8 hdr_bits = 0; - gboolean flag_has_time = 0; - gboolean flag_is_data = 0; - gboolean flag_is_fc = 0; - gboolean flag_is_cmd = 0; - gboolean flag_is_resp = 0; - gboolean flag_is_eob = 0; - gboolean flag_is_error = 0; - gboolean flag_is_fcack = 0; - uint64_t timestamp; - gboolean is_network; - gint endianness; - gint id_pos_usb[4] = {3, 2, 1, 0}; - gint id_pos_net[4] = {0, 1, 2, 3}; - gint id_pos[4] = {0, 1, 2, 3}; - - if(pinfo->match_uint == CHDR_PORT){ - is_network = TRUE; - flag_offset = 0; - endianness = ENC_BIG_ENDIAN; - memcpy(id_pos, id_pos_net, 4 * sizeof(gint)); - } - else{ // Parsing a USB capture - is_network = FALSE; - flag_offset = 3; - endianness = ENC_LITTLE_ENDIAN; - memcpy(id_pos, id_pos_usb, 4 * sizeof(gint)); - } - - len = tvb_reported_length(tvb); - - col_append_str(pinfo->cinfo, COL_PROTOCOL, "/CHDR"); - /* This throws a warning: */ - /*col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR", tvb_format_text_wsp(tvb, 0, len));*/ - col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR"); - - if (tree){ - int header_size = -1; // Total size of the CHDR header. Either 8 or 16. - - guint16 hdr_info; - if (len >= 4){ - guint8 pkt_type = 0; - hdr_info = tvb_get_ntohs(tvb, flag_offset); - header_size = 8; // We now know the header is at least 8 bytes long. - hdr_bits = (hdr_info & 0xF000) >> 12; - pkt_type = hdr_bits >> 2; - flag_is_data = (pkt_type == 0); - flag_is_fc = (pkt_type == 1); - flag_is_cmd = (pkt_type == 2); - flag_is_resp = (pkt_type == 3); - flag_is_eob = flag_is_data && (hdr_bits & 0x1); - flag_is_error = flag_is_resp && (hdr_bits & 0x1); - flag_is_fcack = flag_is_fc && (hdr_bits & 0x1); - flag_has_time = hdr_bits & 0x2; - if (flag_has_time) { - header_size += 8; // 64-bit timestamp. - } - /* header_size is now final. */ - } - - /* Start with a top-level item to add everything else to */ - item = proto_tree_add_item(tree, proto_chdr, tvb, 0, min(len, header_size), ENC_NA); - - if (len >= 4) { - chdr_tree = proto_item_add_subtree(item, ett_chdr); - - /* Header info. First, a top-level header tree item: */ - header_item = proto_tree_add_item(chdr_tree, hf_chdr_hdr, tvb, flag_offset, 1, endianness); - header_tree = proto_item_add_subtree(header_item, ett_chdr_header); - proto_item_append_text(header_item, ", Packet type: %s %04x", - val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES, "Unknown (0x%x)"), hdr_bits - ); - /* Let us query hdr.type */ - proto_tree_add_string( - header_tree, hf_chdr_type, tvb, flag_offset, 1, - val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES_SHORT, "invalid") - ); - /* And other flags */ - proto_tree_add_boolean(header_tree, hf_chdr_has_time, tvb, flag_offset, 1, flag_has_time); - if (flag_is_data) { - proto_tree_add_boolean(header_tree, hf_chdr_eob, tvb, flag_offset, 1, flag_is_eob); - } - if (flag_is_resp) { - proto_tree_add_boolean(header_tree, hf_chdr_error, tvb, flag_offset, 1, flag_is_error); - /*proto_tree_add_boolean(header_tree, hf_chdr_error, tvb, flag_offset, 1, true);*/ - } - if (flag_is_fc) { - proto_tree_add_boolean(header_tree, hf_chdr_fc_ack, tvb, flag_offset, 1, flag_is_fcack); - } - - /* These lines add sequence, packet_size and stream ID */ - proto_tree_add_item(chdr_tree, hf_chdr_sequence, tvb, (is_network ? 0:2), 2, endianness); - proto_tree_add_item(chdr_tree, hf_chdr_packet_size, tvb, (is_network ? 2:0), 2, endianness); - - if (len >= 8){ - /* stream id can be broken down to 4 sections. these are collapsed in a subtree */ - stream_item = proto_tree_add_item(chdr_tree, hf_chdr_stream_id, tvb, 4, 4, endianness); - stream_tree = proto_item_add_subtree(stream_item, ett_chdr_id); - proto_tree_add_item(stream_tree, hf_chdr_src_dev, tvb, 4+id_pos[0], 1, ENC_NA); - proto_tree_add_item(stream_tree, hf_chdr_src_ep, tvb, 4+id_pos[1], 1, ENC_NA); - proto_tree_add_item(stream_tree, hf_chdr_dst_dev, tvb, 4+id_pos[2], 1, ENC_NA); - proto_tree_add_item(stream_tree, hf_chdr_dst_ep, tvb, 4+id_pos[3], 1, ENC_NA); - - /* Block ports (only add them if address points to a device) */ - guint32 sid = tvb_get_ntohl(tvb, 4); - guint8* sid_bytes = (guint8*) &sid; - if (sid_bytes[3] != 0) { - proto_tree_add_item(stream_tree, hf_chdr_src_blockport, tvb, 4+2, 1, ENC_NA); - } - if (sid_bytes[1] != 0) { - proto_tree_add_item(stream_tree, hf_chdr_dst_blockport, tvb, 4+0, 1, ENC_NA); - } - - /* Append SID in sid_t hex format */ - proto_item_append_text(stream_item, " (%02X:%02X>%02X:%02X)", - sid_bytes[3], - sid_bytes[2], - sid_bytes[1], - sid_bytes[0] - ); - /*proto_item_append_text(stream_item, "%08X", sid);*/ - - - /* if has_time flag is present interpret timestamp */ - if ((flag_has_time) && (len >= 16)){ - if (is_network) - item = proto_tree_add_item(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, endianness); - else{ - bytes = (guint8*) tvb_get_string_enc(wmem_packet_scope(), tvb, 8, sizeof(unsigned long long), ENC_ASCII); - timestamp = get_timestamp(bytes, sizeof(unsigned long long)); - proto_tree_add_uint64(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, timestamp); - } - } - - int remaining_bytes = (len - header_size); - int show_raw_payload = (remaining_bytes > 0); - - if (flag_is_cmd && remaining_bytes == 8) { - cmd_item = proto_tree_add_item(chdr_tree, hf_chdr_cmd, tvb, header_size, 8, endianness); - cmd_tree = proto_item_add_subtree(cmd_item, ett_chdr_cmd); - proto_tree_add_item(cmd_tree, hf_chdr_cmd_address, tvb, header_size, 4, endianness); - proto_tree_add_item(cmd_tree, hf_chdr_cmd_value, tvb, header_size + 4, 4, endianness); - } else if (flag_is_resp) { - response_item = proto_tree_add_item(chdr_tree, hf_chdr_ext_response, tvb, header_size, 8, endianness); - response_tree = proto_item_add_subtree(response_item, ett_chdr_response); - - proto_tree_add_item(response_tree, hf_chdr_ext_status_code, tvb, header_size, 4, endianness); - /* This will show the 12-bits of sequence ID in the last 2 bytes */ - proto_tree_add_item(response_tree, hf_chdr_ext_seq_num, tvb, (header_size + 4 + (is_network ? 2 : 0)), 2, endianness); - } else if (flag_is_fc) { - fc_item = proto_tree_add_item(chdr_tree, hf_chdr_ext_fc, tvb, header_size, 8, endianness); - fc_tree = proto_item_add_subtree(fc_item, ett_chdr_fc); - proto_tree_add_item(fc_tree, hf_chdr_fc_pktcount, tvb, header_size, 4, endianness); - proto_tree_add_item(fc_tree, hf_chdr_fc_bytecount, tvb, header_size + 4, 4, endianness); - } else if (show_raw_payload) { - proto_tree_add_item(chdr_tree, hf_chdr_payload, tvb, header_size, -1, ENC_NA); - } - } - } - } -} - -void proto_register_chdr(void) -{ - static hf_register_info hf[] = { - { &hf_chdr_hdr, - { "Header bits", "chdr.hdr", - FT_UINT8, BASE_HEX, - NULL, 0xF0, - NULL, HFILL } - }, - { &hf_chdr_type, - { "Packet Type", "chdr.hdr.type", - FT_STRINGZ, BASE_NONE, - NULL, 0x00, - "Packet Type", HFILL } - }, - { &hf_chdr_has_time, - { "Has time", "chdr.hdr.has_time", - FT_BOOLEAN, BASE_NONE, - NULL, 0x20, - NULL, HFILL } - }, - { &hf_chdr_eob, - { "End Of Burst", "chdr.hdr.eob", - FT_BOOLEAN, BASE_NONE, - NULL, 0x10, - NULL, HFILL } - }, - { &hf_chdr_error, - { "Error Flag", "chdr.hdr.error", - FT_BOOLEAN, BASE_NONE, - NULL, 0x10, - NULL, HFILL } - }, - { &hf_chdr_fc_ack, - { "FC ACK Flag", "chdr.hdr.fc_ack", - FT_BOOLEAN, BASE_NONE, - NULL, 0x10, - NULL, HFILL } - }, - { &hf_chdr_ext_fc, - { "Flow Control", "chdr.fc", - FT_BYTES, BASE_NONE, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_fc_bytecount, - { "FC Byte Count", "chdr.hdr.fc.byte_count", - FT_UINT32, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_fc_pktcount, - { "FC Packet Count", "chdr.hdr.fc.pkt_count", - FT_UINT32, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_sequence, - { "Sequence ID", "chdr.seq", - FT_UINT16, BASE_DEC, - NULL, 0x0FFF, - NULL, HFILL } - }, - { &hf_chdr_packet_size, - { "Packet size", "chdr.size", - FT_UINT16, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_stream_id, - { "Stream ID", "chdr.sid", - FT_IPv4, BASE_NONE, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_src_dev, - { "Source device", "chdr.src_dev", - FT_UINT8, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_src_ep, - { "Source endpoint", "chdr.src_ep", - FT_UINT8, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_src_blockport, - { "Source block port", "chdr.src_bp", - FT_UINT8, BASE_DEC, - NULL, 0xF, - NULL, HFILL } - }, - { &hf_chdr_dst_dev, - { "Destination device", "chdr.dst_dev", - FT_UINT8, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_dst_ep, - { "Destination endpoint", "chdr.dst_ep", - FT_UINT8, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_dst_blockport, - { "Destination block port", "chdr.dst_bp", - FT_UINT8, BASE_DEC, - NULL, 0xF, - NULL, HFILL } - }, - { &hf_chdr_timestamp, - { "Time", "chdr.time", - FT_UINT64, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_payload, - { "Payload", "chdr.payload", - FT_BYTES, BASE_NONE, - NULL, 0x0, - NULL, HFILL - } - }, - { &hf_chdr_ext_response, - { "Response", "chdr.res", - FT_BYTES, BASE_NONE, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_ext_status_code, - { "Status code", "chdr.res.status", - FT_UINT32, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_ext_seq_num, - { "Response to sequence ID", "chdr.res.seq", - FT_UINT16, BASE_DEC, - NULL, 0x0FFF, - NULL, HFILL } - }, - { &hf_chdr_cmd, - { "Command", "chdr.cmd", - FT_BYTES, BASE_NONE, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_cmd_address, - { "Register Address", "chdr.cmd.addr", - FT_UINT32, BASE_DEC, - NULL, 0x0, - NULL, HFILL } - }, - { &hf_chdr_cmd_value, - { "Command Value", "chdr.cmd.val", - FT_UINT32, BASE_HEX, - NULL, 0x0, - NULL, HFILL } - }, - }; - - static gint *ett[] = { - &ett_chdr, - &ett_chdr_header, - &ett_chdr_id, - &ett_chdr_response, - &ett_chdr_fc, - &ett_chdr_cmd - }; - - proto_chdr = proto_register_protocol("UHD CHDR", "CHDR", "chdr"); - proto_register_field_array(proto_chdr, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); - register_dissector("chdr", dissect_chdr, proto_chdr); -} - -/* Handler registration */ -void proto_reg_handoff_chdr(void) -{ - /* register heuristic dissector for use with USB */ -#if VERSION_MAJOR == 1 - heur_dissector_add("usb.bulk", heur_dissect_chdr, proto_chdr); -#elif VERSION_MAJOR == 2 - heur_dissector_add("usb.bulk", heur_dissect_chdr, "USB dissector", "usb_bulk", proto_chdr, HEURISTIC_ENABLE); -#else -#error Wireshark version not found or not compatible -#endif - /* register dissector for UDP packets */ - static dissector_handle_t chdr_handle; - chdr_handle = create_dissector_handle(dissect_chdr, proto_chdr); - dissector_add_uint("udp.port", CHDR_PORT, chdr_handle); -} |