From f90a10a0d57b4e7fd56ca4312be733cb27598dbc Mon Sep 17 00:00:00 2001 From: Josef Baumgartner Date: Tue, 21 Oct 2014 13:12:18 +0200 Subject: [PATCH] epl: Rework POWERLINK (EPL) dissector With this patch we want to enable a better support of POWERLINK as a protocol for people who have to perform network diagnostics using analyzing tools. Up until now, the main tool used was Omnipeek. Now wireshark will be used more and more, due to the new extcap infrastructure, which supports debug tools to be added as capture devices. To better facilitate that change, we have adapted the textual representation of the Omnipeek dissector for POWERLINK, as it allows for a faster and simpler diagnosis routine. Additionally the name of the protocol has been changed to it's correct name "POWERLINK" as this is the official name used by EPSG for describing the protocol. Changelog: - Add error code definitions and string values. - Change name for protocol column to POWERLINK which is more commonly used than EPL. - Reformat output in info column to look like output the output of the POWERLINK plugin for Omnipeek. This facilitates the transition to Wireshark. The added information and changed output improves the debugging of POWERLINK nerworks. Change-Id: I795e2487f2ae7af6b90c29366a1843c9fabffa85 Reviewed-on: https://code.wireshark.org/review/5581 Reviewed-by: Roland Knall Petri-Dish: Anders Broman Reviewed-by: Anders Broman --- epan/dissectors/packet-epl.c | 594 ++++++++++++++++++++++++----------- 1 file changed, 402 insertions(+), 192 deletions(-) diff --git a/epan/dissectors/packet-epl.c b/epan/dissectors/packet-epl.c index f0c87d9056..23a3cc4829 100644 --- a/epan/dissectors/packet-epl.c +++ b/epan/dissectors/packet-epl.c @@ -1,6 +1,6 @@ /* packet-epl.c * Routines for "Ethernet POWERLINK 2.0" dissection - * (Ethernet POWERLINK V2.0 Communication Profile Specification Draft Standard Version 1.0.0) + * (Ethernet POWERLINK V2.0 Communication Profile Specification Draft Standard Version 1.2.0) * * Copyright (c) 2006: Zurich University of Applied Sciences Winterthur (ZHW) * Institute of Embedded Systems (InES) @@ -81,7 +81,7 @@ static const value_string addr_str_vals[] = { {EPL_INVALID_NODEID, " (invalid)" }, {EPL_MN_NODEID, " (Managing Node)" }, {EPL_DIAGNOSTIC_DEVICE_NODEID, " (Diagnostic Device)" }, - {EPL_TO_LEGACY_ETHERNET_ROUTER_NODEID, " (EPL to legacy Ethernet Router)" }, + {EPL_TO_LEGACY_ETHERNET_ROUTER_NODEID, " (POWERLINK to legacy Ethernet Router)" }, {EPL_BROADCAST_NODEID, " (broadcast)" }, {0,NULL} }; @@ -144,6 +144,9 @@ static const value_string mtyp_vals[] = { #define EPL_SOC_PS_MASK 0x40 #define EPL_PDO_RD_MASK 0x01 +#define EPL_PDO_RS_MASK 0x07 +#define EPL_PDO_PR_MASK 0x38 + /* RequestedServiceID s for EPL message type "SoA" */ #define EPL_SOA_NOSERVICE 0 #define EPL_SOA_IDENTREQUEST 1 @@ -152,6 +155,15 @@ static const value_string mtyp_vals[] = { #define EPL_SOA_SYNCREQUEST 6 #define EPL_SOA_UNSPECIFIEDINVITE 255 +#define EPL_SOA_SYNC_PRES_FIRST 0x01 +#define EPL_SOA_SYNC_PRES_SECOND 0x02 +#define EPL_SOA_SYNC_MND_FIRST 0x04 +#define EPL_SOA_SYNC_MND_SECOND 0x08 +#define EPL_SOA_SYNC_PRES_TIMEOUT 0x10 +#define EPL_SOA_SYNC_MAC_VALID 0x20 +#define EPL_SOA_SYNC_PRES_RESET 0x40 +#define EPL_SOA_SYNC_PRES_SET 0x80 + static const value_string soa_svid_vals[] = { {EPL_SOA_NOSERVICE, "NoService" }, {EPL_SOA_IDENTREQUEST, "IdentRequest" }, @@ -170,6 +182,20 @@ static const value_string soa_svid_vals[] = { #define EPL_ASND_SDO 5 #define EPL_ASND_SYNCRESPONSE 6 +#define EPL_ASND_SYNCRESPONSE_FST_VALID 0x01 +#define EPL_ASND_SYNCRESPONSE_SEC_VALID 0x02 +#define EPL_ASND_SYNCRESPONSE_MODE 0x80 + +static const value_string soa_svid_id_vals[] = { + {EPL_SOA_NOSERVICE, "NO_SERVICE" }, + {EPL_SOA_IDENTREQUEST, "IDENT_REQUEST" }, + {EPL_SOA_STATUSREQUEST, "STATUS_REQUEST" }, + {EPL_SOA_NMTREQUESTINVITE, "NMT_REQUEST_INV" }, + {EPL_SOA_SYNCREQUEST, "SYNC_REQUEST" }, + {EPL_SOA_UNSPECIFIEDINVITE, "UNSPEC_INVITE" }, + {0,NULL} +}; + static const value_string asnd_svid_vals[] = { {EPL_ASND_IDENTRESPONSE, "IdentResponse" }, {EPL_ASND_STATUSRESPONSE, "StatusResponse"}, @@ -180,6 +206,16 @@ static const value_string asnd_svid_vals[] = { {0,NULL} }; +static const value_string asnd_svid_id_vals[] = { + {EPL_ASND_IDENTRESPONSE, "IDENT_RESPONSE" }, + {EPL_ASND_STATUSRESPONSE, "STATUS_RESPONSE"}, + {EPL_ASND_NMTREQUEST, "NMT_REQUEST" }, + {EPL_ASND_NMTCOMMAND, "NMT_COMMAND" }, + {EPL_ASND_SDO, "SDO" }, + {EPL_ASND_SYNCRESPONSE, "SYNC_RESPONSE" }, + {0,NULL} +}; + /* NMTCommand values for EPL message type "ASnd" */ #define EPL_ASND_NMTCOMMAND_NMTSTARTNODE 0x21 #define EPL_ASND_NMTCOMMAND_NMTSTOPNODE 0x22 @@ -251,14 +287,115 @@ static value_string_ext asnd_cid_vals_ext = VALUE_STRING_EXT_INIT(asnd_cid_vals) /* Maximal Sequence */ #define EPL_MAX_SEQUENCE 0x40 +#define EPL_MAX_ADDRESSES 0xF1 /* SCON and RCON values*/ #define EPL_NO_CONNECTION 0x00 #define EPL_INITIALIZATION 0x01 #define EPL_VALID 0x02 +#define EPL_ACKREQ 0x03 #define EPL_RETRANSMISSION 0x03 /* MAX Frame offset */ #define EPL_MAX_FRAME_OFFSET 0x64 + +/* error codes */ +#define E_NO_ERROR 0x0000 +#define E_NMT_NO_IDENT_RES 0xF001 +#define E_NMT_NO_STATUS_RES 0xF002 +#define E_DLL_BAD_PHYS_MODE 0x8161 +#define E_DLL_COLLISION 0x8162 +#define E_DLL_COLLISION_TH 0x8163 +#define E_DLL_CRC_TH 0x8164 +#define E_DLL_LOSS_OF_LINK 0x8165 +#define E_DLL_MAC_BUFFER 0x8166 +#define E_DLL_ADDRESS_CONFLICT 0x8201 +#define E_DLL_MULTIPLE_MN 0x8202 +#define E_PDO_SHORT_RX 0x8210 +#define E_PDO_MAP_VERS 0x8211 +#define E_NMT_ASND_MTU_DIF 0x8212 +#define E_NMT_ASND_MTU_LIM 0x8213 +#define E_NMT_ASND_TX_LIM 0x8214 +#define E_NMT_CYCLE_LEN 0x8231 +#define E_DLL_CYCLE_EXCEED 0x8232 +#define E_DLL_CYCLE_EXCEED_TH 0x8233 +#define E_NMT_IDLE_LIM 0x8234 +#define E_DLL_JITTER_TH 0x8235 +#define E_DLL_LATE_PRES_TH 0x8236 +#define E_NMT_PREQ_CN 0x8237 +#define E_NMT_PREQ_LIM 0x8238 +#define E_NMT_PRES_CN 0x8239 +#define E_NMT_PRES_RX_LIM 0x823A +#define E_NMT_PRES_TX_LIM 0x823B +#define E_DLL_INVALID_FORMAT 0x8241 +#define E_DLL_LOSS_PREQ_TH 0x8242 +#define E_DLL_LOSS_PRES_TH 0x8243 +#define E_DLL_LOSS_SOA_TH 0x8244 +#define E_DLL_LOSS_SOC_TH 0x8245 +#define E_NMT_BA1 0x8410 +#define E_NMT_BA1_NO_MN_SUPPORT 0x8411 +#define E_NMT_BPO1 0x8420 +#define E_NMT_BPO1_GET_IDENT 0x8421 +#define E_NMT_BPO1_DEVICE_TYPE 0x8422 +#define E_NMT_BPO1_VENDOR_ID 0x8423 +#define E_NMT_BPO1_PRODUCT_CODE 0x8424 +#define E_NMT_BPO1_REVISION_NO 0x8425 +#define E_NMT_BPO1_SERIAL_NO 0x8426 +#define E_NMT_BPO1_CF_VERIFY 0x8428 +#define E_NMT_BPO2 0x8430 +#define E_NMT_BRO 0x8440 +#define E_NMT_WRONG_STATE 0x8480 + +static const value_string errorcode_vals[] = { + { E_NO_ERROR, "E_NO_ERROR" }, + { E_DLL_BAD_PHYS_MODE, "E_DLL_BAD_PHYS_MODE" }, + { E_DLL_COLLISION, "E_DLL_COLLISION" }, + { E_DLL_COLLISION_TH, "E_DLL_COLLISION_TH" }, + { E_DLL_CRC_TH, "E_DLL_CRC_TH" }, + { E_DLL_LOSS_OF_LINK, "E_DLL_LOSS_OF_LINK" }, + { E_DLL_MAC_BUFFER, "E_DLL_MAC_BUFFER" }, + { E_DLL_ADDRESS_CONFLICT, "E_DLL_ADDRESS_CONFLICT" }, + { E_DLL_MULTIPLE_MN, "E_DLL_MULTIPLE_MN" }, + { E_PDO_SHORT_RX, "E_PDO_SHORT_RX" }, + { E_PDO_MAP_VERS, "E_PDO_MAP_VERS" }, + { E_NMT_ASND_MTU_DIF, "E_NMT_ASND_MTU_DIF" }, + { E_NMT_ASND_MTU_LIM, "E_NMT_ASND_MTU_LIM" }, + { E_NMT_ASND_TX_LIM, "E_NMT_ASND_TX_LIM" }, + { E_NMT_CYCLE_LEN, "E_NMT_CYCLE_LEN" }, + { E_DLL_CYCLE_EXCEED, "E_DLL_CYCLE_EXCEED" }, + { E_DLL_CYCLE_EXCEED_TH, "E_DLL_CYCLE_EXCEED_TH" }, + { E_NMT_IDLE_LIM, "E_NMT_IDLE_LIM" }, + { E_DLL_JITTER_TH, "E_DLL_JITTER_TH" }, + { E_DLL_LATE_PRES_TH, "E_DLL_LATE_PRES_TH" }, + { E_NMT_PREQ_CN, "E_NMT_PREQ_CN" }, + { E_NMT_PREQ_LIM, "E_NMT_PREQ_LIM" }, + { E_NMT_PRES_CN, "E_NMT_PRES_CN" }, + { E_NMT_PRES_RX_LIM, "E_NMT_PRES_RX_LIM" }, + { E_NMT_PRES_TX_LIM, "E_NMT_PRES_TX_LIM" }, + { E_DLL_INVALID_FORMAT, "E_DLL_INVALID_FORMAT" }, + { E_DLL_LOSS_PREQ_TH, "E_DLL_LOSS_PREQ_TH" }, + { E_DLL_LOSS_PRES_TH, "E_DLL_LOSS_PRES_TH" }, + { E_DLL_LOSS_SOA_TH, "E_DLL_LOSS_SOA_TH" }, + { E_DLL_LOSS_SOC_TH, "E_DLL_LOSS_SOC_TH" }, + { E_NMT_BA1, "E_NMT_BA1" }, + { E_NMT_BA1_NO_MN_SUPPORT, "E_NMT_BA1_NO_MN_SUPPORT" }, + { E_NMT_BPO1, "E_NMT_BPO1" }, + { E_NMT_BPO1_GET_IDENT, "E_NMT_BPO1_GET_IDENT" }, + { E_NMT_BPO1_DEVICE_TYPE, "E_NMT_BPO1_DEVICE_TYPE" }, + { E_NMT_BPO1_VENDOR_ID, "E_NMT_BPO1_VENDOR_ID" }, + { E_NMT_BPO1_PRODUCT_CODE, "E_NMT_BPO1_PRODUCT_CODE" }, + { E_NMT_BPO1_REVISION_NO, "E_NMT_BPO1_REVISION_NO" }, + { E_NMT_BPO1_SERIAL_NO, "E_NMT_BPO1_SERIAL_NO" }, + { E_NMT_BPO1_CF_VERIFY, "E_NMT_BPO1_CF_VERIFY" }, + { E_NMT_BPO2, "E_NMT_BPO2" }, + { E_NMT_BRO, "E_NMT_BRO" }, + { E_NMT_WRONG_STATE, "E_NMT_WRONG_STATE" }, + { E_NMT_NO_IDENT_RES, "E_NMT_NO_IDENT_RES" }, + { E_NMT_NO_STATUS_RES, "E_NMT_NO_STATUS_RES" }, + {0,NULL} +}; + +static value_string_ext errorcode_vals_ext = VALUE_STRING_EXT_INIT(errorcode_vals); + /* duplication table key */ typedef struct { guint8 src; @@ -408,6 +545,14 @@ static const value_string epl_sdo_receive_con_vals[] = { #define EPL_ASND_SDO_SEQ_SEND_CON_CONNECTION_VALID 0x02 #define EPL_ASND_SDO_SEQ_SEND_CON_ERROR_VALID_ACK_REQ 0x03 +static const value_string epl_sdo_init_abbr_vals[] = { + {EPL_ASND_SDO_SEQ_RECEIVE_CON_NO_CONNECTION, "n" }, + {EPL_ASND_SDO_SEQ_RECEIVE_CON_INITIALIZATION, "i" }, + {EPL_ASND_SDO_SEQ_RECEIVE_CON_CONNECTION_VALID, "c" }, + {EPL_ASND_SDO_SEQ_RECEIVE_CON_ERROR_RESPONSE, "e" }, + {0,NULL} +}; + static const value_string epl_sdo_send_con_vals[] = { {EPL_ASND_SDO_SEQ_SEND_CON_NO_CONNECTION, "No connection" }, {EPL_ASND_SDO_SEQ_SEND_CON_INITIALIZATION, "Initialization" }, @@ -416,11 +561,57 @@ static const value_string epl_sdo_send_con_vals[] = { {0,NULL} }; -/* SDO EPL Command Layer Protocol */ +#define EPL_SDO_INIT_REQUEST ((EPL_NO_CONNECTION << 8) | EPL_INITIALIZATION) +#define EPL_SDO_INIT_ACK ((EPL_INITIALIZATION << 8) | EPL_INITIALIZATION) +#define EPL_SDO_INIT_RESPONSE ((EPL_INITIALIZATION << 8) | EPL_VALID) +#define EPL_SDO_VALID ((EPL_VALID << 8) | EPL_VALID) +#define EPL_SDO_RETRANSMISSION ((EPL_RETRANSMISSION << 8) | EPL_VALID) +#define EPL_SDO_ACKREQ ((EPL_VALID << 8) | EPL_ACKREQ) +#define EPL_SDO_CLOSE ((EPL_NO_CONNECTION << 8) | EPL_NO_CONNECTION) + +static const value_string epl_sdo_init_con_vals[] = { + {EPL_SDO_INIT_REQUEST, "InitReq" }, + {EPL_SDO_INIT_ACK, "InitAck" }, + {EPL_SDO_INIT_RESPONSE, "InitResp" }, + {EPL_SDO_VALID, "Valid" }, + {EPL_SDO_RETRANSMISSION, "Retrans" }, + {EPL_SDO_ACKREQ, "AckReq" }, + {EPL_SDO_CLOSE, "Close" }, + {0,NULL} +}; + + +/* SDO Command Layer Protocol */ #define EPL_ASND_SDO_CMD_ABORT_FILTER 0x40 #define EPL_ASND_SDO_CMD_SEGMENTATION_FILTER 0x30 #define EPL_ASND_SDO_CMD_RESPONSE_FILTER 0x80 +#define EPL_ASND_SDO_CMD_RESPONSE_RESPONSE 0 +#define EPL_ASND_SDO_CMD_RESPONSE_REQUEST 1 + +#define EPL_ASND_SDO_CMD_ABORT_TRANSFER_OK 0 +#define EPL_ASND_SDO_CMD_ABORT_ABORT_TRANSFER 1 + +#define EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER 0 +#define EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER 1 +#define EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT 2 +#define EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE 3 + +#define EPL_ASND_SDO_COMMAND_NOT_IN_LIST 0x00 +#define EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX 0x01 +#define EPL_ASND_SDO_COMMAND_READ_BY_INDEX 0x02 +#define EPL_ASND_SDO_COMMAND_WRITE_ALL_BY_INDEX 0x03 +#define EPL_ASND_SDO_COMMAND_READ_ALL_BY_INDEX 0x04 +#define EPL_ASND_SDO_COMMAND_WRITE_BY_NAME 0x05 +#define EPL_ASND_SDO_COMMAND_READ_BY_NAME 0x06 +#define EPL_ASND_SDO_COMMAND_FILE_WRITE 0x20 +#define EPL_ASND_SDO_COMMAND_FILE_READ 0x21 +#define EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX 0x31 +#define EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX 0x32 +#define EPL_ASND_SDO_COMMAND_MAXIMUM_SEGMENT_SIZE 0x70 +#define EPL_ASND_SDO_COMMAND_LINK_NAME_TO_INDEX 0x71 + +/* OD indexes */ #define EPL_SOD_CYLE_LEN 0x1006 #define EPL_SOD_PDO_RX_COMM 0x1400 #define EPL_SOD_PDO_RX_MAPP 0x1600 @@ -929,50 +1120,33 @@ static const value_string sdo_cmd_abort_code[] = { }; static value_string_ext sdo_cmd_abort_code_ext = VALUE_STRING_EXT_INIT(sdo_cmd_abort_code); -#define EPL_ASND_SDO_CMD_RESPONSE_RESPONSE 0 -#define EPL_ASND_SDO_CMD_RESPONSE_REQUEST 1 - static const value_string epl_sdo_asnd_cmd_response[] = { - {EPL_ASND_SDO_CMD_RESPONSE_RESPONSE, "Request" }, - {EPL_ASND_SDO_CMD_RESPONSE_REQUEST, "Response" }, + {EPL_ASND_SDO_CMD_RESPONSE_RESPONSE, "Request" }, + {EPL_ASND_SDO_CMD_RESPONSE_REQUEST, "Response" }, {0,NULL} }; -#define EPL_ASND_SDO_CMD_ABORT_TRANSFER_OK 0 -#define EPL_ASND_SDO_CMD_ABORT_ABORT_TRANSFER 1 - static const value_string epl_sdo_asnd_cmd_abort[] = { - {EPL_ASND_SDO_CMD_ABORT_TRANSFER_OK, "Transfer OK" }, - {EPL_ASND_SDO_CMD_ABORT_ABORT_TRANSFER, "Abort Transfer" }, + {EPL_ASND_SDO_CMD_ABORT_TRANSFER_OK, "Transfer OK" }, + {EPL_ASND_SDO_CMD_ABORT_ABORT_TRANSFER, "Abort Transfer" }, {0,NULL} }; -#define EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER 0 -#define EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER 1 -#define EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT 2 -#define EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE 3 - static const value_string epl_sdo_asnd_cmd_segmentation[] = { - {EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER, "Expedited Transfer" }, - {EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER, "Initiate Transfer" }, - {EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT, "Segment" }, - {EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE, "Transfer Complete" }, + {EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER, "Expedited Transfer" }, + {EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER, "Initiate Transfer" }, + {EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT, "Segment" }, + {EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE, "Transfer Complete" }, {0,NULL} }; -#define EPL_ASND_SDO_COMMAND_NOT_IN_LIST 0x00 -#define EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX 0x01 -#define EPL_ASND_SDO_COMMAND_READ_BY_INDEX 0x02 -#define EPL_ASND_SDO_COMMAND_WRITE_ALL_BY_INDEX 0x03 -#define EPL_ASND_SDO_COMMAND_READ_ALL_BY_INDEX 0x04 -#define EPL_ASND_SDO_COMMAND_WRITE_BY_NAME 0x05 -#define EPL_ASND_SDO_COMMAND_READ_BY_NAME 0x06 -#define EPL_ASND_SDO_COMMAND_FILE_WRITE 0x20 -#define EPL_ASND_SDO_COMMAND_FILE_READ 0x21 -#define EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX 0x31 -#define EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX 0x32 -#define EPL_ASND_SDO_COMMAND_MAXIMUM_SEGMENT_SIZE 0x70 -#define EPL_ASND_SDO_COMMAND_LINK_NAME_TO_INDEX 0x71 +static const value_string epl_sdo_asnd_cmd_segmentation_abbr[] = { + {EPL_ASND_SDO_CMD_SEGMENTATION_EPEDITED_TRANSFER, "EX" }, + {EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER, "SI" }, + {EPL_ASND_SDO_CMD_SEGMENTATION_SEGMENT, "ST" }, + {EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE, "SC" }, + {0,NULL} +}; static const value_string epl_sdo_asnd_commands[] = { {EPL_ASND_SDO_COMMAND_NOT_IN_LIST , "Not in List" }, @@ -991,21 +1165,27 @@ static const value_string epl_sdo_asnd_commands[] = { {0,NULL} }; -#define EPL_SOA_SYNC_PRES_FIRST 0x01 -#define EPL_SOA_SYNC_PRES_SECOND 0x02 -#define EPL_SOA_SYNC_MND_FIRST 0x04 -#define EPL_SOA_SYNC_MND_SECOND 0x08 -#define EPL_SOA_SYNC_PRES_TIMEOUT 0x10 -#define EPL_SOA_SYNC_MAC_VALID 0x20 -#define EPL_SOA_SYNC_PRES_RESET 0x40 -#define EPL_SOA_SYNC_PRES_SET 0x80 - -#define EPL_ASND_SYNCRESPONSE_FST_VALID 0x01 -#define EPL_ASND_SYNCRESPONSE_SEC_VALID 0x02 -#define EPL_ASND_SYNCRESPONSE_MODE 0x80 - static value_string_ext epl_sdo_asnd_commands_ext = VALUE_STRING_EXT_INIT(epl_sdo_asnd_commands); +static const value_string epl_sdo_asnd_commands_short[] = { + {EPL_ASND_SDO_COMMAND_NOT_IN_LIST , "NotInList" }, + {EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX , "WriteByIndex" }, + {EPL_ASND_SDO_COMMAND_READ_BY_INDEX , "ReadByIndex" }, + {EPL_ASND_SDO_COMMAND_WRITE_ALL_BY_INDEX , "WriteAllByIndex" }, + {EPL_ASND_SDO_COMMAND_READ_ALL_BY_INDEX , "ReadAllByIndex" }, + {EPL_ASND_SDO_COMMAND_WRITE_BY_NAME , "WriteByName" }, + {EPL_ASND_SDO_COMMAND_READ_BY_NAME , "ReadByName" }, + {EPL_ASND_SDO_COMMAND_FILE_WRITE , "FileWrite" }, + {EPL_ASND_SDO_COMMAND_FILE_READ , "FileRead" }, + {EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX, "WriteMultipleParam" }, + {EPL_ASND_SDO_COMMAND_READ_MULTIPLE_PARAMETER_BY_INDEX , "ReadMultipleParam" }, + {0,NULL} +}; + + +static value_string_ext epl_sdo_asnd_commands_short_ext = VALUE_STRING_EXT_INIT(epl_sdo_asnd_commands_short); + + static const gchar* addr_str_cn = " (Controlled Node)"; static const gchar* addr_str_res = " (reserved)"; @@ -1027,9 +1207,9 @@ static gint dissect_epl_asnd_sdo(proto_tree *epl_tree, tvbuff_t *tvb, packet_inf static gint dissect_epl_asnd_resp(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset); static gint dissect_epl_sdo_sequence(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset); static gint dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset); -static gint dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response); -static gint dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response); -static gint dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response); +static gint dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response, guint16 segment_size); +static gint dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response, guint16 segment_size); +static gint dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response, guint16 segment_size); static const gchar* decode_epl_address(guchar adr); @@ -1194,6 +1374,7 @@ static gint hf_epl_asnd_nmtrequest_rcd = -1; /*NMTCommand*/ static gint hf_epl_asnd_nmtcommand_cid = -1; static gint hf_epl_asnd_nmtcommand_cdat = -1; +static gint hf_epl_asnd_nmtcommand_resetnode_reason = -1; /*static gint hf_epl_asnd_nmtcommand_nmtnetparameterset_mtu = -1;*/ static gint hf_epl_asnd_nmtcommand_nmtnethostnameset_hn = -1; static gint hf_epl_asnd_nmtcommand_nmtflusharpentry_nid = -1; @@ -1479,12 +1660,12 @@ dissect_eplpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean udp /* Make entries in Protocol column and Info column on summary display */ if (!udpencap) { - col_set_str(pinfo->cinfo, COL_PROTOCOL, "EPL"); + col_set_str(pinfo->cinfo, COL_PROTOCOL, "POWERLINK"); } else { /* guess that this is an EPL frame encapsulated into an UDP datagram */ - col_set_str(pinfo->cinfo, COL_PROTOCOL, "EPL/UDP"); + col_set_str(pinfo->cinfo, COL_PROTOCOL, "POWERLINK/UDP"); } /* Get message type */ @@ -1519,46 +1700,40 @@ dissect_eplpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean udp switch (epl_mtyp) { case EPL_SOC: - /* source and destination NodeID are fixed according to the spec */ - col_set_str(pinfo->cinfo, COL_INFO, "SoC "); + col_add_fstr(pinfo->cinfo, COL_INFO, "%3d->%3d SoC ", epl_src, epl_dest); break; case EPL_PREQ: - /* show only destination NodeID, because source is always 240 (MN) */ - col_add_fstr(pinfo->cinfo, COL_INFO, "PReq dst = %3d ", epl_dest); + col_add_fstr(pinfo->cinfo, COL_INFO, "%3d->%3d PReq ", epl_src, epl_dest); break; case EPL_PRES: - /* show only source NodeID, because destination is always 255 (broadcast) */ - col_add_fstr(pinfo->cinfo, COL_INFO, "PRes src = %3d ", epl_src); + col_add_fstr(pinfo->cinfo, COL_INFO, "%3d->%3d PRes ", epl_src, epl_dest); break; case EPL_SOA: - /* source and destination NodeID are fixed according to the spec */ - col_set_str(pinfo->cinfo, COL_INFO, "SoA "); + col_add_fstr(pinfo->cinfo, COL_INFO, "%3d->%3d SoA ", epl_src, epl_dest); break; case EPL_ASND: if (udpencap) { - col_set_str(pinfo->cinfo, COL_INFO, "ASnd "); + col_set_str(pinfo->cinfo, COL_INFO, " ASnd "); } else { - col_add_fstr(pinfo->cinfo, COL_INFO, - "ASnd src = %3d dst = %3d ", epl_src, epl_dest); + col_add_fstr(pinfo->cinfo, COL_INFO, "%3d->%3d ASnd ", epl_src, epl_dest); } break; case EPL_AINV: if (udpencap) { - col_set_str(pinfo->cinfo, COL_INFO, "AInv "); + col_set_str(pinfo->cinfo, COL_INFO, " AInv "); } else { - col_add_fstr(pinfo->cinfo, COL_INFO, - "AInv src = %3d dst = %3d ", epl_src, epl_dest); + col_add_fstr(pinfo->cinfo, COL_INFO, "%3d->%3d AInv ", epl_src, epl_dest); } break; @@ -1709,7 +1884,7 @@ dissect_epl_soc(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint of if (show_soc_flags) { - col_append_fstr(pinfo->cinfo, COL_INFO, "MC = %d PS = %d", + col_append_fstr(pinfo->cinfo, COL_INFO, "F:MC=%d,PS=%d", ((EPL_SOC_MC_MASK & flags) >> 7), ((EPL_SOC_PS_MASK & flags) >> 6)); } @@ -1752,8 +1927,8 @@ dissect_epl_preq(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint o len = tvb_get_letohs(tvb, offset); proto_tree_add_uint(epl_tree, hf_epl_preq_size, tvb, offset, 2, len); - col_append_fstr(pinfo->cinfo, COL_INFO, "RD = %d size = %d ver = %d.%d", - (EPL_PDO_RD_MASK & flags), len, hi_nibble(pdoversion), lo_nibble(pdoversion)); + col_append_fstr(pinfo->cinfo, COL_INFO, "[%4d] F:RD=%d V:%d.%d", len, + (EPL_PDO_RD_MASK & flags), hi_nibble(pdoversion), lo_nibble(pdoversion)); offset += 2; offset += dissect_epl_payload(epl_tree, tvb, pinfo, offset, len, EPL_PREQ ); @@ -1768,7 +1943,7 @@ dissect_epl_pres(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 { guint16 len; guint8 pdoversion; - guint8 flags; + guint8 state, flags, flags2; static const int * res_flags[] = { &hf_epl_pres_ms, &hf_epl_pres_en, @@ -1776,6 +1951,7 @@ dissect_epl_pres(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 NULL }; + state = tvb_get_guint8(tvb, offset); if (epl_src != EPL_MN_NODEID) /* check if the sender is CN or MN */ { proto_tree_add_item(epl_tree, hf_epl_pres_stat_cs, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1790,6 +1966,7 @@ dissect_epl_pres(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 proto_tree_add_bitmask(epl_tree, tvb, offset, hf_epl_pres, ett_epl_pres, res_flags, ENC_NA); offset += 1; + flags2 = tvb_get_guint8(tvb, offset); proto_tree_add_item(epl_tree, hf_epl_pres_pr, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(epl_tree, hf_epl_pres_rs, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; @@ -1802,8 +1979,23 @@ dissect_epl_pres(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 len = tvb_get_letohs(tvb, offset); proto_tree_add_uint(epl_tree, hf_epl_pres_size, tvb, offset, 2, len); - col_append_fstr(pinfo->cinfo, COL_INFO, "RD = %d size = %d ver = %d.%d", - (EPL_PDO_RD_MASK & flags), len, hi_nibble(pdoversion), lo_nibble(pdoversion)); + col_append_fstr(pinfo->cinfo, COL_INFO, "[%4d]", len); + + col_append_fstr(pinfo->cinfo, COL_INFO, " F:RD=%d,RS=%d,PR=%d V=%d.%d", + (EPL_PDO_RD_MASK & flags), (EPL_PDO_RS_MASK & flags2), (EPL_PDO_PR_MASK & flags2) >> 3, + hi_nibble(pdoversion), lo_nibble(pdoversion)); + + if (epl_src != EPL_MN_NODEID) /* check if the sender is CN or MN */ + { + col_append_fstr(pinfo->cinfo, COL_INFO, " %s", + val_to_str(state, epl_nmt_cs_vals, "Unknown(%d)")); + } + else /* MN */ + { + col_append_fstr(pinfo->cinfo, COL_INFO, " %s", + val_to_str(state, epl_nmt_ms_vals, "Unknown(%d)")); + } + offset += 2; offset += dissect_epl_payload ( epl_tree, tvb, pinfo, offset, len, EPL_PRES ); @@ -1816,10 +2008,11 @@ gint dissect_epl_soa(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 epl_src, gint offset) { guint8 svid, target; + guint8 state; proto_item *psf_item = NULL; proto_tree *psf_tree = NULL; - + state = tvb_get_guint8(tvb, offset); if (epl_src != EPL_MN_NODEID) /* check if CN or MN */ { proto_tree_add_item(epl_tree, hf_epl_soa_stat_cs, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1828,6 +2021,7 @@ dissect_epl_soa(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 { proto_tree_add_item(epl_tree, hf_epl_soa_stat_ms, tvb, offset, 1, ENC_LITTLE_ENDIAN); } + offset += 1; proto_tree_add_item(epl_tree, hf_epl_soa_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1842,10 +2036,18 @@ dissect_epl_soa(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 proto_tree_add_uint(epl_tree, hf_epl_soa_svtg, tvb, offset, 1, target); offset += 1; - if (svid != EPL_SOA_NOSERVICE) + col_append_fstr(pinfo->cinfo, COL_INFO, "(%s)->%3d", + val_to_str(svid, soa_svid_id_vals, "UNKNOWN(%d)"), target); + + if (epl_src != EPL_MN_NODEID) /* check if CN or MN */ { - col_append_fstr(pinfo->cinfo, COL_INFO, "tgt = %3d %s", - target, val_to_str(svid, soa_svid_vals, "Unknown (%d)")); + col_append_fstr(pinfo->cinfo, COL_INFO, " %s", + val_to_str(state, epl_nmt_cs_vals, "Unknown(%d)")); + } + else /* MN */ + { + col_append_fstr(pinfo->cinfo, COL_INFO, " %s", + val_to_str(state, epl_nmt_ms_vals, "Unknown(%d)")); } proto_tree_add_item(epl_tree, hf_epl_soa_eplv, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1925,8 +2127,8 @@ dissect_epl_asnd(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 offset += 1; - col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", - val_to_str(svid, asnd_svid_vals, "Unknown (%d)")); + col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ", + val_to_str(svid, asnd_svid_id_vals, "UNKNOWN(%d)")); switch (svid) { @@ -1982,8 +2184,8 @@ dissect_epl_ainv(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, guint8 svid = tvb_get_guint8(tvb, offset); - col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", - val_to_str(svid, asnd_svid_vals, "Unknown (%d)")); + col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ", + val_to_str(svid, asnd_svid_id_vals, "UNKNOWN(%d)")); item = proto_tree_add_uint(epl_tree, hf_epl_asnd_svid, tvb, offset, 1, svid); offset += 1; @@ -2046,12 +2248,15 @@ dissect_epl_asnd_nmtreq(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint dissect_epl_asnd_nmtcmd(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset) { - guint8 epl_asnd_nmtcommand_cid; + guint8 epl_asnd_nmtcommand_cid; + guint16 errorcode; epl_asnd_nmtcommand_cid = tvb_get_guint8(tvb, offset); proto_tree_add_uint(epl_tree, hf_epl_asnd_nmtcommand_cid, tvb, offset, 1, epl_asnd_nmtcommand_cid); offset += 2; + col_append_str(pinfo->cinfo, COL_INFO, val_to_str_ext(epl_asnd_nmtcommand_cid, &asnd_cid_vals_ext, "Unknown(%d)")); + switch (epl_asnd_nmtcommand_cid) { case EPL_ASND_NMTCOMMAND_NMTNETHOSTNAMESET: @@ -2069,13 +2274,21 @@ dissect_epl_asnd_nmtcmd(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, offset += 6; break; + case EPL_ASND_NMTCOMMAND_NMTRESETNODE: + errorcode = tvb_get_letohs(tvb, offset); + if (errorcode != 0) + { + col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str(errorcode, errorcode_vals, "Unknown Error(0x%04x")); + proto_tree_add_item(epl_tree, hf_epl_asnd_nmtcommand_resetnode_reason, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } + else + proto_tree_add_item(epl_tree, hf_epl_asnd_nmtcommand_cdat, tvb, offset, -1, ENC_NA); + break; + default: proto_tree_add_item(epl_tree, hf_epl_asnd_nmtcommand_cdat, tvb, offset, -1, ENC_NA); } - col_append_str(pinfo->cinfo, COL_INFO, - val_to_str_ext(epl_asnd_nmtcommand_cid, &asnd_cid_vals_ext, "Unknown (%d)")); - return offset; } @@ -2151,8 +2364,8 @@ dissect_epl_asnd_ires(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, g profile = tvb_get_letohs(tvb, offset); additional = tvb_get_letohs(tvb, offset+2); proto_tree_add_string_format_value(epl_tree, hf_epl_asnd_identresponse_dt, tvb, offset, - 4, "", "Profile %d (%s), Additional Information: 0x%4.4X", - profile, val_to_str_const(profile, epl_device_profiles, "Unknown Profile"), additional); + 4, "", "Profile %d (%s), Additional Information: 0x%4.4X", + profile, val_to_str_const(profile, epl_device_profiles, "Unknown Profile"), additional); proto_tree_add_item(epl_tree, hf_epl_asnd_identresponse_profile, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 4; @@ -2317,7 +2530,7 @@ dissect_epl_asnd_sres(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, g /*Entry Type*/ ti_el_entry_type = proto_tree_add_item(ti_el_entry, - hf_epl_asnd_statusresponse_el_entry_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); + hf_epl_asnd_statusresponse_el_entry_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); epl_el_entry_type_tree = proto_item_add_subtree(ti_el_entry_type, ett_epl_el_entry_type); @@ -2495,19 +2708,15 @@ dissect_epl_sdo_sequence(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo proto_tree_add_uint(sod_seq_tree, hf_epl_asnd_sdo_seq_send_con, tvb, offset, 1, seq_send); offset += 3; + col_append_fstr(pinfo->cinfo, COL_INFO, "Seq:%02d%s,%02d%s", + seq_recv >> EPL_ASND_SDO_SEQ_MASK, val_to_str(seq_recv & EPL_ASND_SDO_SEQ_CON_MASK, epl_sdo_init_abbr_vals, "x"), + seq_send >> EPL_ASND_SDO_SEQ_MASK, val_to_str(seq_send & EPL_ASND_SDO_SEQ_CON_MASK, epl_sdo_init_abbr_vals, "x")); + seq_recv &= EPL_ASND_SDO_SEQ_CON_MASK; seq_send &= EPL_ASND_SDO_SEQ_CON_MASK; - if ((seq_recv == EPL_NO_CONNECTION) && (seq_send == EPL_NO_CONNECTION)) - { - /* Sequence layer will be closed */ - col_append_str(pinfo->cinfo, COL_INFO, "Close "); - } - else if ((seq_recv < EPL_VALID) || (seq_send < EPL_VALID)) - { - col_append_fstr(pinfo->cinfo, COL_INFO, "Init=%d%d ", - seq_recv, seq_send); - } + col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ", val_to_str((seq_recv << 8) | seq_send, epl_sdo_init_con_vals, "Invalid")); + return offset; } @@ -2515,7 +2724,7 @@ gint dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset) { gint payload_length; - guint8 segmented, command_id; + guint8 segmented, command_id, transaction_id; gboolean response, abort_flag; guint32 abort_code = 0; guint32 fragmentId = 0; @@ -2528,7 +2737,6 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, offset += 1; command_id = tvb_get_guint8(tvb, offset + 2); - abort_flag = tvb_get_guint8(tvb, offset + 1) & EPL_ASND_SDO_CMD_ABORT_FILTER; /* test if CommandField == empty */ @@ -2537,10 +2745,14 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, item = proto_tree_add_item(epl_tree, hf_epl_asnd_sdo_cmd, tvb, offset, 0, ENC_NA); sdo_cmd_tree = proto_item_add_subtree(item, ett_epl_sdo_command_layer); - segmented = (tvb_get_guint8(tvb, offset + 1) & EPL_ASND_SDO_CMD_SEGMENTATION_FILTER) >> 4; + transaction_id = tvb_get_guint8(tvb, offset); response = tvb_get_guint8(tvb, offset + 1) & EPL_ASND_SDO_CMD_RESPONSE_FILTER; + segmented = (tvb_get_guint8(tvb, offset + 1) & EPL_ASND_SDO_CMD_SEGMENTATION_FILTER) >> 4; segment_size = tvb_get_letohs(tvb, offset + 3); + col_append_fstr(pinfo->cinfo, COL_INFO, "Cmd:%s,TID=%02d ", + val_to_str(segmented, epl_sdo_asnd_cmd_segmentation_abbr, " Inv(%d)"), transaction_id); + proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_transaction_id, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; @@ -2561,8 +2773,7 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, if (segmented == EPL_ASND_SDO_CMD_SEGMENTATION_INITIATE_TRANSFER) { - if((command_id == EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX) || - (command_id == EPL_ASND_SDO_COMMAND_READ_BY_INDEX)) + if((command_id == EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX) || (command_id == EPL_ASND_SDO_COMMAND_READ_BY_INDEX)) { /* if download => reset counter */ if(command_id == EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX) @@ -2606,23 +2817,22 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, abort_code = tvb_get_letohl(tvb, offset); /* if AbortBit is set then print AbortMessage */ proto_tree_add_uint(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_abort_code, tvb, offset, 4, abort_code); - - col_append_fstr(pinfo->cinfo, COL_INFO, "Abort = 0x%08X", abort_code); + col_append_fstr(pinfo->cinfo, COL_INFO, "Abort:0x%08X (%s)", abort_code, val_to_str_ext_const(abort_code, &sdo_cmd_abort_code_ext, "Unknown")); } else { switch (command_id) { case EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX: - offset = dissect_epl_sdo_command_write_by_index(sdo_cmd_tree, tvb, pinfo, offset, segmented, response); + offset = dissect_epl_sdo_command_write_by_index(sdo_cmd_tree, tvb, pinfo, offset, segmented, response, segment_size); break; case EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX: - offset = dissect_epl_sdo_command_write_multiple_by_index(sdo_cmd_tree, tvb, pinfo, offset, segmented, response); + offset = dissect_epl_sdo_command_write_multiple_by_index(sdo_cmd_tree, tvb, pinfo, offset, segmented, response, segment_size); break; case EPL_ASND_SDO_COMMAND_READ_BY_INDEX: - offset = dissect_epl_sdo_command_read_by_index(sdo_cmd_tree, tvb, pinfo, offset, segmented, response); + offset = dissect_epl_sdo_command_read_by_index(sdo_cmd_tree, tvb, pinfo, offset, segmented, response, segment_size); break; default: @@ -2633,9 +2843,8 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, return offset; } - gint -dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response) +dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response, guint16 segment_size) { gint size, payload_length; guint16 idx = 0x00, nosub = 0x00, sod_index = 0x00, error = 0xFF, entries = 0x00, sub_val = 0x00; @@ -2660,8 +2869,6 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack idx = tvb_get_letohs(tvb, offset); /* add index item */ psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_index, tvb, offset, 2, idx, "OD Index: 0x%04X", idx); - /* info text */ - col_append_fstr(pinfo->cinfo, COL_INFO, " Req. %s", val_to_str(segmented, epl_sdo_asnd_cmd_segmentation, " User Defined (%d)")); /* value to string */ index_str = rval_to_str_const(idx, sod_cmd_str, "unknown"); /* get index string value */ @@ -2671,6 +2878,18 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack /* get subindex string value*/ nosub = str_to_val(sub_index_str, sod_cmd_str_no_sub,error); + offset += 2; + /* get subindex offset */ + subindex = tvb_get_guint8(tvb, offset); + /* get subindex string */ + sub_str = val_to_str_ext_const(idx, &sod_cmd_sub_str, "unknown"); + /* get string value */ + sub_val = str_to_val(sub_str, sod_cmd_sub_str_val,error); + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: (0x%04X/%d)", + val_to_str_ext(EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX, &epl_sdo_asnd_commands_short_ext, "Command(%02X)"), + segment_size, idx, subindex); + /* string is in list */ if(sod_index != error) { @@ -2686,7 +2905,7 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack proto_item_append_text(psf_item,"_REC)"); } /* info text */ - col_append_fstr(pinfo->cinfo, COL_INFO, " [%s", val_to_str_ext_const(((guint32)(sod_index << 16)), &sod_index_names, "User Defined")); + col_append_fstr(pinfo->cinfo, COL_INFO, " (%s", val_to_str_ext_const(((guint32)(sod_index << 16)), &sod_index_names, "User Defined")); col_append_fstr(pinfo->cinfo, COL_INFO, "_%02Xh", (idx-sod_index)); if(sod_index == EPL_SOD_PDO_RX_MAPP || sod_index == EPL_SOD_PDO_TX_MAPP) { @@ -2701,65 +2920,47 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack else { proto_item_append_text(psf_item," (%s)", val_to_str_ext_const(((guint32)(idx<<16)), &sod_index_names, "User Defined")); - col_append_fstr(pinfo->cinfo, COL_INFO, " [%s", val_to_str_ext_const(((guint32) (idx << 16)), &sod_index_names, "User Defined")); + col_append_fstr(pinfo->cinfo, COL_INFO, " (%s", val_to_str_ext_const(((guint32) (idx << 16)), &sod_index_names, "User Defined")); } - offset += 2; - /* get subindex offset */ - subindex = tvb_get_guint8(tvb, offset); - /* get subindex string */ - sub_str = val_to_str_ext_const(idx, &sod_cmd_sub_str, "unknown"); - /* get string value */ - sub_val = str_to_val(sub_str, sod_cmd_sub_str_val,error); - if(sub_val != error) idx = sub_val; /* if the subindex is a EPL_SOD_STORE_PARAM */ - if(idx == EPL_SOD_STORE_PARAM && subindex <= 0x7F && subindex >= 0x04) - { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%02X", subindex); - proto_item_append_text(psf_item, " (ManufacturerParam_%02Xh_U32)",subindex); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ManufacturerParam_%02Xh_U32]",subindex); - } /* if the subindex is a EPL_SOD_RESTORE_PARAM */ - else if(idx == EPL_SOD_RESTORE_PARAM && subindex <= 0x7F && subindex >= 0x04) + if((idx == EPL_SOD_STORE_PARAM && subindex <= 0x7F && subindex >= 0x04) || + (idx == EPL_SOD_RESTORE_PARAM && subindex <= 0x7F && subindex >= 0x04)) { psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%02X", subindex); - proto_item_append_text(psf_item, " (ManufacturerParam_%02Xh_U32)",subindex); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ManufacturerParam_%02Xh_U32]",subindex); + proto_item_append_text(psf_item, " (ManufacturerParam_%02Xh_U32)", subindex); + col_append_fstr(pinfo->cinfo, COL_INFO, "/ManufacturerParam_%02Xh_U32)", subindex); } /* if the subindex is a EPL_SOD_PDO_RX_MAPP */ - else if(idx == EPL_SOD_PDO_RX_MAPP && subindex >= 0x01 && subindex <= 0xfe) - { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%02X", subindex); - proto_item_append_text(psf_item, " (ObjectMapping)"); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ObjectMapping]"); - } /* if the subindex is a EPL_SOD_PDO_TX_MAPP */ - else if(idx == EPL_SOD_PDO_TX_MAPP && subindex >= 0x01 && subindex <= 0xfe) + else if((idx == EPL_SOD_PDO_RX_MAPP && subindex >= 0x01 && subindex <= 0xfe) || + (idx == EPL_SOD_PDO_TX_MAPP && subindex >= 0x01 && subindex <= 0xfe)) { psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%02X", subindex); proto_item_append_text(psf_item, " (ObjectMapping)"); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ObjectMapping]"); + col_append_fstr(pinfo->cinfo, COL_INFO, "/ObjectMapping)"); } /* no subindex */ else if(nosub != error) { - col_append_fstr(pinfo->cinfo, COL_INFO, "]"); + col_append_fstr(pinfo->cinfo, COL_INFO, ")"); } /* if the subindex has the value 0x00 */ else if(subindex == entries) { psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%02X", subindex); proto_item_append_text(psf_item, " (NumberOfEntries)"); - col_append_fstr(pinfo->cinfo, COL_INFO, " | NumberOfEntries]"); + col_append_fstr(pinfo->cinfo, COL_INFO, "/NumberOfEntries)"); } else { psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%02X", subindex); - proto_item_append_text(psf_item, " (%s)", val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); - col_append_fstr(pinfo->cinfo, COL_INFO, " | %s]",val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); + proto_item_append_text(psf_item, " (%s)", val_to_str_ext_const((subindex | (idx << 16)), &sod_index_names, "User Defined")); + col_append_fstr(pinfo->cinfo, COL_INFO, "/%s)",val_to_str_ext_const((subindex | (idx << 16)), &sod_index_names, "User Defined")); } offset += 2; } @@ -2796,7 +2997,7 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack ct += 1; /* add the frame to reassembly_table */ frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, - fragmentId, NULL, ct, payload_length, end_segment ? FALSE : TRUE ); + fragmentId, NULL, ct, payload_length, end_segment ? FALSE : TRUE ); } /* if the reassembly_table is not Null and the frame stored is the same as the current frame */ @@ -2811,7 +3012,7 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack /* add the reassembley fields */ process_reassembled_data(tvb, 0, pinfo, "Reassembled Message", frag_msg, &epl_frag_items, NULL, payload_tree ); proto_tree_add_uint_format_value(payload_tree, hf_epl_asnd_sdo_cmd_reassembled, tvb, 0, 0, - payload_length, "%d bytes (over all fragments)", frag_msg->len); + payload_length, "%d bytes (over all fragments)", frag_msg->len); col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)" ); /* reset memory */ memset(&epl_asnd_sdo_reassembly_write,0,sizeof(epl_sdo_reassembly)); @@ -2860,12 +3061,12 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack } gint -dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented _U_, gboolean response) +dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented _U_, gboolean response, guint16 segment_size) { gint dataoffset; guint8 subindex = 0x00, padding = 0x00; guint16 idx = 0x00, sod_index = 0x00, nosub = 0x00 ,error = 0xFF, entries = 0x00, sub_val = 0x00; - guint32 size, offsetincrement, datalength, remlength; + guint32 size, offsetincrement, datalength, remlength, objectcnt; gboolean lastentry = FALSE; const gchar *index_str, *sub_str, *sub_index_str; proto_item *psf_item; @@ -2877,24 +3078,27 @@ dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t * * EPL_SOA_EPLV_OFFSET has to be recognized, because the increment of PLK SDO payloads * is calculated, starting with the byte position AFTER the Sequence Layer. */ - if (!response) { /* request */ - col_append_str(pinfo->cinfo, COL_INFO, "Write Multiple Parameter by Index" ); + col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%d]:", + val_to_str_ext(EPL_ASND_SDO_COMMAND_WRITE_MULTIPLE_PARAMETER_BY_INDEX, + &epl_sdo_asnd_commands_short_ext, "Command(%02X)"), + segment_size); remlength = (guint32)tvb_reported_length_remaining(tvb, offset); + objectcnt = 0; + /* As long as no lastentry has been detected, and we have still bytes left, * we start the loop. lastentry is probably not necessary anymore, since * we now use length_remaining, but it is kept to be on the safe side. */ while ( !lastentry && remlength > 0 ) { + offsetincrement = tvb_get_letohl(tvb, offset); /* the data is aligned in 4-byte increments, therfore maximum padding is 3 */ padding = tvb_get_guint8 ( tvb, offset + 7 ) & 0x03; - if ( padding > 3 ) - break; datalength = offsetincrement - ( offset - EPL_SOA_EPLV_OFFSET ); /* An offset increment of zero usually indicates, that we are at the end @@ -2966,24 +3170,20 @@ dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t * { proto_item_append_text(psf_item,"_REC)"); } - /* info text */ - col_append_fstr(pinfo->cinfo, COL_INFO, " [%s", val_to_str_ext_const(((guint32)(sod_index << 16)), &sod_index_names, "User Defined")); - col_append_fstr(pinfo->cinfo, COL_INFO, "_%02Xh", (idx-sod_index)); - if(sod_index == EPL_SOD_PDO_RX_MAPP || sod_index == EPL_SOD_PDO_TX_MAPP) - { - col_append_fstr(pinfo->cinfo, COL_INFO, "_AU64"); - } - else - { - col_append_fstr(pinfo->cinfo, COL_INFO, "_REC"); - } - idx = sod_index; } else { proto_item_append_text(psf_item," (%s)", val_to_str_ext_const(((guint32)(idx<<16)), &sod_index_names, "User Defined")); - col_append_fstr(pinfo->cinfo, COL_INFO, " [%s", val_to_str_ext_const(((guint32) (idx << 16)), &sod_index_names, "User Defined")); } + + if (objectcnt < 8) + col_append_fstr(pinfo->cinfo, COL_INFO, " (0x%04X", idx); + else + col_append_str(pinfo->cinfo, COL_INFO, "."); + + if (sod_index != error) + idx = sod_index; + dataoffset += 2; /* get subindex offset */ @@ -2999,54 +3199,55 @@ dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t * /* if the subindex is a EPL_SOD_STORE_PARAM */ if(idx == EPL_SOD_STORE_PARAM && subindex <= 0x7F && subindex >= 0x04) { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, dataoffset, 1, subindex, "OD SubIndex: 0x%02X", subindex); - proto_item_append_text(psf_item, " (ManufacturerParam_%02Xh_U32)",subindex); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ManufacturerParam_%02Xh_U32]",subindex); + psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%d", subindex); + proto_item_append_text(psf_item, " (ManufacturerParam_%02Xh_U32)", subindex); } /* if the subindex is a EPL_SOD_RESTORE_PARAM */ else if(idx == EPL_SOD_RESTORE_PARAM && subindex <= 0x7F && subindex >= 0x04) { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, dataoffset, 1, subindex, "OD SubIndex: 0x%02X", subindex); - proto_item_append_text(psf_item, " (ManufacturerParam_%02Xh_U32)",subindex); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ManufacturerParam_%02Xh_U32]",subindex); + psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%d", subindex); + proto_item_append_text(psf_item, " (ManufacturerParam_%02Xh_U32)", subindex); } /* if the subindex is a EPL_SOD_PDO_RX_MAPP */ else if(idx == EPL_SOD_PDO_RX_MAPP && subindex >= 0x01 && subindex <= 0xfe) { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset+6, 1, subindex, "OD SubIndex: 0x%02X", subindex); + psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%d", subindex); proto_item_append_text(psf_item, " (ObjectMapping)"); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ObjectMapping]"); } /* if the subindex is a EPL_SOD_PDO_TX_MAPP */ else if(idx == EPL_SOD_PDO_TX_MAPP && subindex >= 0x01 && subindex <= 0xfe) { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset+6, 1, subindex, "OD SubIndex: 0x%02X", subindex); + psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%d", subindex); proto_item_append_text(psf_item, " (ObjectMapping)"); - col_append_fstr(pinfo->cinfo, COL_INFO, " | ObjectMapping]"); - } - /* no subindex */ - else if(nosub != error) - { - col_append_fstr(pinfo->cinfo, COL_INFO, "]"); } /* if the subindex has the value 0x00 */ else if(subindex == entries) { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, dataoffset, 1, subindex, "OD SubIndex: 0x%02X", subindex); + psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%d", subindex); proto_item_append_text(psf_item, " (NumberOfEntries)"); - col_append_fstr(pinfo->cinfo, COL_INFO, " | NumberOfEntries]"); } /* subindex */ else { - psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, dataoffset, 1, subindex, "OD SubIndex: 0x%02X", subindex); - proto_item_append_text(psf_item, " (%s)", val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); - col_append_fstr(pinfo->cinfo, COL_INFO, " | %s]",val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); + psf_item = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, subindex, "OD SubIndex: 0x%d", subindex); + proto_item_append_text(psf_item, " (%s)", val_to_str_ext_const((subindex | (idx << 16)), &sod_index_names, "User Defined")); } - dataoffset += 1; + /* info text */ + if (objectcnt < 8) + { + if (nosub != error) + /* no subindex */ + col_append_fstr(pinfo->cinfo, COL_INFO, ")"); + else + col_append_fstr(pinfo->cinfo, COL_INFO, "/%d)", subindex); + } + + + dataoffset += 1; proto_tree_add_uint(epl_tree, hf_epl_asnd_sdo_cmd_data_padding, tvb, dataoffset, 1, padding); dataoffset += 1; + objectcnt++; } /* if the frame is a PDO Mapping and the subindex is bigger than 0x00 */ @@ -3077,6 +3278,8 @@ dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t * /* calculating the remaining length, based on the current offset */ remlength = (guint32)tvb_reported_length_remaining(tvb, offset); } + + col_append_fstr(pinfo->cinfo, COL_INFO, " (%d)", objectcnt); } else { @@ -3087,7 +3290,7 @@ dissect_epl_sdo_command_write_multiple_by_index(proto_tree *epl_tree, tvbuff_t * } gint -dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response) +dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response, guint16 segment_size) { gint size, payload_length; guint16 idx = 0x00; @@ -3103,20 +3306,23 @@ dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packe if (!response) { /* request */ - col_append_fstr(pinfo->cinfo, COL_INFO, " Req. %s", - val_to_str(segmented, epl_sdo_asnd_cmd_segmentation, "User Defined (%d)")); idx = tvb_get_letohs(tvb, offset); psf_item = proto_tree_add_item(epl_tree, hf_epl_asnd_sdo_cmd_data_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); proto_item_append_text(psf_item," (%s)", val_to_str_ext_const(((guint32)(idx<<16)), &sod_index_names, "User Defined" )); - col_append_fstr(pinfo->cinfo, COL_INFO, " [%s", val_to_str_ext_const(((guint32) (idx << 16)), &sod_index_names, "User Defined")); offset += 2; subindex = tvb_get_guint8(tvb, offset); psf_item = proto_tree_add_item(epl_tree, hf_epl_asnd_sdo_cmd_data_subindex, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(psf_item, " (%s)", val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); - col_append_fstr(pinfo->cinfo, COL_INFO, " | %s]",val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); + offset += 1; + col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: (0x%04X/%d)", + val_to_str_ext(EPL_ASND_SDO_COMMAND_READ_BY_INDEX, &epl_sdo_asnd_commands_short_ext, "Command(%02X)"), + segment_size, idx, subindex); + col_append_fstr(pinfo->cinfo, COL_INFO, " (%s", val_to_str_ext_const(((guint32) (idx << 16)), &sod_index_names, "User Defined")); + col_append_fstr(pinfo->cinfo, COL_INFO, "/%s)",val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); + } else { @@ -3178,8 +3384,7 @@ dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packe } } /* response */ - col_append_fstr(pinfo->cinfo, COL_INFO, " Resp. %s", - val_to_str(segmented, epl_sdo_asnd_cmd_segmentation, "User Defined (%d)")); + col_append_str(pinfo->cinfo, COL_INFO, "Response"); size = tvb_reported_length_remaining(tvb, offset); offset = dissect_epl_payload ( epl_tree, tvb, pinfo, offset, size, EPL_ASND ); @@ -3777,6 +3982,11 @@ proto_register_epl(void) FT_UINT8, BASE_HEX_DEC | BASE_EXT_STRING, &asnd_cid_vals_ext, 0x00, NULL, HFILL } }, + { &hf_epl_asnd_nmtcommand_resetnode_reason, + { "Reset Reason", "epl.asnd.nmtcommand.resetnode_reason", + FT_UINT16, BASE_HEX | BASE_EXT_STRING, + &errorcode_vals_ext, 0x00, NULL, HFILL } + }, { &hf_epl_asnd_nmtcommand_cdat, { "NMTCommandData", "epl.asnd.nmtcommand.cdat", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }