diff --git a/src/apps/ipv6/nd_light.lua b/src/apps/ipv6/nd_light.lua index 2018c001b8..4502a9c089 100644 --- a/src/apps/ipv6/nd_light.lua +++ b/src/apps/ipv6/nd_light.lua @@ -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 @@ -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 @@ -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()) @@ -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 @@ -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 diff --git a/src/lib/protocol/datagram.lua b/src/lib/protocol/datagram.lua index fda1c44eb6..8f5bffe431 100644 --- a/src/lib/protocol/datagram.lua +++ b/src/lib/protocol/datagram.lua @@ -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() @@ -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 @@ -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 @@ -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 @@ -201,7 +202,7 @@ end -- Remove bytes from the start of the packet and set upper-layer -- protocol to if 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 @@ -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