drop-count.luaΒΆ

--
-- Demonstration of collecting per socket packet drop counts
-- statistics reported by the network stack.
--

local stats = collect({
    -- Received packets
    recv_pkts = 0,
    -- Dropped packets
    drop_pkts = 0,
})

server_socket(
  function (sockfd)
    -- XXX: Make setsockopt() wrapper abort or error by default
    local ok, err = setsockopt(sockfd, SOL_SOCKET, SO_RXQ_OVFL, 1)
    assert(ok, tostring(err))
  end
)

server_recvmsg(
  function (sockfd, msg, flags)
    local n_recv, err = recvmsg(sockfd, msg, flags)
    assert(n_recv, tostring(err))

    stats.recv_pkts = stats.recv_pkts + 1

    local _, cmsg = msg:cmsg_firsthdr()
    if cmsg then
      if cmsg.cmsg_level == SOL_SOCKET and cmsg.cmsg_type == SO_RXQ_OVFL then
        local n_drop = tonumber(uint32_ptr(cmsg.cmsg_data)[0])

        -- Uncomment to see packet drops being reported
        -- if n_drop > drop_pkts then
        --   io.stderr:write('.')
        -- end

        stats.drop_pkts = n_drop
      end
    end

    return n_recv
  end
)

run()

print()
print(string.format("%10s %12s %12s", "", "Received", "Dropped"))
print(string.format("%10s %12s %12s", "", "(packets)", "(packets)"))

local total = {
  recv_pkts = 0,
  drop_pkts = 0,
}

for i = 1, #stats do
  print(string.format("%10s %12d %12d",
                      string.format("Thread-%02d:", i),
                      stats[i].recv_pkts, stats[i].drop_pkts))

  total.recv_pkts = total.recv_pkts + stats[i].recv_pkts
  total.drop_pkts = total.drop_pkts + stats[i].drop_pkts
end

print(string.format("%10s %12d %12d",
                    "Total:", total.recv_pkts, total.drop_pkts))
print()