From c52ad036610565f5a17665f78f7228694331c9fe Mon Sep 17 00:00:00 2001 From: Alexander Gall Date: Mon, 13 Apr 2015 08:30:56 +0200 Subject: [PATCH 1/3] 64-bit enhancments for RC registers A new register type called RC64 is introduced, which allows access to two consecutive 32-bit registers in the case of 64-bit byte and octet statistics registers. At the same time, the accumulator for both types of RC registers is promoted from a Lua number to a uint64_t cdata object. In addition to allow maintaining high-capacity counters based on 32-bit registers (e.g. packet counters), this also avoids conversions from integers to doubles. --- src/core/lib.lua | 3 +++ src/lib/hardware/register.lua | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/lib.lua b/src/core/lib.lua index dd16c8d9fe..9863b03afc 100644 --- a/src/core/lib.lua +++ b/src/core/lib.lua @@ -238,6 +238,9 @@ function hexundump(h, n) end function comma_value(n) -- credit http://richard.warburton.it + if type(n) == 'cdata' then + n = tonumber(n) + end if n ~= n then return "NaN" end local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$') return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right diff --git a/src/lib/hardware/register.lua b/src/lib/hardware/register.lua index bc16283055..44f217a046 100644 --- a/src/lib/hardware/register.lua +++ b/src/lib/hardware/register.lua @@ -2,6 +2,7 @@ module(...,package.seeall) +local ffi = require("ffi") local lib = require("core.lib") --- ### Register object @@ -22,9 +23,8 @@ end function Register:readrc () -- XXX JIT of this function is causing register value to be misread. jit.off(true,true) - local value = self.ptr[0] - self.acc = (self.acc or 0) + value - return self.acc + self.acc[0] = self.acc[0] + self.ptr[0] + return self.acc[0] end --- Write a register @@ -46,7 +46,7 @@ function Register:wait (bitmask, value) end --- For type `RC`: Reset the accumulator to 0. -function Register:reset () self.acc = 0 end +function Register:reset () self.acc[0] = 0ULL end --- For other registers provide a noop function Register:noop () end @@ -87,6 +87,9 @@ local mt = { RC = {__index = { read=Register.readrc, reset=Register.reset, print=Register.printrc}, __call = Register.readrc, __tostring = Register.__tostring}, + RC64 = {__index = { read=Register.readrc, reset=Register.reset, + print=Register.printrc}, + __call = Register.readrc, __tostring = Register.__tostring}, } --- Create a register `offset` bytes from `base_ptr`. @@ -98,6 +101,12 @@ function new (name, longname, offset, base_ptr, mode) ptr=base_ptr + offset/4 } local mt = mt[mode] assert(mt) + if mode == 'RC' or mode == 'RC64' then + o.acc = ffi.new("uint64_t[1]") + if mode == 'RC64' then + o.ptr = ffi.cast("uint64_t*", o.ptr) + end + end return setmetatable(o, mt) end From 479868ecd4cf4aa1663c60d4b5689aa528a8b193 Mon Sep 17 00:00:00 2001 From: Alexander Gall Date: Thu, 2 Apr 2015 12:54:37 +0200 Subject: [PATCH 2/3] Add support for HC counters in ifMIB High-capacity (64-bit) counters are supported through the new RC64 register type. --- src/apps/intel/intel10g.lua | 95 ++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/src/apps/intel/intel10g.lua b/src/apps/intel/intel10g.lua index 7759d71493..084f7e18f5 100644 --- a/src/apps/intel/intel10g.lua +++ b/src/apps/intel/intel10g.lua @@ -227,14 +227,13 @@ function M_sf:init_snmp () ifTable:register('ifOutMulticastPkts', 'Counter32', 0) ifTable:register('ifOutBroadcastPkts', 'Counter32', 0) ifTable:register('ifHCInOctets', 'Counter64', 0) - -- Note: Only the Octets counter is available as HC - -- ifTable:register('ifHCInUcastPkts', 'Counter64', 0) - -- ifTable:register('ifHCInMulticastPkts', 'Counter64', 0) - -- ifTable:register('ifHCInBroadcastPkts', 'Counter64', 0) + ifTable:register('ifHCInUcastPkts', 'Counter64', 0) + ifTable:register('ifHCInMulticastPkts', 'Counter64', 0) + ifTable:register('ifHCInBroadcastPkts', 'Counter64', 0) ifTable:register('ifHCOutOctets', 'Counter64', 0) - -- ifTable:register('ifHCOutUcastPkts', 'Counter64', 0) - -- ifTable:register('ifHCOutMulticastPkts', 'Counter64', 0) - -- ifTable:register('ifHCOutBroadcastPkts', 'Counter64', 0) + ifTable:register('ifHCOutUcastPkts', 'Counter64', 0) + ifTable:register('ifHCOutMulticastPkts', 'Counter64', 0) + ifTable:register('ifHCOutBroadcastPkts', 'Counter64', 0) ifTable:register('ifLinkUpDownTrapEnable', 'Integer32', 2) -- disabled ifTable:register('ifHighSpeed', 'Gauge32', 10000) ifTable:register('ifPromiscuousMode', 'Integer32', 2) -- false @@ -244,11 +243,34 @@ function M_sf:init_snmp () ifTable:register('ifCounterDiscontinuityTime', 'TimeTicks', 0) -- TBD ifTable:register('_X_ifCounterDiscontinuityTime', 'Counter64', 0) -- TBD - -- Create a timer to periodically check the interface status. The - -- default interval is 5 seconds, defined by the status_timer - -- variable. + --- Create a timer to periodically check the interface status. + --- Static variables are used in the timer function to avoid + --- garbage. local status = { [1] = 'up', [2] = 'down' } local mask = bits{Link_up=30} + local promisc = bits({UPE = 9}) + -- Pre-allocate storage for the results of register-reads + local r = { + in_mcast_pkts = { r = self.s.MPRC }, + in_bcast_pkts = { r = self.s.BPRC }, + in_pkts = { r = self.s.GPRC }, + in_octets64 = { r = self.s.GORC64 }, + + out_mcast_pkts = { r = self.s.MPTC }, + out_bcast_pkts = { r = self.s.BPTC }, + out_pkts = { r = self.s.GPTC }, + out_octets64 = { r = self.s.GOTC64 }, + } + local r_keys = {} + for k, _ in pairs(r) do + table.insert(r_keys, k) + r[k].v = ffi.new("uint64_t [1]") + end + local function read_registers() + for _, k in ipairs(r_keys) do + r[k].v[0] = r[k].r() + end + end local t = timer.new("Interface "..self.pciaddress.." status checker", function(t) local old = ifTable:get('ifOperStatus') @@ -267,40 +289,37 @@ function M_sf:init_snmp () end ifTable:set('ifPromiscuousMode', - (bit.band(self.r.FCTRL(), bits({UPE = 9})) ~= 0ULL + (bit.band(self.r.FCTRL(), promisc) ~= 0ULL and 1) or 2) -- Update counters - local in_mcast_pkts = self.s.MPRC() - local in_bcast_pkts = self.s.BPRC() - local in_pkts = self.s.GPRC() - local in_octets_lo = self.s.GORCL() - local in_octets_hi = self.s.GORCH() - ifTable:set('ifInMulticastPkts', in_mcast_pkts) - ifTable:set('ifInBroadcastPkts', in_bcast_pkts) - ifTable:set('ifInOctets', in_octets_lo) - ifTable:set('ifHCInOctets', in_octets_lo + - bit.lshift(in_octets_hi, 32)) - ifTable:set('ifInUcastPkts', in_pkts - in_bcast_pkts - - in_mcast_pkts) + read_registers() + ifTable:set('ifHCInMulticastPkts', r.in_mcast_pkts.v[0]) + ifTable:set('ifInMulticastPkts', r.in_mcast_pkts.v[0]) + ifTable:set('ifHCInBroadcastPkts', r.in_bcast_pkts.v[0]) + ifTable:set('ifInBroadcastPkts', r.in_bcast_pkts.v[0]) + local in_ucast_pkts = r.in_pkts.v[0] - r.in_bcast_pkts.v[0] + - r.in_mcast_pkts.v[0] + ifTable:set('ifHCInUcastPkts', in_ucast_pkts) + ifTable:set('ifInUcastPkts', in_ucast_pkts) + ifTable:set('ifHCInOctets', r.in_octets64.v[0]) + ifTable:set('ifInOctets', r.in_octets64.v[0]) + + ifTable:set('ifHCOutMulticastPkts', r.out_mcast_pkts.v[0]) + ifTable:set('ifOutMulticastPkts', r.out_mcast_pkts.v[0]) + ifTable:set('ifHCOutBroadcastPkts', r.out_bcast_pkts.v[0]) + ifTable:set('ifOutBroadcastPkts', r.out_bcast_pkts.v[0]) + local out_ucast_pkts = r.out_pkts.v[0] - r.out_bcast_pkts.v[0] + - r.out_mcast_pkts.v[0] + ifTable:set('ifHCOutUcastPkts', out_ucast_pkts) + ifTable:set('ifOutUcastPkts', out_ucast_pkts) + ifTable:set('ifHCOutOctets', r.out_octets64.v[0]) + ifTable:set('ifOutOctets', r.out_octets64.v[0]) -- The RX receive drop counts are only -- available through the RX stats register. -- We only read stats register #0 here. See comment -- in init_statistics() - ifTable:set('ifInDiscards', tonumber(self.qs.QPRDC[0]())) - - local out_mcast_pkts = self.s.MPTC() - local out_bcast_pkts = self.s.BPTC() - local out_pkts = self.s.GPTC() - local out_octets_lo = self.s.GOTCL() - local out_octets_hi = self.s.GOTCH() - ifTable:set('ifOutMulticastPkts', out_mcast_pkts) - ifTable:set('ifOutBroadcastPkts', out_bcast_pkts) - ifTable:set('ifOutOctets', out_octets_lo) - ifTable:set('ifHCOutOctets', out_octets_lo + - bit.lshift(out_octets_hi, 32)) - ifTable:set('ifOutUcastPkts', out_pkts - out_bcast_pkts - - out_mcast_pkts) + ifTable:set('ifInDiscards', self.qs.QPRDC[0]()) ifTable:set('ifInErrors', self.s.CRCERRS() + self.s.ILLERRC() + self.s.ERRBC() + @@ -1312,6 +1331,7 @@ PRC1522 0x04070 - RC Packets Received [1024 to Max Bytes] Count BPRC 0x04078 - RC Broadcast Packets Received Count MPRC 0x0407C - RC Multicast Packets Received Count GPRC 0x04074 - RC Good Packets Received Count +GORC64 0x04088 - RC64 Good Octets Received Count 64-bit GORCL 0x04088 - RC Good Octets Received Count Low GORCH 0x0408C - RC Good Octets Received Count High RXNFGPC 0x041B0 - RC Good Rx Non-Filtered Packet Counter @@ -1330,6 +1350,7 @@ RXDLPBKPC 0x02F74 - RC DMA Duplicated Good Rx LPBK Packet Counter RXDLPBKBCL 0x02F78 - RC DMA Duplicated Good Rx LPBK Byte Counter Low RXDLPBKBCH 0x02F7C - RC DMA Duplicated Good Rx LPBK Byte Counter High GPTC 0x04080 - RC Good Packets Transmitted Count +GOTC64 0x04090 - RC64 Good Octets Transmitted Count 64-bit GOTCL 0x04090 - RC Good Octets Transmitted Count Low GOTCH 0x04094 - RC Good Octets Transmitted Count High TXDGPC 0x087A0 - RC DMA Good Tx Packet Counter From 0a126b56dcb2c892ddb5da567d94656aa0ea124a Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Wed, 13 May 2015 21:38:07 +0200 Subject: [PATCH 3/3] register.lua: Remove jit.off() voodoo This was added long ago when counter values were "sticking" suspiciously. We have no way to reproduce this problem at present and since it does not appear in recent testing we remove this kludge. The worst anticipated regression would be that counter registers stop updating. If that happens then we will need to revisit the issue. --- src/lib/hardware/register.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/hardware/register.lua b/src/lib/hardware/register.lua index 44f217a046..9fde7aeadb 100644 --- a/src/lib/hardware/register.lua +++ b/src/lib/hardware/register.lua @@ -21,8 +21,6 @@ end --- Read a counter register function Register:readrc () - -- XXX JIT of this function is causing register value to be misread. - jit.off(true,true) self.acc[0] = self.acc[0] + self.ptr[0] return self.acc[0] end