diff options
Diffstat (limited to 'tools/dissectors/epan')
-rw-r--r-- | tools/dissectors/epan/octoclock/CMakeLists.txt | 25 | ||||
-rw-r--r-- | tools/dissectors/epan/octoclock/packet-octoclock.c | 203 | ||||
-rw-r--r-- | tools/dissectors/epan/octoclock/plugin.rc.in | 35 | ||||
-rw-r--r-- | tools/dissectors/epan/rfnoc/CMakeLists.txt | 27 | ||||
-rw-r--r-- | tools/dissectors/epan/rfnoc/packet-rfnoc.cpp | 705 | ||||
-rw-r--r-- | tools/dissectors/epan/rfnoc/plugin.rc.in | 35 | ||||
-rw-r--r-- | tools/dissectors/epan/zpu/CMakeLists.txt | 25 | ||||
-rw-r--r-- | tools/dissectors/epan/zpu/packet-zpu.c | 245 | ||||
-rw-r--r-- | tools/dissectors/epan/zpu/plugin.rc.in | 35 | ||||
-rw-r--r-- | tools/dissectors/epan/zpu/zpu_addr_names.h | 39 |
10 files changed, 1374 insertions, 0 deletions
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/epan/octoclock/packet-octoclock.c b/tools/dissectors/epan/octoclock/packet-octoclock.c new file mode 100644 index 000000000..e8e5e6858 --- /dev/null +++ b/tools/dissectors/epan/octoclock/packet-octoclock.c @@ -0,0 +1,203 @@ +/* + * Dissector for Ettus Octoclock packets + * + * Copyright 2016 Ettus Research + * Copyright 2019 Ettus Research, a National Instruments brand + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "config.h" + +#include <glib.h> +#include <epan/packet.h> +#include <ctype.h> +#include <stdio.h> +#include <stddef.h> + +#include "../../../../host/lib/usrp_clock/octoclock/common.h" + +#define LOG_HEADER "[Octoclock] " +#define size_mem(t,m) sizeof(((t*)0)->m) +#define packet_elem_size(m) (size_mem(octoclock_packet_t,m)) +#define packet_offset(m) (offsetof(octoclock_packet_t, m)) +const unsigned int OCTOCLOCK_PORT = OCTOCLOCK_UDP_CTRL_PORT; + +static int proto_octo = -1; +static int hf_octo_proto_version = -1; +static int hf_octo_proto_sequence = -1; +static int hf_octo_proto_code = -1; +static int hf_octo_proto_poolsize = -1; +static int hf_octo_proto_data = -1; +static int hf_octo_proto_payload = -1; +static int hf_octo_proto_len = -1; +static gint ett_octo = -1; +static const value_string packetcodes[] = { + {1, "OCTOCLOCK_QUERY_CMD"}, + {2, "OCTOCLOCK_QUERY_ACK"}, + {3, "SEND_EEPROM_CMD"}, + {4, "SEND_EEPROM_ACK"}, + {5, "BURN_EEPROM_CMD"}, + {6, "BURN_EEPROM_SUCCESS_ACK"}, + {7, "BURN_EEPROM_FAILURE_ACK"}, + {8, "CLEAR_EEPROM_CMD"}, + {9, "CLEAR_EEPROM_ACK"}, + {10, "SEND_STATE_CMD"}, + {11, "SEND_STATE_ACK"}, + {12, "RESET_CMD"}, + {13, "RESET_ACK"}, + {14, "HOST_SEND_TO_GPSDO_CMD"}, + {15, "HOST_SEND_TO_GPSDO_ACK"}, + {16, "SEND_POOLSIZE_CMD"}, + {17, "SEND_POOLSIZE_ACK"}, + {18, "SEND_CACHE_STATE_CMD"}, + {19, "SEND_CACHE_STATE_ACK"}, + {20, "SEND_GPSDO_CACHE_CMD"}, + {21, "SEND_GPSDO_CACHE_ACK"}, + {22, "PREPARE_FW_BURN_CMD"}, + {23, "FW_BURN_READY_ACK"}, + {24, "FILE_TRANSFER_CMD"}, + {25, "FILE_TRANSFER_ACK"}, + {26, "READ_FW_CMD"}, + {27, "READ_FW_ACK"}, + {28, "FINALIZE_BURNING_CMD"}, + {29, "FINALIZE_BURNING_ACK"}, + { 0, NULL } +}; +/* Forward-declare the dissector functions */ +void proto_register_octo(void); +void proto_reg_handoff_octo(void); +static int dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data); + +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); + proto_item *ti = proto_tree_add_item(tree, proto_octo, tvb, 0, -1, ENC_NA); + proto_tree *octo_tree = proto_item_add_subtree(ti, ett_octo); + proto_tree_add_item(octo_tree, + hf_octo_proto_version, + tvb, + packet_offset(proto_ver), + packet_elem_size(proto_ver), + ENC_LITTLE_ENDIAN); + guint32 rev = tvb_get_letohl(tvb, packet_offset(proto_ver)); + if(rev==3) + { + proto_tree_add_item(octo_tree, + hf_octo_proto_sequence, + tvb, + packet_offset(sequence), + packet_elem_size(sequence), + ENC_LITTLE_ENDIAN); + proto_tree_add_item(octo_tree, + hf_octo_proto_code, + tvb, + packet_offset(code), + packet_elem_size(code), + ENC_LITTLE_ENDIAN); + proto_tree_add_item(octo_tree, + hf_octo_proto_poolsize, + tvb, + packet_offset(poolsize), + packet_elem_size(poolsize), + ENC_LITTLE_ENDIAN); + + //packet_code_t code = (packet_code_t)(tvb_get_guint8(tvb, packet_offset(code))); + + guint16 len = tvb_get_letohs(tvb, packet_offset(len)); + if(len && len <= packet_elem_size(data)) + { + proto_tree_add_item(octo_tree, + hf_octo_proto_payload, + tvb, + packet_offset(data), + len, + ENC_LITTLE_ENDIAN); + } + proto_tree_add_item(octo_tree, + hf_octo_proto_data, + tvb, + packet_offset(data), + packet_elem_size(data), + ENC_LITTLE_ENDIAN); + proto_tree_add_item(octo_tree, + hf_octo_proto_len, + tvb, + packet_offset(len), + packet_elem_size(len), + ENC_LITTLE_ENDIAN); + return len; + } + return 0; +} + + +void proto_register_octo(void) +{ + static hf_register_info hf[] = { + { &hf_octo_proto_version, + { "version", "octo.rev", + FT_UINT32, BASE_DEC, + NULL, 0x0, + "Protocol Revision", HFILL } + }, + { &hf_octo_proto_sequence, + { "sequence number", "octo.seq", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_octo_proto_code, + { "code", "octo.code", + FT_UINT8, BASE_DEC, + VALS(packetcodes), 0x0, + NULL, HFILL } + }, + { &hf_octo_proto_poolsize, + { "poolsize", "octo.poolsize", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_octo_proto_payload, + { "payload", "octo.payload", + FT_STRING, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_octo_proto_data, + { "data", "octo.data", + FT_BYTES, BASE_NONE, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_octo_proto_len, + { "length", "octo.len", + FT_UINT16, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + } + }; + //protocol subtree array + static gint *ett[] = { + &ett_octo + }; + proto_octo = proto_register_protocol( + "Octoclock", + "Octoclock", + "octo" + ); + + proto_register_field_array(proto_octo, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + register_dissector("octo", dissect_octo, proto_octo); +} + +void proto_reg_handoff_octo(void) +{ + static dissector_handle_t octo_handle; + octo_handle = create_dissector_handle(dissect_octo, proto_octo); + 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/epan/octoclock/plugin.rc.in b/tools/dissectors/epan/octoclock/plugin.rc.in new file mode 100644 index 000000000..eca74e1a7 --- /dev/null +++ b/tools/dissectors/epan/octoclock/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/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/epan/zpu/packet-zpu.c b/tools/dissectors/epan/zpu/packet-zpu.c new file mode 100644 index 000000000..3eff36997 --- /dev/null +++ b/tools/dissectors/epan/zpu/packet-zpu.c @@ -0,0 +1,245 @@ +/* + * Dissector for ZPU packets (communication with X300 firmware) + * + * Copyright 2013-2014 Ettus Research LLC + * Copyright 2019 Ettus Research, a National Instruments brand + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +/* Format of ZPU packets is defined in x300_fw_commons.h, + * x300_fw_comms_t. + * + * Reminder: + * + * uint32_t flags; (ack, error, peek, poke) + * uint32_t sequence; + * uint32_t addr; + * 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 "zpu_addr_names.h" + +#define LOG_HEADER "[ZPU] " + +#ifndef min +#define min(a,b) ((a<b)?a:b) +#endif // min + +const unsigned int FW_PORT = X300_FW_COMMS_UDP_PORT; + +static int proto_zpu = -1; +static int hf_zpu_flags = -1; +static int hf_zpu_flags_ack = -1; +static int hf_zpu_flags_error = -1; +static int hf_zpu_flags_poke = -1; +static int hf_zpu_flags_peek = -1; +static int hf_zpu_seq = -1; +static int hf_zpu_addr = -1; +static int hf_zpu_data = -1; +static int hf_zpu_shmem_addr = -1; +static int hf_zpu_shmem_addr_name = -1; + +/* Subtree handles: set by register_subtree_array */ +static gint ett_zpu = -1; +static gint ett_zpu_flags = -1; +//static gint ett_zpu_shmem = -1; + +/* Forward-declare the dissector functions */ +void proto_register_zpu(void); +void proto_reg_handoff_zpu(void); +static int dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data); + +/* The dissector itself */ +static int dissect_zpu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + proto_item *item; + proto_tree *zpu_tree; + proto_item *flags_item; + proto_tree *flags_tree; + gint len; + + gboolean is_network; + gint endianness; + + if (pinfo->match_uint == FW_PORT) { + is_network = TRUE; + endianness = ENC_BIG_ENDIAN; + } + else { + is_network = FALSE; + endianness = ENC_LITTLE_ENDIAN; + } + + len = tvb_reported_length(tvb); + + col_append_str(pinfo->cinfo, COL_PROTOCOL, "/ZPU"); + /*col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "ZPU", tvb_format_text_wsp(tvb, 0, len));*/ + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "ZPU"); + + if (tree) + { + item = proto_tree_add_item(tree, proto_zpu, tvb, 0, min(16, len), ENC_NA); + + // Dissect 'flags' + if (len >= 4) + { + zpu_tree = proto_item_add_subtree(item, ett_zpu); + + flags_item = proto_tree_add_item(zpu_tree, hf_zpu_flags, tvb, 0, 4, endianness); + flags_tree = proto_item_add_subtree(flags_item, ett_zpu_flags); + + proto_tree_add_item(flags_tree, hf_zpu_flags_ack, tvb, 0, 4, ENC_NA); + proto_tree_add_item(flags_tree, hf_zpu_flags_error, tvb, 0, 4, ENC_NA); + proto_tree_add_item(flags_tree, hf_zpu_flags_poke, tvb, 0, 4, ENC_NA); + proto_tree_add_item(flags_tree, hf_zpu_flags_peek, tvb, 0, 4, ENC_NA); + + // Dissect 'sequence number' + if (len >= 8) + { + proto_tree_add_item(zpu_tree, hf_zpu_seq, tvb, 4, 4, ENC_NA); + + // Dissect 'address' + if (len >= 12) + { + proto_tree_add_item(zpu_tree, hf_zpu_addr, tvb, 8, 4, ENC_NA); +#if VERSION_MAJOR == 1 + 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 + unsigned int addr = 0; + memcpy(&addr, bytes, 4); + /* TODO proper endianness handling */ + addr = (addr >> 24) | ((addr & 0x00FF0000) >> 8) | ((addr & 0x0000FF00) << 8) | ((addr & 0x000000FF) << 24); + /* TODO check the actual size of shmem instead of this constant */ + if (addr >= X300_FW_SHMEM_BASE && addr <= X300_FW_SHMEM_BASE + 0x2000) + { + proto_item *shmem_addr_item = NULL; + + // Convert the address to a register number (32-bit registers == 4-byte registers) + addr -= X300_FW_SHMEM_BASE; + addr /= 4; + + shmem_addr_item = proto_tree_add_uint(zpu_tree, hf_zpu_shmem_addr, tvb, 8, 4, addr); + proto_item_append_text(shmem_addr_item, ", Register name: %s", + val_to_str(addr, X300_SHMEM_NAMES, "Unknown (0x%04x)") + ); + + } + + // Dissect 'data' + if (len >= 16) + { + proto_tree_add_item(zpu_tree, hf_zpu_data, tvb, 12, 4, ENC_NA); + } + } + } + } + } + return len; +} + +void proto_register_zpu(void) +{ + static hf_register_info hf[] = { + { &hf_zpu_flags, + { "Flags", "zpu.flags", + FT_UINT32, BASE_HEX, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_zpu_flags_ack, + { "ACK", "zpu.flags.ack", + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x1, + NULL, HFILL } + }, + { &hf_zpu_flags_error, + { "Error", "zpu.flags.error", + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x2, + NULL, HFILL } + }, + { &hf_zpu_flags_poke, + { "Poke", "zpu.flags.poke", + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x4, + NULL, HFILL } + }, + { &hf_zpu_flags_peek, + { "Peek", "zpu.flags.peek", + FT_BOOLEAN, 32, + TFS(&tfs_set_notset), 0x8, + NULL, HFILL } + }, + { &hf_zpu_seq, + { "Sequence ID", "zpu.seq", + FT_UINT32, BASE_HEX, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_zpu_addr, + { "Address", "zpu.addr", + FT_UINT32, BASE_HEX, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_zpu_shmem_addr, + { "SHMEM section", "zpu.shmem", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_zpu_data, + { "Data", "zpu.data", + FT_UINT32, BASE_HEX, + NULL, 0x0, + NULL, HFILL } + }, + }; + + static gint *ett[] = { + &ett_zpu, + &ett_zpu_flags, + //&ett_zpu_shmem + }; + + proto_zpu = proto_register_protocol("ZPU FW", "ZPU", "zpu"); + proto_register_field_array(proto_zpu, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + register_dissector("zpu", dissect_zpu, proto_zpu); +} + +/* Handler registration */ +void proto_reg_handoff_zpu(void) +{ + /* register dissector for UDP packets */ + static dissector_handle_t zpu_handle; + zpu_handle = create_dissector_handle(dissect_zpu, proto_zpu); + dissector_add_uint("udp.port", FW_PORT, zpu_handle); +} 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/epan/zpu/zpu_addr_names.h b/tools/dissectors/epan/zpu/zpu_addr_names.h new file mode 100644 index 000000000..64a1307bc --- /dev/null +++ b/tools/dissectors/epan/zpu/zpu_addr_names.h @@ -0,0 +1,39 @@ +/* + * Dissector for ZPU packets (communication with X300 firmware) + * + * Copyright 2013-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/>. + * + */ + +/* TODO: autogenerate this file */ + +/* Names of SHMEM registers: */ +static const value_string X300_SHMEM_NAMES[] = { + { 0, "X300_FW_SHMEM_COMPAT_NUM" }, + { 1, "X300_FW_SHMEM_GPSDO_STATUS" }, + { 2, "X300_FW_SHMEM_UART_RX_INDEX" }, + { 3, "X300_FW_SHMEM_UART_TX_INDEX" }, + { 5, "X300_FW_SHMEM_CLAIM_STATUS" }, + { 6, "X300_FW_SHMEM_CLAIM_TIME" }, + { 7, "X300_FW_SHMEM_CLAIM_SRC" }, + { 8, "X300_FW_SHMEM_UART_RX_ADDR" }, + { 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" }, + { 0, NULL } +}; + |