Commit 0cdf1073 authored by 's avatar

Added several EXPIRED_FLOWS / packetloss features for perfmormance tuning.


git-svn-id: file:///home/svn/mapi/trunk@1354 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent dbf81108
......@@ -157,16 +157,9 @@ $form["time"] = new FormElement( // select - option (more selects)
<script type="text/javascript" src="js/ajax.js"></script>
<script type="text/javascript" src="js/packetlossTop.js"></script>
<script type="text/javascript" src="js/mouse.js"></script>
<style type="text/css">
/* <![CDATA[ */
body {
background-image: url(img/uc.jpg);
background-repeat: no-repeat;
}
div.clear {
clear: both
}
......@@ -272,6 +265,13 @@ $form["time"] = new FormElement( // select - option (more selects)
element.src = 'graph/packetcount.php?predefined=' + predefined;
}
*/
function setTime(d, year, month, day, hours, minutes) {
year.value = d.getFullYear();
month.value = d.getMonth() + 1;
day.value = d.getDate();
hours.value = d.getHours();
minutes.value = d.getMinutes();
}
//]]>
</script>
......@@ -297,7 +297,7 @@ $form["time"] = new FormElement( // select - option (more selects)
<form method="get" action="index.php">
<div class="step">
<h2>Step 1: Select monitoring stations:</h2>
<div class="note">At least two monitoring stations must be checked.</div>
<div class="note">(At least two monitoring stations must be checked.)</div>
<?php
$name = $form["subject"]->name;
foreach($form["subject"]->elementvals as $key => $val) {
......@@ -415,6 +415,8 @@ EOD;
?>
</select>
<input type="button" value="Now" onclick="setTime(new Date(), this.form['time[year]'], this.form['time[mon]'], this.form['time[mday]'], this.form['time[hours]'], this.form['time[minutes]'])" />
</div>
<div class="tr medium">
......
/*
* Filename: mouse.js
* Date: 2007/01/25 18:43
* Author: Aleš Friedl <ales.friedl@email.cz>
*
*/
// Object Literal mouse {{{
var mouse = {
author: "Aleš Friedl",
version: "0.2",
exists: false,
autorun: true,
MX: 0,
MY: 0,
seeX: 800,
seeY: 600,
init: function() {
if(mouse.exists) return false;
mouse.exists = true;
if(mouse.autorun) mouse.start();
},
start: function() {
document.onmousemove = mouse.mousemove;
//if(document.captureEvents) document.captureEvents(Event.MOUSEMOVE);
},
stop: function() {
document.onmousemove = null
//if(document.releaseEvents) document.releaseEvents(Event.MOUSEMOVE);
},
mousemove: function(e) {
if(mouse.exists) {
if(e) {
mouse.MX = e.pageX
mouse.MY = e.pageY
}
else {
mouse.MX = window.event.clientX + (document.documentElement?document.documentElement.scrollLeft:document.body.scrollLeft)
mouse.MY = window.event.clientY + (document.documentElement?document.documentElement.scrollTop:document.body.scrollTop)
}
if(window.innerWidth) {
mouse.seeX = window.innerWidth + window.pageXOffset - 22;
mouse.seeY = window.innerHeight + window.pageYOffset;
}
else {
mouse.seeX = document.body.offsetWidth + (document.documentElement?document.documentElement.scrollLeft:document.body.scrollLeft - 22);
mouse.seeY = document.body.offsetHeight + (document.documentElement?document.documentElement.scrollTop:document.body.scrollTop);
}
//if(mirage) mirage.show();
//window.status = "seeX: "+mouse.seeX+" seeY: "+mouse.seeY+" MX: "+mouse.MX+" MY: "+mouse.MY+"";
}
}
}
// }}}
window_onDOMContentLoaded_add(mouse.init);
// vim: set foldmethod=marker foldmarker=\ {{{,\ }}} foldclose= foldcolumn=0 :
......@@ -8,6 +8,8 @@ class FormElement {
var $debug = false;
var $formaction = "action";
var $name;
var $elementvals;
var $selectedvals;
......@@ -17,7 +19,7 @@ class FormElement {
$this->name = $name;
$this->elementvals = $elementvals;
if(isset($_GET[$name])) $this->selectedvals = $_GET[$name];
if(isset($_GET[$name]) || isset($_GET[$this->formaction])) $this->selectedvals = $_GET[$name];
else $this->selectedvals = $selectedvals;
if($this->debug) {
......
......@@ -11,6 +11,13 @@ typedef struct flow_data {
u_char ttl_pkt1;
}flow_data;
typedef struct flows_stat {
unsigned int sent;
unsigned int buffered;
unsigned long long ignored_total;
unsigned long long dropped_total;
} flows_stat;
struct exfl_list_node {
unsigned int value;
......@@ -33,6 +40,8 @@ struct exfl_hash_node {
struct exfl_data {
int list_size;
unsigned int expired_flows_list_size;
unsigned int expired_flows_list_size_max;
struct exfl_list_node *list_head;
struct exfl_list_node *list_tail;
struct exfl_hash_node *hashtable[EXFL_HASH_SIZE];
......@@ -42,4 +51,5 @@ struct exfl_data {
pthread_t pthread;
unsigned int run;
unsigned long long epoch;
unsigned int packets_count_min;
};
......@@ -20,7 +20,7 @@
#define SEND_SIZE 64 //Number of expired flows send per mapi_read_results.
#define TIMEOUT 30 //in epochs
#define EPOCHDURATION 1
#define SHM_FLOWS 1000 //shm flows count
#define SHM_FLOWS 1000 //1249 // (DIMAPI_DATA_SIZE - sizeof(flows_stat)) / sizeof(struct flow_data))
#define ETHERTYPE_8021Q 0x8100
#define MPLS_MASK 0x8847
......@@ -214,7 +214,7 @@ int checkhash(struct exfl_hash_node **hashtable) {
* Check if there are any records in expired flows list and put them
* in shared memory if there is enough space.
*/
void check_expired_flows(struct exfl_data *data, shm shm_struct) {
void check_expired_flows(struct exfl_data *data, shm shm_struct, flows_stat *stat) {
struct exfl_list_node *tmp, *tail = data->expired_flows_tail;
while( (tail != NULL) && (*(shm_struct.size) != SHM_FLOWS) ) {
......@@ -224,6 +224,8 @@ void check_expired_flows(struct exfl_data *data, shm shm_struct) {
(*(shm_struct.size))++;
pthread_mutex_unlock( shm_struct.smmutex );
// Remove node from the expired flows list
data->expired_flows_list_size--;
stat->buffered--;
tmp = tail->previous;
if(tmp != NULL)
tmp->next = NULL;
......@@ -233,6 +235,8 @@ void check_expired_flows(struct exfl_data *data, shm shm_struct) {
if( tail == NULL ) {
data->expired_flows_head = data->expired_flows_tail = NULL;
DEBUG_CMD(if (data->expired_flows_list_size) Debug_Message("WARNING: expired_flows_list_size == %d, should be 0", data->expired_flows_list_size));
DEBUG_CMD(if (stat->buffered) Debug_Message("WARNING: stat->buffered == %d, should be 0", stat->buffered));
}
else
data->expired_flows_tail = tail;
......@@ -241,24 +245,26 @@ void check_expired_flows(struct exfl_data *data, shm shm_struct) {
void poll_expired_flows(mapidflib_function_instance_t *instance) {
struct exfl_data *data = instance->internal_data;
struct exfl_list_node *tmp, *previous;
struct exfl_list_node *tmp, *tmp2, *previous;
struct exfl_hash_node *lookup_hash;
flow_data tmpflow_data;
flows_stat *stat;
unsigned int value;
pthread_mutex_t *mutex = &(data->mutex);
int check;
shm shm_struct;
stat = (flows_stat *) instance->result.data;
shm_struct.size = (unsigned int *)instance->result.data;
shm_struct.Table = (flow_data *)((char *)instance->result.data+sizeof(unsigned int));
shm_struct.smmutex = (pthread_mutex_t *)(((char *)instance->result.data) + sizeof(unsigned int) + sizeof(struct flow_data)*SHM_FLOWS);
shm_struct.Table = (flow_data *)((char *)instance->result.data+sizeof(flows_stat));
shm_struct.smmutex = (pthread_mutex_t *)(((char *)instance->result.data) + sizeof(flows_stat) + sizeof(struct flow_data)*SHM_FLOWS);
*(shm_struct.size) = 0;
while(data->run) {
pthread_testcancel();
pthread_mutex_lock( mutex );
tmp = data->list_tail;
check_expired_flows(data,shm_struct );
check_expired_flows(data, shm_struct, stat);
if(tmp) { //if list is not empty
while( data->epoch - tmp->flow.timestamp > TIMEOUT) {
previous = tmp->previous;
......@@ -312,33 +318,58 @@ void poll_expired_flows(mapidflib_function_instance_t *instance) {
* records that couldn't be returned.
*/
if(*(shm_struct.size) == SHM_FLOWS) {
if(*(shm_struct.size) == SHM_FLOWS) { // shm full
//remove node from temporal sorted list
if(tmp->next)
tmp->next->previous = tmp->previous;
if(tmp->previous)
tmp->previous->next = tmp->next;
//add node to expired flows list
if(data->expired_flows_head != NULL) {
tmp->next = data->expired_flows_head;
data->expired_flows_head->previous = tmp;
tmp->previous = NULL;
data->expired_flows_head = tmp;
// if packets_count is worth to add
if(tmp->flow.packets_count >= ((struct exfl_data *)instance->internal_data)->packets_count_min) {
//add node to expired flows list
data->expired_flows_list_size++;
stat->buffered++;
if(data->expired_flows_head != NULL) {
tmp->next = data->expired_flows_head;
data->expired_flows_head->previous = tmp;
tmp->previous = NULL;
data->expired_flows_head = tmp;
}
else {
data->expired_flows_head = data->expired_flows_tail = tmp;
tmp->previous = tmp->next = NULL;
}
if(data->expired_flows_list_size > data->expired_flows_list_size_max) {
// remove/drop oldest
data->expired_flows_list_size--;
stat->buffered--;
stat->dropped_total++;
tmp2 = (data->expired_flows_tail)->previous;
if(tmp2 != NULL) tmp2->next = NULL;
free(data->expired_flows_tail);
data->expired_flows_tail = tmp2;
}
}
else {
data->expired_flows_head = data->expired_flows_tail = tmp;
tmp->previous = tmp->next = NULL;
stat->ignored_total++;
free(tmp);
}
}
else {
// Add the expired flow from temporal sorted list directly into shared memory table
pthread_mutex_lock( shm_struct.smmutex );
memcpy(&(shm_struct.Table[*(shm_struct.size)]), &(tmp->flow), sizeof(struct flow_data));
(*(shm_struct.size))++;
pthread_mutex_unlock( shm_struct.smmutex );
else { // shm not full
// if packets_count is worth to add
if(tmp->flow.packets_count >= ((struct exfl_data *)instance->internal_data)->packets_count_min) {
// Add the expired flow from temporal sorted list directly into shared memory table
pthread_mutex_lock( shm_struct.smmutex );
memcpy(&(shm_struct.Table[*(shm_struct.size)]), &(tmp->flow), sizeof(struct flow_data));
(*(shm_struct.size))++;
pthread_mutex_unlock( shm_struct.smmutex );
}
else {
stat->ignored_total++;
}
free(tmp);
}
......@@ -363,7 +394,10 @@ static int exprflow_init(mapidflib_function_instance_t *instance, MAPI_UNUSED in
pthread_mutex_t tmpmutex = PTHREAD_MUTEX_INITIALIZER;
shm shm_struct;
struct exfl_data *data;
flows_stat *stat;
mapiFunctArg* fargs;
fargs = instance->args;
// HashTable initialization
if( (instance->internal_data = malloc(sizeof(struct exfl_data))) == NULL) {
......@@ -379,16 +413,28 @@ static int exprflow_init(mapidflib_function_instance_t *instance, MAPI_UNUSED in
data->mutex = tmpmutex;
data->run = 1;
data->list_size = 0;
data->expired_flows_list_size = 0;
// Epoch initialization
data->epoch=0;
// function arguments
data->expired_flows_list_size_max = getargint(&fargs);
data->packets_count_min = getargint(&fargs);
// Shared Memory Initialization
stat = (flows_stat *)instance->result.data;
shm_struct.size = (unsigned int *)instance->result.data;
shm_struct.Table = (flow_data *)((char *)instance->result.data+sizeof(unsigned int));
shm_struct.smmutex = (pthread_mutex_t *)(((char *)instance->result.data) + sizeof(unsigned int) + sizeof(struct flow_data)*SHM_FLOWS);
shm_struct.Table = (flow_data *)((char *)instance->result.data+sizeof(flows_stat));
shm_struct.smmutex = (pthread_mutex_t *)(((char *)instance->result.data) + sizeof(flows_stat) + sizeof(struct flow_data)*SHM_FLOWS);
*(shm_struct.size) = 0;
//stat->sent = 0;
stat->buffered = 0;
stat->ignored_total = 0;
stat->dropped_total = 0;
//mutex initialization
*(shm_struct.smmutex) = tmpmutex;
......@@ -556,18 +602,11 @@ static int exprflow_client_read_result(mapidflib_function_instance_t *instance,m
flow_data *data;
shm_struct.size = (unsigned int *)instance->result.data;
shm_struct.Table = (flow_data *)((char *)instance->result.data+sizeof(unsigned int));
shm_struct.smmutex = (pthread_mutex_t *)(((char *)instance->result.data) + sizeof(unsigned int) + sizeof(struct flow_data)*SHM_FLOWS);
if( *(shm_struct.size) == 0) {
res->res = instance->internal_data;
*((unsigned int *)res->res) = 0;
res->size = sizeof(unsigned int);
return(0);
}
res->res = instance->internal_data;
res->size = sizeof(unsigned int) + sizeof(flow_data)*(*(shm_struct.size));
shm_struct.Table = (flow_data *)((char *)instance->result.data+sizeof(flows_stat));
shm_struct.smmutex = (pthread_mutex_t *)(((char *)instance->result.data) + sizeof(flows_stat) + sizeof(struct flow_data)*SHM_FLOWS);
res->res = instance->internal_data;
res->size = sizeof(flows_stat) + sizeof(flow_data)*(*(shm_struct.size));
size = *shm_struct.size;
pthread_mutex_lock( shm_struct.smmutex );
......@@ -575,14 +614,14 @@ static int exprflow_client_read_result(mapidflib_function_instance_t *instance,m
*(shm_struct.size) = 0;
pthread_mutex_unlock( shm_struct.smmutex );
data = (flow_data *)((char *)instance->internal_data+sizeof(unsigned int));
data = (flow_data *)((char *)instance->internal_data+sizeof(flows_stat));
return(0);
}
static int exprflow_client_init( mapidflib_function_instance_t *instance, void *data) {
if((instance->internal_data = malloc(sizeof(unsigned int)+sizeof(struct flow_data)*SHM_FLOWS)) == NULL) {
printf("Malloc failed for size %d [%s:%d]\n", sizeof(unsigned int)+sizeof(struct flow_data)*SHM_FLOWS, __FILE__, __LINE__);
if((instance->internal_data = malloc(sizeof(flows_stat)+sizeof(struct flow_data)*SHM_FLOWS)) == NULL) {
printf("Malloc failed for size %d [%s:%d]\n", sizeof(flows_stat)+sizeof(struct flow_data)*SHM_FLOWS, __FILE__, __LINE__);
return(-1);
}
data = instance->internal_data;
......@@ -602,10 +641,10 @@ static mapidflib_function_def_t finfo={
"", //libname
EXPIRED_FLOWS, //name
"Expired Flows function", //descr
"", //argdescr
"ii", //argdescr
MAPI_DEVICE_ALL, //devtype
MAPIRES_SHM, //Method for returning results
sizeof(unsigned int)+sizeof(struct flow_data)*SHM_FLOWS + sizeof(pthread_mutex_t), //shm size
sizeof(flows_stat)+sizeof(struct flow_data)*SHM_FLOWS + sizeof(pthread_mutex_t), //shm size
0, //modifies_pkts
0, //filters packets ?
MAPIOPT_NONE,
......
......@@ -486,7 +486,7 @@ void *handle_request(void *arg) {
break;
case READ_RESULT:
result = mapi_read_results(dbuf->fd,dbuf->fid);
if(result!=NULL){
if(result!=NULL && result->size < DIMAPI_DATA_SIZE){
dbuf->cmd = READ_RESULT_ACK;
dbuf->timestamp = result->ts;
memcpy(dbuf->data, result->res, result->size);
......
......@@ -4,7 +4,6 @@
#include <signal.h>
#include <string.h>
#include <ncurses.h>
#include <rrd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
......@@ -14,7 +13,7 @@
#include <mapi.h>
#include "../test.h"
#define DOTS DOT; DOT; DOT; DOT; DOT; DOT; DOT; DOT; DOT; DOT
#define SLEEP 10
#define LOOPS 10
......@@ -23,8 +22,9 @@ void print_flow(flow_data *data);
int main(int argc, char *argv[]) {
mapi_results_t *result;
unsigned int *results;
struct flow_data *flowdata;
flow_data *flowdata;
flows_stat *stat;
//unsigned int *stat;
unsigned int i;
......@@ -36,6 +36,9 @@ int main(int argc, char *argv[]) {
int loops = LOOPS;
const unsigned int expired_flows_list_size_max = 1249;
const unsigned int packets_count_min = 2;
if(argc != 2){
printf("Usage: %s <interface> \n", argv[0]);
return -1;
......@@ -48,7 +51,7 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE);
}
if ((fid = mapi_apply_function(fd, "EXPIRED_FLOWS")) < 0) {
if ((fid = mapi_apply_function(fd, "EXPIRED_FLOWS", expired_flows_list_size_max, packets_count_min)) < 0) {
fprintf(stderr, "Count not apply function EXPIRED_FLOWS to flow %d\n", fd);
mapi_read_error(&err_no, error);
fprintf(stderr, "Errorcode: %d description: %s\n", err_no, error);
......@@ -68,19 +71,19 @@ int main(int argc, char *argv[]) {
printf("loop %d/%d\n", LOOPS - loops, LOOPS);
DOTS;
sleep(SLEEP);
result = (mapi_results_t *) mapi_read_results(fd, fid);
results = (unsigned int *) result->res; // number of results/flows at host h, dev d
flowdata = (struct flow_data *)((char *) result->res + sizeof(unsigned int)); // results/flows array
printf("results: %d (please wait)\n", *results);
stat = (flows_stat *) result->res;
flowdata = (struct flow_data *)((char *) result->res + sizeof(flows_stat)); // results/flows array
for (i = *results; i > 0; i--) {
for (i = stat->sent; i > 0; i--) {
print_flow(flowdata);
flowdata++;
}
printf("results: %u, buffered: %u, ignored_total: %llu, dropped_total: %llu\n", stat->sent, stat->buffered, stat->ignored_total, stat->dropped_total);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment