路由器的流量圖製作
1.繪製svg 向量圖 bandwidth.svg
註釋:繪製流量圖的方法有三種,
1) :直接將 svg 嵌入的html 頁面中
2 ):通過使用embed/frame 等引用到頁面中去;
<div class="cbi-table">
<embed id="bwsvg" src="/JS/bandwidth.svg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" type="image/svg+xml" pluginspage="http://www.adobe.com/svg/viewer/install/"/>
<div style="text-align:right"><small id="scale">2 分鐘繪圖,1 秒重新整理</small></div>
<br />
</div>
3):在html 頁面中動態的建立
<div class="cbi-table">
<embed id="bwsvg" style="width:100%; height:320px; border:1px solid #000000; background-color:#FFFFFF" type="image/svg+xml" pluginspage="http://www.adobe.com/svg/viewer/install/" src="/JS/bandwidth.svg" />
<div style="text-align:right"><small id="scale">2 分鐘繪圖,1 秒重新整理</small></div>
<br />
</div>
function LoadFrame()
{
<% if tcwebApi_get("WebCustom_Entry","isSVGSupported","h") = "Yes" then %>
var svg = document.getElementById('bwsvg');
var line_25=document.createElementNS("http://www.w3.org/2000/svg","line");
//水平線25%
if(line_25)
{
line_25.setAttribute('x1',0);
line_25.setAttribute('y1',"25%");
line_25.setAttribute('x2',"100%");
line_25.setAttribute('y2',"25%");
line_25.setAttribute("style","stroke:black;stroke-width:0.1");
svg.appendChild(line_25);
}
text_25=document.createElementNS("http://www.w3.org/2000/svg","text");
if(text_25)
{
text_25.setAttribute('x',15);
text_25.setAttribute('y',"75%");
text_25.setAttribute("id","label_25");
text_25.setAttribute("style","fill:black; font-size:9pt");
svg.appendChild(text_25);
}
//水平線50%
var line_50=document.createElementNS("http://www.w3.org/2000/svg","line");
if(line_50)
{
line_50.setAttribute('x1',0);
line_50.setAttribute('y1',"50%");
line_50.setAttribute('x2',"100%");
line_50.setAttribute('y2',"50%");
line_50.setAttribute("style","stroke:black;stroke-width:0.1");
svg.appendChild(line_50);
}
text_50=document.createElementNS("http://www.w3.org/2000/svg","text");
if(text_50)
{
text_50.setAttribute('x',15);
text_50.setAttribute('y',"50%");
text_50.setAttribute("id","label_50");
text_50.setAttribute("style","fill:black; font-size:9pt");
svg.appendChild(text_50);
}
//水平線75%
var line_75=document.createElementNS("http://www.w3.org/2000/svg","line");
if(line_75)
{
line_75.setAttribute('x1',0);
line_75.setAttribute('y1',"75%");
line_75.setAttribute('x2',"100%");
line_75.setAttribute('y2',"75%");
line_75.setAttribute("style","stroke:black;stroke-width:0.1");
svg.appendChild(line_75);
}
text_75=document.createElementNS("http://www.w3.org/2000/svg","text");
if(text_75)
{
text_75.setAttribute('x',15);
text_75.setAttribute('y',"25%");
text_75.setAttribute("id","label_75");
text_75.setAttribute("style","fill:black; font-size:9pt");
svg.appendChild(text_75);
}
text_v=document.createElementNS("http://www.w3.org/2000/svg","text");
if(text_v)
{
//text_v.setAttribute("x",50);
//text_v.setAttribute("y","74%");
text_v.setAttribute("id","label_v");
text_v.setAttribute("style","fill:#FF0000; font-size:9pt");
svg.appendChild(text_v);
}
//折線
line_rx=document.createElementNS("http://www.w3.org/2000/svg","polyline");
if(line_rx)
{
line_rx.setAttribute("point","");
line_rx.setAttribute("id","rx");
line_rx.setAttribute("style","fill:red;fill-opacity:0.4;stroke:red;stroke-width:1");
svg.appendChild(line_rx);
}
line_tx=document.createElementNS("http://www.w3.org/2000/svg","polyline");
if(line_tx)
{
line_tx.setAttribute("point","");
line_tx.setAttribute("id","tx");
line_tx.setAttribute("style","fill:blue;fill-opacity:0.4;stroke:blue;stroke-width:1");
svg.appendChild(line_tx);
}
for (var i = step * 60; i < width; i += step * 60)
{
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i-5);
line.setAttribute('y1', 0);
line.setAttribute('x2', i-5);
line.setAttribute('y2', '100%');
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', i + 5);
text.setAttribute('y', 15);
text.setAttribute('style', 'fill:#999999; font-size:9pt');
text.appendChild(document.createTextNode(Math.round(i / step / 60) + 'min'));
text_v.parentNode.appendChild(line);
text_v.parentNode.appendChild(text);
}
label_rx_cur = document.getElementById('rx_bw_cur');
label_rx_avg = document.getElementById('rx_bw_avg');
label_rx_peak = document.getElementById('rx_bw_peak');
label_tx_cur = document.getElementById('tx_bw_cur');
label_tx_avg = document.getElementById('tx_bw_avg');
label_tx_peak = document.getElementById('tx_bw_peak');
window.setTimeout(update_graph, 1000);
<% end if %>
}
function update_graph()
{
console.log("...data_max="+data_max);
data_max=0;
bwxhr.get('/cgi-bin/traffic.cgi', null,
function(x, data)
{
var data_scale = 0;
var data_rx_avg = 0;
var data_tx_avg = 0;
var data_rx_peak = 0;
var data_tx_peak = 0;
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
{
if (data[i][TIME] <= data_stamp)
continue;
//。兩個時間資料之間的差值
var time_delta = data[i][TIME] - data[i-1][TIME];
if (time_delta)
{
data_rx.push((data[i][RXB] - data[i-1][RXB]) / time_delta);
data_tx.push((data[i][TXB] - data[i-1][TXB]) / time_delta);
}
}
//從陣列中擷取data_rx.length 0~data_rx.length - data_wanted
data_rx = data_rx.slice(data_rx.length - data_wanted, data_rx.length);
data_tx = data_tx.slice(data_tx.length - data_wanted, data_tx.length);
//尋找這組資料的最大值
for (var i = 0; i < data_rx.length; i++)
{
data_max = Math.max(data_max, data_rx[i]);
//data_max = Math.max(data_max, data_tx[i]);
data_rx_peak = Math.max(data_rx_peak, data_rx[i]);
data_tx_peak = Math.max(data_tx_peak, data_tx[i]);
if (i > 0)
{
data_rx_avg = (data_rx_avg + data_rx[i]) / 2;
data_tx_avg = (data_tx_avg + data_tx[i]) / 2;
}
else
{
data_rx_avg = data_rx[i];
data_tx_avg = data_tx[i];
}
}
//最後一組時間資料
data_stamp = data[data.length-1][TIME];
data_scale = height / (data_max * 1.1);
var pt_rx = '0,' + height;
var pt_tx = '0,' + height;
var y_rx = 0;
var y_tx = 0;
for (var i = 0; i < data_rx.length; i++)
{
var x = i * step * 2;
y_rx = height - Math.floor(data_rx[i] * data_scale);
y_tx = height - Math.floor(data_tx[i] * data_scale);
pt_rx += ' ' + x + ',' + y_rx;
pt_tx += ' ' + x + ',' + y_tx;
}
pt_rx += ' ' + width + ',' + y_rx + ' ' + width + ',' + height;
pt_tx += ' ' + width + ',' + y_tx + ' ' + width + ',' + height;
line_rx.setAttribute('points', pt_rx);
line_tx.setAttribute('points', pt_tx);
var textNode=document.createTextNode( bandwidth_label(1.1 * 0.75 * data_max));
var L75Node=getElementById("label_75");
var childs75 = L75Node.childNodes;
for(var i=0;i<childs75.length;i++)
{
L75Node.removeChild(childs75[i]);
}
text_75.appendChild(textNode);
var textNode=document.createTextNode( bandwidth_label(1.1 * 0.5 * data_max));
var L50Node=getElementById("label_50");
var childs50 = L50Node.childNodes;
for(var i=0;i<childs50.length;i++)
{
L50Node.removeChild(childs50[i]);
}
text_50.appendChild(textNode);
var textNode=document.createTextNode( bandwidth_label(1.1 * 0.25 * data_max));
var L25Node=getElementById("label_25");
var childs25 = L25Node.childNodes;
for(var i=0;i<childs25.length;i++)
{
L25Node.removeChild(childs25[i]);
}
text_25.appendChild(textNode);
//顯示下面資料值
label_rx_cur.innerHTML = bandwidth_label(data_rx[data_rx.length-1], true);
label_tx_cur.innerHTML = bandwidth_label(data_tx[data_tx.length-1], true);
label_rx_avg.innerHTML = bandwidth_label(data_rx_avg, true);
label_tx_avg.innerHTML = bandwidth_label(data_tx_avg, true);
label_rx_peak.innerHTML = bandwidth_label(data_rx_peak, true);
label_tx_peak.innerHTML = bandwidth_label(data_tx_peak, true);
window.setTimeout(update_graph, 1000);
}
)
}
3.頁面顯示程式碼實現:
4:頁面程式碼的資料處理
<script type="text/javascript">//<![CDATA[
var bwxhr = new XHR();
var G;
var TIME = 0;
var RXB = 1;
var RXP = 2;
var TXB = 3;
var TXP = 4;
var width = 460;
var height = 300;
var step = 3;
var data_wanted = Math.floor(width / step);
var data_fill = 0;
var data_stamp = 0;
var data_rx = [ ];
var data_tx = [ ];
var line_rx;
var line_tx;
var label_25;
var label_50;
var label_75;
var label_rx_cur;
var label_rx_avg;
var label_rx_peak;
var label_tx_cur;
var label_tx_avg;
var label_tx_peak;
var label_scale;
var objstring=new String();
function bandwidth_label(bytes, br)
{
var uby = 'KByte';
var kby = (bytes / 1024);
if (kby >= 1024)
{
uby = 'MByte';
kby = kby / 1024;
}
var ubi = 'KBit';
var kbi = (bytes * 8 / 1024);
if (kbi >= 1024)
{
ubi = 'MBit';
kbi = kbi / 1024;
}
var tmp=objstring.concat(kbi.toFixed(2), ubi,"/s",(br ? '<br />' : ' '),"(",kby.toFixed(2), uby,"/s)");
//return String.format("%f %s/s%s(%f %s/s)",kbi.toFixed(2), ubi,br ? '<br />' : ' ',kby.toFixed(2), uby);
return tmp;
}
/*********頁面流量圖資料的重新整理處理********/
function update_graph(){
bwxhr.get('/cgi-bin/traffic.cgi', null,
function(x, data)
{
var data_max = 0;
var data_scale = 0;
var data_rx_avg = 0;
var data_tx_avg = 0;
var data_rx_peak = 0;
var data_tx_peak = 0;
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
{
/* skip overlapping entries */
if (data[i][TIME] <= data_stamp)
continue;
/* normalize difference against time interval */
//。兩個時間資料之間的差值
var time_delta = data[i][TIME] - data[i-1][TIME];
if (time_delta)
{
//像data_rx陣列中新增一個單位時間收發的資料量
data_rx.push((data[i][RXB] - data[i-1][RXB]) / time_delta);
data_tx.push((data[i][TXB] - data[i-1][TXB]) / time_delta);
}
}
//從陣列中擷取data_rx.length 0~data_rx.length - data_wanted
data_rx = data_rx.slice(data_rx.length - data_wanted, data_rx.length);
data_tx = data_tx.slice(data_tx.length - data_wanted, data_tx.length);
//尋找這組資料的最大值
for (var i = 0; i < data_rx.length; i++)
{
data_max = Math.max(data_max, data_rx[i]);
data_max = Math.max(data_max, data_tx[i]);
data_rx_peak = Math.max(data_rx_peak, data_rx[i]);
data_tx_peak = Math.max(data_tx_peak, data_tx[i]);
if (i > 0)
{
data_rx_avg = (data_rx_avg + data_rx[i]) / 2;
data_tx_avg = (data_tx_avg + data_tx[i]) / 2;
}
else
{
data_rx_avg = data_rx[i];
data_tx_avg = data_tx[i];
}
}
/* remember current timestamp, calculate horizontal scale */
//最後一組時間資料
data_stamp = data[data.length-1][TIME];
data_scale = height / (data_max * 1.1);
/* plot data */
var pt_rx = '0,' + height;
var pt_tx = '0,' + height;
var y_rx = 0;
var y_tx = 0;
for (var i = 0; i < data_rx.length; i++)
{
var x = i * step;
y_rx = height - Math.floor(data_rx[i] * data_scale);
y_tx = height - Math.floor(data_tx[i] * data_scale);
pt_rx += ' ' + x + ',' + y_rx;
pt_tx += ' ' + x + ',' + y_tx;
}
pt_rx += ' ' + width + ',' + y_rx + ' ' + width + ',' + height;
pt_tx += ' ' + width + ',' + y_tx + ' ' + width + ',' + height;
line_rx.setAttribute('points', pt_rx);
line_tx.setAttribute('points', pt_tx);
label_25.firstChild.data = bandwidth_label(1.1 * 0.25 * data_max);
label_50.firstChild.data = bandwidth_label(1.1 * 0.50 * data_max);
label_75.firstChild.data = bandwidth_label(1.1 * 0.75 * data_max);
label_rx_cur.innerHTML = bandwidth_label(data_rx[data_rx.length-1], true);
label_tx_cur.innerHTML = bandwidth_label(data_tx[data_tx.length-1], true);
label_rx_avg.innerHTML = bandwidth_label(data_rx_avg, true);
label_tx_avg.innerHTML = bandwidth_label(data_tx_avg, true);
label_rx_peak.innerHTML = bandwidth_label(data_rx_peak, true);
label_tx_peak.innerHTML = bandwidth_label(data_tx_peak, true);
}
)
}
/* wait for SVG */
window.setTimeout(
function() {
//先獲取頁面元素物件
var svg = document.getElementById('bwsvg');
//獲取SVG 物件
try {
G = svg.getSVGDocument
? svg.getSVGDocument() : svg.contentDocument;
}
catch(e) {
G = document.embeds['bwsvg'].getSVGDocument();
}
if (!G)
{
window.setTimeout(arguments.callee, 1000);
}
else
{
/* find sizes */
width = svg.offsetWidth - 2;
height = svg.offsetHeight - 2;
data_wanted = Math.ceil(width / step);
//初始化data_rx tx
for (var i = 0; i < data_wanted; i++)
{
data_rx[i] = 0;
data_tx[i] = 0;
}
/* find svg elements */
line_rx = G.getElementById('rx');//polyline rx
line_tx = G.getElementById('tx');//polyline tx
label_25 = G.getElementById('label_25');
label_50 = G.getElementById('label_50');
label_75 = G.getElementById('label_75');
label_rx_cur = document.getElementById('rx_bw_cur');
label_rx_avg = document.getElementById('rx_bw_avg');
label_rx_peak = document.getElementById('rx_bw_peak');
label_tx_cur = document.getElementById('tx_bw_cur');
label_tx_avg = document.getElementById('tx_bw_avg');
label_tx_peak = document.getElementById('tx_bw_peak');
label_scale = document.getElementById('scale');
/* plot horizontal time interval lines */
for (var i = step * 60; i < width; i += step * 60)
{
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i-5);
line.setAttribute('y1', 0);
line.setAttribute('x2', i-5);
line.setAttribute('y2', '100%');
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
//text.setAttribute('x', i + 5);
text.setAttribute('x', i-5);
text.setAttribute('y', 15);
text.setAttribute('style', 'fill:#999999; font-size:9pt');
text.appendChild(G.createTextNode(Math.round(i / step / 60) + 'min'));
label_25.parentNode.appendChild(line);
label_25.parentNode.appendChild(text);
}
//label_scale.innerHTML = String.format('( %d 分鐘繪圖,%d 秒重新整理)', data_wanted / 60, 1);
/* render datasets, start update interval */
update_graph();
}
}, 1000
);
//]]></script>
頁面的引用xhr.js
/*
* xhr.js - XMLHttpRequest helper class
* (c) 2008-2010 Jo-Philipp Wich
*/
XHR = function()
{
this.reinit = function()
{
if( window.XMLHttpRequest ) {
this._xmlHttp = new XMLHttpRequest();
}
else if( window.ActiveXObject ) {
this._xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else {
alert("xhr.js: XMLHttpRequest is not supported by this browser!");
}
}
this.busy = function() {
switch( this._xmlHttp.readyState )
{
case 1:
case 2:
case 3:
return true;
default:
return false;
}
}
this.abort = function() {
if( this.busy() )
this._xmlHttp.abort();
}
this.get = function(url,data,callback)
{
this.reinit();
var xhr = this._xmlHttp;
var code = this._encode( data );
url = location.protocol + '//' + location.hostname +
( location.port ? ':' + location.port : '' ) + url;
if( code )
if( url.substr(url.length-1,1) == '&' )
url += code;
else
url += '?' + code;
xhr.open( 'GET', url, true );
xhr.onreadystatechange = function()
{
if( xhr.readyState == 4 ) {
var json = null;
if( xhr.getResponseHeader("Content-Type") == "application/json" ) {
try {
json = eval('(' + xhr.responseText + ')');
}
catch(e) {
json = null;
}
}
callback( xhr, json );
}
}
xhr.send( null );
}
this.post = function(url,data,callback)
{
this.reinit();
var xhr = this._xmlHttp;
var code = this._encode( data );
xhr.onreadystatechange = function()
{
if( xhr.readyState == 4 )
callback( xhr );
}
xhr.open( 'POST', url, true );
xhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );
xhr.setRequestHeader( 'Content-length', code.length );
xhr.setRequestHeader( 'Connection', 'close' );
xhr.send( code );
}
this.cancel = function()
{
this._xmlHttp.onreadystatechange = function(){};
this._xmlHttp.abort();
}
this.send_form = function(form,callback,extra_values)
{
var code = '';
for( var i = 0; i < form.elements.length; i++ )
{
var e = form.elements[i];
if( e.options )
{
code += ( code ? '&' : '' ) +
form.elements[i].name + '=' + encodeURIComponent(
e.options[e.selectedIndex].value
);
}
else if( e.length )
{
for( var j = 0; j < e.length; j++ )
if( e[j].name ) {
code += ( code ? '&' : '' ) +
e[j].name + '=' + encodeURIComponent( e[j].value );
}
}
else
{
code += ( code ? '&' : '' ) +
e.name + '=' + encodeURIComponent( e.value );
}
}
if( typeof extra_values == 'object' )
for( var key in extra_values )
code += ( code ? '&' : '' ) +
key + '=' + encodeURIComponent( extra_values[key] );
return(
( form.method == 'get' )
? this.get( form.getAttribute('action'), code, callback )
: this.post( form.getAttribute('action'), code, callback )
);
}
this._encode = function(obj)
{
obj = obj ? obj : { };
obj['_'] = Math.random();
if( typeof obj == 'object' )
{
var code = '';
var self = this;
for( var k in obj )
code += ( code ? '&' : '' ) +
k + '=' + encodeURIComponent( obj[k] );
return code;
}
return obj;
}
}
5.資料獲取的處理函式
/* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _BWC_H__
#define _BWC_H__
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <sys/types.h>
#define STEP_COUNT60
#define STEP_TIME1
#define DB_PATH"/var/lib/bwc"
#define DB_IF_FILEDB_PATH "/if/%s"
#define DB_CN_FILEDB_PATH "/connections"
#define DB_LD_FILEDB_PATH "/load"
#define IF_SCAN_PATTERN \
" %[^ :]:%" SCNu64 " %" SCNu64 \
" %*d %*d %*d %*d %*d %*d" \
" %" SCNu64 " %" SCNu64
#define LD_SCAN_PATTERN \
"%f %f %f"
//typedef unsigned long long uint64_t;
struct file_map {
int fd;
int size;
char *mmap;
};
struct traffic_entry {
uint64_t time;
uint64_t rxb;
uint64_t rxp;
uint64_t txb;
uint64_t txp;
};
#endif
檔案bwc.c
#include "bwc.h"
#define ntohll htonll
static uint64_t htonll(uint64_t value)
{
int num = 1;
if (*(char *)&num == 1)
return htonl((uint32_t)(value & 0xFFFFFFFF)) |
htonl((uint32_t)(value >> 32));
return value;
}
static int init_directory(char *path)
{
char *p = path;
for (p = &path[1]; *p; p++)
{
if (*p == '/')
{
*p = 0;
if (mkdir(path, 0700) && (errno != EEXIST))
return -1;
*p = '/';
}
}
return 0;
}
static int init_file(char *path, int esize)
{
int i, file;
char buf[sizeof(struct traffic_entry)] = { 0 };
if (init_directory(path))
return -1;
if ((file = open(path, O_WRONLY | O_CREAT, 0600)) >= 0)
{
for (i = 0; i < STEP_COUNT; i++)
{
if (write(file, buf, esize) < 0)
break;
}
close(file);
return 0;
}
return -1;
}
static int update_file(const char *path, void *entry, int esize)
{
int rv = -1;
int file;
char *map;
if ((file = open(path, O_RDWR)) >= 0)
{
map = mmap(NULL, esize * STEP_COUNT, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_LOCKED, file, 0);
if ((map != NULL) && (map != MAP_FAILED))
{
memmove(map, map + esize, esize * (STEP_COUNT-1));
//拷貝
memcpy(map + esize * (STEP_COUNT-1), entry, esize);
munmap(map, esize * STEP_COUNT);
rv = 0;
}
close(file);
}
return rv;
}
#if 0
static int mmap_file(const char *path, int esize, struct file_map *m)
{
m->fd = -1;
m->size = -1;
m->mmap = NULL;
if ((m->fd = open(path, O_RDONLY)) >= 0)
{
m->size = STEP_COUNT * esize;
m->mmap = mmap(NULL, m->size, PROT_READ,
MAP_SHARED | MAP_LOCKED, m->fd, 0);
if ((m->mmap != NULL) && (m->mmap != MAP_FAILED))
return 0;
}
return -1;
}
static void umap_file(struct file_map *m)
{
if ((m->mmap != NULL) && (m->mmap != MAP_FAILED))
munmap(m->mmap, m->size);
if (m->fd > -1)
close(m->fd);
}
#endif
/**/
static int update_ifstat(
const char *ifname, uint64_t rxb, uint64_t rxp, uint64_t txb, uint64_t txp
) {
char path[1024];
struct stat s;
struct traffic_entry e;
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
if (stat(path, &s))
{
if (init_file(path, sizeof(struct traffic_entry)))
{
fprintf(stderr, "Failed to init %s: %s\n",
path, strerror(errno));
return -1;
}
}
e.time = htonll(time(NULL));
e.rxb = htonll(rxb);
e.rxp = htonll(rxp);
e.txb = htonll(txb);
e.txp = htonll(txp);
return update_file(path, &e, sizeof(struct traffic_entry));
}
int svg_writedata()
{
FILE *info;
uint64_t rxb, txb, rxp, txp;
uint32_t udp, tcp, other;
float lf1, lf5, lf15;
char line[1024];
char ifname[16];
struct stat s;
if ((info = fopen("/proc/net/dev", "r")) != NULL)
{
while (fgets(line, sizeof(line), info))
{
if (strchr(line, '|'))
continue;
if (sscanf(line, IF_SCAN_PATTERN, ifname, &rxb, &rxp, &txb, &txp))
{
if (strncmp(ifname, "lo", sizeof(ifname)))
update_ifstat(ifname, rxb, rxp, txb, txp);
}
}
fclose(info);
}
}
檔案luci-bwc.c
/*
* luci-bwc - Very simple bandwidth collector cache for LuCI realtime graphs
*
* Copyright (C) 2010 Jo-Philipp Wich <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#define STEP_COUNT60
#define STEP_TIME1
#define DB_PATH"/var/lib/bwc"
#define DB_IF_FILEDB_PATH "/if/%s"
#define DB_CN_FILEDB_PATH "/connections"
#define DB_LD_FILEDB_PATH "/load"
#define IF_SCAN_PATTERN \
" %[^ :]:%" SCNu64 " %" SCNu64 \
" %*d %*d %*d %*d %*d %*d" \
" %" SCNu64 " %" SCNu64
#define LD_SCAN_PATTERN \
"%f %f %f"
struct file_map {
int fd;
int size;
char *mmap;
};
struct traffic_entry {
uint64_t time;
uint64_t rxb;
uint64_t rxp;
uint64_t txb;
uint64_t txp;
};
struct conn_entry {
uint64_t time;
uint32_t udp;
uint32_t tcp;
uint32_t other;
};
struct load_entry {
uint64_t time;
uint16_t load1;
uint16_t load5;
uint16_t load15;
};
static uint64_t htonll(uint64_t value)
{
int num = 1;
if (*(char *)&num == 1)
return htonl((uint32_t)(value & 0xFFFFFFFF)) |
htonl((uint32_t)(value >> 32));
return value;
}
#define ntohll htonll
static int init_directory(char *path)
{
char *p = path;
for (p = &path[1]; *p; p++)
{
if (*p == '/')
{
*p = 0;
if (mkdir(path, 0700) && (errno != EEXIST))
return -1;
*p = '/';
}
}
return 0;
}
static int init_file(char *path, int esize)
{
int i, file;
char buf[sizeof(struct traffic_entry)] = { 0 };
if (init_directory(path))
return -1;
if ((file = open(path, O_WRONLY | O_CREAT, 0600)) >= 0)
{
for (i = 0; i < STEP_COUNT; i++)
{
if (write(file, buf, esize) < 0)
break;
}
close(file);
return 0;
}
return -1;
}
static int update_file(const char *path, void *entry, int esize)
{
int rv = -1;
int file;
char *map;
if ((file = open(path, O_RDWR)) >= 0)
{
map = mmap(NULL, esize * STEP_COUNT, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_LOCKED, file, 0);
if ((map != NULL) && (map != MAP_FAILED))
{
memmove(map, map + esize, esize * (STEP_COUNT-1));
//拷貝
memcpy(map + esize * (STEP_COUNT-1), entry, esize);
munmap(map, esize * STEP_COUNT);
rv = 0;
}
close(file);
}
return rv;
}
static int mmap_file(const char *path, int esize, struct file_map *m)
{
m->fd = -1;
m->size = -1;
m->mmap = NULL;
if ((m->fd = open(path, O_RDONLY)) >= 0)
{
m->size = STEP_COUNT * esize;
m->mmap = mmap(NULL, m->size, PROT_READ,
MAP_SHARED | MAP_LOCKED, m->fd, 0);
if ((m->mmap != NULL) && (m->mmap != MAP_FAILED))
return 0;
}
return -1;
}
static void umap_file(struct file_map *m)
{
if ((m->mmap != NULL) && (m->mmap != MAP_FAILED))
munmap(m->mmap, m->size);
if (m->fd > -1)
close(m->fd);
}
static int update_ifstat(
const char *ifname, uint64_t rxb, uint64_t rxp, uint64_t txb, uint64_t txp
) {
char path[1024];
struct stat s;
struct traffic_entry e;
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
if (stat(path, &s))
{
if (init_file(path, sizeof(struct traffic_entry)))
{
fprintf(stderr, "Failed to init %s: %s\n",
path, strerror(errno));
return -1;
}
}
e.time = htonll(time(NULL));
e.rxb = htonll(rxb);
e.rxp = htonll(rxp);
e.txb = htonll(txb);
e.txp = htonll(txp);
return update_file(path, &e, sizeof(struct traffic_entry));
}
static int update_cnstat(uint32_t udp, uint32_t tcp, uint32_t other)
{
char path[1024];
struct stat s;
struct conn_entry e;
snprintf(path, sizeof(path), DB_CN_FILE);
if (stat(path, &s))
{
if (init_file(path, sizeof(struct conn_entry)))
{
fprintf(stderr, "Failed to init %s: %s\n",
path, strerror(errno));
return -1;
}
}
e.time = htonll(time(NULL));
e.udp = htonl(udp);
e.tcp = htonl(tcp);
e.other = htonl(other);
return update_file(path, &e, sizeof(struct conn_entry));
}
static int update_ldstat(uint16_t load1, uint16_t load5, uint16_t load15)
{
char path[1024];
struct stat s;
struct load_entry e;
snprintf(path, sizeof(path), DB_LD_FILE);
if (stat(path, &s))
{
if (init_file(path, sizeof(struct load_entry)))
{
fprintf(stderr, "Failed to init %s: %s\n",
path, strerror(errno));
return -1;
}
}
e.time = htonll(time(NULL));
e.load1 = htons(load1);
e.load5 = htons(load5);
e.load15 = htons(load15);
return update_file(path, &e, sizeof(struct load_entry));
}
static int run_daemon(int nofork)
{
FILE *info;
uint64_t rxb, txb, rxp, txp;
uint32_t udp, tcp, other;
float lf1, lf5, lf15;
char line[1024];
char ifname[16];
struct stat s;
const char *ipc = stat("/proc/net/nf_conntrack", &s)
? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack";
if (!nofork)
{
switch (fork())
{
case -1:
perror("fork()");
return -1;
case 0:
if (chdir("/") < 0)
{
perror("chdir()");
exit(1);
}
close(0);
close(1);
close(2);
break;
default:
exit(0);
}
}
/* go */
while (1)
{
if ((info = fopen("/proc/net/dev", "r")) != NULL)
{
while (fgets(line, sizeof(line), info))
{
if (strchr(line, '|'))
continue;
if (sscanf(line, IF_SCAN_PATTERN, ifname, &rxb, &rxp, &txb, &txp))
{
if (strncmp(ifname, "lo", sizeof(ifname)))
update_ifstat(ifname, rxb, rxp, txb, txp);
}
}
fclose(info);
}
if ((info = fopen(ipc, "r")) != NULL)
{
udp = 0;
tcp = 0;
other = 0;
while (fgets(line, sizeof(line), info))
{
if (strstr(line, "TIME_WAIT"))
continue;
if (sscanf(line, "%*s %*d %s", ifname) || sscanf(line, "%s %*d", ifname))
{
if (!strcmp(ifname, "tcp"))
tcp++;
else if (!strcmp(ifname, "udp"))
udp++;
else
other++;
}
}
update_cnstat(udp, tcp, other);
fclose(info);
}
if ((info = fopen("/proc/loadavg", "r")) != NULL)
{
if (fscanf(info, LD_SCAN_PATTERN, &lf1, &lf5, &lf15))
{
update_ldstat((uint16_t)(lf1 * 100),
(uint16_t)(lf5 * 100),
(uint16_t)(lf15 * 100));
}
fclose(info);
}
sleep(STEP_TIME);
}
}
static int run_dump_ifname(const char *ifname)
{
int i;
char path[1024];
struct file_map m;
struct traffic_entry *e;
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
if (mmap_file(path, sizeof(struct traffic_entry), &m))
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return 1;
}
for (i = 0; i < m.size; i += sizeof(struct traffic_entry))
{
e = (struct traffic_entry *) &m.mmap[i];
if (!e->time)
continue;
printf("[ %" PRIu64 ", %" PRIu64 ", %" PRIu64
", %" PRIu64 ", %" PRIu64 " ]%s\n",
ntohll(e->time),
ntohll(e->rxb), ntohll(e->rxp),
ntohll(e->txb), ntohll(e->txp),
((i + sizeof(struct traffic_entry)) < m.size) ? "," : "");
}
umap_file(&m);
return 0;
}
static int run_dump_conns(void)
{
int i;
char path[1024];
struct file_map m;
struct conn_entry *e;
snprintf(path, sizeof(path), DB_CN_FILE);
if (mmap_file(path, sizeof(struct conn_entry), &m))
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return 1;
}
for (i = 0; i < m.size; i += sizeof(struct conn_entry))
{
e = (struct conn_entry *) &m.mmap[i];
if (!e->time)
continue;
printf("[ %" PRIu64 ", %u, %u, %u ]%s\n",
ntohll(e->time), ntohl(e->udp),
ntohl(e->tcp), ntohl(e->other),
((i + sizeof(struct conn_entry)) < m.size) ? "," : "");
}
umap_file(&m);
return 0;
}
static int run_dump_load(void)
{
int i;
char path[1024];
struct file_map m;
struct load_entry *e;
snprintf(path, sizeof(path), DB_LD_FILE);
if (mmap_file(path, sizeof(struct load_entry), &m))
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return 1;
}
for (i = 0; i < m.size; i += sizeof(struct load_entry))
{
e = (struct load_entry *) &m.mmap[i];
if (!e->time)
continue;
printf("[ %" PRIu64 ", %u, %u, %u ]%s\n",
ntohll(e->time),
ntohs(e->load1), ntohs(e->load5), ntohs(e->load15),
((i + sizeof(struct load_entry)) < m.size) ? "," : "");
}
umap_file(&m);
return 0;
}
int main(int argc, char *argv[])
{
int opt;
int daemon = 0;
int nofork = 0;
while ((opt = getopt(argc, argv, "dfi:cl")) > -1)
{
switch (opt)
{
case 'd':
daemon = 1;
break;
case 'f':
nofork = 1;
break;
case 'i':
if (optarg)
return run_dump_ifname(optarg);
break;
case 'c':
return run_dump_conns();
case 'l':
return run_dump_load();
default:
break;
}
}
if (daemon)
return run_daemon(nofork);
else
fprintf(stderr,
"Usage:\n"
"%s -d [-f]\n"
"%s -i ifname\n"
"%s -c\n"
"%s -l\n",
argv[0], argv[0], argv[0], argv[0]
);
return 1;
}
trafiic.cgi 檔案
獲取到的資料:
timerxb(bytes)rxp(packets) txbtxp
[
[ 1525791505, 2713473997, 2076240, 1082240, 5642 ],
[ 1525791506, 2713766199, 2076461, 1082240, 5642 ],
[ 1525791507, 2714048619, 2076674, 1082240, 5642 ],
[ 1525791508, 2714310395, 2076870, 1082240, 5642 ],
[ 1525791509, 2714655101, 2077125, 1082240, 5642 ],
[ 1525791510, 2715002651, 2077384, 1082240, 5642 ],
[ 1525791511, 2715264395, 2077580, 1082240, 5642 ],
[ 1525791512, 2715496235, 2077755, 1082240, 5642 ],
[ 1525791513, 2715728233, 2077930, 1082240, 5642 ],
[ 1525791514, 2716014869, 2078148, 1082240, 5642 ],
[ 1525791515, 2716303733, 2078362, 1082240, 5642 ],
[ 1525791516, 2716549073, 2078545, 1082240, 5642 ],
[ 1525791517, 2716714265, 2078671, 1082240, 5642 ],
[ 1525791518, 2716898467, 2078811, 1082240, 5642 ],
[ 1525791520, 2717081247, 2078949, 1082240, 5642 ],
[ 1525791521, 2717283245, 2079102, 1082240, 5642 ],
[ 1525791522, 2717538151, 2079292, 1082240, 5642 ],
[ 1525791523, 2717835431, 2079515, 1082240, 5642 ],
[ 1525791524, 2718148935, 2079749, 1082240, 5642 ],
[ 1525791525, 2718557715, 2080052, 1082240, 5642 ],
[ 1525791526, 2718854871, 2080274, 1082240, 5642 ],
[ 1525791527, 2719098849, 2080456, 1082240, 5642 ],
[ 1525791528, 2719252995, 2080573, 1082240, 5642 ],
[ 1525791529, 2719416675, 2080697, 1082240, 5642 ],
[ 1525791530, 2719565463, 2080810, 1082240, 5642 ],
[ 1525791531, 2719747209, 2080953, 1082240, 5642 ],
[ 1525791532, 2719929837, 2081089, 1082240, 5642 ],
[ 1525791533, 2720096544, 2081217, 1082240, 5642 ],
[ 1525791534, 2720257560, 2081340, 1082240, 5642 ],
[ 1525791535, 2720417094, 2081460, 1082240, 5642 ],
[ 1525791536, 2720556322, 2081567, 1082240, 5642 ],
[ 1525791537, 2720808532, 2081756, 1082240, 5642 ],
[ 1525791538, 2721011862, 2081911, 1082240, 5642 ],
[ 1525791540, 2721217824, 2082069, 1082240, 5642 ],
[ 1525791541, 2721445610, 2082241, 1082240, 5642 ],
[ 1525791542, 2721581994, 2082351, 1082240, 5642 ],
[ 1525791543, 2721725453, 2082462, 1082240, 5642 ],
[ 1525791544, 2721859109, 2082563, 1082240, 5642 ],
[ 1525791545, 2722011833, 2082678, 1082240, 5642 ],
[ 1525791546, 2722170215, 2082799, 1082240, 5642 ],
[ 1525791547, 2722317551, 2082911, 1082240, 5642 ],
[ 1525791548, 2722475723, 2083030, 1082240, 5642 ],
[ 1525791549, 2722649027, 2083161, 1082240, 5642 ],
[ 1525791550, 2722914857, 2083360, 1082240, 5642 ],
[ 1525791551, 2723114013, 2083511, 1082240, 5642 ],
[ 1525791552, 2723278935, 2083634, 1082240, 5642 ],
[ 1525791553, 2723441253, 2083757, 1082240, 5642 ],
[ 1525791554, 2723588529, 2083868, 1082240, 5642 ],
[ 1525791555, 2723722185, 2083969, 1082240, 5642 ],
[ 1525791556, 2723903721, 2084107, 1082240, 5642 ],
[ 1525791557, 2724194067, 2084324, 1082240, 5642 ],
[ 1525791558, 2724461387, 2084525, 1082240, 5642 ],
[ 1525791560, 2724644511, 2084667, 1082240, 5642 ],
[ 1525791561, 2724845055, 2084818, 1082240, 5642 ],
[ 1525791562, 2725013485, 2084955, 1082240, 5642 ],
[ 1525791563, 2725171809, 2085076, 1082240, 5642 ],
[ 1525791564, 2725428045, 2085267, 1082240, 5642 ],
[ 1525791565, 2725590243, 2085388, 1082240, 5642 ],
[ 1525791566, 2725726743, 2085493, 1082240, 5642 ],
[ 1525791567, 2725879531, 2085609, 1082240, 5642 ]
]
相關推薦
路由器的流量圖製作
1.繪製svg 向量圖 bandwidth.svg註釋:繪製流量圖的方法有三種,1) :直接將 svg 嵌入的html 頁面中2 ):通過使用embed/frame 等引用到頁面中去;<div class="cbi-table"><embed id="bw
路由器流量控制機制
所有 分享 性能 gravity 應該 策略 機制 技術分享 nag 高端路由器的流量控制機制 1. 概述 一些高端路由器上均具備流量控制機制,本篇文檔主要介紹3個應用於高端路由器的流量控制機制:反壓機制、隊列機制、流量監管。wn及擴展 2. 流量控制機制 2.1 反
百分百原創cacti跨主機跨設備拼接流量圖
tro mar png 屬於 包括 數據源 引用 roc 基礎 前言 日常工作中經常會遇到機房搬遷,或者IP更換什麽的。那就會引起原來的流量圖就斷掉了,再重新增加的流量圖和原來的又續不上,導致核對流量時,會遇到不少麻煩。另外本教程屬於進階使用教程,一些比較基礎的我不會在這
zblog2.3版本的asp系統是否可以超越盧松松博客的流量[圖]
OS http 為我 堅持 是我 客流量 size 階段 nag 最近訪問zblog官網,發現zlbog-asp2.3版本已經進入測試階段了,雖然正式版還沒有發布,想必也不久了。那麽作為aps縱橫江湖十多年的今天,blog2.2版本應該已經成熟了,為什麽還要發布這個2.3版
MT7621設計的無線路由器原理圖pcb和源代碼
standard 內存 圖片 truct 成本 cmp 技術分享 打開 evm MT7621設計的無線路由器原理圖pcb和源代碼 這裏有更多MT7612的資料下載 簡介:MT7612是一款高度整合式Wi-Fi單芯片,支持866 Mbps PHY速率。它完全符合IEEE 80
cacti中個別流量圖超過80M不顯示解決辦法
tool cti .html process -o alt tex bin 問題解決 修改前 #/usr/bin/rrdtool info /var/www/html/rra/_5328_traffic_in_792.rrd ds[traffic_in].min = 0.0
網站效能優化之雪碧圖製作
雪碧圖製作及使用 製作目的:由於網站上有需要小的icon且每次載入的時候都會有許多類似的請求,影響了網站的效能。所以將小圖示合併成一張雪碧圖,從而減少圖片的請求數,優化網站效能。 製作方法: 1、刀耕火種法 利用photoshop把一張張小圖合成一張雪碧圖(工作效率太低不建議使
opencv之gif動圖製作
import cv2 import imageio img1=cv2.imread('./yang1.jpg',1) img2=cv2.imread("./yang2.jpg",1) img3=cv2.imread("./yang3.jpg",1) img1 = cv2.resize(img1, (
supermap專題圖製作及釋出服務
開啟軟體。右擊工作空間中的的資料來源,點選新建資料來源,新建一個名為gulou的資料來源。右擊該資料來源,點選匯入資料集,選擇相應的影像圖匯入即可。(匯入資料集以後選擇右鍵新增到當前地圖。由於,下載器自動過濾了邊界以外的圖片,沒有圖的地圖會是黑色的,解決方法是在圖層管理器中,選擇影像引數,
IC數字前端設計開發25 (rtl時序圖製作工具)
timing editor http://timingeditor.sourceforge.net/ timingdesigner9.2 http://bbs.eetop.cn/thread-611436-1-1.html &
語音波形,截斷的頻域輸出以及語譜圖製作
語音視覺化 參考連結1 參考連結2 參考連結3 今天我想復現一下,文中語譜圖提取部分的程式碼 由於輸入的語音有單通道和雙通道之分,處理方式是單通道不變,雙通道只取一個通道的資訊。附上程式碼: import wave as we import numpy as np
Axure學習筆記-輪播圖製作(包括自動輪播及點選)
覺得下面這個分享挺好,我就不重複做了。 如何製作輪播圖: (1)實現圖片輪播; (2)將圓點與輪播圖片一一對應; (3)實現前一張、後一張圖片切換。 1、所需元件 首先我們需要準備以下元件: 動態面板(1000*400)、圓(3個,15*15)、
Axure學習筆記整理2-Banner輪播圖製作(包括自動輪播及手動輪播)
覺得下面這個分享挺好,我就不重複做了。 另外,我在原文中添加了一個小點,關於輪播導致的圓點顏色變化的設定。請看第3章第2部分的紅色字型。 謝謝原作者的分享。以下為原文連結。 轉載至:https://www.jianshu.com/p/628a22c1f653 &nb
H5Css3動畫 背景圖 製作幀動畫
<span class="css-class" style="color: rgb(255, 0, 255);"><span class="before"> </span></span><span class="css-
使用TexturePacker打包遊戲貼圖製作幀動畫
TexturePacker是個非常好用的貼圖打包工具,最近我在學習cocos2d-x,正巧聽說了這個工具,試用了一下,非常不錯.分享給大家 比如我有一些動畫幀,為了讓動畫更加流暢,我們將所有的動畫幀合成一張圖,然後通過每次展示一部分圖片來達到動畫效果 如果是美工來拼接,他
使用超圖製作室內導航地圖資料
只要按照參考文件的步驟,一步一步來,就一定能夠做好室內導航地圖 1.匯入資料集 這裡需要注意的事匯入資料時,超圖桌面端會把shp和dbf檔案一起呈現出來,如圖 我們只要選擇shp檔案就可以了,不要全選,不然會冗餘 2.建立圖層組,按組匯入資料 這裡需要注意
菜雞的ShaderForge3-利用UV貼圖製作卡通風格材質
說到卡通渲染,這兩年的遊戲想起的必然是崩崩崩了:
【轉載】“思維導圖”製作注意問題
“思維導圖”製作注意的問題我們學校的“思維導圖”逐漸被師生認可並自覺開始使用,但部分師生對思維導圖的製作方式並不明確,現借鑑部分專著的做法,讓大家更深入地瞭解“思維導圖”製作時應注意的問題。(我利用思維
使用SVG路徑圖製作線追蹤特效
近期看了幾篇三精-大精wing的“互動炸了”系列文章,收穫頗多,這裡學習記錄一下。 本文知識點一覽: 專案地址在最下面。 本篇主要記錄如何動態繪製曲線,從而形成很精緻的特性,先上圖: SVG簡介 SVG 意為可縮放向量圖形(Scalabl
幾款線上腦圖製作工具
在來不及開啟思維導圖的專業軟體是,採用線上工具也是很好的選項。 介紹:介紹百度腦圖是由百度公司開發的一款線上思維導圖編輯器,百度使用者可以直接通過百度腦圖網頁版本,介面還是相對比較好看的,百度家產品,向來風格簡約大方,受人喜愛。 介紹:Proce