[Spice-devel] [PATCH v4 29/41] dissector: Handle flags

Frediano Ziglio fziglio at redhat.com
Thu Jul 23 08:54:46 PDT 2015


Instead of only showing the hexadecimal value show all bits.
Every bit is displayed as a different field (usually displayed
in a different line indented under the main one).
This also allows to use wireshark filter to target specific bits.

Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
 codegen/Makefile.am         |   1 +
 codegen/check_dissector     |   3 ++
 codegen/dissector_test.c    |  22 +++++++++
 codegen/out_base1.txt       |  81 +++++++++++++++++++++++++++++----
 codegen/out_flags1.txt      | 107 ++++++++++++++++++++++++++++++++++++++++++++
 codegen/test.proto          |  10 +++++
 python_modules/dissector.py |  92 ++++++++++++++++++++++++++++++++++---
 7 files changed, 300 insertions(+), 16 deletions(-)
 create mode 100644 codegen/out_flags1.txt

diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 590c5e5..50c81a1 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -63,6 +63,7 @@ EXTRA_DIST =				\
 	out_array_raw.txt		\
 	out_array_struct.txt		\
 	out_channel.txt			\
+	out_flags1.txt			\
 	$(NULL)
 
 CLEANFILES = test.c test.h enums.h dissector.c dissector.h *.trs check_dissector.txt
diff --git a/codegen/check_dissector b/codegen/check_dissector
index e2d06b5..94ce0bc 100755
--- a/codegen/check_dissector
+++ b/codegen/check_dissector
@@ -62,4 +62,7 @@ check data_u16s 1 102 out_array_struct.txt --client
 
 check data_base1 1 2 out_channel.txt
 
+# flags and descriptions
+check data_base1 1 3 out_flags1.txt
+
 exit 0
diff --git a/codegen/dissector_test.c b/codegen/dissector_test.c
index dcc0134..96b3107 100644
--- a/codegen/dissector_test.c
+++ b/codegen/dissector_test.c
@@ -254,6 +254,28 @@ expert_add_info_format(packet_info *pinfo, proto_item *pi, expert_field *eiindex
 		return;
 }
 
