Skip to content

Commit

Permalink
Merge "wireshark dissector pluggin support" into R3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Aug 17, 2016
2 parents 60256bf + c2c3370 commit f63824a
Show file tree
Hide file tree
Showing 3 changed files with 285 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/vnsw/agent/contrail/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ contrail_vrouter_agent = env.Program(target = 'contrail-vrouter-agent',
env.Alias('contrail-vrouter-agent', contrail_vrouter_agent)
env.Default(contrail_vrouter_agent)

utils_scripts = [
'contrail-vrouter-agent-health-check.py',
'agent_dissector.lua',
'mpls_dissector.lua']

# Documentation
doc_files = []
doc_files += env['AGENT_COMMON_DOC_FILES']
Expand All @@ -120,8 +125,8 @@ doc_files += env['AGENT_FLOW_DOC_FILES']

# Please update sandesh/common/vns.sandesh on process name change
env.Alias('install', env.Install(env['INSTALL_BIN'], contrail_vrouter_agent))
env.Alias('install', env.Install(env['INSTALL_EXAMPLE'],
'contrail-vrouter-agent-health-check.py'))
for utils in utils_scripts:
env.Alias('install', env.Install(env['INSTALL_EXAMPLE'], utils))
env.Alias('install', env.Install(env['INSTALL_CONF'],
'../contrail-vrouter-agent.conf'))
env.Alias('install',
Expand Down
130 changes: 130 additions & 0 deletions src/vnsw/agent/contrail/agent_dissector.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
local dprint2 = function() end
dprint2 = function(...)
print(table.concat({"Lua:", ...}," "))
end
----------------------------------------
-- creates a Proto object, but doesn't register it yet
local agent = Proto("agent","agent Protocol")

----------------------------------------
-- multiple ways to do the same thing: create a protocol field (but not register it yet)
-- the abbreviation should always have "<myproto>." before the specific abbreviation, to avoid collisions
local pf_if_index = ProtoField.new ("Interface index", "agent.if_id", ftypes.UINT16)
local pf_vrf = ProtoField.new ("Vrf", "agent.vrf", ftypes.UINT16)
local pf_cmd = ProtoField.new ("command", "agent.cmd", ftypes.UINT16)
local pf_cmd_param = ProtoField.new ("command parameter", "agent.cmd_param", ftypes.UINT32)
local pf_cmd_param_1 = ProtoField.new ("command parameter 1", "agent.cmd_param_1", ftypes.UINT32)
local pf_cmd_param_2 = ProtoField.new ("command parameter 2", "agent.cmd_param_2", ftypes.UINT32)
local pf_cmd_param_3 = ProtoField.new ("command parameter 3", "agent.cmd_param_3", ftypes.UINT32)
local pf_cmd_param_4 = ProtoField.new ("command parameter 4", "agent.cmd_param_4", ftypes.UINT32)
local pf_cmd_param_5 = ProtoField.new ("command parameter 5", "agent.cmd_param_5", ftypes.UINT32)

----------------------------------------
-- this actually registers the ProtoFields above, into our new Protocol
agent.fields = { pf_if_index, pf_vrf,
pf_cmd, pf_cmd_param, pf_cmd_param_1, pf_cmd_param_2,
pf_cmd_param_3, pf_cmd_param_4, pf_cmd_param_5 }

----------------------------------------
-- The following creates the callback function for the dissector.
-- It's the same as doing "dns.dissector = function (tvbuf,pkt,root)"
-- The 'tvbuf' is a Tvb object, 'pktinfo' is a Pinfo object, and 'root' is a TreeItem object.
-- Whenever Wireshark dissects a packet that our Proto is hooked into, it will call
-- this function and pass it these arguments for the packet it's dissecting.
function agent.dissector(tvbuf,pktinfo,root)

-- set the protocol column to show our protocol name
pktinfo.cols.protocol:set("Agent")

-- We start by adding our protocol to the dissection display tree.
-- A call to tree:add() returns the child created, so we can add more "under" it using that return value.
-- The second argument is how much of the buffer/packet this added tree item covers/represents
local tree = root:add(agent, tvbuf:range(0,30))
local offset = 14

-- Now let's add our if_index under our agent protocol tree we just created.
-- The if_index starts at offset 0, for 2 bytes length.
tree:add(pf_if_index, tvbuf:range(offset,2))

-- now add more to the main agent tree
tree:add(pf_vrf, tvbuf:range(offset+2,2))
tree:add(pf_cmd, tvbuf:range(offset+4,2))
tree:add(pf_cmd_param, tvbuf:range(offset+6,4))
tree:add(pf_cmd_param_1, tvbuf:range(offset+10,4))
tree:add(pf_cmd_param_2, tvbuf:range(offset+14,4))
tree:add(pf_cmd_param_3, tvbuf:range(offset+18,4))
tree:add(pf_cmd_param_4, tvbuf:range(offset+22,4))
tree:add(pf_cmd_param_5, tvbuf:range(offset+26,4))

local data_dis = Dissector.get("data")
local inner_type = tvbuf:range(offset+42,2):uint()
if inner_type == 2054 then
Dissector.get("arp"):call(tvbuf(58):tvb(),pktinfo,root)
elseif inner_type == 2048 then
local ip_proto = tvbuf:range(67,1):uint()
if ip_proto == 17 then
local udp_port = tvbuf:range(80,2):uint()
if udp_port == 51234 then
-- It is a MPLSoUDP encapsulated packet
-- Check if inner packet is Layer-2
local ethertype = tvbuf:range(102,2):uint()
local version = tvbuf:range(104,1):uint()
version = bit.rshift(version,4)
if ethertype == 2048 and version == 4 then
Dissector.get("ip"):call(tvbuf(104):tvb(),pktinfo,root)
elseif ethertype == 34525 and version == 6 then
Dissector.get("ipv6"):call(tvbuf(104):tvb(),pktinfo,root)
else
-- inner packet can potentially be layer-3
version = tvbuf:range(90,1):uint()
version = bit.rshift(version,4)
if version == 4 then
Dissector.get("ip"):call(tvbuf(90):tvb(),pktinfo,root)
elseif version == 6 then
Dissector.get("ipv6"):call(tvbuf(90):tvb(),pktinfo,root)
else
data_dis:call(tvbuf(90):tvb(),pktinfo,root)
end
end
return
end
elseif ip_proto == 47 then
-- It is a MPLSoGRE encapsulated packet
-- Check if inner packet is Layer-2
local ethertype = tvbuf:range(98,2):uint()
local version = tvbuf:range(100,1):uint()
version = bit.rshift(version,4)
if ethertype == 2048 and version == 4 then
Dissector.get("ip"):call(tvbuf(100):tvb(),pktinfo,root)
elseif ethertype == 34525 and version == 6 then
Dissector.get("ipv6"):call(tvbuf(100):tvb(),pktinfo,root)
else
-- inner packet can potentially be layer-3
version = tvbuf:range(86,1):uint()
version = bit.rshift(version,4)
if version == 4 then
Dissector.get("ip"):call(tvbuf(86):tvb(),pktinfo,root)
elseif version == 6 then
Dissector.get("ipv6"):call(tvbuf(86):tvb(),pktinfo,root)
else
data_dis:call(tvbuf(86):tvb(),pktinfo,root)
end
end
return
end
Dissector.get("ip"):call(tvbuf(58):tvb(),pktinfo,root)
elseif inner_type == 34525 then
Dissector.get("ipv6"):call(tvbuf(58):tvb(),pktinfo,root)
else
data_dis:call(tvbuf(44):tvb(),pktinfo,root)
end
end

----------------------------------------
-- so get the wiretap-encap dissector table and add our protocol to it
local wtap_encap_table = DissectorTable.get("wtap_encap")
wtap_encap_table:add(1, agent)

-- We're done!
-- our protocol (Proto) gets automatically registered after this script finishes loading
----------------------------------------
148 changes: 148 additions & 0 deletions src/vnsw/agent/contrail/mpls_dissector.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
local dprint2 = function() end
dprint2 = function(...)
print(table.concat({"Lua:", ...}," "))
end
----------------------------------------
-- creates a Proto object, but doesn't register it yet
local mpls_udp = Proto("mpls_udp","MplsoUdp Protocol")

----------------------------------------
-- create a protocol field (but not register it yet)
-- the abbreviation should always have "<myproto>." before the specific abbreviation, to avoid collisions
local pf_mpls_label = ProtoField.new ("Mpls Label", "mpls_udp.mpls_label", ftypes.UINT32)

----------------------------------------
-- this actually registers the ProtoFields above, into our new Protocol
mpls_udp.fields = { pf_mpls_label }

----------------------------------------
-- The following creates the callback function for the dissector.
-- It's the same as doing "dns.dissector = function (tvbuf,pkt,root)"
-- The 'tvbuf' is a Tvb object, 'pktinfo' is a Pinfo object, and 'root' is a TreeItem object.
-- Whenever Wireshark dissects a packet that our Proto is hooked into, it will call
-- this function and pass it these arguments for the packet it's dissecting.
function mpls_udp.dissector(tvbuf,pktinfo,root)

-- set the protocol column to show our protocol name
pktinfo.cols.protocol:set("MplsoUdp")

-- We start by adding our protocol to the dissection display tree.
-- A call to tree:add() returns the child created, so we can add more "under" it using that return value.
-- The second argument is how much of the buffer/packet this added tree item covers/represents
local tree = root:add(mpls_udp, tvbuf:range(0,4))

-- Now let's add our mpls label under our MplsoUdp protocol tree we just created.
-- The label is present in first 20 bits of MPLS header
local mpls_field = tvbuf:range(0,4):uint()
tree:add(pf_mpls_label, bit.rshift(mpls_field,12))

-- Now check if inner packet is layer-2
local inner_type = tvbuf:range(16,2):uint()
local version = tvbuf:range(18,1):uint()
version = bit.rshift(version,4)
-- Check if it is Arp Ethertype
if inner_type == 2054 then
Dissector.get("arp"):call(tvbuf(18):tvb(),pktinfo,root)
return
-- Check if it is Ip Ethertype
elseif inner_type == 2048 and version == 4 then
Dissector.get("ip"):call(tvbuf(18):tvb(),pktinfo,root)
return
-- Check if it is Ipv6 Ethertype
elseif inner_type == 34525 and version == 6 then
Dissector.get("ipv6"):call(tvbuf(18):tvb(),pktinfo,root)
return
else
-- potentially a layer-3 packet, check for version field
version = tvbuf:range(4,1):uint()
version = bit.rshift(version,4)
if version == 4 then
Dissector.get("ip"):call(tvbuf(4):tvb(),pktinfo,root)
elseif version == 6 then
Dissector.get("ipv6"):call(tvbuf(4):tvb(),pktinfo,root)
else
-- Otherwise call data dissector which prints payload data
local data_dis = Dissector.get("data")
data_dis:call(tvbuf(4):tvb(),pktinfo,root)
end
end
end

----------------------------------------
-- we want to have our protocol dissection invoked for a specific UDP port,
-- so get the udp dissector table and add our protocol to it
DissectorTable.get("udp.port"):add(51234, mpls_udp)

----------------------------------------
-- creates a Proto object, but doesn't register it yet
local mpls_gre = Proto("mpls_gre","MplsoGre Protocol")

----------------------------------------
-- create a protocol field (but not register it yet)
-- the abbreviation should always have "<myproto>." before the specific abbreviation, to avoid collisions
local pf_gre_flags = ProtoField.new ("Gre flags", "mpls_gre.gre_flags", ftypes.UINT16)
local pf_gre_protocol = ProtoField.new ("Gre proto", "mpls_gre.gre_protocol", ftypes.UINT16)
local pf_mpls_label = ProtoField.new ("Mpls Label", "mpls_gre.mpls_label", ftypes.UINT32)

----------------------------------------
-- this actually registers the ProtoFields above, into our new Protocol
mpls_gre.fields = { pf_gre_flags, pf_gre_protocol, pf_mpls_label }

----------------------------------------
-- The following creates the callback function for the dissector.
-- It's the same as doing "dns.dissector = function (tvbuf,pkt,root)"
-- The 'tvbuf' is a Tvb object, 'pktinfo' is a Pinfo object, and 'root' is a TreeItem object.
-- Whenever Wireshark dissects a packet that our Proto is hooked into, it will call
-- this function and pass it these arguments for the packet it's dissecting.
function mpls_gre.dissector(tvbuf,pktinfo,root)

-- set the protocol column to show our protocol name
pktinfo.cols.protocol:set("MplsoGre")

-- We start by adding our protocol to the dissection display tree.
-- A call to tree:add() returns the child created, so we can add more "under" it using that return value.
-- The second argument is how much of the buffer/packet this added tree item covers/represents
local tree = root:add(mpls_gre, tvbuf:range(0,8))

-- Now let's add gre flags, protocol and mpls label under our MplsoGre protocol tree we just created.
tree:add(pf_gre_flags, tvbuf:range(0,2))
tree:add(pf_gre_protocol, tvbuf:range(2,2))
local mpls_field = tvbuf:range(4,4):uint()
tree:add(pf_mpls_label, bit.rshift(mpls_field,12))

-- Now check if inner-packet is layer-2
local inner_type = tvbuf:range(20,2):uint()
local version = tvbuf:range(22,1):uint()
version = bit.rshift(version,4)
if inner_type == 2054 then
Dissector.get("arp"):call(tvbuf(22):tvb(),pktinfo,root)
return
elseif inner_type == 2048 and version == 4 then
Dissector.get("ip"):call(tvbuf(22):tvb(),pktinfo,root)
return
elseif inner_type == 34525 and version == 6 then
Dissector.get("ipv6"):call(tvbuf(22):tvb(),pktinfo,root)
return
else
-- Potentially a layer-3 packet
version = tvbuf:range(8,1):uint()
version = bit.rshift(version,4)
if version == 4 then
Dissector.get("ip"):call(tvbuf(8):tvb(),pktinfo,root)
elseif version == 6 then
Dissector.get("ipv6"):call(tvbuf(8):tvb(),pktinfo,root)
else
-- Call data-dissector with payload
local data_dis = Dissector.get("data")
data_dis:call(tvbuf(8):tvb(),pktinfo,root)
end
end
end

----------------------------------------
-- we want to have our protocol dissection invoked for a specific ip proto,
-- so get the ip proto dissector table and add our protocol to it
DissectorTable.get("ip.proto"):add(47, mpls_gre)
-- We're done!
-- our protocol (Proto) gets automatically registered after this script finishes loading
----------------------------------------

0 comments on commit f63824a

Please sign in to comment.