etherbone: clean up ohwr dissector, Python model checked against it

This commit is contained in:
Florent Kermarrec 2015-02-10 23:04:05 +01:00
parent 5728f61f3a
commit 02bfc0a5a8
3 changed files with 320 additions and 101 deletions

View File

@ -0,0 +1,260 @@
--[[---------------
LuaBit v0.4
-------------------
a bitwise operation lib for lua.
http://luaforge.net/projects/bit/
How to use:
-------------------
bit.bnot(n) -- bitwise not (~n)
bit.band(m, n) -- bitwise and (m & n)
bit.bor(m, n) -- bitwise or (m | n)
bit.bxor(m, n) -- bitwise xor (m ^ n)
bit.brshift(n, bits) -- right shift (n >> bits)
bit.blshift(n, bits) -- left shift (n << bits)
bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
Please note that bit.brshift and bit.blshift only support number within
32 bits.
2 utility functions are provided too:
bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence)
-- high bits first
bit.tonumb(bit_tbl) -- convert a bit table into a number
-------------------
Under the MIT license.
copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
--]]---------------
do
------------------------
-- bit lib implementions
local function check_int(n)
-- checking not float
if(n - math.floor(n) > 0) then
error("trying to use bitwise operation on non-integer!")
end
end
local function to_bits(n)
check_int(n)
if(n < 0) then
-- negative
return to_bits(bit.bnot(math.abs(n)) + 1)
end
-- to bits table
local tbl = {}
local cnt = 1
while (n > 0) do
local last = math.mod(n,2)
if(last == 1) then
tbl[cnt] = 1
else
tbl[cnt] = 0
end
n = (n-last)/2
cnt = cnt + 1
end
return tbl
end
local function tbl_to_number(tbl)
local n = table.getn(tbl)
local rslt = 0
local power = 1
for i = 1, n do
rslt = rslt + tbl[i]*power
power = power*2
end
return rslt
end
local function expand(tbl_m, tbl_n)
local big = {}
local small = {}
if(table.getn(tbl_m) > table.getn(tbl_n)) then
big = tbl_m
small = tbl_n
else
big = tbl_n
small = tbl_m
end
-- expand small
for i = table.getn(small) + 1, table.getn(big) do
small[i] = 0
end
end
local function bit_or(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
for i = 1, rslt do
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl_to_number(tbl)
end
local function bit_and(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
for i = 1, rslt do
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl_to_number(tbl)
end
local function bit_not(n)
local tbl = to_bits(n)
local size = math.max(table.getn(tbl), 32)
for i = 1, size do
if(tbl[i] == 1) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl_to_number(tbl)
end
local function bit_xor(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
for i = 1, rslt do
if(tbl_m[i] ~= tbl_n[i]) then
tbl[i] = 1
else
tbl[i] = 0
end
end
--table.foreach(tbl, print)
return tbl_to_number(tbl)
end
local function bit_rshift(n, bits)
check_int(n)
local high_bit = 0
if(n < 0) then
-- negative
n = bit_not(math.abs(n)) + 1
high_bit = 2147483648 -- 0x80000000
end
for i=1, bits do
n = n/2
n = bit_or(math.floor(n), high_bit)
end
return math.floor(n)
end
-- logic rightshift assures zero filling shift
local function bit_logic_rshift(n, bits)
check_int(n)
if(n < 0) then
-- negative
n = bit_not(math.abs(n)) + 1
end
for i=1, bits do
n = n/2
end
return math.floor(n)
end
local function bit_lshift(n, bits)
check_int(n)
if(n < 0) then
-- negative
n = bit_not(math.abs(n)) + 1
end
for i=1, bits do
n = n*2
end
return bit_and(n, 4294967295) -- 0xFFFFFFFF
end
local function bit_xor2(m, n)
local rhs = bit_or(bit_not(m), bit_not(n))
local lhs = bit_or(m, n)
local rslt = bit_and(lhs, rhs)
return rslt
end
--------------------
-- bit lib interface
bit = {
-- bit operations
bnot = bit_not,
band = bit_and,
bor = bit_or,
bxor = bit_xor,
brshift = bit_rshift,
blshift = bit_lshift,
bxor2 = bit_xor2,
blogic_rshift = bit_logic_rshift,
-- utility func
tobits = to_bits,
tonumb = tbl_to_number,
}
end
--[[
for i = 1, 100 do
for j = 1, 100 do
if(bit.bxor(i, j) ~= bit.bxor2(i, j)) then
error("bit.xor failed.")
end
end
end
--]]

View File

@ -1,9 +1,9 @@
-- value-string maps for the protocol fields
-- Etherbone Dissector
-- Copyright 2013 OHWR.org
-- Copyright 2015 EnjoyDigital (global clean up)
local bit = require("bit")
local VALS_BAR = {[0x11] = "Whiskey", [0x12] = "Rum", [0x13] =
"Vodka", [0x14] = "Gin"}
local VALS_BOOL = {[0] = "False", [1] = "True"}
local VALS_RES = {[0] = "not set", [1] = "set, bad data?"}
local VALS_SIZE = {
@ -25,7 +25,6 @@ local VALS_SIZE = {
[0x0F] = "64,32,16,8 bit",
}
--- Returns HEX representation of num
function num2hex(num)
local hexstr = '0123456789abcdef'
local s = ''
@ -46,88 +45,80 @@ function max(a, b)
end
end
-- Declare protocol
-- declare protocol
proto_eb = Proto("eb", "Etherbone")
-- declare fields
local eb = proto_eb.fields
eb.hdr = ProtoField.uint32("eb.hdr", "Header", base.HEX)
eb.rec = ProtoField.bytes("eb.rec", "Record ", base.HEX)
-- Declare its fields
local eb = proto_eb.fields
eb.hdr = ProtoField.uint32("eb.hdr", "Header", base.HEX)
eb.rec = ProtoField.bytes("eb.rec", "Record ", base.HEX)
eb.hdr_magic = ProtoField.uint16("eb.hdr.magic", "Magic ", base.HEX, nil, 0xFFFF)
eb.hdr_ver = ProtoField.uint16("eb.hdr.ver", "Version ", base.DEC, nil, 0xF000)
eb.hdr_noreads = ProtoField.uint16("eb.hdr.noreads", "No Reads ", base.DEC, VALS_BOOL, 0x0400)
eb.hdr_proberep = ProtoField.uint16("eb.hdr.proberes", "Probe Reply ", base.DEC, VALS_BOOL, 0x0200)
eb.hdr_probereq = ProtoField.uint16("eb.hdr.probereq", "Probe Flag ", base.DEC, VALS_BOOL, 0x0100)
eb.hdr_adrs = ProtoField.uint16("eb.hdr.adrw", "Address Width ", base.DEC, VALS_SIZE , 0x00F0)
eb.hdr_ports = ProtoField.uint16("eb.hdr.portw", "Port Width ", base.DEC, VALS_SIZE , 0x000F)
eb.hdr_magic = ProtoField.uint16("eb.hdr.magic", "Magic ", base.HEX, nil, 0xFFFF)
eb.hdr_ver = ProtoField.uint16("eb.hdr.ver", "Version ", base.DEC, nil, 0xF000)
eb.hdr_noreads = ProtoField.uint16("eb.hdr.noreads", "No Reads ", base.DEC, VALS_BOOL, 0x0400)
eb.hdr_proberep = ProtoField.uint16("eb.hdr.proberes", "Probe Reply ", base.DEC, VALS_BOOL, 0x0200)
eb.hdr_probereq = ProtoField.uint16("eb.hdr.probereq", "Probe Flag ", base.DEC, VALS_BOOL, 0x0100)
eb.hdr_adrs = ProtoField.uint16("eb.hdr.adrw", "Address Width ", base.DEC, VALS_SIZE , 0x00F0)
eb.hdr_ports = ProtoField.uint16("eb.hdr.portw", "Port Width ", base.DEC, VALS_SIZE , 0x000F)
eb.rec_hdr = ProtoField.uint32("eb.rec.hdr", "Header ", base.HEX)
eb.rec_hdr = ProtoField.uint32("eb.rec.hdr", "Header ", base.HEX)
eb.rec_writes = ProtoField.bytes("eb.rec.writes", "Writes ", base.HEX)
eb.rec_reads = ProtoField.bytes("eb.rec.reads", "Reads ", base.HEX)
eb.rec_reads = ProtoField.bytes("eb.rec.reads", "Reads ", base.HEX)
eb.rec_hdr_flags = ProtoField.uint8("eb.rec.hdr.flags", "Flags ", base.HEX)
eb.rec_hdr_flags = ProtoField.uint8("eb.rec.hdr.flags", "Flags ", base.HEX)
eb.rec_hdr_select = ProtoField.uint8("eb.rec.hdr.select", "Select ", base.HEX)
eb.rec_hdr_wr = ProtoField.uint8("eb.rec.hdr.wr", "Writes ", base.DEC)
eb.rec_hdr_rd = ProtoField.uint8("eb.rec.hdr.rd", "Reads ", base.DEC)
eb.rec_hdr_wr = ProtoField.uint8("eb.rec.hdr.wr", "Writes ", base.DEC)
eb.rec_hdr_rd = ProtoField.uint8("eb.rec.hdr.rd", "Reads ", base.DEC)
eb.rec_hdr_flags_adrcfg = ProtoField.uint8("eb.rec.hdr.flags.adrcfg", "ReplyToCfgSpace ", base.DEC, VALS_BOOL, 0x80)
eb.rec_hdr_flags_rbacfg = ProtoField.uint8("eb.rec.hdr.adrcfg", "ReadFromCfgSpace ", base.DEC, VALS_BOOL, 0x40)
eb.rec_hdr_flags_rdfifo = ProtoField.uint8("eb.rec.hdr.adrcfg", "ReadFIFO ", base.DEC, VALS_BOOL, 0x20)
eb.rec_hdr_flags_dropcyc= ProtoField.uint8("eb.rec.hdr.adrcfg", "DropCycle ", base.DEC, VALS_BOOL, 0x08)
eb.rec_hdr_flags_wbacfg = ProtoField.uint8("eb.rec.hdr.adrcfg", "WriteToCfgSpace ", base.DEC, VALS_BOOL, 0x04)
eb.rec_hdr_flags_wrfifo = ProtoField.uint8("eb.rec.hdr.adrcfg", "WriteFIFO ", base.DEC, VALS_BOOL, 0x02)
eb.rec_hdr_flags_rbacfg = ProtoField.uint8("eb.rec.hdr.adrcfg", "ReadFromCfgSpace ", base.DEC, VALS_BOOL, 0x40)
eb.rec_hdr_flags_rdfifo = ProtoField.uint8("eb.rec.hdr.adrcfg", "ReadFIFO ", base.DEC, VALS_BOOL, 0x20)
eb.rec_hdr_flags_dropcyc= ProtoField.uint8("eb.rec.hdr.adrcfg", "DropCycle ", base.DEC, VALS_BOOL, 0x08)
eb.rec_hdr_flags_wbacfg = ProtoField.uint8("eb.rec.hdr.adrcfg", "WriteToCfgSpace ", base.DEC, VALS_BOOL, 0x04)
eb.rec_hdr_flags_wrfifo = ProtoField.uint8("eb.rec.hdr.adrcfg", "WriteFIFO ", base.DEC, VALS_BOOL, 0x02)
eb.rec_wrsadr8 = ProtoField.uint8("eb.rec.wrsadr8", "BaseAddr8 ", base.HEX)
eb.rec_wrsadr16 = ProtoField.uint16("eb.rec.wrsadr16", "BaseAddr16 ", base.HEX)
eb.rec_wrsadr32 = ProtoField.uint32("eb.rec.wrsadr32", "BaseAddr32 ", base.HEX)
eb.rec_wrsadr64 = ProtoField.uint64("eb.rec.wrsadr64", "BaseAddr64 ", base.HEX)
eb.rec_wrdata8 = ProtoField.uint8("eb.rec.wrdata8", "Value8 ", base.HEX)
eb.rec_wrdata16 = ProtoField.uint16("eb.rec.wrdata16", "Value16 ", base.HEX)
eb.rec_wrdata32 = ProtoField.uint32("eb.rec.wrdata32", "Value32 ", base.HEX)
eb.rec_wrdata64 = ProtoField.uint64("eb.rec.wrdata64", "Value64 ", base.HEX)
eb.rec_wrsadr8 = ProtoField.uint8("eb.rec.wrsadr8", "BaseAddr8 ", base.HEX)
eb.rec_wrsadr16 = ProtoField.uint16("eb.rec.wrsadr16", "BaseAddr16 ", base.HEX)
eb.rec_wrsadr32 = ProtoField.uint32("eb.rec.wrsadr32", "BaseAddr32 ", base.HEX)
eb.rec_wrsadr64 = ProtoField.uint64("eb.rec.wrsadr64", "BaseAddr64 ", base.HEX)
eb.rec_wrdata8 = ProtoField.uint8("eb.rec.wrdata8", "Value8 ", base.HEX)
eb.rec_wrdata16 = ProtoField.uint16("eb.rec.wrdata16", "Value16 ", base.HEX)
eb.rec_wrdata32 = ProtoField.uint32("eb.rec.wrdata32", "Value32 ", base.HEX)
eb.rec_wrdata64 = ProtoField.uint64("eb.rec.wrdata64", "Value64 ", base.HEX)
eb.rec_rdbadr8 = ProtoField.uint8("eb.rec.rdbadr8", "ReplyAddr8 ", base.HEX)
eb.rec_rdbadr16 = ProtoField.uint16("eb.rec.rdbadr16", "ReplyAddr16 ", base.HEX)
eb.rec_rdbadr32 = ProtoField.uint32("eb.rec.rdbadr32", "ReplyAddr32 ", base.HEX)
eb.rec_rdbadr64 = ProtoField.uint64("eb.rec.rdbadr64", "ReplyAddr64 ", base.HEX)
eb.rec_rddata8 = ProtoField.uint8("eb.rec.rddata8", "Address8 ", base.HEX)
eb.rec_rddata16 = ProtoField.uint16("eb.rec.rddata16", "Address16 ", base.HEX)
eb.rec_rddata32 = ProtoField.uint32("eb.rec.rddata32", "Address32 ", base.HEX)
eb.rec_rddata64 = ProtoField.uint64("eb.rec.rddata64", "Address64 ", base.HEX)
eb.rec_rdbadr8 = ProtoField.uint8("eb.rec.rdbadr8", "ReplyAddr8 ", base.HEX)
eb.rec_rdbadr16 = ProtoField.uint16("eb.rec.rdbadr16", "ReplyAddr16 ", base.HEX)
eb.rec_rdbadr32 = ProtoField.uint32("eb.rec.rdbadr32", "ReplyAddr32 ", base.HEX)
eb.rec_rdbadr64 = ProtoField.uint64("eb.rec.rdbadr64", "ReplyAddr64 ", base.HEX)
eb.rec_rddata8 = ProtoField.uint8("eb.rec.rddata8", "Address8 ", base.HEX)
eb.rec_rddata16 = ProtoField.uint16("eb.rec.rddata16", "Address16 ", base.HEX)
eb.rec_rddata32 = ProtoField.uint32("eb.rec.rddata32", "Address32 ", base.HEX)
eb.rec_rddata64 = ProtoField.uint64("eb.rec.rddata64", "Address64 ", base.HEX)
-- Define the dissector
-- define the dissector
function proto_eb.dissector(buf, pinfo, tree)
-- min length, 4 for eb hdr with probe
local EXPECTED_LENGTH = 4
if (buf:len() < EXPECTED_LENGTH) then
-- not ours, let it go to default Data dissector
return 0
end
if (buf:len() < 4) then
return 0 -- too short, go to default protocol
end
local mylen = buf:len()
pinfo.cols.protocol = "eb"
pinfo.cols.protocol = "eb"
-- add our packet to the tree root...we'll add fields to its subtree
local t = tree:add( proto_eb, buf(0, mylen) )
local t_hdr = t:add( eb.hdr, buf(0,4) ) -- hdr
-- add packet to the tree root, fields will be added to subtree
local t = tree:add( proto_eb, buf(0, mylen) )
local t_hdr = t:add( eb.hdr, buf(0,4) )
local magic = num2hex(tonumber(buf(0,2):uint()))
if(magic == "4e6f") then -- is this a valid etherbone packet ?
if(magic == "4e6f") then
t_hdr:add( eb.hdr_magic, buf(0,2)) -- magic
t_hdr:add( eb.hdr_ver, buf(2,2)) -- version
t_hdr:add( eb.hdr_noreads, buf(2,2)) -- no reads
t_hdr:add( eb.hdr_proberep, buf(2,2)) -- probe response
t_hdr:add( eb.hdr_probereq, buf(2,2)) -- probe request
t_hdr:add( eb.hdr_magic, buf(0,2)) -- magic
t_hdr:add( eb.hdr_ver, buf(2,2)) -- version
t_hdr:add( eb.hdr_noreads, buf(2,2)) -- no reads
t_hdr:add( eb.hdr_proberep, buf(2,2)) -- probe response
t_hdr:add( eb.hdr_probereq, buf(2,2)) -- probe request
t_hdr:add( eb.hdr_adrs, buf(2,2)) -- supported addr size
t_hdr:add( eb.hdr_ports, buf(2,2)) -- supported port size
t_hdr:add( eb.hdr_adrs, buf(2,2)) -- supported addr size
t_hdr:add( eb.hdr_ports, buf(2,2)) -- supported port size
local probe = tonumber(buf(2,1):uint()) % 4
if (probe == 0) then
@ -139,11 +130,6 @@ function proto_eb.dissector(buf, pinfo, tree)
local record_alignment = max(alignment, 4)
local offset = max(alignment, 4)
--local t_foo = t:add( "Addr "..tostring(addr_width), buf(4,4))
--local t_foo = t:add( "Data "..tostring(data_width), buf(4,4))
--local t_foo = t:add( "Value Alignment "..tostring(alignment), buf(4,4))
--local t_foo = t:add( "Record Alignment "..tostring(record_alignment), buf(4,4))
local recordcnt = 0
while (offset < buf:len()) do
local wr = tonumber(buf(offset+2,1):uint())
@ -158,11 +144,6 @@ function proto_eb.dissector(buf, pinfo, tree)
wradr = 1
end
-- t_rec = t:add(wr)
-- t_rec = t:add(rd)
-- t_rec = t:add(offset)
-- t_rec = t:add((1+rd+wr+rdadr+wradr)*4)
if((wr == 0) and (rd == 0)) then
offset = offset + record_alignment
else
@ -235,30 +216,8 @@ function proto_eb.dissector(buf, pinfo, tree)
return 0
end
-- local offset = 4
-- while offset <= mylen do
-- local rec = buf(offset,4)
-- if (buf:len() < EXPECTED_LENGTH + 4) then
--not ours, let it go to default Data dissector
-- return 0
-- end
end
-- Register eb protocol on UDP port 22222
-- register eb protocol on UDP port 20000
local tab = DissectorTable.get("udp.port")
tab:add(60368, proto_eb)
tab:add(8183, proto_eb)
tab:add(20000, proto_eb)

View File

@ -262,7 +262,7 @@ if __name__ == "__main__":
# Send packet over UDP to check against Wireshark dissector
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(bytes(packet), ("192.168.1.1", 60368))
sock.sendto(bytes(packet), ("192.168.1.1", 20000))
packet = EtherbonePacket(packet)
packet.decode()