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

通讯编程

开发平台:

Visual C++

  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <strings.h>
  6. #include <assert.h>
  7. #include <iostream.h>
  8. // Integration of Ashish's RED and asim
  9. #define _RED_ROUTER_MAIN_
  10. #include "asim.h"
  11. #define sp " " 
  12. // Optimization
  13. #include<vector>
  14. using namespace std;
  15. typedef struct c{
  16. int no; // no of edges in the connection
  17. double delay; // total delay;
  18. double drop; // total drop prob
  19. double p_tput;
  20. double t;
  21. // The short flow stuff
  22. int is_sflow; // boolean to indicate whether there is a short flow
  23. double slambda; // The arrival rate of the connections
  24. int snopkts; // average of no of packets each short flow givies
  25. RedRouter * red;
  26. int scaled; // Whether this flow has been scaled or not
  27. }flow_stats;
  28. typedef struct n{
  29. int red; // flag to notify whether its a red queue or not
  30. double pmin, pmax, minth, maxth; // RED parameters
  31. double lambda; // Arrival rate - Packets per second
  32. double plambda; // Temp lambda value. previous lambda
  33. double tlambda;
  34. double mu; // Consumption rate - Packets per second
  35. double prop; // Propagation delay of the link
  36. double qdelay; // Store the queuing delay for each link
  37. int    buffer; // Total buffer
  38. double drop; // probability of drop
  39. int nflows; // Number of flows through this link
  40. vector<int> theflows; // The flows through this link
  41. double scaled_lambda;
  42. double unscaled_lambda;
  43. double utput; // unscaled tput 
  44. double uc; // unscaled capacity
  45. // RED
  46. RedRouter * redrouter;
  47. }link_stats;
  48. class asim {
  49. public:
  50. // data structures 
  51. int nConnections; // Number of connections
  52. int K, MaxHops; // 
  53. int nLinks; // Number of links 
  54. int **Adj; // Stores the edge list of each connection
  55. int *nAdj; // Stores the no of edges per connection
  56. link_stats* links;
  57. flow_stats* flows;
  58. double min(double x, double y){
  59. return (x<y)?x:y;
  60. }
  61. double padhye(double rtt, double p){
  62. double rto = 1;
  63. double t=1;
  64. t = rtt*sqrt(2*p/3)+rto*min(1,(3*sqrt(3*p/8)))*p*(1+32*p*p);
  65. return min(20/rtt,1/t);
  66. }
  67. double Po(double rho, int K){
  68. if(rho==1)
  69. return 1.0/(K+1);
  70. double t;
  71. t=(1.0*(1-rho))/(1.0-pow(rho,K));
  72. return t;
  73. }
  74. double Pk(double rho, int K, int k){
  75. if(rho==1)
  76. return 1.0/(K+1);
  77. if(rho==0)
  78. return 0;
  79. double t;
  80. // M/M/1/K
  81. t=((1-rho)*pow(rho,k))/(1-pow(rho,K+1));
  82. return t;
  83. }  
  84. double Lq(double rho, int K){
  85. double t1,t2;
  86. if(rho==1){
  87. return (1.0*K*(K-1))/(2.0*(K+1));
  88. }
  89. t1=rho*1.0/(1-rho);
  90. t2=rho*1.0/(1-pow(rho,K+1));
  91. t2*=K*pow(rho,K)+1;
  92. return (t1-t2)/2;
  93. }
  94. double get_link_drop(int x){
  95. assert(x<nLinks);
  96. return links[x].drop;
  97. }
  98. double get_link_delay(int x){
  99. assert(x<nLinks);
  100. return links[x].qdelay + links[x].prop ;
  101. }
  102. double get_link_qdelay(int x){
  103. assert(x<nLinks);
  104. return links[x].qdelay;
  105. }
  106. double get_link_pdelay(int x){
  107. assert(x<nLinks);
  108. return links[x].prop;
  109. }
  110. double get_link_tput(int x){
  111. assert(x<nLinks);
  112. return links[x].lambda;
  113. }
  114. double get_flow_delay(int x){
  115. assert(x<nConnections);
  116. return flows[x].delay;
  117. }
  118. double get_flow_tput(int x){
  119. assert(x<nConnections);
  120. return flows[x].p_tput;
  121. }
  122. double get_flow_drop(int x){
  123. assert(x<nConnections);
  124. return flows[x].drop;
  125. }
  126. void GetInputs(char *argv) {
  127. // Init links and connections 
  128. nConnections = 0;
  129. nLinks = 0;
  130. // Start the reading process
  131. FILE *f;
  132. f = fopen(argv,"r");
  133. assert(f);
  134. char s[256];
  135. while (fgets(s, 255, f)) {
  136. // Read a token 
  137. char *t;
  138. t = strtok(s, " tn");
  139. // Ignore comments 
  140. if (!t || !t[0] || (t[0] == '#') || !strncasecmp(t, "comment", 6))
  141. continue;
  142. // Define the number of connections
  143. if (!strcasecmp(t,"n")) {
  144. t = strtok(NULL," t");
  145. assert(t);
  146. nConnections = atoi(t);
  147. assert(nConnections > 0);
  148. assert(nConnections >= 0);
  149. nAdj = new int[nConnections];
  150. Adj = new int*[nConnections];
  151. flows = new flow_stats[nConnections];
  152. for (int i=0; i<nConnections; ++i)
  153. nAdj[i] = -1;
  154. continue;
  155. }
  156. // Define the number of links
  157. else if (!strcasecmp(t,"m")) {
  158. t = strtok(NULL," t");
  159. assert(t);
  160. // #of links defined
  161. nLinks = atoi(t);
  162. assert(nLinks > 0);
  163. // Allocate space for sotring lambdas and mus
  164. links = new link_stats[nLinks];
  165. continue;
  166. }
  167. // Enter each route 
  168. else if (!strcasecmp(t,"route")) {
  169. assert (nConnections > 0);
  170. assert (nLinks > 0);
  171. t = strtok(NULL," t");
  172. assert(t);
  173. int i = atoi(t);
  174. assert(i > 0 && i<= nConnections);
  175. i--;
  176. // We dunno whether this will be short flow specs
  177. flows[i].is_sflow = 0; // Lets assume its a normal flow
  178. flows[i].drop = 0; // Assume ideal case to start off
  179. flows[i].scaled = 0; // Not scaled as yet
  180. t = strtok(NULL," t");
  181. assert(t);
  182. nAdj[i] = atoi(t);
  183. assert(nAdj[i] > 0 && nAdj[i] <= nLinks);
  184. // We know how many links it will use
  185. Adj[i] = new int[nAdj[i]];
  186. for (int j=0; j<nAdj[i]; ++j) {
  187. t = strtok(NULL," t");
  188. assert(t);
  189. int l = atoi(t);
  190. assert(l > 0 && l <= nLinks);
  191. l--;
  192. Adj[i][j] = l;
  193. }
  194. if (MaxHops < nAdj[i]) MaxHops = nAdj[i];
  195. t = strtok(NULL," t");
  196. // assert(t);
  197. // Short flows stuff 
  198. if (t && !strcasecmp(t,"sh")) {
  199. // There are short flows on this route.
  200. flows[i].is_sflow = 1;
  201. // read the slambda
  202. t = strtok(NULL," t");
  203. assert(t);
  204. double  tmp = atof(t);
  205. flows[i].slambda = tmp;
  206. // read the snopkts
  207. t = strtok(NULL," t");
  208. assert(t);
  209. int  tmpi = atoi(t);
  210. flows[i].snopkts = tmpi;
  211. }
  212. // For cbr 
  213. // Treat almost like a short flow!
  214. if (t && !strcasecmp(t,"cbr")) {
  215. // There are short flows on this route.
  216. flows[i].is_sflow = 2;
  217. // read the rate
  218. t = strtok(NULL," t");
  219. assert(t);
  220. double  tmp = atof(t);
  221. flows[i].slambda = tmp;
  222. flows[i].snopkts = 1;
  223. }      
  224. // Now, let us put the flows in persective
  225. // Insert the flow id trhough all the links
  226. int l_;
  227. for(int j=0;j<nAdj[i];j++){
  228. l_ = Adj[i][j];
  229. (links[l_].theflows).push_back(i);
  230. links[l_].nflows++;
  231. if(flows[i].is_sflow){
  232. links[l_].lambda+=flows[i].slambda*flows[i].snopkts;
  233. }
  234. }
  235. continue;
  236. }
  237. else if(!strcasecmp(t,"link")){
  238. assert (nLinks > 0);
  239. // Get the link number
  240. t = strtok(NULL," t");
  241. assert(t);
  242. int i = atoi(t);
  243. assert(i > 0 && i<= nLinks);
  244. i--;
  245. // Get the prop delay
  246. t = strtok(NULL," t");
  247. assert(t);
  248. double p = atof(t);
  249. assert(p>=0); 
  250. links[i].prop = p;
  251. // Get the lambda for this link
  252. t = strtok(NULL," t");
  253. assert(t);
  254. p = atof(t);
  255. assert(p>=0);
  256. links[i].lambda = 0;
  257. links[i].tlambda = p;
  258. links[i].plambda = p;
  259. // Get the mu for this link
  260. t = strtok(NULL," t");
  261. assert(t);
  262. p = atof(t);
  263. assert(p>=0);
  264. links[i].mu = p;
  265. // Get the buffer for this link
  266. t = strtok(NULL," t");
  267. assert(t);
  268. int t1 = atoi(t);
  269. assert(t1>0);
  270. links[i].buffer = t1;
  271. // Check for RED Q or not
  272. t = strtok(NULL," t");
  273. if(t && !strcasecmp(t,"red")){
  274. // must be a red queue
  275. // input red parameters
  276. // all parameters between 0 and 1
  277. links[i].red=1;
  278. // get minth
  279. t = strtok(NULL," t");
  280. double dt = atof(t); 
  281. //assert(dt>=0 && dt<=1);
  282. links[i].minth=dt;
  283. // get pmin
  284. t = strtok(NULL," t");
  285. dt = atof(t); 
  286. //assert(dt>=0 && dt<=1);
  287. links[i].pmin=dt;
  288. // get maxth
  289. t = strtok(NULL," t");
  290. dt = atof(t); 
  291. //assert(dt>=0 && dt<=1);
  292. links[i].maxth=dt;
  293. // get pmax
  294. t = strtok(NULL," t");
  295. dt = atof(t); 
  296. //assert(dt>=0 && dt<=1);
  297. links[i].pmax=dt;
  298. // Invoke Ashish's RED module ... ignore pmin .....
  299. links[i].redrouter = new RedRouter((int)links[i].minth, 
  300.    (int)links[i].maxth,
  301.    links[i].pmax);
  302. assert(links[i].red);
  303. }
  304. else{
  305. links[i].red=0;
  306. }
  307. links[i].nflows = 0; // init the num of flows
  308. continue;
  309. }
  310. assert(0);
  311. }
  312. // Check whether everything is all right 
  313. assert (nConnections > 0);
  314. assert (nLinks > 0);
  315. for (int i=0; i<nConnections; ++i)
  316. assert(nAdj[i] > 0);
  317.   
  318. }
  319. double redFn(double minth, double pmin,
  320.      double maxth, double pmax, double qlength){
  321. assert(qlength>=0 && qlength<=1);
  322. assert(pmax>=0 && pmax<=1);
  323. assert(pmin>=0 && pmin<=1);
  324. assert(minth>=0 && minth<=1);
  325. assert(maxth>=0 && maxth<=1);
  326. assert(maxth>=minth);
  327. assert(pmax>pmin);
  328. double t;
  329. if(qlength<minth)
  330. return 0;
  331. if(qlength>maxth)
  332. return 1;
  333. return pmin + (qlength-minth)/(pmax-pmin);
  334. }
  335. void  CalcLinkStats(int flag = 0){
  336. // flag = 1 means enable RED
  337. // Calculate Link delays ... basically queuing delays
  338. for(int i=0; i<nLinks; i++){
  339. double rho = links[i].lambda/links[i].mu;
  340. double qlength = Lq(rho,links[i].buffer);
  341. links[i].qdelay = qlength/links[i].mu; 
  342. links[i].drop = Pk(rho,links[i].buffer,links[i].buffer);
  343. // cout << "Link " << i << " has drop prob = " << links[i].drop << endl;
  344. // Special code for RED gateways
  345. if(flag){
  346. if(links[i].red){
  347. double minth, maxth, pmin, pmax, delay,p;
  348. minth = links[i].minth;
  349. maxth = links[i].maxth;
  350. pmin = links[i].pmin;
  351. pmax = links[i].pmax;
  352. // The RED approx.
  353. p=(links[i].redrouter)->ComputeProbability(rho, delay);
  354. links[i].drop = p;
  355. qlength = Lq(rho*(1-p), links[i].buffer);
  356. links[i].qdelay = delay;
  357. }
  358. }
  359. // cout << i << sp << "rho = " << rho << " delay = " << links[i].qdelay << " and drop = " << links[i].drop << endl;
  360. }
  361. }
  362. void CalcPerFlowStats(){
  363.  
  364. for(int i=0; i<nConnections; i++){
  365. double d = 0, p = 1 ;
  366. // Calculate drops and delays
  367. for(int j=0;j<nAdj[i];j++){
  368. d += 2*links[Adj[i][j]].prop + links[Adj[i][j]].qdelay;
  369. p *= 1-links[Adj[i][j]].drop;
  370. }
  371. p = 1-p;
  372. //cout << "Flow " << i << " has drop prob = " << p << endl; 
  373. flows[i].no = nAdj[i];
  374. flows[i].delay = d;
  375. flows[i].drop = p;
  376. flows[i].t = flows[i].p_tput;    
  377. // p is the end2end drop prob
  378. // If its normal flow, calculate Padhye's stuff
  379. // If its short flow, use our approximations
  380. // Nothing more
  381. if(flows[i].is_sflow==1){
  382. // If k flows come and each each flow has n packets to 
  383. // send then 
  384. double t = (flows[i].slambda*flows[i].snopkts);
  385. flows[i].p_tput = t/(1-p);
  386. }
  387. else if(flows[i].is_sflow==2){
  388. // For CBR, dont divide by 1-p unlike short flows.
  389. // If rate is x and prob is p, net goodput is x(1-p)
  390. flows[i].p_tput = flows[i].slambda*(1-p);
  391. // cout << "cbr stuff - tput = " << flows[i].p_tput << endl;
  392. }
  393. else{
  394. // regular bulk TCP connections, Padhye et. al.
  395. if(!p){
  396. // cout << "Oops, something wrong";
  397. }
  398. flows[i].p_tput = padhye(d,p);
  399. }
  400. // cout << "connection " << sp << i << sp << d << sp << p; 
  401. //cout << sp << flows[i].p_tput << endl;
  402. }
  403. }
  404. void PrintData(){
  405. for(int i=0;i<nLinks;i++){
  406. cout << i << sp << links[i].lambda << sp << links[i].mu;
  407. cout << sp << links[i].buffer << endl;
  408. }
  409. }
  410. void PrintResults(){
  411. for(int i=0;i<nLinks;i++){
  412. printf("l %d qdel %.5lf drop %.5lf lam %.3lfn", i+1, links[i].qdelay, links[i].drop,links[i].lambda);
  413. }
  414. for(int i=0; i<nConnections; i++){
  415. printf("c %d gput %.5lf drop %.5lf e2edel %.5lfn", i+1,
  416.        flows[i].p_tput,
  417.        flows[i].drop,
  418.        flows[i].delay);
  419. }
  420. }
  421. void UpdateHelper(int flag=0){
  422. // if flag = 1 then update only when link is unscaled as of now
  423. // if flag = 0 then do the usual update 
  424. for(int i=0; i<nLinks; i++){
  425. links[i].tlambda=0;
  426. }
  427. for(int i=0; i<nConnections; i++){
  428. if(!flag || !flows[i].scaled) 
  429. for(int j=0;j<nAdj[i];j++){
  430. if(flows[i].is_sflow==2){
  431. // cbr flow
  432. links[Adj[i][j]].tlambda += flows[i].slambda*(1-links[Adj[i][j]].drop);
  433. //cout << "cbr flow " << i << " adding " << flows[i].slambda*(1-links[Adj[i][j]].drop)
  434. //    << " to link " << j << " tlam = " << links[Adj[i][j]].tlambda << endl;
  435. }
  436. else
  437. links[Adj[i][j]].tlambda += flows[i].p_tput;
  438. }
  439. //    cout << flows[i].p_tput << "n";
  440. }
  441. }
  442. void Update(int niter){
  443. UpdateHelper();
  444. for(int i=0; i<nLinks; i++){
  445. links[i].plambda = links[i].lambda;
  446. double t;
  447. double tk=links[i].mu*(1.05)+5;
  448. if(niter){
  449. if(links[i].tlambda>tk)
  450. //t = pow((sqrt(links[i].lambda)+sqrt(links[i].mu+5))/2,2);
  451. t = ((links[i].lambda)+tk)/2;
  452. // t = exp((log(links[i].lambda)+log(links[i].mu+5))/2);
  453. else
  454. //t = pow((sqrt(links[i].tlambda)+sqrt(links[i].lambda))/2,2);
  455. t= ((links[i].tlambda)+(links[i].lambda))/2;
  456. // t = exp((log(links[i].tlambda)+log(links[i].lambda))/2);
  457. }
  458. else t = links[i].tlambda;
  459. links[i].lambda = t; // Update the lambda ..........
  460. }
  461. }
  462. int allscaled(){
  463. //cout << nConnections;
  464. for(int i=0; i<nConnections; i++)
  465. if(!flows[i].is_sflow && !flows[i].scaled){
  466. //cout << "Connection " << i << " not scaled as yetn";
  467. return 0;
  468. }
  469. cout << "All are scaledn";
  470. return 1;
  471. }
  472.   
  473. void newupdate(int niter){
  474. // 1st init all unscaled tputs and cap
  475. for (int i=0;i<nLinks;i++){
  476. links[i].uc = links[i].mu*(1.05);
  477. links[i].utput = 0;
  478. }
  479. // calc all the unscaled tputs and C set all short flows 
  480. // to be scaled already 
  481. for(int i=0; i<nConnections; i++){
  482. if(flows[i].is_sflow)
  483. flows[i].scaled = 1;
  484. else 
  485. flows[i].scaled = 0;
  486. for(int j=0;j<nAdj[i];j++){
  487. if(flows[i].is_sflow)
  488. links[Adj[i][j]].uc -= flows[i].p_tput;
  489. else
  490. links[Adj[i][j]].utput += flows[i].p_tput;
  491. }
  492. }
  493. //for(int i =0; i<nLinks; i++ ){
  494. //cout << i << sp << links[i].uc << sp << links[i].utput << endl;
  495. //}
  496. double maxgamma; // most congested link
  497. int bneck;
  498. double t;
  499. bneck = -1;
  500. maxgamma = 0;
  501. for(int i=0; i<nLinks; i++){
  502. if(links[i].uc){
  503. t=links[i].utput/links[i].uc;
  504. if(t > maxgamma){
  505. bneck = i;
  506. maxgamma = t;
  507. }
  508. }
  509. }    
  510. while(bneck+1){
  511. //cout << "bneck = " << bneck << sp << links[bneck].uc << sp << links[bneck].utput << sp << maxgamma << sp << links[bneck].nflows <<endl;
  512. for(int i=0; i<links[bneck].nflows; i++){
  513. // For all the connections passing through this link
  514. int t = links[bneck].theflows[i]; // get a connection id
  515. //     cout << i<< sp << t << sp ;
  516. // Now reduce its p_tput iff its not a short flow
  517. // For short flows we dont do scaling
  518. if(!flows[t].is_sflow && !flows[t].scaled){
  519. flows[t].p_tput /= maxgamma;
  520. //cout << "Flow " << t << " getting scaled to  << " << flows[t].p_tput;
  521. flows[t].scaled = 1; // we have scaled this flow already
  522. for(int j=0;j<nAdj[t];j++){
  523. // subtract this scaled throughout from all teh links that
  524. // have this flow. 
  525. links[Adj[t][j]].uc -= flows[t].p_tput;
  526. links[Adj[t][j]].utput -= flows[t].p_tput*maxgamma;
  527. // cout << sp << Adj[i][j];
  528. }
  529. //cout << endl;
  530. }
  531. }
  532.     
  533. //cout << links[bneck].uc << sp << links[bneck].utput << endl;
  534.     
  535. links[bneck].uc = 0;
  536. bneck = -1;
  537. maxgamma = 0;
  538. for(int i=0; i<nLinks; i++){
  539. if(links[i].uc){
  540. t=links[i].utput/links[i].uc;
  541. if(t > maxgamma){
  542. bneck = i;
  543. maxgamma = t;
  544. }
  545. }
  546. }
  547. Update(niter);
  548. }
  549. asim(){
  550. //cout << "Reached heren";
  551. }
  552. };
  553. int main(int argc, char **argv) {
  554. int niter = 0;
  555. // error if usage is wrong 
  556.    
  557. if (argc != 2) {
  558. fprintf(stderr,"Usage: %s  <InputFile>n", argv[0]);
  559. exit(-1); 
  560. }
  561. asim sim;
  562. sim.GetInputs(argv[1]);
  563. //sim.PrintResults();
  564. //cout << "Read the input .... n";
  565. for(int i=0; i<3; i++){
  566. sim.CalcLinkStats(1);
  567. //cout << "Calculated link delays ... n";
  568. sim.CalcPerFlowStats();
  569. //cout << "Calculated per flow delays ... n";
  570. //cout << " ------------------------------n";
  571. sim.newupdate(niter);
  572. //sim.PrintResults();
  573. //cout << " ------------------------------n"; 
  574. }
  575. sim.PrintResults();
  576. }