2 * Routines for PN-PTCP (PROFINET Precision Time Clock Protocol)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/dissectors/packet-dcerpc.h>
34 #include "packet-pn.h"
38 static int proto_pn_ptcp = -1;
40 static int hf_pn_ptcp_header = -1;
41 static int hf_pn_ptcp_block = -1;
42 static int hf_pn_ptcp_block_tlvheader = -1;
44 static int hf_pn_ptcp_res1 = -1;
45 static int hf_pn_ptcp_res2 = -1;
46 static int hf_pn_ptcp_delay10ns = -1;
47 static int hf_pn_ptcp_seq_id = -1;
48 static int hf_pn_ptcp_delay1ns_byte = -1;
49 static int hf_pn_ptcp_delay1ns_fup = -1;
50 static int hf_pn_ptcp_delay1ns = -1;
52 static int hf_pn_ptcp_tl_length = -1;
53 static int hf_pn_ptcp_tl_type = -1;
55 static int hf_pn_ptcp_master_source_address = -1;
56 static int hf_pn_ptcp_subdomain_uuid = -1;
58 static int hf_pn_ptcp_port_mac_address = -1;
60 static int hf_pn_ptcp_t2portrxdelay = -1;
61 static int hf_pn_ptcp_t3porttxdelay = -1;
63 static int hf_pn_ptcp_t2timestamp = -1;
65 static int hf_pn_ptcp_epoch_number = -1;
66 static int hf_pn_ptcp_seconds = -1;
67 static int hf_pn_ptcp_nanoseconds = -1;
69 static int hf_pn_ptcp_flags = -1;
70 static int hf_pn_ptcp_currentutcoffset = -1;
72 static int hf_pn_ptcp_master_priority1 = -1;
73 static int hf_pn_ptcp_master_priority2 = -1;
74 static int hf_pn_ptcp_clock_class = -1;
75 static int hf_pn_ptcp_clock_accuracy = -1;
76 static int hf_pn_ptcp_clockvariance = -1;
78 static int hf_pn_ptcp_oui = -1;
79 static int hf_pn_ptcp_profinet_subtype = -1;
80 static int hf_pn_ptcp_irdata_uuid = -1;
82 static gint ett_pn_ptcp = -1;
83 static gint ett_pn_ptcp_header = -1;
84 static gint ett_pn_ptcp_block = -1;
85 static gint ett_pn_ptcp_block_header = -1;
87 #define OUI_PROFINET_MULTICAST 0x010ECF /* PROFIBUS Nutzerorganisation e.V. */
90 #define PN_PTCP_BT_END 0x00
91 #define PN_PTCP_BT_SUBDOMAIN 0x01
92 #define PN_PTCP_BT_TIME 0x02
93 #define PN_PTCP_BT_TIME_EXTENSION 0x03
94 #define PN_PTCP_BT_MASTER 0x04
95 #define PN_PTCP_BT_PORT_PARAMETER 0x05
96 #define PN_PTCP_BT_DELAY_PARAMETER 0x06
97 #define PN_PTCP_BT_PORT_TIME 0x07
98 #define PN_PTCP_BT_OPTION 0x7F
99 #define PN_PTCP_BT_RTDATA 0x7F
102 static const value_string pn_ptcp_block_type[] = {
103 { PN_PTCP_BT_END, "End" },
104 { PN_PTCP_BT_SUBDOMAIN, "Subdomain"},
105 { PN_PTCP_BT_TIME, "Time"},
106 { PN_PTCP_BT_TIME_EXTENSION, "TimeExtension"},
107 { PN_PTCP_BT_MASTER, "Master"},
108 { PN_PTCP_BT_PORT_PARAMETER, "PortParameter"},
109 { PN_PTCP_BT_DELAY_PARAMETER, "DelayParameter"},
110 { PN_PTCP_BT_PORT_TIME, "PortTime"},
111 /*0x08 - 0x7E Reserved */
112 { PN_PTCP_BT_OPTION, "Organizationally Specific"},
116 static const value_string pn_ptcp_oui_vals[] = {
117 { OUI_PROFINET, "PROFINET" },
118 { OUI_PROFINET_MULTICAST, "PROFINET" },
122 static const value_string pn_ptcp_master_prio1_vals[] = {
123 { 0x01, "Primary sync. master" },
124 { 0x02, "Secondary sync. master" },
128 static const value_string pn_ptcp_master_prio1_short_vals[] = {
130 { 0x02, "Secondary" },
134 static const value_string pn_ptcp_master_prio2_vals[] = {
139 static const value_string pn_ptcp_clock_class_vals[] = {
140 { 0xFF, "Slave-only clock" },
144 static const value_string pn_ptcp_clock_accuracy_vals[] = {
146 { 0x21, "100ns (Default)" },
159 static const value_string pn_ptcp_profinet_subtype_vals[] = {
168 dissect_PNPTCP_TLVHeader(tvbuff_t *tvb, int offset,
169 packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint16 *type, guint16 *length)
176 dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_type, &tl_type);
177 *type = tl_type >> 9;
180 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_length, &tl_length);
181 *length = tl_length & 0x1FF;
188 dissect_PNPTCP_Subdomain(tvbuff_t *tvb, int offset,
189 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID)
195 /* MasterSourceAddress */
196 offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_master_source_address, mac);
199 offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_subdomain_uuid, &uuid);
201 if(u16FrameID == 0xff00 || u16FrameID == 0xff01) {
202 col_append_fstr(pinfo->cinfo, COL_INFO, ", Master=%02x:%02x:%02x:%02x:%02x:%02x",
203 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
206 proto_item_append_text(item, ": MasterSource=%02x:%02x:%02x:%02x:%02x:%02x",
207 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
209 proto_item_append_text(item, ", Subdomain=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
210 uuid.Data1, uuid.Data2, uuid.Data3,
211 uuid.Data4[0], uuid.Data4[1],
212 uuid.Data4[2], uuid.Data4[3],
213 uuid.Data4[4], uuid.Data4[5],
214 uuid.Data4[6], uuid.Data4[7]);
221 dissect_PNPTCP_Time(tvbuff_t *tvb, int offset,
222 packet_info *pinfo, proto_tree *tree, proto_item *item)
230 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_epoch_number, &EpochNumber);
233 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_seconds, &Seconds);
236 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_nanoseconds, &NanoSeconds);
238 proto_item_append_text(item, ": Seconds=%u NanoSeconds=%u EpochNumber=%u",
239 Seconds, NanoSeconds, EpochNumber);
241 col_append_fstr(pinfo->cinfo, COL_INFO, ", Time: %4us %09uns, Epoch: %u",
242 Seconds, NanoSeconds, EpochNumber);
249 dissect_PNPTCP_TimeExtension(tvbuff_t *tvb, int offset,
250 packet_info *pinfo, proto_tree *tree, proto_item *item)
253 guint16 CurrentUTCOffset;
257 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_flags, &Flags);
259 /* CurrentUTCOffset */
260 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_currentutcoffset, &CurrentUTCOffset);
263 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
265 proto_item_append_text(item, ": Flags=0x%x, CurrentUTCOffset=%u", Flags, CurrentUTCOffset);
272 dissect_PNPTCP_Master(tvbuff_t *tvb, int offset,
273 packet_info *pinfo, proto_tree *tree, proto_item *item)
275 guint8 MasterPriority1;
276 guint8 MasterPriority2;
278 guint8 ClockAccuracy;
279 gint16 ClockVariance;
282 /* MasterPriority1 */
283 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority1, &MasterPriority1);
285 /* MasterPriority2 */
286 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority2, &MasterPriority2);
289 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clock_class, &ClockClass);
292 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clock_accuracy, &ClockAccuracy);
295 offset = dissect_pn_int16(tvb, offset, pinfo, tree, hf_pn_ptcp_clockvariance, &ClockVariance);
298 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
300 col_append_fstr(pinfo->cinfo, COL_INFO, ", Prio1=\"%s\"",
301 val_to_str(MasterPriority1, pn_ptcp_master_prio1_short_vals, "(Reserved: 0x%x)"));
303 proto_item_append_text(item, ": Prio1=\"%s\", Prio2=%s, Clock: Class=\"%s\", Accuracy=%s, Variance=%d",
304 val_to_str(MasterPriority1, pn_ptcp_master_prio1_short_vals, "(Reserved: 0x%x)"),
305 val_to_str(MasterPriority2, pn_ptcp_master_prio2_vals, "(Reserved: 0x%x)"),
306 val_to_str(ClockClass, pn_ptcp_clock_class_vals, "(Reserved: 0x%x)"),
307 val_to_str(ClockAccuracy, pn_ptcp_clock_accuracy_vals, "(Reserved: 0x%x)"),
315 dissect_PNPTCP_PortParameter(tvbuff_t *tvb, int offset,
316 packet_info *pinfo, proto_tree *tree, proto_item *item)
318 guint32 t2portrxdelay;
319 guint32 t3porttxdelay;
323 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
326 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t2portrxdelay, &t2portrxdelay);
329 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t3porttxdelay, &t3porttxdelay);
331 proto_item_append_text(item, ": T2PortRxDelay=%uns, T3PortTxDelay=%uns",
332 t2portrxdelay, t3porttxdelay);
334 col_append_fstr(pinfo->cinfo, COL_INFO, ", T2Rx=%uns, T3Tx=%uns",
335 t2portrxdelay, t3porttxdelay);
342 dissect_PNPTCP_DelayParameter(tvbuff_t *tvb, int offset,
343 packet_info *pinfo, proto_tree *tree, proto_item *item)
349 offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_port_mac_address, mac);
352 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
355 proto_item_append_text(item, ": PortMAC=%02x:%02x:%02x:%02x:%02x:%02x",
356 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
358 col_append_fstr(pinfo->cinfo, COL_INFO, ", PortMAC=%02x:%02x:%02x:%02x:%02x:%02x",
359 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
366 dissect_PNPTCP_PortTime(tvbuff_t *tvb, int offset,
367 packet_info *pinfo, proto_tree *tree, proto_item *item)
373 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
376 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t2timestamp, &t2timestamp);
378 proto_item_append_text(item, ": T2TimeStamp=%uns", t2timestamp);
380 col_append_fstr(pinfo->cinfo, COL_INFO, ", T2TS=%uns", t2timestamp);
387 dissect_PNPTCP_Option_PROFINET(tvbuff_t *tvb, int offset,
388 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length)
393 /* OUI already dissected! */
396 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_profinet_subtype, &subType);
402 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
405 offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_irdata_uuid, &uuid);
406 proto_item_append_text(item, ": IRDataUUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
407 uuid.Data1, uuid.Data2, uuid.Data3,
408 uuid.Data4[0], uuid.Data4[1],
409 uuid.Data4[2], uuid.Data4[3],
410 uuid.Data4[4], uuid.Data4[5],
411 uuid.Data4[6], uuid.Data4[7]);
415 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
424 dissect_PNPTCP_Option(tvbuff_t *tvb, int offset,
425 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length)
430 /* verify remaining TLV length */
435 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
440 /* OUI (organizational unique id) */
441 offset = dissect_pn_oid(tvb, offset, pinfo,tree, hf_pn_ptcp_oui, &oui);
447 case OUI_PROFINET_MULTICAST:
448 proto_item_append_text(item, ": PROFINET");
449 offset = dissect_PNPTCP_Option_PROFINET(tvb, offset, pinfo, tree, item, length);
453 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
461 dissect_PNPTCP_block(tvbuff_t *tvb, int offset,
462 packet_info *pinfo, proto_tree *tree, proto_item *item _U_, gboolean *end, guint16 u16FrameID)
467 proto_item *sub_item;
468 proto_tree *sub_tree;
469 proto_item *tlvheader_item;
470 proto_tree *tlvheader_tree;
477 sub_item = proto_tree_add_item(tree, hf_pn_ptcp_block, tvb, offset, 0, ENC_NA);
478 sub_tree = proto_item_add_subtree(sub_item, ett_pn_ptcp_block);
479 u32SubStart = offset;
481 /* tlvheader subtree */
482 tlvheader_item = proto_tree_add_item(sub_tree, hf_pn_ptcp_block_tlvheader, tvb, offset, 2 /* len */, ENC_NA);
483 tlvheader_tree = proto_item_add_subtree(tlvheader_item, ett_pn_ptcp_block_header);
485 offset = dissect_PNPTCP_TLVHeader(tvb, offset, pinfo, tlvheader_tree, sub_item, &type, &length);
487 proto_item_set_text(sub_item, "%s",
488 val_to_str(type, pn_ptcp_block_type, "Unknown"));
490 proto_item_append_text(tlvheader_item, ": Type=%s (%x), Length=%u",
491 val_to_str(type, pn_ptcp_block_type, "Unknown"), type, length);
494 case(0x00): /* End, no content */
497 case(0x01): /* Subdomain */
498 dissect_PNPTCP_Subdomain(tvb, offset, pinfo, sub_tree, sub_item, u16FrameID);
500 case(0x02): /* Time */
501 dissect_PNPTCP_Time(tvb, offset, pinfo, sub_tree, sub_item);
503 case(0x03): /* TimeExtension */
504 dissect_PNPTCP_TimeExtension(tvb, offset, pinfo, sub_tree, sub_item);
506 case(0x04): /* Master */
507 dissect_PNPTCP_Master(tvb, offset, pinfo, sub_tree, sub_item);
509 case(0x05): /* PortParameter */
510 dissect_PNPTCP_PortParameter(tvb, offset, pinfo, sub_tree, sub_item);
512 case(0x06): /* DelayParameter */
513 dissect_PNPTCP_DelayParameter(tvb, offset, pinfo, sub_tree, sub_item);
515 case(0x07): /* PortTime */
516 dissect_PNPTCP_PortTime(tvb, offset, pinfo, sub_tree, sub_item);
518 case(0x7F): /* Organizational Specific */
519 dissect_PNPTCP_Option(tvb, offset, pinfo, sub_tree, sub_item, length);
522 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
526 proto_item_set_len(sub_item, offset - u32SubStart);
533 dissect_PNPTCP_blocks(tvbuff_t *tvb, int offset,
534 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID)
536 gboolean end = FALSE;
538 /* as long as we have some bytes, try a new block */
540 offset = dissect_PNPTCP_block(tvb, offset, pinfo, tree, item, &end, u16FrameID);
548 dissect_PNPTCP_FollowUpPDU(tvbuff_t *tvb, int offset,
549 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
551 proto_item *header_item;
552 proto_tree *header_tree;
557 /* dissect the header */
558 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA);
559 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
561 /* Padding 12 bytes */
562 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12);
565 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
568 offset = dissect_pn_align4(tvb, offset, pinfo, header_tree);
571 offset = dissect_pn_int32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns_fup, &delay1ns_fup);
573 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11dns", name, seq_id, delay1ns_fup);
574 proto_item_append_text(item, "%s: Sequence=%u, Delay=%dns", name_short, seq_id, delay1ns_fup);
575 proto_item_append_text(header_item, ": Sequence=%u, Delay=%dns", seq_id, delay1ns_fup);
578 /* dissect the TLV blocks */
579 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
586 dissect_PNPTCP_RTSyncPDU(tvbuff_t *tvb, int offset,
587 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
589 proto_item *header_item;
590 proto_tree *header_tree;
601 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA);
602 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
605 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_res1, &res_1);
608 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_res2, &res_2);
611 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay10ns, &delay10ns);
614 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
617 offset = dissect_pn_uint8(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns_byte, &delay1ns_8);
620 offset = dissect_pn_align4(tvb, offset, pinfo, header_tree);
623 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns, &delay1ns_32);
626 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
629 delay1ns_64 = ((guint64) delay10ns) * 10 + delay1ns_8 + delay1ns_32;
630 delayms = (guint32) (delay1ns_64 / (1000 * 1000));
632 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11" G_GINT64_MODIFIER "uns",
633 name, seq_id, delay1ns_64);
634 proto_item_append_text(item, "%s: Sequence=%u, Delay=%" G_GINT64_MODIFIER "uns",
635 name_short, seq_id, delay1ns_64);
636 proto_item_append_text(header_item, ": Sequence=%u, Delay=%" G_GINT64_MODIFIER "uns",
637 seq_id, delay1ns_64);
640 proto_item_append_text(header_item, " (%u.%03u,%03u,%03u sec)",
643 (delay10ns % (1000*100)) / 100,
644 delay10ns % 100 * 10 + delay1ns_8);
646 /* dissect the PDU */
647 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
654 dissect_PNPTCP_AnnouncePDU(tvbuff_t *tvb, int offset,
655 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
657 proto_item *header_item;
658 proto_tree *header_tree;
662 /* dissect the header */
663 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA);
664 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
666 /* Padding 12 bytes */
667 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12);
670 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
672 /* Padding 6 bytes */
673 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 6);
675 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u", name, seq_id);
676 proto_item_append_text(item, "%s: Sequence=%u", name_short, seq_id);
677 proto_item_append_text(header_item, ": Sequence=%u", seq_id);
680 /* dissect the PDU */
681 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
688 dissect_PNPTCP_DelayPDU(tvbuff_t *tvb, int offset,
689 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
691 proto_item *header_item;
692 proto_tree *header_tree;
697 /* dissect the header */
698 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA);
699 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
701 /* Padding 12 bytes */
702 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12);
705 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
708 offset = dissect_pn_align4(tvb, offset, pinfo, header_tree);
711 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns, &delay1ns);
713 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11uns", name, seq_id, delay1ns);
714 proto_item_append_text(item, "%s: Sequence=%u, Delay=%uns", name_short, seq_id, delay1ns);
715 proto_item_append_text(header_item, ": Sequence=%u, Delay=%uns", seq_id, delay1ns);
718 /* dissect the PDU */
719 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
725 /* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */
727 dissect_PNPTCP_Data_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
731 proto_item *item = NULL;
732 proto_tree *ptcp_tree = NULL;
735 /*proto_item *unknown_item = NULL;*/
738 /* the tvb will NOT contain the frame_id here, so get it from our private data! */
739 u16FrameID = GPOINTER_TO_UINT(pinfo->private_data);
741 /* frame id must be in valid range (acyclic Real-Time, PTCP) */
742 /* 0x0000 - 0x007F: RTSyncPDU (with follow up) */
743 /* 0x0080 - 0x00FF: RTSyncPDU (without follow up) */
744 /* 0xFF00 - 0xFF1F: AnnouncePDU */
745 /* 0xFF20 - 0xFF3F: FollowUpPDU */
746 /* 0xFF40 - 0xFF5F: Delay...PDU */
747 if ( (u16FrameID >= 0x0100 && u16FrameID < 0xFF00) || (u16FrameID > 0xFF5F) ) {
748 /* we are not interested in this packet */
752 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-PTCP");
753 col_clear(pinfo->cinfo, COL_INFO);
755 /* subtree for PTCP */
756 item = proto_tree_add_protocol_format(tree, proto_pn_ptcp, tvb, 0, 0, "PROFINET PTCP, ");
757 ptcp_tree = proto_item_add_subtree(item, ett_pn_ptcp);
758 u32SubStart = offset;
761 /* range 1 (0x0000 - 0x007F) */
762 /* 0x0000 - 0x001F reserved */
764 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync FU (Clock)", "RTSync FU (Clock)");
767 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync FU (Time)", "RTSync FU (Time)");
769 /* 0x0022 - 0x007F reserved */
771 /* range 2 (0x0080 - 0x00FF) */
773 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync (Clock)", "RTSync (Clock)");
776 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync (Time)", "RTSync (Time)");
778 /* 0x0081 - 0x00FF reserved */
780 /* range 7 (0xFF00 - 0xFF5F) */
782 offset = dissect_PNPTCP_AnnouncePDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "Announce (Clock)", "Announce (Clock)");
785 offset = dissect_PNPTCP_AnnouncePDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "Announce (Time)", "Announce (Time)");
787 /* 0xFF02 - 0xFF1F reserved */
789 offset = dissect_PNPTCP_FollowUpPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "FollowUp (Clock)", "FollowUp (Clock)");
792 offset = dissect_PNPTCP_FollowUpPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "FollowUp (Time)", "FollowUp (Time)");
794 /* 0xFF22 - 0xFF3F reserved */
796 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayReq ", "DelayReq");
799 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayRes ", "DelayRes");
802 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayFuRes ", "DelayFuRes");
805 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayRes ", "DelayRes");
807 /* 0xFF44 - 0xFF5F reserved */
809 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_length_remaining(tvb, offset));
811 col_append_fstr(pinfo->cinfo, COL_INFO, "Reserved FrameID 0x%04x", u16FrameID);
813 proto_item_append_text(item, "Reserved FrameID 0x%04x", u16FrameID);
815 offset += tvb_length_remaining(tvb, offset);
818 proto_item_set_len(item, offset - u32SubStart);
825 proto_register_pn_ptcp (void)
827 static hf_register_info hf[] = {
828 { &hf_pn_ptcp_header,
829 { "Header", "pn_ptcp.header", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
831 { "Block", "pn_ptcp.block", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
832 { &hf_pn_ptcp_block_tlvheader,
833 { "TLVHeader", "pn_ptcp.tlvheader", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
836 { "Reserved 1", "pn_ptcp.res1", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
838 { "Reserved 2", "pn_ptcp.res2", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
839 { &hf_pn_ptcp_delay10ns,
840 { "Delay10ns", "pn_ptcp.delay10ns", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
841 { &hf_pn_ptcp_seq_id,
842 { "SequenceID", "pn_ptcp.sequence_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
843 { &hf_pn_ptcp_delay1ns_byte,
844 { "Delay1ns_Byte", "pn_ptcp.delay1ns_byte", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
845 { &hf_pn_ptcp_delay1ns,
846 { "Delay1ns", "pn_ptcp.delay1ns", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
847 { &hf_pn_ptcp_delay1ns_fup,
848 { "Delay1ns_FUP", "pn_ptcp.delay1ns_fup", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
850 { &hf_pn_ptcp_tl_length,
851 { "TypeLength.Length", "pn_ptcp.tl_length", FT_UINT16, BASE_DEC, 0x0, 0x1FF, NULL, HFILL }},
852 { &hf_pn_ptcp_tl_type,
853 { "TypeLength.Type", "pn_ptcp.tl_type", FT_UINT16, BASE_DEC, 0x0, 0xFE00, NULL, HFILL }},
855 { &hf_pn_ptcp_master_source_address,
856 { "MasterSourceAddress", "pn_ptcp.master_source_address", FT_ETHER, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
857 { &hf_pn_ptcp_subdomain_uuid,
858 { "SubdomainUUID", "pn_ptcp.subdomain_uuid", FT_GUID, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
860 { &hf_pn_ptcp_port_mac_address,
861 { "PortMACAddress", "pn_ptcp.port_mac_address", FT_ETHER, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
863 { &hf_pn_ptcp_t2portrxdelay,
864 { "T2PortRxDelay (ns)", "pn_ptcp.t2portrxdelay", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
865 { &hf_pn_ptcp_t3porttxdelay,
866 { "T3PortTxDelay (ns)", "pn_ptcp.t3porttxdelay", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
867 { &hf_pn_ptcp_t2timestamp,
868 { "T2TimeStamp (ns)", "pn_ptcp.t2timestamp", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
870 { &hf_pn_ptcp_epoch_number,
871 { "EpochNumber", "pn_ptcp.epoch_number", FT_UINT16, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
872 { &hf_pn_ptcp_seconds,
873 { "Seconds", "pn_ptcp.seconds", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
874 { &hf_pn_ptcp_nanoseconds,
875 { "NanoSeconds", "pn_ptcp.nanoseconds", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
878 { "Flags", "pn_ptcp.flags", FT_UINT16, BASE_HEX, 0x0, 0x0, NULL, HFILL }},
879 { &hf_pn_ptcp_currentutcoffset,
880 { "CurrentUTCOffset", "pn_ptcp.currentutcoffset", FT_UINT16, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
882 { &hf_pn_ptcp_master_priority1,
883 { "MasterPriority1", "pn_ptcp.master_priority1", FT_UINT8, BASE_DEC, VALS(pn_ptcp_master_prio1_vals), 0x0, NULL, HFILL }},
884 { &hf_pn_ptcp_master_priority2,
885 { "MasterPriority2", "pn_ptcp.master_priority2", FT_UINT8, BASE_DEC, VALS(pn_ptcp_master_prio2_vals), 0x0, NULL, HFILL }},
886 { &hf_pn_ptcp_clock_class,
887 { "ClockClass", "pn_ptcp.clock_class", FT_UINT8, BASE_DEC, VALS(pn_ptcp_clock_class_vals), 0x0, NULL, HFILL }},
888 { &hf_pn_ptcp_clock_accuracy,
889 { "ClockAccuracy", "pn_ptcp.clock_accuracy", FT_UINT8, BASE_DEC, VALS(pn_ptcp_clock_accuracy_vals), 0x0, NULL, HFILL }},
890 { &hf_pn_ptcp_clockvariance,
891 { "ClockVariance", "pn_ptcp.clockvariance", FT_INT16, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
894 { "Organizationally Unique Identifier", "pn_ptcp.oui", FT_UINT24, BASE_HEX,
895 VALS(pn_ptcp_oui_vals), 0x0, NULL, HFILL }},
896 { &hf_pn_ptcp_profinet_subtype,
897 { "Subtype", "pn_ptcp.subtype", FT_UINT8, BASE_HEX,
898 VALS(pn_ptcp_profinet_subtype_vals), 0x0, "PROFINET Subtype", HFILL }},
900 { &hf_pn_ptcp_irdata_uuid,
901 { "IRDataUUID", "pn_ptcp.irdata_uuid", FT_GUID, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
904 static gint *ett[] = {
908 &ett_pn_ptcp_block_header
910 proto_pn_ptcp = proto_register_protocol ("PROFINET PTCP", "PN-PTCP", "pn_ptcp");
911 proto_register_field_array (proto_pn_ptcp, hf, array_length (hf));
912 proto_register_subtree_array (ett, array_length (ett));
916 proto_reg_handoff_pn_ptcp (void)
918 /* register ourself as an heuristic pn-rt payload dissector */
919 heur_dissector_add("pn_rt", dissect_PNPTCP_Data_heur, proto_pn_ptcp);