forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
RouterCoreSave.cpp
1 
9 #include "RouterCore.h"
10 
11 namespace forest {
12 
13 
24 bool processArgs(int argc, char *argv[], RouterInfo& args) {
25  // set default values
26  args.mode = "local";
27  args.myAdr = args.bootIp = args.nmAdr = args.nmIp = 0;
28  args.ccAdr = args.firstLeafAdr = args.lastLeafAdr = 0;
29  args.ifTbl = ""; args.lnkTbl = ""; args.comtTbl = "";
30  args.rteTbl = ""; args.statSpec = "";
31  args.finTime = 0;
32 
33  string s;
34  for (int i = 1; i < argc; i++) {
35  s = argv[i];
36  if (s.compare(0,10,"mode=local") == 0) {
37  args.mode = "local";
38  } else if (s.compare(0,11,"mode=remote") == 0) {
39  args.mode = "remote";
40  } else if (s.compare(0,6,"myAdr=") == 0) {
41  args.myAdr = Forest::forestAdr(&argv[i][6]);
42  } else if (s.compare(0,7,"bootIp=") == 0) {
43  args.bootIp = Np4d::ipAddress(&argv[i][7]);
44  } else if (s.compare(0,6,"nmAdr=") == 0) {
45  args.nmAdr = Forest::forestAdr(&argv[i][6]);
46  } else if (s.compare(0,5,"nmIp=") == 0) {
47  args.nmIp = Np4d::ipAddress(&argv[i][5]);
48  } else if (s.compare(0,6,"ccAdr=") == 0) {
49  args.ccAdr = Forest::forestAdr(&argv[i][6]);
50  } else if (s.compare(0,13,"firstLeafAdr=") == 0) {
51  args.firstLeafAdr = Forest::forestAdr(&argv[i][13]);
52  } else if (s.compare(0,12,"lastLeafAdr=") == 0) {
53  args.lastLeafAdr = Forest::forestAdr(&argv[i][12]);
54  } else if (s.compare(0,6,"ifTbl=") == 0) {
55  args.ifTbl = &argv[i][6];
56  } else if (s.compare(0,7,"lnkTbl=") == 0) {
57  args.lnkTbl = &argv[i][7];
58  } else if (s.compare(0,8,"comtTbl=") == 0) {
59  args.comtTbl = &argv[i][8];
60  } else if (s.compare(0,7,"rteTbl=") == 0) {
61  args.rteTbl = &argv[i][7];
62  } else if (s.compare(0,9,"statSpec=") == 0) {
63  args.statSpec = &argv[i][9];
64  } else if (s.compare(0,8,"finTime=") == 0) {
65  sscanf(&argv[i][8],"%d",&args.finTime);
66  } else {
67  cerr << "unrecognized argument: " << argv[i] << endl;
68  return false;
69  }
70  }
71  if (args.mode.compare("local") == 0 &&
72  (args.myAdr == 0 || args.firstLeafAdr == 0 ||
73  args.lastLeafAdr ==0 || args.lastLeafAdr < args.firstLeafAdr)) {
74  cerr << "processArgs: local configuration requires myAdr, "
75  "firstLeafAdr, lastLeafAdr and that firstLeafAdr "
76  "be no larger than lastLeafAdr\n";
77  return false;
78  } else if (args.mode.compare("remote") == 0 &&
79  (args.bootIp == 0 || args.myAdr == 0 ||
80  args.nmIp == 0 || args.nmAdr == 0)) {
81  cerr << "processArgs: remote configuration requires bootIp, "
82  "myAdr, netMgrIp and netMgrAdr\n";
83  return false;
84  }
85  return true;
86 }
87 
88 
91 int main(int argc, char *argv[]) {
92  RouterInfo args;
93  if (!processArgs(argc, argv, args))
94  fatal("fRouter: error processing command line arguments");
95  bool booting = args.mode.compare("remote") == 0;
96  RouterCore router(booting,args);
97 
98  if (!router.readTables(args))
99  fatal("router: could not read specified config files");
100  if (!booting) {
101  if (!router.setup())
102  fatal("router: inconsistency in config files");
103  }
104  router.run(args.finTime);
105  cout << endl;
106  router.dump(cout); // print final tables
107  cout << endl;
108  return 0;
109 }
110 
115 RouterCore::RouterCore(bool booting1, const RouterInfo& config)
116  : booting(booting1) {
117  nIfaces = 50; nLnks = 1000;
118  nComts = 5000; nRts = 100000;
119  nPkts = 200000; nBufs = 100000; nQus = 10000;
120 
121  myAdr = config.myAdr;
122  bootIp = config.bootIp;
123  nmAdr = config.nmAdr;
124  nmIp = config.nmIp;
125  ccAdr = config.ccAdr;
126  firstLeafAdr = config.firstLeafAdr;
127 
128  ps = new PacketStore(nPkts, nBufs);
129  ift = new IfaceTable(nIfaces);
130  lt = new LinkTable(nLnks);
131  ctt = new ComtreeTable(nComts,10*nComts,lt);
132  rt = new RouteTable(nRts,myAdr,ctt);
133  sm = new StatsModule(1000, nLnks, nQus, ctt);
134  iop = new IoProcessor(nIfaces, ift, lt, ps, sm);
135  qm = new QuManager(nLnks, nPkts, nQus, min(50,5*nPkts/nLnks), ps, sm);
136  pktLog = new PacketLog(20000,500,ps);
137 
138  if (!booting)
139  leafAdr = new UiSetPair((config.lastLeafAdr - firstLeafAdr)+1);
140 
141  seqNum = 1;
142  pending = new map<uint64_t,CpInfo>;
143 }
144 
145 RouterCore::~RouterCore() {
146  delete pktLog; delete qm; delete iop; delete sm;
147  delete rt; delete ctt; delete lt; delete ift; delete ps;
148  if (leafAdr != 0) delete leafAdr;
149 }
150 
157 bool RouterCore::readTables(const RouterInfo& config) {
158  if (config.ifTbl.compare("") != 0) {
159  ifstream fs; fs.open(config.ifTbl.c_str());
160  if (fs.fail() || !ift->read(fs)) {
161  cerr << "RouterCore::init: can't read "
162  << "interface table\n";
163  return false;
164  }
165  fs.close();
166  }
167  if (config.lnkTbl.compare("") != 0) {
168  ifstream fs; fs.open(config.lnkTbl.c_str());
169  if (fs.fail() || !lt->read(fs)) {
170  cerr << "RouterCore::init: can't read "
171  << "link table\n";
172  return false;
173  }
174  fs.close();
175  }
176  if (config.comtTbl.compare("") != 0) {
177  ifstream fs; fs.open(config.comtTbl.c_str());
178  if (fs.fail() || !ctt->read(fs)) {
179  cerr << "RouterCore::init: can't read "
180  << "comtree table\n";
181  return false;
182  }
183  fs.close();
184  }
185  if (config.rteTbl.compare("") != 0) {
186  ifstream fs; fs.open(config.rteTbl.c_str());
187  if (fs.fail() || !rt->read(fs)) {
188  cerr << "RouterCore::init: can't read "
189  << "routing table\n";
190  return false;
191  }
192  fs.close();
193  }
194  if (config.statSpec.compare("") != 0) {
195  ifstream fs; fs.open(config.statSpec.c_str());
196  if (fs.fail() || !sm->read(fs)) {
197  cerr << "RouterCore::init: can't read "
198  << "statistics spec\n";
199  return false;
200  }
201  fs.close();
202  }
203  return true;
204 }
205 
210 bool RouterCore::setup() {
211  dump(cout);
212  if (!setupIfaces()) return false;
213  if (!setupLeafAddresses()) return false;
214  if (!setupQueues()) return false;
215  if (!checkTables()) return false;
216  if (!setAvailRates()) return false;
217  addLocalRoutes();
218 
219  return true;
220 }
221 
226 bool RouterCore::setupIfaces() {
227  for (int iface = ift->firstIface(); iface != 0;
228  iface = ift->nextIface(iface)) {
229  if (!iop->setup(iface)) {
230  cerr << "RouterCore::setupIfaces: could not "
231  "setup interface " << iface << endl;
232  return false;
233  }
234  }
235  return true;
236 }
237 
238 
244 bool RouterCore::setupLeafAddresses() {
245  for (int lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
246  if (booting || lt->getPeerType(lnk) == ROUTER) continue;
247  if (!allocLeafAdr(lt->getPeerAdr(lnk)))
248  return false;
249  }
250  return true;
251 }
252 
259 bool RouterCore::setupQueues() {
260  // Set link rates in QuManager
261  for (int lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
262  qm->setLinkRates(lnk,lt->getBitRate(lnk),lt->getPktRate(lnk));
263  }
264  int ctx;
265  for (ctx = ctt->firstComtIndex(); ctx != 0;
266  ctx = ctt->nextComtIndex(ctx)) {
267  set<int>& links = ctt->getLinks(ctx);
268  set<int>::iterator p;
269  for (p = links.begin(); p != links.end(); p++) {
270  int cLnk = *p; int lnk = ctt->getLink(cLnk);
271  int qid = qm->allocQ(lnk);
272  if (qid == 0) return false;
273  ctt->setLinkQ(cLnk,qid);
274  qm->setQRates(qid,Forest::MINBITRATE,
275  Forest::MINPKTRATE);
276  if (lt->getPeerType(lnk) == ROUTER)
277  qm->setQLimits(qid,100,200000);
278  else
279  qm->setQLimits(qid,50,100000);
280  sm->clearQuStats(qid);
281  }
282  }
283  return true;
284 }
285 
292 bool RouterCore::checkTables() {
293  bool success = true;
294 
295  // verify that the default interface is valid and
296  // that each interface has a non-zero IP address
297  if (!ift->valid(ift->getDefaultIface())) {
298  cerr << "RouterCore::checkTables: specified default iface "
299  << ift->getDefaultIface() << " is invalid\n";
300  success = false;
301  }
302  int iface;
303  for (iface = ift->firstIface(); iface != 0;
304  iface = ift->nextIface(iface)) {
305  if (ift->getIpAdr(iface) == 0) {
306  cerr << "RouterCore::checkTables: interface "
307  << iface << " has zero for IP address\n";
308  success = false;
309  }
310  }
311 
312  // verify that each link is assigned to a valid interface
313  // that the peer Ip address and port are non-zero and consistent,
314  // the the peer type is valid and that the peer address is a valid
315  // unicast forest address
316  int lnk;
317  for (lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
318  iface = lt->getIface(lnk);
319  if (!ift->valid(iface)) {
320  cerr << "RouterCore::checkTables: interface " << iface
321  << " for link " << lnk << " is not valid\n";
322  success = false;
323  }
324  if (lt->getPeerIpAdr(lnk) == 0) {
325  cerr << "RouterCore::checkTables: invalid peer IP "
326  << "for link " << lnk << endl;
327  success = false;
328  }
329  if (!Forest::validUcastAdr(lt->getPeerAdr(lnk))) {
330  cerr << "RouterCore::checkTables: invalid peer address "
331  << "for link " << lnk << endl;
332  success = false;
333  }
334  }
335 
336  // verify that the links in each comtree are valid,
337  // that the router links and core links refer to peer routers,
338  // and that each comtree link is consistent
339  int ctx;
340  for (ctx = ctt->firstComtIndex(); ctx != 0;
341  ctx = ctt->nextComtIndex(ctx)) {
342  int comt = ctt->getComtree(ctx);
343  int plnk = ctt->getPlink(ctx);
344  int pcLnk = ctt->getPCLink(ctx);
345  if (plnk != ctt->getLink(pcLnk)) {
346  cerr << "RouterCore::checkTables: parent link "
347  << plnk << " not consistent with pcLnk\n";
348  success = false;
349  }
350  if (ctt->inCore(ctx) && plnk != 0 && !ctt->isCoreLink(pcLnk)) {
351  cerr << "RouterCore::checkTables: parent link "
352  << plnk << " of core node does not lead to "
353  << "another core node\n";
354  success = false;
355  }
356  set<int>& links = ctt->getLinks(ctx);
357  set<int>::iterator p;
358  for (p = links.begin(); p != links.end(); p++) {
359  int cLnk = *p; int lnk = ctt->getLink(cLnk);
360  if (!lt->valid(lnk)) {
361  cerr << "RouterCore::checkTables: link "
362  << lnk << " in comtree " << comt
363  << " not in link table" << endl;
364  success = false;
365  continue;
366  }
367  fAdr_t dest = ctt->getDest(cLnk);
368  if (dest != 0 && !Forest::validUcastAdr(dest)) {
369  cerr << "RouterCore::checkTables: dest addr "
370  << "for " << lnk << " in comtree " << comt
371  << " is not valid" << endl;
372  success = false;
373  }
374  int qid = ctt->getLinkQ(cLnk);
375  if (qid == 0) {
376  cerr << "RouterCore::checkTables: queue id "
377  << "for " << lnk << " in comtree " << comt
378  << " is zero" << endl;
379  success = false;
380  }
381  }
382  if (!success) break;
383  set<int>& rtrLinks = ctt->getRtrLinks(ctx);
384  for (p = rtrLinks.begin(); p != rtrLinks.end(); p++) {
385  int cLnk = *p; int lnk = ctt->getLink(cLnk);
386  if (!ctt->isLink(ctx,lnk)) {
387  cerr << "RouterCore::checkTables: router link "
388  << lnk << " is not valid in comtree "
389  << comt << endl;
390  success = false;
391  }
392  if (lt->getPeerType(lnk) != ROUTER) {
393  cerr << "RouterCore::checkTables: router link "
394  << lnk << " in comtree " << comt
395  << " connects to non-router peer\n";
396  success = false;
397  }
398  }
399  set<int>& coreLinks = ctt->getCoreLinks(ctx);
400  for (p = coreLinks.begin(); p != coreLinks.end(); p++) {
401  int cLnk = *p; int lnk = ctt->getLink(cLnk);
402  if (!ctt->isRtrLink(ctx,lnk)) {
403  cerr << "RouterCore::checkTables: core link "
404  << lnk << " is not a router link "
405  << comt << endl;
406  success = false;
407  }
408  }
409  }
410  // come back later and add checks for route table
411  return success;
412 }
413 
419 bool RouterCore::setAvailRates() {
420  bool success = true;
421  int iface;
422  for (iface = ift->firstIface(); iface != 0;
423  iface = ift->nextIface(iface)) {
424  if (ift->getMaxBitRate(iface) < Forest::MINBITRATE ||
425  ift->getMaxBitRate(iface) > Forest::MAXBITRATE ||
426  ift->getMaxPktRate(iface) < Forest::MINBITRATE ||
427  ift->getMaxPktRate(iface) > Forest::MAXBITRATE) {
428  cerr << "RouterCore::setAvailRates: interface rates "
429  "outside allowed range\n";
430  success = false;
431  }
432  ift->setAvailBitRate(iface, ift->getMaxBitRate(iface));
433  ift->setAvailPktRate(iface, ift->getMaxPktRate(iface));
434  }
435  if (!success) return false;
436  int lnk;
437  for (lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
438  if (lt->getBitRate(lnk) < Forest::MINBITRATE ||
439  lt->getBitRate(lnk) > Forest::MAXBITRATE ||
440  lt->getPktRate(lnk) < Forest::MINBITRATE ||
441  lt->getPktRate(lnk) > Forest::MAXBITRATE) {
442  cerr << "RouterCore::setAvailRates: link rates "
443  "outside allowed range\n";
444  success = false;
445  }
446  iface = lt->getIface(lnk);
447  if (!ift->addAvailBitRate(iface,-lt->getBitRate(lnk)) ||
448  !ift->addAvailPktRate(iface,-lt->getPktRate(lnk))) {
449  cerr << "RouterCore::setAvailRates: oversubscribing "
450  "interface " << iface << endl;
451  success = false;
452  }
453  lt->setAvailInBitRate(lnk,lt->getBitRate(lnk));
454  lt->setAvailInPktRate(lnk,lt->getPktRate(lnk));
455  lt->setAvailOutBitRate(lnk,lt->getBitRate(lnk));
456  lt->setAvailOutPktRate(lnk,lt->getPktRate(lnk));
457  sm->clearLnkStats(lnk);
458  }
459  if (!success) return false;
460  int ctx;
461  for (ctx = ctt->firstComtIndex(); ctx != 0;
462  ctx = ctt->nextComtIndex(ctx)) {
463  set<int>& comtLinks = ctt->getLinks(ctx);
464  set<int>::iterator p;
465  for (p = comtLinks.begin(); p != comtLinks.end(); p++) {
466  int cLnk = *p; int lnk = ctt->getLink(cLnk);
467  int ibr = ctt->getInBitRate(cLnk);
468  int ipr = ctt->getInPktRate(cLnk);
469  int obr = ctt->getOutBitRate(cLnk);
470  int opr = ctt->getOutPktRate(cLnk);
471  if (!lt->addAvailInBitRate(lnk,-ibr) ||
472  !lt->addAvailInPktRate(lnk,-ipr) ||
473  !lt->addAvailOutBitRate(lnk,-obr) ||
474  !lt->addAvailOutPktRate(lnk,-opr)) {
475  cerr << "RouterCore::setAvailRates: "
476  "oversubscribing link "
477  << lnk << endl;
478  success = false;
479  }
480  }
481  }
482  return success;
483 }
484 
488 void RouterCore::addLocalRoutes() {
489  for (int ctx = ctt->firstComtIndex(); ctx != 0;
490  ctx = ctt->nextComtIndex(ctx)) {
491  int comt = ctt->getComtree(ctx);
492  set<int>& comtLinks = ctt->getLinks(ctx);
493  set<int>::iterator p;
494  for (p = comtLinks.begin(); p != comtLinks.end(); p++) {
495  int cLnk = *p; int lnk = ctt->getLink(cLnk);
496  fAdr_t peerAdr = lt->getPeerAdr(lnk);
497  if (lt->getPeerType(lnk) == ROUTER &&
498  Forest::zipCode(peerAdr)
499  == Forest::zipCode(myAdr))
500  continue;
501  if (rt->getRteIndex(comt,peerAdr) != 0)
502  continue;
503  rt->addEntry(comt,peerAdr,cLnk);
504  }
505  }
506 }
507 
511 void RouterCore::dump(ostream& out) {
512  string s;
513  out << "Interface Table\n\n" << ift->toString(s) << endl;
514  out << "Link Table\n\n" << lt->toString(s) << endl;
515  out << "Comtree Table\n\n" << ctt->toString(s) << endl;
516  out << "Routing Table\n\n" << rt->toString(s) << endl;
517  out << "Statistics\n\n" << sm->toString(s) << endl;
518 }
519 
548 void RouterCore::run(uint64_t finishTime) {
549  #ifdef PROFILING // MAH
550  Timer timer_loop( "RouterCore::run() main loop ");
551  Timer timer_deq( "RouterCore::run() -> QuManager::deq() ");
552  //Timer timer_enq("RouterCore::run() -> QuManager::enq()");
553  //Timer timer_lookup("RouterCore::run() -> UiHashTbl::lookup()");
554  Timer timer_pktCheck("RouterCore::run() -> RouterCore::pktCheck() ");
555  Timer timer_pktLog( "RouterCore::run() -> PacketLog::log() ");
556  Timer timer_forward( "RouterCore::run() -> RouterCore::forward() ");
557  Timer timer_receive( "RouterCore::run() -> IoProcessor::receive() ");
558  Timer timer_send( "RouterCore::run() -> IoProcessor::send() ");
559  #endif
560  now = Misc::getTimeNs();
561  if (booting) {
562  if (!iop->setupBootSock(bootIp,nmIp))
563  fatal("RouterCore:run: could not setup boot socket\n");
564  string s1;
565  cout << "sending boot request to " << Np4d::ip2string(nmIp,s1)
566  << endl;
567  CtlPkt cp(BOOT_REQUEST,REQUEST,0);
568  if (!sendCpReq(cp,nmAdr))
569  fatal("RouterCore::run: could not send boot request\n");
570  }
571  // create packet log to record a sample of packets handled
572 
573  uint64_t statsTime = 0; // time statistics were last processed
574  bool didNothing;
575  int controlCount = 20; // used to limit overhead of control
576  // packet processing
577  queue<int> ctlQ; // queue for control packets
578 
579  now = Misc::getTimeNs();
580  finishTime *= 1000000000; // convert from seconds to ns
581  while (finishTime == 0 || now < finishTime) {
582  didNothing = true;
583 
584  // input processing
585  #ifdef PROFILING // MAH
586  timer_loop.start();
587  timer_receive.start();
588  #endif
589  int p = iop->receive();
590  #ifdef PROFILING // MAH
591  if (p == 0) { timer_receive.cancel(); } // Don't count receive when no packet
592  else { timer_receive.stop(); }
593  #endif
594  if (p != 0) {
595  didNothing = false;
596  PacketHeader& h = ps->getHeader(p);
597  int ptype = h.getPtype();
598  #ifdef PROFILING
599  timer_pktLog.start();
600  pktLog->log(p,h.getInLink(),false,now);
601  timer_pktLog.stop();
602  #else
603  pktLog->log(p,h.getInLink(),false,now);
604  #endif
605  int ctx = ctt->getComtIndex(h.getComtree());
606  #ifdef PROFILING // MAH
607  timer_pktCheck.start();
608  bool pkt_check = pktCheck(p,ctx);
609  timer_pktCheck.stop();
610  if (!pkt_check) {
611  #else
612  if (!pktCheck(p,ctx)) {
613  #endif
614  ps->free(p);
615  } else if (booting) {
616  handleCtlPkt(p);
617  } else if (ptype == CLIENT_DATA) {
618  #ifdef PROFILING // MAH
619  timer_forward.start();
620  #endif
621  forward(p,ctx);
622  #ifdef PROFILING // MAH
623  timer_forward.stop();
624  #endif
625  } else if (ptype == SUB_UNSUB) {
626  subUnsub(p,ctx);
627  } else if (ptype == RTE_REPLY) {
628  handleRteReply(p,ctx);
629  } else if (ptype == CONNECT || ptype == DISCONNECT) {
630  handleConnDisc(p);
631  } else if (h.getDstAdr() != myAdr) {
632  #ifdef PROFILING // MAH
633  timer_forward.start();
634  #endif
635  forward(p,ctx);
636  #ifdef PROFILING // MAH
637  timer_forward.stop();
638  #endif
639  } else {
640  ctlQ.push(p);
641  }
642  }
643 
644  #ifdef PROFILING // MAH
645  timer_deq.start();
646  #endif
647  // output processing
648  int lnk;
649  while ((p = qm->deq(lnk, now)) != 0) {
650  didNothing = false;
651  #ifdef PROFILING
652  timer_deq.stop();
653  timer_pktLog.start();
654  #endif
655  pktLog->log(p,lnk,true,now);
656  #ifdef PROFILING
657  timer_pktLog.stop();
658  timer_send.start();
659  #endif
660  iop->send(p,lnk);
661  #ifdef PROFILING
662  timer_send.stop();
663  #endif
664  }
665  #ifdef PROFILING
666  timer_deq.cancel();
667  #endif
668 
669  // control packet processing
670  if (!ctlQ.empty() && (didNothing || --controlCount <= 0)) {
671  handleCtlPkt(ctlQ.front());
672  ctlQ.pop();
673  controlCount = 20; // do one control packet for
674  // every 20 iterations when busy
675  }
676 
677  // every 300 ms, update statistics and check for un-acked
678  // control packets
679  if (now - statsTime > 300000000) {
680  sm->record(now);
681  statsTime = now;
682  resendCpReq();
683  didNothing = false;
684  }
685 
686  // if did nothing on that pass, sleep for a millisecond.
687  if (didNothing) { usleep(1000); }
688 
689  // update current time
690  now = Misc::getTimeNs();
691  #ifdef PROFILING // MAH
692  timer_loop.stop();
693  #endif
694  }
695 
696  // write out recorded events
697  pktLog->write(cout);
698  cout << endl;
699  cout << sm->iPktCnt(0) << " packets received, "
700  << sm->oPktCnt(0) << " packets sent\n";
701  cout << sm->iPktCnt(-1) << " from routers, "
702  << sm->oPktCnt(-1) << " to routers\n";
703  cout << sm->iPktCnt(-2) << " from clients, "
704  << sm->oPktCnt(-2) << " to clients\n";
705  #ifdef PROFILING // MAH
706  cout << timer_loop << endl;
707  cout << timer_deq << endl;
708  cout << timer_pktCheck << endl;
709  cout << timer_forward << endl;
710  cout << timer_receive << endl;
711  cout << timer_send << endl;
712  #endif
713 }
714 
720 bool RouterCore::pktCheck(int p, int ctx) {
721  PacketHeader& h = ps->getHeader(p);
722  // check version and length
723  if (h.getVersion() != Forest::FOREST_VERSION) {
724  return false;
725  }
726 
727  if (h.getLength() != h.getIoBytes() || h.getLength()<Forest::HDR_LENG) {
728  return false;
729  }
730 
731  if (booting) {
732  return h.getSrcAdr() == nmAdr && h.getDstAdr() == myAdr &&
733  h.getPtype() == NET_SIG &&
734  h.getComtree() == Forest::NET_SIG_COMT;
735  }
736 
737  if (!ctt->validComtIndex(ctx)) {
738  return false;
739  }
740  fAdr_t adr = h.getDstAdr();
741  if (!Forest::validUcastAdr(adr) && !Forest::mcastAdr(adr)) {
742  return false;
743  }
744 
745  int inLink = h.getInLink();
746  if (inLink == 0) return false;
747  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),inLink);
748  if (cLnk == 0) {
749  return false;
750  }
751 
752  // extra checks for packets from untrusted peers
753  if (lt->getPeerType(inLink) < TRUSTED) {
754  // check for spoofed source address
755  if (lt->getPeerAdr(inLink) != h.getSrcAdr()) return false;
756  // and that destination restrictions are respected
757  fAdr_t dest = ctt->getDest(cLnk);
758  if (dest!=0 && h.getDstAdr() != dest && h.getDstAdr() != myAdr)
759  return false;
760  // verify that type is valid
761  ptyp_t ptype = h.getPtype();
762  if (ptype != CLIENT_DATA &&
763  ptype != CONNECT && ptype != DISCONNECT &&
764  ptype != SUB_UNSUB && ptype != CLIENT_SIG)
765  return false;
766  int comt = ctt->getComtree(ctx);
767  if ((ptype == CONNECT || ptype == DISCONNECT) &&
768  comt != (int) Forest::CLIENT_CON_COMT)
769  return false;
770  if (ptype == CLIENT_SIG &&
771  comt != (int) Forest::CLIENT_SIG_COMT)
772  return false;
773  }
774  return true;
775 }
776 
786 void RouterCore::forward(int p, int ctx) {
787  PacketHeader& h = ps->getHeader(p);
788  int rtx = rt->getRteIndex(h.getComtree(),h.getDstAdr());
789  if (rtx != 0) { // valid route case
790  // reply to route request
791  if ((h.getFlags() & Forest::RTE_REQ)) {
792  sendRteReply(p,ctx);
793  h.setFlags(h.getFlags() & (~Forest::RTE_REQ));
794  ps->pack(p);
795  ps->hdrErrUpdate(p);
796  }
797  if (Forest::validUcastAdr(h.getDstAdr())) {
798  int rcLnk = rt->getLink(rtx);
799  int lnk = ctt->getLink(rcLnk);
800  int qid = ctt->getLinkQ(rcLnk);
801  if (lnk == h.getInLink() || !qm->enq(p,qid,now)) {
802  ps->free(p);
803  }
804  return;
805  }
806  // multicast data packet
807  multiSend(p,ctx,rtx);
808  return;
809  }
810  // no valid route
811 // think about suppressing flooding, if address is in range for this router
812  if (Forest::validUcastAdr(h.getDstAdr())) {
813  // send to neighboring routers in comtree
814  h.setFlags(Forest::RTE_REQ);
815  ps->pack(p); ps->hdrErrUpdate(p);
816  }
817  multiSend(p,ctx,rtx);
818  return;
819 }
830 void RouterCore::multiSend(int p, int ctx, int rtx) {
831  int qvec[nLnks]; int n = 0;
832  PacketHeader& h = ps->getHeader(p);
833 
834  int inLink = h.getInLink();
835  if (Forest::validUcastAdr(h.getDstAdr())) {
836  // flooding a unicast packet to neighboring routers
837  int myZip = Forest::zipCode(myAdr);
838  int pZip = Forest::zipCode(h.getDstAdr());
839  set<int>& rtrLinks = ctt->getRtrLinks(ctx);
840  set<int>::iterator lp;
841  for (lp = rtrLinks.begin(); lp != rtrLinks.end(); lp++) {
842  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
843  int peerZip = Forest::zipCode(lt->getPeerAdr(lnk));
844  if (pZip == myZip && peerZip != myZip) continue;
845  if (lnk == inLink) continue;
846  qvec[n++] = ctt->getLinkQ(rcLnk);
847  }
848  } else {
849  // forwarding a multicast packet
850  // first identify neighboring core routers to get copies
851  int pLink = ctt->getPlink(ctx);
852  set<int>& coreLinks = ctt->getCoreLinks(ctx);
853  set<int>::iterator lp;
854  for (lp = coreLinks.begin(); lp != coreLinks.end(); lp++) {
855  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
856  if (lnk == inLink || lnk == pLink) continue;
857  qvec[n++] = ctt->getLinkQ(rcLnk);
858  }
859  // now copy for parent
860  if (pLink != 0 && pLink != inLink) {
861  qvec[n++] = ctt->getLinkQ(ctt->getPCLink(ctx));
862  }
863  // now, copies for subscribers if any
864  if (rtx != 0) {
865  set<int>& subLinks = rt->getSubLinks(rtx);
866  for (lp = subLinks.begin(); lp !=subLinks.end(); lp++) {
867  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
868  if (lnk == inLink) continue;
869  qvec[n++] = ctt->getLinkQ(rcLnk);
870  }
871  }
872  }
873 
874  if (n == 0) { ps->free(p); return; }
875 
876  // make copies and queue them
877  int p1 = p;
878  for (int i = 0; i < n-1; i++) { // process first n-1 copies
879  if (qm->enq(p1,qvec[i],now)) {
880  p1 = ps->clone(p);
881  }
882  }
883  // process last copy
884  if (!qm->enq(p1,qvec[n-1],now)) {
885  ps->free(p1);
886  }
887 }
888 
895 void RouterCore::sendRteReply(int p, int ctx) {
896  PacketHeader& h = ps->getHeader(p);
897 
898  int p1 = ps->alloc();
899  PacketHeader& h1 = ps->getHeader(p1);
900  h1.setLength(Forest::HDR_LENG + 8);
901  h1.setPtype(RTE_REPLY);
902  h1.setFlags(0);
903  h1.setComtree(h.getComtree());
904  h1.setSrcAdr(myAdr);
905  h1.setDstAdr(h.getSrcAdr());
906 
907  ps->pack(p1);
908  ps->getPayload(p1)[0] = htonl(h.getDstAdr());
909  ps->hdrErrUpdate(p1); ps->payErrUpdate(p1);
910 
911  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),h.getInLink());
912  qm->enq(p1,ctt->getLinkQ(cLnk),now);
913 }
914 
923 void RouterCore::handleRteReply(int p, int ctx) {
924  PacketHeader& h = ps->getHeader(p);
925  int rtx = rt->getRteIndex(h.getComtree(), h.getDstAdr());
926  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),h.getInLink());
927  if ((h.getFlags() & Forest::RTE_REQ) && rtx != 0)
928  sendRteReply(p,ctx);
929  int adr = ntohl(ps->getPayload(p)[0]);
930  if (Forest::validUcastAdr(adr) &&
931  rt->getRteIndex(h.getComtree(),adr) == 0) {
932  rt->addEntry(h.getComtree(),adr,cLnk);
933  }
934  if (rtx == 0) {
935  // send to neighboring routers in comtree
936  h.setFlags(Forest::RTE_REQ);
937  ps->pack(p); ps->hdrErrUpdate(p);
938  multiSend(p,ctx,rtx);
939  return;
940  }
941  int dcLnk = rt->getLink(rtx); int dLnk = ctt->getLink(dcLnk);
942  if (lt->getPeerType(dLnk) != ROUTER || !qm->enq(p,dLnk,now))
943  ps->free(p);
944  return;
945 }
946 
954 void RouterCore::subUnsub(int p, int ctx) {
955  PacketHeader& h = ps->getHeader(p);
956  uint32_t *pp = ps->getPayload(p);
957 
958  // add/remove branches from routes
959  // if non-core node, also propagate requests upward as
960  // appropriate
961  int comt = ctt->getComtree(ctx);
962  int inLink = h.getInLink();
963  int cLnk = ctt->getComtLink(comt,inLink);
964  // ignore subscriptions from the parent or core neighbors
965  if (inLink == ctt->getPlink(ctx) || ctt->isCoreLink(cLnk)) {
966  ps->free(p); return;
967  }
968  bool propagate = false;
969  int rtx; fAdr_t addr;
970 
971  // add subscriptions
972  int addcnt = ntohl(pp[0]);
973  if (addcnt < 0 || addcnt > 350 ||
974  Forest::OVERHEAD + (addcnt + 2)*4 > h.getLength()) {
975  ps->free(p); return;
976  }
977  for (int i = 1; i <= addcnt; i++) {
978  addr = ntohl(pp[i]);
979  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
980  rtx = rt->getRteIndex(comt,addr);
981  if (rtx == 0) {
982  rtx = rt->addEntry(comt,addr,cLnk);
983  propagate = true;
984  } else if (!rt->isLink(rtx,cLnk)) {
985  rt->addLink(rtx,cLnk);
986  pp[i] = 0; // so, parent will ignore
987  }
988  }
989  // remove subscriptions
990  int dropcnt = ntohl(pp[addcnt+1]);
991  if (dropcnt < 0 || addcnt + dropcnt > 350 ||
992  Forest::OVERHEAD + (addcnt + dropcnt + 2)*4 > h.getLength()) {
993  ps->free(p); return;
994  }
995  for (int i = addcnt + 2; i <= addcnt + dropcnt + 1; i++) {
996  addr = ntohl(pp[i]);
997  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
998  rtx = rt->getRteIndex(comt,addr);
999  if (rtx == 0) continue;
1000  rt->removeLink(rtx,cLnk);
1001  if (rt->noLinks(rtx)) {
1002  rt->removeEntry(rtx);
1003  propagate = true;
1004  } else {
1005  pp[i] = 0;
1006  }
1007  }
1008  // propagate subscription packet to parent if not a core node
1009  if (propagate && !ctt->inCore(ctx) && ctt->getPlink(ctx) != 0) {
1010  ps->payErrUpdate(p);
1011  int qid = ctt->getLinkQ(ctt->getPCLink(ctx));
1012  if (qm->enq(p,qid,now)) {
1013  return;
1014  }
1015  }
1016  ps->free(p); return;
1017 }
1018 
1022 void RouterCore::handleConnDisc(int p) {
1023  PacketHeader& h = ps->getHeader(p);
1024  int inLnk = h.getInLink();
1025 
1026  if (!validLeafAdr(h.getSrcAdr())) {
1027  ps->free(p); return;
1028  }
1029  if (h.getPtype() == CONNECT) {
1030  if (lt->getPeerPort(inLnk) == 0) {
1031  lt->setPeerPort(inLnk,h.getTunSrcPort());
1032  }
1033 /*
1034  if (lt->getPeerPort(inLnk) != h.getTunSrcPort()) {
1035  if (lt->getPeerPort(inLnk) != 0) {
1036  string s;
1037  cerr << "modifying peer port for host with ip "
1038  << Np4d::ip2string(h.getTunSrcIp(),s)
1039  << endl;
1040  }
1041  lt->setPeerPort(inLnk,h.getTunSrcPort());
1042  }
1043 */
1044  if (nmAdr != 0 && lt->getPeerType(inLnk) == CLIENT) {
1045  CtlPkt cp(CLIENT_CONNECT,REQUEST,0);
1046  cp.setAttr(CLIENT_ADR,h.getSrcAdr());
1047  cp.setAttr(RTR_ADR,myAdr);
1048  sendCpReq(cp,nmAdr);
1049  }
1050  } else if (h.getPtype() == DISCONNECT) {
1051  if (lt->getPeerPort(inLnk) == h.getTunSrcPort()) {
1052  dropLink(inLnk);
1053  }
1054  if (nmAdr != 0 && lt->getPeerType(inLnk) == CLIENT) {
1055  CtlPkt cp(CLIENT_DISCONNECT,REQUEST,0);
1056  cp.setAttr(CLIENT_ADR,h.getSrcAdr());
1057  cp.setAttr(RTR_ADR,myAdr);
1058  sendCpReq(cp,nmAdr);
1059  }
1060  }
1061  ps->free(p); return;
1062 }
1063 
1075 void RouterCore::handleCtlPkt(int p) {
1076  PacketHeader& h = ps->getHeader(p);
1077  CtlPkt cp;
1078 
1079  int len = h.getLength() - (Forest::HDR_LENG + 4);
1080  if (!cp.unpack(ps->getPayload(p), len)) {
1081  string s;
1082  cerr << "RouterCore::handleCtlPkt: misformatted control "
1083  " packet\n" << h.toString(ps->getBuffer(p),s);
1084  cp.setRrType(NEG_REPLY);
1085  cp.setErrMsg("misformatted control packet");
1086  returnToSender(p,cp.pack(ps->getPayload(p)));
1087  return;
1088  }
1089  if (h.getPtype() != NET_SIG || h.getComtree() != Forest::NET_SIG_COMT) {
1090  ps->free(p); return;
1091  }
1092  if (cp.getRrType() != REQUEST) {
1093  handleCpReply(p,cp); return;
1094  }
1095 
1096  // Prepare positive reply packet for use where appropriate
1097  CtlPkt reply;
1098  reply.setCpType(cp.getCpType());
1099  reply.setRrType(POS_REPLY);
1100  reply.setSeqNum(cp.getSeqNum());
1101  switch (cp.getCpType()) {
1102 
1103  // configuring logical interfaces
1104  case ADD_IFACE: addIface(p,cp,reply); break;
1105  case DROP_IFACE: dropIface(p,cp,reply); break;
1106  case GET_IFACE: getIface(p,cp,reply); break;
1107  case MOD_IFACE: modIface(p,cp,reply); break;
1108 
1109  // configuring links
1110  case ADD_LINK: addLink(p,cp,reply); break;
1111  case DROP_LINK: dropLink(p,cp,reply); break;
1112  case GET_LINK: getLink(p,cp,reply); break;
1113  case MOD_LINK: modLink(p,cp,reply); break;
1114 
1115  // configuring comtrees
1116  case ADD_COMTREE: addComtree(p,cp,reply); break;
1117  case DROP_COMTREE: dropComtree(p,cp,reply); break;
1118  case GET_COMTREE: getComtree(p,cp,reply); break;
1119  case MOD_COMTREE: modComtree(p,cp,reply); break;
1120  case ADD_COMTREE_LINK: addComtreeLink(p,cp,reply); break;
1121  case DROP_COMTREE_LINK: dropComtreeLink(p,cp,reply); break;
1122  case GET_COMTREE_LINK: getComtreeLink(p,cp,reply); break;
1123  case MOD_COMTREE_LINK: modComtreeLink(p,cp,reply); break;
1124 
1125  // configuring routes
1126  case ADD_ROUTE: addRoute(p,cp,reply); break;
1127  case DROP_ROUTE: dropRoute(p,cp,reply); break;
1128  case GET_ROUTE: getRoute(p,cp,reply); break;
1129  case MOD_ROUTE: modRoute(p,cp,reply); break;
1130 
1131  // finishing up boot phase
1132  case BOOT_COMPLETE: bootComplete(p,cp,reply); break;
1133 
1134  // aborting boot process
1135  case BOOT_ABORT: bootAbort(p,cp,reply); break;
1136 
1137  default:
1138  cerr << "unrecognized control packet type " << cp.getCpType()
1139  << endl;
1140  reply.setErrMsg("invalid control packet for router");
1141  reply.setRrType(NEG_REPLY);
1142  break;
1143  }
1144 
1145  returnToSender(p,reply.pack(ps->getPayload(p)));
1146 
1147  if (reply.getCpType() == BOOT_COMPLETE) {
1148  iop->closeBootSock();
1149  booting = false;
1150  }
1151 
1152  return;
1153 }
1154 
1166 bool RouterCore::addIface(int p, CtlPkt& cp, CtlPkt& reply) {
1167  if (!cp.isSet(IFACE_NUM) || !cp.isSet(LOCAL_IP) ||
1168  !cp.isSet(MAX_BIT_RATE) || !cp.isSet(MAX_PKT_RATE)) {
1169  reply.setErrMsg("add iface: missing required attribute");
1170  reply.setRrType(NEG_REPLY);
1171  return false;
1172  }
1173  int iface = cp.getAttr(IFACE_NUM);
1174  ipa_t localIp = cp.getAttr(LOCAL_IP);
1175  int bitRate = cp.getAttr(MAX_BIT_RATE);
1176  int pktRate = cp.getAttr(MAX_PKT_RATE);
1177  bitRate = max(bitRate, Forest::MINBITRATE);
1178  pktRate = max(pktRate, Forest::MINPKTRATE);
1179  bitRate = min(bitRate, Forest::MAXBITRATE);
1180  pktRate = min(pktRate, Forest::MAXPKTRATE);
1181  if (ift->valid(iface)) {
1182  if (localIp != ift->getIpAdr(iface) ||
1183  bitRate != ift->getMaxBitRate(iface) ||
1184  pktRate != ift->getMaxPktRate(iface)) {
1185  reply.setErrMsg("add iface: requested interface "
1186  "conflicts with existing interface");
1187  reply.setRrType(NEG_REPLY);
1188  return false;
1189  }
1190  } else if (!ift->addEntry(iface, localIp, bitRate, pktRate)) {
1191  reply.setErrMsg("add iface: cannot add interface");
1192  reply.setRrType(NEG_REPLY);
1193  return false;
1194  }
1195  return true;
1196 }
1197 
1198 bool RouterCore::dropIface(int p, CtlPkt& cp, CtlPkt& reply) {
1199  if (!cp.isSet(IFACE_NUM)) {
1200  reply.setErrMsg("drop iface: missing required "
1201  "attribute");
1202  reply.setRrType(NEG_REPLY);
1203  return false;
1204  }
1205  int iface = cp.getAttr(IFACE_NUM);
1206  ift->removeEntry(iface);
1207  return true;
1208 }
1209 
1210 bool RouterCore::getIface(int p, CtlPkt& cp, CtlPkt& reply) {
1211  if (!cp.isSet(IFACE_NUM)) {
1212  reply.setErrMsg("get iface: missing required "
1213  "attribute");
1214  reply.setRrType(NEG_REPLY);
1215  return false;
1216  }
1217  int iface = cp.getAttr(IFACE_NUM);
1218  if (ift->valid(iface)) {
1219  reply.setAttr(IFACE_NUM,iface);
1220  reply.setAttr(LOCAL_IP,ift->getIpAdr(iface));
1221  reply.setAttr(AVAIL_BIT_RATE,ift->getAvailBitRate(iface));
1222  reply.setAttr(AVAIL_PKT_RATE,ift->getAvailPktRate(iface));
1223  reply.setAttr(MAX_BIT_RATE,ift->getMaxBitRate(iface));
1224  reply.setAttr(MAX_PKT_RATE,ift->getMaxPktRate(iface));
1225  return true;
1226  }
1227  reply.setErrMsg("get iface: invalid interface");
1228  reply.setRrType(NEG_REPLY);
1229  return false;
1230 }
1231 
1232 bool RouterCore::modIface(int p, CtlPkt& cp, CtlPkt& reply) {
1233  if (!cp.isSet(IFACE_NUM)) {
1234  reply.setErrMsg("add iface: missing required "
1235  "attribute");
1236  reply.setRrType(NEG_REPLY);
1237  return false;
1238  }
1239  int iface = cp.getAttr(IFACE_NUM);
1240  if (ift->valid(iface)) {
1241  if (cp.isSet(MAX_BIT_RATE))
1242  ift->setMaxBitRate(iface,cp.getAttr(MAX_BIT_RATE));
1243  if (cp.isSet(MAX_PKT_RATE))
1244  ift->setMaxPktRate(iface,cp.getAttr(MAX_PKT_RATE));
1245  return true;
1246  }
1247  reply.setErrMsg("mod iface: invalid interface");
1248  reply.setRrType(NEG_REPLY);
1249  return false;
1250 }
1251 
1252 bool RouterCore::addLink(int p, CtlPkt& cp, CtlPkt& reply) {
1253  if (!cp.isSet(PEER_IP) || !cp.isSet(PEER_TYPE)) {
1254  reply.setErrMsg("add link: missing required attribute");
1255  reply.setRrType(NEG_REPLY);
1256  return false;
1257  }
1258  ntyp_t peerType = (ntyp_t) cp.getAttr(PEER_TYPE);
1259  if (peerType == ROUTER && !cp.isSet(PEER_ADR)) {
1260  reply.setErrMsg("add link: adding link to router, but no peer "
1261  "address supplied");
1262  reply.setRrType(NEG_REPLY);
1263  return false;
1264  }
1265  ipa_t pipa = cp.getAttr(PEER_IP);
1266  int lnk = (cp.isSet(LINK_NUM) ? cp.getAttr(LINK_NUM) : 0);
1267  int iface = (cp.isSet(IFACE_NUM) ? cp.getAttr(IFACE_NUM) :
1268  ift->getDefaultIface());
1269  ipp_t pipp = (cp.isSet(PEER_PORT) ? cp.getAttr(PEER_PORT) :
1270  (peerType == ROUTER ? Forest::ROUTER_PORT : 0));
1271  fAdr_t padr = (cp.isSet(PEER_ADR) ? cp.getAttr(PEER_ADR): 0);
1272  int xlnk = lt->lookup(pipa,pipp);
1273  if (xlnk != 0) { // this link already exists
1274  if ((lnk != 0 && lnk != xlnk) ||
1275  (peerType != lt->getPeerType(xlnk)) ||
1276  (cp.isSet(IFACE_NUM) &&
1277  cp.getAttr(IFACE_NUM) != lt->getIface(xlnk)) ||
1278  (padr != 0 && padr != lt->getPeerAdr(xlnk))) {
1279  reply.setErrMsg("add link: new link conflicts "
1280  "with existing link");
1281  reply.setRrType(NEG_REPLY);
1282  return false;
1283  }
1284  lnk = xlnk; padr = lt->getPeerAdr(xlnk);
1285  } else { // adding a new link
1286  // first ensure that the interface has enough
1287  // capacity to support a new link
1288  int br = Forest::MINBITRATE;
1289  int pr = Forest::MINPKTRATE;
1290  if (!ift->addAvailBitRate(iface,-br)) {
1291  reply.setErrMsg("add link: requested link "
1292  "exceeds interface capacity");
1293  reply.setRrType(NEG_REPLY);
1294  return false;
1295  }
1296  if (!ift->addAvailPktRate(iface,-pr)) {
1297  reply.setErrMsg("add link: requested link "
1298  "exceeds interface capacity");
1299  reply.setRrType(NEG_REPLY);
1300  return false;
1301  }
1302  if ((peerType == ROUTER && pipp != Forest::ROUTER_PORT) ||
1303  (peerType != ROUTER && pipp == Forest::ROUTER_PORT) ||
1304  (lnk = lt->addEntry(lnk,pipa,pipp)) == 0) {
1305  ift->addAvailBitRate(iface,br);
1306  ift->addAvailPktRate(iface,pr);
1307  reply.setErrMsg("add link: cannot add "
1308  "requested link");
1309  reply.setRrType(NEG_REPLY);
1310  return false;
1311  }
1312  // note: when lt->addEntry succeeds, link rates are
1313  // initializied to Forest minimum rates
1314  if (peerType != ROUTER && padr != 0 && !allocLeafAdr(padr)) {
1315  ift->addAvailBitRate(iface,br);
1316  ift->addAvailPktRate(iface,pr);
1317  lt->removeEntry(lnk);
1318  reply.setErrMsg("add link: specified peer "
1319  "address is in use");
1320  reply.setRrType(NEG_REPLY);
1321  return false;
1322  }
1323  if (padr == 0) padr = allocLeafAdr();
1324  if (padr == 0) {
1325  ift->addAvailBitRate(iface,br);
1326  ift->addAvailPktRate(iface,pr);
1327  lt->removeEntry(lnk);
1328  reply.setErrMsg("add link: no available "
1329  "peer addresses");
1330  reply.setRrType(NEG_REPLY);
1331  return false;
1332  }
1333  lt->setIface(lnk,iface);
1334  lt->setPeerType(lnk,peerType);
1335  lt->setPeerAdr(lnk,padr);
1336  sm->clearLnkStats(lnk);
1337  }
1338  reply.setAttr(LINK_NUM,lnk);
1339  reply.setAttr(PEER_ADR,padr);
1340  reply.setAttr(RTR_IP,ift->getIpAdr(iface));
1341  return true;
1342 }
1343 
1344 bool RouterCore::dropLink(int p, CtlPkt& cp, CtlPkt& reply) {
1345  if (!cp.isSet(LINK_NUM)) {
1346  reply.setErrMsg("drop link: missing required "
1347  "attribute");
1348  reply.setRrType(NEG_REPLY);
1349  return false;
1350  }
1351  dropLink(cp.getAttr(LINK_NUM));
1352  return true;
1353 }
1354 
1355 void RouterCore::dropLink(int lnk) {
1356  set<int>& comtSet = lt->getComtSet(lnk);
1357  set<int>::iterator cp;
1358  int *comtVec = new int[comtSet.size()]; int i = 0;
1359  for (cp = comtSet.begin(); cp != comtSet.end(); cp++) {
1360  comtVec[i++] = *cp;
1361  }
1362  while (--i >= 0) {
1363  int ctx = comtVec[i];
1364  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),lnk);
1365  dropComtreeLink(ctx,lnk,cLnk);
1366  }
1367  int iface = lt->getIface(lnk);
1368  ift->addAvailBitRate(iface,lt->getBitRate(lnk));
1369  ift->addAvailPktRate(iface,lt->getPktRate(lnk));
1370  lt->removeEntry(lnk);
1371  freeLeafAdr(lt->getPeerAdr(lnk));
1372 }
1373 
1374 bool RouterCore::getLink(int p, CtlPkt& cp, CtlPkt& reply) {
1375  if (!cp.isSet(LINK_NUM)) {
1376  reply.setErrMsg("get link: missing required attribute");
1377  reply.setRrType(NEG_REPLY);
1378  return false;
1379  }
1380  int link = cp.getAttr(LINK_NUM);
1381  if (lt->valid(link)) {
1382  reply.setAttr(LINK_NUM, link);
1383  reply.setAttr(IFACE_NUM, lt->getIface(link));
1384  reply.setAttr(PEER_IP, lt->getPeerIpAdr(link));
1385  reply.setAttr(PEER_TYPE, lt->getPeerType(link));
1386  reply.setAttr(PEER_PORT, lt->getPeerPort(link));
1387  reply.setAttr(PEER_ADR, lt->getPeerAdr(link));
1388  reply.setAttr(AVAIL_BIT_RATE_IN,
1389  lt->getAvailInBitRate(link));
1390  reply.setAttr(AVAIL_PKT_RATE_IN,
1391  lt->getAvailInPktRate(link));
1392  reply.setAttr(AVAIL_BIT_RATE_OUT,
1393  lt->getAvailOutBitRate(link));
1394  reply.setAttr(AVAIL_PKT_RATE_OUT,
1395  lt->getAvailOutPktRate(link));
1396  reply.setAttr(BIT_RATE, lt->getBitRate(link));
1397  reply.setAttr(PKT_RATE, lt->getPktRate(link));
1398  return true;
1399  }
1400  reply.setErrMsg("get link: invalid link number");
1401  reply.setRrType(NEG_REPLY);
1402  return false;
1403 }
1404 
1405 bool RouterCore::modLink(int p, CtlPkt& cp, CtlPkt& reply) {
1406  if (!cp.isSet(LINK_NUM)) {
1407  reply.setErrMsg("modify link: missing required "
1408  "attribute");
1409  reply.setRrType(NEG_REPLY);
1410  return false;
1411  }
1412  int link = cp.getAttr(LINK_NUM);
1413  if (lt->valid(link)) {
1414  reply.setAttr(LINK_NUM,link);
1415  int iface = lt->getIface(link);
1416  int br, dbr; br = dbr = 0;
1417  if (cp.isSet(BIT_RATE)) {
1418  br = cp.getAttr(BIT_RATE);
1419  dbr = br - lt->getBitRate(link);
1420  if (!ift->addAvailBitRate(iface,-dbr)) {
1421  reply.setErrMsg("mod link: request "
1422  "exceeds interface capacity");
1423  reply.setRrType(NEG_REPLY);
1424  return false;
1425  }
1426  lt->setBitRate(link, br);
1427  lt->addAvailInBitRate(link, dbr);
1428  lt->addAvailOutBitRate(link, dbr);
1429  qm->setLinkRates(link,br,lt->getPktRate(link));
1430  }
1431  if (cp.isSet(PKT_RATE)) {
1432  int pr = cp.getAttr(PKT_RATE);
1433  int dpr = pr - lt->getPktRate(link);
1434  if (!ift->addAvailPktRate(iface,-dpr)) {
1435  if (cp.isSet(BIT_RATE)) { //undo earlier changes
1436  ift->addAvailBitRate(iface,dbr);
1437  lt->setBitRate(link,br-dbr);
1438  lt->addAvailInBitRate(link, -dbr);
1439  lt->addAvailOutBitRate(link, -dbr);
1440  qm->setLinkRates(link,br-dbr,
1441  lt->getPktRate(link));
1442  }
1443  reply.setErrMsg("mod link: request "
1444  "exceeds interface capacity");
1445  reply.setRrType(NEG_REPLY);
1446  return false;
1447  }
1448  lt->setPktRate(link, pr);
1449  lt->addAvailInPktRate(link, dpr);
1450  lt->addAvailOutPktRate(link, dpr);
1451  qm->setLinkRates(link,lt->getBitRate(link),pr);
1452  }
1453  return true;
1454  }
1455  reply.setErrMsg("get link: invalid link number");
1456  reply.setRrType(NEG_REPLY);
1457  return false;
1458 }
1459 
1460 bool RouterCore::addComtree(int p, CtlPkt& cp, CtlPkt& reply) {
1461  if (!cp.isSet(COMTREE_NUM)) {
1462  reply.setErrMsg("add comtree: missing required "
1463  "attribute");
1464  reply.setRrType(NEG_REPLY);
1465  return false;
1466  }
1467  int comt = cp.getAttr(COMTREE_NUM);
1468  if(ctt->validComtree(comt) || ctt->addEntry(comt) != 0)
1469  return true;
1470  reply.setErrMsg("add comtree: cannot add comtree");
1471  reply.setRrType(NEG_REPLY);
1472  return false;
1473 }
1474 
1475 bool RouterCore::dropComtree(int p, CtlPkt& cp, CtlPkt& reply) {
1476  if (!cp.isSet(COMTREE_NUM)) {
1477  reply.setErrMsg("drop comtree: missing required "
1478  "attribute");
1479  reply.setRrType(NEG_REPLY);
1480  return false;
1481  }
1482  int comt = cp.getAttr(COMTREE_NUM);
1483  int ctx = ctt->getComtIndex(comt);
1484  if (!ctt->validComtIndex(ctx))
1485  return true; // so dropComtree op is idempotent
1486 
1487  // remove all routes involving this comtree
1488  // also degisters each route in the comtree table
1489  rt->purgeRoutes(comt);
1490 
1491  // remove all the comtree links
1492  // first, copy out the comtree links, then remove them
1493  // two step process is needed because dropComtreeLink modifies linkSet
1494  set<int>& linkSet = ctt->getLinks(ctx);
1495  set<int>::iterator pp;
1496  int *clnks = new int[linkSet.size()]; int i = 0;
1497  for (pp = linkSet.begin(); pp != linkSet.end(); pp++) clnks[i++] = *pp;
1498  while (--i >= 0) {
1499  dropComtreeLink(ctx,ctt->getLink(clnks[i]),clnks[i]);
1500  }
1501  delete [] clnks;
1502 
1503  ctt->removeEntry(ctx); // and finally drop entry in comtree table
1504  return true;
1505 }
1506 
1507 bool RouterCore::getComtree(int p, CtlPkt& cp, CtlPkt& reply) {
1508  if (!cp.isSet(COMTREE_NUM)) {
1509  reply.setErrMsg("get comtree: missing required "
1510  "attribute");
1511  reply.setRrType(NEG_REPLY);
1512  return false;
1513  }
1514  comt_t comt = cp.getAttr(COMTREE_NUM);
1515  int ctx = ctt->getComtIndex(comt);
1516  if (ctx == 0) {
1517  reply.setErrMsg("get comtree: invalid comtree");
1518  reply.setRrType(NEG_REPLY);
1519  return false;
1520  }
1521  reply.setAttr(COMTREE_NUM,comt);
1522  reply.setAttr(CORE_FLAG,ctt->inCore(ctx));
1523  reply.setAttr(PARENT_LINK,ctt->getPlink(ctx));
1524  reply.setAttr(LINK_COUNT,ctt->getLinkCount(ctx));
1525  return true;
1526 }
1527 
1528 bool RouterCore::modComtree(int p, CtlPkt& cp, CtlPkt& reply) {
1529  if (!cp.isSet(COMTREE_NUM)) {
1530  reply.setErrMsg("modify comtree: missing required "
1531  "attribute");
1532  reply.setRrType(NEG_REPLY);
1533  return false;
1534  }
1535  comt_t comt = cp.getAttr(COMTREE_NUM);
1536  int ctx = ctt->getComtIndex(comt);
1537  if (ctx != 0) {
1538  if (cp.isSet(CORE_FLAG))
1539  ctt->setCoreFlag(ctx,cp.getAttr(CORE_FLAG));
1540  if (cp.isSet(PARENT_LINK)) {
1541  int plnk = cp.getAttr(PARENT_LINK);
1542  if (plnk != 0 && !ctt->isLink(ctx,plnk)) {
1543  reply.setErrMsg("specified link does "
1544  "not belong to comtree");
1545  reply.setRrType(NEG_REPLY);
1546  return false;
1547  }
1548  if (plnk != 0 && !ctt->isRtrLink(ctx,plnk)) {
1549  reply.setErrMsg("specified link does "
1550  "not connect to a router");
1551  reply.setRrType(NEG_REPLY);
1552  return false;
1553  }
1554  ctt->setPlink(ctx,plnk);
1555  }
1556  return true;
1557  }
1558  reply.setErrMsg("modify comtree: invalid comtree");
1559  reply.setRrType(NEG_REPLY);
1560  return false;
1561 }
1562 
1563 bool RouterCore::addComtreeLink(int p, CtlPkt& cp, CtlPkt& reply) {
1564  // Note: we require the comtree number and
1565  // either the link number or the peerIP and peerPort
1566  if (!(cp.isSet(COMTREE_NUM) &&
1567  (cp.isSet(LINK_NUM) ||
1568  (cp.isSet(PEER_IP) && cp.isSet(PEER_PORT))))) {
1569  reply.setErrMsg("add comtree link: missing required "
1570  "attribute");
1571  reply.setRrType(NEG_REPLY);
1572  return false;
1573  }
1574  comt_t comt = cp.getAttr(COMTREE_NUM);
1575  int ctx = ctt->getComtIndex(comt);
1576  if (ctx == 0) {
1577  reply.setErrMsg("add comtree link: invalid comtree");
1578  reply.setRrType(NEG_REPLY);
1579  return false;
1580  }
1581  int lnk = 0;
1582  if (cp.isSet(LINK_NUM)) {
1583  lnk = cp.getAttr(LINK_NUM);
1584  } else if (cp.isSet(PEER_IP) && cp.isSet(PEER_PORT)) {
1585  lnk = lt->lookup(cp.getAttr(PEER_IP),
1586  cp.getAttr(PEER_PORT));
1587  }
1588  if (!lt->valid(lnk)) {
1589  reply.setErrMsg("add comtree link: invalid link or "
1590  "peer IP and port");
1591  reply.setRrType(NEG_REPLY);
1592  return false;
1593  }
1594  bool isRtr = (lt->getPeerType(lnk) == ROUTER);
1595  bool isCore = false;
1596  if (isRtr) {
1597  if(!cp.isSet(PEER_CORE_FLAG)) {
1598  reply.setErrMsg("add comtree link: must "
1599  "specify core flag on links to routers");
1600  reply.setRrType(NEG_REPLY);
1601  return false;
1602  }
1603  isCore = cp.getAttr(PEER_CORE_FLAG);
1604  }
1605  int cLnk = ctt->getComtLink(comt,lnk);
1606  if (cLnk != 0) {
1607  if (ctt->isRtrLink(cLnk) == isRtr &&
1608  ctt->isCoreLink(cLnk) == isCore) {
1609  reply.setAttr(LINK_NUM,lnk);
1610  return true;
1611  } else {
1612  reply.setErrMsg("add comtree link: specified "
1613  "link already in comtree");
1614  reply.setRrType(NEG_REPLY);
1615  return false;
1616  }
1617  }
1618  // define new comtree link
1619  if (!ctt->addLink(ctx,lnk,isRtr,isCore)) {
1620  reply.setErrMsg("add comtree link: cannot add "
1621  "requested comtree link");
1622  reply.setRrType(NEG_REPLY);
1623  return false;
1624  }
1625  cLnk = ctt->getComtLink(comt,lnk);
1626 
1627  // add unicast route to cLnk if peer is a leaf or a router
1628  // in a different zip code
1629  fAdr_t peerAdr = lt->getPeerAdr(lnk);
1630  if (lt->getPeerType(lnk) != ROUTER) {
1631  int rtx = rt->getRteIndex(comt,peerAdr);
1632  if (rtx == 0) rt->addEntry(comt,peerAdr,cLnk);
1633  } else {
1634  int zipPeer = Forest::zipCode(peerAdr);
1635  if (zipPeer != Forest::zipCode(myAdr)) {
1636  fAdr_t dest = Forest::forestAdr(zipPeer,0);
1637  int rtx = rt->getRteIndex(comt,dest);
1638  if (rtx == 0) rt->addEntry(comt,dest,cLnk);
1639  }
1640  }
1641 
1642  // allocate queue and bind it to lnk and comtree link
1643  int qid = qm->allocQ(lnk);
1644  if (qid == 0) {
1645  ctt->removeLink(ctx,cLnk);
1646  reply.setErrMsg("add comtree link: no queues "
1647  "available for link");
1648  reply.setRrType(NEG_REPLY);
1649  return false;
1650  }
1651  ctt->setLinkQ(cLnk,qid);
1652 
1653  // adjust rates for link comtree and queue
1654  int br = Forest::MINBITRATE;
1655  int pr = Forest::MINPKTRATE;
1656  if (!(lt->addAvailInBitRate(lnk, -br) &&
1657  lt->addAvailInPktRate(lnk, -pr) &&
1658  lt->addAvailOutBitRate(lnk, -br) &&
1659  lt->addAvailOutPktRate(lnk, -pr))) {
1660  reply.setErrMsg("add comtree link: request "
1661  "exceeds link capacity");
1662  reply.setRrType(NEG_REPLY);
1663  return false;
1664  }
1665  ctt->setInBitRate(cLnk,br);
1666  ctt->setInPktRate(cLnk,pr);
1667  ctt->setOutBitRate(cLnk,br);
1668  ctt->setOutPktRate(cLnk,pr);
1669 
1670  qm->setQRates(qid,br,pr);
1671  if (isRtr) qm->setQLimits(qid,500,1000000);
1672  else qm->setQLimits(qid,500,1000000);
1673  sm->clearQuStats(qid);
1674  reply.setAttr(LINK_NUM,lnk);
1675  return true;
1676 }
1677 
1678 bool RouterCore::dropComtreeLink(int p, CtlPkt& cp, CtlPkt& reply) {
1679  // Note: we require either the link number or
1680  // the peerIP and peerPort
1681  if (!(cp.isSet(COMTREE_NUM) &&
1682  (cp.isSet(LINK_NUM) ||
1683  (cp.isSet(PEER_IP) && cp.isSet(PEER_PORT))))) {
1684  reply.setErrMsg("add comtree link: missing required "
1685  "attribute");
1686  reply.setRrType(NEG_REPLY);
1687  return false;
1688  }
1689  comt_t comt = cp.getAttr(COMTREE_NUM);
1690  int ctx = ctt->getComtIndex(comt);
1691  if (ctx == 0) {
1692  reply.setErrMsg("drop comtree link: invalid comtree");
1693  reply.setRrType(NEG_REPLY);
1694  return false;
1695  }
1696  int lnk;
1697  if (cp.isSet(LINK_NUM)) lnk = cp.getAttr(LINK_NUM);
1698  else lnk = lt->lookup(cp.getAttr(PEER_IP),cp.getAttr(PEER_PORT));
1699  if (!lt->valid(lnk)) {
1700  reply.setErrMsg("drop comtree link: invalid link "
1701  "or peer IP and port");
1702  reply.setRrType(NEG_REPLY);
1703  return false;
1704  }
1705  int cLnk = ctt->getComtLink(comt,lnk);
1706  if (cLnk != 0) {
1707  dropComtreeLink(ctx,lnk,cLnk);
1708  }
1709  return true;
1710 }
1711 
1712 void RouterCore::dropComtreeLink(int ctx, int lnk, int cLnk) {
1713  // release the link bandwidth used by comtree link
1714  lt->addAvailInBitRate(lnk,ctt->getInBitRate(cLnk));
1715  lt->addAvailInPktRate(lnk,ctt->getInPktRate(cLnk));
1716  lt->addAvailOutBitRate(lnk,ctt->getOutBitRate(cLnk));
1717  lt->addAvailOutPktRate(lnk,ctt->getOutPktRate(cLnk));
1718 
1719  // remove unicast route for this comtree
1720  fAdr_t peerAdr = lt->getPeerAdr(lnk);
1721  int comt = ctt->getComtree(ctx);
1722  if (lt->getPeerType(lnk) != ROUTER) {
1723  int rtx = rt->getRteIndex(comt,peerAdr);
1724  if (rtx != 0) rt->removeEntry(rtx);
1725  } else {
1726  int zipPeer = Forest::zipCode(peerAdr);
1727  if (zipPeer != Forest::zipCode(myAdr)) {
1728  fAdr_t dest = Forest::forestAdr(zipPeer,0);
1729  int rtx = rt->getRteIndex(comt,dest);
1730  if (rtx != 0) rt->removeEntry(rtx);
1731  }
1732  }
1733  // remove cLnk from multicast routes for this comtree
1734  // must first copy out the routes that are registered for
1735  // cLnk, then remove cLnk from all these routes;
1736  // two step process is needed because the removal of the link from
1737  // the route, also deregisters the route in the comtree table
1738  // causing the rteSet to change
1739  set<int>& rteSet = ctt->getRteSet(cLnk);
1740  set<int>::iterator rp;
1741  int *routes = new int[rteSet.size()];
1742  int i = 0;
1743  for (rp = rteSet.begin(); rp != rteSet.end(); rp++) routes[i++] = *rp;
1744  while (--i >= 0) rt->removeLink(routes[i],cLnk);
1745  delete [] routes;
1746 
1747  // release queue and remove link from comtree
1748  // (which also deregisters comtree with lnk)
1749  int qid = ctt->getLinkQ(cLnk);
1750  qm->freeQ(qid);
1751  if (!ctt->removeLink(ctx,cLnk)) {
1752  cerr << "dropComtreeLink: internal error detected "
1753  "final removeLink failed\n";
1754  }
1755 }
1756 
1757 bool RouterCore::modComtreeLink(int p, CtlPkt& cp, CtlPkt& reply) {
1758  if (!(cp.isSet(COMTREE_NUM) && cp.isSet(LINK_NUM))) {
1759  reply.setErrMsg("modify comtree link: missing required "
1760  "attribute");
1761  reply.setRrType(NEG_REPLY);
1762  return false;
1763  }
1764  comt_t comt = cp.getAttr(COMTREE_NUM);
1765  int ctx = ctt->getComtIndex(comt);
1766  if (ctx == 0) {
1767  reply.setErrMsg("modify comtree link: invalid comtree");
1768  reply.setRrType(NEG_REPLY);
1769  return false;
1770  }
1771  int lnk = cp.getAttr(LINK_NUM);
1772  if (!lt->valid(lnk)) {
1773  reply.setErrMsg("modify comtree link: invalid link "
1774  "number");
1775  reply.setRrType(NEG_REPLY);
1776  return false;
1777  }
1778  int cLnk = ctt->getComtLink(comt,lnk);
1779  if (cLnk == 0) {
1780  reply.setErrMsg("modify comtree link: specified link "
1781  "not defined in specified comtree");
1782  reply.setRrType(NEG_REPLY);
1783  return false;
1784  }
1785 
1786  int ibr = ctt->getInBitRate(cLnk);
1787  int ipr = ctt->getInPktRate(cLnk);
1788  int obr = ctt->getOutBitRate(cLnk);
1789  int opr = ctt->getOutPktRate(cLnk);
1790 
1791  if (cp.isSet(BIT_RATE_IN)) ibr = cp.getAttr(BIT_RATE_IN);
1792  if (cp.isSet(PKT_RATE_IN)) ipr = cp.getAttr(PKT_RATE_IN);
1793  if (cp.isSet(BIT_RATE_OUT)) obr = cp.getAttr(BIT_RATE_OUT);
1794  if (cp.isSet(PKT_RATE_OUT)) opr = cp.getAttr(PKT_RATE_OUT);
1795 
1796  int dibr = ibr - ctt->getInBitRate(cLnk);
1797  int dipr = ipr - ctt->getInPktRate(cLnk);
1798  int dobr = obr - ctt->getOutBitRate(cLnk);
1799  int dopr = opr - ctt->getOutPktRate(cLnk);
1800 
1801  bool success = true;
1802  if (lt->getAvailInBitRate(lnk) < dibr) {
1803  reply.setErrMsg("modify comtree link: increase in "
1804  "input bit rate exceeds link capacity");
1805  success = false;
1806  }
1807  if (lt->getAvailInPktRate(lnk) < dipr) {
1808  reply.setErrMsg("modify comtree link: increase in "
1809  "input packet rate exceeds link capacity");
1810  success = false;
1811  }
1812  if (lt->getAvailOutBitRate(lnk) < dobr) {
1813  reply.setErrMsg("modify comtree link: increase in "
1814  "output bit rate exceeds link capacity");
1815  success = false;
1816  }
1817  if (lt->getAvailOutPktRate(lnk) < dopr) {
1818  reply.setErrMsg("modify comtree link: increase in "
1819  "output packet rate exceeds link capacity");
1820  success = false;
1821  }
1822  if (!success) { reply.setRrType(NEG_REPLY); return false; }
1823 
1824  if (dibr != 0) {
1825  lt->addAvailInBitRate(lnk,-dibr); ctt->setInBitRate(cLnk,ibr);
1826  }
1827  if (dipr != 0) {
1828  lt->addAvailInPktRate(lnk,-dipr); ctt->setInPktRate(cLnk,ipr);
1829  }
1830  if (dobr != 0) {
1831  lt->addAvailOutBitRate(lnk,-dobr); ctt->setOutBitRate(cLnk,obr);
1832  }
1833  if (dopr != 0) {
1834  lt->addAvailOutPktRate(lnk,-dopr); ctt->setOutPktRate(cLnk,opr);
1835  }
1836  return true;
1837 }
1838 
1839 bool RouterCore::getComtreeLink(int p, CtlPkt& cp, CtlPkt& reply) {
1840  if (!(cp.isSet(COMTREE_NUM) && cp.isSet(LINK_NUM))) {
1841  reply.setErrMsg("get comtree link: missing required "
1842  "attribute");
1843  reply.setRrType(NEG_REPLY);
1844  return false;
1845  }
1846  comt_t comt = cp.getAttr(COMTREE_NUM);
1847  int ctx = ctt->getComtIndex(comt);
1848  if (ctx == 0) {
1849  reply.setErrMsg("get comtree link: invalid comtree");
1850  reply.setRrType(NEG_REPLY);
1851  return false;
1852  }
1853  int lnk = cp.getAttr(LINK_NUM);
1854  if (!lt->valid(lnk)) {
1855  reply.setErrMsg("get comtree link: invalid link "
1856  "number");
1857  reply.setRrType(NEG_REPLY);
1858  return false;
1859  }
1860  int cLnk = ctt->getComtLink(comt,lnk);
1861  if (cLnk == 0) {
1862  reply.setErrMsg("get comtree link: specified link "
1863  "not defined in specified comtree");
1864  reply.setRrType(NEG_REPLY);
1865  return false;
1866  }
1867  reply.setAttr(COMTREE_NUM,comt);
1868  reply.setAttr(LINK_NUM,lnk);
1869  reply.setAttr(QUEUE_NUM,ctt->getLinkQ(cLnk));
1870  reply.setAttr(PEER_DEST,ctt->getDest(cLnk));
1871  reply.setAttr(BIT_RATE_IN,ctt->getInBitRate(cLnk));
1872  reply.setAttr(PKT_RATE_IN,ctt->getInPktRate(cLnk));
1873  reply.setAttr(BIT_RATE_OUT,ctt->getOutBitRate(cLnk));
1874  reply.setAttr(PKT_RATE_OUT,ctt->getOutPktRate(cLnk));
1875 
1876  return true;
1877 }
1878 
1879 bool RouterCore::addRoute(int p, CtlPkt& cp, CtlPkt& reply) {
1880  if (!(cp.isSet(COMTREE_NUM) && cp.isSet(DEST_ADR) &&
1881  cp.isSet(LINK_NUM))) {
1882  reply.setErrMsg("add route: missing required "
1883  "attribute");
1884  reply.setRrType(NEG_REPLY);
1885  return false;
1886  }
1887  comt_t comt = cp.getAttr(COMTREE_NUM);
1888  if (!ctt->validComtree(comt)) {
1889  reply.setErrMsg("comtree not defined at this router\n");
1890  reply.setRrType(NEG_REPLY);
1891  return false;
1892  }
1893  fAdr_t dest = cp.getAttr(DEST_ADR);
1894  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1895  reply.setErrMsg("invalid address\n");
1896  reply.setRrType(NEG_REPLY);
1897  return false;
1898  }
1899  int lnk = cp.getAttr(LINK_NUM);
1900  int cLnk = ctt->getComtLink(comt,lnk);
1901  int rtx = rt->getRteIndex(comt,dest);
1902  if (rtx != 0) {
1903  if ((Forest::validUcastAdr(dest) && rt->getLink(rtx) == cLnk) ||
1904  (Forest::mcastAdr(dest) && rt->isLink(rtx,cLnk))) {
1905  return true;
1906  } else {
1907  reply.setErrMsg("add route: requested route "
1908  "conflicts with existing route");
1909  reply.setRrType(NEG_REPLY);
1910  return false;
1911  }
1912  } else if (rt->addEntry(comt, dest, lnk)) {
1913  return true;
1914  }
1915  reply.setErrMsg("add route: cannot add route");
1916  reply.setRrType(NEG_REPLY);
1917  return false;
1918 }
1919 
1920 bool RouterCore::dropRoute(int p, CtlPkt& cp, CtlPkt& reply) {
1921  if (!(cp.isSet(COMTREE_NUM) && cp.isSet(DEST_ADR))) {
1922  reply.setErrMsg("drop route: missing required "
1923  "attribute");
1924  reply.setRrType(NEG_REPLY);
1925  return false;
1926  }
1927  comt_t comt = cp.getAttr(COMTREE_NUM);
1928  if (!ctt->validComtree(comt)) {
1929  reply.setErrMsg("comtree not defined at this router\n");
1930  reply.setRrType(NEG_REPLY);
1931  return false;
1932  }
1933  fAdr_t dest = cp.getAttr(DEST_ADR);
1934  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1935  reply.setErrMsg("invalid address\n");
1936  reply.setRrType(NEG_REPLY);
1937  return false;
1938  }
1939  int rtx = rt->getRteIndex(comt,dest);
1940  rt->removeEntry(rtx);
1941  return true;
1942 }
1943 
1944 bool RouterCore::getRoute(int p, CtlPkt& cp, CtlPkt& reply) {
1945  if (!(cp.isSet(COMTREE_NUM) && cp.isSet(DEST_ADR))) {
1946  reply.setErrMsg("get route: missing required "
1947  "attribute");
1948  reply.setRrType(NEG_REPLY);
1949  return false;
1950  }
1951  comt_t comt = cp.getAttr(COMTREE_NUM);
1952  if (!ctt->validComtree(comt)) {
1953  reply.setErrMsg("comtree not defined at this router\n");
1954  reply.setRrType(NEG_REPLY);
1955  return false;
1956  }
1957  fAdr_t dest = cp.getAttr(DEST_ADR);
1958  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1959  reply.setErrMsg("invalid address\n");
1960  reply.setRrType(NEG_REPLY);
1961  return false;
1962  }
1963  int rtx = rt->getRteIndex(comt,dest);
1964  if (rtx != 0) {
1965  reply.setAttr(COMTREE_NUM,comt);
1966  reply.setAttr(DEST_ADR,dest);
1967  if (Forest::validUcastAdr(dest)) {
1968  int lnk = ctt->getLink(rt->getLink(rtx));
1969  reply.setAttr(LINK_NUM,lnk);
1970  } else {
1971  reply.setAttr(LINK_NUM,0);
1972  }
1973  return true;
1974  }
1975  reply.setErrMsg("get route: no route for specified address");
1976  reply.setRrType(NEG_REPLY);
1977  return false;
1978 }
1979 
1980 bool RouterCore::modRoute(int p, CtlPkt& cp, CtlPkt& reply) {
1981  if (!(cp.isSet(COMTREE_NUM) && cp.isSet(DEST_ADR))) {
1982  reply.setErrMsg("mod route: missing required "
1983  "attribute");
1984  reply.setRrType(NEG_REPLY);
1985  return false;
1986  }
1987  comt_t comt = cp.getAttr(COMTREE_NUM);
1988  if (!ctt->validComtree(comt)) {
1989  reply.setErrMsg("comtree not defined at this router\n");
1990  reply.setRrType(NEG_REPLY);
1991  return false;
1992  }
1993  fAdr_t dest = cp.getAttr(DEST_ADR);
1994  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1995  reply.setErrMsg("invalid address\n");
1996  reply.setRrType(NEG_REPLY);
1997  return false;
1998  }
1999  int rtx = rt->getRteIndex(comt,dest);
2000  if (rtx != 0) {
2001  if (cp.isSet(LINK_NUM)) {
2002  if (Forest::mcastAdr(dest)) {
2003  reply.setErrMsg("modify route: cannot "
2004  "set link in multicast route");
2005  reply.setRrType(NEG_REPLY);
2006  return false;
2007  }
2008  rt->setLink(rtx,cp.getAttr(LINK_NUM));
2009  }
2010  return true;
2011  }
2012  reply.setErrMsg("modify route: invalid route");
2013  reply.setRrType(NEG_REPLY);
2014  return false;
2015 }
2016 
2029 bool RouterCore::bootComplete(int p, CtlPkt& cp, CtlPkt& reply) {
2030  if (booting && !setup()) {
2031  cerr << "RouterCore::bootComplete: setup failed after "
2032  "completion of boot phase\n";
2033  perror("");
2034  reply.setErrMsg("configured tables are not consistent\n");
2035  reply.setRrType(NEG_REPLY);
2036  returnToSender(p,reply.pack(ps->getPayload(p)));
2037  pktLog->write(cout);
2038  exit(1);
2039  }
2040  return true;
2041 }
2042 
2043 bool RouterCore::bootAbort(int p, CtlPkt& cp, CtlPkt& reply) {
2044  cerr << "RouterCore::bootAbort: received boot abort message "
2045  "from netMgr; exiting\n";
2046  reply.setRrType(POS_REPLY);
2047  returnToSender(p,reply.pack(ps->getPayload(p)));
2048  pktLog->write(cout);
2049  exit(1);
2050 }
2051 
2060 bool RouterCore::sendCpReq(CtlPkt& cp, fAdr_t dest) {
2061  int p = ps->alloc();
2062  if (p == 0) {
2063  cerr << "RouterCore::sendCpReq: no packets left in packet "
2064  "store\n";
2065  return false;
2066  }
2067  PacketHeader& h = ps->getHeader(p);
2068 
2069  // pack cp into p, setting rr type and seq number
2070  cp.setRrType(REQUEST);
2071  cp.setSeqNum(seqNum);
2072  int paylen = cp.pack(ps->getPayload(p));
2073  if (paylen == 0) {
2074  cerr << "RouterCore::sendCpReq: control packet packing error\n";
2075  return false;
2076  }
2077  h.setLength(Forest::OVERHEAD + paylen);
2078  h.setPtype(NET_SIG); h.setFlags(0);
2079  h.setComtree(Forest::NET_SIG_COMT);
2080  h.setSrcAdr(myAdr); h.setDstAdr(dest);
2081  h.setInLink(0);
2082  ps->pack(p);
2083 
2084  // save a record of the packet in pending map
2085  pair<uint64_t,CpInfo> cpp;
2086  cpp.first = seqNum;
2087  cpp.second.p = p; cpp.second.nSent = 1; cpp.second.timestamp = now;
2088  pending->insert(cpp);
2089  seqNum++;
2090 
2091  // now, make copy of packet and send the copy
2092  int copy = ps->fullCopy(p);
2093  if (copy == 0) {
2094  cerr << "RouterCore::sendCpReq: no packets left in packet "
2095  "store\n";
2096  return false;
2097  }
2098  if (booting) {
2099  iop->send(copy,0);
2100  pktLog->log(copy,0,true,now);
2101  } else
2102  forward(copy,ctt->getComtIndex(h.getComtree()));
2103 
2104  return true;
2105 
2106 }
2107 
2114 void RouterCore::resendCpReq() {
2115  map<uint64_t,CpInfo>::iterator pp;
2116  for (pp = pending->begin(); pp != pending->end(); pp++) {
2117  if (now < pp->second.timestamp + 1000000000) continue;
2118  int p = pp->second.p;
2119  PacketHeader h = ps->getHeader(p);
2120  if (pp->second.nSent >= 3) { // give up on this packet
2121  string s;
2122  cerr << "RouterCore::resendCpReq: received no reply to "
2123  "control packet after three attempts\n"
2124  << h.toString(ps->getBuffer(p),s);
2125  ps->free(p);
2126  pending->erase(pp->first);
2127  continue;
2128  }
2129  string s1;
2130  cout << "resending control packet\n"
2131  << h.toString(ps->getBuffer(p),s1);
2132  // make copy of packet and send the copy
2133  pp->second.timestamp = now;
2134  pp->second.nSent++;
2135  int copy = ps->fullCopy(p);
2136  if (copy == 0) {
2137  cerr << "RouterCore::resendCpReq: no packets left in "
2138  "packet store\n";
2139  return;
2140  }
2141  if (booting) {
2142  pktLog->log(copy,0,true,now);
2143  iop->send(copy,0);
2144  } else
2145  forward(copy,ctt->getComtIndex(h.getComtree()));
2146  }
2147 }
2148 
2158 void RouterCore::handleCpReply(int reply, CtlPkt& cpr) {
2159  PacketHeader hr = ps->getHeader(reply);
2160  map<uint64_t,CpInfo>::iterator pp = pending->find(cpr.getSeqNum());
2161  if (pp == pending->end()) {
2162  // this is a reply to a request we never sent, or
2163  // possibly, a reply to a request we gave up on
2164  ps->free(reply);
2165  return;
2166  }
2167  // so, remove it from the map of pending requests
2168  ps->free(pp->second.p);
2169  pending->erase(pp);
2170 
2171  // and then handle the reply
2172  switch (cpr.getCpType()) {
2173  case CLIENT_CONNECT: case CLIENT_DISCONNECT:
2174  if (cpr.getRrType() == NEG_REPLY) {
2175  cerr << "RouterCore::handleCpReply: got negative reply "
2176  "to a connect or disconnect request: "
2177  << cpr.getErrMsg() << endl;
2178  break;
2179  }
2180  // otherwise, nothing to do
2181  break;
2182  case BOOT_REQUEST: {
2183  if (cpr.getRrType() == NEG_REPLY) {
2184  cerr << "RouterCore::handleCpReply: got "
2185  "negative reply to a boot request: "
2186  << cpr.getErrMsg() << endl;
2187  break;
2188  }
2189  // unpack first and last leaf addresses, initialize leafAdr
2190  if (!(cpr.isSet(FIRST_LEAF_ADR) && cpr.isSet(LAST_LEAF_ADR))) {
2191  cerr << "RouterCore::handleCpReply: reply to boot "
2192  "request did not include leaf address range\n";
2193  break;
2194  }
2195  firstLeafAdr = cpr.getAttr(FIRST_LEAF_ADR);
2196  fAdr_t lastLeafAdr = cpr.getAttr(LAST_LEAF_ADR);
2197  if (firstLeafAdr > lastLeafAdr) {
2198  cerr << "RouterCore::handleCpReply: reply to boot "
2199  "request contained empty leaf address range\n";
2200  break;
2201  }
2202  leafAdr = new UiSetPair((lastLeafAdr - firstLeafAdr)+1);
2203  break;
2204  }
2205  default:
2206  cerr << "RouterCore::handleCpReply: unexpected control packet "
2207  "type\n";
2208  break;
2209  }
2210  ps->free(reply);
2211 }
2212 
2218 void RouterCore::returnToSender(packet p, int paylen) {
2219  PacketHeader& h = ps->getHeader(p);
2220  if (paylen == 0) {
2221  cerr << "RouterCore::returnToSender: control packet formatting "
2222  "error, zero payload length\n";
2223  ps->free(p);
2224  }
2225  h.setLength(Forest::OVERHEAD + paylen);
2226  h.setFlags(0);
2227  h.setDstAdr(h.getSrcAdr());
2228  h.setSrcAdr(myAdr);
2229 
2230  ps->pack(p);
2231 
2232  if (booting) {
2233  pktLog->log(p,0,true,now);
2234  iop->send(p,0);
2235  return;
2236  }
2237 
2238  int cLnk = ctt->getComtLink(h.getComtree(),h.getInLink());
2239  int qn = ctt->getLinkQ(cLnk);
2240  if (!qm->enq(p,qn,now)) { ps->free(p); }
2241 }
2242 
2243 } // ends namespace
2244