File: netdev.tcl

package info (click to toggle)
moodss 14.0-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 2,536 kB
  • ctags: 1,003
  • sloc: tcl: 25,371; ansic: 132; perl: 72; python: 64; sh: 63; makefile: 50
file content (166 lines) | stat: -rw-r--r-- 10,259 bytes parent folder | download
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# copyright (C) 1997-2001 Jean-Luc Fontaine (mailto:jfontain@free.fr)
# this program is free software: please read the COPYRIGHT file enclosed in this package or use the Help Copyright menu

set rcsId {$Id: netdev.tcl,v 2.8 2001/02/04 10:46:20 jfontain Exp $}


package provide netdev [lindex {$Revision: 2.8 $} 1]
package require network 1


namespace eval netdev {

    # documentation from net/core/dev.c and include/linux/netdevice.h kernel source files
    array set data {
        updates 0
        0,label interface 0,type dictionary 0,message {network device name}
        1,label <bytes 1,type integer 1,message {total bytes received}
        2,label <packets 2,type integer 2,message {total packets received}
        3,label <errors 3,type integer 3,message {bad packets received}
        4,label <dropped 4,type integer
            4,message "received packets dropped for lack of space in\nkernel buffers, plus receiver missed packets"
        5,label <FIFO 5,type integer 5,message {receiver FIFO overruns}
        6,label <frame 6,type integer
            6,message "frame alignment errors received, including length,\nreceiver ring buff overflow and CRC errors"
        7,label <compressed 7,type integer 7,message {compressed packets received}
        8,label <multicast 8,type integer 8,message {multicast packets received}
        9,label bytes> 9,type integer 9,message {total bytes transmitted}
        10,label packets> 10,type integer 10,message {total packets transmitted}
        11,label errors> 11,type integer 11,message {packet transmit problems}
        12,label dropped> 12,type integer 12,message "packets not transmitted for\nlack of space in kernel buffers"
        13,label FIFO> 13,type integer 13,message {transmitter FIFO overruns}
        14,label collisions> 14,type integer 14,message {collisions while transmitting}
        15,label carrier> 15,type integer 15,message "carriers errors, including aborted,\nwindow and heartbeat errors"
        16,label compressed> 16,type integer 16,message {compressed packets transmitted}
        17,label <bytes/s 17,type real 17,message "total bytes received\nper second during last poll period"
        18,label <packets/s 18,type real 18,message "total packets received\nper second during last poll period"
        19,label <errors/s 19,type real 19,message "bad packets received\nper second during last poll period"
        20,label <dropped/s 20,type real
            20,message "received packets dropped for lack of space in\nkernel buffers, plus receiver missed packets,\nper second during last poll period"
        21,label <FIFO/s 21,type real 21,message "receiver FIFO overruns\nper second during last poll period"
        22,label <frame/s 22,type real
            22,message "frame alignment errors received, including length,\nreceiver ring buff overflow and CRC errors,\nper second during last poll period"
        23,label <compressed/s 23,type real 23,message "compressed packets received\nper second during last poll period"
        24,label <multicast/s 24,type real 24,message "multicast packets received\nper second during last poll period"
        25,label bytes/s> 25,type real 25,message "total bytes transmitted\nper second during last poll period"
        26,label packets/s> 26,type real 26,message "total packets transmitted\nper second during last poll period"
        27,label errors/s> 27,type real 27,message "packet transmit problems\nper second during last poll period"
        28,label dropped/s> 28,type real
            28,message "packets not transmitted\nfor lack of space in kernel buffers,\nper second during last poll period"
        29,label FIFO/s> 29,type real 29,message "transmitter FIFO overruns\nper second during last poll period"
        30,label collisions/s> 30,type real 30,message "collisions while transmitting\nper second during last poll period"
        31,label carrier/s> 31,type real
            31,message "carriers errors, including aborted,\nwindow and heartbeat errors,\nper second during last poll period"
        32,label compressed/s> 32,type real 32,message "compressed packets transmitted\nper second during last poll period"
        indexColumns 0
        views {
            {visibleColumns {0 1 2 3 4 5 6 7 8} sort {0 increasing}}
            {visibleColumns {0 9 10 11 12 13 14 15 16} sort {0 increasing}}
            {visibleColumns {0 17 18 19 20 21 22 23 24} sort {0 increasing}}
            {visibleColumns {0 25 26 27 28 29 30 31 32} sort {0 increasing}}
        }
        switches {-r 1 --remote 1}
    }
    set file [open netdev.htm]
    set data(helpText) [read $file]                                                           ;# initialize HTML help data from file
    close $file

