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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
38 #include <epan/packet.h>
39 #include <epan/dissectors/packet-dcerpc.h>
42 #include "packet-pn.h"
46 static int proto_pn_ptcp = -1;
48 static int hf_pn_ptcp = -1;
49 static int hf_pn_ptcp_header = -1;
50 static int hf_pn_ptcp_block = -1;
51 static int hf_pn_ptcp_block_tlvheader = -1;
53 static int hf_pn_ptcp_res1 = -1;
54 static int hf_pn_ptcp_res2 = -1;
55 static int hf_pn_ptcp_delay10ns = -1;
56 static int hf_pn_ptcp_seq_id = -1;
57 static int hf_pn_ptcp_delay1ns_byte = -1;
58 static int hf_pn_ptcp_delay1ns_fup = -1;
59 static int hf_pn_ptcp_delay1ns = -1;
61 static int hf_pn_ptcp_tl_length = -1;
62 static int hf_pn_ptcp_tl_type = -1;
64 static int hf_pn_ptcp_master_source_address = -1;
65 static int hf_pn_ptcp_subdomain_uuid = -1;
67 static int hf_pn_ptcp_port_mac_address = -1;
69 static int hf_pn_ptcp_t2portrxdelay = -1;
70 static int hf_pn_ptcp_t3porttxdelay = -1;
72 static int hf_pn_ptcp_t2timestamp = -1;
74 static int hf_pn_ptcp_epoch_number = -1;
75 static int hf_pn_ptcp_seconds = -1;
76 static int hf_pn_ptcp_nanoseconds = -1;
78 static int hf_pn_ptcp_flags = -1;
79 static int hf_pn_ptcp_currentutcoffset = -1;
81 static int hf_pn_ptcp_master_priority1 = -1;
82 static int hf_pn_ptcp_master_priority2 = -1;
83 static int hf_pn_ptcp_clock_class = -1;
84 static int hf_pn_ptcp_clock_accuracy = -1;
85 static int hf_pn_ptcp_clockvariance = -1;
87 static int hf_pn_ptcp_oui = -1;
88 static int hf_pn_ptcp_profinet_subtype = -1;
89 static int hf_pn_ptcp_irdata_uuid = -1;
91 static gint ett_pn_ptcp = -1;
92 static gint ett_pn_ptcp_header = -1;
93 static gint ett_pn_ptcp_block = -1;
94 static gint ett_pn_ptcp_block_header = -1;
96 #define OUI_PROFINET_MULTICAST 0x010ECF /* PROFIBUS Nutzerorganisation e.V. */
99 #define PN_PTCP_BT_END 0x00
100 #define PN_PTCP_BT_SUBDOMAIN 0x01
101 #define PN_PTCP_BT_TIME 0x02
102 #define PN_PTCP_BT_TIME_EXTENSION 0x03
103 #define PN_PTCP_BT_MASTER 0x04
104 #define PN_PTCP_BT_PORT_PARAMETER 0x05
105 #define PN_PTCP_BT_DELAY_PARAMETER 0x06
106 #define PN_PTCP_BT_PORT_TIME 0x07
107 #define PN_PTCP_BT_OPTION 0x7F
108 #define PN_PTCP_BT_RTDATA 0x7F
111 static const value_string pn_ptcp_block_type[] = {
112 { PN_PTCP_BT_END, "End" },
113 { PN_PTCP_BT_SUBDOMAIN, "Subdomain"},
114 { PN_PTCP_BT_TIME, "Time"},
115 { PN_PTCP_BT_TIME_EXTENSION, "TimeExtension"},
116 { PN_PTCP_BT_MASTER, "Master"},
117 { PN_PTCP_BT_PORT_PARAMETER, "PortParameter"},
118 { PN_PTCP_BT_DELAY_PARAMETER, "DelayParameter"},
119 { PN_PTCP_BT_PORT_TIME, "PortTime"},
120 /*0x08 - 0x7E Reserved */
121 { PN_PTCP_BT_OPTION, "Organizationally Specific"},
125 static const value_string pn_ptcp_oui_vals[] = {
126 { OUI_PROFINET, "PROFINET" },
127 { OUI_PROFINET_MULTICAST, "PROFINET" },
131 static const value_string pn_ptcp_master_prio1_vals[] = {
132 { 0x01, "Primary sync. master" },
133 { 0x02, "Secondary sync. master" },
137 static const value_string pn_ptcp_master_prio1_short_vals[] = {
139 { 0x02, "Secondary" },
143 static const value_string pn_ptcp_master_prio2_vals[] = {
148 static const value_string pn_ptcp_clock_class_vals[] = {
149 { 0xFF, "Slave-only clock" },
153 static const value_string pn_ptcp_clock_accuracy_vals[] = {
155 { 0x21, "100ns (Default)" },
168 static const value_string pn_ptcp_profinet_subtype_vals[] = {
177 dissect_PNPTCP_TLVHeader(tvbuff_t *tvb, int offset,
178 packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint16 *type, guint16 *length)
185 dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_type, &tl_type);
186 *type = tl_type >> 9;
189 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_length, &tl_length);
190 *length = tl_length & 0x1FF;
197 dissect_PNPTCP_Subdomain(tvbuff_t *tvb, int offset,
198 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID)
204 /* MasterSourceAddress */
205 offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_master_source_address, mac);
208 offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_subdomain_uuid, &uuid);
210 if(u16FrameID == 0xff00 || u16FrameID == 0xff01) {
211 if (check_col(pinfo->cinfo, COL_INFO))
212 col_append_fstr(pinfo->cinfo, COL_INFO, ", Master=%02x:%02x:%02x:%02x:%02x:%02x",
213 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
216 proto_item_append_text(item, ": MasterSource=%02x:%02x:%02x:%02x:%02x:%02x",
217 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
219 proto_item_append_text(item, ", Subdomain=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
220 uuid.Data1, uuid.Data2, uuid.Data3,
221 uuid.Data4[0], uuid.Data4[1],
222 uuid.Data4[2], uuid.Data4[3],
223 uuid.Data4[4], uuid.Data4[5],
224 uuid.Data4[6], uuid.Data4[7]);
231 dissect_PNPTCP_Time(tvbuff_t *tvb, int offset,
232 packet_info *pinfo, proto_tree *tree, proto_item *item)
240 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_epoch_number, &EpochNumber);
243 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_seconds, &Seconds);
246 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_nanoseconds, &NanoSeconds);
248 proto_item_append_text(item, ": Seconds=%u NanoSeconds=%u EpochNumber=%u",
249 Seconds, NanoSeconds, EpochNumber);
251 if (check_col(pinfo->cinfo, COL_INFO))
252 col_append_fstr(pinfo->cinfo, COL_INFO, ", Time: %4us %09uns, Epoch: %u",
253 Seconds, NanoSeconds, EpochNumber);
260 dissect_PNPTCP_TimeExtension(tvbuff_t *tvb, int offset,
261 packet_info *pinfo, proto_tree *tree, proto_item *item)
264 guint16 CurrentUTCOffset;
268 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_flags, &Flags);
270 /* CurrentUTCOffset */
271 offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_currentutcoffset, &CurrentUTCOffset);
274 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
276 proto_item_append_text(item, ": Flags=0x%x, CurrentUTCOffset=%u", Flags, CurrentUTCOffset);
283 dissect_PNPTCP_Master(tvbuff_t *tvb, int offset,
284 packet_info *pinfo, proto_tree *tree, proto_item *item)
286 guint8 MasterPriority1;
287 guint8 MasterPriority2;
289 guint8 ClockAccuracy;
290 gint16 ClockVariance;
293 /* MasterPriority1 */
294 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority1, &MasterPriority1);
296 /* MasterPriority2 */
297 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority2, &MasterPriority2);
300 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clock_class, &ClockClass);
303 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clock_accuracy, &ClockAccuracy);
306 offset = dissect_pn_int16(tvb, offset, pinfo, tree, hf_pn_ptcp_clockvariance, &ClockVariance);
309 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
311 if (check_col(pinfo->cinfo, COL_INFO))
312 col_append_fstr(pinfo->cinfo, COL_INFO, ", Prio1=\"%s\"",
313 val_to_str(MasterPriority1, pn_ptcp_master_prio1_short_vals, "(Reserved: 0x%x)"));
315 proto_item_append_text(item, ": Prio1=\"%s\", Prio2=%s, Clock: Class=\"%s\", Accuracy=%s, Variance=%d",
316 val_to_str(MasterPriority1, pn_ptcp_master_prio1_short_vals, "(Reserved: 0x%x)"),
317 val_to_str(MasterPriority2, pn_ptcp_master_prio2_vals, "(Reserved: 0x%x)"),
318 val_to_str(ClockClass, pn_ptcp_clock_class_vals, "(Reserved: 0x%x)"),
319 val_to_str(ClockAccuracy, pn_ptcp_clock_accuracy_vals, "(Reserved: 0x%x)"),
327 dissect_PNPTCP_PortParameter(tvbuff_t *tvb, int offset,
328 packet_info *pinfo, proto_tree *tree, proto_item *item)
330 guint32 t2portrxdelay;
331 guint32 t3porttxdelay;
335 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
338 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t2portrxdelay, &t2portrxdelay);
341 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t3porttxdelay, &t3porttxdelay);
343 proto_item_append_text(item, ": T2PortRxDelay=%uns, T3PortTxDelay=%uns",
344 t2portrxdelay, t3porttxdelay);
346 if (check_col(pinfo->cinfo, COL_INFO))
347 col_append_fstr(pinfo->cinfo, COL_INFO, ", T2Rx=%uns, T3Tx=%uns",
348 t2portrxdelay, t3porttxdelay);
355 dissect_PNPTCP_DelayParameter(tvbuff_t *tvb, int offset,
356 packet_info *pinfo, proto_tree *tree, proto_item *item)
362 offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_port_mac_address, mac);
365 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
368 proto_item_append_text(item, ": PortMAC=%02x:%02x:%02x:%02x:%02x:%02x",
369 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
371 if (check_col(pinfo->cinfo, COL_INFO))
372 col_append_fstr(pinfo->cinfo, COL_INFO, ", PortMAC=%02x:%02x:%02x:%02x:%02x:%02x",
373 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
380 dissect_PNPTCP_PortTime(tvbuff_t *tvb, int offset,
381 packet_info *pinfo, proto_tree *tree, proto_item *item)
387 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
390 offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t2timestamp, &t2timestamp);
392 proto_item_append_text(item, ": T2TimeStamp=%uns", t2timestamp);
394 if (check_col(pinfo->cinfo, COL_INFO))
395 col_append_fstr(pinfo->cinfo, COL_INFO, ", T2TS=%uns", t2timestamp);
402 dissect_PNPTCP_Option_PROFINET(tvbuff_t *tvb, int offset,
403 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length)
408 /* OUI already dissected! */
411 offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_profinet_subtype, &subType);
417 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
420 offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_irdata_uuid, &uuid);
421 proto_item_append_text(item, ": IRDataUUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
422 uuid.Data1, uuid.Data2, uuid.Data3,
423 uuid.Data4[0], uuid.Data4[1],
424 uuid.Data4[2], uuid.Data4[3],
425 uuid.Data4[4], uuid.Data4[5],
426 uuid.Data4[6], uuid.Data4[7]);
430 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
439 dissect_PNPTCP_Option(tvbuff_t *tvb, int offset,
440 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length)
445 /* verify remaining TLV length */
450 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
455 /* OUI (organizational unique id) */
456 offset = dissect_pn_oid(tvb, offset, pinfo,tree, hf_pn_ptcp_oui, &oui);
462 case OUI_PROFINET_MULTICAST:
463 proto_item_append_text(item, ": PROFINET");
464 offset = dissect_PNPTCP_Option_PROFINET(tvb, offset, pinfo, tree, item, length);
468 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
476 dissect_PNPTCP_block(tvbuff_t *tvb, int offset,
477 packet_info *pinfo, proto_tree *tree, proto_item *item _U_, gboolean *end, guint16 u16FrameID)
482 proto_item *sub_item;
483 proto_tree *sub_tree;
484 proto_item *tlvheader_item;
485 proto_tree *tlvheader_tree;
492 sub_item = proto_tree_add_item(tree, hf_pn_ptcp_block, tvb, offset, 0, FALSE);
493 sub_tree = proto_item_add_subtree(sub_item, ett_pn_ptcp_block);
494 u32SubStart = offset;
496 /* tlvheader subtree */
497 tlvheader_item = proto_tree_add_item(sub_tree, hf_pn_ptcp_block_tlvheader, tvb, offset, 2 /* len */, FALSE);
498 tlvheader_tree = proto_item_add_subtree(tlvheader_item, ett_pn_ptcp_block_header);
500 offset = dissect_PNPTCP_TLVHeader(tvb, offset, pinfo, tlvheader_tree, sub_item, &type, &length);
502 proto_item_set_text(sub_item, "%s",
503 val_to_str(type, pn_ptcp_block_type, "Unknown"));
505 proto_item_append_text(tlvheader_item, ": Type=%s (%x), Length=%u",
506 val_to_str(type, pn_ptcp_block_type, "Unknown"), type, length);
509 case(0x00): /* End, no content */
512 case(0x01): /* Subdomain */
513 dissect_PNPTCP_Subdomain(tvb, offset, pinfo, sub_tree, sub_item, u16FrameID);
515 case(0x02): /* Time */
516 dissect_PNPTCP_Time(tvb, offset, pinfo, sub_tree, sub_item);
518 case(0x03): /* TimeExtension */
519 dissect_PNPTCP_TimeExtension(tvb, offset, pinfo, sub_tree, sub_item);
521 case(0x04): /* Master */
522 dissect_PNPTCP_Master(tvb, offset, pinfo, sub_tree, sub_item);
524 case(0x05): /* PortParameter */
525 dissect_PNPTCP_PortParameter(tvb, offset, pinfo, sub_tree, sub_item);
527 case(0x06): /* DelayParameter */
528 dissect_PNPTCP_DelayParameter(tvb, offset, pinfo, sub_tree, sub_item);
530 case(0x07): /* PortTime */
531 dissect_PNPTCP_PortTime(tvb, offset, pinfo, sub_tree, sub_item);
533 case(0x7F): /* Organizational Specific */
534 dissect_PNPTCP_Option(tvb, offset, pinfo, sub_tree, sub_item, length);
537 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
541 proto_item_set_len(sub_item, offset - u32SubStart);
548 dissect_PNPTCP_blocks(tvbuff_t *tvb, int offset,
549 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID)
551 gboolean end = FALSE;
553 /* as long as we have some bytes, try a new block */
555 offset = dissect_PNPTCP_block(tvb, offset, pinfo, tree, item, &end, u16FrameID);
563 dissect_PNPTCP_FollowUpPDU(tvbuff_t *tvb, int offset,
564 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
566 proto_item *header_item;
567 proto_tree *header_tree;
572 /* dissect the header */
573 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, FALSE);
574 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
576 /* Padding 12 bytes */
577 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12);
580 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
583 offset = dissect_pn_align4(tvb, offset, pinfo, header_tree);
586 offset = dissect_pn_int32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns_fup, &delay1ns_fup);
588 if (check_col(pinfo->cinfo, COL_INFO))
589 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11dns", name, seq_id, delay1ns_fup);
590 proto_item_append_text(item, "%s: Sequence=%u, Delay=%dns", name_short, seq_id, delay1ns_fup);
591 proto_item_append_text(header_item, ": Sequence=%u, Delay=%dns", seq_id, delay1ns_fup);
594 /* dissect the TLV blocks */
595 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
602 dissect_PNPTCP_RTSyncPDU(tvbuff_t *tvb, int offset,
603 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
605 proto_item *header_item;
606 proto_tree *header_tree;
617 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, FALSE);
618 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
621 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_res1, &res_1);
624 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_res2, &res_2);
627 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay10ns, &delay10ns);
630 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
633 offset = dissect_pn_uint8(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns_byte, &delay1ns_8);
636 offset = dissect_pn_align4(tvb, offset, pinfo, header_tree);
639 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns, &delay1ns_32);
642 offset = dissect_pn_align4(tvb, offset, pinfo, tree);
645 delay1ns_64 = ((guint64) delay10ns) * 10 + delay1ns_8 + delay1ns_32;
646 delayms = (guint32) (delay1ns_64 / (1000 * 1000));
648 if (check_col(pinfo->cinfo, COL_INFO))
649 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11" G_GINT64_MODIFIER "uns",
650 name, seq_id, delay1ns_64);
651 proto_item_append_text(item, "%s: Sequence=%u, Delay=%" G_GINT64_MODIFIER "uns",
652 name_short, seq_id, delay1ns_64);
653 proto_item_append_text(header_item, ": Sequence=%u, Delay=%" G_GINT64_MODIFIER "uns",
654 seq_id, delay1ns_64);
657 proto_item_append_text(header_item, " (%u.%03u,%03u,%03u sec)",
660 (delay10ns % (1000*100)) / 100,
661 delay10ns % 100 * 10 + delay1ns_8);
663 /* dissect the PDU */
664 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
671 dissect_PNPTCP_AnnouncePDU(tvbuff_t *tvb, int offset,
672 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
674 proto_item *header_item;
675 proto_tree *header_tree;
679 /* dissect the header */
680 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, FALSE);
681 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
683 /* Padding 12 bytes */
684 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12);
687 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
689 /* Padding 6 bytes */
690 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 6);
692 if (check_col(pinfo->cinfo, COL_INFO))
693 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u", name, seq_id);
694 proto_item_append_text(item, "%s: Sequence=%u", name_short, seq_id);
695 proto_item_append_text(header_item, ": Sequence=%u", seq_id);
698 /* dissect the PDU */
699 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
706 dissect_PNPTCP_DelayPDU(tvbuff_t *tvb, int offset,
707 packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, const char *name, const char *name_short)
709 proto_item *header_item;
710 proto_tree *header_tree;
715 /* dissect the header */
716 header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, FALSE);
717 header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
719 /* Padding 12 bytes */
720 offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12);
723 offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
726 offset = dissect_pn_align4(tvb, offset, pinfo, header_tree);
729 offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns, &delay1ns);
731 if (check_col(pinfo->cinfo, COL_INFO))
732 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11uns", name, seq_id, delay1ns);
733 proto_item_append_text(item, "%s: Sequence=%u, Delay=%uns", name_short, seq_id, delay1ns);
734 proto_item_append_text(header_item, ": Sequence=%u, Delay=%uns", seq_id, delay1ns);
737 /* dissect the PDU */
738 offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID);
744 /* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */
746 dissect_PNPTCP_Data_heur(tvbuff_t *tvb,
747 packet_info *pinfo, proto_tree *tree)
750 proto_item *item = NULL;
751 proto_tree *ptcp_tree = NULL;
754 /*proto_item *unknown_item = NULL;*/
757 /* the tvb will NOT contain the frame_id here, so get it from our private data! */
758 u16FrameID = GPOINTER_TO_UINT(pinfo->private_data);
760 /* frame id must be in valid range (acyclic Real-Time, PTCP) */
761 /* 0x0000 - 0x007F: RTSyncPDU (with follow up) */
762 /* 0x0080 - 0x00FF: RTSyncPDU (without follow up) */
763 /* 0xFF00 - 0xFF1F: AnnouncePDU */
764 /* 0xFF20 - 0xFF3F: FollowUpPDU */
765 /* 0xFF40 - 0xFF5F: Delay...PDU */
766 if ( (u16FrameID >= 0x0100 && u16FrameID < 0xFF00) || (u16FrameID > 0xFF5F) ) {
767 /* we are not interested in this packet */
771 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-PTCP");
772 col_clear(pinfo->cinfo, COL_INFO);
774 /* subtree for PTCP */
775 item = proto_tree_add_protocol_format(tree, proto_pn_ptcp, tvb, 0, 0, "PROFINET PTCP, ");
776 ptcp_tree = proto_item_add_subtree(item, ett_pn_ptcp);
777 u32SubStart = offset;
780 /* range 1 (0x0000 - 0x007F) */
781 /* 0x0000 - 0x001F reserved */
783 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync FU (Clock)", "RTSync FU (Clock)");
786 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync FU (Time)", "RTSync FU (Time)");
788 /* 0x0022 - 0x007F reserved */
790 /* range 2 (0x0080 - 0x00FF) */
792 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync (Clock)", "RTSync (Clock)");
795 offset = dissect_PNPTCP_RTSyncPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "RTSync (Time)", "RTSync (Time)");
797 /* 0x0081 - 0x00FF reserved */
799 /* range 7 (0xFF00 - 0xFF5F) */
801 offset = dissect_PNPTCP_AnnouncePDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "Announce (Clock)", "Announce (Clock)");
804 offset = dissect_PNPTCP_AnnouncePDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "Announce (Time)", "Announce (Time)");
806 /* 0xFF02 - 0xFF1F reserved */
808 offset = dissect_PNPTCP_FollowUpPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "FollowUp (Clock)", "FollowUp (Clock)");
811 offset = dissect_PNPTCP_FollowUpPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "FollowUp (Time)", "FollowUp (Time)");
813 /* 0xFF22 - 0xFF3F reserved */
815 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayReq ", "DelayReq");
818 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayRes ", "DelayRes");
821 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayFuRes ", "DelayFuRes");
824 offset = dissect_PNPTCP_DelayPDU (tvb, offset, pinfo, ptcp_tree, item, u16FrameID, "DelayRes ", "DelayRes");
826 /* 0xFF44 - 0xFF5F reserved */
828 offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_length_remaining(tvb, offset));
830 if (check_col(pinfo->cinfo, COL_INFO))
831 col_append_fstr(pinfo->cinfo, COL_INFO, "Reserved FrameID 0x%04x", u16FrameID);
833 proto_item_append_text(item, "Reserved FrameID 0x%04x", u16FrameID);
835 offset += tvb_length_remaining(tvb, offset);
838 proto_item_set_len(item, offset - u32SubStart);
845 proto_register_pn_ptcp (void)
847 static hf_register_info hf[] = {
849 { "PROFINET PTCP", "pn_ptcp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
850 { &hf_pn_ptcp_header,
851 { "Header", "pn_ptcp.header", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
853 { "Block", "pn_ptcp.block", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
854 { &hf_pn_ptcp_block_tlvheader,
855 { "TLVHeader", "pn_ptcp.tlvheader", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
858 { "Reserved 1", "pn_ptcp.res1", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
860 { "Reserved 2", "pn_ptcp.res2", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
861 { &hf_pn_ptcp_delay10ns,
862 { "Delay10ns", "pn_ptcp.delay10ns", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
863 { &hf_pn_ptcp_seq_id,
864 { "SequenceID", "pn_ptcp.sequence_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
865 { &hf_pn_ptcp_delay1ns_byte,
866 { "Delay1ns_Byte", "pn_ptcp.delay1ns_byte", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
867 { &hf_pn_ptcp_delay1ns,
868 { "Delay1ns", "pn_ptcp.delay1ns", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
869 { &hf_pn_ptcp_delay1ns_fup,
870 { "Delay1ns_FUP", "pn_ptcp.delay1ns_fup", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
872 { &hf_pn_ptcp_tl_length,
873 { "TypeLength.Length", "pn_ptcp.tl_length", FT_UINT16, BASE_DEC, 0x0, 0x1FF, NULL, HFILL }},
874 { &hf_pn_ptcp_tl_type,
875 { "TypeLength.Type", "pn_ptcp.tl_type", FT_UINT16, BASE_DEC, 0x0, 0xFE00, NULL, HFILL }},
877 { &hf_pn_ptcp_master_source_address,
878 { "MasterSourceAddress", "pn_ptcp.master_source_address", FT_ETHER, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
879 { &hf_pn_ptcp_subdomain_uuid,
880 { "SubdomainUUID", "pn_ptcp.subdomain_uuid", FT_GUID, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
882 { &hf_pn_ptcp_port_mac_address,
883 { "PortMACAddress", "pn_ptcp.port_mac_address", FT_ETHER, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
885 { &hf_pn_ptcp_t2portrxdelay,
886 { "T2PortRxDelay (ns)", "pn_ptcp.t2portrxdelay", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
887 { &hf_pn_ptcp_t3porttxdelay,
888 { "T3PortTxDelay (ns)", "pn_ptcp.t3porttxdelay", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
889 { &hf_pn_ptcp_t2timestamp,
890 { "T2TimeStamp (ns)", "pn_ptcp.t2timestamp", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
892 { &hf_pn_ptcp_epoch_number,
893 { "EpochNumber", "pn_ptcp.epoch_number", FT_UINT16, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
894 { &hf_pn_ptcp_seconds,
895 { "Seconds", "pn_ptcp.seconds", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
896 { &hf_pn_ptcp_nanoseconds,
897 { "NanoSeconds", "pn_ptcp.nanoseconds", FT_UINT32, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
900 { "Flags", "pn_ptcp.flags", FT_UINT16, BASE_HEX, 0x0, 0x0, NULL, HFILL }},
901 { &hf_pn_ptcp_currentutcoffset,
902 { "CurrentUTCOffset", "pn_ptcp.currentutcoffset", FT_UINT16, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
904 { &hf_pn_ptcp_master_priority1,
905 { "MasterPriority1", "pn_ptcp.master_priority1", FT_UINT8, BASE_DEC, VALS(pn_ptcp_master_prio1_vals), 0x0, NULL, HFILL }},
906 { &hf_pn_ptcp_master_priority2,
907 { "MasterPriority2", "pn_ptcp.master_priority2", FT_UINT8, BASE_DEC, VALS(pn_ptcp_master_prio2_vals), 0x0, NULL, HFILL }},
908 { &hf_pn_ptcp_clock_class,
909 { "ClockClass", "pn_ptcp.clock_class", FT_UINT8, BASE_DEC, VALS(pn_ptcp_clock_class_vals), 0x0, NULL, HFILL }},
910 { &hf_pn_ptcp_clock_accuracy,
911 { "ClockAccuracy", "pn_ptcp.clock_accuracy", FT_UINT8, BASE_DEC, VALS(pn_ptcp_clock_accuracy_vals), 0x0, NULL, HFILL }},
912 { &hf_pn_ptcp_clockvariance,
913 { "ClockVariance", "pn_ptcp.clockvariance", FT_INT16, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
916 { "Organizationally Unique Identifier", "pn_ptcp.oui", FT_UINT24, BASE_HEX,
917 VALS(pn_ptcp_oui_vals), 0x0, NULL, HFILL }},
918 { &hf_pn_ptcp_profinet_subtype,
919 { "Subtype", "pn_ptcp.subtype", FT_UINT8, BASE_HEX,
920 VALS(pn_ptcp_profinet_subtype_vals), 0x0, "PROFINET Subtype", HFILL }},
922 { &hf_pn_ptcp_irdata_uuid,
923 { "IRDataUUID", "pn_ptcp.irdata_uuid", FT_GUID, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
926 static gint *ett[] = {
930 &ett_pn_ptcp_block_header
932 proto_pn_ptcp = proto_register_protocol ("PROFINET PTCP", "PN-PTCP", "pn_ptcp");
933 proto_register_field_array (proto_pn_ptcp, hf, array_length (hf));
934 proto_register_subtree_array (ett, array_length (ett));
938 proto_reg_handoff_pn_ptcp (void)
940 /* register ourself as an heuristic pn-rt payload dissector */
941 heur_dissector_add("pn_rt", dissect_PNPTCP_Data_heur, proto_pn_ptcp);