Added a handler for SIGUSR1, which toggles off/on the enforcement calls to tc.
Kevin Webb [Wed, 19 Nov 2008 04:52:10 +0000 (04:52 +0000)]
Added several more statistics variables to the common accounting type.  Print
the stats to the log regularly to make sure that everything is working.

drl/common_accounting.h
drl/drl_state.c
drl/estimate.c
drl/standard.c
drl/ulogd_DRL.c

index d656d8a..0fbcdbe 100644 (file)
@@ -74,6 +74,26 @@ typedef struct {
     /** The number of bytes sent since the last_update time. */
     uint32_t bytes_since;
 
+    /* Statistics below. */
+
+    /** The current number of flows. */
+    uint32_t num_flows;
+
+    /** The number of flows sending above 5KB/s. */
+    uint32_t num_flows_5k;
+
+    /** The number of flows sending above 10KB/s. */
+    uint32_t num_flows_10k;
+
+    /** The number of flows sending above 20KB/s. */
+    uint32_t num_flows_20k;
+
+    /** The number of flows sending above 50KB/s. */
+    uint32_t num_flows_50k;
+
+    /** The average flow rate. */
+    uint32_t avg_rate;
+
 } common_accounting_t;
 
 /** Determines the difference between two timeval structs (in seconds, with
index eba79ba..fed3326 100644 (file)
@@ -214,6 +214,7 @@ void *limiter_receive_thread(void *unused) {
 
     sigemptyset(&signal_mask);
     sigaddset(&signal_mask, SIGHUP);
+    sigaddset(&signal_mask, SIGUSR1);
     pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
 
     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
index 17a0fd8..29704be 100644 (file)
 #include "ratetypes.h" /* needs util and pthread.h */
 #include "logging.h"
 
+#define PRINT_COUNTER_RESET (7)
+
 extern uint8_t system_loglevel;
-static int printcounter = 8;
+static int printcounter = PRINT_COUNTER_RESET - 1;
+
+uint8_t do_enforcement = 0;
 
 /**
  * Called for each identity each estimate interval.  Uses flow table information
@@ -233,8 +237,10 @@ static uint32_t allocate_fps(identity_t *ident, double total_weight) {
     }
 
     if (printcounter <= 0) {
-        printlog(LOG_WARN, "%d %.1f %.1f %.1f\n", local_rate, idealweight, ident->localweight, total_weight);
-        printcounter = 8;
+        printlog(LOG_WARN, "%d %.1f %.1f %.1f %d %d %d %d %d %d ", local_rate, idealweight,
+            ident->localweight, total_weight, ftable->num_flows, ftable->num_flows_5k, ftable->num_flows_10k,
+            ftable->num_flows_20k, ftable->num_flows_50k, ftable->avg_rate);
+        printcounter = PRINT_COUNTER_RESET;
     } else {
         printcounter -= 1;
     }
@@ -370,16 +376,22 @@ static void enforce(limiter_t *limiter, identity_t *ident) {
                 printf("FPS: Setting local limit to %d\n", ident->locallimit);
             }
             printlog(LOG_DEBUG, "%d Limit ID:%d\n", ident->locallimit, ident->id);
-            printlog(LOG_WARN, "%d\n", ident->locallimit);
+
+            if (printcounter == PRINT_COUNTER_RESET) {
+                printlog(LOG_WARN, "%d\n", ident->locallimit);
+            }
 
             snprintf(cmd, CMD_BUFFER_SIZE,
                      "/sbin/tc class change dev eth0 parent 1:%x classid 1:%x htb rate 8bit ceil %dbps quantum 1600",
                      ident->htb_parent, ident->htb_node, ident->locallimit);
 
-            ret = system(cmd);
+            if (do_enforcement) {
+                ret = system(cmd);
 
-            if (ret) {
-                /* FIXME: call failed.  What to do? */
+                if (ret) {
+                    /* FIXME: call failed.  What to do? */
+                    printlog(LOG_CRITICAL, "***TC call failed?***\n");
+                }
             }
             break;
 
@@ -423,10 +435,13 @@ static void enforce(limiter_t *limiter, identity_t *ident) {
                          ident->leaves[i]->xid, ident->leaves[i]->xid,
                          (100 * ident->leaves[i]->drop_prob));
 #endif
-                ret = system(cmd);
+                if (do_enforcement) {
+                    ret = system(cmd);
 
-                if (ret) {
-                    /* FIXME: call failed.  What to do? */
+                    if (ret) {
+                        /* FIXME: call failed.  What to do? */
+                        printlog(LOG_CRITICAL, "***TC call failed?***\n");
+                    }
                 }
             }
 
