snabbco / snabb

Snabb: Simple and fast packet networking
Apache License 2.0
2.98k stars 301 forks source link

Unanchored FFI objects in lpm4_dxr #1238

Open alexandergall opened 7 years ago

alexandergall commented 7 years ago

I ran across an issue with lib.lpm.lpm4_dxr that seems to be caused by an unanchroed FFI object. The only way I found to reproduce it is a bit weird, though. For me, the following code is stuck in table:build()

local lpm = require("lib.lpm.lpm4_dxr").LPM4_dxr
require("lib.protocol.ipv4")

local table = lpm:new()
for i = 1, 10 do
   local pfx = "10.0."..i..".0/24"
   table:add_string(pfx, i)
end

collectgarbage()
table:build()

It behaves correctly if either collectgarbage() or require("lib.protocol.ipv4") is removed. The weird part is that this only happens when I require something from lib.protocol. Nevertheless, I believe that this just happens to create a particular state on the heap that causes an object used by lpm4_dxr to be collected prematurely due to a lack of anchoring.

alexandergall commented 7 years ago

@petebristow can you have a look at this, please?

raj2569 commented 7 years ago

Slightly different error here:

module(..., package.seeall)

local lib      = require("core.lib")
local logger   = lib.logger_new({ rate = 32, module = 'lpm'});
local lpm4     = require("lib.lpm.lpm4_dxr").LPM4_dxr

Route = {}

function Route:new (conf)
   local o = {lpm_hash  = lpm4:new()}

   logger:log("Adding entries to lpm")
   o.lpm_hash:add_string("16.0.0.0/24", 1)
   o.lpm_hash:add_string("16.0.0.1/24", 2)
   o.lpm_hash:add_string("48.0.0.1/24", 3)

   logger:log("Building lpm")
   o.lpm_hash:build()

   logger:log("Added entries to lpm")
   return setmetatable(o, {__index = self})
end

function Route:push()
end

Its stuck after printing "Added entries to lpm"

petebristow commented 7 years ago

Apologies for my tardiness. You've hit an undocumented feature. (It's documented in my internal version of LPM but I'm not sure that counts :S) Every LPM instance requires a 0.0.0.0/0 entry. If you don't have a a default route then you need to install an explicit "I don't know" value.