Logo Search packages:      
Sourcecode: netams version File versions  Download package

bw.c

/*************************************************************************
***   Authentication, authorization, accounting + firewalling package
***   Copyright 1998-2002 Anton Vinokurov <anton@netams.com>
***   Copyright 2002-2008 NeTAMS Development Team
***   This code is GPL v3
***   For latest version and more info, visit this project web page
***   located at http://www.netams.com
***
*************************************************************************/
/* $Id: bw.c,v 1.36 2008-02-23 08:35:02 anton Exp $ */

#include "netams.h"
#include "ds_any.h"

#ifdef HAVE_BW
//////////////////////////////////////////////////////////////////////////////////////////
BWEngine::BWEngine() {
      
      bwd_used=bwd_total=0;
      bwdReady=NULL;

      bwu_used=bwu_total=0;
      bwuReady=NULL;

      table=(BWdata**)aMalloc(BW_HASH_SIZE*sizeof(BWdata*));
      aLog(D_INFO, "BW HASH initialized with size %u\n",BW_HASH_SIZE);
}

BWEngine::~BWEngine() {
      BWdata *b, *p;
      
      for(unsigned i=0; i<BW_HASH_SIZE; i++) {
            for(b=table[i]; b!=NULL; b=p) {
                  p=b->next;  
                  aFree(b);
            }
      }

      bwUlist *bwu;
      while(bwuReady) {
            bwu=bwuReady;
            bwuReady=bwuReady->next;
            aFree(bwu);
      }

      aFree(table);
      aLog(D_INFO, "BW HASH uninitialized\n");
}

void BWEngine::AddBW2entry(BWinfo *bwi, entry *e, match mf, void *key) {
      bwUlist *bwu;
      
      //find if there is this BWinfo
      unsigned hash = BW_HASH(bwi);
      BWdata *b;

      for(b=table[hash]; b!=NULL; b=b->next) {
            if(b->key == key) break;
      }

      if(b==NULL) {
            b=(BWdata*)aMalloc(sizeof(BWdata));
            b->key=key;
            
            bwd_total++;
            bwd_used++;
            
            //fill init BWdata        
            struct timeval tv;
            netams_gettimeofday(&tv, NULL);
            
            b->end_t[0] = b->end_t[1]     = (tv.tv_sec-start_t)*1000+tv.tv_usec/1000;
            b->total_bytes[0]             = bwi->out;
            b->total_bytes[1]             = bwi->in;
            b->num_flows                  = 0;

            b->next=table[hash];
            table[hash]=b;
      } else {
            //check for overlaping BW
            for(bwu=e->bwRoot; bwu!=NULL; bwu=bwu->next) {
                  if(bwu->bwd==b && bwu->mf==mf)
                        return;
            }
      }     
      
      //get new BWUlist element
      if(bwuReady) {
            bwu=bwuReady;
            bwuReady=bwuReady->next;
      } else {
            bwu=(bwUlist*)aMalloc(sizeof(bwUlist));
            bwu_total++;
      }
      bwu_used++;
      
      //this resolvs problem when parent object for BWdata destroyed
      // and accidentaly , new created obkect receives same key
      //we just refill limits with new data
      b->limit_out        = bwi->out;
      b->limit_in         = bwi->in;

      b->num_flows++;
      bwu->bwd=b;
      bwu->mf=mf;
      bwu->next=e->bwRoot;
      e->bwRoot=bwu;
      
      aDebug(DEBUG_BW, "add bwdata key %p [in=%lu,out=%lu] to entry %p, match=%u\n",
            b->key, b->limit_in, b->limit_out, e, mf);
}

void BWEngine::FreeBWentry(entry *e){
      if(!e->bwRoot) return;

      bwUlist *bwu;
      u_char num=1;

      for(bwu=e->bwRoot; bwu->next!=NULL; bwu=bwu->next, num++){
            bwu->bwd->num_flows--;
      }
      
      bwu->bwd->num_flows--;
      bwu->next=bwuReady;
      bwuReady=e->bwRoot;
      bwu_used-=num;

      e->bwRoot=NULL;
}

