[Spice-devel] wireshark codegen

Alon Levy alevy at redhat.com
Mon Sep 16 00:46:37 PDT 2013


> Opinions on this?  The end goal is to be able to generate a header that has
> both the enums and descriptions of those enum values (e.g. a mapping from
> enum to string name) that we can use for the wireshark dissector.
> Obviously, when a new channel or new message gets added to the protocol,
> there is still some manual work that needs to be done to update the
> wireshark dissector, but being able to autogenerate theses values reduces
> the maintenance burden for this part at least.

Hi Jonathon,

 I'm not sure what opinions you are looking for. The only one I have is go ahead! great work!

Alon

> 
> 
> From c6cef8747b61e203ebb8ade580dae063d581afb2 Mon Sep 17 00:00:00 2001
> From: Jonathon Jongsma <jjongsma at redhat.com>
> Date: Thu, 12 Sep 2013 12:11:02 -0500
> Subject: [PATCH] codegen: Add a --generate-wireshark-dissector option
> 
> The wireshark protocol dissector is a bit out-of-date. Several new channel
> types
> and enums have been added.  It would be nice if these values (and the
> translation between the value and the name) could be automatically generated
> so
> that updating the dissector was a slightly less manual process.  This patch
> adds
> a commandline switch which generates both the enums and value-name lists in
> the
> format that wireshark expects.
> ---
>  python_modules/codegen.py |   2 +-
>  python_modules/ptypes.py  |  17 ++++++++
>  spice_codegen.py          | 105
>  ++++++++++++++++++++++++++++++----------------
>  3 files changed, 87 insertions(+), 37 deletions(-)
> 
> diff --git a/python_modules/codegen.py b/python_modules/codegen.py
> index 009cf95..5dee0b8 100644
> --- a/python_modules/codegen.py
> +++ b/python_modules/codegen.py
> @@ -41,7 +41,7 @@ def set_prefix(prefix):
>  def prefix_underscore_upper(*args):
>      s = proto_prefix_upper
>      for arg in args:
> -        s = s + "_" + arg
> +        s = s + "_" + arg.upper()
>      return s
>  
>  def prefix_underscore_lower(*args):
> diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
> index d9fbfe2..2bfbf0d 100644
> --- a/python_modules/ptypes.py
> +++ b/python_modules/ptypes.py
> @@ -247,6 +247,23 @@ class EnumBaseType(Type):
>      def get_fixed_nw_size(self):
>          return self.bits / 8
>  
> +    # generates a value-name table suitable for use with the wireshark
> protocol
> +    # dissector
> +    def c_describe(self, writer):
> +        writer.write("static const value_string %s_vs[] = " %
> codegen.prefix_underscore_lower(self.name))
> +        writer.begin_block()
> +        values = self.names.keys()
> +        values.sort()
> +        for i in values:
> +            writer.write("{ ")
> +            writer.write(self.c_enumname(i))
> +            writer.write(", \"%s\" }," % self.names[i])
> +            writer.newline()
> +        writer.write("{ 0, NULL }")
> +        writer.end_block(semicolon=True)
> +        writer.newline()
> +
> +
>  class EnumType(EnumBaseType):
>      def __init__(self, bits, name, enums, attribute_list):
>          Type.__init__(self)
> diff --git a/spice_codegen.py b/spice_codegen.py
> index e9e64c0..de1f87b 100755
> --- a/spice_codegen.py
> +++ b/spice_codegen.py
> @@ -10,38 +10,73 @@ from python_modules import codegen
>  from python_modules import demarshal
>  from python_modules import marshal
>  
> -def write_channel_enums(writer, channel, client):
> +def write_channel_enums(writer, channel, client, describe):
>      messages = filter(lambda m : m.channel == channel, \
>                            channel.client_messages if client else
>                            channel.server_messages)
>      if len(messages) == 0:
>          return
> -    writer.begin_block("enum")
> -    i = 0
>      if client:
> -        prefix = [ "MSGC" ]
> +        prefix = [ "msgc" ]
>      else:
> -        prefix = [ "MSG" ]
> +        prefix = [ "msg" ]
>      if channel.member_name:
> -        prefix.append(channel.member_name.upper())
> +        prefix.append(channel.member_name)
> +    if not describe:
> +        writer.begin_block("enum")
> +    else:
> +        writer.begin_block("static const value_string %s_vs[] = " %
> (codegen.prefix_underscore_lower(*prefix)))
> +    i = 0
>      prefix.append(None) # To be replaced with name
>      for m in messages:
> -        prefix[-1] = m.name.upper()
> +        prefix[-1] = m.name
>          enum = codegen.prefix_underscore_upper(*prefix)
> -        if m.value == i:
> -            writer.writeln("%s," % enum)
> -            i = i + 1
> +        if describe:
> +            writer.writeln("{ %s, \"%s %s\" }," % (enum, "Client" if client
> else "Server", m.name.upper()))
>          else:
> -            writer.writeln("%s = %s," % (enum, m.value))
> -            i = m.value + 1
> -    if channel.member_name:
> -        prefix[-1] = prefix[-2]
> -        prefix[-2] = "END"
> -        writer.newline()
> -        writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix)))
> +            if m.value == i:
> +                writer.writeln("%s," % enum)
> +                i = i + 1
> +            else:
> +                writer.writeln("%s = %s," % (enum, m.value))
> +                i = m.value + 1
> +    if describe:
> +        writer.writeln("{ 0, NULL }");
> +    else:
> +        if channel.member_name:
> +            prefix[-1] = prefix[-2]
> +            prefix[-2] = "END"
> +            writer.newline()
> +            writer.writeln("%s" %
> (codegen.prefix_underscore_upper(*prefix)))
>      writer.end_block(semicolon=True)
>      writer.newline()
>  
> -def write_enums(writer):
> +def write_channel_type_enum(writer, describe=False):
> +    i = 0
> +    if describe:
> +        writer.begin_block("static const value_string channel_types_vs[] =")
> +    else:
> +        writer.begin_block("enum")
> +    for c in proto.channels:
> +        enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
> +        if describe:
> +            writer.writeln("{ %s, \"%s\" }," % (enum, c.name.upper()))
> +        else:
> +            if c.value == i:
> +                writer.writeln("%s," % enum)
> +                i = i + 1
> +            else:
> +                writer.writeln("%s = %s," % (enum, c.value))
> +                i = c.value + 1
> +    writer.newline()
> +    if describe:
> +        writer.writeln("{ 0, NULL }")
> +    else:
> +        writer.writeln("SPICE_END_CHANNEL")
> +    writer.end_block(semicolon=True)
> +    writer.newline()
> +
> +
> +def write_enums(writer, describe=False):
>      writer.writeln("#ifndef _H_SPICE_ENUMS")
>      writer.writeln("#define _H_SPICE_ENUMS")
>      writer.newline()
> @@ -52,27 +87,22 @@ def write_enums(writer):
>      for t in ptypes.get_named_types():
>          if isinstance(t, ptypes.EnumBaseType):
>              t.c_define(writer)
> +            if describe:
> +                t.c_describe(writer)
>  
> -    i = 0
> -    writer.begin_block("enum")
> -    for c in proto.channels:
> -        enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
> -        if c.value == i:
> -            writer.writeln("%s," % enum)
> -            i = i + 1
> -        else:
> -            writer.writeln("%s = %s," % (enum, c.value))
> -            i = c.value + 1
> -    writer.newline()
> -    writer.writeln("SPICE_END_CHANNEL")
> -    writer.end_block(semicolon=True)
> -    writer.newline()
> +    write_channel_type_enum(writer)
> +    if (describe):
> +        write_channel_type_enum(writer, True)
>  
>      for c in ptypes.get_named_types():
>          if not isinstance(c, ptypes.ChannelType):
>              continue
> -        write_channel_enums(writer, c, False)
> -        write_channel_enums(writer, c, True)
> +        write_channel_enums(writer, c, False, False)
> +        if describe:
> +            write_channel_enums(writer, c, False, describe)
> +        write_channel_enums(writer, c, True, False)
> +        if describe:
> +            write_channel_enums(writer, c, True, describe)
>  
>      writer.writeln("#endif /* _H_SPICE_ENUMS */")
>  
> @@ -80,6 +110,9 @@ parser = OptionParser(usage="usage: %prog [options]
> <protocol_file> <destination
>  parser.add_option("-e", "--generate-enums",
>                    action="store_true", dest="generate_enums", default=False,
>                    help="Generate enums")
> +parser.add_option("-w", "--generate-wireshark-dissector",
> +                  action="store_true", dest="generate_dissector",
> default=False,
> +                  help="Generate Wireshark dissector definitions")
>  parser.add_option("-d", "--generate-demarshallers",
>                    action="store_true", dest="generate_demarshallers",
>                    default=False,
>                    help="Generate demarshallers")
> @@ -160,8 +193,8 @@ if options.includes:
>          writer.header.writeln('#include "%s"' % i)
>          writer.writeln('#include "%s"' % i)
>  
> -if options.generate_enums:
> -    write_enums(writer)
> +if options.generate_enums or options.generate_dissector:
> +    write_enums(writer, options.generate_dissector)
>  
>  if options.generate_demarshallers:
>      if not options.server and not options.client:
> --
> 1.8.3.1
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
> 


More information about the Spice-devel mailing list