forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
RouterCore-sav.cpp
1 
9 #include "RouterCore.h"
10 
11 using namespace forest;
12 
23 bool processArgs(int argc, char *argv[], RouterInfo& args) {
24  // set default values
25  args.mode = "local";
26  args.myAdr = args.bootIp = args.nmAdr = args.nmIp = 0;
27  args.ccAdr = args.firstLeafAdr = args.lastLeafAdr = 0;
28  args.ifTbl = ""; args.lnkTbl = ""; args.comtTbl = "";
29  args.rteTbl = ""; args.statSpec = "";
30  args.portNum = 0; args.finTime = 0;
31 
32  string s;
33  for (int i = 1; i < argc; i++) {
34  s = argv[i];
35  if (s.compare(0,10,"mode=local") == 0) {
36  args.mode = "local";
37  } else if (s.compare(0,11,"mode=remote") == 0) {
38  args.mode = "remote";
39  } else if (s.compare(0,6,"myAdr=") == 0) {
40  args.myAdr = Forest::forestAdr(&argv[i][6]);
41  } else if (s.compare(0,7,"bootIp=") == 0) {
42  args.bootIp = Np4d::ipAddress(&argv[i][7]);
43  } else if (s.compare(0,6,"nmAdr=") == 0) {
44  args.nmAdr = Forest::forestAdr(&argv[i][6]);
45  } else if (s.compare(0,5,"nmIp=") == 0) {
46  args.nmIp = Np4d::ipAddress(&argv[i][5]);
47  } else if (s.compare(0,6,"ccAdr=") == 0) {
48  args.ccAdr = Forest::forestAdr(&argv[i][6]);
49  } else if (s.compare(0,13,"firstLeafAdr=") == 0) {
50  args.firstLeafAdr = Forest::forestAdr(&argv[i][13]);
51  } else if (s.compare(0,12,"lastLeafAdr=") == 0) {
52  args.lastLeafAdr = Forest::forestAdr(&argv[i][12]);
53  } else if (s.compare(0,6,"ifTbl=") == 0) {
54  args.ifTbl = &argv[i][6];
55  } else if (s.compare(0,7,"lnkTbl=") == 0) {
56  args.lnkTbl = &argv[i][7];
57  } else if (s.compare(0,8,"comtTbl=") == 0) {
58  args.comtTbl = &argv[i][8];
59  } else if (s.compare(0,7,"rteTbl=") == 0) {
60  args.rteTbl = &argv[i][7];
61  } else if (s.compare(0,9,"statSpec=") == 0) {
62  args.statSpec = &argv[i][9];
63  } else if (s.compare(0,8,"portNum=") == 0) {
64  sscanf(&argv[i][8],"%hd",&args.portNum);
65  } else if (s.compare(0,8,"finTime=") == 0) {
66  sscanf(&argv[i][8],"%d",&args.finTime);
67  } else {
68  cerr << "unrecognized argument: " << argv[i] << endl;
69  return false;
70  }
71  }
72  if (args.mode.compare("local") == 0 &&
73  (args.myAdr == 0 || args.firstLeafAdr == 0 ||
74  args.lastLeafAdr ==0 || args.lastLeafAdr < args.firstLeafAdr)) {
75  cerr << "processArgs: local configuration requires myAdr, "
76  "firstLeafAdr, lastLeafAdr and that firstLeafAdr "
77  "be no larger than lastLeafAdr\n";
78  return false;
79  } else if (args.mode.compare("remote") == 0 &&
80  (args.bootIp == 0 || args.myAdr == 0 ||
81  args.nmIp == 0 || args.nmAdr == 0)) {
82  cerr << "processArgs: remote configuration requires bootIp, "
83  "myAdr, netMgrIp and netMgrAdr\n";
84  return false;
85  }
86  return true;
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 
111 namespace forest {
112 
117 RouterCore::RouterCore(bool booting1, const RouterInfo& config)
118  : booting(booting1) {
119  nIfaces = 50; nLnks = 1000;
120  nComts = 5000; nRts = 100000;
121  nPkts = 100000; nBufs = 50000; nQus = 10000;
122 
123  myAdr = config.myAdr;
124  bootIp = config.bootIp;
125  nmAdr = config.nmAdr;
126  nmIp = config.nmIp;
127  ccAdr = config.ccAdr;
128  firstLeafAdr = config.firstLeafAdr;
129 
130  ps = new PacketStore(nPkts, nBufs);
131  ift = new IfaceTable(nIfaces);
132  lt = new LinkTable(nLnks);
133  ctt = new ComtreeTable(nComts,10*nComts,lt);
134  rt = new RouteTable(nRts,myAdr,ctt);
135  sm = new StatsModule(1000, nLnks, nQus, ctt);
136  iop = new IoProcessor(nIfaces, config.portNum, ift, lt, ps, sm);
137  qm = new QuManager(nLnks, nPkts, nQus, min(50,5*nPkts/nLnks), ps, sm);
138  pktLog = new PacketLog(5000,20,ps);
139 
140  if (!booting)
141  leafAdr = new UiSetPair((config.lastLeafAdr - firstLeafAdr)+1);
142 
143  seqNum = 1;
144  pending = new map<uint64_t,CpInfo>;
145 }
146 
147 RouterCore::~RouterCore() {
148  delete pktLog; delete qm; delete iop; delete sm;
149  delete rt; delete ctt; delete lt; delete ift; delete ps;
150  if (leafAdr != 0) delete leafAdr;
151 }
152 
159 bool RouterCore::readTables(const RouterInfo& config) {
160  if (config.ifTbl.compare("") != 0) {
161  ifstream fs; fs.open(config.ifTbl.c_str());
162  if (fs.fail() || !ift->read(fs)) {
163  cerr << "RouterCore::init: can't read "
164  << "interface table\n";
165  return false;
166  }
167  fs.close();
168  }
169  if (config.lnkTbl.compare("") != 0) {
170  ifstream fs; fs.open(config.lnkTbl.c_str());
171  if (fs.fail() || !lt->read(fs)) {
172  cerr << "RouterCore::init: can't read "
173  << "link table\n";
174  return false;
175  }
176  fs.close();
177  }
178  if (config.comtTbl.compare("") != 0) {
179  ifstream fs; fs.open(config.comtTbl.c_str());
180  if (fs.fail() || !ctt->read(fs)) {
181  cerr << "RouterCore::init: can't read "
182  << "comtree table\n";
183  return false;
184  }
185  fs.close();
186  }
187  if (config.rteTbl.compare("") != 0) {
188  ifstream fs; fs.open(config.rteTbl.c_str());
189  if (fs.fail() || !rt->read(fs)) {
190  cerr << "RouterCore::init: can't read "
191  << "routing table\n";
192  return false;
193  }
194  fs.close();
195  }
196  if (config.statSpec.compare("") != 0) {
197  ifstream fs; fs.open(config.statSpec.c_str());
198  if (fs.fail() || !sm->read(fs)) {
199  cerr << "RouterCore::init: can't read "
200  << "statistics spec\n";
201  return false;
202  }
203  fs.close();
204  }
205  return true;
206 }
207 
213  dump(cout);
214  if (!setupIfaces()) return false;
215  if (!setupLeafAddresses()) return false;
216  if (!setupQueues()) return false;
217  if (!checkTables()) return false;
218  if (!setAvailRates()) return false;
219  addLocalRoutes();
220 
221  return true;
222 }
223 
229  for (int iface = ift->firstIface(); iface != 0;
230  iface = ift->nextIface(iface)) {
231  if (iop->ready(iface)) continue;
232  if (!iop->setup(iface)) {
233  cerr << "RouterCore::setupIfaces: could not "
234  "setup interface " << iface << endl;
235  return false;
236  }
237  }
238  return true;
239 }
240 
241 
248  for (int lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
249  if (booting || lt->getPeerType(lnk) == Forest::ROUTER) continue;
250  if (!allocLeafAdr(lt->getPeerAdr(lnk)))
251  return false;
252  }
253  return true;
254 }
255 
263  // Set link rates in QuManager
264  for (int lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
265  qm->setLinkRates(lnk,lt->getRates(lnk));
266  }
269  int ctx;
270  for (ctx = ctt->firstComtIndex(); ctx != 0;
271  ctx = ctt->nextComtIndex(ctx)) {
272  set<int>& links = ctt->getLinks(ctx);
273  set<int>::iterator p;
274  for (p = links.begin(); p != links.end(); p++) {
275  int cLnk = *p; int lnk = ctt->getLink(cLnk);
276  int qid = qm->allocQ(lnk);
277  if (qid == 0) return false;
278  ctt->setLinkQ(cLnk,qid);
279  qm->setQRates(qid,rs);
280  if (lt->getPeerType(lnk) == Forest::ROUTER)
281  qm->setQLimits(qid,100,200000);
282  else
283  qm->setQLimits(qid,50,100000);
284  sm->clearQuStats(qid);
285  }
286  }
287  return true;
288 }
289 
297  bool success = true;
298 
299  // verify that the default interface is valid and
300  // that each interface has a non-zero IP address
301  if (!ift->valid(ift->getDefaultIface())) {
302  cerr << "RouterCore::checkTables: specified default iface "
303  << ift->getDefaultIface() << " is invalid\n";
304  success = false;
305  }
306  int iface;
307  for (iface = ift->firstIface(); iface != 0;
308  iface = ift->nextIface(iface)) {
309  if (ift->getIpAdr(iface) == 0) {
310  cerr << "RouterCore::checkTables: interface "
311  << iface << " has zero for IP address\n";
312  success = false;
313  }
314  }
315 
316  // verify that each link is assigned to a valid interface
317  // that the peer Ip address and port are non-zero and consistent,
318  // the the peer type is valid and that the peer address is a valid
319  // unicast forest address
320  int lnk;
321  for (lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
322  iface = lt->getIface(lnk);
323  if (!ift->valid(iface)) {
324  cerr << "RouterCore::checkTables: interface " << iface
325  << " for link " << lnk << " is not valid\n";
326  success = false;
327  }
328  if (lt->getPeerIpAdr(lnk) == 0 &&
329  lt->getPeerType(lnk) == Forest::ROUTER) {
330  cerr << "RouterCore::checkTables: invalid peer IP "
331  << "for link " << lnk << endl;
332  success = false;
333  }
334  if (!Forest::validUcastAdr(lt->getPeerAdr(lnk))) {
335  cerr << "RouterCore::checkTables: invalid peer address "
336  << "for link " << lnk << endl;
337  success = false;
338  }
339  }
340 
341  // verify that the links in each comtree are valid,
342  // that the router links and core links refer to peer routers,
343  // and that each comtree link is consistent
344  int ctx;
345  for (ctx = ctt->firstComtIndex(); ctx != 0;
346  ctx = ctt->nextComtIndex(ctx)) {
347  int comt = ctt->getComtree(ctx);
348  int plnk = ctt->getPlink(ctx);
349  int pcLnk = ctt->getPCLink(ctx);
350  if (plnk != ctt->getLink(pcLnk)) {
351  cerr << "RouterCore::checkTables: parent link "
352  << plnk << " not consistent with pcLnk\n";
353  success = false;
354  }
355  if (ctt->inCore(ctx) && plnk != 0 && !ctt->isCoreLink(pcLnk)) {
356  cerr << "RouterCore::checkTables: parent link "
357  << plnk << " of core node does not lead to "
358  << "another core node\n";
359  success = false;
360  }
361  set<int>& links = ctt->getLinks(ctx);
362  set<int>::iterator p;
363  for (p = links.begin(); p != links.end(); p++) {
364  int cLnk = *p; int lnk = ctt->getLink(cLnk);
365  if (!lt->valid(lnk)) {
366  cerr << "RouterCore::checkTables: link "
367  << lnk << " in comtree " << comt
368  << " not in link table" << endl;
369  success = false;
370  continue;
371  }
372  fAdr_t dest = ctt->getDest(cLnk);
373  if (dest != 0 && !Forest::validUcastAdr(dest)) {
374  cerr << "RouterCore::checkTables: dest addr "
375  << "for " << lnk << " in comtree " << comt
376  << " is not valid" << endl;
377  success = false;
378  }
379  int qid = ctt->getLinkQ(cLnk);
380  if (qid == 0) {
381  cerr << "RouterCore::checkTables: queue id "
382  << "for " << lnk << " in comtree " << comt
383  << " is zero" << endl;
384  success = false;
385  }
386  }
387  if (!success) break;
388  set<int>& rtrLinks = ctt->getRtrLinks(ctx);
389  for (p = rtrLinks.begin(); p != rtrLinks.end(); p++) {
390  int cLnk = *p; int lnk = ctt->getLink(cLnk);
391  if (!ctt->isLink(ctx,lnk)) {
392  cerr << "RouterCore::checkTables: router link "
393  << lnk << " is not valid in comtree "
394  << comt << endl;
395  success = false;
396  }
397  if (lt->getPeerType(lnk) != Forest::ROUTER) {
398  cerr << "RouterCore::checkTables: router link "
399  << lnk << " in comtree " << comt
400  << " connects to non-router peer\n";
401  success = false;
402  }
403  }
404  set<int>& coreLinks = ctt->getCoreLinks(ctx);
405  for (p = coreLinks.begin(); p != coreLinks.end(); p++) {
406  int cLnk = *p; int lnk = ctt->getLink(cLnk);
407  if (!ctt->isRtrLink(ctx,lnk)) {
408  cerr << "RouterCore::checkTables: core link "
409  << lnk << " is not a router link "
410  << comt << endl;
411  success = false;
412  }
413  }
414  }
415  // come back later and add checks for route table
416  return success;
417 }
418 
425  bool success = true;
430  int iface;
431  for (iface = ift->firstIface(); iface != 0;
432  iface = ift->nextIface(iface)) {
433  RateSpec ifRates = ift->getRates(iface);
434  if (!minRates.leq(ifRates) || !ifRates.leq(maxRates)) {
435  cerr << "RouterCore::setAvailRates: interface rates "
436  "outside allowed range\n";
437  success = false;
438  }
439  ift->getAvailRates(iface) = ifRates;
440  }
441  if (!success) return false;
442  int lnk;
443  for (lnk = lt->firstLink(); lnk != 0; lnk = lt->nextLink(lnk)) {
444  RateSpec lnkRates = lt->getRates(lnk);
445  if (!minRates.leq(lnkRates) || !lnkRates.leq(maxRates)) {
446  cerr << "RouterCore::setAvailRates: link rates "
447  "outside allowed range\n";
448  success = false;
449  }
450  iface = lt->getIface(lnk);
451  RateSpec ifAvail = ift->getRates(iface);
452  if (!lnkRates.leq(ifAvail)) {
453  cerr << "RouterCore::setAvailRates: oversubscribing "
454  "interface " << iface << endl;
455  success = false;
456  }
457  ift->getAvailRates(iface).subtract(lnkRates);
458  lnkRates.scale(.9); // allocate at most 90% of link
459  lt->getAvailRates(lnk) = lnkRates;
460  sm->clearLnkStats(lnk);
461  }
462  if (!success) return false;
463  int ctx;
464  for (ctx = ctt->firstComtIndex(); ctx != 0;
465  ctx = ctt->nextComtIndex(ctx)) {
466  set<int>& comtLinks = ctt->getLinks(ctx);
467  set<int>::iterator p;
468  for (p = comtLinks.begin(); p != comtLinks.end(); p++) {
469  int cLnk = *p; int lnk = ctt->getLink(cLnk);
470  RateSpec comtRates = ctt->getRates(cLnk);
471  if (!comtRates.leq(lt->getAvailRates(lnk))) {
472  cerr << "RouterCore::setAvailRates: "
473  "oversubscribing link "
474  << lnk << endl;
475  success = false;
476  }
477  lt->getAvailRates(lnk).subtract(comtRates);
478  }
479  }
480  return success;
481 }
482 
487  for (int ctx = ctt->firstComtIndex(); ctx != 0;
488  ctx = ctt->nextComtIndex(ctx)) {
489  int comt = ctt->getComtree(ctx);
490  set<int>& comtLinks = ctt->getLinks(ctx);
491  set<int>::iterator p;
492  for (p = comtLinks.begin(); p != comtLinks.end(); p++) {
493  int cLnk = *p; int lnk = ctt->getLink(cLnk);
494  fAdr_t peerAdr = lt->getPeerAdr(lnk);
495  if (lt->getPeerType(lnk) == Forest::ROUTER &&
496  Forest::zipCode(peerAdr)
498  continue;
499  if (rt->getRteIndex(comt,peerAdr) != 0)
500  continue;
501  rt->addEntry(comt,peerAdr,cLnk);
502  }
503  }
504 }
505 
509 void RouterCore::dump(ostream& out) {
510  string s;
511  out << "Interface Table\n\n" << ift->toString(s) << endl;
512  out << "Link Table\n\n" << lt->toString(s) << endl;
513  out << "Comtree Table\n\n" << ctt->toString(s) << endl;
514  out << "Routing Table\n\n" << rt->toString(s) << endl;
515  out << "Statistics\n\n" << sm->toString(s) << endl;
516 }
517 
546 void RouterCore::run(uint64_t finishTime) {
547  now = Misc::getTimeNs();
548  if (booting) {
549  if (!iop->setupBootSock(bootIp,nmIp))
550  fatal("RouterCore:run: could not setup boot socket\n");
551  string s1;
552  cout << "sending boot request to " << Np4d::ip2string(nmIp,s1)
553  << endl;
554  CtlPkt cp(CtlPkt::BOOT_ROUTER,CtlPkt::REQUEST,0);
555  if (!sendCpReq(cp,nmAdr))
556  fatal("RouterCore::run: could not send boot request\n");
557  }
558 
559  uint64_t statsTime = 0; // time statistics were last processed
560  bool didNothing;
561  int controlCount = 20; // used to limit overhead of control
562  // packet processing
563  queue<int> ctlQ; // queue for control packets
564 
565  now = Misc::getTimeNs();
566  finishTime *= 1000000000; // convert from seconds to ns
567  while (finishTime == 0 || now < finishTime) {
568  didNothing = true;
569 
570  // input processing
571  pktx px = iop->receive();
572  if (px != 0) {
573  didNothing = false;
574  Packet& p = ps->getPacket(px);
575  int ptype = p.type;
576  pktLog->log(px,p.inLink,false,now);
577  int ctx = ctt->getComtIndex(p.comtree);
578  if (!pktCheck(px,ctx)) {
579  ps->free(px);
580  } else if (booting) {
581  handleCtlPkt(px);
582  } else if (ptype == Forest::CLIENT_DATA) {
583  forward(px,ctx);
584  } else if (ptype == Forest::SUB_UNSUB) {
585  subUnsub(px,ctx);
586  } else if (ptype == Forest::RTE_REPLY) {
587  handleRteReply(px,ctx);
588  } else if (ptype == Forest::CONNECT ||
589  ptype == Forest::DISCONNECT) {
590  handleConnDisc(px);
591  } else if (p.dstAdr != myAdr) {
592  forward(px,ctx);
593  } else {
594  ctlQ.push(px);
595  }
596  }
597 
598  // output processing
599  int lnk;
600  while ((px = qm->deq(lnk, now)) != 0) {
601  didNothing = false;
602  pktLog->log(px,lnk,true,now);
603  iop->send(px,lnk);
604  }
605 
606  // control packet processing
607  if (!ctlQ.empty() && (didNothing || --controlCount <= 0)) {
608  handleCtlPkt(ctlQ.front());
609  ctlQ.pop();
610  controlCount = 20; // do one control packet for
611  // every 20 iterations when busy
612  didNothing = false;
613  }
614 
615  // every 300 ms, update statistics and check for un-acked
616  // control packets
617  if (now - statsTime > 300000000) {
618  sm->record(now);
619  statsTime = now;
620  resendCpReq();
621  didNothing = false;
622  }
623 
624  // if did nothing on that pass, sleep for a millisecond.
625  if (didNothing) { usleep(1000); }
626 
627  // update current time
628  now = Misc::getTimeNs();
629  }
630 
631  // write out recorded events
632  // pktLog->write(cout);
633  cout << endl;
634  cout << sm->iPktCnt(0) << " packets received, "
635  << sm->oPktCnt(0) << " packets sent\n";
636  cout << sm->iPktCnt(-1) << " from routers, "
637  << sm->oPktCnt(-1) << " to routers\n";
638  cout << sm->iPktCnt(-2) << " from clients, "
639  << sm->oPktCnt(-2) << " to clients\n";
640 }
641 
647 bool RouterCore::pktCheck(pktx px, int ctx) {
648  Packet& p = ps->getPacket(px);
649  // check version and length
650  if (p.version != Forest::FOREST_VERSION) {
651  return false;
652  }
653  if (p.length != p.bufferLen || p.length < Forest::HDR_LENG) {
654  return false;
655  }
656  if (booting) {
657  return p.tunIp == nmIp && p.type == Forest::NET_SIG
659  }
660  if (p.type == Forest::CONNECT || p.type == Forest::DISCONNECT)
661  return (p.length == Forest::OVERHEAD+8);
662 
663  if (!ctt->validComtIndex(ctx)) {
664  return false;
665  }
666  fAdr_t adr = p.dstAdr;
667  if (!Forest::validUcastAdr(adr) && !Forest::mcastAdr(adr)) {
668  return false;
669  }
670 
671  int inLink = p.inLink;
672  if (inLink == 0) return false;
673  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),inLink);
674  if (cLnk == 0) {
675  return false;
676  }
677 
678  // extra checks for packets from untrusted peers
679  if (lt->getPeerType(inLink) < Forest::TRUSTED) {
680  // check for spoofed source address
681  if (lt->getPeerAdr(inLink) != p.srcAdr) return false;
682  // and that destination restrictions are respected
683  fAdr_t dest = ctt->getDest(cLnk);
684  if (dest!=0 && p.dstAdr != dest && p.dstAdr != myAdr)
685  return false;
686  // verify that type is valid
687  Forest::ptyp_t ptype = p.type;
688  if (ptype != Forest::CLIENT_DATA &&
689  ptype != Forest::CONNECT && ptype != Forest::DISCONNECT &&
690  ptype != Forest::SUB_UNSUB && ptype != Forest::CLIENT_SIG)
691  return false;
692  int comt = ctt->getComtree(ctx);
693  if ((ptype == Forest::CONNECT || ptype == Forest::DISCONNECT) &&
694  comt != (int) Forest::CONNECT_COMT)
695  return false;
696  if (ptype == Forest::CLIENT_SIG &&
697  comt != (int) Forest::CLIENT_SIG_COMT)
698  return false;
699  }
700  return true;
701 }
702 
712 void RouterCore::forward(pktx px, int ctx) {
713  Packet& p = ps->getPacket(px);
714  int rtx = rt->getRteIndex(p.comtree,p.dstAdr);
715  if (rtx != 0) { // valid route case
716  // reply to route request
717  if ((p.flags & Forest::RTE_REQ)) {
718  sendRteReply(px,ctx);
719  p.flags = (p.flags & (~Forest::RTE_REQ));
720  p.pack();
721  p.hdrErrUpdate();
722  }
723  if (Forest::validUcastAdr(p.dstAdr)) {
724  int rcLnk = rt->getLink(rtx);
725  int lnk = ctt->getLink(rcLnk);
726  int qid = ctt->getLinkQ(rcLnk);
727  if (lnk == p.inLink || !qm->enq(px,qid,now)) {
728  ps->free(px);
729  }
730  return;
731  }
732  // multicast data packet
733  multiSend(px,ctx,rtx);
734  return;
735  }
736  // no valid route
737 // think about suppressing flooding, if address is in range for this router
738  if (Forest::validUcastAdr(p.dstAdr)) {
739  // send to neighboring routers in comtree
741  p.pack(); p.hdrErrUpdate();
742  }
743  multiSend(px,ctx,rtx);
744  return;
745 }
756 void RouterCore::multiSend(pktx px, int ctx, int rtx) {
757  int qvec[nLnks]; int n = 0;
758  Packet& p = ps->getPacket(px);
759 
760  int inLink = p.inLink;
761  if (Forest::validUcastAdr(p.dstAdr)) {
762  // flooding a unicast packet to neighboring routers
763  int myZip = Forest::zipCode(myAdr);
764  int pZip = Forest::zipCode(p.dstAdr);
765  set<int>& rtrLinks = ctt->getRtrLinks(ctx);
766  set<int>::iterator lp;
767  for (lp = rtrLinks.begin(); lp != rtrLinks.end(); lp++) {
768  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
769  int peerZip = Forest::zipCode(lt->getPeerAdr(lnk));
770  if (pZip == myZip && peerZip != myZip) continue;
771  if (lnk == inLink) continue;
772  qvec[n++] = ctt->getLinkQ(rcLnk);
773  }
774  } else {
775  // forwarding a multicast packet
776  // first identify neighboring core routers to get copies
777  int pLink = ctt->getPlink(ctx);
778  set<int>& coreLinks = ctt->getCoreLinks(ctx);
779  set<int>::iterator lp;
780  for (lp = coreLinks.begin(); lp != coreLinks.end(); lp++) {
781  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
782  if (lnk == inLink || lnk == pLink) continue;
783  qvec[n++] = ctt->getLinkQ(rcLnk);
784  }
785  // now copy for parent
786  if (pLink != 0 && pLink != inLink) {
787  qvec[n++] = ctt->getLinkQ(ctt->getPCLink(ctx));
788  }
789  // now, copies for subscribers if any
790  if (rtx != 0) {
791  set<int>& subLinks = rt->getSubLinks(rtx);
792  for (lp = subLinks.begin(); lp !=subLinks.end(); lp++) {
793  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
794  if (lnk == inLink) continue;
795  qvec[n++] = ctt->getLinkQ(rcLnk);
796  }
797  }
798  }
799 
800  if (n == 0) { ps->free(px); return; }
801 
802  // make copies and queue them
803  pktx px1 = px;
804  for (int i = 0; i < n-1; i++) { // process first n-1 copies
805  if (qm->enq(px1,qvec[i],now)) {
806  px1 = ps->clone(px);
807  }
808  }
809  // process last copy
810  if (!qm->enq(px1,qvec[n-1],now)) {
811  ps->free(px1);
812  }
813 }
814 
821 void RouterCore::sendRteReply(pktx px, int ctx) {
822  Packet& p = ps->getPacket(px);
823 
824  pktx px1 = ps->alloc();
825  Packet& p1 = ps->getPacket(px1);
826  p1.length = Forest::HDR_LENG + 8;
827  p1.type = Forest::RTE_REPLY;
828  p1.flags = 0;
829  p1.comtree = p.comtree;
830  p1.srcAdr = myAdr;
831  p1.dstAdr = p.srcAdr;
832 
833  p1.pack();
834  (p1.payload())[0] = htonl(p.dstAdr);
835  p1.hdrErrUpdate(); p.payErrUpdate();
836 
837  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),p.inLink);
838  qm->enq(px1,ctt->getLinkQ(cLnk),now);
839 }
840 
849 void RouterCore::handleRteReply(pktx px, int ctx) {
850  Packet& p = ps->getPacket(px);
851  int rtx = rt->getRteIndex(p.comtree, p.dstAdr);
852  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),p.inLink);
853  if ((p.flags & Forest::RTE_REQ) && rtx != 0)
854  sendRteReply(px,ctx);
855  int adr = ntohl((p.payload())[0]);
856  if (Forest::validUcastAdr(adr) &&
857  rt->getRteIndex(p.comtree,adr) == 0) {
858  rt->addEntry(p.comtree,adr,cLnk);
859  }
860  if (rtx == 0) {
861  // send to neighboring routers in comtree
863  p.pack(); p.hdrErrUpdate();
864  multiSend(px,ctx,rtx);
865  return;
866  }
867  int dcLnk = rt->getLink(rtx); int dLnk = ctt->getLink(dcLnk);
868  if (lt->getPeerType(dLnk) != Forest::ROUTER || !qm->enq(px,dLnk,now))
869  ps->free(px);
870  return;
871 }
872 
880 /*
881 void RouterCore::subUnsub(pktx px, int ctx) {
882  Packet& p = ps->getPacket(px);
883  uint32_t *pp = p.payload();
884 
885  // add/remove branches from routes
886  // if non-core node, also propagate requests upward as
887  // appropriate
888  int comt = ctt->getComtree(ctx);
889  int inLink = p.inLink;
890  int cLnk = ctt->getComtLink(comt,inLink);
891  // ignore subscriptions from the parent or core neighbors
892  if (inLink == ctt->getPlink(ctx) || ctt->isCoreLink(cLnk)) {
893  ps->free(px); return;
894  }
895  bool propagate = false;
896  int rtx; fAdr_t addr;
897 
898  // add subscriptions
899  int addcnt = ntohl(pp[0]);
900  if (addcnt < 0 || addcnt > 350 ||
901  Forest::OVERHEAD + (addcnt + 2)*4 > p.length) {
902  ps->free(px); return;
903  }
904  for (int i = 1; i <= addcnt; i++) {
905  addr = ntohl(pp[i]);
906  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
907  rtx = rt->getRteIndex(comt,addr);
908  if (rtx == 0) {
909  rtx = rt->addEntry(comt,addr,cLnk);
910  propagate = true;
911  } else if (!rt->isLink(rtx,cLnk)) {
912  rt->addLink(rtx,cLnk);
913  pp[i] = 0; // so, parent will ignore
914  }
915  }
916  // remove subscriptions
917  int dropcnt = ntohl(pp[addcnt+1]);
918  if (dropcnt < 0 || addcnt + dropcnt > 350 ||
919  Forest::OVERHEAD + (addcnt + dropcnt + 2)*4 > p.length) {
920  ps->free(px); return;
921  }
922  for (int i = addcnt + 2; i <= addcnt + dropcnt + 1; i++) {
923  addr = ntohl(pp[i]);
924  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
925  rtx = rt->getRteIndex(comt,addr);
926  if (rtx == 0) continue;
927  rt->removeLink(rtx,cLnk);
928  if (rt->noLinks(rtx)) {
929  rt->removeEntry(rtx);
930  propagate = true;
931  } else {
932  pp[i] = 0;
933  }
934  }
935  // propagate subscription packet to parent if not a core node
936  if (propagate && !ctt->inCore(ctx) && ctt->getPlink(ctx) != 0) {
937  p.payErrUpdate();
938  int qid = ctt->getLinkQ(ctt->getPCLink(ctx));
939  if (qm->enq(px,qid,now)) {
940  return;
941  }
942  }
943  ps->free(px); return;
944 }
945 
946 */
947 
948 
949 void RouterCore::subUnsub(pktx px, int ctx) {
950  Packet& p = ps->getPacket(px);
951  uint32_t *pp = p.payload();
952 
953 
954  // add/remove branches from routes
955  // if non-core node, also propagate requests upward as
956  // appropriate
957  int comt = ctt->getComtree(ctx);
958  int inLink = p.inLink;
959  int cLnk = ctt->getComtLink(comt,inLink);
960  uint64_t seq = ntohl(pp[0]);
961  seq <<= 32; seq |= ntohl(pp[1]);
962  // process ack from parent router - just remove packet from pending map
963  if ((p.flags & Forest::ACK_FLAG) != 0) {
964  map<uint64_t,CpInfo>::iterator it = pending->find(seq);
965  if (it == pending->end()) {
966  // this is a reply to a request we never sent, or
967  // possibly, a reply to a request we gave up on
968  ps->free(px);
969  return;
970  }
971  pending->erase(it); ps->free(px); return;
972  }
973  // ignore subscriptions from the parent or core neighbors
974  if (inLink == ctt->getPlink(ctx) || ctt->isCoreLink(cLnk)) {
975  ps->free(px); return;
976  }
977 
978  // make copy to be used for ack
979  pktx copy = ps->fullCopy(px);
980  Packet& p1 = ps->getPacket(copy);
981 
982  bool propagate = false;
983  int rtx; fAdr_t addr;
984 
985  // add subscriptions
986  int addcnt = ntohl(pp[2]);
987  if (addcnt < 0 || addcnt > 350 ||
988  Forest::OVERHEAD + (addcnt + 4)*4 > p.length) {
989  ps->free(px); ps->free(copy); return;
990  }
991  for (int i = 3; i <= addcnt + 2; i++) {
992  addr = ntohl(pp[i]);
993  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
994  rtx = rt->getRteIndex(comt,addr);
995  if (rtx == 0) {
996  rtx = rt->addEntry(comt,addr,cLnk);
997  propagate = true;
998  } else if (!rt->isLink(rtx,cLnk)) {
999  rt->addLink(rtx,cLnk);
1000  pp[i] = 0; // so, parent will ignore
1001  }
1002  }
1003  // remove subscriptions
1004  int dropcnt = ntohl(pp[addcnt+3]);
1005  if (dropcnt < 0 || addcnt + dropcnt > 350 ||
1006  Forest::OVERHEAD + (addcnt + dropcnt + 4)*4 > p.length) {
1007  ps->free(px); ps->free(copy); return;
1008  }
1009  for (int i = addcnt + 4; i <= addcnt + dropcnt + 3; i++) {
1010  addr = ntohl(pp[i]);
1011  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
1012  rtx = rt->getRteIndex(comt,addr);
1013  if (rtx == 0) continue;
1014  rt->removeLink(rtx,cLnk);
1015  if (rt->noLinks(rtx)) {
1016  rt->removeEntry(rtx);
1017  propagate = true;
1018  } else {
1019  pp[i] = 0;
1020  }
1021  }
1022  // propagate subscription packet to parent if not a core node
1023  if (propagate && !ctt->inCore(ctx) && ctt->getPlink(ctx) != 0) {
1024  pair<uint64_t,CpInfo> cpp;
1025  cpp.first = seqNum;
1026  pp[0] = htonl((uint32_t) (seqNum >> 32));
1027  pp[1] = htonl((uint32_t) (seqNum & 0xffffffff));
1028  seqNum++;
1029  //change srcAdr of outgoing subscription packet
1030  p.srcAdr = myAdr;
1031  p.dstAdr = lt->getPeerAdr(ctt->getPlink(ctx));
1032  p.pack();
1033  cpp.second.px = px; cpp.second.nSent = 1;
1034  cpp.second.timestamp = now;
1035  pending->insert(cpp);
1036  //propagate
1037  p.payErrUpdate();
1038  int qid = ctt->getLinkQ(ctt->getPCLink(ctx));
1039  if (!qm->enq(px,qid,now)) ps->free(px);
1040  } else {
1041  ps->free(px);
1042  }
1043  // send ack back to sender
1044  // note that we send ack before getting ack from sender
1045  // this is by design
1046  p1.flags |= Forest::ACK_FLAG;
1047  p1.dstAdr = p1.srcAdr; p1.srcAdr = myAdr;
1048  p1.pack();
1049  int qid = ctt->getLinkQ(cLnk);
1050  if (!qm->enq(copy,qid,now)) ps->free(copy);
1051  return;
1052 }
1053 
1058  Packet& p = ps->getPacket(px);
1059  int inLnk = p.inLink;
1060 
1061  if (p.srcAdr != lt->getPeerAdr(inLnk) ||
1062  p.length != Forest::OVERHEAD + 8) {
1063  ps->free(px); return;
1064  }
1065  uint64_t nonce = ntohl(p.payload()[0]);
1066  nonce <<= 32;
1067  nonce |= ntohl(p.payload()[1]);
1068  if (nonce != lt->getNonce(inLnk)) { ps->free(px); return; }
1069  if ((p.flags & Forest::ACK_FLAG) != 0) {
1070  uint64_t x = 1; x <<= 63; x |= nonce;
1071  pending->erase(x); ps->free(px); return;
1072  }
1073  if (p.type == Forest::CONNECT) {
1074  if (lt->isConnected(inLnk) && !lt->revertEntry(inLnk)) {
1075  ps->free(px); return;
1076  }
1077  if (!lt->remapEntry(inLnk,p.tunIp,p.tunPort)) {
1078  ps->free(px); return;
1079  }
1080  lt->setConnectStatus(inLnk,true);
1081  if (nmAdr != 0 && lt->getPeerType(inLnk) == Forest::CLIENT) {
1082  CtlPkt cp(CtlPkt::CLIENT_CONNECT,CtlPkt::REQUEST,0);
1083  cp.adr1 = p.srcAdr; cp.adr2 = myAdr;
1084  sendCpReq(cp,nmAdr);
1085  }
1086  } else if (p.type == Forest::DISCONNECT) {
1087  lt->setConnectStatus(inLnk,false);
1088  lt->revertEntry(inLnk);
1089  if (nmAdr != 0 && lt->getPeerType(inLnk) == Forest::CLIENT) {
1090  dropLink(inLnk);
1091  CtlPkt cp(CtlPkt::CLIENT_DISCONNECT,CtlPkt::REQUEST,0);
1092  cp.adr1 = p.srcAdr; cp.adr2 = myAdr;
1093  sendCpReq(cp,nmAdr);
1094  }
1095  }
1096  // send ack back to sender
1097  p.flags |= Forest::ACK_FLAG; p.dstAdr = p.srcAdr; p.srcAdr = myAdr;
1098  p.pack();
1099  pktLog->log(px,inLnk,true,now);
1100  iop->send(px,inLnk);
1101  return;
1102 }
1103 
1109  Packet& p = ps->getPacket(px);
1110  CtlPkt cp(p.payload(), p.length - Packet::OVERHEAD);
1111 
1112  if (p.type != Forest::NET_SIG || p.comtree != Forest::NET_SIG_COMT) {
1113  ps->free(px); return;
1114  }
1115  if (!cp.unpack()) {
1116  string s;
1117  cerr << "RouterCore::handleCtlPkt: misformatted control "
1118  " packet\n" << p.toString(s);
1119  cp.reset(cp.type,CtlPkt::NEG_REPLY,cp.seqNum);
1120  cp.mode = CtlPkt::NEG_REPLY;
1121  cp.errMsg = "misformatted control packet";
1122  returnToSender(px,cp);
1123  return;
1124  }
1125  if (cp.mode != CtlPkt::REQUEST) {
1126  handleCpReply(px,cp); return;
1127  }
1128 
1129  // Prepare positive reply packet for use where appropriate
1130  CtlPkt reply(cp.type,CtlPkt::POS_REPLY,cp.seqNum);
1131 
1132  switch (cp.type) {
1133 
1134  // configuring logical interfaces
1135  case CtlPkt::ADD_IFACE: addIface(cp,reply); break;
1136  case CtlPkt::DROP_IFACE: dropIface(cp,reply); break;
1137  case CtlPkt::GET_IFACE: getIface(cp,reply); break;
1138  case CtlPkt::MOD_IFACE: modIface(cp,reply); break;
1139  case CtlPkt::GET_IFACE_SET: getIfaceSet(cp,reply); break;
1140 
1141  // configuring links
1142  case CtlPkt::ADD_LINK: addLink(cp,reply); break;
1143  case CtlPkt::DROP_LINK: dropLink(cp,reply); break;
1144  case CtlPkt::GET_LINK: getLink(cp,reply); break;
1145  case CtlPkt::MOD_LINK: modLink(cp,reply); break;
1146  case CtlPkt::GET_LINK_SET: getLinkSet(cp,reply); break;
1147 
1148  // configuring comtrees
1149  case CtlPkt::ADD_COMTREE: addComtree(cp,reply); break;
1150  case CtlPkt::DROP_COMTREE: dropComtree(cp,reply); break;
1151  case CtlPkt::GET_COMTREE: getComtree(cp,reply); break;
1152  case CtlPkt::MOD_COMTREE: modComtree(cp,reply); break;
1153  case CtlPkt::GET_COMTREE_SET: getComtreeSet(cp,reply); break;
1154 
1155  // and comtree links
1156  case CtlPkt::ADD_COMTREE_LINK: addComtreeLink(cp,reply); break;
1157  case CtlPkt::DROP_COMTREE_LINK: dropComtreeLink(cp,reply); break;
1158  case CtlPkt::GET_COMTREE_LINK: getComtreeLink(cp,reply); break;
1159  case CtlPkt::MOD_COMTREE_LINK: modComtreeLink(cp,reply); break;
1160 
1161  // configuring routes
1162  case CtlPkt::ADD_ROUTE: addRoute(cp,reply); break;
1163  case CtlPkt::DROP_ROUTE: dropRoute(cp,reply); break;
1164  case CtlPkt::GET_ROUTE: getRoute(cp,reply); break;
1165  case CtlPkt::MOD_ROUTE: modRoute(cp,reply); break;
1166  case CtlPkt::GET_ROUTE_SET: getRouteSet(cp,reply); break;
1167 
1168  // configuring filters and retrieving pacets
1169  case CtlPkt::ADD_FILTER: addFilter(cp,reply); break;
1170  case CtlPkt::DROP_FILTER: dropFilter(cp,reply); break;
1171  case CtlPkt::GET_FILTER: getFilter(cp,reply); break;
1172  case CtlPkt::MOD_FILTER: modFilter(cp,reply); break;
1173  case CtlPkt::GET_FILTER_SET: getFilterSet(cp,reply); break;
1174  case CtlPkt::GET_LOGGED_PACKETS: getLoggedPackets(cp,reply); break;
1175 
1176  // setting parameters
1177  case CtlPkt::SET_LEAF_RANGE: setLeafRange(cp,reply); break;
1178 
1179  default:
1180  cerr << "unrecognized control packet type " << cp.type
1181  << endl;
1182  reply.errMsg = "invalid control packet for router";
1183  reply.mode = CtlPkt::NEG_REPLY;
1184  break;
1185  }
1186 
1187  returnToSender(px,reply);
1188 
1189  return;
1190 }
1191 
1204  int iface = cp.iface;
1205  RateSpec rs(max(min(cp.rspec1.bitRateUp, Forest::MAXBITRATE),
1207  max(min(cp.rspec1.bitRateDown,Forest::MAXBITRATE),
1209  max(min(cp.rspec1.pktRateUp, Forest::MAXPKTRATE),
1211  max(min(cp.rspec1.pktRateDown,Forest::MAXPKTRATE),
1213  if (ift->valid(iface)) {
1214  if (cp.iface != ift->getIpAdr(iface) ||
1215  !rs.equals(ift->getRates(iface))) {
1216  reply.errMsg = "add iface: requested interface "
1217  "conflicts with existing interface";
1218  reply.mode = CtlPkt::NEG_REPLY;
1219  return false;
1220  }
1221  // means reply to earlier add iface was lost
1222  reply.ip1 = ift->getIpAdr(iface);
1223  reply.port1 = ift->getPort(iface);
1224  return true;
1225  } else if (!ift->addEntry(iface, cp.ip1, 0, rs)) {
1226  reply.errMsg = "add iface: cannot add interface";
1227  reply.mode = CtlPkt::NEG_REPLY;
1228  return false;
1229  } else if (!iop->setup(iface)) {
1230  reply.errMsg = "add iface: could not setup interface";
1231  reply.mode = CtlPkt::NEG_REPLY;
1232  return false;
1233  }
1234  reply.ip1 = ift->getIpAdr(iface);
1235  reply.port1 = ift->getPort(iface);
1236  return true;
1237 }
1238 
1239 bool RouterCore::dropIface(CtlPkt& cp, CtlPkt& reply) {
1240  ift->removeEntry(cp.iface);
1241  return true;
1242 }
1243 
1244 bool RouterCore::getIface(CtlPkt& cp, CtlPkt& reply) {
1245  int iface = cp.iface;
1246  if (ift->valid(iface)) {
1247  reply.iface = iface;
1248  reply.ip1 = ift->getIpAdr(iface);
1249  reply.port1 = ift->getPort(iface);
1250  reply.rspec1 = ift->getRates(iface);
1251  reply.rspec2 = ift->getAvailRates(iface);
1252  return true;
1253  }
1254  reply.errMsg = "get iface: invalid interface";
1255  reply.mode = CtlPkt::NEG_REPLY;
1256  return false;
1257 }
1258 
1259 bool RouterCore::modIface(CtlPkt& cp, CtlPkt& reply) {
1260  int iface = cp.iface;
1261  if (ift->valid(iface)) {
1262  ift->getRates(iface) = cp.rspec1;
1263  return true;
1264  }
1265  reply.errMsg = "mod iface: invalid interface";
1266  reply.mode = CtlPkt::NEG_REPLY;
1267  return false;
1268 }
1269 
1281  int ifIndex = cp.index1;
1282  if (ifIndex == 0) {
1283  ifIndex = ift->firstIface(); // 0 means start with first iface
1284  } else if (!ift->valid(ifIndex)) {
1285  reply.errMsg = "get iface set: invalid iface number";
1286  reply.mode = CtlPkt::NEG_REPLY;
1287  return false;
1288  }
1289  reply.index1 = ifIndex;
1290  int count = min(10,cp.count);
1291  int i = 0;
1292  while (i < count && ifIndex != 0) {
1293  string s; ift->entry2string(ifIndex,s); //s.push_back('\n');
1294  reply.stringData.append(s);
1295  if (reply.stringData.length() > 1300) {
1296  reply.errMsg = "get iface set: error while formatting "
1297  "reply";
1298  reply.mode = CtlPkt::NEG_REPLY;
1299  return false;
1300  }
1301  i++; ifIndex = ift->nextIface(ifIndex);
1302  }
1303  reply.index2 = ifIndex; reply.count = i;
1304  return true;
1305 }
1306 
1307 bool RouterCore::addLink(CtlPkt& cp, CtlPkt& reply) {
1308  Forest::ntyp_t peerType = cp.nodeType;
1309  if (peerType == Forest::ROUTER && cp.adr1 == 0) {
1310  reply.errMsg = "add link: adding link to router, but no peer "
1311  "address supplied";
1312  reply.mode = CtlPkt::NEG_REPLY;
1313  return false;
1314  }
1315  int iface = cp.iface;
1316 
1317  int xlnk = lt->lookup(cp.ip1,cp.port1);
1318  if (xlnk != 0 || (cp.link != 0 && lt->valid(cp.link))) {
1319  if (cp.link != xlnk ||
1320  (peerType != lt->getPeerType(xlnk)) ||
1321  (cp.iface != lt->getIface(xlnk)) ||
1322  (cp.adr1 != 0 && cp.adr1 != lt->getPeerAdr(xlnk)) ||
1323  (cp.ip1 != 0 && cp.ip1 != ift->getIpAdr(iface)) ||
1324  (cp.port1 != 0 && cp.port1 != ift->getPort(iface))) {
1325  reply.errMsg = "add link: new link conflicts "
1326  "with existing link";
1327  reply.mode = CtlPkt::NEG_REPLY;
1328  return false;
1329  }
1330  // assume response to previous add link was lost
1331  reply.link = xlnk;
1332  reply.adr1 = lt->getPeerAdr(xlnk);
1333  reply.ip1 = lt->getPeerIpAdr(xlnk);
1334  return true;
1335  }
1336 
1337  // first ensure that the interface has enough
1338  // capacity to support a new link of minimum capacity
1341  RateSpec& availRates = ift->getAvailRates(iface);
1342  if (!rs.leq(availRates)) {
1343  reply.errMsg = "add link: requested link "
1344  "exceeds interface capacity";
1345  reply.mode = CtlPkt::NEG_REPLY;
1346  return false;
1347  }
1348 
1349  // setting up link
1350  // case 1: adding link to leaf; peer (ip,port) not known, use nonce
1351  // subcase - lnk, peer forest address is known
1352  // (for preconfigured leaf)
1353  // subcase - lnk, peer address to be assigned by router
1354  // case 2: adding link to router not yet up; port not known, use nonce
1355  // lnk, peer address specified
1356  // case 3: adding link to a router that is already up
1357  // lnk, peer address specified, peer (ip,port) specified
1358 
1359  // add table entry with (ip,port) or nonce
1360  // note: when lt->addEntry succeeds, link rates are
1361  // initialized to Forest minimum rates
1362  int lnk = lt->addEntry(cp.link,cp.ip1,cp.port1,cp.nonce);
1363  if (lnk == 0) {
1364  reply.errMsg = "add link: cannot add requested link";
1365  reply.mode = CtlPkt::NEG_REPLY;
1366  return false;
1367  }
1368 
1369  if (peerType == Forest::ROUTER) {
1370  lt->setPeerAdr(lnk,cp.adr1);
1371  } else { // case 1
1372  fAdr_t peerAdr = 0;
1373  if (cp.adr1 == 0) peerAdr = allocLeafAdr();
1374  else if (allocLeafAdr(cp.adr1)) peerAdr = cp.adr1;
1375  if (peerAdr == 0) {
1376  lt->removeEntry(lnk);
1377  reply.errMsg = "add link: cannot add link using "
1378  "specified address";
1379  reply.mode = CtlPkt::NEG_REPLY;
1380  return false;
1381  }
1382  lt->setPeerAdr(lnk,peerAdr);
1383  }
1384 
1385  availRates.subtract(rs);
1386  lt->setIface(lnk,iface);
1387  lt->setPeerType(lnk,peerType);
1388  lt->setConnectStatus(lnk,false);
1389  sm->clearLnkStats(lnk);
1390  if (peerType == Forest::ROUTER && cp.ip1 != 0 && cp.port1 != 0) {
1391  // link to a router that's already up, so connect
1393  }
1394 
1395  reply.link = lnk;
1396  reply.adr1 = lt->getPeerAdr(lnk);
1397  return true;
1398 }
1399 
1400 bool RouterCore::dropLink(CtlPkt& cp, CtlPkt& reply) {
1401  dropLink(cp.link, cp.adr1);
1402  return true;
1403 }
1404 
1413 void RouterCore::dropLink(int lnk, fAdr_t peerAdr) {
1414  if (lnk == 0) lnk = lt->lookup(peerAdr);
1415  int *comtVec = new int[lt->getComtSet(lnk).size()];
1416  int i = 0;
1417  for (int comt : lt->getComtSet(lnk)) comtVec[i++] = comt;
1418  while (--i >= 0) {
1419  int ctx = comtVec[i];
1420  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),lnk);
1421  dropComtreeLink(ctx,lnk,cLnk);
1422  }
1423  int iface = lt->getIface(lnk);
1424  ift->getAvailRates(iface).add(lt->getRates(lnk));
1425  lt->removeEntry(lnk);
1426  freeLeafAdr(lt->getPeerAdr(lnk));
1427 }
1428 
1429 bool RouterCore::getLink(CtlPkt& cp, CtlPkt& reply) {
1430  int link = cp.link;
1431  if (lt->valid(link)) {
1432  reply.link = link;
1433  reply.iface = lt->getIface(link);
1434  reply.ip1 = lt->getPeerIpAdr(link);
1435  reply.nodeType = lt->getPeerType(link);
1436  reply.port1 = lt->getPeerPort(link);
1437  reply.adr1 = lt->getPeerAdr(link);
1438  reply.rspec1 = lt->getRates(link);
1439  reply.rspec2 = lt->getAvailRates(link);
1440  reply.count = lt->getComtCount(link);
1441  return true;
1442  }
1443  reply.errMsg = "get link: invalid link number";
1444  reply.mode = CtlPkt::NEG_REPLY;
1445  return false;
1446 }
1447 
1459  int lnk = cp.index1;
1460  if (lnk == 0) {
1461  lnk = lt->firstLink(); // 0 means start with first link
1462  } else if (!lt->valid(lnk)) {
1463  reply.errMsg = "get link set: invalid link number";
1464  reply.mode = CtlPkt::NEG_REPLY;
1465  return false;
1466  }
1467  reply.index1 = lnk;
1468  int count = min(10,cp.count);
1469  int i = 0;
1470  while (i < count && lnk != 0) {
1471  string s; lt->link2string(lnk,s); s.push_back('\n');
1472  reply.stringData.append(s);
1473  if (reply.stringData.length() > 1300) {
1474  reply.errMsg = "get link set: error while formatting "
1475  "reply";
1476  reply.mode = CtlPkt::NEG_REPLY;
1477  return false;
1478  }
1479  i++; lnk = lt->nextLink(lnk);
1480  }
1481  reply.index2 = lnk; reply.count = i;
1482  return true;
1483 }
1484 
1485 bool RouterCore::modLink(CtlPkt& cp, CtlPkt& reply) {
1486  int link = cp.link;
1487  if (!lt->valid(link)) {
1488  reply.errMsg = "get link: invalid link number";
1489  reply.mode = CtlPkt::NEG_REPLY;
1490  return false;
1491  }
1492  reply.link = link;
1493  int iface = lt->getIface(link);
1494  if (cp.rspec1.isSet()) {
1495  RateSpec& linkRates = lt->getRates(link);
1496  RateSpec& ifAvail = ift->getAvailRates(iface);
1497  RateSpec delta = cp.rspec1;
1498  delta.subtract(linkRates);
1499  if (!delta.leq(ifAvail)) {
1500  string s;
1501  reply.errMsg = "mod link: request "
1502  + cp.rspec1.toString(s) +
1503  "exceeds interface capacity";
1504  reply.mode = CtlPkt::NEG_REPLY;
1505  return false;
1506  }
1507  ifAvail.subtract(delta);
1508  linkRates = cp.rspec1;
1509  qm->setLinkRates(link,cp.rspec1);
1510  cp.rspec1.scale(.9); // allocate at most 90% of link
1511  lt->getAvailRates(link) = cp.rspec1;
1512  }
1513  return true;
1514 }
1515 
1516 bool RouterCore::addComtree(CtlPkt& cp, CtlPkt& reply) {
1517  int comt = cp.comtree;
1518  if(ctt->validComtree(comt) || ctt->addEntry(comt) != 0)
1519  return true;
1520  reply.errMsg = "add comtree: cannot add comtree";
1521  reply.mode = CtlPkt::NEG_REPLY;
1522  return false;
1523 }
1524 
1525 bool RouterCore::dropComtree(CtlPkt& cp, CtlPkt& reply) {
1526  int comt = cp.comtree;
1527  int ctx = ctt->getComtIndex(comt);
1528  if (!ctt->validComtIndex(ctx))
1529  return true; // so dropComtree op is idempotent
1530 
1531  // remove all routes involving this comtree
1532  // also degisters each route in the comtree table
1533  rt->purgeRoutes(comt);
1534 
1535  // remove all the comtree links
1536  // first, copy out the comtree links, then remove them
1537  // two step process is needed because dropComtreeLink modifies linkSet
1538  set<int>& linkSet = ctt->getLinks(ctx);
1539  set<int>::iterator pp;
1540  int *clnks = new int[linkSet.size()]; int i = 0;
1541  for (pp = linkSet.begin(); pp != linkSet.end(); pp++) clnks[i++] = *pp;
1542  while (--i >= 0) {
1543  dropComtreeLink(ctx,ctt->getLink(clnks[i]),clnks[i]);
1544  }
1545  delete [] clnks;
1546 
1547  ctt->removeEntry(ctx); // and finally drop entry in comtree table
1548  return true;
1549 }
1550 
1551 bool RouterCore::getComtree(CtlPkt& cp, CtlPkt& reply) {
1552  comt_t comt = cp.comtree;
1553  int ctx = ctt->getComtIndex(comt);
1554  if (ctx == 0) {
1555  reply.errMsg = "get comtree: invalid comtree";
1556  reply.mode = CtlPkt::NEG_REPLY;
1557  return false;
1558  }
1559  reply.comtree = comt;
1560  reply.coreFlag = ctt->inCore(ctx);
1561  reply.link = ctt->getPlink(ctx);
1562  reply.count = ctt->getLinkCount(ctx);
1563  return true;
1564 }
1565 
1577  int comtIndex = cp.index1;
1578  if (comtIndex == 0) {
1579  comtIndex = ctt->firstComtIndex(); // 0 means first comtree
1580  } else if (!ctt->validComtIndex(comtIndex)) {
1581  reply.errMsg = "get comtree set: invalid comtree number";
1582  reply.mode = CtlPkt::NEG_REPLY;
1583  return false;
1584  }
1585  reply.index1 = comtIndex;
1586  int count = min(10,cp.count);
1587  int i = 0;
1588  while (i < count && comtIndex != 0) {
1589  string s; ctt->entry2string(comtIndex,s); //s.push_back('\n');
1590  reply.stringData.append(s);
1591  if (reply.stringData.length() > 1300) {
1592  reply.errMsg = "get comtee set: error while "
1593  "formatting reply";
1594  reply.mode = CtlPkt::NEG_REPLY;
1595  return false;
1596  }
1597  i++; comtIndex = ctt->nextComtIndex(comtIndex);
1598  }
1599  reply.index2 = comtIndex; reply.count = i;
1600  return true;
1601 }
1602 
1603 bool RouterCore::modComtree(CtlPkt& cp, CtlPkt& reply) {
1604  comt_t comt = cp.comtree;
1605  int ctx = ctt->getComtIndex(comt);
1606  if (ctx != 0) {
1607  if (cp.coreFlag >= 0)
1608  ctt->setCoreFlag(ctx,cp.coreFlag);
1609  if (cp.link != 0) {
1610  int plnk = cp.link;
1611  if (plnk != 0 && !ctt->isLink(ctx,plnk)) {
1612  reply.errMsg = "specified link does "
1613  "not belong to comtree";
1614  reply.mode = CtlPkt::NEG_REPLY;
1615  return false;
1616  }
1617  if (plnk != 0 && !ctt->isRtrLink(ctx,plnk)) {
1618  reply.errMsg = "specified link does "
1619  "not connect to a router";
1620  reply.mode = CtlPkt::NEG_REPLY;
1621  return false;
1622  }
1623  ctt->setPlink(ctx,plnk);
1624  }
1625  return true;
1626  }
1627  reply.errMsg = "modify comtree: invalid comtree";
1628  reply.mode = CtlPkt::NEG_REPLY;
1629  return false;
1630 }
1631 
1632 bool RouterCore::addComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1633  comt_t comt = cp.comtree;
1634  int ctx = ctt->getComtIndex(comt);
1635  if (ctx == 0) {
1636  reply.errMsg = "add comtree link: invalid comtree";
1637  reply.mode = CtlPkt::NEG_REPLY;
1638  return false;
1639  }
1640  int lnk = 0;
1641  if (cp.link != 0) {
1642  lnk = cp.link;
1643  } else if (cp.ip1 != 0 && cp.port1 != 0) {
1644  lnk = lt->lookup(cp.ip1, cp.port1);
1645  } else if (cp.adr1 != 0) {
1646  lnk = lt->lookup(cp.adr1);
1647  }
1648  if (!lt->valid(lnk)) {
1649  reply.errMsg = "add comtree link: invalid link or "
1650  "peer IP and port";
1651  reply.mode = CtlPkt::NEG_REPLY;
1652  return false;
1653  }
1654  bool isRtr = (lt->getPeerType(lnk) == Forest::ROUTER);
1655  bool isCore = false;
1656  if (isRtr) {
1657  if (cp.coreFlag < 0) {
1658  reply.errMsg = "add comtree link: must specify "
1659  "core flag on links to routers";
1660  reply.mode = CtlPkt::NEG_REPLY;
1661  return false;
1662  }
1663  isCore = cp.coreFlag;
1664  }
1665  int cLnk = ctt->getComtLink(comt,lnk);
1666  if (cLnk != 0) {
1667  if (ctt->isRtrLink(cLnk) == isRtr &&
1668  ctt->isCoreLink(cLnk) == isCore) {
1669  reply.link = lnk;
1670  return true;
1671  } else {
1672  reply.errMsg = "add comtree link: specified "
1673  "link already in comtree";
1674  reply.mode = CtlPkt::NEG_REPLY;
1675  return false;
1676  }
1677  }
1678  // define new comtree link
1679  if (!ctt->addLink(ctx,lnk,isRtr,isCore)) {
1680  reply.errMsg = "add comtree link: cannot add "
1681  "requested comtree link";
1682  reply.mode = CtlPkt::NEG_REPLY;
1683  return false;
1684  }
1685  cLnk = ctt->getComtLink(comt,lnk);
1686 
1687  // add unicast route to cLnk if peer is a leaf or a router
1688  // in a different zip code
1689  fAdr_t peerAdr = lt->getPeerAdr(lnk);
1690  if (lt->getPeerType(lnk) != Forest::ROUTER) {
1691  int rtx = rt->getRteIndex(comt,peerAdr);
1692  if (rtx == 0) rt->addEntry(comt,peerAdr,cLnk);
1693  } else {
1694  int zipPeer = Forest::zipCode(peerAdr);
1695  if (zipPeer != Forest::zipCode(myAdr)) {
1696  fAdr_t dest = Forest::forestAdr(zipPeer,0);
1697  int rtx = rt->getRteIndex(comt,dest);
1698  if (rtx == 0) rt->addEntry(comt,dest,cLnk);
1699  }
1700  }
1701 
1702  // allocate queue and bind it to lnk and comtree link
1703  int qid = qm->allocQ(lnk);
1704  if (qid == 0) {
1705  ctt->removeLink(ctx,cLnk);
1706  reply.errMsg = "add comtree link: no queues "
1707  "available for link";
1708  reply.mode = CtlPkt::NEG_REPLY;
1709  return false;
1710  }
1711  ctt->setLinkQ(cLnk,qid);
1712 
1713  // adjust rates for link comtree and queue
1716  if (!minRates.leq(lt->getAvailRates(lnk))) {
1717  reply.errMsg = "add comtree link: request "
1718  "exceeds link capacity";
1719  reply.mode = CtlPkt::NEG_REPLY;
1720  return false;
1721  }
1722  lt->getAvailRates(lnk).subtract(minRates);
1723  ctt->getRates(cLnk) = minRates;
1724 
1725  qm->setQRates(qid,minRates);
1726  if (isRtr) qm->setQLimits(qid,500,1000000);
1727  else qm->setQLimits(qid,500,1000000);
1728  sm->clearQuStats(qid);
1729  reply.link = lnk;
1730  return true;
1731 }
1732 
1733 bool RouterCore::dropComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1734  comt_t comt = cp.comtree;
1735  int ctx = ctt->getComtIndex(comt);
1736  if (ctx == 0) {
1737  reply.errMsg = "drop comtree link: invalid comtree";
1738  reply.mode = CtlPkt::NEG_REPLY;
1739  return false;
1740  }
1741  int lnk = 0;
1742  if (cp.link != 0) {
1743  lnk = cp.link;
1744  } else if (cp.ip1 != 0 && cp.port1 != 0) {
1745  lnk = lt->lookup(cp.ip1, cp.port1);
1746  } else if (cp.adr1 != 0) {
1747  lnk = lt->lookup(cp.adr1);
1748  }
1749  if (!lt->valid(lnk)) {
1750  reply.errMsg = "drop comtree link: invalid link "
1751  "or peer IP and port";
1752  reply.mode = CtlPkt::NEG_REPLY;
1753  return false;
1754  }
1755  int cLnk = ctt->getComtLink(comt,lnk);
1756  if (cLnk != 0) {
1757  dropComtreeLink(ctx,lnk,cLnk);
1758  }
1759  return true;
1760 }
1761 
1762 void RouterCore::dropComtreeLink(int ctx, int lnk, int cLnk) {
1763  // release the link bandwidth used by comtree link
1764  lt->getAvailRates(lnk).add(ctt->getRates(cLnk));
1765 
1766  // remove unicast route for this comtree
1767  fAdr_t peerAdr = lt->getPeerAdr(lnk);
1768  int comt = ctt->getComtree(ctx);
1769  if (lt->getPeerType(lnk) != Forest::ROUTER) {
1770  int rtx = rt->getRteIndex(comt,peerAdr);
1771  if (rtx != 0) rt->removeEntry(rtx);
1772  } else {
1773  int zipPeer = Forest::zipCode(peerAdr);
1774  if (zipPeer != Forest::zipCode(myAdr)) {
1775  fAdr_t dest = Forest::forestAdr(zipPeer,0);
1776  int rtx = rt->getRteIndex(comt,dest);
1777  if (rtx != 0) rt->removeEntry(rtx);
1778  }
1779  }
1780  // remove cLnk from multicast routes for this comtree
1781  // must first copy out the routes that are registered for
1782  // cLnk, then remove cLnk from all these routes;
1783  // two step process is needed because the removal of the link from
1784  // the route, also deregisters the route in the comtree table
1785  // causing the rteSet to change
1786  set<int>& rteSet = ctt->getRteSet(cLnk);
1787  set<int>::iterator rp;
1788  int *routes = new int[rteSet.size()];
1789  int i = 0;
1790  for (rp = rteSet.begin(); rp != rteSet.end(); rp++) routes[i++] = *rp;
1791  while (--i >= 0) rt->removeLink(routes[i],cLnk);
1792  delete [] routes;
1793 
1794  // release queue and remove link from comtree
1795  // (which also deregisters comtree with lnk)
1796  int qid = ctt->getLinkQ(cLnk);
1797  qm->freeQ(qid);
1798  if (!ctt->removeLink(ctx,cLnk)) {
1799  cerr << "dropComtreeLink: internal error detected "
1800  "final removeLink failed\n";
1801  }
1802 }
1803 
1804 bool RouterCore::modComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1805  comt_t comt = cp.comtree;
1806  int ctx = ctt->getComtIndex(comt);
1807  if (ctx == 0) {
1808  reply.errMsg = "modify comtree link: invalid comtree";
1809  reply.mode = CtlPkt::NEG_REPLY;
1810  return false;
1811  }
1812  int lnk = cp.link;
1813  if (!lt->valid(lnk)) {
1814  reply.errMsg = "modify comtree link: invalid link number";
1815  reply.mode = CtlPkt::NEG_REPLY;
1816  return false;
1817  }
1818  int cLnk = ctt->getComtLink(comt,lnk);
1819  if (cLnk == 0) {
1820  reply.errMsg = "modify comtree link: specified link "
1821  "not defined in specified comtree";
1822  reply.mode = CtlPkt::NEG_REPLY;
1823  return false;
1824  }
1825 
1826  RateSpec rs = cp.rspec1;
1827  if (!rs.isSet()) return true;
1828  RateSpec diff = rs; diff.subtract(ctt->getRates(cLnk));
1829  if (!diff.leq(lt->getAvailRates(lnk))) {
1830  reply.errMsg = "modify comtree link: new rate spec "
1831  "exceeds available link capacity";
1832  return false;
1833  }
1834  lt->getAvailRates(lnk).subtract(diff);
1835  ctt->getRates(cLnk) = rs;
1836  return true;
1837 }
1838 
1839 bool RouterCore::getComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1840  comt_t comt = cp.comtree;
1841  int ctx = ctt->getComtIndex(comt);
1842  if (ctx == 0) {
1843  reply.errMsg = "get comtree link: invalid comtree";
1844  reply.mode = CtlPkt::NEG_REPLY;
1845  return false;
1846  }
1847  int lnk = cp.link;
1848  if (!lt->valid(lnk)) {
1849  reply.errMsg = "get comtree link: invalid link number";
1850  reply.mode = CtlPkt::NEG_REPLY;
1851  return false;
1852  }
1853  int cLnk = ctt->getComtLink(comt,lnk);
1854  if (cLnk == 0) {
1855  reply.errMsg = "get comtree link: specified link "
1856  "not defined in specified comtree";
1857  reply.mode = CtlPkt::NEG_REPLY;
1858  return false;
1859  }
1860  reply.comtree = comt;
1861  reply.link = lnk;
1862  reply.queue = ctt->getLinkQ(cLnk);
1863  reply.adr1 = ctt->getDest(cLnk);
1864  reply.rspec1 = ctt->getRates(cLnk);
1865 
1866  return true;
1867 }
1868 
1869 bool RouterCore::addRoute(CtlPkt& cp, CtlPkt& reply) {
1870  comt_t comt = cp.comtree;
1871  if (!ctt->validComtree(comt)) {
1872  reply.errMsg = "comtree not defined at this router\n";
1873  reply.mode = CtlPkt::NEG_REPLY;
1874  return false;
1875  }
1876  fAdr_t dest = cp.adr1;
1877  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1878  reply.errMsg = "invalid address\n";
1879  reply.mode = CtlPkt::NEG_REPLY;
1880  return false;
1881  }
1882  int lnk = cp.link;
1883  int cLnk = ctt->getComtLink(comt,lnk);
1884  int rtx = rt->getRteIndex(comt,dest);
1885  if (rtx != 0) {
1886  if ((Forest::validUcastAdr(dest) && rt->getLink(rtx) == cLnk) ||
1887  (Forest::mcastAdr(dest) && rt->isLink(rtx,cLnk))) {
1888  return true;
1889  } else {
1890  reply.errMsg = "add route: requested route "
1891  "conflicts with existing route";
1892  reply.mode = CtlPkt::NEG_REPLY;
1893  return false;
1894  }
1895  } else if (rt->addEntry(comt, dest, lnk)) {
1896  return true;
1897  }
1898  reply.errMsg = "add route: cannot add route";
1899  reply.mode = CtlPkt::NEG_REPLY;
1900  return false;
1901 }
1902 
1903 bool RouterCore::dropRoute(CtlPkt& cp, CtlPkt& reply) {
1904  comt_t comt = cp.comtree;
1905  if (!ctt->validComtree(comt)) {
1906  reply.errMsg = "comtree not defined at this router\n";
1907  reply.mode = CtlPkt::NEG_REPLY;
1908  return false;
1909  }
1910  fAdr_t dest = cp.adr1;
1911  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1912  reply.errMsg = "invalid address\n";
1913  reply.mode = CtlPkt::NEG_REPLY;
1914  return false;
1915  }
1916  int rtx = rt->getRteIndex(comt,dest);
1917  rt->removeEntry(rtx);
1918  return true;
1919 }
1920 
1921 bool RouterCore::getRoute(CtlPkt& cp, CtlPkt& reply) {
1922  comt_t comt = cp.comtree;
1923  if (!ctt->validComtree(comt)) {
1924  reply.errMsg = "comtree not defined at this router\n";
1925  reply.mode = CtlPkt::NEG_REPLY;
1926  return false;
1927  }
1928  fAdr_t dest = cp.adr1;
1929  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1930  reply.errMsg = "invalid address\n";
1931  reply.mode = CtlPkt::NEG_REPLY;
1932  return false;
1933  }
1934  int rtx = rt->getRteIndex(comt,dest);
1935  if (rtx != 0) {
1936  reply.comtree = comt;
1937  reply.adr1 = dest;
1938  if (Forest::validUcastAdr(dest)) {
1939  int lnk = ctt->getLink(rt->getLink(rtx));
1940  reply.link = lnk;
1941  } else {
1942  reply.link = 0;
1943  }
1944  return true;
1945  }
1946  reply.errMsg = "get route: no route for specified address";
1947  reply.mode = CtlPkt::NEG_REPLY;
1948  return false;
1949 }
1950 
1951 bool RouterCore::modRoute(CtlPkt& cp, CtlPkt& reply) {
1952  comt_t comt = cp.comtree;
1953  if (!ctt->validComtree(comt)) {
1954  reply.errMsg = "comtree not defined at this router\n";
1955  reply.mode = CtlPkt::NEG_REPLY;
1956  return false;
1957  }
1958  fAdr_t dest = cp.adr1;
1959  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1960  reply.errMsg = "invalid address\n";
1961  reply.mode = CtlPkt::NEG_REPLY;
1962  return false;
1963  }
1964  int rtx = rt->getRteIndex(comt,dest);
1965  if (rtx != 0) {
1966  if (cp.link != 0) {
1967  if (Forest::mcastAdr(dest)) {
1968  reply.errMsg = "modify route: cannot "
1969  "set link in multicast route";
1970  reply.mode = CtlPkt::NEG_REPLY;
1971  return false;
1972  }
1973  rt->setLink(rtx,cp.link);
1974  }
1975  return true;
1976  }
1977  reply.errMsg = "modify route: invalid route";
1978  reply.mode = CtlPkt::NEG_REPLY;
1979  return false;
1980 }
1981 
1993  int rIndex = cp.index1;
1994  if (rIndex == 0) {
1995  rIndex = rt->firstRteIndex(); // 0 means start with first route
1996  } else if (!rt->validRteIndex(rIndex)) {
1997  reply.errMsg = "get route set: invalid route number";
1998  reply.mode = CtlPkt::NEG_REPLY;
1999  return false;
2000  }
2001  reply.index1 = rIndex;
2002  int count = min(10,cp.count);
2003  int i = 0;
2004  while (i < count && rIndex != 0) {
2005  string s; rt->entry2string(rIndex,s); //s.push_back('\n');
2006  reply.stringData.append(s);
2007  if (reply.stringData.length() > 1300) {
2008  reply.errMsg = "get route set: error while formatting "
2009  "reply";
2010  reply.mode = CtlPkt::NEG_REPLY;
2011  return false;
2012  }
2013  i++; rIndex = rt->nextRteIndex(rIndex);
2014  }
2015  reply.index2 = rIndex; reply.count = i;
2016  return true;
2017 }
2018 
2030  fltx fx = pktLog->addFilter();
2031  if (fx == 0) {
2032  reply.errMsg = "add filter: cannot add filter";
2033  reply.mode = CtlPkt::NEG_REPLY;
2034  return false;
2035  }
2036  reply.index1 = fx;
2037  return true;
2038 }
2039 
2040 bool RouterCore::dropFilter(CtlPkt& cp, CtlPkt& reply) {
2041  pktLog->dropFilter(cp.index1);
2042  return true;
2043 }
2044 
2045 bool RouterCore::getFilter(CtlPkt& cp, CtlPkt& reply) {
2046  fltx fx = cp.index1;
2047  if (!pktLog->validFilter(fx)) {
2048  reply.errMsg = "get filter: invalid filter index";
2049  reply.mode = CtlPkt::NEG_REPLY;
2050  return false;
2051  }
2052  PacketFilter& f = pktLog->getFilter(fx);
2053  f.toString(reply.stringData);
2054  return true;
2055 }
2056 
2057 bool RouterCore::modFilter(CtlPkt& cp, CtlPkt& reply) {
2058  fltx fx = cp.index1;
2059  if (!pktLog->validFilter(fx)) {
2060  reply.errMsg = "mod filter: invalid filter index";
2061  reply.mode = CtlPkt::NEG_REPLY;
2062  return false;
2063  }
2064  PacketFilter& f = pktLog->getFilter(fx);
2065  f.fromString(cp.stringData);
2066  return true;
2067 }
2068 
2080  fltx fx = cp.index1;
2081  if (fx == 0) {
2082  fx = pktLog->firstFilter(); // 0 means start with first filter
2083  } else if (!pktLog->validFilter(fx)) {
2084  reply.errMsg = "get filter set: invalid filter index";
2085  reply.mode = CtlPkt::NEG_REPLY;
2086  return false;
2087  }
2088  reply.index1 = fx;
2089  int count = min(10,cp.count);
2090  int i = 0;
2091  while (i < count && fx != 0) {
2092  string s;
2093  PacketFilter& f = pktLog->getFilter(fx);
2094  reply.stringData.append(f.toString(s));
2095  reply.stringData.push_back('\n');
2096 
2097  if (reply.stringData.length() > 1300) {
2098  reply.errMsg = "get filter set: error while "
2099  "formatting reply";
2100  reply.mode = CtlPkt::NEG_REPLY;
2101  return false;
2102  }
2103  i++; fx = pktLog->nextFilter(fx);
2104  }
2105  reply.index2 = fx; reply.count = i;
2106  return true;
2107 }
2108 
2116  reply.count = pktLog->log2string(1300, reply.stringData);
2117  return true;
2118 }
2119 
2129  if (!booting) {
2130  reply.errMsg = "attempting to set leaf address range when "
2131  "not booting";
2132  reply.mode = CtlPkt::NEG_REPLY;
2133  return false;
2134  }
2135  firstLeafAdr = cp.adr1;
2136  fAdr_t lastLeafAdr = cp.adr2;
2137  if (firstLeafAdr > lastLeafAdr) {
2138  reply.errMsg = "request contained empty leaf address range";
2139  reply.mode = CtlPkt::NEG_REPLY;
2140  return false;
2141  }
2142  leafAdr = new UiSetPair((lastLeafAdr - firstLeafAdr)+1);
2143  return true;
2144 }
2145 
2150  pktx px = ps->alloc();
2151  Packet& p = ps->getPacket(px);
2152 
2153  uint64_t nonce = lt->getNonce(lnk);
2154  p.length = Forest::OVERHEAD + 8; p.type = type; p.flags = 0;
2155  p.comtree = Forest::CONNECT_COMT;
2156  p.srcAdr = myAdr; p.dstAdr = lt->getPeerAdr(lnk);
2157  p.payload()[0] = htonl((int) (nonce >> 32));
2158  p.payload()[1] = htonl((int) (nonce & 0xffffffff));
2159  p.inLink = lnk; // hack to force consistent routing of conn/disc
2160  p.pack();
2161 
2162  // save a record of the packet in pending map
2163  pair<uint64_t,CpInfo> cpp;
2164  cpp.first = 1; cpp.first <<= 63; cpp.first |= nonce;
2165  cpp.second.px = px; cpp.second.nSent = 1; cpp.second.timestamp = now;
2166  pending->insert(cpp);
2167 
2168  // now, make copy of packet and send the copy
2169  int copy = ps->fullCopy(px);
2170  if (copy == 0) {
2171  cerr << "RouterCore::sendConnect: no packets left in packet "
2172  "store\n";
2173  return;
2174  }
2175  pktLog->log(copy,lnk,true,now);
2176  iop->send(copy,lnk);
2177 }
2178 
2188  pktx px = ps->alloc();
2189  if (px == 0) {
2190  cerr << "RouterCore::sendCpReq: no packets left in packet "
2191  "store\n";
2192  return false;
2193  }
2194  Packet& p = ps->getPacket(px);
2195 
2196  // pack cp into p, setting mode and seq number
2197  cp.mode = CtlPkt::REQUEST;
2198  cp.seqNum = seqNum;
2199  cp.payload = p.payload();
2200  if (cp.pack() == 0) {
2201  cerr << "RouterCore::sendCpReq: control packet packing error\n";
2202  return false;
2203  }
2204  p.length = Forest::OVERHEAD + cp.paylen;
2205  p.type = Forest::NET_SIG; p.flags = 0;
2207  p.srcAdr = myAdr; p.dstAdr = dest;
2208  p.inLink = 0;
2209  p.pack();
2210 
2211  // save a record of the packet in pending map
2212  pair<uint64_t,CpInfo> cpp;
2213  cpp.first = seqNum;
2214  cpp.second.px = px; cpp.second.nSent = 1; cpp.second.timestamp = now;
2215  pending->insert(cpp);
2216  seqNum++;
2217 
2218  // now, make copy of packet and send the copy
2219  int copy = ps->fullCopy(px);
2220  if (copy == 0) {
2221  cerr << "RouterCore::sendCpReq: no packets left in packet "
2222  "store\n";
2223  return false;
2224  }
2225  if (booting) {
2226  iop->send(copy,0);
2227  pktLog->log(copy,0,true,now);
2228  } else
2229  forward(copy,ctt->getComtIndex(p.comtree));
2230 
2231  return true;
2232 }
2233 
2241  map<uint64_t,CpInfo>::iterator pp;
2242  for (pp = pending->begin(); pp != pending->end(); pp++) {
2243  if (now < pp->second.timestamp + 1000000000) continue;
2244  pktx px = pp->second.px;
2245  Packet& p = ps->getPacket(px);
2246  if (pp->second.nSent >= 3) { // give up on this packet
2247  string s;
2248  cerr << "RouterCore::resendCpReq: received no reply to "
2249  "control packet after three attempts\n"
2250  << p.toString(s);
2251  ps->free(px);
2252  pending->erase(pp->first);
2253  continue;
2254  }
2255  string s1;
2256  cout << "resending control packet\n" << p.toString(s1);
2257  // make copy of packet and send the copy
2258  pp->second.timestamp = now;
2259  pp->second.nSent++;
2260  pktx copy = ps->fullCopy(px);
2261  if (copy == 0) {
2262  cerr << "RouterCore::resendCpReq: no packets left in "
2263  "packet store\n";
2264  return;
2265  }
2266  if (p.type == Forest::CONNECT || p.type == Forest::DISCONNECT) {
2267  iop->send(copy,p.inLink);
2268  pktLog->log(copy,p.inLink,true,now);
2269  } else if (booting) {
2270  pktLog->log(copy,0,true,now);
2271  iop->send(copy,0);
2272  } else {
2273  forward(copy,ctt->getComtIndex(p.comtree));
2274  }
2275  }
2276 }
2277 
2287 void RouterCore::handleCpReply(pktx reply, CtlPkt& cpr) {
2288  map<uint64_t,CpInfo>::iterator pp = pending->find(cpr.seqNum);
2289  if (pp == pending->end()) {
2290  // this is a reply to a request we never sent, or
2291  // possibly, a reply to a request we gave up on
2292  ps->free(reply);
2293  return;
2294  }
2295  // an expected reply, so remove it from the map of pending requests
2296  ps->free(pp->second.px);
2297  pending->erase(pp);
2298 
2299  // and then handle it
2300  switch (cpr.type) {
2301  case CtlPkt::CLIENT_CONNECT: case CtlPkt::CLIENT_DISCONNECT:
2302  if (cpr.mode == CtlPkt::NEG_REPLY) {
2303  cerr << "RouterCore::handleCpReply: got negative reply "
2304  "to a connect or disconnect request: "
2305  << cpr.errMsg << endl;
2306  break;
2307  }
2308  // otherwise, nothing to do
2309  break;
2310  case CtlPkt::BOOT_ROUTER: {
2311  if (cpr.mode == CtlPkt::NEG_REPLY) {
2312  cerr << "RouterCore::handleCpReply: got "
2313  "negative reply to a boot request: "
2314  << cpr.errMsg << endl;
2315  break;
2316  }
2317  if (booting && !setup()) {
2318  cerr << "RouterCore::handleCpReply: setup failed after "
2319  "completion of boot phase\n";
2320  perror("");
2321  // pktLog->write(cout);
2322  exit(1);
2323  }
2324  iop->closeBootSock();
2325  booting = false;
2326  break;
2327  }
2328  default:
2329  cerr << "RouterCore::handleCpReply: unexpected control packet "
2330  "type\n";
2331  break;
2332  }
2333  ps->free(reply);
2334 }
2335 
2342  Packet& p = ps->getPacket(px);
2343  cp.payload = p.payload();
2344  int paylen = cp.pack();
2345  if (paylen == 0) {
2346  cerr << "RouterCore::returnToSender: control packet formatting "
2347  "error, zero payload length\n";
2348  ps->free(px);
2349  }
2350  p.length = (Packet::OVERHEAD + paylen);
2351  p.flags = 0;
2352  p.dstAdr = p.srcAdr;
2353  p.srcAdr = myAdr;
2354  p.pack();
2355 
2356  if (booting) {
2357  pktLog->log(px,0,true,now);
2358  iop->send(px,0);
2359  return;
2360  }
2361 
2362  int cLnk = ctt->getComtLink(p.comtree,p.inLink);
2363  int qn = ctt->getLinkQ(cLnk);
2364  if (!qm->enq(px,qn,now)) { ps->free(px); }
2365 }
2366 
2367 } // ends namespace