@@ -496,6 +511,7 @@ void handle_estimation(void *arg) {
 
     sigemptyset(&signal_mask);
     sigaddset(&signal_mask, SIGHUP);
+    sigaddset(&signal_mask, SIGUSR1);
     pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
 
     /* Determine the number of intervals we should wait before hitting the
index 93cb663..ba1fcc7 100644 (file)
@@ -244,6 +244,15 @@ void standard_table_update_flows(standard_flow_table table, struct timeval now,
     struct in_addr src, dst;
     char sip[22], dip[22];
 
+    /* Reset statistics. */
+    table->common->num_flows = 0;
+    table->common->num_flows_5k = 0;
+    table->common->num_flows_10k = 0;
+    table->common->num_flows_20k = 0;
+    table->common->num_flows_50k = 0;
+    table->common->avg_rate = 0;
+    /* End statistics. */
+
     time_delta = timeval_subtract(now, table->common->last_update);
 
     if (time_delta <= 0) {
@@ -295,6 +304,28 @@ void standard_table_update_flows(standard_flow_table table, struct timeval now,
             maxflowrate = current->rate;
         }
 
+        if (current->rate > 51200) {
+            table->common->num_flows_50k += 1;
+            table->common->num_flows_20k += 1;
+            table->common->num_flows_10k += 1;
+            table->common->num_flows_5k += 1;
+            table->common->num_flows += 1;
+        } else if (current->rate > 20480) {
+            table->common->num_flows_20k += 1;
+            table->common->num_flows_10k += 1;
+            table->common->num_flows_5k += 1;
+            table->common->num_flows += 1;
+        } else if (current->rate > 10240) {
+            table->common->num_flows_10k += 1;
+            table->common->num_flows_5k += 1;
+            table->common->num_flows += 1;
+        } else if (current->rate > 5120) {
+            table->common->num_flows_5k += 1;
+            table->common->num_flows += 1;
+        } else {
+            table->common->num_flows += 1;
+        }
+
         src.s_addr = ntohl(current->source_ip);
         dst.s_addr = ntohl(current->dest_ip);
         strcpy(sip, inet_ntoa(src));
@@ -305,6 +336,10 @@ void standard_table_update_flows(standard_flow_table table, struct timeval now,
                 current->rate);
     }
 
+    if (table->common->num_flows > 0) {
+        table->common->avg_rate = table->common->rate / table->common->num_flows;
+    }
+
     printlog(LOG_DEBUG, "FLOW:--\n--\n");
 
     table->common->max_flow_rate = maxflowrate;
index ef5cf20..b87b96e 100644 (file)
@@ -229,6 +229,7 @@ uint32_t local_ip = 0;
 limiter_t limiter;
 extern FILE *logfile;
 extern uint8_t system_loglevel;
+extern uint8_t do_enforcement;
 
 /* functions */
 
@@ -1468,6 +1469,33 @@ static void time_reconfig(int iterations) {
     // Seems to take about 85ms / iteration
 }
 
+static int stop_enforcement(drl_instance_t *instance) {
+    char cmd[300];
+    int i;
+
+    for (i = 0; i < instance->machine_count; ++i) {
+        sprintf(cmd, "/sbin/tc class change dev eth0 parent 1:%x classid 1:%x htb rate 8bit ceil 100mbit",
+                instance->machines[i]->htb_parent,
+                instance->machines[i]->htb_node);
+
+        if (execute_cmd(cmd)) {
+            return 1;
+        }
+    }
+
+    for (i = 0; i < instance->set_count; ++i) {
+        sprintf(cmd, "/sbin/tc class change dev eth0 parent 1:%x classid 1:%x htb rate 8bit ceil 100mbit",
+                instance->sets[i]->htb_parent,
+                instance->sets[i]->htb_node);
+
+        if (execute_cmd(cmd)) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
 static void *signal_thread_func(void *args) {
     int sig;
     int err;
@@ -1475,11 +1503,13 @@ static void *signal_thread_func(void *args) {
 
     sigemptyset(&sigs);
     sigaddset(&sigs, SIGHUP);
+    sigaddset(&sigs, SIGUSR1);
     pthread_sigmask(SIG_BLOCK, &sigs, NULL);
 
     while (1) {
         sigemptyset(&sigs);
         sigaddset(&sigs, SIGHUP);
+        sigaddset(&sigs, SIGUSR1);
 
         err = sigwait(&sigs, &sig);
 
@@ -1492,11 +1522,23 @@ static void *signal_thread_func(void *args) {
             case SIGHUP:
                 printlog(LOG_WARN, "Caught SIGHUP - re-reading XML file.\n");
                 reconfig();
-                //time_reconfig(1000); //instrumentation
+                //time_reconfig(1000); /* instrumentation */
                 flushlog();
                 break;
+            case SIGUSR1:
+                pthread_rwlock_wrlock(&limiter.limiter_lock);
+                if (do_enforcement) {
+                    do_enforcement = 0;
+                    stop_enforcement(&limiter.stable_instance);
+                    printlog(LOG_CRITICAL, "--Switching enforcement off.--\n");
+                } else {
+                    do_enforcement = 1;
+                    printlog(LOG_CRITICAL, "--Switching enforcement on.--\n");
+                }
+                pthread_rwlock_unlock(&limiter.limiter_lock);
+                break;
             default:
-                /* Should be impossible... */
+                /* Intentionally blank. */
                 break;
         }
     }
@@ -1511,6 +1553,7 @@ static void _drl_reg_op(void)
 
     sigemptyset(&signal_mask);
     sigaddset(&signal_mask, SIGHUP);
+    sigaddset(&signal_mask, SIGUSR1);
     pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
 
     if (pthread_create(&signal_thread, NULL, &signal_thread_func, NULL) != 0) {