Merge into master from pull request #111:
Adding handling of OF_STATS messages (https://github.com/floodlight/loxigen/pull/111)
diff --git a/wireshark_gen/field_info.py b/wireshark_gen/field_info.py
index 4a80a8e..ec81665 100644
--- a/wireshark_gen/field_info.py
+++ b/wireshark_gen/field_info.py
@@ -113,9 +113,52 @@
     ('of_instruction_write_actions', 'type'): 'ofp_instruction_type',
     ('of_group_mod', 'group_type'): 'ofp_group_type',
     ('of_group_mod', 'type'): 'ofp_type',
-    ('of_group_mod', 'command'): 'ofp_group_mod_commane',
+    ('of_group_mod', 'command'): 'ofp_group_mod_command',
     ('of_group_mod', 'group_id'): 'ofp_group',
-
+    ('of_packet_out', 'type'): 'ofp_type',
+    ('of_packet_in', 'type'): 'ofp_type',
+    ('of_packet_in', 'reason'): 'ofp_packet_in_reason',
+    ('of_flow_stats_request', 'type'): 'ofp_type',
+    ('of_flow_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_desc_stats_request', 'type'): 'ofp_type',
+    ('of_desc_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_queue_stats_request', 'type'): 'ofp_type',
+    ('of_queue_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_port_stats_request', 'type'): 'ofp_type',
+    ('of_port_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_table_stats_request', 'type'): 'ofp_type',
+    ('of_table_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_port_desc_stats_request', 'type'): 'ofp_type',
+    ('of_port_desc_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_meter_stats_request', 'type'): 'ofp_type',
+    ('of_meter_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_meter_features_stats_request', 'type'): 'ofp_type',
+    ('of_meter_features_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_meter_config_stats_request', 'type'): 'ofp_type',
+    ('of_meter_config_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_group_stats_request', 'type'): 'ofp_type',
+    ('of_group_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_group_features_stats_request', 'type'): 'ofp_type',
+    ('of_group_features_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_group_desc_stats_request', 'type'): 'ofp_type',
+    ('of_group_desc_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_aggregate_stats_request', 'type'): 'ofp_type',
+    ('of_aggregate_stats_request', 'stats_type'): 'ofp_stats_type',
+    ('of_async_get_request', 'type'): 'ofp_type',
+    ('of_flow_stats_reply', 'type'): 'ofp_type',
+    ('of_flow_stats_reply', 'stats_type'): 'ofp_stats_type',
+    ('of_desc_stats_reply', 'type'): 'ofp_type',
+    ('of_desc_stats_reply', 'stats_type'): 'ofp_stats_type',
+    ('of_queue_stats_reply', 'type'): 'ofp_type',
+    ('of_queue_stats_reply', 'stats_type'): 'ofp_stats_type',
+    ('of_port_stats_reply', 'type'): 'ofp_type',
+    ('of_port_stats_reply', 'stats_type'): 'ofp_stats_type',
+    ('of_table_stats_reply', 'type'): 'ofp_type',
+    ('of_table_stats_reply', 'stats_type'): 'ofp_stats_type',
+    ('of_port_desc_stats_reply', 'type'): 'ofp_type',
+    ('of_port_desc_stats_reply', 'stats_type'): 'ofp_stats_type',
+    ('of_aggregate_stats_reply', 'type'): 'ofp_type',
+    ('of_aggregate_stats_reply', 'stats_type'): 'ofp_stats_type',
 }
 
 # Override oftype_to_base for certain field names
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index 4f5d7f9..9a5e4fa 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -81,6 +81,10 @@
     end
 end
 
+function read_of_port_name_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 16)
+end
+
 function read_of_mac_addr_t(reader, version, subtree, field_name)
     read_scalar(reader, subtree, field_name, 6)
 end
@@ -106,10 +110,30 @@
         return
     end
 
-    local list = subtree:add(fields[field_name], reader.peek_all(0))
-    while not reader.is_empty() do
-        local action_len = reader.peek(2, 2):uint()
-        local child_reader = reader.slice(action_len)
+    local list_len = 0
+
+    if string.find(field_name,'packet_out') then
+        if version == 1 then
+            list_len = reader.peek(-2,2):uint()
+        else
+            list_len = reader.peek(-8,2):uint()
+        end
+    end
+
+    local list = nil
+    local reader2 = nil
+
+    if list_len == 0 then
+        list = subtree:add(fields[field_name], reader.peek_all(0))
+        reader2 = reader
+    else
+        list = subtree:add(fields[field_name], reader.peek(0, list_len))
+        reader2 = reader.slice(list_len)
+    end
+
+    while not reader2.is_empty() do
+        local action_len = reader2.peek(2, 2):uint()
+        local child_reader = reader2.slice(action_len)
         local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
         local info = dissect_of_action(child_reader, child_subtree, version)
         child_subtree:set_text(info)
@@ -118,11 +142,91 @@
 end
 
 function read_list_of_port_desc_t(reader, version, subtree, field_name)