+WS_DLL_PUBLIC proto_tree* proto_item_add_subtree(proto_item *ti, const gint idx)
+{
+	proto_tree *res;
+
+	assert(idx >= first_tree_registered);
+	assert(idx <= last_tree_registered);
+	if (!ti)
+		return NULL;
+
+	assert(ti->tree_data == NULL);
+	assert(ti->first_child == NULL);
+	assert(ti->last_child == NULL);
+	res = calloc(1, sizeof(*res));
+	assert(res);
+	res->tree_data = (void *) res;
+	ti->first_child = res;
+	ti->last_child = res;
+	check_tree(res);
+	check_item(ti);
+	return res;
+}
+
 struct all_ti
 {
 	proto_item ti;
diff --git a/codegen/out_base1.txt b/codegen/out_base1.txt
index 7921afd..66b42bc 100644
--- a/codegen/out_base1.txt
+++ b/codegen/out_base1.txt
@@ -66,20 +66,83 @@
     Type: FT_UINT32
     Base: BASE_DEC
     --- item
-    Text: H (1)
-    Name: f8
-    Abbrev: spice2.auto.msg_base_Base1_f8
+    Text: 1 (0x1)
+    Name: F8
+    Abbrev: spice2.f8_flags
     Type: FT_UINT8
     Base: BASE_HEX
+        --- tree
+            --- item
+            Text: Not set
+            Name: K
+            Abbrev: spice2.F8_k
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Not set
+            Name: J
+            Abbrev: spice2.F8_j
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Not set
+            Name: I
+            Abbrev: spice2.F8_i
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Set
+            Name: H
+            Abbrev: spice2.F8_h
+            Type: FT_BOOLEAN
+            Base: 4
     --- item
-    Text: L (1)
-    Name: f16
-    Abbrev: spice2.auto.msg_base_Base1_f16
+    Text: 1 (0x1)
+    Name: F16
+    Abbrev: spice2.f16_flags
     Type: FT_UINT16
     Base: BASE_HEX
+        --- tree
+            --- item
+            Text: Not set
+            Name: M
+            Abbrev: spice2.F16_m
+            Type: FT_BOOLEAN
+            Base: 2
+            --- item
+            Text: Set
+            Name: L
+            Abbrev: spice2.F16_l
+            Type: FT_BOOLEAN
+            Base: 2
     --- item
-    Text: N (1)
-    Name: f32
-    Abbrev: spice2.auto.msg_base_Base1_f32
+    Text: 1 (0x1)
+    Name: F32
+    Abbrev: spice2.f32_flags
     Type: FT_UINT32
     Base: BASE_HEX
+        --- tree
+            --- item
+            Text: Not set
+            Name: Q
+            Abbrev: spice2.F32_q
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Not set
+            Name: P
+            Abbrev: spice2.F32_p
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Not set
+            Name: O
+            Abbrev: spice2.F32_o
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Set
+            Name: N
+            Abbrev: spice2.F32_n
+            Type: FT_BOOLEAN
+            Base: 4
diff --git a/codegen/out_flags1.txt b/codegen/out_flags1.txt
new file mode 100644
index 0000000..0776300
--- /dev/null
+++ b/codegen/out_flags1.txt
@@ -0,0 +1,107 @@
+--- tree
+    --- item
+    Text: 130 (0x82)
+    Name: Test flags
+    Abbrev: spice2.tests_flag
+    Type: FT_UINT8
+    Base: BASE_DEC_HEX
+        --- tree
+            --- item
+            Text: Not set
+            Name: Z
+            Abbrev: spice2.test_flags_z
+            Type: FT_BOOLEAN
+            Base: 3
+            --- item
+            Text: Set
+            Name: Y
+            Abbrev: spice2.test_flags_y
+            Type: FT_BOOLEAN
+            Base: 3
+            --- item
+            Text: Not set
+            Name: X
+            Abbrev: spice2.test_flags_x
+            Type: FT_BOOLEAN
+            Base: 3
+    --- item
+    Text: 129 (0x81)
+    Name: Test flags override
+    Abbrev: spice2.tests_flag_override
+    Type: FT_UINT8
+    Base: BASE_HEX_DEC
+        --- tree
+            --- item
+            Text: Not set
+            Name: Z
+            Abbrev: spice2.test_flags_z
+            Type: FT_BOOLEAN
+            Base: 3
+            --- item
+            Text: Not set
+            Name: Y
+            Abbrev: spice2.test_flags_y
+            Type: FT_BOOLEAN
+            Base: 3
+            --- item
+            Text: Set
+            Name: X
+            Abbrev: spice2.test_flags_x
+            Type: FT_BOOLEAN
+            Base: 3
+    --- item
+    Text: 1 (0x1)
+    Name: Test flags
+    Abbrev: spice2.tests_flag
+    Type: FT_UINT8
+    Base: BASE_HEX_DEC
+        --- tree
+            --- item
+            Text: Not set
+            Name: Z
+            Abbrev: spice2.test_flags_z
+            Type: FT_BOOLEAN
+            Base: 3
+            --- item
+            Text: Not set
+            Name: Y
+            Abbrev: spice2.test_flags_y
+            Type: FT_BOOLEAN
+            Base: 3
+            --- item
+            Text: Set
+            Name: X
+            Abbrev: spice2.test_flags_x
+            Type: FT_BOOLEAN
+            Base: 3
+    --- item
+    Text: 131 (0x83)
+    Name: flags4
+    Abbrev: spice2.auto.msg_base_Flags1_flags4
+    Type: FT_UINT8
+    Base: BASE_HEX_DEC
+        --- tree
+            --- item
+            Text: Not set
+            Name: K
+            Abbrev: spice2.F8_k
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Not set
+            Name: J
+            Abbrev: spice2.F8_j
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Set
+            Name: I
+            Abbrev: spice2.F8_i
+            Type: FT_BOOLEAN
+            Base: 4
+            --- item
+            Text: Set
+            Name: H
+            Abbrev: spice2.F8_h
+            Type: FT_BOOLEAN
+            Base: 4
diff --git a/codegen/test.proto b/codegen/test.proto
index 0f14125..6d97317 100644
--- a/codegen/test.proto
+++ b/codegen/test.proto
@@ -30,6 +30,10 @@ flags32 F32 {
 	N, O, P, Q
 };
 
+flags8 test_flags {
+    X, Y, Z
+} @ws("Test flags", tests_flag) @ws_base(DEC_HEX);
+
 struct Dummy {
     uint16 dummy;
 };
@@ -67,6 +71,12 @@ channel BaseChannel {
     message {
         uint8 channel @ws_type(CHANNEL);
     } Channel;
+    message {
+        test_flags flags1;
+        test_flags flags2 @ws("Test flags override", tests_flag_override) @ws_base(HEX_DEC);
+        test_flags flags3 @ws_base(HEX_DEC);
+        F8 flags4 @ws_base(HEX_DEC);
+    } Flags1;
     Empty empty = 100;
 
   client:
diff --git a/python_modules/dissector.py b/python_modules/dissector.py
index 6898a13..1bcefa3 100644
--- a/python_modules/dissector.py
+++ b/python_modules/dissector.py
@@ -289,7 +289,7 @@ def get_primitive_ft_type(t):
     return "FT_%sINT%d" % (unsigned, size * 8)
 
 # write a field
-def write_wireshark_field(writer, container, member, t, ws, tree, size, encoding='ENC_LITTLE_ENDIAN', prefix=''):
+def write_wireshark_field(writer, container, member, t, ws, tree, dest, size, encoding='ENC_LITTLE_ENDIAN', prefix=''):
 
     assert(member and container)
 
@@ -305,10 +305,15 @@ def write_wireshark_field(writer, container, member, t, ws, tree, size, encoding
         f_type = get_primitive_ft_type(t)
         size_name = str(t.get_fixed_nw_size() * 8)
         if isinstance(t, ptypes.FlagsType):
-            # show flag as hexadecimal for now
-            base = 'BASE_HEX'
-            assert(t.has_name())
-            vals = 'VALS(%s_vs)' % codegen.prefix_underscore_lower(t.name)
+            # if the attribute unique_flag is not set must compute
+            # all flags writing a HF for each bit
+            if t.has_attr('unique_flag'):
+                base = 'BASE_HEX'
+                assert(t.has_name())
+                vals = 'VALS(%s_vs)' % codegen.prefix_underscore_lower(t.name)
+            else:
+                write_flags(writer, container, member, t, ws, tree, dest)
+                return
         elif isinstance(t, ptypes.EnumType) or isinstance(t, ptypes.EnumBaseType):
             base = 'BASE_DEC'
             assert(t.has_name())
@@ -448,7 +453,7 @@ def write_array(writer, container, member, nelements, array, dest, scope):
     element_type = array.element_type
 
     if element_type == ptypes.uint8 or element_type == ptypes.int8:
-        write_wireshark_field(writer, container, member, array, ws, dest.level.tree, nelements, 'ENC_NA')
+        write_wireshark_field(writer, container, member, array, ws, dest.level.tree, dest, nelements, 'ENC_NA')
         writer.increment("offset", nelements)
         return
 
@@ -538,13 +543,86 @@ def write_struct(writer, member, t, index, dest, scope):
         write_struct_func(writer, t, func_name, index)
         writer.assign('offset', '%s(glb, %s, offset, %s)' % (func_name, dest.level.tree, index))
 
+
+def write_flags_func(writer, t, ws, tree, ti):
+    size = t.get_fixed_nw_size()
+    hf_name = 'hf_%s_flag%d' % (t.name, size*8)
+    func_name = 'dissect_flags%d_%s' % (size*8, t.name)
+    stmt = '%s(glb, %s, offset, %s)' % (func_name, tree, ti)
+
+    if writer.is_generated("flags", t.name):
+        return stmt
+    writer.set_is_generated("flags", t.name)
+
+    writer = writer.function_helper()
+    scope = writer.function(func_name, "proto_item *", "GlobalInfo *glb _U_, proto_tree *tree _U_, guint32 offset, proto_item *ti", True)
+    dest = RootDestination(scope)
+
+    desc = ws.desc if ws.desc else t.name
+    hf = HF(hf_name, desc)
+    hf.ws_name = ws.name if ws.name else '%s_flags' % (t.name.lower())
+    hf.f_type = get_primitive_ft_type(t)
+    hf.base = 'BASE_%s' % (ws.base if ws.base else 'HEX')
+    hf.vals = 'NULL'
+    hf.create()
+
+    with writer.if_block('ti == NULL'):
+        writer.assign('ti', 'proto_tree_add_item(tree, %s, glb->tvb, offset, %d, ENC_LITTLE_ENDIAN)' % (hf_name, size))
+    writer.assign('tree', 'proto_item_add_subtree(ti, %s)' % new_ett(writer))
+
+    values = list(t.names.keys())
+    values.sort()
+    values.reverse()
+    bits = max(values) + 1
+    for v in values:
+        name = hf_name + '_' + t.names[v].lower()
+
+        desc = t.descs[v] if t.descs[v] else t.names[v]
+        hf = HF(name, desc)
+        hf.ws_name = '%s_%s' % (t.name, t.names[v].lower())
+        hf.f_type = 'FT_BOOLEAN'
+        hf.base = str(bits)
+        hf.vals = 'TFS(&tfs_set_notset)'
+        hf.mask = t.c_enumname(v)
+        hf.create()
+
+        writer.statement('proto_tree_add_item(tree, %s, glb->tvb, offset, %d, ENC_LITTLE_ENDIAN)' % (name, size))
+
+    writer.statement('return ti');
+    writer.end_block()
+
+    return stmt
+
+
+def write_flags(writer, container, member, t, ws, tree, dest):
+    if ws.type:
+        assert False, "Attribute ws_type for member %s flag %s are ignored" % (member.name, t.name)
+
+    ws_func = WSAttributes(t)
+
+    own_ti = ws.name != ws_func.name or ws.desc != ws_func.desc or ws.base != ws_func.base
+    if not own_ti:
+        stmt = write_flags_func(writer, t, ws_func, tree, 'NULL')
+        writer.statement(stmt)
+        return
+
+    tree = dest.level.tree
+    with writer.block() as scope, dest.level:
+        scope.variable_def('proto_item *', dest.level.ti)
+        size = t.get_fixed_nw_size()
+        int_type = ptypes.IntegerType(size*8, False)
+        write_wireshark_field(writer, container, member, int_type, ws, tree, dest, size, prefix=dest.level.ti + ' = ')
+        stmt = write_flags_func(writer, t, ws_func, tree, dest.level.ti)
+        writer.statement(stmt)
+
+
 def write_member_primitive(writer, container, member, t, ws, dest, scope):
     assert(t.is_primitive())
 
     if member.has_attr("bytes_count"):
         raise NotImplementedError("bytes_count not implemented")
 
-    write_wireshark_field(writer, container, member, t, ws, dest.level.tree, t.get_fixed_nw_size())
+    write_wireshark_field(writer, container, member, t, ws, dest.level.tree, dest, t.get_fixed_nw_size())
     if member.has_attr("bytes_count"):
         dest_var = member.attributes["bytes_count"][0]
     else:
-- 
2.1.0



More information about the Spice-devel mailing list