Add IEEE 802.3br Frame Preemption Protocol dissector
authorAnton Glukhov <anton.a.glukhov@gmail.com>
Mon, 18 Dec 2017 15:25:18 +0000 (16:25 +0100)
committerAnders Broman <a.broman58@gmail.com>
Thu, 21 Dec 2017 11:39:24 +0000 (11:39 +0000)
Bug: 14280
Change-Id: I25444b069af4bb78db6ae5ff649596599eba2a0c
Signed-off-by: Anton Glukhov <anton.a.glukhov@gmail.com>
Reviewed-on: https://code.wireshark.org/review/24881
Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
Petri-Dish: Pascal Quantin <pascal.quantin@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
docbook/release-notes.asciidoc
epan/dissectors/.editorconfig
epan/dissectors/CMakeLists.txt
epan/dissectors/Makefile.am
epan/dissectors/packet-fpp.c [new file with mode: 0644]
wiretap/pcap-common.c
wiretap/wtap.h

index 5a6e24f9e0b88fc597e6fc2aa27806c996a27be0..15b4f487dc0e163940663c1d6a9bae83adc22094 100644 (file)
@@ -92,6 +92,7 @@ IEEE 1905.1a
 Bluetooth Mesh
 TWAMP and OWAMP
 ActiveMQ Artemis Core Protocol
+IEEE 802.3br Frame Preemption Protocol
 --sort-and-group--
 
 === Updated Protocol Support
index 11236dd7035e076b4474c38438d25afc2310013d..474d3d37fcc40f4ce89ce96b3f02d6cacf3de178 100644 (file)
@@ -735,6 +735,10 @@ indent_size = tab
 indent_style = tab
 indent_size = tab
 
+[packet-fpp.[ch]]
+indent_style = tab
+indent_size = tab
+
 [packet-fr.[ch]]
 indent_size = 2
 
