diff options
author | Anthony Coddington <anthony.coddington@endace.com> | 2016-07-25 17:55:13 +1200 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2016-08-22 16:47:05 +0000 |
commit | 14af515846db90424b41b17a4b992d16a884ba46 (patch) | |
tree | dd0bd16f1409b3e3f05b0bdc5e61d23b2197431b | |
parent | c66c2a7cf3e087a8913d2e7e6d90f1675fddbce7 (diff) | |
download | wireshark-14af515846db90424b41b17a4b992d16a884ba46.tar.gz wireshark-14af515846db90424b41b17a4b992d16a884ba46.tar.bz2 wireshark-14af515846db90424b41b17a4b992d16a884ba46.zip |
ERF: Add ERF_TYPE_META clock tags
Adds various clock configuration related tags.
Uses ptp_v2 value strings exported from packet-ptp.
Refactor out common ERF_TYPE_META bitfield code.
Also clean up field registration a bit.
Add flow_hash_mode enum, other minor wording cleanup.
Manually display relative timestamps as nanoseconds for <1ms.
Fix ns_host_* tag subtree summary field name duplication.
Ping-Bug: 12303
Change-Id: I76264d141f1c4a3590627637daa5dcd4fdfd2e93
Reviewed-on: https://code.wireshark.org/review/16782
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
(cherry picked from commit 94cb86a0ca62680ceb8565b4f0a716e48010d885)
Reviewed-on: https://code.wireshark.org/review/17238
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
-rw-r--r-- | epan/dissectors/packet-erf.c | 532 | ||||
-rw-r--r-- | wiretap/erf.h | 32 |
2 files changed, 412 insertions, 152 deletions
diff --git a/epan/dissectors/packet-erf.c b/epan/dissectors/packet-erf.c index f5f7099bb9..b3e8aa4d4d 100644 --- a/epan/dissectors/packet-erf.c +++ b/epan/dissectors/packet-erf.c @@ -29,6 +29,7 @@ #include <epan/to_str.h> #include <wsutil/str_util.h> #include "packet-erf.h" +#include "packet-ptp.h" /* */ @@ -385,6 +386,8 @@ static dissector_handle_t sdh_handle; #define ERF_META_SECTION_NONE 0 #define ERF_META_SECTION_UNKNOWN 1 +#define NS_PER_S 1000000000 + /* Record type defines */ static const value_string erf_type_vals[] = { { ERF_TYPE_LEGACY ,"LEGACY"}, @@ -492,11 +495,26 @@ static const value_string channelised_type[] = { static const value_string erf_hash_type[] = { { 0x00, "Not set"}, { 0x01, "Non-IP (Src/Dst MACs, EtherType)"}, - { 0x02, "2-tuple (Src/Dst IP Addresses)"}, - { 0x03, "3-tuple (Src/Dst IP Addresses, IP Protocol)"}, - { 0x04, "4-tuple (Src/Dst IP Addresses, IP Protocol, Interface ID)"}, - { 0x05, "5-tuple (Src/Dst IP Addresses, IP Protocol, Src/Dst L4 Ports)"}, - { 0x06, "6-tuple (Src/Dst IP Addresses, IP Protocol, Src/Dst L4 Ports, Interface ID)"}, + { 0x02, "2-tuple (Src/Dst IPs)"}, + { 0x03, "3-tuple (Src/Dst IPs, IP Protocol)"}, + { 0x04, "4-tuple (Src/Dst IPs, IP Protocol, Interface ID)"}, + { 0x05, "5-tuple (Src/Dst IPs, IP Protocol, Src/Dst L4 Ports)"}, + { 0x06, "6-tuple (Src/Dst IPs, IP Protocol, Src/Dst L4 Ports, Interface ID)"}, + { 0, NULL} +}; + +static const value_string erf_hash_mode[] = { + { 0x00, "Reserved"}, + { 0x01, "Reserved"}, + { 0x02, "2-tuple (Src/Dst IPs)"}, + { 0x03, "3-tuple (Src/Dst IPs, IP Protocol)"}, + { 0x04, "4-tuple (Src/Dst IPs, IP Protocol, Interface ID)"}, + { 0x05, "5-tuple (Src/Dst IPs, IP Protocol, Src/Dst L4 Ports)"}, + { 0x06, "6-tuple (Src/Dst IPs, IP Protocol, Src/Dst L4 Ports, Interface ID)"}, + { 0x07, "2-tuple (Inner Src/Dst IPs)"}, + { 0x08, "4-tuple (Inner Src/Dst IPs, Outer Src/Dst IPs)"}, + { 0x09, "4-tuple (Inner Src/Dst IPs, Inner Src/Dst L4 Ports)"}, + { 0x10, "6-tuple (Inner Src/Dst IPs, Outer Src/Dst IPs, Inner Src/Dst L4 Ports)"}, { 0, NULL} }; @@ -518,15 +536,85 @@ static const value_string erf_port_type[] = { { 0, NULL} }; +static const value_string erf_clk_source[] = { + { 0x00, "Invalid"}, + { 0x01, "None" }, + { 0x02, "External"}, + { 0x03, "Host"}, + { 0x04, "Link Cable"}, + { 0x05, "PTP"}, + { 0x06, "Internal"}, + { 0, NULL} +}; + +static const value_string erf_clk_state[] = { + { 0x00, "Invalid" }, + { 0x01, "Unsynchronized"}, + { 0x02, "Synchronized"}, + { 0, NULL} +}; + +static const value_string erf_clk_link_mode[] = { + { 0x00, "Inavild"}, + { 0x01, "Not Connected"}, + { 0x02, "Master"}, + { 0x03, "Disabled Master"}, + { 0x04, "Slave"}, + { 0, NULL} +}; + +static const value_string erf_clk_port_proto[] = { + { 0x00, "Invalid" }, + { 0x01, "None" }, + { 0x02, "1PPS" }, + { 0x03, "IRIG-B" }, + { 0x04, "Ethernet" }, + { 0, NULL } +}; + /* Used as templates for ERF_META_TAG_tunneling_mode */ static const header_field_info erf_tunneling_modes[] = { - { "IP-in-IP", "ip_in_ip", FT_UINT32, BASE_DEC, NULL, 0x1, NULL, HFILL }, + { "IP-in-IP", "ip_in_ip", FT_BOOLEAN, 32, NULL, 0x1, NULL, HFILL }, /* 0x02 is currently unused and reserved */ - { "VXLAN", "vxlan", FT_UINT32, BASE_DEC, NULL, 0x4, NULL, HFILL }, - { "GRE", "gre", FT_UINT32, BASE_DEC, NULL, 0x8, NULL, HFILL }, - { "GTP", "gtp", FT_UINT32, BASE_DEC, NULL, 0x10, NULL, HFILL }, - { "MPLS over VLAN", "mpls_vlan", FT_UINT32, BASE_DEC, NULL, 0x20, NULL, HFILL } + { "VXLAN", "vxlan", FT_BOOLEAN, 32, NULL, 0x4, NULL, HFILL }, + { "GRE", "gre", FT_BOOLEAN, 32, NULL, 0x8, NULL, HFILL }, + { "GTP", "gtp", FT_BOOLEAN, 32, NULL, 0x10, NULL, HFILL }, + { "MPLS over VLAN", "mpls_vlan", FT_BOOLEAN, 32, NULL, 0x20, NULL, HFILL } +}; + +static const true_false_string erf_link_status_tfs = { + "Up", + "Down" +}; + +/* Used as templates for ERF_META_TAG_if_link_status */ +static const header_field_info erf_link_status[] = { + { "Link", "link", FT_BOOLEAN, 32, TFS(&erf_link_status_tfs), 0x1, NULL, HFILL } +}; + +/* Used as templates for ERF_META_TAG_ptp_time_properties */ +static const header_field_info erf_ptp_time_properties_flags[] = { + { "Leap61", "leap61", FT_BOOLEAN, 32, NULL, 0x1, NULL, HFILL }, + { "Leap59", "leap59", FT_BOOLEAN, 32, NULL, 0x2, NULL, HFILL }, + { "Current UTC Offset Valid", "currentUtcOffsetValid", FT_BOOLEAN, 32, NULL, 0x4, NULL, HFILL }, + { "PTP Timescale", "ptpTimescale", FT_BOOLEAN, 32, NULL, 0x8, NULL, HFILL }, + { "Time Traceable", "timeTraceable", FT_BOOLEAN, 32, NULL, 0x10, NULL, HFILL }, + { "Frequency Traceable", "frequencyTraceable", FT_BOOLEAN, 32, NULL, 0x20, NULL, HFILL } +}; + +/* Used as templates for ERF_META_TAG_ptp_gm_clock_quality */ +static const header_field_info erf_ptp_clock_quality[] = { + { "Clock Class", "clockClass", FT_UINT32, BASE_DEC, NULL, 0xFF000000, NULL, HFILL }, + { "Clock Accuracy", "clockAccuracy", FT_UINT32, BASE_DEC | BASE_EXT_STRING, &ptp_v2_clockAccuracy_vals_ext, 0x00FF0000, NULL, HFILL }, + { "Offset Scaled Log Variance","offsetScaledLogVariance", FT_UINT32, BASE_DEC, NULL, 0x0000FFFF, NULL, HFILL }, }; + +/* Used as templates for ERF_META_TAG_parent_section */ +static const header_field_info erf_parent_section[] = { + { "Section Type", "section_type", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }, + { "Section ID", "section_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } +}; + /* XXX: Must be at least array_length(erf_tunneling_modes). */ #define ERF_HF_VALUES_PER_TAG 8 @@ -549,6 +637,7 @@ typedef struct { guint16 code; guint16 section; const erf_meta_hf_template_t* tag_template; + const erf_meta_hf_template_t* section_template; gint ett; int hf_value; @@ -624,8 +713,8 @@ static const erf_meta_hf_template_t erf_meta_tags[] = { { ERF_META_TAG_loc_name, { "Location Name", "loc_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_parent_file, { "Parent Filename", "parent_file", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_filter, { "Filter", "filter", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, - { ERF_META_TAG_flow_hash_mode, { "Flow Hash Mode", "flow_hash_mode", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, - { ERF_META_TAG_tunneling_mode, { "Tunneling Mode", "tunneling_mode", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_flow_hash_mode, { "Flow Hash Mode", "flow_hash_mode", FT_UINT32, BASE_DEC, VALS(erf_hash_mode), 0x0, NULL, HFILL } }, + { ERF_META_TAG_tunneling_mode, { "Tunneling Mode", "tunneling_mode", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_npb_format, { "NPB Format", "npb_format", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_mem, { "Memory", "mem", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_datamine_id, { "Datamine ID", "datamine_id", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, @@ -662,6 +751,7 @@ static const erf_meta_hf_template_t erf_meta_tags[] = { { ERF_META_TAG_if_link_status, { "Interface Link Status", "if_link_status", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_if_phy_mode, { "Interface Endace PHY Mode", "if_phy_mode", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_if_port_type, { "Interface Port Type", "if_port_type", FT_UINT32, BASE_DEC, VALS(erf_port_type), 0x0, NULL, HFILL } }, + { ERF_META_TAG_if_rx_latency, { "Interface Uncorrected RX Latency", "if_rx_latency", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_src_ipv4, { "Source IPv4 address", "src_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_dest_ipv4, { "Destination IPv4 address", "dest_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } }, @@ -726,7 +816,49 @@ static const erf_meta_hf_template_t erf_meta_tags[] = { { ERF_META_TAG_exthdr, { "ERF Extension Header", "exthdr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { ERF_META_TAG_pcap_ng_block, { "PCAP-NG Block", "pcap_ng_block", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, - { ERF_META_TAG_asn1, { "ASN.1", "asn1", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } } + { ERF_META_TAG_asn1, { "ASN.1", "asn1", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + + { ERF_META_TAG_clk_source, { "Clock Source", "clk_source", FT_UINT32, BASE_DEC, VALS(erf_clk_source), 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_state, { "Clock State", "clk_state", FT_UINT32, BASE_DEC, VALS(erf_clk_state), 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_threshold, { "Clock Threshold", "clk_threshold", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_correction, { "Clock Correction", "clk_correction", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_failures, { "Clock Failures", "clk_failures", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_resyncs, { "Clock Resyncs", "clk_resyncs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_phase_error, { "Clock Phase Error", "clk_phase_error", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_input_pulses, { "Clock Input Pulses", "clk_input_pulses", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_rejected_pulses, { "Clock Rejected Pulses", "clk_rejected_pulses", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_phc_index, { "Clock PHC Index", "clk_phc_index", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_phc_offset, { "Clock PHC Offset", "clk_phc_offset", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_timebase, { "Clock Timebase", "clk_timebase", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_descr, { "Clock Description", "clk_descr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_out_source, { "Clock Output Source", "clk_out_source", FT_UINT32, BASE_DEC, VALS(erf_clk_source), 0x0, NULL, HFILL } }, + { ERF_META_TAG_clk_link_mode, { "Clock Link Cable Mode", "clk_link_mode", FT_UINT32, BASE_DEC, VALS(erf_clk_link_mode), 0x0, NULL, HFILL } }, + + /* + * PTP tags use the native PTPv2 format to preserve precision + * (except expanding integers to 32-bit). + */ + { ERF_META_TAG_ptp_domain_num, { "PTP Domain Number", "ptp_domain_num", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_steps_removed, { "PTP Steps Removed", "ptp_steps_removed", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + /* PTP TimeInterval scaled nanoseconds, using FT_RELATIVE_TIME so can compare with clk_threshold */ + { ERF_META_TAG_ptp_offset_from_master, { "PTP Offset From Master", "ptp_offset_from_master", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_mean_path_delay, { "PTP Mean Path Delay", "ptp_mean_path_delay", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_parent_identity, { "PTP Parent Clock Identity", "ptp_parent_identity", FT_EUI64, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_parent_port_num, { "PTP Parent Port Number", "ptp_parent_port_num", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_gm_identity, { "PTP Grandmaster Identity", "ptp_gm_identity", FT_EUI64, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + /* PTP ClockQuality combined field, see erf_ptp_clock_quality */ + { ERF_META_TAG_ptp_gm_clock_quality, { "PTP Grandmaster Clock Quality", "ptp_gm_clock_quality", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + /* Integer seconds, using FT_RELATIVE_TIME so can compare with clk_phc_offset */ + { ERF_META_TAG_ptp_current_utc_offset, { "PTP Current UTC Offset", "ptp_current_utc_offset", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + /* PTP TIME_PROPERTIES_DATA_SET flags, see erf_ptp_time_properties_flags */ + { ERF_META_TAG_ptp_time_properties, { "PTP Time Properties", "ptp_time_properties", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_time_source, { "PTP Time Source", "ptp_time_source", FT_UINT32, BASE_DEC | BASE_EXT_STRING, &ptp_v2_timeSource_vals_ext, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_clock_identity, { "PTP Clock Identity", "ptp_clock_identity", FT_EUI64, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_port_num, { "PTP Port Number", "ptp_port_num", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_port_state, { "PTP Port State", "ptp_port_state", FT_UINT32, BASE_DEC | BASE_EXT_STRING, &ptp_v2_portState_vals_ext, 0x0, NULL, HFILL } }, + { ERF_META_TAG_ptp_delay_mechanism, { "PTP Delay Mechanism", "ptp_delay_mechanism", FT_UINT32, BASE_DEC, VALS(ptp_v2_delayMechanism_vals), 0x0, NULL, HFILL } }, + + { ERF_META_TAG_clk_port_proto, { "Clock Input Port Protocol", "clk_port_proto", FT_UINT32, BASE_DEC, VALS(erf_clk_port_proto), 0x0, NULL, HFILL } } }; /* Sections are also tags, but enumerate them seperately to make logic simpler */ @@ -764,6 +896,20 @@ static erf_meta_tag_info_ex_t* erf_meta_tag_info_ex_new(wmem_allocator_t *alloca return extra; } +static erf_meta_tag_info_t* erf_meta_tag_info_new(wmem_allocator_t *allocator, const erf_meta_hf_template_t *section, const erf_meta_hf_template_t *tag) { + erf_meta_tag_info_t *tag_info = wmem_new0(allocator, erf_meta_tag_info_t); + + tag_info->code = tag->code; + tag_info->section = section->code; + tag_info->ett = -1; + tag_info->hf_value = -1; + tag_info->tag_template = tag; + tag_info->section_template = section; + tag_info->extra = NULL; + + return tag_info; +} + static erf_meta_tag_info_t* init_section_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf_meta_hf_template_t *section) { @@ -775,14 +921,10 @@ init_section_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf { NULL, { "Reserved", NULL, FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }} /* Reserved extra bytes */ }; - section_info = wmem_new0(wmem_epan_scope(), erf_meta_tag_info_t); - section_info->code = section->code; - section_info->section = section->code; /* Needed for lookup commonality */ - section_info->ett = -1; - section_info->hf_value = -1; - section_info->tag_template = section; + section_info = erf_meta_tag_info_new(wmem_epan_scope(), section, section /*Needed for lookup commonality*/); section_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope()); + /*Can't use the generic functions here because directly at section level*/ hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".section_id", NULL); hfri_tmp[0].p_id = §ion_info->hf_value; hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".section_len", NULL); @@ -801,80 +943,78 @@ init_section_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf } static erf_meta_tag_info_t* -init_tag_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf_meta_hf_template_t *section, const erf_meta_hf_template_t *tag) +init_tag_value_field(wmem_array_t *hfri_table, erf_meta_tag_info_t *tag_info) { - erf_meta_tag_info_t *tag_info; - unsigned int i = 0; - gint *ett_tmp; /* wmem_array_append needs actual memory to copy from */ - hf_register_info hfri_tmp[] = { - { NULL, { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, /* Value, will be filled from template */ - { NULL, { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }} /* Second value, if any */ - }; - guint hfri_len = 0; + hf_register_info hfri_tmp = { NULL, { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}; /* Value, will be filled from template */ - tag_info = wmem_new0(wmem_epan_scope(), erf_meta_tag_info_t); - tag_info->code = tag->code; - tag_info->section = section->code; - tag_info->ett = -1; - tag_info->hf_value = -1; - tag_info->tag_template = tag; - tag_info->extra = NULL; + /* Add value field */ + hfri_tmp.p_id = &tag_info->hf_value; + hfri_tmp.hfinfo = tag_info->tag_template->hfinfo; + hfri_tmp.hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", tag_info->section_template->hfinfo.abbrev, ".", tag_info->tag_template->hfinfo.abbrev, NULL); + wmem_array_append_one(hfri_table, hfri_tmp); - switch (tag_info->code) { - /* Special case: parent section */ - case ERF_META_TAG_parent_section: - tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope()); + return tag_info; +} - hfri_tmp[0].p_id = &tag_info->hf_value; - hfri_tmp[0].hfinfo.name = "Section Type"; - hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".section_type", NULL); - hfri_tmp[0].hfinfo.type = FT_UINT16; - hfri_tmp[0].hfinfo.display = BASE_DEC; - /* XXX: Cannot set strings here as array may be realloced as more added! */ - hfri_len++; - - hfri_tmp[1].p_id = &tag_info->extra->hf_values[0]; - hfri_tmp[1].hfinfo.name = "Section ID"; - hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".section_id", NULL); - hfri_tmp[1].hfinfo.type = FT_UINT16; - hfri_tmp[1].hfinfo.display = BASE_DEC; - hfri_len++; - break; +static erf_meta_tag_info_t* +init_tag_value_subfields(wmem_array_t *hfri_table, erf_meta_tag_info_t *tag_info, const header_field_info *extra_fields, int extra_fields_len) +{ + int i = 0; + hf_register_info hfri_tmp = { NULL, { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}; /* Value, will be filled from template */ - /* Special case: Link Status bits */ - case ERF_META_TAG_if_link_status: + if (extra_fields) { tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope()); + for (i = 0; i < extra_fields_len; i++) { + /* Add value subfield */ + hfri_tmp.p_id = &tag_info->extra->hf_values[i]; + hfri_tmp.hfinfo = extra_fields[i]; + hfri_tmp.hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", tag_info->section_template->hfinfo.abbrev, ".", tag_info->tag_template->hfinfo.abbrev, ".", extra_fields[i].abbrev, NULL); + wmem_array_append_one(hfri_table, hfri_tmp); + } + } - hfri_tmp[0].p_id = &tag_info->hf_value; - hfri_tmp[0].hfinfo = tag->hfinfo; - hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, NULL); - hfri_len++; - - hfri_tmp[1].p_id = &tag_info->extra->hf_values[0]; - hfri_tmp[1].hfinfo.name = "Link"; - hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".link", NULL); - hfri_tmp[1].hfinfo.type = FT_UINT32; - hfri_tmp[1].hfinfo.display = BASE_DEC; - hfri_tmp[1].hfinfo.bitmask = 0x00000001; - hfri_len++; - break; + return tag_info; +} - /* Special case: Tunneling mode bits */ - case ERF_META_TAG_tunneling_mode: - tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope()); +static erf_meta_tag_info_t* +init_ns_addr_tag_value_fields(wmem_array_t *hfri_table, erf_meta_tag_info_t *tag_info) +{ + header_field_info ns_addr_extra_fields[] = { + { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }, /* Address value, will be filled from template */ + { "Name", "name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } /* Name value */ + }; - hfri_tmp[0].p_id = &tag_info->hf_value; - hfri_tmp[0].hfinfo = tag->hfinfo; - hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, NULL); - hfri_len++; - - /* Borrow hfri_tmp[1], inserting each bitfield value */ - for (i = 0; i < array_length(erf_tunneling_modes); i++) { - hfri_tmp[1].p_id = &tag_info->extra->hf_values[i]; - hfri_tmp[1].hfinfo = erf_tunneling_modes[i]; - hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".", erf_tunneling_modes[i].abbrev, NULL); - wmem_array_append(hfri_table, &hfri_tmp[1], 1); - } + tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope()); + + /* Set address subfield type, etc. from template based on address type */ + ns_addr_extra_fields[0] = tag_info->tag_template->hfinfo; + ns_addr_extra_fields[0].name = "Address"; + ns_addr_extra_fields[0].abbrev = "addr"; + /* Don't need a main value as we just use a text subtree */ + /* Init subfields */ + init_tag_value_subfields(hfri_table, tag_info, ns_addr_extra_fields, array_length(ns_addr_extra_fields)); + + return tag_info; +} + +static erf_meta_tag_info_t* +init_tag_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf_meta_hf_template_t *section, const erf_meta_hf_template_t *tag) +{ + erf_meta_tag_info_t *tag_info; + gint *ett_tmp; /* wmem_array_append needs actual memory to copy from */ + + tag_info = erf_meta_tag_info_new(wmem_epan_scope(), section, tag); + + /*Tags with subfields (only)*/ + /*XXX: Can't currently easily be described in the template because + * there is curently no dissect bitfield equivalent that supports arbitrary + * types/offsets*/ + switch (tag->code) { + /*Special case: parent_section*/ + case ERF_META_TAG_parent_section: + /*Don't need a main value*/ + /*Init subfields*/ + init_tag_value_subfields(hfri_table, tag_info, erf_parent_section, array_length(erf_parent_section)); break; /* Special case: name entry */ @@ -888,36 +1028,35 @@ init_tag_fields(wmem_array_t *hfri_table, wmem_array_t *ett_table, const erf_met case ERF_META_TAG_ns_host_ib_gid: case ERF_META_TAG_ns_host_ib_lid: case ERF_META_TAG_ns_host_fc_id: - tag_info->extra = erf_meta_tag_info_ex_new(wmem_epan_scope()); - - hfri_tmp[0].p_id = &tag_info->hf_value; - /* Set type, etc. from template based on address type */ - hfri_tmp[0].hfinfo = tag->hfinfo; - hfri_tmp[0].hfinfo.name = "Address"; - hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".addr", NULL); - hfri_len++; - - hfri_tmp[1].p_id = &tag_info->extra->hf_values[0]; - hfri_tmp[1].hfinfo.name = "Name"; - hfri_tmp[1].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, ".name", NULL); - hfri_tmp[1].hfinfo.type = FT_STRING; - hfri_tmp[1].hfinfo.display = BASE_NONE; - hfri_len++; + init_ns_addr_tag_value_fields(hfri_table, tag_info); break; - /* Usual case: just use template */ + /* Usual case: init single field template */ default: - hfri_tmp[0].p_id = &tag_info->hf_value; - hfri_tmp[0].hfinfo = tag->hfinfo; - hfri_tmp[0].hfinfo.abbrev = wmem_strconcat(wmem_epan_scope(), "erf.meta.", section->hfinfo.abbrev, ".", tag->hfinfo.abbrev, NULL); - hfri_len++; + init_tag_value_field(hfri_table, tag_info); break; } - /* Add hf_register_info, ett entries */ - wmem_array_append(hfri_table, hfri_tmp, hfri_len); + /*Tags that need additional subfields*/ + switch (tag->code) { + /*Special case: bitfields*/ + /*TODO: Maybe put extra_fields in template with dissect callback?*/ + case ERF_META_TAG_tunneling_mode: + init_tag_value_subfields(hfri_table, tag_info, erf_tunneling_modes, array_length(erf_tunneling_modes)); + break; + case ERF_META_TAG_if_link_status: + init_tag_value_subfields(hfri_table, tag_info, erf_link_status, array_length(erf_link_status)); + break; + case ERF_META_TAG_ptp_time_properties: + init_tag_value_subfields(hfri_table, tag_info, erf_ptp_time_properties_flags, array_length(erf_ptp_time_properties_flags)); + break; + case ERF_META_TAG_ptp_gm_clock_quality: + init_tag_value_subfields(hfri_table, tag_info, erf_ptp_clock_quality, array_length(erf_ptp_clock_quality)); + } + + /* Add ett entries */ ett_tmp = &tag_info->ett; - wmem_array_append(ett_table, &ett_tmp, 1); + wmem_array_append_one(ett_table, ett_tmp); return tag_info; } @@ -1879,6 +2018,101 @@ check_section_length(packet_info *pinfo, proto_item *sectionlen_pi, int offset, } } +static proto_item* +dissect_meta_tag_bitfield(proto_item *section_tree, tvbuff_t *tvb, int offset, erf_meta_tag_info_t *tag_info, proto_item **out_tag_tree) +{ + proto_item *tag_pi = NULL; + const int* hf_flags[ERF_HF_VALUES_PER_TAG]; + int i; + + DISSECTOR_ASSERT(tag_info->extra); + + /* This is allowed as the array itself is not constant (not const int* const) */ + for (i = 0; tag_info->extra->hf_values[i] != -1; i++) { + hf_flags[i] = &tag_info->extra->hf_values[i]; + } + hf_flags[i] = NULL; + + /* use flags variant so we print integers without value_strings */ + tag_pi = proto_tree_add_bitmask_with_flags(section_tree, tvb, offset + 4, tag_info->hf_value, tag_info->ett, hf_flags, ENC_BIG_ENDIAN, BMT_NO_FLAGS); + if (out_tag_tree) { + *out_tag_tree = proto_item_get_subtree(tag_pi); + } + + return tag_pi; +} + +void erf_ts_to_nstime(guint64 timestamp, nstime_t* t, gboolean is_relative) { + guint64 ts = timestamp; + + /* relative ERF timestamps are signed, convert as if unsigned then flip back */ + if (is_relative) { + ts = (guint64) ABS((gint64)timestamp); + } + + + t->secs = (long) (ts >> 32); + ts = ((ts & 0xffffffff) * 1000 * 1000 * 1000); + ts += (ts & 0x80000000) << 1; /* rounding */ + t->nsecs = ((int) (ts >> 32)); + if (t->nsecs >= NS_PER_S) { + t->nsecs -= NS_PER_S; + t->secs += 1; + } + + if (is_relative && (gint64)timestamp < 0) { + /* + * Set both signs to negative for consistency with other nstime code + * and so -0.123 works. + */ + t->secs = -(t->secs); + t->nsecs = -(t->nsecs); + } +} + +/* TODO: Would be nice if default FT_RELATIVE_TIME formatter was prettier */ +proto_item *dissect_relative_time(proto_tree *tree, const int hfindex, tvbuff_t *tvb, gint offset, gint length, nstime_t* t) { + proto_item *pi = NULL; + + DISSECTOR_ASSERT(t); + + /*Print in nanoseconds if <1ms for small values*/ + if (t->secs == 0 && t->nsecs < 1000000 && t->nsecs > -1000000) { + pi = proto_tree_add_time_format_value(tree, hfindex, tvb, offset, length, t, "%d nanoseconds", t->nsecs); + } else { + pi = proto_tree_add_time(tree, hfindex, tvb, offset, length, t); + } + + return pi; +} + +proto_item *dissect_ptp_timeinterval(proto_tree *tree, const int hfindex, tvbuff_t *tvb, gint offset, gint length, gint64 timeinterval) { + nstime_t t; + guint64 ti, ti_ns; + + ti = (guint64) ABS(timeinterval); + + ti += (ti & 0x8000) << 1; /* rounding */ + ti_ns = ti >> 16; + t.secs = ti_ns / NS_PER_S; + t.nsecs = ti_ns % NS_PER_S; + if (t.nsecs >= NS_PER_S) { + t.nsecs -= NS_PER_S; + t.secs += 1; + } + + if (timeinterval < 0) { + /* + * Set both signs to negative for consistency with other nstime code + * and so -0.123 works. + */ + t.secs = -(t.secs); + t.nsecs = -(t.nsecs); + } + + return dissect_relative_time(tree, hfindex, tvb, offset, length, &t); +} + static void dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *pi = NULL; @@ -1897,7 +2131,7 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Used for search entry and unknown tags */ erf_meta_hf_template_t tag_template_unknown = { 0, { "Unknown", "unknown", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }; - erf_meta_tag_info_t tag_info_local = { 0, 0, &tag_template_unknown, + erf_meta_tag_info_t tag_info_local = { 0, 0, &tag_template_unknown, &tag_template_unknown, ett_erf_meta_tag, hf_erf_meta_tag_unknown, NULL }; int offset = 0; @@ -1922,6 +2156,7 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tagtype = tvb_get_ntohs(tvb, offset); taglength = tvb_get_ntohs(tvb, offset + 2); tag_tree = NULL; + tag_pi = NULL; if (ERF_META_IS_SECTION(tagtype)) sectiontype = tagtype; @@ -2057,9 +2292,9 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tag_tree = proto_tree_add_subtree_format(section_tree, tvb, offset + 4, taglength, tag_info->ett, &tag_pi, "%s: %s %u", tag_info->tag_template->hfinfo.name, val_to_str(value32, VALS(wmem_array_get_raw(erf_meta_index.vs_list)), "Unknown Section (%u)"), tvb_get_ntohs(tvb, offset + 4 + 2)); - proto_tree_add_uint_format_value(tag_tree, tag_info->hf_value, tvb, offset + 4, MIN(2, taglength), value32, "%s (%u)", + proto_tree_add_uint_format_value(tag_tree, tag_info->extra->hf_values[0], tvb, offset + 4, MIN(2, taglength), value32, "%s (%u)", val_to_str(value32, VALS(wmem_array_get_raw(erf_meta_index.vs_abbrev_list)), "Unknown"), value32); - proto_tree_add_item(tag_tree, tag_info->extra->hf_values[0], tvb, offset + 6, MIN(2, taglength - 2), ENC_BIG_ENDIAN); + proto_tree_add_item(tag_tree, tag_info->extra->hf_values[1], tvb, offset + 6, MIN(2, taglength - 2), ENC_BIG_ENDIAN); break; case ERF_META_TAG_reset: @@ -2068,35 +2303,13 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { break; case ERF_META_TAG_if_link_status: - DISSECTOR_ASSERT(tag_info->extra); - { - const int *link_status_flags[] = { - &tag_info->extra->hf_values[0], - NULL - }; - - tag_pi = proto_tree_add_bitmask(section_tree, tvb, offset + 4, tag_info->hf_value, tag_info->ett, link_status_flags, ENC_BIG_ENDIAN); - tag_tree = proto_item_get_subtree(tag_pi); - } - break; - case ERF_META_TAG_tunneling_mode: - DISSECTOR_ASSERT(tag_info->extra); - { - const int* tunneling_mode_flags[array_length(erf_tunneling_modes)+1]; - int i; - - /* XXX: This is allowed as the array itself is not constant (not const int* const) */ - for (i = 0; i < (int) array_length(erf_tunneling_modes); i++) { - tunneling_mode_flags[i] = &tag_info->extra->hf_values[i]; - } - tunneling_mode_flags[array_length(erf_tunneling_modes)] = NULL; - - tag_pi = proto_tree_add_bitmask(section_tree, tvb, offset + 4, tag_info->hf_value, tag_info->ett, tunneling_mode_flags, ENC_BIG_ENDIAN); - tag_tree = proto_item_get_subtree(tag_pi); - } + case ERF_META_TAG_ptp_time_properties: + case ERF_META_TAG_ptp_gm_clock_quality: + tag_pi = dissect_meta_tag_bitfield(section_tree, tvb, offset, tag_info, &tag_tree); break; + case ERF_META_TAG_ns_dns_ipv4: case ERF_META_TAG_ns_dns_ipv6: case ERF_META_TAG_ns_host_ipv4: @@ -2114,19 +2327,39 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tag_tree = proto_tree_add_subtree(section_tree, tvb, offset + 4, taglength, tag_info->ett, &tag_pi, tag_info->tag_template->hfinfo.name); /* Address */ - pi = proto_tree_add_item(tag_tree, tag_info->hf_value, tvb, offset + 4, MIN(addr_len, taglength), IS_FT_INT(tag_ft) || IS_FT_UINT(tag_ft) ? ENC_BIG_ENDIAN : ENC_NA); + pi = proto_tree_add_item(tag_tree, tag_info->extra->hf_values[0], tvb, offset + 4, MIN(addr_len, taglength), IS_FT_INT(tag_ft) || IS_FT_UINT(tag_ft) ? ENC_BIG_ENDIAN : ENC_NA); /* Name */ - proto_tree_add_item(tag_tree, tag_info->extra->hf_values[0], tvb, offset + 4 + addr_len, taglength - addr_len, ENC_UTF_8); + proto_tree_add_item(tag_tree, tag_info->extra->hf_values[1], tvb, offset + 4 + addr_len, taglength - addr_len, ENC_UTF_8); if (pi) { proto_item_fill_label(PITEM_FINFO(pi), pi_label); - /* Set top level label TagName: Address Hostname */ - proto_item_append_text(tag_pi, "%s %s", pi_label /* Includes ": " */, - tvb_get_stringzpad(wmem_packet_scope(), tvb, offset + 4 + addr_len, taglength - addr_len, ENC_UTF_8)); + /* Set top level label e.g IPv4 Name: hostname Address: 1.2.3.4 */ + /* TODO: Name is unescaped here but escaped in actual field */ + proto_item_append_text(tag_pi, ": %s, %s", + tvb_get_stringzpad(wmem_packet_scope(), tvb, offset + 4 + addr_len, taglength - addr_len, ENC_UTF_8), pi_label /* Includes ": " */); } break; } + case ERF_META_TAG_ptp_offset_from_master: + case ERF_META_TAG_ptp_mean_path_delay: + value64 = tvb_get_ntoh64(tvb, offset + 4); + tag_pi = dissect_ptp_timeinterval(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, (gint64) value64); + break; + + case ERF_META_TAG_ptp_current_utc_offset: + { + nstime_t t; + + value32 = tvb_get_ntohl(tvb, offset + 4); + /* PTP value is signed */ + t.secs = (gint32) value32; + t.nsecs = 0; + + tag_pi = dissect_relative_time(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, &t); + break; + } + default: dissected = FALSE; break; @@ -2153,17 +2386,9 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint64 ts; ts = tvb_get_letoh64(tvb, offset + 4); + erf_ts_to_nstime(ts, &t, tag_ft == FT_RELATIVE_TIME); - t.secs = (long) (ts >> 32); - ts = ((ts & 0xffffffff) * 1000 * 1000 * 1000); - ts += (ts & 0x80000000) << 1; /* rounding */ - t.nsecs = ((int) (ts >> 32)); - if (t.nsecs >= 1000000000) { - t.nsecs -= 1000000000; - t.secs += 1; - } - - tag_pi = proto_tree_add_time(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, &t); + tag_pi = dissect_relative_time(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, &t); } else { tag_pi = proto_tree_add_item(section_tree, tag_info->hf_value, tvb, offset + 4, taglength, ENC_NA); } @@ -2171,8 +2396,11 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { } /* Create subtree for tag if we haven't already */ - if (!tag_tree) + if (!tag_tree) { + /* Make sure we actually put the subtree in the right place */ + DISSECTOR_ASSERT(tag_pi || !tree); tag_tree = proto_item_add_subtree(tag_pi, tag_info->ett); + } /* Add tag type field to subtree */ /* diff --git a/wiretap/erf.h b/wiretap/erf.h index bf91311025..c7d9e0ccac 100644 --- a/wiretap/erf.h +++ b/wiretap/erf.h @@ -199,6 +199,7 @@ #define ERF_META_TAG_if_link_status 81 #define ERF_META_TAG_if_phy_mode 82 #define ERF_META_TAG_if_port_type 83 +#define ERF_META_TAG_if_rx_latency 84 #define ERF_META_TAG_src_ipv4 128 #define ERF_META_TAG_dest_ipv4 129 @@ -265,6 +266,37 @@ #define ERF_META_TAG_pcap_ng_block 322 #define ERF_META_TAG_asn1 323 +#define ERF_META_TAG_clk_source 384 +#define ERF_META_TAG_clk_state 385 +#define ERF_META_TAG_clk_threshold 386 +#define ERF_META_TAG_clk_correction 387 +#define ERF_META_TAG_clk_failures 388 +#define ERF_META_TAG_clk_resyncs 389 +#define ERF_META_TAG_clk_phase_error 390 +#define ERF_META_TAG_clk_input_pulses 391 +#define ERF_META_TAG_clk_rejected_pulses 392 +#define ERF_META_TAG_clk_phc_index 393 +#define ERF_META_TAG_clk_phc_offset 394 +#define ERF_META_TAG_clk_timebase 395 +#define ERF_META_TAG_clk_descr 396 +#define ERF_META_TAG_clk_out_source 397 +#define ERF_META_TAG_clk_link_mode 398 +#define ERF_META_TAG_ptp_domain_num 399 +#define ERF_META_TAG_ptp_steps_removed 400 +#define ERF_META_TAG_ptp_offset_from_master 401 +#define ERF_META_TAG_ptp_mean_path_delay 402 +#define ERF_META_TAG_ptp_parent_identity 403 +#define ERF_META_TAG_ptp_parent_port_num 404 +#define ERF_META_TAG_ptp_gm_identity 405 +#define ERF_META_TAG_ptp_gm_clock_quality 406 +#define ERF_META_TAG_ptp_current_utc_offset 407 +#define ERF_META_TAG_ptp_time_properties 408 +#define ERF_META_TAG_ptp_time_source 409 +#define ERF_META_TAG_ptp_clock_identity 410 +#define ERF_META_TAG_ptp_port_num 411 +#define ERF_META_TAG_ptp_port_state 412 +#define ERF_META_TAG_ptp_delay_mechanism 413 +#define ERF_META_TAG_clk_port_proto 414 /* * The timestamp is 64bit unsigned fixed point little-endian value with |