aboutsummaryrefslogtreecommitdiff
path: root/contrib/net.lua
blob: 5e6ba938ffcb06dbcf060cb5241d761af6c2d654 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
---------------------------------------------------
-- Licensed under the GNU General Public License v2
--  * (c) 2010, Adrian C. <anrxc@sysphere.org>
--  * (c) 2009, Henning Glawe <glaweh@debian.org>
--  * (c) 2009, Lucas de Vries <lucas@glacicle.com>
---------------------------------------------------

-- {{{ Grab environment
local pairs = pairs
local tonumber = tonumber
local os = { time = os.time }
local io = { lines = io.lines }
local setmetatable = setmetatable
local string = { match = string.match }
local helpers = require("vicious.helpers")
-- }}}


-- Net: provides usage statistics for all network interfaces
-- vicious.contrib.net
local net = {}


-- Initialise function tables
local nets = {}
-- Variable definitions
local unit = { ["b"] = 1, ["kb"] = 1024,
    ["mb"] = 1024^2, ["gb"] = 1024^3
}

-- {{{ Net widget type
local function worker(format, tignorelist)
    local args    = {}
    local tignore = {}
    local total_rx = 0
    local total_tx = 0
    local any_up   = 0

    if not tignorelist then
        tignorelist = {"lo", "wmaster0"}
    end
    for k, i in pairs(tignorelist) do
        tignore[i] = true
    end

    -- Get NET stats
    for line in io.lines("/proc/net/dev") do
        -- Match wmaster0 as well as rt0 (multiple leading spaces)
        local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
        if name ~= nil then
            -- Received bytes, first value after the name
            local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
            -- Transmited bytes, 7 fields from end of the line
            local send = tonumber(string.match(line,
             "([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))

            if not tignore[name] then
                total_rx = total_rx + recv
                total_tx = total_tx + send
            end

            helpers.uformat(args, name .. " rx", recv, unit)
            helpers.uformat(args, name .. " tx", send, unit)

            if nets[name] == nil then
                -- Default values on the first run
                nets[name] = {}

                helpers.uformat(args, name .. " down", 0, unit)
                helpers.uformat(args, name .. " up",   0, unit)
                args["{"..name.." carrier}"] = 0

                nets[name].time = os.time()
            else -- Net stats are absolute, substract our last reading
                local interval  = os.time() - nets[name].time >  0 and
                                  os.time() - nets[name].time or 1
                nets[name].time = os.time()

                local down = (recv - nets[name][1]) / interval
                local up   = (send - nets[name][2]) / interval

                helpers.uformat(args, name .. " down", down, unit)
                helpers.uformat(args, name .. " up",   up,   unit)

                -- Carrier detection
                sysnet = helpers.pathtotable("/sys/class/net/" .. name)

                if sysnet.carrier then
                    ccarrier = tonumber(sysnet.carrier)

                    args["{"..name.." carrier}"] = ccarrier
                    if ccarrier ~= 0 and not tignore[name] then
                        any_up = 1
                    end
                else
                    args["{"..name.." carrier}"] = 0
                end
            end

            -- Store totals
            nets[name][1] = recv
            nets[name][2] = send
        end
    end

    helpers.uformat(args, "total rx", total_rx, unit)
    helpers.uformat(args, "total tx", total_tx, unit)

    if nets["total"] == nil then
        -- Default values on the first run
        nets["total"] = {}

        helpers.uformat(args, "total down", 0, unit)
        helpers.uformat(args, "total up",   0, unit)
        args["{total carrier}"] =   0

        nets["total"].time = os.time()
    else -- Net stats are absolute, substract our last reading
        local interval = os.time() - nets["total"].time >  0 and
                         os.time() - nets["total"].time or 1
        nets["total"].time = os.time()

        local down = (total_rx - nets["total"][1]) / interval
        local up   = (total_tx - nets["total"][2]) / interval

        helpers.uformat(args, "total down", down, unit)
        helpers.uformat(args, "total up",   up,   unit)
        args["{total carrier}"] = any_up
    end

    -- Store totals
    nets["total"][1] = total_rx
    nets["total"][2] = total_tx

    return args
end
-- }}}

return setmetatable(net, { __call = function(_, ...) return worker(...) end })