//////////////////////////////////////////////////////////////////////////////////////////      
u_char BWCheck(entry *e, u_long size, struct timeval *tv) {
      bwUlist *bwu;
      BWdata *bwd;
        unsigned long rate;
      unsigned long new_t;
      match mf;

      for(bwu=e->bwRoot; bwu!=NULL; bwu=bwu->next) {
            bwd         = bwu->bwd;
            mf          = bwu->mf;
            rate        = 0;
            
            // second algorithm

            // 2. adjust end_t
            new_t=(tv->tv_sec - start_t)*1000 + tv->tv_usec/1000;
            
            // 1. adjust tocken buckets for each directions
            // 3. check if number of tokens is enough
            if ((mf&MATCH_DST) && bwd->limit_in > 0) {
                  rate = (new_t - bwd->end_t[1])*bwd->limit_in/1000;
                  bwd->total_bytes[1]+=rate;

                  if ((unsigned long)bwd->total_bytes[1] > bwd->limit_in)
                        bwd->total_bytes[1] = bwd->limit_in;

                  aDebug(DEBUG_BW, "entry %p, DST s:%lu - e:%lu left:%lu lim:%lu rate:%lu size=%u\n",
                        e, new_t, bwd->end_t[1], bwd->total_bytes[1], bwd->limit_in, rate, size);
                  
                  if (bwd->total_bytes[1]>=size) {
                        bwd->total_bytes[1]-=size;
                  } else 
                        return 1;
            }
            if ((mf&MATCH_SRC) && bwd->limit_out > 0) {
                  rate = (new_t - bwd->end_t[0])*bwd->limit_out/1000;
                  bwd->total_bytes[0]+=rate;
                  
                  if ((unsigned long)bwd->total_bytes[0] > bwd->limit_out)
                        bwd->total_bytes[0]=bwd->limit_out;

                  aDebug(DEBUG_BW, "entry %p SRC s:%lu - e:%lu left:%lu lim:%lu rate:%lu size=%u\n",
                        e, new_t, bwd->end_t[0], bwd->total_bytes[0], bwd->limit_out, rate, size);
                  
                  if (bwd->total_bytes[0]>=size) {
                        bwd->total_bytes[0]-=size;
                  } else
                        return 1;
            } 
            bwd->end_t[0] = bwd->end_t[1] = new_t;
      }
      return 0;
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
BWinfo* setBW(BWinfo* bwi, char **param, u_char *i) {
      
      u_char j=*i+1;
      unsigned long tmp, bw_in, bw_out;
      bw_in=bw_out=tmp=0;
      
      while(param[j]) {
            if(isdigit(param[j][0]))
                  tmp=(unsigned long)bytesT2Q(param[j]);
            else {
                  j-=2;
                  break;
            }
            if(STREQ("in", param[j+1])) 
                  bw_in=tmp;
            else if(STREQ("out", param[j+1]))
                  bw_out=tmp;
            else {
                  bw_in=bw_out=tmp;
                  j--;
            }
            j+=2;
      }
      //printf("setBW: bwi=%p, tmp=%lu, bw_in=%lu, bw_out=%lu\n", bwi, tmp, bw_in, bw_out);
      *i=j;
      if(bw_in || bw_out) {
            if(bwi==NULL) bwi=(BWinfo*)aMalloc(sizeof(BWinfo));
            //since we set as bit/s and work with bytes/s
            bwi->in=bw_in>>3;
            bwi->out=bw_out>>3;
      } 
      else if(bwi) {
            aFree(bwi);
            bwi=NULL;
      }
      
      return bwi;
}

void getBW(BWinfo *bwi, struct cli_def *cli) {
      char tmp[32];

      if (bwi != NULL) {
            if(bwi->in==bwi->out && bwi->in)
                  cli_bufprint(cli, " %s", bytesQ2T((unsigned long long)bwi->in<<3, tmp));
            else {
                  if(bwi->in) cli_bufprint(cli, " %s in", bytesQ2T((unsigned long long)bwi->in<<3, tmp));
                  if(bwi->out) cli_bufprint(cli, " %s out", bytesQ2T((unsigned long long)bwi->out<<3, tmp));
            }
      }
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

Generated by  Doxygen 1.6.0   Back to index