-    -- TODO
+    if reader.is_empty() then
+        return
+    end
+    local list = subtree:add(fields[field_name], reader.peek_all(0))
+    list:set_text("List of port descriptions")
+    while not reader.is_empty() do
+        local port_desc_len = 64
+        local child_reader = reader.slice(port_desc_len)
+        local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_port_desc(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
+end
+
+function read_list_of_flow_stats_entry_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local list = subtree:add(fields[field_name], reader.peek_all(0))
+    list:set_text("List of flow stats entries")
+    while not reader.is_empty() do
+        local stats_len = reader.peek(0,2):uint()
+        local child_reader = reader.slice(stats_len)
+        local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_flow_stats_entry(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
+end
+
+function read_list_of_port_stats_entry_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local list = subtree:add(fields[field_name], reader.peek_all(0))
+    list:set_text("List of port stats entries")
+    while not reader.is_empty() do
+        local stats_len = 112
+        local child_reader = reader.slice(stats_len)
+        local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_port_stats_entry(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
+end
+
+function read_list_of_table_stats_entry_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local list = subtree:add(fields[field_name], reader.peek_all(0))
+    list:set_text("List of table stats entries")
+    while not reader.is_empty() do
+        local stats_len = 24
+        local child_reader = reader.slice(stats_len)
+        local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_table_stats_entry(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
+end
+
+function read_list_of_queue_stats_entry_t(reader, version, subtree, field_name)
+    if reader.is_empty() then
+        return
+    end
+    local list = subtree:add(fields[field_name], reader.peek_all(0))
+    list:set_text("List of flow stats entries")
+    while not reader.is_empty() do
+        local stats_len = 40
+        local child_reader = reader.slice(stats_len)
+        local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+        local info = dissect_of_queue_stats_entry(child_reader, child_subtree, version)
+        child_subtree:set_text(info)
+    end
 end
 
 function read_list_of_packet_queue_t(reader, version, subtree, field_name)
     -- TODO
+    read_of_octets_t()
+end
+
+function read_of_desc_str_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 256)
+end
+
+function read_of_serial_num_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 32)
 end
 
 function read_list_of_oxm_t(reader, version, subtree, field_name)
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
index f2791d1..841e502 100644
--- a/wireshark_gen/templates/openflow.lua
+++ b/wireshark_gen/templates/openflow.lua
@@ -125,6 +125,48 @@
 :: #endfor
 }
 
+local of_port_desc_dissectors = {
+:: for version in ir:
+    [${version}] = dissect_of_port_desc_v${version},
+:: #endfor
+}
+
+local of_stats_reply_dissectors = {
+:: for version in ir:
+    [${version}] = of_stats_reply_v${version}_dissectors,
+:: #endfor
+}
+
+local of_stats_request_dissectors = {
+:: for version in ir:
+    [${version}] = of_stats_request_v${version}_dissectors,
+:: #endfor
+}
+
+local of_flow_stats_entry_dissectors = {
+:: for version in ir:
+    [${version}] = dissect_of_flow_stats_entry_v${version},
+:: #endfor
+}
+
+local of_port_stats_entry_dissectors = {
+:: for version in ir:
+    [${version}] = dissect_of_port_stats_entry_v${version},
+:: #endfor
+}
+
+local of_table_stats_entry_dissectors = {
+:: for version in ir:
+    [${version}] = dissect_of_table_stats_entry_v${version},
+:: #endfor
+}
+
+local of_queue_stats_entry_dissectors = {
+:: for version in ir:
+    [${version}] = dissect_of_queue_stats_entry_v${version},
+:: #endfor
+}
+
 function dissect_of_message(buf, root)
     local reader = OFReader.new(buf)
     local subtree = root:add(p_of, buf(0))
@@ -137,7 +179,13 @@
     end
 
     local info = "unknown"
-    if of_message_dissectors[version_val] and of_message_dissectors[version_val][type_val] then
+    if type_val == 19 then
+        local stats_type = buf(8,2):uint()
+        info = of_stats_reply_dissectors[version_val][stats_type](reader,subtree)
+    elseif type_val == 18 then
+        local stats_type = buf(8,2):uint()
+        info = of_stats_request_dissectors[version_val][stats_type](reader,subtree)
+    elseif of_message_dissectors[version_val] and of_message_dissectors[version_val][type_val] then
         info = of_message_dissectors[version_val][type_val](reader, subtree)
     end
 
@@ -183,6 +231,51 @@
     return info
 end
 
+function dissect_of_port_desc(reader, subtree, version_val)
+    local info = "unknown"
+    if of_port_desc_dissectors[version_val] then
+        info = of_port_desc_dissectors[version_val](reader, subtree)
+    end
+
+    return info
+end
+
+function dissect_of_flow_stats_entry(reader, subtree, version_val)
+    local info = "unknown"
+    if of_flow_stats_entry_dissectors[version_val] then
+        info = of_flow_stats_entry_dissectors[version_val](reader, subtree)
+    end
+
+    return info
+end
+
+function dissect_of_port_stats_entry(reader, subtree, version_val)
+    local info = "unknown"
+    if of_port_stats_entry_dissectors[version_val] then
+        info = of_port_stats_entry_dissectors[version_val](reader, subtree)
+    end
+
+    return info
+end
+
+function dissect_of_table_stats_entry(reader, subtree, version_val)
+    local info = "unknown"
+    if of_table_stats_entry_dissectors[version_val] then
+        info = of_table_stats_entry_dissectors[version_val](reader, subtree)
+    end
+
+    return info
+end
+
+function dissect_of_queue_stats_entry(reader, subtree, version_val)
+    local info = "unknown"
+    if of_queue_stats_entry_dissectors[version_val] then
+        info = of_queue_stats_entry_dissectors[version_val](reader, subtree)
+    end
+
+    return info
+end
+
 -- of dissector function
 function p_of.dissector (buf, pkt, root)
     local offset = 0