index c0ae2ff396a0f13a2e8b3348f9fa22be48a2a748..480b40eae084d6fc2bef583df152c2eedb071ca6 100644 (file)
@@ -989,6 +989,7 @@ set(DISSECTOR_SRC
        ${CMAKE_CURRENT_SOURCE_DIR}/packet-foundry.c
        ${CMAKE_CURRENT_SOURCE_DIR}/packet-fp_hint.c
        ${CMAKE_CURRENT_SOURCE_DIR}/packet-fp_mux.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/packet-fpp.c
        ${CMAKE_CURRENT_SOURCE_DIR}/packet-fr.c
        ${CMAKE_CURRENT_SOURCE_DIR}/packet-fractalgeneratorprotocol.c
        ${CMAKE_CURRENT_SOURCE_DIR}/packet-frame.c
index 40331aeb6ff41b0d70c41b1295760e2ada16606c..28982e65738779321336a997e0b1aa4d4bb120a1 100644 (file)
@@ -615,6 +615,7 @@ DISSECTOR_SRC = \
        packet-foundry.c        \
        packet-fp_hint.c        \
        packet-fp_mux.c     \
+       packet-fpp.c            \
        packet-fr.c             \
        packet-fractalgeneratorprotocol.c       \
        packet-frame.c          \
diff --git a/epan/dissectors/packet-fpp.c b/epan/dissectors/packet-fpp.c
new file mode 100644 (file)
index 0000000..bc4dc3f
--- /dev/null
@@ -0,0 +1,698 @@
+/* packet-fpp.c
+ * Routines for IEEE 802.3br Frame Preemption Protocol packet disassembly
+ *
+ * Copyright 2017, Anton Glukhov <anton.a.glukhov@gmail.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <wiretap/wtap.h>
+
+#include <epan/expert.h>
+#include <epan/conversation.h>
+#include <wsutil/crc32.h>
+#include <epan/crc32-tvb.h>
+#include <epan/reassemble.h>
+#include <epan/proto_data.h>
+
+void proto_register_fpp(void);
+void proto_reg_handoff_fpp(void);
+
+static int proto_fpp = -1;
+
+static dissector_handle_t fpp_handle;
+
+static int hf_fpp_preamble = -1;
+static int hf_fpp_preamble_seventh = -1;
+static int hf_fpp_preamble_eight = -1;
+static int hf_fpp_mdata = -1;
+static int hf_fpp_crc32 = -1;
+static int hf_fpp_crc32_status = -1;
+static int hf_fpp_mcrc32 = -1;
+static int hf_fpp_mcrc32_status = -1;
+
+static expert_field ei_fpp_crc32 = EI_INIT;
+static expert_field ei_fpp_mcrc32 = EI_INIT;
+
+static gint ett_fpp = -1;
+static gint ett_fpp_preamble = -1;
+
+static reassembly_table fpp_reassembly_table;
+
+static dissector_handle_t ethl2_handle;
+
+/* Reassembly Data */
+static int hf_fpp_fragments = -1;
+static int hf_fpp_fragment = -1;
+static int hf_fpp_fragment_overlap = -1;
+static int hf_fpp_fragment_overlap_conflicts = -1;
+static int hf_fpp_fragment_multiple_tails = -1;
+static int hf_fpp_fragment_too_long_fragment = -1;
+static int hf_fpp_fragment_error = -1;
+static int hf_fpp_fragment_count = -1;
+static int hf_fpp_reassembled_in = -1;
+static int hf_fpp_reassembled_length = -1;
+static gint ett_fpp_fragment = -1;
+static gint ett_fpp_fragments = -1;
+
+static const fragment_items fpp_frag_items = {
+       /* Fragment subtrees */
+       &ett_fpp_fragment,
+       &ett_fpp_fragments,
+       /* Fragment fields */
+       &hf_fpp_fragments,
+       &hf_fpp_fragment,
+       &hf_fpp_fragment_overlap,
+       &hf_fpp_fragment_overlap_conflicts,
+       &hf_fpp_fragment_multiple_tails,
+       &hf_fpp_fragment_too_long_fragment,
+       &hf_fpp_fragment_error,
+       &hf_fpp_fragment_count,
+       /* Reassembled in field */
+       &hf_fpp_reassembled_in,
+       /* Reassembled length field */
+       &hf_fpp_reassembled_length,
+       /* Reassembled data field */
+       NULL,
+       /* Tag */
+       "fpp fragments"
+};
+
+#define FPP_PREAMBLE_LENGTH            8
+#define FPP_CRC_LENGTH                 4
+
+#define FPP_CONVERSATION_ID            0
+
+typedef enum {
+       FPP_Packet_Expess,
+       FPP_Packet_Verify,
+       FPP_Packet_Response,
+       FPP_Packet_Init,
+       FPP_Packet_Cont,
+       FPP_Packet_Invalid,
+} fpp_packet_t;
+
+typedef enum {
+       SMD_Verify                      = 0x7,
+       SMD_Respond                     = 0x19,
+       SMD_Express                     = 0xd5,
+       SMD_PP_Start_0          = 0xe6,
+       SMD_PP_Start_1          = 0x4c,
+       SMD_PP_Start_2          = 0x7f,
+       SMD_PP_Start_3          = 0xb3,
+       FragCount_0                     = SMD_PP_Start_0,
+       FragCount_1                     = SMD_PP_Start_1,
+       FragCount_2                     = SMD_PP_Start_2,
+       FragCount_3                     = SMD_PP_Start_3
+} first_delim;
+
+typedef enum {
+       Octet_0x55                      = 0x55,
+       SMD_PP_ContFrag_0       = 0x61,
+       SMD_PP_ContFrag_1       = 0x52,
+       SMD_PP_ContFrag_2       = 0x9e,
+       SMD_PP_ContFrag_3       = 0x2a,
+} second_delim;
+
+typedef enum {
+       CRC_CRC,
+       CRC_mCRC,
+       CRC_FALSE
+} fpp_crc_t;
+
+/* Packets with correct CRC sum */
+static const value_string preemptive_delim_desc[] = {
+       { SMD_PP_Start_0, "[Non-fragmented packet: SMD-S0]" },
+       { SMD_PP_Start_1, "[Non-fragmented packet: SMD-S1]" },
+       { SMD_PP_Start_2, "[Non-fragmented packet: SMD-S2]" },
+       { SMD_PP_Start_3, "[Non-fragmented packet: SMD-S3]" },
+       { 0x0, NULL }
+};
+
+/* Packets with correct mCRC sum */
+static const value_string initial_delim_desc[] = {
+       { SMD_PP_Start_0, "[Initial fragment: SMD-S0]" },
+       { SMD_PP_Start_1, "[Initial fragment: SMD-S1]" },
+       { SMD_PP_Start_2, "[Initial fragment: SMD-S2]" },
+       { SMD_PP_Start_3, "[Initial fragment: SMD-S3]" },
+       { 0x0, NULL }
+};
+
+static const value_string continuation_delim_desc[] = {
+       { SMD_PP_ContFrag_0, "[Continuation fragment: SMD-C0]" },
+       { SMD_PP_ContFrag_1, "[Continuation fragment: SMD-C1]" },
+       { SMD_PP_ContFrag_2, "[Continuation fragment: SMD-C2]" },
+       { SMD_PP_ContFrag_3, "[Continuation fragment: SMD-C3]" },
+       { 0x0, NULL }
+};
+
+static const value_string frag_count_delim_desc[] = {
+       { FragCount_0, "[#0]"},
+       { FragCount_1, "[#1]"},
+       { FragCount_2, "[#2]"},
+       { FragCount_3, "[#3]"},
+       { 0x0, NULL }
+};
+
+static fpp_crc_t
+get_crc_stat(tvbuff_t *tvb, guint32 crc, guint32 mcrc) {
+       fpp_crc_t crc_val;
+       if (tvb_get_guint32(tvb, tvb_reported_length(tvb) - FPP_CRC_LENGTH, ENC_BIG_ENDIAN) == crc) {
+               crc_val = CRC_CRC;
+       } else if (tvb_get_guint32(tvb, tvb_reported_length(tvb) - FPP_CRC_LENGTH, ENC_BIG_ENDIAN) == mcrc) {
+               crc_val = CRC_mCRC;
+       } else {
+               crc_val = CRC_FALSE;
+       }
+       return crc_val;
+}
+
+static void
+col_fstr_process(tvbuff_t *tvb, packet_info *pinfo, fpp_crc_t crc_val) {
+       if (tvb_get_guint8(tvb, 6) == Octet_0x55) {
+               if (tvb_get_guint8(tvb, 7) == SMD_Express) {
+                       col_add_str(pinfo->cinfo, COL_INFO, "[Express]");
+               } else {
+                       if ((crc_val == CRC_CRC) || (crc_val == CRC_FALSE))
+                               col_add_fstr(pinfo->cinfo, COL_INFO, "%s", try_val_to_str(tvb_get_guint8(tvb, 7), preemptive_delim_desc));
+                       else
+                               col_add_fstr(pinfo->cinfo, COL_INFO, "%s", try_val_to_str(tvb_get_guint8(tvb, 7), initial_delim_desc));
+               }
+       } else {
+               col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", try_val_to_str(tvb_get_guint8(tvb, 6), continuation_delim_desc),
+                                                                                                       try_val_to_str(tvb_get_guint8(tvb, 7), frag_count_delim_desc));
+       }
+}
+
+static fpp_packet_t
+get_packet_type(tvbuff_t *tvb) {
+       /* function analyze a packet based on preamble and ignore crc */
+       guint8 smd1 = tvb_get_guint8(tvb, 6);
+       guint8 smd2 = tvb_get_guint8(tvb, 7);
+
+       switch (smd1) {
+               case Octet_0x55:
+                       switch (smd2) {
+                               case SMD_PP_Start_0:
+                               case SMD_PP_Start_1:
+                               case SMD_PP_Start_2:
+                               case SMD_PP_Start_3:
+                                       return FPP_Packet_Init;
+                               case SMD_Verify:
+                                       return FPP_Packet_Verify;
+                               case SMD_Respond:
+                                       return FPP_Packet_Response;
+                               case SMD_Express:
+                                       return FPP_Packet_Expess;
+                               default:
+                                       return FPP_Packet_Invalid;
+                       }
+               case SMD_PP_ContFrag_0:
+               case SMD_PP_ContFrag_1:
+               case SMD_PP_ContFrag_2:
+               case SMD_PP_ContFrag_3:
+                       switch (smd2) {
+                               case FragCount_0:
+                               case FragCount_1:
+                               case FragCount_2:
+                               case FragCount_3:
+                                       return FPP_Packet_Cont;
+                               default:
+                                       return FPP_Packet_Invalid;
+                       }
+               default:
+                       return FPP_Packet_Invalid;
+       }
+
+       return FPP_Packet_Invalid;
+}
+
+struct _fpp_ctx_t {
+       gboolean preemption;
+       guint8 frame_cnt;
+       guint8 frag_cnt;
+       guint32 size;
+};
+
+typedef struct _fpp_ctx_t fpp_ctx_t;
+
+static void
+init_fpp_ctx(struct _fpp_ctx_t *ctx, guint8 frame_cnt) {
+       ctx->preemption = TRUE;
+       ctx->frame_cnt = frame_cnt;
+       ctx->frag_cnt = FragCount_3;
+       ctx->size = 0;
+}
+
+static guint8
+frag_cnt_next(guint8 cur_num) {
+       if (cur_num == FragCount_0)
+               return FragCount_1;
+       else if (cur_num == FragCount_1)
+               return FragCount_2;
+       else if (cur_num == FragCount_2)
+               return FragCount_3;
+       else if (cur_num == FragCount_3)
+               return FragCount_0;
+       else
+               return FragCount_0;
+}
+
+static guint8
+get_cont_by_start(guint8 start_cnt) {
+       if (start_cnt == SMD_PP_Start_0)
+               return SMD_PP_ContFrag_0;
+       else if (start_cnt == SMD_PP_Start_1)
+               return SMD_PP_ContFrag_1;
+       else if (start_cnt == SMD_PP_Start_2)
+               return SMD_PP_ContFrag_2;
+       else if (start_cnt == SMD_PP_Start_3)
+               return SMD_PP_ContFrag_3;
+       else
+               return SMD_PP_ContFrag_0;
+}
+
+struct _fpp_pdata_t {
+       /* struct for future possible usage */
+       guint32 offset;
+};
+
+typedef struct _fpp_pdata_t fpp_pdata_t;
+
+static void
+drop_conversation(conversation_t *conv) {
+       fpp_ctx_t *ctx;
+       ctx = (fpp_ctx_t*)conversation_get_proto_data(conv, proto_fpp);
+       if (ctx != NULL) {
+               wmem_free(wmem_file_scope(), ctx);
+       }
+       conversation_delete_proto_data(conv, proto_fpp);
+}
+
+static void
+drop_fragments(packet_info *pinfo) {
+       tvbuff_t *tvbuf;
+       tvbuf = fragment_delete(&fpp_reassembly_table, pinfo, 1, NULL);
+       if (tvbuf != NULL) {
+               tvb_free(tvbuf);
+       }
+}
+
+static tvbuff_t *
+dissect_preemption(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 crc, fpp_crc_t crc_val) {
+
+       fpp_packet_t pck_type;
+
+       guint8 smd1 = tvb_get_guint8(tvb, 6);
+       guint8 smd2 = tvb_get_guint8(tvb, 7);
+
+       guint crc_offset = tvb_reported_length(tvb) - FPP_CRC_LENGTH;
+       gint frag_size = tvb_reported_length(tvb) - FPP_PREAMBLE_LENGTH - FPP_CRC_LENGTH;
+       /* Reassembly parameters. */
+       tvbuff_t *new_tvb = NULL;
+       fragment_head *frag_data;
+       gboolean save_fragmented;
+       conversation_t *conv;
+       fpp_ctx_t *ctx;
+
+       conv = find_conversation_by_id(pinfo->num, ENDPOINT_NONE, FPP_CONVERSATION_ID, 0);
+       if (!conv) {
+               conv = conversation_new_by_id(pinfo->num, ENDPOINT_NONE, FPP_CONVERSATION_ID, 0);
+       }
+
+       /* Create a tree for the preamble. */
+       proto_item *ti_preamble = proto_tree_add_item(tree, hf_fpp_preamble, tvb, 0, FPP_PREAMBLE_LENGTH, ENC_BIG_ENDIAN);
+
+       proto_tree_add_item(tree, hf_fpp_mdata, tvb, FPP_PREAMBLE_LENGTH, frag_size, ENC_NA);
+
+       proto_tree *fpp_preamble_tree = proto_item_add_subtree(ti_preamble, ett_fpp_preamble);
+       proto_tree_add_item(fpp_preamble_tree, hf_fpp_preamble_seventh, tvb, 6, 1, ENC_BIG_ENDIAN);
+       proto_tree_add_item(fpp_preamble_tree, hf_fpp_preamble_eight, tvb, 7, 1, ENC_BIG_ENDIAN);
+
+       pck_type = get_packet_type(tvb);
+       if (pck_type == FPP_Packet_Init) {
+               if (crc_val == CRC_CRC) {
+                       /* Non-fragmented packet */
+                       drop_fragments(pinfo);
+
+                       if (!PINFO_FD_VISITED(pinfo)) {
+                               drop_conversation(conv);
+                       }
+
+                       proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_crc32, hf_fpp_crc32_status, &ei_fpp_crc32, pinfo, crc, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+
+                       return tvb_new_subset_length(tvb, FPP_PREAMBLE_LENGTH, frag_size);
+               } else if (crc_val == CRC_mCRC) {
+                       /* Init frag */
+                       drop_fragments(pinfo);
+
+                       if (!PINFO_FD_VISITED(pinfo)) {
+                               // Fist delete previous conversation
+                               drop_conversation(conv);
+                               ctx = (struct _fpp_ctx_t *)wmem_alloc(wmem_file_scope(), sizeof(struct _fpp_ctx_t));
+                               init_fpp_ctx(ctx, get_cont_by_start(smd2));
+                               ctx->size = frag_size;
+                               conversation_add_proto_data(conv, proto_fpp, ctx);
+                       }
+
+                       frag_data = fragment_add_check(&fpp_reassembly_table,
+                                                                                       tvb, FPP_PREAMBLE_LENGTH, pinfo, 1, NULL,
+                                                                                       0, frag_size, TRUE);
+
+                       set_address_tvb(&pinfo->dl_dst, AT_ETHER, 6, tvb, 8);
+                       set_address_tvb(&pinfo->dst, AT_ETHER, 6, tvb, 8);
+                       set_address_tvb(&pinfo->dl_src, AT_ETHER, 6, tvb, 14);
+                       set_address_tvb(&pinfo->src, AT_ETHER, 6, tvb, 14);
+
+                       proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_mcrc32, hf_fpp_mcrc32_status, &ei_fpp_mcrc32, pinfo, (crc ^ 0xffff0000), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+               } else {
+                       /* Invalid packet */
+                       drop_fragments(pinfo);
+
+                       if (!PINFO_FD_VISITED(pinfo)) {
+                               drop_conversation(conv);
+                       }
+
+                       proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_mcrc32, hf_fpp_mcrc32_status, &ei_fpp_mcrc32, pinfo, (crc ^ 0xffff0000), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+               }
+       } else if (pck_type == FPP_Packet_Cont) {
+               if (crc_val == CRC_mCRC) {
+                       /* Continuation frag */
+
+                       if (!PINFO_FD_VISITED(pinfo)) {
+                               ctx = (fpp_ctx_t*)conversation_get_proto_data(conv, proto_fpp);
+                               if ((ctx) && (ctx->preemption) && (ctx->frame_cnt == smd1) && (frag_cnt_next(ctx->frag_cnt) == smd2)) {
+                                       fpp_pdata_t *fpp_pdata = wmem_new(wmem_file_scope(), fpp_pdata_t);
+                                       fpp_pdata->offset = ctx->size;
+                                       p_add_proto_data(wmem_file_scope(), pinfo, proto_fpp, 0, fpp_pdata);
+
+                                       ctx->size += frag_size;
+                                       ctx->frag_cnt = smd2;
+                               } else {
+                                       // There is no conversation or ctx is wrong
+                                       drop_conversation(conv);
+                               }
+                       }
+
+                       fpp_pdata_t *fpp_pdata = (fpp_pdata_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fpp, 0);
+                       if (fpp_pdata) {
+                               frag_data = fragment_add_check(&fpp_reassembly_table,
+                                                                                               tvb, FPP_PREAMBLE_LENGTH, pinfo, 1, NULL,
+                                                                                               fpp_pdata->offset, frag_size, TRUE);
+                       } else {
+                               drop_fragments(pinfo);
+                       }
+
+                       proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_mcrc32, hf_fpp_mcrc32_status, &ei_fpp_mcrc32, pinfo, (crc ^ 0xffff0000), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+               } else {
+                       /* Suppose that the last fragment dissected
+                               1. preemption is active
+                               2. check frame count and frag count values
+                               After these steps check crc of entire reassembled frame
+                       */
+                       if (!PINFO_FD_VISITED(pinfo)) {
+                               ctx = (fpp_ctx_t*)conversation_get_proto_data(conv, proto_fpp);
+                               if ((ctx) && (ctx->preemption) && (ctx->frame_cnt == smd1) && (frag_cnt_next(ctx->frag_cnt) == smd2)) {
+                                       fpp_pdata_t *fpp_pdata = wmem_new(wmem_file_scope(), fpp_pdata_t);
+                                       fpp_pdata->offset = ctx->size;
+                                       p_add_proto_data(wmem_file_scope(), pinfo, proto_fpp, 0, fpp_pdata);
+                               }
+
+                               drop_conversation(conv);
+                       }
+
+                       fpp_pdata_t *fpp_pdata = (fpp_pdata_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fpp, 0);
+                       if (fpp_pdata) {
+                               save_fragmented = pinfo->fragmented;
+                               pinfo->fragmented = TRUE;
+                               frag_data = fragment_add_check(&fpp_reassembly_table,
+                                                                                               tvb, FPP_PREAMBLE_LENGTH, pinfo, 1, NULL,
+                                                                                               fpp_pdata->offset, frag_size, FALSE);
+                               // Attempt reassembly.
+                               new_tvb = process_reassembled_data(tvb, FPP_PREAMBLE_LENGTH, pinfo,
+                                                                                                       "Reassembled FPP", frag_data, &fpp_frag_items,
+                                                                                                       NULL, tree);
+                               pinfo->fragmented = save_fragmented;
+                       } else {
+                               drop_fragments(pinfo);
+                               proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_mcrc32, hf_fpp_mcrc32_status, &ei_fpp_mcrc32, pinfo, (crc ^ 0xffff0000), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+                       }
+
+                       if (new_tvb) {
+                               /* Reassembly was successful; return the completed datagram. */
+                               guint32 reassembled_crc = crc32_ccitt_tvb_offset(new_tvb, 0, tvb_reported_length(new_tvb));
+
+                               /* Reassembly frame takes place regardless of whether the check sum was correct or not. */
+                               proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_crc32, -1, &ei_fpp_crc32, pinfo, reassembled_crc, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+
+                               return new_tvb;
+                       } else {
+                               /* Reassembly was unsuccessful; show this fragment.  This may
+                                       just mean that we don't yet have all the fragments, so
+                                       we should not just continue dissecting. */
+                               return NULL;
+                       }
+               }
+       } else if (pck_type == FPP_Packet_Verify) {
+               proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_mcrc32, -1, &ei_fpp_mcrc32, pinfo, (crc ^ 0xffff0000), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+       } else if (pck_type == FPP_Packet_Response) {
+               proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_mcrc32, hf_fpp_mcrc32_status, &ei_fpp_mcrc32, pinfo, (crc ^ 0xffff0000), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+       }
+
+       return NULL;
+}
+
+static tvbuff_t *
+dissect_express(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 crc, fpp_crc_t crc_val) {
+
+       guint crc_offset = tvb_reported_length(tvb) - FPP_CRC_LENGTH;
+       guint offset = 0;
+       guint pdu_data_len = tvb_reported_length(tvb) - FPP_PREAMBLE_LENGTH - FPP_CRC_LENGTH;
+
+       proto_item *ti_preamble = proto_tree_add_item(tree, hf_fpp_preamble, tvb, offset, 8, ENC_BIG_ENDIAN);
+       offset += FPP_PREAMBLE_LENGTH;
+
+       proto_tree_add_item(tree, hf_fpp_mdata, tvb, offset, pdu_data_len, ENC_NA);
+
+       proto_tree *fpp_preamble_tree = proto_item_add_subtree(ti_preamble, ett_fpp_preamble);
+       proto_tree_add_item(fpp_preamble_tree, hf_fpp_preamble_seventh, tvb, 6, 1, ENC_BIG_ENDIAN);
+       proto_tree_add_item(fpp_preamble_tree, hf_fpp_preamble_eight, tvb, 7, 1, ENC_BIG_ENDIAN);
+
+       proto_tree_add_checksum(tree, tvb, crc_offset, hf_fpp_crc32, hf_fpp_crc32_status, &ei_fpp_crc32, pinfo, crc, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+
+       if (crc_val == CRC_CRC) {
+               return tvb_new_subset_length(tvb, FPP_PREAMBLE_LENGTH, pdu_data_len);
+       }
+       return NULL;
+}
+
+static int
+dissect_fpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+       guint32 crc, mcrc;
+       fpp_crc_t crc_val;
+       tvbuff_t *next = tvb;
+       guint pdu_data_len = tvb_reported_length(tvb) - FPP_PREAMBLE_LENGTH - FPP_CRC_LENGTH;
+
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "FPP");
+       col_clear(pinfo->cinfo,COL_INFO);
+
+       crc = crc32_ccitt_tvb_offset(tvb, FPP_PREAMBLE_LENGTH, pdu_data_len);
+       mcrc = crc ^ 0xffff0000;
+
+       // get crc type
+       crc_val = get_crc_stat(tvb, crc, mcrc);
+
+       // fill column Info
+       col_fstr_process(tvb, pinfo, crc_val);
+
+       proto_item *ti = proto_tree_add_item(tree, proto_fpp, tvb, 0, -1, ENC_NA);
+
+       proto_tree *fpp_tree = proto_item_add_subtree(ti, ett_fpp);
+
+       switch (get_packet_type(tvb)) {
+               case FPP_Packet_Expess:
+                       next = dissect_express(tvb, pinfo, fpp_tree, crc, crc_val);
+                       break;
+               case FPP_Packet_Init:
+               case FPP_Packet_Cont:
+               case FPP_Packet_Verify:
+               case FPP_Packet_Response:
+                       next = dissect_preemption(tvb, pinfo, fpp_tree, crc, crc_val);
+                       break;
+               default:
+                       break;
+       }
+
+       if (next) {
+               call_dissector(ethl2_handle, next, pinfo, tree);
+       } else {
+               tvbuff_t *new_tvb = tvb_new_subset_length(tvb, FPP_PREAMBLE_LENGTH, pdu_data_len);
+               call_data_dissector(new_tvb, pinfo, tree);
+       }
+       return tvb_captured_length(tvb);
+}
+
+void
+proto_register_fpp(void)
+{
+       static hf_register_info hf[] = {
+               { &hf_fpp_preamble,
+                       { "Preamble", "fpp.preamble",
+                               FT_UINT64, BASE_HEX,
+                               NULL, 0x0,
+                               NULL, HFILL }
+               },
+               { &hf_fpp_preamble_seventh,
+                       { "Seventh", "fpp.preamble.seventh",
+                               FT_UINT8, BASE_HEX,
+                               NULL, 0x0,
+                               NULL, HFILL }
+               },
+               { &hf_fpp_preamble_eight,
+                       { "Eight", "fpp.preamble.eight",
+                               FT_UINT8, BASE_HEX,
+                               NULL, 0x0,
+                               NULL, HFILL }
+               },
+               { &hf_fpp_mdata,
+                       { "mData", "fpp.mdata",
+                               FT_BYTES, BASE_NONE,
+                               NULL, 0x0,
+                               NULL, HFILL }
+               },
+               { &hf_fpp_crc32,
+                       { "CRC", "fpp.crc32",
+                               FT_UINT32, BASE_HEX,
+                               NULL, 0x0,
+                               NULL, HFILL }
+               },
+               { &hf_fpp_crc32_status,
+                       { "Checksum Status", "fpp.checksum.status",
+                               FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
+                               NULL, HFILL
+                       },
+               },
+               { &hf_fpp_mcrc32,
+                       { "mCRC", "fpp.mcrc32",
+                               FT_UINT32, BASE_HEX,
+                               NULL, 0x0,
+                               NULL, HFILL }
+               },
+               { &hf_fpp_mcrc32_status,
+                       { "Checksum Status", "fpp.checksum.status",
+                               FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
+                               NULL, HFILL
+                       },
+               },
+
+               /* Reassembly fields. */
+               { &hf_fpp_fragments,
+                       { "Message fragments", "fpp.fragments",
+                               FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_fragment,
+                       { "Message fragment", "fpp.fragment",
+                               FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_fragment_overlap,
+                       { "Message fragment overlap", "fpp.fragment.overlap",
+                               FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_fragment_overlap_conflicts,
+                       { "Message fragment overlapping with conflicting data", "fpp.fragment.overlap.conflicts",
+                               FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_fragment_multiple_tails,
+                       { "Message has multiple tail fragments", "fpp.fragment.multiple_tails",
+                               FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_fragment_too_long_fragment,
+                       { "Message fragment too long", "fpp.fragment.too_long_fragment",
+                               FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_fragment_error,
+                       { "Message defragmentation error", "fpp.fragment.error",
+                               FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_fragment_count,
+                       { "Message fragment count", "fpp.fragment.count",
+                               FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_reassembled_in,
+                       { "Reassembled in", "fpp.reassembled.in",
+                               FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+               { &hf_fpp_reassembled_length,
+                       { "Reassembled fpp length", "fpp.reassembled.length",
+                               FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+       };
+
+       /* Setup protocol subtree array */
+       static gint *ett[] = {
+               &ett_fpp,
+               &ett_fpp_preamble,
+               /* Reassembly subtrees. */
+               &ett_fpp_fragment,
+               &ett_fpp_fragments
+       };
+
+       static ei_register_info ei[] = {
+               { &ei_fpp_mcrc32,
+                       { "fpp.mcrc32_bad", PI_CHECKSUM, PI_ERROR,
+                               "Bad mCRC checksum", EXPFILL }
+               },
+               { &ei_fpp_crc32,
+                       { "fpp..crc32_bad", PI_CHECKSUM, PI_ERROR,
+                               "Bad CRC checksum", EXPFILL }
+               },
+       };
+
+       expert_module_t* expert_fpp;
+
+       proto_fpp = proto_register_protocol (
+               "IEEE 802.3br Frame Preemption Protocol",
+               "Frame Preemption Protocol",
+               "fpp"
+       );
+
+       proto_register_field_array(proto_fpp, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
+       expert_fpp = expert_register_protocol(proto_fpp);
+       expert_register_field_array(expert_fpp, ei, array_length(ei));
+
+       reassembly_table_register(&fpp_reassembly_table, &addresses_reassembly_table_functions);
+
+       fpp_handle = register_dissector("fpp", dissect_fpp, proto_fpp);
+}
+
+void
+proto_reg_handoff_fpp(void)
+{
+       dissector_add_uint("wtap_encap", WTAP_ENCAP_ETHERNET_MPACKET, fpp_handle);
+
+       ethl2_handle = find_dissector_add_dependency("eth_withoutfcs", proto_fpp);
+}
+
+/*
+ * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
index a37703ca686edb0b563260c2c88da2a06d17259b..95b416e177051c596d691d233cb509e51f9c4d0d 100644 (file)
@@ -467,6 +467,9 @@ static const struct {
        /* Nordic BLE Sniffer */
        { 272,          WTAP_ENCAP_NORDIC_BLE },
 
+       /* mPackets as specified by 802.3br */
+       { 274,          WTAP_ENCAP_ETHERNET_MPACKET },
+
        /*
         * To repeat:
         *
index 4e11751d4c1d7d803c0916e5f8dd6b126ea96750..5c3fece007455d70ce663120bfb39e8a33688f1e 100644 (file)
@@ -290,6 +290,7 @@ extern "C" {
 #define WTAP_ENCAP_MA_WFP_CAPTURE_AUTH_V4       195
 #define WTAP_ENCAP_MA_WFP_CAPTURE_AUTH_V6       196
 #define WTAP_ENCAP_JUNIPER_ST                   197
+#define WTAP_ENCAP_ETHERNET_MPACKET             198
 
 /* After adding new item here, please also add new item to encap_table_base array */