    proc initialize {optionsName} {
        upvar $optionsName options
        variable remote
        variable data
        variable devicesFile

        if {![catch {set locator $options(--remote)}]||![catch {set locator $options(-r)}]} {                   ;# remote monitoring
            set data(pollTimes) {20 10 30 60 120 300 600}                                ;# poll less often when remotely monitoring
            foreach {remote(protocol) remote(user) remote(host)} [network::parseRemoteLocator $locator] {}
            network::checkRemoteOutputEmptiness $remote(protocol) $remote(user) $remote(host)
            set data(identifier) netdev($remote(host))
            set file [open "| /usr/bin/$remote(protocol) -n -l $remote(user) $remote(host) cat /proc/net/dev"]
            fileevent $file readable {set ::netdev::remote(busy) 0}
            vwait ::netdev::remote(busy)                                                                    ;# allow GUI interaction
            # detect errors early (but avoid write on pipe with no readers errors by reading whole data)
            if {[catch {read $file} message]||[catch {close $file} message]} {
                error "on remote host $remote(host) as user $remote(user): $message"
            }
        } else {
            set data(pollTimes) {10 5 20 30 60 120 300 600}
            set devicesFile [open /proc/net/dev]                                      ;# keep local file open for better performance
        }
    }

    variable nextIndex 0

    proc update {} {                                               ;# gather cpu statistics (based on the proc man page information)
        variable remote
        variable devicesFile
        variable index
        variable nextIndex
        variable data
        variable last

        if {[info exists remote]} {
            if {![info exists devicesFile]} {                              ;# start data gathering process in a non blocking fashion
                if {$remote(busy)} return                                           ;# core invocation while waiting for remote data
                set remote(busy) 1
                set file [open "| /usr/bin/$remote(protocol) -n -l $remote(user) $remote(host) cat /proc/net/dev"]
                # do not hang GUI, allow other modules updates
                fileevent $file readable "set ::netdev::devicesFile $file; ::netdev::update"
                return                                                                                       ;# wait for remote data
            }                                                                                 ;# else continue below to process data
        } else {
            seek $devicesFile 0                                                                     ;# rewind before retrieving data
        }
        gets $devicesFile; gets $devicesFile                                                             ;# skip column titles lines
        while {[gets $devicesFile line]>=0} {
            lappend lines $line
        }
        set clock [expr {[clock clicks -milliseconds]/1000.0}]                         ;# immediately store current clock in seconds
        if {[info exists remote]} {                                                 ;# closing is necessary since seek does not work
            read $devicesFile                                ;# avoid write on pipe with no readers errors by reading remaining data
            if {[catch {close $devicesFile} message]} {
                flashMessage "netdev error: $message"
                set lines {}                                                                   ;# consider data corrupted as a whole
            }
            unset devicesFile
            set remote(busy) 0
        }
        set row 0
        foreach line $lines {
            regsub : $line { } line                      ;# remove column after interface name to make sure of proper list structure
            set interface [lindex $line 0]
            if {[catch {set row $index($interface)}]} {                                                             ;# new interface
                set row [set index($interface) $nextIndex]
                incr nextIndex
            }
            set data($row,0) $interface
            set column 1
            foreach cell [lrange $line 1 end] {
                set data($row,$column) $cell
                if {[info exists last(clock)]} {
                    set data($row,[expr {$column+16}]) [format %.1f [expr {($cell-$last($row,$column))/($clock-$last(clock))}]]
                } else {                                                                                             ;# first update
                    set data($row,[expr {$column+16}]) ?
                }
                set last($row,$column) $cell
                incr column
            }
            set current($interface) {}
            incr row
        }
        set last(clock) $clock
        foreach {interface row} [array get index] {                                                   ;# cleanup disappeared entries
            if {[info exists current($interface)]} continue
            unset index($interface)
            unset data($row,0)
            for {set column 1} {$column<=16} {incr column} {
                unset data($row,$column) last($row,$column)
            }
            for {} {$column<=32} {incr column} {
                unset data($row,$column)
            }
        }
        incr data(updates)
    }

}