Skip to content

Commit

Permalink
Performance enhancements
Browse files Browse the repository at this point in the history
Use static arrays to cache pointers to cdata objects in the nd_light
app and the datagram class.
  • Loading branch information
alexandergall committed Mar 27, 2015
1 parent c82edb6 commit 37eccc0
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 24 deletions.
41 changes: 26 additions & 15 deletions src/apps/ipv6/nd_light.lua
Expand Up @@ -183,13 +183,21 @@ function nd_light:new (arg)
sna.eth, sna.ipv6, sna.icmp = unpack(dgram:stack())
sna.dgram = dgram
o._sna = sna

-- Caches for for various cdata pointer objects to avoid boxing in
-- the push() loop
o._cache = {
p = ffi.new("struct packet *[1]"),
mem = ffi.new("uint8_t *[1]")
}
return o
end

-- Process neighbor solicitation
local function ns (self, dgram, eth, ipv6, icmp)
local payload, length = dgram:payload()
if not icmp:checksum_check(payload, length, ipv6) then
local mem, length = self._cache.mem
mem[0], length = dgram:payload()
if not icmp:checksum_check(mem[0], length, ipv6) then
print(self:name()..": bad icmp checksum")
return nil
end
Expand All @@ -209,8 +217,8 @@ local function ns (self, dgram, eth, ipv6, icmp)
sna.ipv6:dst(ipv6:src())
-- The payload of the pre-fabricated packet consists of the NA and
-- target ll-option
local mem, length = sna.dgram:payload()
sna.icmp:checksum(mem, length, sna.ipv6)
mem[0], length = sna.dgram:payload()
sna.icmp:checksum(mem[0], length, sna.ipv6)
return true
end

Expand All @@ -237,10 +245,10 @@ local function na (self, dgram, eth, ipv6, icmp)
end

local function from_south (self, p)
if not self._filter:match(packet.data(p), packet.length(p)) then
if not self._filter:match(packet.data(p[0]), packet.length(p[0])) then
return false
end
local dgram = datagram:new(p, ethernet)
local dgram = datagram:new(p[0], ethernet)
-- Parse the ethernet, ipv6 amd icmp headers
dgram:parse_n(3)
local eth, ipv6, icmp = unpack(dgram:stack())
Expand All @@ -264,22 +272,24 @@ function nd_light:push ()
self._next_hop.timer_cb()
end

local cache = self._cache
local l_in = self.input.south
local l_out = self.output.north
local l_reply = self.output.south
while not link.empty(l_in) and not link.full(l_out) do
local p = link.receive(l_in)
local p = cache.p
p[0] = link.receive(l_in)
local status = from_south(self, p)
if status == nil then
-- Discard
packet.free(p)
packet.free(p[0])
elseif status == true then
-- Send NA back south
packet.free(p)
packet.free(p[0])
link.transmit(l_reply, packet.clone(self._sna.packet))
else
-- Send transit traffic up north
link.transmit(l_out, p)
link.transmit(l_out, p[0])
end
end

Expand All @@ -291,11 +301,12 @@ function nd_light:push ()
-- has completed.
packet.free(link.receive(l_in))
else
local p = link.receive(l_in)
if packet.length(p) >= self._eth_header:sizeof() then
self._eth_header:copy(packet.data(p))
link.transmit(l_out, p)
else packet.free(p) end
local p = cache.p
p[0] = link.receive(l_in)
if packet.length(p[0]) >= self._eth_header:sizeof() then
self._eth_header:copy(packet.data(p[0]))
link.transmit(l_out, p[0])
else packet.free(p[0]) end
end
end
end
Expand Down
19 changes: 10 additions & 9 deletions src/lib/protocol/datagram.lua
Expand Up @@ -53,6 +53,7 @@ local datagram = subClass(nil)
local function init (o, p, class)
if not o._recycled then
o._parse = { stack = {}, index = 0 }
o._packet = ffi.new("struct packet *[1]")
elseif o._parse.stack[1] then
for i, _ in ipairs(o._parse.stack) do
o._parse.stack[i]:free()
Expand All @@ -62,7 +63,7 @@ local function init (o, p, class)
end
o._parse.offset = 0
o._parse.ulp = class
o._packet = p or packet.allocate()
o._packet[0] = p or packet.allocate()
return o
end

Expand All @@ -81,7 +82,7 @@ end

-- Push a new protocol header to the front of the packet.
function datagram:push (proto)
packet.prepend(self._packet, proto:header(), proto:sizeof())
packet.prepend(self._packet[0], proto:header(), proto:sizeof())
self._parse.offset = self._parse.offset + proto:sizeof()
end

Expand Down Expand Up @@ -113,8 +114,8 @@ function datagram:parse_match (class, check)
local parse = self._parse
local class = class or parse.ulp
if not class then return nil end
local proto = class:new_from_mem(packet.data(self._packet) + parse.offset,
packet.length(self._packet) - parse.offset)
local proto = class:new_from_mem(packet.data(self._packet[0]) + parse.offset,
packet.length(self._packet[0]) - parse.offset)
if proto == nil or (check and not check(proto)) then
if proto then proto:free() end
return nil
Expand Down Expand Up @@ -201,7 +202,7 @@ end
-- Remove <length> bytes from the start of the packet and set upper-layer
-- protocol to <ulp> if <ulp> is supplied.
function datagram:pop_raw (length, ulp)
packet.shiftleft(self._packet, length)
packet.shiftleft(self._packet[0], length)
if ulp then self._parse.ulp = ulp end
end

Expand All @@ -210,16 +211,16 @@ function datagram:stack ()
end

function datagram:packet ()
return(self._packet)
return(self._packet[0])
end

-- Return the location and size of the packet's payload. If mem is
-- non-nil, the memory region at the given address and size is
-- appended to the packet's payload first.
function datagram:payload (mem, size)
if mem then packet.append(self._packet, mem, size) end
return packet.data(self._packet) + self._parse.offset,
packet.length(self._packet) - self._parse.offset
if mem then packet.append(self._packet[0], mem, size) end
return packet.data(self._packet[0]) + self._parse.offset,
packet.length(self._packet[0]) - self._parse.offset
end

return datagram

0 comments on commit 37eccc0

Please sign in to comment.