ew.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:27k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * ew.cc
  3.  * Copyright (C) 1999 by the University of Southern California
  4.  * $Id: ew.cc,v 1.7 2006/02/21 15:20:18 mahrenho Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. //
  46. // ew.cc (Early warning system)
  47. //   by Xuan Chen (xuanc@isi.edu), USC/ISI
  48. #include "ip.h"
  49. #include "tcp.h"
  50. #include "tcp-full.h"
  51. #include "random.h"
  52. #include "ew.h"
  53. // Definition of High-Low Filter
  54. HLF::HLF() {
  55.   alpha = 0;
  56.   high = low = 0;
  57. }
  58. void HLF::reset(double value) {
  59.   high = low = value;
  60. }
  61. void HLF::reset() {
  62.   reset(0);
  63. }
  64. // Set Alpha
  65. void HLF::setAlpha(double value) {
  66.   if (value > 1 || value < 0)
  67.     return;
  68.   if (value >= 0.5)
  69.     alpha = value;
  70.   else
  71.     alpha = 1 - value;
  72. }
  73. // Get outputs from HLF
  74. double HLF::getHigh() {
  75.   return(high);
  76. }
  77. double HLF::getLow() {
  78.   return(low);
  79. }
  80. // update high-low filter
  81. // high(t) = alpha * high(t-1) + (1 - alpha) * o(t)
  82. // low(t) = (1 - alpha) * low(t-1) + alpha * o(t)
  83. void HLF::update(double input) {
  84.   // Set values to the current observation for the first time.
  85.   if (high)
  86.    high = alpha * high + (1 - alpha) * input;
  87.   else
  88.    high = input;
  89.   if (low)
  90. low = (1 - alpha) * low + alpha * input;
  91.   else
  92.    low = input;
  93.   //  printf("HLF %d %.2f, %.2fn", (int)now, high, low);
  94. }
  95. // Definition for a token-bucket rate limitor
  96. TBrateLimitor::TBrateLimitor() {
  97.   TBrateLimitor(DEFAULT_TB_RATE_P);
  98. }
  99. TBrateLimitor::TBrateLimitor(double rate) {
  100.   double now = Scheduler::instance().clock();
  101.   pkt_mode = 1;
  102.   bucket_size = DEFAULT_TB_SIZE;
  103.   token_rate = 0;
  104.   token_num = bucket_size;
  105.   last_time = now;
  106.   ini_token_rate = rate;
  107.   resetScore();
  108.   setRate(rate);
  109.   //printf("TB pkt_mode:%d, bucket_size:%g, token_num:%g, last_time:%gn",
  110.   //  pkt_mode, bucket_size, token_num, last_time);
  111.   // High-low filter
  112.   hlf.setAlpha(ALPHA);
  113.   hlf.reset(rate);
  114. }
  115. // adjust the rate limit to the default value
  116. void TBrateLimitor::setRate(double rate) {
  117.   last_token_rate = token_rate;
  118.   
  119.   if (! token_rate) {
  120.     token_rate = rate;
  121.   } else if (rate != token_rate) {
  122.     // use HLF to change token rate
  123.     hlf.update(rate);
  124.     // Use low-gain filter for fast response
  125.     //token_rate = hlf.getLow();
  126.     token_rate = hlf.getHigh();
  127.     token_rate = rate;
  128.   }
  129.   
  130.   printf("TR %d %.2f %.2f %d %dn", (int)(Scheduler::instance().clock()), 
  131.  token_rate, rate, p_score, n_score);
  132. }
  133. // adjust the rate limit to approaching an optimal rate limit
  134. void TBrateLimitor::adjustRate() {
  135.   // pay the penalty
  136.   adjustScore(-1);
  137.   double rate = token_rate;
  138.   if (p_score >= n_score)
  139.     rate = token_rate * (1 + 0.2);
  140.   else 
  141.     rate = token_rate * (1 - 0.2);
  142.   setRate(rate);
  143. }
  144. // Reset negative / positive score
  145. void TBrateLimitor::resetScore() {
  146.   n_score = p_score = 0;
  147. }
  148. // adjust the score for increasing or decreasing scores
  149. void TBrateLimitor::adjustScore(int score) {
  150.   // pay the penalty
  151.   if (last_token_rate > token_rate)
  152.     n_score += score;
  153.   else
  154.     p_score += score;
  155. }
  156. int TBrateLimitor::run(double incoming, double t_rate) {
  157.   double now = Scheduler::instance().clock();
  158.   double interval = now - last_time;
  159.   
  160.   //printf("TB: now:%g last_time:%g interval:%g; ", now, last_time, interval);
  161.   token_num += interval * t_rate;
  162.   last_time = now;
  163.   // more tokens are overflowed
  164.   if (token_num > bucket_size)
  165.     token_num = bucket_size;
  166.   //printf("token #:%g; ", token_num);
  167.   // through (0 dropping probability)
  168.   if (token_num >= incoming) {
  169.     token_num -= incoming;
  170.     //printf("...throughn");
  171.     return 0;
  172.   }
  173.   // dropped
  174.   //printf("...droppedn");
  175.   return 1;
  176. }
  177. int TBrateLimitor::run(double incoming) {
  178.   return (run(incoming, token_rate));
  179. }
  180. // EW detector
  181. // Constructor
  182. EWdetector::EWdetector() {
  183.   ew_src = ew_dst = -1;
  184.   // reset measurement
  185.   cur_rate = avg_rate = 0;
  186.   // reset timers
  187.   db_timer = dt_timer = 0;
  188.   // reset alarm
  189.   resetAlarm();
  190.   resetChange();
  191.   // High-low filter
  192.   hlf.setAlpha(ALPHA);
  193. }
  194. //EWdetector::~EWdetector() {
  195. //};
  196. // Enable detecting and debugging
  197. void EWdetector::setDt(int inv) {
  198.   dt_inv = inv;
  199.   //printf("DT: %dn", dt_inv);
  200. }
  201. void EWdetector::setDb(int inv) {
  202.   db_inv = inv;
  203.   //printf("DB: %dn", db_inv);
  204. }
  205. void EWdetector::setLink(int src, int dst) {
  206.   ew_src = src;
  207.   ew_dst = dst;
  208.   //printf("EW: (%d:%d)n", ew_src, ew_dst);
  209. }
  210. void EWdetector::setAlarm() {
  211.   alarm = 1;
  212.   // Reset low and high gain filters' input values to the long-term avg
  213.   // Actually, there is no change to high gain filter
  214.   hlf.reset(avg_rate);
  215. }
  216. void EWdetector::resetAlarm() {
  217.   alarm = 0;
  218.   // Reset low and high gain filters' input values to the long-term avg
  219.   // Actually, there is no change to low gain filter
  220.   hlf.reset(avg_rate);
  221. }
  222. // Set and reset change flag
  223. void EWdetector::setChange() {
  224.   change = 1;
  225. }
  226. void EWdetector::resetChange() {
  227.   change = 0;
  228. }
  229. // Test if the alarm has been triggered
  230. int EWdetector::testAlarm() {
  231.   if (!change)
  232.     return(EW_UNCHANGE);
  233.   else 
  234.     return(alarm);
  235. }
  236. // Update long term average
  237. void EWdetector::updateAvg() {
  238.   // update the request rate
  239.   // update the aggregated response rate
  240.   // Update flip-flop filter
  241.   hlf.update(cur_rate);
  242.   
  243.   // Update SWIN, not used any more.
  244.   //updateSWin(cur_rate);
  245.   //ravgSWin();
  246.   //printSWin();
  247.   
  248.   // Update the long term average value with the output from different filters
  249.   if (!alarm) {
  250.     // Use low-gain filter for fast response
  251.     //avg_rate = hlf.getLow();
  252.     avg_rate = hlf.getHigh();
  253.   } else {
  254.     // Use high-gain filter to keep the long term average stable
  255.     avg_rate = hlf.getHigh();
  256.   }
  257. }
  258. // the detector's engine
  259. void EWdetector::run(Packet *pkt) {
  260.   // get the time
  261.   now = Scheduler::instance().clock();
  262.   
  263.   //printf("EW[%d:%d] run ", ew_src, ew_dst);
  264.   // update the measurement 
  265.   measure(pkt);
  266.   // There is a timeout!
  267.   if (now >= dt_timer) {
  268.     // Start detection
  269.     //printf("Detection timeout(%d)n", (int)now);
  270.     
  271.     // 1. Update the current rate from measurement
  272.     updateCur();
  273.     // 2. Detect change and Trigger alarm if necessary
  274.     // Compare the current rate with the long term average
  275.     detect();
  276.     
  277.     // 3. Update the long term averages
  278.     updateAvg();
  279.     // setup the sleeping timer
  280.     dt_timer = (int)now + dt_inv;
  281.     //printf("%dn", dt_inv);
  282.     change = 1;
  283.   }
  284.   
  285.   // Schedule debug
  286.   if (db_inv && now >= db_timer) {
  287.     //printf("debugB ");
  288.     trace();
  289.     db_timer = (int)now + db_inv;
  290.   }
  291. }
  292. // end of EW detector
  293. // EW bit rate detector
  294. //Constructor.  
  295. EWdetectorB::EWdetectorB() : EWdetector() {
  296.   drop_p = 0;
  297.   arr_count = 0;
  298.   adjustor = 1.0;
  299.   // Initialize ALIST
  300.   alist.head = alist.tail = NULL;
  301.   alist.count = 0;
  302.   swin.head = swin.tail = NULL;
  303.   swin.count = swin.ravg = 0;
  304. }
  305. //Deconstructor.
  306. EWdetectorB::~EWdetectorB(){
  307.   resetAList();
  308.   resetSWin();
  309. }
  310. // Initialize the EW parameters
  311. void EWdetectorB::init(int ew_adj) {
  312.   // EW adjustor (g = resp rate / request rate)
  313.   adjustor = ew_adj;
  314. }
  315. // Update current measurement 
  316. void EWdetectorB::measure(Packet *pkt) {
  317.   //printf(" before UA");
  318.   // Conduct detection continously
  319.   updateAList(pkt);
  320.   //printf(" after UA");
  321. }
  322. // Update current measurement 
  323. void EWdetectorB::updateCur() {
  324.   //printAList();
  325.   // Record current aggregated response rate
  326.   cur_rate = computeARR();
  327. }
  328. // Check if the packet belongs to existing flow
  329. int EWdetectorB::exFlow(Packet *pkt) {
  330.   // Should check SYN packets to protect existing connections
  331.   //   need to use FullTCP
  332.   return(0);
  333. }
  334. // Conduct the measurement
  335. void EWdetectorB::updateAList(Packet *pkt) {
  336.   hdr_cmn* hdr = hdr_cmn::access(pkt);
  337.   hdr_ip* iph = hdr_ip::access(pkt);
  338.   int dst_id = iph->daddr();
  339.   int src_id = iph->saddr();
  340.   int f_id = iph->flowid(); 
  341.   // Get the corresponding id.
  342.   //printf("EW[%d:%d] in detectorn", ew_src, ew_dst);
  343.   AListEntry *p;
  344.   p = searchAList(src_id, dst_id, f_id);
  345.   // Add new entry to AList
  346.   // keep the bytes sent by each aggregate in AList
  347.   if (!p) {
  348.     p = newAListEntry(src_id, dst_id, f_id);
  349.   }
  350.   // update the existing (or just created) entry in AList
  351.   assert(p && p->f_id == f_id && p->src_id == src_id && p->dst_id == dst_id);
  352.   // update the flow's arrival rate using TSW
  353.   double bytesInTSW, newBytes;
  354.   bytesInTSW = p->avg_rate * p->win_length;
  355.   newBytes = bytesInTSW + (double) hdr->size();
  356.   p->avg_rate = newBytes / (now - p->t_front + p->win_length);
  357.   p->t_front = now;
  358.   //printAListEntry(p, 0);
  359. }
  360. // Get the median for a part of AList 
  361. //   starting from index with count entries
  362. int EWdetectorB::getMedianAList(int index, int count) {
  363.   int m;
  364.   
  365.   if (!count)
  366.     return 0;
  367.   sortAList();
  368.   //printAList();
  369.   // Pick the entry with median avg_rate
  370.   m = (int) (count / 2);
  371.   if (2 * m == count) {
  372.     return((getRateAList(index + m - 1) + getRateAList(index + m)) / 2);
  373.   } else {
  374.     return(getRateAList(index + m));
  375.   }
  376. }
  377. // Get the rate given the index in the list
  378. int EWdetectorB::getRateAList(int index) {
  379.   struct AListEntry *p;
  380.   //printf("%dn", index);
  381.   p = alist.head;
  382.   for (int i = 0; i < index; i++) {
  383.     if (p)
  384.       p = p->next;
  385.   }
  386.   
  387.   if (p)
  388.     return ((int)p->avg_rate);
  389.   printf("Error in AList!n");
  390.   return(0);
  391. }
  392. // Calculate the aggragated response rate for high-bandwidth flows
  393. int EWdetectorB::computeARR() {
  394.   int i, agg_rate;
  395.   // Explicit garbage collection first 
  396.   //  before both choosing HBFs and searching AList
  397.   //printf("before timeout ");
  398.   timeoutAList();
  399.   //printf("after timeout ");
  400.   // do nothing if no entry exists
  401.   if (!alist.count) 
  402.     return 0;
  403.   // Pick the 10% highest bandwidth flows
  404.   arr_count = (int) (alist.count * 0.1 + 1);
  405.   // Sort AList first
  406.   sortAList();
  407.   // Calculate the ARR for HBFs
  408.   // Use mean
  409.   agg_rate = 0;
  410.   for (i = 0; i < arr_count; i++) {
  411.     agg_rate += getRateAList(i);
  412.   }
  413.   
  414.   if (i)
  415.     agg_rate = (int) (agg_rate / i);
  416.   else {
  417.     printf("No MAX returned from ALIST!!!n");
  418.   }
  419.   
  420.   // Use median (the median for the list or median for HBFs?)
  421.   //agg_rate = getMedianAList(0, k);
  422.   //printf("%f %d %d %dn", now, k, agg_rate, getMedianAList(0, k));
  423.   
  424.   return(agg_rate);
  425. }
  426. // Find the matched AList entry
  427. struct AListEntry * EWdetectorB::searchAList(int src_id, int dst_id, int f_id){
  428.   AListEntry *p;
  429.   // Explicit garbage collection first.
  430.   //printf("before timeout ");
  431.   timeoutAList();
  432.   //printf("after timeout ");
  433.   // Use src and dest pair and flow id:
  434.   //   aggregate flows within the same request-response exchange
  435.   // Timeout need to be set to a very small value in order to
  436.   //   seperate different exchanges.
  437.   p = alist.head;
  438.   while (p && 
  439.  (p->f_id != f_id || p->src_id != src_id || p->dst_id != dst_id)) {
  440.     p = p->next;
  441.   }
  442.   
  443.   return(p);
  444. }
  445. // Add new entry to AList
  446. struct AListEntry * EWdetectorB::newAListEntry(int src_id, int dst_id, int f_id) {
  447.   AListEntry *p;
  448.   p = new AListEntry;
  449.   p->src_id = src_id;
  450.   p->dst_id = dst_id;
  451.   p->f_id = f_id;
  452.   p->last_update = now;
  453.   p->avg_rate = 0;
  454.   // Since we are doing random sampling, 
  455.   // the t_front should set to the beginning of this period instead of 0.
  456.   p->t_front = now;
  457.   p->win_length = 1;
  458.   p->next = NULL;
  459.   
  460.   // Add new entry to AList
  461.   if (alist.tail)
  462.     alist.tail->next = p;
  463.   alist.tail = p;
  464.   
  465.   if (!alist.head)
  466.     alist.head = p;
  467.   
  468.   alist.count++;
  469.   return(p);
  470. }
  471. // Find the entry with max avg_rate in AList
  472. struct AListEntry * EWdetectorB::getMaxAList() {
  473.   struct AListEntry *p, *pp, *max, *pm;
  474.   //printAList();
  475.   // find the max entry and remove
  476.   p = pp = alist.head;
  477.   max = pm = p;
  478.   
  479.   while (p) {
  480.     if (p->avg_rate > max->avg_rate) {
  481.       pm = pp;
  482.       max = p;
  483.     }
  484.     
  485.     pp = p;
  486.     p = p->next;
  487.   }
  488.   
  489.   // remove max from AList
  490.   if (alist.head == max)
  491.     alist.head = max->next;
  492.   
  493.   if (pm != max)
  494.     pm->next = max->next;
  495.   
  496.   max->next = NULL;
  497.   //printAList();
  498.   return(max);
  499. }
  500. // Sort AList based on the avg_rate
  501. void EWdetectorB::sortAList() {
  502.   struct AListEntry *max, *head, *tail;
  503.   
  504.   if (!alist.head)
  505.     return;
  506.   //printAList();
  507.   head = tail = NULL;
  508.   while (alist.head) {
  509.     // Get the entry with the max avg_rate
  510.     max = getMaxAList();
  511.     //printAListEntry(max, i);
  512.     
  513.     if (max) {
  514.       // Add max to the tail of the new list
  515.       if (tail)
  516. tail->next = max;
  517.       tail = max;
  518.       
  519.       if (!head)
  520. head = max;
  521.     }
  522.   }
  523.   alist.head = head;
  524.   alist.tail = tail;
  525.   //printAList();
  526. }
  527. // Timeout AList entries
  528. void EWdetectorB::timeoutAList() {
  529.   AListEntry *p, *q;
  530.   float to;
  531.   to = EW_FLOW_TIME_OUT;
  532.   if (dt_inv)
  533.     to = dt_inv;
  534.   // Expire the old entries in AList
  535.   p = q = alist.head;
  536.   while (p) {
  537.     // Garbage collection
  538.     if (p->last_update + to < now){
  539.       // The coresponding flow is expired.      
  540.       if (p == alist.head){
  541. if (p == alist.tail) {
  542.   alist.head = alist.tail = NULL;
  543.   free(p);
  544.   p = q = NULL;
  545. } else {
  546.   alist.head = p->next;
  547.   free(p);
  548.   p = q = alist.head;
  549. }
  550.       } else {
  551. q->next = p->next;
  552. if (p == alist.tail)
  553.   alist.tail = q;
  554. free(p);
  555. p = q->next;
  556.       }
  557.       alist.count--;
  558.     } else {
  559.       q = p;
  560.       p = q->next;
  561.     }
  562.   }
  563. }
  564. // Reset AList
  565. void EWdetectorB::resetAList() {
  566.   struct AListEntry *ap, *aq;
  567.   ap = aq = alist.head;
  568.   while (ap) {
  569.     aq = ap;
  570.     ap = ap->next;
  571.     free(aq);
  572.   }
  573.   
  574.   ap = aq = NULL;
  575.   alist.head = alist.tail = NULL;  
  576.   alist.count = 0;
  577. }
  578. // Reset SWin
  579. void EWdetectorB::resetSWin() {
  580.   struct SWinEntry *p, *q;
  581.   p = q = swin.head;
  582.   while (p) {
  583.     q = p;
  584.     p = p->next;
  585.     free(q);
  586.   }
  587.   
  588.   p = q = NULL;
  589.   swin.head = swin.tail = NULL;  
  590.   swin.count = swin.ravg = 0;
  591. }
  592. // update swin with the latest measurement of aggregated response rate
  593. void EWdetectorB::updateSWin(int rate) {
  594.   struct SWinEntry *p, *new_entry;
  595.   new_entry = new SWinEntry;
  596.   new_entry->rate = rate;
  597.   new_entry->weight = 1;
  598.   new_entry->next = NULL;
  599.   
  600.   if (swin.tail)
  601.     swin.tail->next = new_entry;
  602.   swin.tail = new_entry;
  603.   
  604.   if (!swin.head)
  605.     swin.head = new_entry;
  606.   // Reset current rate.
  607.   if (swin.count < EW_SWIN_SIZE) {
  608.     swin.count++;
  609.   } else {
  610.     p = swin.head;
  611.     swin.head = p->next;
  612.     free(p);
  613.   }
  614. }
  615. // Calculate the running average over the sliding window
  616. void EWdetectorB::ravgSWin() {
  617.   struct SWinEntry *p;
  618.   float sum = 0;
  619.   float t_weight = 0;
  620.   //printf("Calculate running average over the sliding window:n");
  621.   p = swin.head;
  622.   //printf("after pn");
  623.   while (p) {
  624.     //printSWinEntry(p, i++);
  625.     sum += p->rate * p->weight;
  626.     t_weight += p->weight;
  627.     p = p->next;
  628.   }
  629.   p = NULL;
  630.   //printf("n");  
  631.   swin.ravg = (int)(sum / t_weight);
  632.   //  printf("Ravg: %dn", swin.ravg);
  633. }
  634. // detect the traffic change by 
  635. // comparing the current measurement with the long-term average
  636. //   trigger alarm if necessary.
  637. void EWdetectorB::detect() {
  638.   // When ALARM:
  639.   //  detect if it is the time to release the alarm
  640.   // When NO ALARM:
  641.   //  detect if it is the time to trigger the alarm
  642.   if (alarm) {
  643.     // Determine if an alarm should be released
  644.     if (cur_rate > avg_rate * (1 + EW_RELEASE_RANGE)) {
  645.       // reset alarm
  646.       resetAlarm();
  647.     } 
  648.   } else {
  649.     // Determine if an alarm should be triggered
  650.     //   need to be conservative!
  651.     if (cur_rate < avg_rate * (1 - EW_DETECT_RANGE)) {
  652.       setAlarm();
  653.       
  654.       // Initial drop_p to the MAX value whenever alarm triggered
  655.       if (drop_p < EW_MAX_DROP_P)
  656. drop_p = EW_MAX_DROP_P;
  657.     } else {
  658.     }
  659.   }
  660.   
  661.   // Determine the dropping probability
  662.   //computeDropP();
  663. }
  664. // Determine the dropping probability based on current measurement
  665. void EWdetectorB::computeDropP() {
  666.   double p = 0;
  667.   if (alarm) {
  668.     // Compute the dropping probability as a linear function of current rate
  669.     //  p is computed towards the current measurement.
  670.     p = 1;
  671.     if (cur_rate)
  672.       p = (avg_rate - cur_rate) * adjustor / cur_rate;
  673.     
  674.     // p could be greater than 1
  675.     if (p > 1)
  676.       p = 1;
  677.     // p could also be negative
  678.     if (p < 0)
  679.       p = 0;
  680.     
  681.     // Compute the actual drop probability
  682.     drop_p = ALPHA * drop_p + (1 - ALPHA) * p;    
  683.     // adjust drop_p
  684.     if (drop_p < EW_MIN_DROP_P)
  685.       drop_p = EW_MIN_DROP_P;
  686.     if (drop_p > EW_MAX_DROP_P)
  687.       drop_p = EW_MAX_DROP_P;
  688.   } else {
  689.     // Fade out the drop_p when no alarm
  690.     if (drop_p > 0) {
  691.       if (drop_p <= EW_MIN_DROP_P)
  692.         drop_p = 0;
  693.       else {
  694.         drop_p = ALPHA * drop_p;
  695.       }
  696.     }
  697.   }
  698. }
  699. // Decreas the sample interval
  700. void EWdetectorB::decSInv() {
  701.   // Need some investigation for the min allowed detection interval
  702.   //  if (s_inv / 2 > EW_MIN_SAMPLE_INTERVAL) {
  703.   // s_inv = s_inv / 2;
  704.     
  705.     //printf("SINV decreased by 2.n");
  706.   //}
  707. }
  708. // Increase the sample interval
  709. void EWdetectorB::incSInv() {
  710.   //if(s_inv * 2 <= init_s_inv) {
  711.   //  s_inv = s_inv * 2;
  712.   
  713.   //printf("SINV increased by 2.n");
  714.   // }
  715. }
  716. // Prints one entry in SWin
  717. void EWdetectorB::printSWin() {
  718.   struct SWinEntry *p;
  719.   printf("%f SWIN[%d, %d]", now, swin.ravg, swin.count);
  720.   p = swin.head;
  721.   int i = 0;
  722.   while (p) {
  723.     printSWinEntry(p, i++);
  724.     p = p->next;
  725.   }
  726.   p = NULL;
  727.   printf("n");
  728. }
  729. // Print the contents in SWin
  730. void EWdetectorB::printSWinEntry(struct SWinEntry *p, int i) {
  731.   if (p)
  732.     printf("[%d: %d %.2f] ", i, p->rate, p->weight);
  733. }
  734. // Print one entry in AList
  735. void EWdetectorB::printAListEntry(struct AListEntry *p, int i) {
  736.   if (!p)
  737.     return;
  738.   printf("[%d] %d (%d %d) %.2f %.2fn", i, p->f_id, p->src_id, p->dst_id, 
  739.  p->avg_rate, p->last_update);
  740. }
  741. // Print the entries in AList
  742. void EWdetectorB::printAList() {
  743.   struct AListEntry *p;
  744.   printf("%f AList(%d):n", now, alist.count);
  745.   p = alist.head;
  746.   int i = 0;
  747.   while (p) {
  748.     printAListEntry(p, i);
  749.     i++;
  750.     p = p->next;
  751.   }
  752.   p = NULL;
  753.   printf("n");
  754. }
  755. // Trace bit rate (resp rate)
  756. void EWdetectorB::trace() {
  757.   double db_rate = 0;
  758.   double m_rate = 0;
  759.   timeoutAList();
  760.   m_rate = getMedianAList(0, alist.count);
  761.   //printf("B ");
  762.   db_rate = computeARR();
  763.   if (!m_rate || !db_rate);
  764.     //printAList();
  765.   printf("B %d %.2f %.2f %d %d %.2f %.2fn", 
  766.  (int)now, cur_rate, avg_rate, arr_count, alarm, db_rate, m_rate);
  767. }
  768. // EW packet detector
  769. EWdetectorP::EWdetectorP() : EWdetector() {
  770.   // Packet stats
  771.   cur_p.arrival = cur_p.dept = cur_p.drop = 0;
  772.   last_p.arrival = last_p.dept = last_p.drop = 0;
  773.   last_p_db.arrival = last_p_db.dept = last_p_db.drop = 0;
  774. }
  775. EWdetectorP::~EWdetectorP(){
  776.   // Packet stats
  777.   cur_p.arrival = cur_p.dept = cur_p.drop = 0;
  778.   last_p.arrival = last_p.dept = last_p.drop = 0;
  779. }
  780. // get the current request rate
  781. double EWdetectorP::getRate() {
  782.   return(cur_rate);
  783. }
  784. // update packet stats
  785. void EWdetectorP::updateStats(int flag) {
  786.   // Packet arrival
  787.   if (flag == PKT_ARRIVAL) {
  788.     cur_p.arrival++;
  789.     return;
  790.   }
  791.   // Packet departure
  792.   if (flag == PKT_DEPT) {
  793.     cur_p.dept++;
  794.     return;
  795.   }
  796.   // Packet dropped
  797.   if (flag == PKT_DROP) {
  798.     cur_p.drop++;
  799.     return;
  800.   }
  801. }
  802. // Detect changes in packet rate
  803. void EWdetectorP::detect() {
  804.   if (cur_rate > avg_rate * (1 + EW_DETECT_RANGE)) {
  805.     if (!alarm) {
  806.       setAlarm();
  807.     }
  808.   } else if (cur_rate < avg_rate * (1 - EW_RELEASE_RANGE)) {
  809.     if (alarm)
  810.       resetAlarm();
  811.   }
  812. }
  813. // Update current measurement
  814. void EWdetectorP::updateCur() {
  815.   // measure the accepted packet rate (rather than arrival rate)
  816.   cur_rate = (cur_p.dept - last_p.dept) / dt_inv;
  817.   // keep the current value
  818.   last_p.arrival = cur_p.arrival;
  819.   last_p.dept = cur_p.dept;
  820.   last_p.drop = cur_p.drop;
  821. }
  822. // Update long term average
  823. /*void EWdetectorP::updateAvg() {
  824.   avg_rate = (int)(hlf.alpha * avg_rate + (1 - hlf.alpha) * cur_rate);
  825. }
  826. */
  827. // Update stats
  828. void EWdetectorP::measure(Packet *pkt) {
  829.   
  830.   // stats on packet departure and drop are collect in policer 
  831. }
  832. // Trace packet incoming rate (req rate)
  833. void EWdetectorP::trace() {
  834.   printf("P %d %.2f %.2f %d %d %d %d %d %d %dn", 
  835.  (int)now, cur_rate, avg_rate, alarm,
  836.  cur_p.arrival - last_p_db.arrival,
  837.  cur_p.dept - last_p_db.dept,
  838.  cur_p.drop - last_p_db.drop,  
  839.  cur_p.arrival, cur_p.dept, cur_p.drop);
  840.   last_p_db.arrival = cur_p.arrival;
  841.   last_p_db.dept = cur_p.dept;
  842.   last_p_db.drop = cur_p.drop;
  843. }
  844. // EW Policy: deal with queueing stuffs.
  845. //Constructor.  
  846. EWPolicy::EWPolicy() : Policy() {
  847.   // Initialize detectors
  848.   ewB = cewB = NULL;
  849.   ewP = cewP = NULL;
  850.   
  851.   // Initialize rate limitor
  852.   rlP = rlB = NULL;
  853.   max_p = max_b = 0;
  854.   alarm = pre_alarm = 0;
  855.   change = 0;
  856. }
  857. //Deconstructor.
  858. EWPolicy::~EWPolicy(){
  859.   if (ewB)
  860.     free(ewB);
  861.   if (ewP)
  862.     free(ewP);
  863.   if (cewB)
  864.     free(cewB);
  865.   if (cewP)
  866.     free(cewP);
  867. }
  868. // Initialize the EW parameters
  869. void EWPolicy::init(int adj, int src, int dst) {
  870.   ew_adj = adj;
  871.   qsrc = src;
  872.   qdst = dst;
  873. }
  874. // EW meter: do nothing.
  875. //  measurement is done in policer: we need to know whether the packet is
  876. //    dropped or not.
  877. void EWPolicy::applyMeter(policyTableEntry *policy, Packet *pkt) {
  878.   return;
  879. }
  880. // EW Policer
  881. //  1. do measurement: P: both arrival and departure; B: only departure
  882. //  2. make packet drop decisions
  883. int EWPolicy::applyPolicer(policyTableEntry *policy, policerTableEntry *policer, Packet *pkt) {
  884.   //printf("enter applyPolicer ");
  885.   // can't count/penalize ACKs:
  886.   //   with resp: may cause inaccurate calculation with TSW(??)
  887.   //   with req:  may cause resp retransmission.
  888.   // just pass them through
  889.   hdr_cmn *th = hdr_cmn::access(pkt);
  890.   hdr_ip* iph = hdr_ip::access(pkt);
  891.   int dst_id = iph->daddr();
  892.   int src_id = iph->saddr();
  893.   if (th->ptype() == PT_ACK)
  894.     return(policer->initialCodePt);
  895.   // for other packets...
  896.   // Get time
  897.   now = Scheduler::instance().clock();
  898.   // keep arrival packet stats
  899.   if (ewP) {
  900.     printf("TRR %d %d %d %dn", (int)now, src_id, dst_id, th->size());
  901.     ewP->updateStats(PKT_ARRIVAL);
  902.   }
  903.   // For other packets:
  904.   if (dropPacket(pkt)) {
  905.     // keep packet stats
  906.     if (ewP)
  907.       ewP->updateStats(PKT_DROP);
  908.     
  909.     //printf("downgrade!n");
  910.     return(policer->downgrade1);
  911.   } else {
  912.     // keep packet stats
  913.     if (ewP)
  914.       ewP->updateStats(PKT_DEPT);
  915.     // conduct EW detection
  916.     if (ewP)
  917.       ewP->run(pkt);
  918.     
  919.     if (ewB)
  920.       ewB->run(pkt);    
  921.     //printf("initial!n");
  922.     return(policer->initialCodePt);
  923.   }
  924. }
  925. // detect if there is alarm triggered
  926. void EWPolicy::detect(Packet *pkt) {
  927.   int alarm_b, alarm_p;
  928.   alarm_b = alarm_p = 0;
  929.   if (!ewP || ! cewB)
  930.     return;
  931.   
  932.   alarm_b = cewB->testAlarm();
  933.   alarm_p = ewP->testAlarm();
  934.   
  935.   if (alarm_p == EW_UNCHANGE || alarm_b == EW_UNCHANGE)
  936.     return;
  937.   // Need to get info from both parts to make a decision
  938.   // Reset change flags
  939.   ewP->resetChange();
  940.   cewB->resetChange();
  941.   change = 1;
  942.   // keep the old value of alarm
  943.   pre_alarm = alarm;
  944.   // As long as alarm_b is 0, reset the alarm
  945.   if (alarm_b == 0)
  946.     alarm = 0;
  947.   else if (alarm_p == 0)
  948.     alarm = 0;
  949.   else 
  950.     alarm = 1;
  951.   printf("ALARM %d %dn", pre_alarm, alarm);
  952. }
  953. //  make packet drop decisions
  954. int EWPolicy::dropPacket(Packet *pkt) {
  955.   // 1. arrival stats is measured in meter (departure and drops here)
  956.   // 2. No penalty to response traffic!!
  957.   // 3. need to protect existing connections
  958.   // pass EW if there is any
  959.   if (cewB && ewP) {
  960.     // protecting existing connections
  961.     //  drop requests for new connection (SYN packet)
  962.     //    if (cewB->exFlow(pkt))
  963.     hdr_tcp *tcph = hdr_tcp::access(pkt);
  964.     // Protecting non-SYN packets: existing connections
  965.     if ((tcph->flags() & TH_SYN) == 0) {
  966.       //return(0);
  967.     }
  968.     // Check alarm
  969.     detect(pkt);
  970.     if (change) {
  971.       // for new incoming requests:
  972.       //   use EW measurement to adjust the rate limit (to current Rq)
  973.       // see if the alarm should be reset
  974.       
  975.       if (pre_alarm) {
  976. if (alarm) {
  977.   // The rate is not right:
  978.   //   too low: too few connection admitted;
  979.   //   too high: congestion in response
  980.   // Adjustment is needed.
  981.   if (rlP)
  982.     rlP->adjustRate();
  983. } else {
  984.   // the current rate is ok, award the current choice
  985.   if (rlP)
  986.     rlP->adjustScore(1);
  987. }
  988.       } else {
  989. if (alarm) {
  990.   if (rlP) {
  991.     // Start a new round
  992.     rlP->resetScore();
  993.     // Use current request rate as the rate limit
  994.     rlP->setRate(ewP->getRate());
  995.   }
  996. } else {
  997.   // the current rate is ok
  998. }
  999.       }    
  1000.       
  1001.       change = 0;
  1002.     }  
  1003.   }
  1004.   // Passing rate limitor if there is any
  1005.   if (rlP) {
  1006.     // rate limiting
  1007.     return(rlP->run(1));
  1008.   };
  1009.   
  1010.   // through by default
  1011.   return(0);
  1012. }
  1013. // Enable detecting on packet incoming rate (req rate)
  1014. void EWPolicy::detectPr(int dt_inv, int db_inv) {
  1015.   ewP = new EWdetectorP;
  1016.   ewP->setLink(qsrc, qdst);
  1017.   ewP->setDt(dt_inv);
  1018.   ewP->setDb(db_inv);
  1019. }
  1020. void EWPolicy::detectPr(int dt_inv) {
  1021.   detectPr(dt_inv, dt_inv);
  1022. }
  1023. void EWPolicy::detectPr() {
  1024.   detectPr(EW_DT_INV, EW_DB_INV);
  1025. }
  1026. // Enable detecting and debugging bit rate (eg: resp rate)
  1027. void EWPolicy::detectBr(int dt_inv, int db_inv) {
  1028.   ewB = new EWdetectorB;
  1029.   ewB->init(ew_adj);
  1030.   ewB->setLink(qsrc, qdst);
  1031.   ewB->setDt(dt_inv);
  1032.   ewB->setDb(db_inv);
  1033. }
  1034. void EWPolicy::detectBr(int dt_inv) {
  1035.   detectBr(dt_inv, dt_inv);
  1036. }
  1037. void EWPolicy::detectBr() {
  1038.   detectBr(EW_DT_INV, EW_DB_INV);
  1039. }
  1040. // Rate limitor: packet rate
  1041. void EWPolicy::limitPr(double rate) {
  1042.   //printf("PR %dn", rate);
  1043.   rlP = new TBrateLimitor(rate);
  1044. }
  1045. // Rate limitor: bit rate
  1046. void EWPolicy::limitBr(double rate) {
  1047.   //printf("BR %dn", rate);
  1048.   rlB = new TBrateLimitor(rate);
  1049. }
  1050. // Rate limitor: packet rate
  1051. void EWPolicy::limitPr() {
  1052.   limitPr(DEFAULT_TB_RATE_P);
  1053. }
  1054. // Rate limitor: bit rate
  1055. void EWPolicy::limitBr() {
  1056.   limitBr(DEFAULT_TB_RATE_B);
  1057. }
  1058. // couple EW detector
  1059. void EWPolicy::coupleEW(EWPolicy *ewpc) {
  1060.   coupleEW(ewpc, 0);
  1061. }
  1062. // couple EW detector
  1063. void EWPolicy::coupleEW(EWPolicy *ewpc, double rate) {
  1064.   // couple the EW detector 
  1065.   cewB = ewpc->ewB;
  1066.   
  1067.   // Setup rate limitor with the default limit
  1068.   if (rate)
  1069.     limitPr(rate);
  1070.   else
  1071.     limitPr();
  1072. }
  1073. // End of EWP