forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
RouterCore.cpp
Go to the documentation of this file.
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(ps);
139 
140  if (!booting)
141  leafAdr = new UiSetPair((config.lastLeafAdr - firstLeafAdr)+1);
142 
143  seqNum = 1;
144  pending = new map<uint64_t,ControlInfo>();
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 
212 bool RouterCore::setup() {
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  // create packet log to record a sample of packets handled
559 
560  uint64_t statsTime = 0; // time statistics were last processed
561  bool didNothing;
562  int controlCount = 20; // used to limit overhead of control
563  // packet processing
564  queue<int> ctlQ; // queue for control packets
565 
566  now = Misc::getTimeNs();
567  finishTime *= 1000000000; // convert from seconds to ns
568  while (finishTime == 0 || now < finishTime) {
569  didNothing = true;
570 
571  // input processing
572  pktx px = iop->receive();
573  if (px != 0) {
574  didNothing = false;
575  Packet& p = ps->getPacket(px);
576  int ptype = p.type;
577  pktLog->log(px,p.inLink,false,now);
578  int ctx = ctt->getComtIndex(p.comtree);
579  if (!pktCheck(px,ctx)) {
580  ps->free(px);
581  } else if (booting) {
582  handleCtlPkt(px);
583  } else if (ptype == Forest::CLIENT_DATA) {
584  forward(px,ctx);
585  } else if (ptype == Forest::SUB_UNSUB) {
586  subUnsub(px,ctx);
587  } else if (ptype == Forest::RTE_REPLY) {
588  handleRteReply(px,ctx);
589  } else if (ptype == Forest::CONNECT ||
590  ptype == Forest::DISCONNECT) {
591  handleConnDisc(px);
592  } else if (p.dstAdr != myAdr) {
593  forward(px,ctx);
594  } else {
595  ctlQ.push(px);
596  }
597  }
598 
599  // output processing
600  int lnk;
601  while ((px = qm->deq(lnk, now)) != 0) {
602  didNothing = false;
603  pktLog->log(px,lnk,true,now);
604  iop->send(px,lnk);
605  }
606 
607  // control packet processing
608  if (!ctlQ.empty() && (didNothing || --controlCount <= 0)) {
609  handleCtlPkt(ctlQ.front());
610  ctlQ.pop();
611  controlCount = 20; // do one control packet for
612  // every 20 iterations when busy
613  didNothing = false;
614  }
615 
616  // every 300 ms, update statistics and check for un-acked
617  // control packets
618  if (now - statsTime > 300000000) {
619  sm->record(now); statsTime = now; resendControl();
620  didNothing = false;
621  }
622 
623  // if did nothing on that pass, sleep for a millisecond.
624  if (didNothing) { /* usleep(1000); */ }
625 
626  // update current time
627  now = Misc::getTimeNs();
628  }
629 
630  // write out recorded events
631  pktLog->write(cout);
632  cout << endl;
633  cout << sm->iPktCnt(0) << " packets received, "
634  << sm->oPktCnt(0) << " packets sent\n";
635  cout << sm->iPktCnt(-1) << " from routers, "
636  << sm->oPktCnt(-1) << " to routers\n";
637  cout << sm->iPktCnt(-2) << " from clients, "
638  << sm->oPktCnt(-2) << " to clients\n";
639 }
640 
646 bool RouterCore::pktCheck(pktx px, int ctx) {
647  Packet& p = ps->getPacket(px);
648  // check version and length
649  if (p.version != Forest::FOREST_VERSION) {
650  return false;
651  }
652  if (p.length != p.bufferLen || p.length < Forest::HDR_LENG) {
653  return false;
654  }
655  if (booting) {
656  return p.tunIp == nmIp && p.type == Forest::NET_SIG
658  }
659  if (p.type == Forest::CONNECT || p.type == Forest::DISCONNECT)
660  return (p.length == Forest::OVERHEAD+8);
661 
662  if (!ctt->validComtIndex(ctx)) {
663  return false;
664  }
665  fAdr_t adr = p.dstAdr;
666  if (!Forest::validUcastAdr(adr) && !Forest::mcastAdr(adr)) {
667  return false;
668  }
669 
670  int inLink = p.inLink;
671  if (inLink == 0) return false;
672  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),inLink);
673  if (cLnk == 0) {
674  return false;
675  }
676 
677  // extra checks for packets from untrusted peers
678  if (lt->getPeerType(inLink) < Forest::TRUSTED) {
679  // check for spoofed source address
680  if (lt->getPeerAdr(inLink) != p.srcAdr) return false;
681  // and that destination restrictions are respected
682  fAdr_t dest = ctt->getDest(cLnk);
683  if (dest!=0 && p.dstAdr != dest && p.dstAdr != myAdr)
684  return false;
685  // verify that type is valid
686  Forest::ptyp_t ptype = p.type;
687  if (ptype != Forest::CLIENT_DATA &&
688  ptype != Forest::CONNECT && ptype != Forest::DISCONNECT &&
689  ptype != Forest::SUB_UNSUB && ptype != Forest::CLIENT_SIG)
690  return false;
691  int comt = ctt->getComtree(ctx);
692  if ((ptype == Forest::CONNECT || ptype == Forest::DISCONNECT) &&
693  comt != (int) Forest::CONNECT_COMT)
694  return false;
695  if (ptype == Forest::CLIENT_SIG &&
696  comt != (int) Forest::CLIENT_SIG_COMT)
697  return false;
698  }
699  return true;
700 }
701 
711 void RouterCore::forward(pktx px, int ctx) {
712  Packet& p = ps->getPacket(px);
713  int rtx = rt->getRteIndex(p.comtree,p.dstAdr);
714  if (rtx != 0) { // valid route case
715  // reply to route request
716  if ((p.flags & Forest::RTE_REQ)) {
717  sendRteReply(px,ctx);
718  p.flags = (p.flags & (~Forest::RTE_REQ));
719  p.pack();
720  p.hdrErrUpdate();
721  }
722  if (Forest::validUcastAdr(p.dstAdr)) {
723  int rcLnk = rt->getLink(rtx);
724  int lnk = ctt->getLink(rcLnk);
725  int qid = ctt->getLinkQ(rcLnk);
726  if (lnk == p.inLink || !qm->enq(px,qid,now)) {
727  ps->free(px);
728  }
729  return;
730  }
731  // multicast data packet
732  multiSend(px,ctx,rtx);
733  return;
734  }
735  // no valid route
736 // think about suppressing flooding, if address is in range for this router
737  if (Forest::validUcastAdr(p.dstAdr)) {
738  // send to neighboring routers in comtree
740  p.pack(); p.hdrErrUpdate();
741  }
742  multiSend(px,ctx,rtx);
743  return;
744 }
755 void RouterCore::multiSend(pktx px, int ctx, int rtx) {
756  int qvec[nLnks]; int n = 0;
757  Packet& p = ps->getPacket(px);
758 
759  int inLink = p.inLink;
760  if (Forest::validUcastAdr(p.dstAdr)) {
761  // flooding a unicast packet to neighboring routers
762  int myZip = Forest::zipCode(myAdr);
763  int pZip = Forest::zipCode(p.dstAdr);
764  set<int>& rtrLinks = ctt->getRtrLinks(ctx);
765  set<int>::iterator lp;
766  for (lp = rtrLinks.begin(); lp != rtrLinks.end(); lp++) {
767  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
768  int peerZip = Forest::zipCode(lt->getPeerAdr(lnk));
769  if (pZip == myZip && peerZip != myZip) continue;
770  if (lnk == inLink) continue;
771  qvec[n++] = ctt->getLinkQ(rcLnk);
772  }
773  } else {
774  // forwarding a multicast packet
775  // first identify neighboring core routers to get copies
776  int pLink = ctt->getPlink(ctx);
777  set<int>& coreLinks = ctt->getCoreLinks(ctx);
778  set<int>::iterator lp;
779  for (lp = coreLinks.begin(); lp != coreLinks.end(); lp++) {
780  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
781  if (lnk == inLink || lnk == pLink) continue;
782  qvec[n++] = ctt->getLinkQ(rcLnk);
783  }
784  // now copy for parent
785  if (pLink != 0 && pLink != inLink) {
786  qvec[n++] = ctt->getLinkQ(ctt->getPCLink(ctx));
787  }
788  // now, copies for subscribers if any
789  if (rtx != 0) {
790  set<int>& subLinks = rt->getSubLinks(rtx);
791  for (lp = subLinks.begin(); lp !=subLinks.end(); lp++) {
792  int rcLnk = *lp; int lnk = ctt->getLink(rcLnk);
793  if (lnk == inLink) continue;
794  qvec[n++] = ctt->getLinkQ(rcLnk);
795  }
796  }
797  }
798 
799  if (n == 0) { ps->free(px); return; }
800 
801  // make copies and queue them
802  pktx px1 = px;
803  for (int i = 0; i < n-1; i++) { // process first n-1 copies
804  if (qm->enq(px1,qvec[i],now)) {
805  px1 = ps->clone(px);
806  }
807  }
808  // process last copy
809  if (!qm->enq(px1,qvec[n-1],now)) {
810  ps->free(px1);
811  }
812 }
813 
820 void RouterCore::sendRteReply(pktx px, int ctx) {
821  Packet& p = ps->getPacket(px);
822 
823  pktx px1 = ps->alloc();
824  Packet& p1 = ps->getPacket(px1);
825  p1.length = Forest::HDR_LENG + 8;
826  p1.type = Forest::RTE_REPLY;
827  p1.flags = 0;
828  p1.comtree = p.comtree;
829  p1.srcAdr = myAdr;
830  p1.dstAdr = p.srcAdr;
831 
832  p1.pack();
833  (p1.payload())[0] = htonl(p.dstAdr);
834  p1.hdrErrUpdate(); p.payErrUpdate();
835 
836  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),p.inLink);
837  if (!qm->enq(px1,ctt->getLinkQ(cLnk),now)) ps->free(px1);
838 }
839 
848 void RouterCore::handleRteReply(pktx px, int ctx) {
849  Packet& p = ps->getPacket(px);
850  int rtx = rt->getRteIndex(p.comtree, p.dstAdr);
851  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),p.inLink);
852  if ((p.flags & Forest::RTE_REQ) && rtx != 0)
853  sendRteReply(px,ctx);
854  int adr = ntohl((p.payload())[0]);
855  if (Forest::validUcastAdr(adr) &&
856  rt->getRteIndex(p.comtree,adr) == 0) {
857  rt->addEntry(p.comtree,adr,cLnk);
858  }
859  if (rtx == 0) {
860  // send to neighboring routers in comtree
862  p.pack(); p.hdrErrUpdate();
863  multiSend(px,ctx,rtx);
864  return;
865  }
866  int dcLnk = rt->getLink(rtx); int dLnk = ctt->getLink(dcLnk);
867  if (lt->getPeerType(dLnk) != Forest::ROUTER || !qm->enq(px,dLnk,now))
868  ps->free(px);
869  return;
870 }
871 
879 void RouterCore::subUnsub(pktx px, int ctx) {
880  Packet& p = ps->getPacket(px);
881  uint32_t *pp = p.payload();
882 
883  // process ack from parent router - just remove packet from pending map
884  if ((p.flags & Forest::ACK_FLAG) != 0) {
885  handleControlReply(px); return;
886  }
887 
888  // add/remove branches from routes
889  // if non-core node, also propagate requests upward as appropriate
890  int comt = ctt->getComtree(ctx);
891  int inLink = p.inLink;
892  int cLnk = ctt->getComtLink(comt,inLink);
893 
894  // ignore subscriptions from the parent or core neighbors
895  if (inLink == ctt->getPlink(ctx) || ctt->isCoreLink(cLnk)) {
896  ps->free(px); return;
897  }
898 
899  // make copy to be used for ack
900  pktx cx = ps->fullCopy(px);
901  Packet& copy = ps->getPacket(cx);
902 
903  bool propagate = false;
904  int rtx; fAdr_t addr;
905 
906  // add subscriptions
907  int addcnt = ntohl(pp[2]);
908  if (addcnt < 0 || addcnt > 350 ||
909  Forest::OVERHEAD + (addcnt + 4)*4 > p.length) {
910  ps->free(px); ps->free(cx); return;
911  }
912  for (int i = 3; i <= addcnt + 2; i++) {
913  addr = ntohl(pp[i]);
914  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
915  rtx = rt->getRteIndex(comt,addr);
916  if (rtx == 0) {
917  rtx = rt->addEntry(comt,addr,cLnk);
918  propagate = true;
919  } else if (!rt->isLink(rtx,cLnk)) {
920  rt->addLink(rtx,cLnk);
921  pp[i] = 0; // so, parent will ignore
922  }
923  }
924  // remove subscriptions
925  int dropcnt = ntohl(pp[addcnt+3]);
926  if (dropcnt < 0 || addcnt + dropcnt > 350 ||
927  Forest::OVERHEAD + (addcnt + dropcnt + 4)*4 > p.length) {
928  ps->free(px); ps->free(cx); return;
929  }
930  for (int i = addcnt + 4; i <= addcnt + dropcnt + 3; i++) {
931  addr = ntohl(pp[i]);
932  if (!Forest::mcastAdr(addr)) continue; // ignore unicast or 0
933  rtx = rt->getRteIndex(comt,addr);
934  if (rtx == 0) continue;
935  rt->removeLink(rtx,cLnk);
936  if (rt->noLinks(rtx)) {
937  rt->removeEntry(rtx);
938  propagate = true;
939  } else {
940  pp[i] = 0;
941  }
942  }
943  // propagate subscription packet to parent if not a core node
944  if (propagate && !ctt->inCore(ctx) && ctt->getPlink(ctx) != 0) {
945  pp[0] = htonl((uint32_t) (seqNum >> 32));
946  pp[1] = htonl((uint32_t) (seqNum & 0xffffffff));
947  p.srcAdr = myAdr;
948  p.dstAdr = lt->getPeerAdr(ctt->getPlink(ctx));
949  sendControl(px,seqNum++,ctt->getPlink(ctx));
950  } else {
951  ps->free(px);
952  }
953  // send ack back to sender
954  // note that we send ack before getting ack from sender
955  // this is by design
956  copy.flags |= Forest::ACK_FLAG;
957  copy.dstAdr = copy.srcAdr; copy.srcAdr = myAdr;
958  copy.pack();
959  int qid = ctt->getLinkQ(cLnk);
960  if (!qm->enq(cx,qid,now)) ps->free(cx);
961  return;
962 }
963 
967 void RouterCore::handleConnDisc(pktx px) {
968  Packet& p = ps->getPacket(px);
969  int inLnk = p.inLink;
970 
971  if (p.srcAdr != lt->getPeerAdr(inLnk) ||
972  p.length != Forest::OVERHEAD + 8) {
973  ps->free(px); return;
974  }
975 
976  uint64_t nonce = ntohl(p.payload()[0]);
977  nonce <<= 32; nonce |= ntohl(p.payload()[1]);
978  if (nonce != lt->getNonce(inLnk)) { ps->free(px); return; }
979  if ((p.flags & Forest::ACK_FLAG) != 0) {
980  handleControlReply(px); return;
981  }
982  if (p.type == Forest::CONNECT) {
983  if (lt->isConnected(inLnk) && !lt->revertEntry(inLnk)) {
984  ps->free(px); return;
985  }
986  if (!lt->remapEntry(inLnk,p.tunIp,p.tunPort)) {
987  ps->free(px); return;
988  }
989  lt->setConnectStatus(inLnk,true);
990  if (nmAdr != 0 && lt->getPeerType(inLnk) == Forest::CLIENT) {
991  CtlPkt cp(CtlPkt::CLIENT_CONNECT,CtlPkt::REQUEST,0);
992  cp.adr1 = p.srcAdr; cp.adr2 = myAdr;
993  sendCpReq(cp,nmAdr);
994  }
995  } else if (p.type == Forest::DISCONNECT) {
996  lt->setConnectStatus(inLnk,false);
997  lt->revertEntry(inLnk);
998  if (nmAdr != 0 && lt->getPeerType(inLnk) == Forest::CLIENT) {
999  dropLink(inLnk);
1000  CtlPkt cp(CtlPkt::CLIENT_DISCONNECT,CtlPkt::REQUEST,0);
1001  cp.adr1 = p.srcAdr; cp.adr2 = myAdr;
1002  sendCpReq(cp,nmAdr);
1003  }
1004  }
1005  // send ack back to sender
1006  p.flags |= Forest::ACK_FLAG; p.dstAdr = p.srcAdr; p.srcAdr = myAdr;
1007  p.pack();
1008  pktLog->log(px,inLnk,true,now); iop->send(px,inLnk);
1009  return;
1010 }
1011 
1016 void RouterCore::handleCtlPkt(int px) {
1017  Packet& p = ps->getPacket(px);
1018  CtlPkt cp(p.payload(), p.length - Packet::OVERHEAD);
1019 
1020  if (p.type != Forest::NET_SIG || p.comtree != Forest::NET_SIG_COMT) {
1021  ps->free(px); return;
1022  }
1023  if (!cp.unpack()) {
1024  string s;
1025  cerr << "RouterCore::handleCtlPkt: misformatted control "
1026  " packet\n" << p.toString(s);
1027  cp.reset(cp.type,CtlPkt::NEG_REPLY,cp.seqNum);
1028  cp.mode = CtlPkt::NEG_REPLY;
1029  cp.errMsg = "misformatted control packet";
1030  returnToSender(px,cp);
1031  return;
1032  }
1033  if (cp.mode != CtlPkt::REQUEST) {
1034  handleControlReply(px); return;
1035  }
1036 
1037  // Prepare positive reply packet for use where appropriate
1038  CtlPkt reply(cp.type,CtlPkt::POS_REPLY,cp.seqNum);
1039 
1040  switch (cp.type) {
1041 
1042  // configuring logical interfaces
1043  case CtlPkt::ADD_IFACE: addIface(cp,reply); break;
1044  case CtlPkt::DROP_IFACE: dropIface(cp,reply); break;
1045  case CtlPkt::GET_IFACE: getIface(cp,reply); break;
1046  case CtlPkt::MOD_IFACE: modIface(cp,reply); break;
1047  case CtlPkt::GET_IFACE_SET: getIfaceSet(cp,reply); break;
1048 
1049  // configuring links
1050  case CtlPkt::ADD_LINK: addLink(cp,reply); break;
1051  case CtlPkt::DROP_LINK: dropLink(cp,reply); break;
1052  case CtlPkt::GET_LINK: getLink(cp,reply); break;
1053  case CtlPkt::MOD_LINK: modLink(cp,reply); break;
1054  case CtlPkt::GET_LINK_SET: getLinkSet(cp,reply); break;
1055 
1056  // configuring comtrees
1057  case CtlPkt::ADD_COMTREE: addComtree(cp,reply); break;
1058  case CtlPkt::DROP_COMTREE: dropComtree(cp,reply); break;
1059  case CtlPkt::GET_COMTREE: getComtree(cp,reply); break;
1060  case CtlPkt::MOD_COMTREE: modComtree(cp,reply); break;
1061  case CtlPkt::GET_COMTREE_SET: getComtreeSet(cp,reply); break;
1062 
1063  case CtlPkt::ADD_COMTREE_LINK: addComtreeLink(cp,reply); break;
1064  case CtlPkt::DROP_COMTREE_LINK: dropComtreeLink(cp,reply); break;
1065  case CtlPkt::GET_COMTREE_LINK: getComtreeLink(cp,reply); break;
1066  case CtlPkt::MOD_COMTREE_LINK: modComtreeLink(cp,reply); break;
1067 
1068  // configuring routes
1069  case CtlPkt::ADD_ROUTE: addRoute(cp,reply); break;
1070  case CtlPkt::DROP_ROUTE: dropRoute(cp,reply); break;
1071  case CtlPkt::GET_ROUTE: getRoute(cp,reply); break;
1072  case CtlPkt::MOD_ROUTE: modRoute(cp,reply); break;
1073  case CtlPkt::GET_ROUTE_SET: getRouteSet(cp,reply); break;
1074 
1075  // configuring filters and retrieving pacets
1076  case CtlPkt::ADD_FILTER: addFilter(cp,reply); break;
1077  case CtlPkt::DROP_FILTER: dropFilter(cp,reply); break;
1078  case CtlPkt::GET_FILTER: getFilter(cp,reply); break;
1079  case CtlPkt::MOD_FILTER: modFilter(cp,reply); break;
1080  case CtlPkt::GET_FILTER_SET: getFilterSet(cp,reply); break;
1081  case CtlPkt::GET_LOGGED_PACKETS: getLoggedPackets(cp,reply); break;
1082  case CtlPkt::ENABLE_PACKET_LOG: enablePacketLog(cp,reply); break;
1083 
1084  // setting parameters
1085  case CtlPkt::SET_LEAF_RANGE: setLeafRange(cp,reply); break;
1086 
1087  default:
1088  cerr << "unrecognized control packet type " << cp.type
1089  << endl;
1090  reply.errMsg = "invalid control packet for router";
1091  reply.mode = CtlPkt::NEG_REPLY;
1092  break;
1093  }
1094 
1095  returnToSender(px,reply);
1096 
1097  return;
1098 }
1099 
1111 bool RouterCore::addIface(CtlPkt& cp, CtlPkt& reply) {
1112  int iface = cp.iface;
1113  RateSpec rs(max(min(cp.rspec1.bitRateUp, Forest::MAXBITRATE),
1115  max(min(cp.rspec1.bitRateDown,Forest::MAXBITRATE),
1117  max(min(cp.rspec1.pktRateUp, Forest::MAXPKTRATE),
1119  max(min(cp.rspec1.pktRateDown,Forest::MAXPKTRATE),
1121  if (ift->valid(iface)) {
1122  if (cp.iface != ift->getIpAdr(iface) ||
1123  !rs.equals(ift->getRates(iface))) {
1124  reply.errMsg = "add iface: requested interface "
1125  "conflicts with existing interface";
1126  reply.mode = CtlPkt::NEG_REPLY;
1127  return false;
1128  }
1129  // means reply to earlier add iface was lost
1130  reply.ip1 = ift->getIpAdr(iface);
1131  reply.port1 = ift->getPort(iface);
1132  return true;
1133  } else if (!ift->addEntry(iface, cp.ip1, 0, rs)) {
1134  reply.errMsg = "add iface: cannot add interface";
1135  reply.mode = CtlPkt::NEG_REPLY;
1136  return false;
1137  } else if (!iop->setup(iface)) {
1138  reply.errMsg = "add iface: could not setup interface";
1139  reply.mode = CtlPkt::NEG_REPLY;
1140  return false;
1141  }
1142  reply.ip1 = ift->getIpAdr(iface);
1143  reply.port1 = ift->getPort(iface);
1144  return true;
1145 }
1146 
1147 bool RouterCore::dropIface(CtlPkt& cp, CtlPkt& reply) {
1148  ift->removeEntry(cp.iface);
1149  return true;
1150 }
1151 
1152 bool RouterCore::getIface(CtlPkt& cp, CtlPkt& reply) {
1153  int iface = cp.iface;
1154  if (ift->valid(iface)) {
1155  reply.iface = iface;
1156  reply.ip1 = ift->getIpAdr(iface);
1157  reply.port1 = ift->getPort(iface);
1158  reply.rspec1 = ift->getRates(iface);
1159  reply.rspec2 = ift->getAvailRates(iface);
1160  return true;
1161  }
1162  reply.errMsg = "get iface: invalid interface";
1163  reply.mode = CtlPkt::NEG_REPLY;
1164  return false;
1165 }
1166 
1167 bool RouterCore::modIface(CtlPkt& cp, CtlPkt& reply) {
1168  int iface = cp.iface;
1169  if (ift->valid(iface)) {
1170  ift->getRates(iface) = cp.rspec1;
1171  return true;
1172  }
1173  reply.errMsg = "mod iface: invalid interface";
1174  reply.mode = CtlPkt::NEG_REPLY;
1175  return false;
1176 }
1177 
1188 bool RouterCore::getIfaceSet(CtlPkt& cp, CtlPkt& reply) {
1189  int ifIndex = cp.index1;
1190  if (ifIndex == 0) ifIndex = ift->firstIface(); // 0 means first ifzce
1191  else if (!ift->valid(ifIndex)) {
1192  reply.errMsg = "get iface set: invalid iface number";
1193  reply.mode = CtlPkt::NEG_REPLY;
1194  return false;
1195  }
1196  reply.index1 = ifIndex;
1197  int count = min(10,cp.count);
1198  int i = 0;
1199  string s; stringstream ss;
1200  while (i < count && ifIndex != 0) {
1201  ss.str(""); ss.clear(); ss << ifIndex << " ";
1202  reply.stringData.append(ss.str());
1203  ift->entry2string(ifIndex,s); //s.push_back('\n');
1204  reply.stringData.append(s);
1205  if (reply.stringData.length() > 1300) {
1206  reply.errMsg = "get iface set: error while formatting "
1207  "reply";
1208  reply.mode = CtlPkt::NEG_REPLY;
1209  return false;
1210  }
1211  i++; ifIndex = ift->nextIface(ifIndex);
1212  }
1213  reply.index2 = ifIndex; reply.count = i;
1214  return true;
1215 }
1216 
1217 bool RouterCore::addLink(CtlPkt& cp, CtlPkt& reply) {
1218  Forest::ntyp_t peerType = cp.nodeType;
1219  if (peerType == Forest::ROUTER && cp.adr1 == 0) {
1220  reply.errMsg = "add link: adding link to router, but no peer "
1221  "address supplied";
1222  reply.mode = CtlPkt::NEG_REPLY;
1223  return false;
1224  }
1225  int iface = cp.iface;
1226 
1227  int xlnk = lt->lookup(cp.ip1,cp.port1);
1228  if (xlnk != 0 || (cp.link != 0 && lt->valid(cp.link))) {
1229  if (cp.link != xlnk ||
1230  (peerType != lt->getPeerType(xlnk)) ||
1231  (cp.iface != lt->getIface(xlnk)) ||
1232  (cp.adr1 != 0 && cp.adr1 != lt->getPeerAdr(xlnk)) ||
1233  (cp.ip1 != 0 && cp.ip1 != ift->getIpAdr(iface)) ||
1234  (cp.port1 != 0 && cp.port1 != ift->getPort(iface))) {
1235  reply.errMsg = "add link: new link conflicts "
1236  "with existing link";
1237  reply.mode = CtlPkt::NEG_REPLY;
1238  return false;
1239  }
1240  // assume response to previous add link was lost
1241  reply.link = xlnk;
1242  reply.adr1 = lt->getPeerAdr(xlnk);
1243  reply.ip1 = lt->getPeerIpAdr(xlnk);
1244  return true;
1245  }
1246 
1247  // first ensure that the interface has enough
1248  // capacity to support a new link of minimum capacity
1251  RateSpec& availRates = ift->getAvailRates(iface);
1252  if (!rs.leq(availRates)) {
1253  reply.errMsg = "add link: requested link "
1254  "exceeds interface capacity";
1255  reply.mode = CtlPkt::NEG_REPLY;
1256  return false;
1257  }
1258 
1259  // setting up link
1260  // case 1: adding link to leaf; peer (ip,port) not known, use nonce
1261  // subcase - lnk, peer forest address is known
1262  // (for preconfigured leaf)
1263  // subcase - lnk, peer address to be assigned by router
1264  // case 2: adding link to router not yet up; port not known, use nonce
1265  // lnk, peer address specified
1266  // case 3: adding link to a router that is already up
1267  // lnk, peer address specified, peer (ip,port) specified
1268 
1269  // add table entry with (ip,port) or nonce
1270  // note: when lt->addEntry succeeds, link rates are
1271  // initialized to Forest minimum rates
1272  int lnk = lt->addEntry(cp.link,cp.ip1,cp.port1,cp.nonce);
1273  if (lnk == 0) {
1274  reply.errMsg = "add link: cannot add requested link";
1275  reply.mode = CtlPkt::NEG_REPLY;
1276  return false;
1277  }
1278 
1279  if (peerType == Forest::ROUTER) {
1280  lt->setPeerAdr(lnk,cp.adr1);
1281  } else { // case 1
1282  fAdr_t peerAdr = 0;
1283  if (cp.adr1 == 0) peerAdr = allocLeafAdr();
1284  else if (allocLeafAdr(cp.adr1)) peerAdr = cp.adr1;
1285  if (peerAdr == 0) {
1286  lt->removeEntry(lnk);
1287  reply.errMsg = "add link: cannot add link using "
1288  "specified address";
1289  reply.mode = CtlPkt::NEG_REPLY;
1290  return false;
1291  }
1292  lt->setPeerAdr(lnk,peerAdr);
1293  }
1294 
1295  availRates.subtract(rs);
1296  lt->setIface(lnk,iface);
1297  lt->setPeerType(lnk,peerType);
1298  lt->setConnectStatus(lnk,false);
1299  sm->clearLnkStats(lnk);
1300  if (peerType == Forest::ROUTER && cp.ip1 != 0 && cp.port1 != 0) {
1301  // link to a router that's already up, so connect
1303  }
1304 
1305  reply.link = lnk;
1306  reply.adr1 = lt->getPeerAdr(lnk);
1307  return true;
1308 }
1309 
1310 bool RouterCore::dropLink(CtlPkt& cp, CtlPkt& reply) {
1311  dropLink(cp.link, cp.adr1);
1312  return true;
1313 }
1314 
1323 void RouterCore::dropLink(int lnk, fAdr_t peerAdr) {
1324  if (lnk == 0) lnk = lt->lookup(peerAdr);
1325  int *comtVec = new int[lt->getComtSet(lnk).size()];
1326  int i = 0;
1327  for (int comt : lt->getComtSet(lnk)) comtVec[i++] = comt;
1328  while (--i >= 0) {
1329  int ctx = comtVec[i];
1330  int cLnk = ctt->getComtLink(ctt->getComtree(ctx),lnk);
1331  dropComtreeLink(ctx,lnk,cLnk);
1332  }
1333  int iface = lt->getIface(lnk);
1334  ift->getAvailRates(iface).add(lt->getRates(lnk));
1335  lt->removeEntry(lnk);
1336  freeLeafAdr(lt->getPeerAdr(lnk));
1337 }
1338 
1339 bool RouterCore::getLink(CtlPkt& cp, CtlPkt& reply) {
1340  int link = cp.link;
1341  if (lt->valid(link)) {
1342  reply.link = link;
1343  reply.iface = lt->getIface(link);
1344  reply.ip1 = lt->getPeerIpAdr(link);
1345  reply.nodeType = lt->getPeerType(link);
1346  reply.port1 = lt->getPeerPort(link);
1347  reply.adr1 = lt->getPeerAdr(link);
1348  reply.rspec1 = lt->getRates(link);
1349  reply.rspec2 = lt->getAvailRates(link);
1350  reply.count = lt->getComtCount(link);
1351  return true;
1352  }
1353  reply.errMsg = "get link: invalid link number";
1354  reply.mode = CtlPkt::NEG_REPLY;
1355  return false;
1356 }
1357 
1368 bool RouterCore::getLinkSet(CtlPkt& cp, CtlPkt& reply) {
1369  int lnk = cp.index1;
1370  if (lnk == 0) lnk = lt->firstLink(); // 0 means start with first link
1371  else if (!lt->valid(lnk)) {
1372  reply.errMsg = "get link set: invalid link number";
1373  reply.mode = CtlPkt::NEG_REPLY;
1374  return false;
1375  }
1376  reply.index1 = lnk;
1377  int count = min(10,cp.count);
1378  int i = 0;
1379  string s; stringstream ss;
1380  while (i < count && lnk != 0) {
1381  ss.str(""); ss.clear(); ss << lnk << " ";
1382  reply.stringData.append(ss.str());
1383  lt->link2string(lnk,s); s.push_back('\n');
1384  reply.stringData.append(s);
1385  if (reply.stringData.length() > 1300) {
1386  reply.errMsg = "get link set: error while formatting "
1387  "reply";
1388  reply.mode = CtlPkt::NEG_REPLY;
1389  return false;
1390  }
1391  i++; lnk = lt->nextLink(lnk);
1392  }
1393  reply.index2 = lnk; reply.count = i;
1394  return true;
1395 }
1396 
1397 
1398 bool RouterCore::modLink(CtlPkt& cp, CtlPkt& reply) {
1399  int link = cp.link;
1400  if (!lt->valid(link)) {
1401  reply.errMsg = "get link: invalid link number";
1402  reply.mode = CtlPkt::NEG_REPLY;
1403  return false;
1404  }
1405  reply.link = link;
1406  int iface = lt->getIface(link);
1407  if (cp.rspec1.isSet()) {
1408  RateSpec& linkRates = lt->getRates(link);
1409  RateSpec& ifAvail = ift->getAvailRates(iface);
1410  RateSpec delta = cp.rspec1;
1411  delta.subtract(linkRates);
1412  if (!delta.leq(ifAvail)) {
1413  string s;
1414  reply.errMsg = "mod link: request "
1415  + cp.rspec1.toString(s) +
1416  "exceeds interface capacity";
1417  reply.mode = CtlPkt::NEG_REPLY;
1418  return false;
1419  }
1420  ifAvail.subtract(delta);
1421  linkRates = cp.rspec1;
1422  lt->getAvailRates(link).add(delta);
1423  qm->setLinkRates(link,cp.rspec1);
1424  }
1425  return true;
1426 }
1427 
1428 bool RouterCore::addComtree(CtlPkt& cp, CtlPkt& reply) {
1429  int comt = cp.comtree;
1430  if(ctt->validComtree(comt) || ctt->addEntry(comt) != 0)
1431  return true;
1432  reply.errMsg = "add comtree: cannot add comtree";
1433  reply.mode = CtlPkt::NEG_REPLY;
1434  return false;
1435 }
1436 
1437 bool RouterCore::dropComtree(CtlPkt& cp, CtlPkt& reply) {
1438  int comt = cp.comtree;
1439  int ctx = ctt->getComtIndex(comt);
1440  if (!ctt->validComtIndex(ctx))
1441  return true; // so dropComtree op is idempotent
1442  int plink = ctt->getPlink(ctx);
1443 
1444  // remove all routes involving this comtree
1445  // also degisters each route in the comtree table
1446  rt->purgeRoutes(comt);
1447 
1448  // remove all the comtree links
1449  // first, copy out the comtree links, then remove them
1450  // two step process is needed because dropComtreeLink modifies linkSet
1451  set<int>& linkSet = ctt->getLinks(ctx);
1452  set<int>::iterator pp;
1453  int *clnks = new int[linkSet.size()]; int i = 0;
1454  for (pp = linkSet.begin(); pp != linkSet.end(); pp++) clnks[i++] = *pp;
1455  while (--i >= 0) {
1456  dropComtreeLink(ctx,ctt->getLink(clnks[i]),clnks[i]);
1457  }
1458  delete [] clnks;
1459 
1460  ctt->removeEntry(ctx); // and finally drop entry in comtree table
1461  if (plink != 0) reply.rspec1 = lt->getAvailRates(plink);
1462  else reply.rspec1.set(0);
1463  return true;
1464 }
1465 
1466 bool RouterCore::getComtree(CtlPkt& cp, CtlPkt& reply) {
1467  comt_t comt = cp.comtree;
1468  int ctx = ctt->getComtIndex(comt);
1469  if (ctx == 0) {
1470  reply.errMsg = "get comtree: invalid comtree";
1471  reply.mode = CtlPkt::NEG_REPLY;
1472  return false;
1473  }
1474  reply.comtree = comt;
1475  reply.coreFlag = ctt->inCore(ctx);
1476  reply.link = ctt->getPlink(ctx);
1477  reply.count = ctt->getLinkCount(ctx);
1478  return true;
1479 }
1480 
1481 bool RouterCore::modComtree(CtlPkt& cp, CtlPkt& reply) {
1482  comt_t comt = cp.comtree;
1483  int ctx = ctt->getComtIndex(comt);
1484  if (ctx != 0) {
1485  if (cp.coreFlag >= 0)
1486  ctt->setCoreFlag(ctx,cp.coreFlag);
1487  if (cp.link != 0) {
1488  int plnk = cp.link;
1489  if (plnk != 0 && !ctt->isLink(ctx,plnk)) {
1490  reply.errMsg = "specified link does "
1491  "not belong to comtree";
1492  reply.mode = CtlPkt::NEG_REPLY;
1493  return false;
1494  }
1495  if (plnk != 0 && !ctt->isRtrLink(ctx,plnk)) {
1496  reply.errMsg = "specified link does "
1497  "not connect to a router";
1498  reply.mode = CtlPkt::NEG_REPLY;
1499  return false;
1500  }
1501  ctt->setPlink(ctx,plnk);
1502  }
1503  return true;
1504  }
1505  reply.errMsg = "modify comtree: invalid comtree";
1506  reply.mode = CtlPkt::NEG_REPLY;
1507  return false;
1508 }
1509 
1520 bool RouterCore::getComtreeSet(CtlPkt& cp, CtlPkt& reply) {
1521  int comtIndex = cp.index1;
1522  if (comtIndex == 0) comtIndex = ctt->firstComtIndex(); // 0 means first
1523  else if (!ctt->validComtIndex(comtIndex)) {
1524  reply.errMsg = "get comtree set: invalid comtree number";
1525  reply.mode = CtlPkt::NEG_REPLY;
1526  return false;
1527  }
1528  reply.index1 = comtIndex;
1529  int count = min(10,cp.count);
1530  int i = 0;
1531  while (i < count && comtIndex != 0) {
1532  string s; ctt->entry2string(comtIndex,s); //s.push_back('\n');
1533  reply.stringData.append(s);
1534  if (reply.stringData.length() > 1300) {
1535  reply.errMsg = "get comtee set: error while formatting "
1536  "reply";
1537  reply.mode = CtlPkt::NEG_REPLY;
1538  return false;
1539  }
1540  i++; comtIndex = ctt->nextComtIndex(comtIndex);
1541  }
1542  reply.index2 = comtIndex; reply.count = i;
1543  return true;
1544 }
1545 
1546 bool RouterCore::addComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1547  comt_t comt = cp.comtree;
1548  int ctx = ctt->getComtIndex(comt);
1549  if (ctx == 0) {
1550  reply.errMsg = "add comtree link: invalid comtree";
1551  reply.mode = CtlPkt::NEG_REPLY;
1552  return false;
1553  }
1554  int lnk = 0;
1555  if (cp.link != 0) {
1556  lnk = cp.link;
1557  } else if (cp.ip1 != 0 && cp.port1 != 0) {
1558  lnk = lt->lookup(cp.ip1, cp.port1);
1559  } else if (cp.adr1 != 0) {
1560  lnk = lt->lookup(cp.adr1);
1561  }
1562  if (!lt->valid(lnk)) {
1563  reply.errMsg = "add comtree link: invalid link or "
1564  "peer IP and port";
1565  reply.mode = CtlPkt::NEG_REPLY;
1566  return false;
1567  }
1568  bool isRtr = (lt->getPeerType(lnk) == Forest::ROUTER);
1569  bool isCore = false;
1570  if (isRtr) {
1571  if (cp.coreFlag < 0) {
1572  reply.errMsg = "add comtree link: must specify "
1573  "core flag on links to routers";
1574  reply.mode = CtlPkt::NEG_REPLY;
1575  return false;
1576  }
1577  isCore = cp.coreFlag;
1578  }
1579  int cLnk = ctt->getComtLink(comt,lnk);
1580  if (cLnk != 0) {
1581  if (ctt->isRtrLink(cLnk) == isRtr &&
1582  ctt->isCoreLink(cLnk) == isCore) {
1583  reply.link = lnk;
1584  return true;
1585  } else {
1586  reply.errMsg = "add comtree link: specified "
1587  "link already in comtree";
1588  reply.mode = CtlPkt::NEG_REPLY;
1589  return false;
1590  }
1591  }
1592  // define new comtree link
1593  if (!ctt->addLink(ctx,lnk,isRtr,isCore)) {
1594  reply.errMsg = "add comtree link: cannot add "
1595  "requested comtree link";
1596  reply.mode = CtlPkt::NEG_REPLY;
1597  return false;
1598  }
1599  cLnk = ctt->getComtLink(comt,lnk);
1600 
1601  // add unicast route to cLnk if peer is a leaf or a router
1602  // in a different zip code
1603  fAdr_t peerAdr = lt->getPeerAdr(lnk);
1604  if (lt->getPeerType(lnk) != Forest::ROUTER) {
1605  int rtx = rt->getRteIndex(comt,peerAdr);
1606  if (rtx == 0) rt->addEntry(comt,peerAdr,cLnk);
1607  } else {
1608  int zipPeer = Forest::zipCode(peerAdr);
1609  if (zipPeer != Forest::zipCode(myAdr)) {
1610  fAdr_t dest = Forest::forestAdr(zipPeer,0);
1611  int rtx = rt->getRteIndex(comt,dest);
1612  if (rtx == 0) rt->addEntry(comt,dest,cLnk);
1613  }
1614  }
1615 
1616  // allocate queue and bind it to lnk and comtree link
1617  int qid = qm->allocQ(lnk);
1618  if (qid == 0) {
1619  ctt->removeLink(ctx,cLnk);
1620  reply.errMsg = "add comtree link: no queues "
1621  "available for link";
1622  reply.mode = CtlPkt::NEG_REPLY;
1623  return false;
1624  }
1625  ctt->setLinkQ(cLnk,qid);
1626 
1627  // adjust rates for link comtree and queue
1630  if (!minRates.leq(lt->getAvailRates(lnk))) {
1631  reply.errMsg = "add comtree link: request "
1632  "exceeds link capacity";
1633  reply.mode = CtlPkt::NEG_REPLY;
1634  return false;
1635  }
1636  lt->getAvailRates(lnk).subtract(minRates);
1637  ctt->getRates(cLnk) = minRates;
1638 
1639  qm->setQRates(qid,minRates);
1640  if (isRtr) qm->setQLimits(qid,500,1000000);
1641  else qm->setQLimits(qid,500,1000000);
1642  sm->clearQuStats(qid);
1643  reply.link = lnk;
1644  reply.rspec1 = lt->getAvailRates(lnk);
1645  return true;
1646 }
1647 
1648 bool RouterCore::dropComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1649  comt_t comt = cp.comtree;
1650  int ctx = ctt->getComtIndex(comt);
1651  if (ctx == 0) {
1652  reply.errMsg = "drop comtree link: invalid comtree";
1653  reply.mode = CtlPkt::NEG_REPLY;
1654  return false;
1655  }
1656  int lnk = 0;
1657  if (cp.link != 0) {
1658  lnk = cp.link;
1659  } else if (cp.ip1 != 0 && cp.port1 != 0) {
1660  lnk = lt->lookup(cp.ip1, cp.port1);
1661  } else if (cp.adr1 != 0) {
1662  lnk = lt->lookup(cp.adr1);
1663  }
1664  if (!lt->valid(lnk)) {
1665  reply.errMsg = "drop comtree link: invalid link "
1666  "or peer IP and port";
1667  reply.mode = CtlPkt::NEG_REPLY;
1668  return false;
1669  }
1670  int cLnk = ctt->getComtLink(comt,lnk);
1671  if (cLnk != 0) {
1672  dropComtreeLink(ctx,lnk,cLnk);
1673  }
1674  reply.rspec1 = lt->getAvailRates(lnk);
1675  return true;
1676 }
1677 
1678 void RouterCore::dropComtreeLink(int ctx, int lnk, int cLnk) {
1679  // release the link bandwidth used by comtree link
1680  lt->getAvailRates(lnk).add(ctt->getRates(cLnk));
1681 
1682  // remove unicast route for this comtree
1683  fAdr_t peerAdr = lt->getPeerAdr(lnk);
1684  int comt = ctt->getComtree(ctx);
1685  if (lt->getPeerType(lnk) != Forest::ROUTER) {
1686  int rtx = rt->getRteIndex(comt,peerAdr);
1687  if (rtx != 0) rt->removeEntry(rtx);
1688  } else {
1689  int zipPeer = Forest::zipCode(peerAdr);
1690  if (zipPeer != Forest::zipCode(myAdr)) {
1691  fAdr_t dest = Forest::forestAdr(zipPeer,0);
1692  int rtx = rt->getRteIndex(comt,dest);
1693  if (rtx != 0) rt->removeEntry(rtx);
1694  }
1695  }
1696  // remove cLnk from multicast routes for this comtree
1697  // must first copy out the routes that are registered for
1698  // cLnk, then remove cLnk from all these routes;
1699  // two step process is needed because the removal of the link from
1700  // the route, also deregisters the route in the comtree table
1701  // causing the rteSet to change
1702  set<int>& rteSet = ctt->getRteSet(cLnk);
1703  set<int>::iterator rp;
1704  int *routes = new int[rteSet.size()];
1705  int i = 0;
1706  for (rp = rteSet.begin(); rp != rteSet.end(); rp++) routes[i++] = *rp;
1707  while (--i >= 0) rt->removeLink(routes[i],cLnk);
1708  delete [] routes;
1709 
1710  // release queue and remove link from comtree
1711  // (which also deregisters comtree with lnk)
1712  int qid = ctt->getLinkQ(cLnk);
1713  qm->freeQ(qid);
1714  if (!ctt->removeLink(ctx,cLnk)) {
1715  cerr << "dropComtreeLink: internal error detected "
1716  "final removeLink failed\n";
1717  }
1718 }
1719 
1720 bool RouterCore::modComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1721  comt_t comt = cp.comtree;
1722  int ctx = ctt->getComtIndex(comt);
1723  if (ctx == 0) {
1724  reply.errMsg = "modify comtree link: invalid comtree";
1725  reply.mode = CtlPkt::NEG_REPLY;
1726  return false;
1727  }
1728  int lnk = cp.link;
1729  if (!lt->valid(lnk)) {
1730  reply.errMsg = "modify comtree link: invalid link number";
1731  reply.mode = CtlPkt::NEG_REPLY;
1732  return false;
1733  }
1734  int cLnk = ctt->getComtLink(comt,lnk);
1735  if (cLnk == 0) {
1736  reply.errMsg = "modify comtree link: specified link "
1737  "not defined in specified comtree";
1738  reply.mode = CtlPkt::NEG_REPLY;
1739  return false;
1740  }
1741 
1742  RateSpec rs = cp.rspec1;
1743  if (!rs.isSet()) return true;
1744  RateSpec diff = rs; diff.subtract(ctt->getRates(cLnk));
1745  if (!diff.leq(lt->getAvailRates(lnk))) {
1746  reply.errMsg = "modify comtree link: new rate spec "
1747  "exceeds available link capacity";
1748  reply.mode = CtlPkt::NEG_REPLY;
1749 {
1750 string s;
1751 cerr << "mod comtree link exceeding link capacity on link " << lnk <<
1752 "\nrequested " << rs.toString(s);
1753 cerr << " only " << lt->getAvailRates(lnk).toString(s) << "available\n";
1754 }
1755  return false;
1756  }
1757  lt->getAvailRates(lnk).subtract(diff);
1758  ctt->getRates(cLnk) = rs;
1759  reply.rspec1 = lt->getAvailRates(lnk); // return available rate on link
1760  return true;
1761 }
1762 
1763 bool RouterCore::getComtreeLink(CtlPkt& cp, CtlPkt& reply) {
1764  comt_t comt = cp.comtree;
1765  int ctx = ctt->getComtIndex(comt);
1766  if (ctx == 0) {
1767  reply.errMsg = "get comtree link: invalid comtree";
1768  reply.mode = CtlPkt::NEG_REPLY;
1769  return false;
1770  }
1771  int lnk = cp.link;
1772  if (!lt->valid(lnk)) {
1773  reply.errMsg = "get comtree link: invalid link number";
1774  reply.mode = CtlPkt::NEG_REPLY;
1775  return false;
1776  }
1777  int cLnk = ctt->getComtLink(comt,lnk);
1778  if (cLnk == 0) {
1779  reply.errMsg = "get comtree link: specified link "
1780  "not defined in specified comtree";
1781  reply.mode = CtlPkt::NEG_REPLY;
1782  return false;
1783  }
1784  reply.comtree = comt;
1785  reply.link = lnk;
1786  reply.queue = ctt->getLinkQ(cLnk);
1787  reply.adr1 = ctt->getDest(cLnk);
1788  reply.rspec1 = ctt->getRates(cLnk);
1789 
1790  return true;
1791 }
1792 
1793 bool RouterCore::addRoute(CtlPkt& cp, CtlPkt& reply) {
1794  comt_t comt = cp.comtree;
1795  if (!ctt->validComtree(comt)) {
1796  reply.errMsg = "comtree not defined at this router\n";
1797  reply.mode = CtlPkt::NEG_REPLY;
1798  return false;
1799  }
1800  fAdr_t dest = cp.adr1;
1801  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1802  reply.errMsg = "invalid address\n";
1803  reply.mode = CtlPkt::NEG_REPLY;
1804  return false;
1805  }
1806  int lnk = cp.link;
1807  int cLnk = ctt->getComtLink(comt,lnk);
1808  int rtx = rt->getRteIndex(comt,dest);
1809  if (rtx != 0) {
1810  if ((Forest::validUcastAdr(dest) && rt->getLink(rtx) == cLnk) ||
1811  (Forest::mcastAdr(dest) && rt->isLink(rtx,cLnk))) {
1812  return true;
1813  } else {
1814  reply.errMsg = "add route: requested route "
1815  "conflicts with existing route";
1816  reply.mode = CtlPkt::NEG_REPLY;
1817  return false;
1818  }
1819  } else if (rt->addEntry(comt, dest, lnk)) {
1820  return true;
1821  }
1822  reply.errMsg = "add route: cannot add route";
1823  reply.mode = CtlPkt::NEG_REPLY;
1824  return false;
1825 }
1826 
1827 bool RouterCore::dropRoute(CtlPkt& cp, CtlPkt& reply) {
1828  comt_t comt = cp.comtree;
1829  if (!ctt->validComtree(comt)) {
1830  reply.errMsg = "comtree not defined at this router\n";
1831  reply.mode = CtlPkt::NEG_REPLY;
1832  return false;
1833  }
1834  fAdr_t dest = cp.adr1;
1835  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1836  reply.errMsg = "invalid address\n";
1837  reply.mode = CtlPkt::NEG_REPLY;
1838  return false;
1839  }
1840  int rtx = rt->getRteIndex(comt,dest);
1841  rt->removeEntry(rtx);
1842  return true;
1843 }
1844 
1845 bool RouterCore::getRoute(CtlPkt& cp, CtlPkt& reply) {
1846  comt_t comt = cp.comtree;
1847  if (!ctt->validComtree(comt)) {
1848  reply.errMsg = "comtree not defined at this router\n";
1849  reply.mode = CtlPkt::NEG_REPLY;
1850  return false;
1851  }
1852  fAdr_t dest = cp.adr1;
1853  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1854  reply.errMsg = "invalid address\n";
1855  reply.mode = CtlPkt::NEG_REPLY;
1856  return false;
1857  }
1858  int rtx = rt->getRteIndex(comt,dest);
1859  if (rtx != 0) {
1860  reply.comtree = comt;
1861  reply.adr1 = dest;
1862  if (Forest::validUcastAdr(dest)) {
1863  int lnk = ctt->getLink(rt->getLink(rtx));
1864  reply.link = lnk;
1865  } else {
1866  reply.link = 0;
1867  }
1868  return true;
1869  }
1870  reply.errMsg = "get route: no route for specified address";
1871  reply.mode = CtlPkt::NEG_REPLY;
1872  return false;
1873 }
1874 
1875 bool RouterCore::modRoute(CtlPkt& cp, CtlPkt& reply) {
1876  comt_t comt = cp.comtree;
1877  if (!ctt->validComtree(comt)) {
1878  reply.errMsg = "comtree not defined at this router\n";
1879  reply.mode = CtlPkt::NEG_REPLY;
1880  return false;
1881  }
1882  fAdr_t dest = cp.adr1;
1883  if (!Forest::validUcastAdr(dest) && !Forest::mcastAdr(dest)) {
1884  reply.errMsg = "invalid address\n";
1885  reply.mode = CtlPkt::NEG_REPLY;
1886  return false;
1887  }
1888  int rtx = rt->getRteIndex(comt,dest);
1889  if (rtx != 0) {
1890  if (cp.link != 0) {
1891  if (Forest::mcastAdr(dest)) {
1892  reply.errMsg = "modify route: cannot "
1893  "set link in multicast route";
1894  reply.mode = CtlPkt::NEG_REPLY;
1895  return false;
1896  }
1897  rt->setLink(rtx,cp.link);
1898  }
1899  return true;
1900  }
1901  reply.errMsg = "modify route: invalid route";
1902  reply.mode = CtlPkt::NEG_REPLY;
1903  return false;
1904 }
1905 
1916 bool RouterCore::getRouteSet(CtlPkt& cp, CtlPkt& reply) {
1917  int rIndex = cp.index1;
1918  if (rIndex == 0)
1919  rIndex = rt->firstRteIndex(); // 0 means first route
1920  else if (!rt->validRteIndex(rIndex)) {
1921  reply.errMsg = "get route set: invalid route number";
1922  reply.mode = CtlPkt::NEG_REPLY;
1923  return false;
1924  }
1925  reply.index1 = rIndex;
1926  int count = min(10,cp.count);
1927  int i = 0;
1928  while (i < count && rIndex != 0) {
1929  string s; rt->entry2string(rIndex,s); //s.push_back('\n');
1930  reply.stringData.append(s);
1931  if (reply.stringData.length() > 1300) {
1932  reply.errMsg = "get route set: error while formatting "
1933  "reply";
1934  reply.mode = CtlPkt::NEG_REPLY;
1935  return false;
1936  }
1937  i++; rIndex = rt->nextRteIndex(rIndex);
1938  }
1939  reply.index2 = rIndex; reply.count = i;
1940  return true;
1941 }
1942 
1953 bool RouterCore::addFilter(CtlPkt& cp, CtlPkt& reply) {
1954  fltx fx = pktLog->addFilter();
1955  if (fx == 0) {
1956  reply.errMsg = "add filter: cannot add filter";
1957  reply.mode = CtlPkt::NEG_REPLY;
1958  return false;
1959  }
1960  reply.index1 = fx;
1961  return true;
1962 }
1963 
1964 bool RouterCore::dropFilter(CtlPkt& cp, CtlPkt& reply) {
1965  pktLog->dropFilter(cp.index1);
1966  return true;
1967 }
1968 
1969 bool RouterCore::getFilter(CtlPkt& cp, CtlPkt& reply) {
1970  fltx fx = cp.index1;
1971  if (!pktLog->validFilter(fx)) {
1972  reply.errMsg = "get filter: invalid filter index";
1973  reply.mode = CtlPkt::NEG_REPLY;
1974  return false;
1975  }
1976  PacketFilter& f = pktLog->getFilter(fx);
1977  f.toString(reply.stringData);
1978  return true;
1979 }
1980 
1981 bool RouterCore::modFilter(CtlPkt& cp, CtlPkt& reply) {
1982  fltx fx = cp.index1;
1983  if (!pktLog->validFilter(fx)) {
1984  reply.errMsg = "mod filter: invalid filter index";
1985  reply.mode = CtlPkt::NEG_REPLY;
1986  return false;
1987  }
1988  PacketFilter& f = pktLog->getFilter(fx);
1989  f.fromString(cp.stringData);
1990  return true;
1991 }
1992 
2003 bool RouterCore::getFilterSet(CtlPkt& cp, CtlPkt& reply) {
2004  fltx fx = cp.index1;
2005  if (fx == 0) {
2006  fx = pktLog->firstFilter(); // 0 means start with first filter
2007  } else if (!pktLog->validFilter(fx)) {
2008  reply.errMsg = "get filter set: invalid filter index";
2009  reply.mode = CtlPkt::NEG_REPLY;
2010  return false;
2011  }
2012  reply.index1 = fx;
2013  int count = min(10,cp.count);
2014  int i = 0;
2015  string s; stringstream ss;
2016  while (i < count && fx != 0) {
2017  PacketFilter& f = pktLog->getFilter(fx);
2018  ss.str(""); ss.clear(); ss << fx << " ";
2019  reply.stringData.append(ss.str());
2020  reply.stringData.append(f.toString(s));
2021  reply.stringData.push_back('\n');
2022 
2023  if (reply.stringData.length() > 1300) {
2024  reply.errMsg = "get filter set: error while "
2025  "formatting reply";
2026  reply.mode = CtlPkt::NEG_REPLY;
2027  return false;
2028  }
2029  i++; fx = pktLog->nextFilter(fx);
2030  }
2031  reply.index2 = fx; reply.count = i;
2032  return true;
2033 }
2034 
2041 bool RouterCore::getLoggedPackets(CtlPkt& cp, CtlPkt& reply) {
2042  reply.count = pktLog->extract(1300, reply.stringData);
2043  return true;
2044 }
2045 
2053  pktLog->turnOnLogging(cp.index1 == 1 ? true : false);
2054  pktLog->enableLocalLog(cp.index2 == 1 ? true : false);
2055  return true;
2056 }
2057 
2066 bool RouterCore::setLeafRange(CtlPkt& cp, CtlPkt& reply) {
2067  if (!booting) {
2068  reply.errMsg = "attempting to set leaf address range when "
2069  "not booting";
2070  reply.mode = CtlPkt::NEG_REPLY;
2071  return false;
2072  }
2073  firstLeafAdr = cp.adr1;
2074  fAdr_t lastLeafAdr = cp.adr2;
2075  if (firstLeafAdr > lastLeafAdr) {
2076  reply.errMsg = "request contained empty leaf address range";
2077  reply.mode = CtlPkt::NEG_REPLY;
2078  return false;
2079  }
2080  leafAdr = new UiSetPair((lastLeafAdr - firstLeafAdr)+1);
2081  return true;
2082 }
2083 
2088 void RouterCore::sendConnDisc(int lnk, Forest::ptyp_t type) {
2089  pktx px = ps->alloc();
2090  Packet& p = ps->getPacket(px);
2091 
2092  uint64_t nonce = lt->getNonce(lnk);
2093  p.length = Forest::OVERHEAD + 8; p.type = type; p.flags = 0;
2094  p.comtree = Forest::CONNECT_COMT;
2095  p.srcAdr = myAdr; p.dstAdr = lt->getPeerAdr(lnk);
2096  p.payload()[0] = htonl((int) (nonce >> 32));
2097  p.payload()[1] = htonl((int) (nonce & 0xffffffff));
2098 
2099  sendControl(px,nonce,lnk);
2100 }
2101 
2110 bool RouterCore::sendCpReq(CtlPkt& cp, fAdr_t dest) {
2111  pktx px = ps->alloc();
2112  if (px == 0) {
2113  cerr << "RouterCore::sendCpReq: no packets left in packet "
2114  "store\n";
2115  return false;
2116  }
2117  Packet& p = ps->getPacket(px);
2118 
2119  // pack cp into p, setting mode and seq number
2120  cp.mode = CtlPkt::REQUEST;
2121  cp.seqNum = seqNum;
2122  cp.payload = p.payload();
2123  if (cp.pack() == 0) {
2124  cerr << "RouterCore::sendCpReq: control packet packing error\n";
2125  return false;
2126  }
2127  p.length = Forest::OVERHEAD + cp.paylen;
2128  p.type = Forest::NET_SIG; p.flags = 0;
2130  p.srcAdr = myAdr; p.dstAdr = dest;
2131  p.inLink = 0;
2132 
2133  sendControl(px,seqNum++,0);
2134  return true;
2135 }
2136 
2139 bool RouterCore::sendControl(pktx px, uint64_t pid, int lnk) {
2140  Packet& p = ps->getPacket(px); p.pack();
2141 
2142  // now, make copy of packet and save it in pending
2143  pktx cx = ps->fullCopy(px);
2144  if (cx == 0) {
2145  cerr << "RouterCore::sendControl: no packets left in packet "
2146  "store\n";
2147  return false;
2148  }
2149 
2150  // save a record of the packet in pending map
2151  pair<uint64_t,ControlInfo> cpp;
2152  cpp.first = pid;
2153  cpp.second.px = cx; cpp.second.nSent = 1; cpp.second.timestamp = now;
2154  cpp.second.lnk = lnk;
2155  pending->insert(cpp);
2156 
2157  // send the packet
2158  comt_t comt = p.comtree;
2159  if (booting) {
2160  pktLog->log(px,lnk,true,now); iop->send(px,lnk);
2161  } else if (lnk != 0) {
2162  int ctx; int clnk; int qid;
2163  if ((ctx = ctt->getComtIndex(comt)) == 0 ||
2164  (clnk = ctt->getComtLink(comt,lnk)) == 0 ||
2165  (qid = ctt->getLinkQ(clnk)) == 0 ||
2166  (!qm->enq(px,qid,now))) {
2167  ps->free(px);
2168  }
2169  } else if (booting) {
2170  pktLog->log(px,0,true,now); iop->send(px,0);
2171  } else {
2172  forward(px,ctt->getComtIndex(comt));
2173  }
2174  return true;
2175 }
2176 
2184  map<uint64_t,ControlInfo>::iterator pp;
2185  list<uint64_t> dropList;
2186  for (pp = pending->begin(); pp != pending->end(); pp++) {
2187  if (now < pp->second.timestamp + 1000000000) continue;
2188  pktx px = pp->second.px;
2189  Packet& p = ps->getPacket(px);
2190  string s;
2191  if (pp->second.nSent >= 3) { // give up on this packet
2192  cerr << "RouterCore::resendControl: received no reply "
2193  "to control packet after three attempts\n"
2194  << p.toString(s);
2195  ps->free(px); dropList.push_front(pp->first); continue;
2196  }
2197  // make copy of packet and send the copy
2198  pp->second.timestamp = now;
2199  pp->second.nSent++;
2200  pktx cx = ps->fullCopy(px);
2201  if (cx == 0) {
2202  cerr << "RouterCore::resendControl: no packets left in "
2203  "packet store\n";
2204  break;
2205  }
2206  int lnk = pp->second.lnk; comt_t comt = p.comtree;
2207  if (booting) {
2208  pktLog->log(cx,lnk,true,now); iop->send(cx,lnk);
2209  } else if (lnk != 0) {
2210  int ctx; int clnk; int qid;
2211  if ((ctx = ctt->getComtIndex(comt)) == 0 ||
2212  (clnk = ctt->getComtLink(comt,lnk)) == 0 ||
2213  (qid = ctt->getLinkQ(clnk)) == 0 ||
2214  (!qm->enq(cx,qid,now)))
2215  ps->free(cx);
2216  } else {
2217  forward(cx,ctt->getComtIndex(comt));
2218  }
2219  }
2220  // remove expired entries from pending list
2221  for (uint64_t pid : dropList) pending->erase(pid);
2222 }
2223 
2233  Packet& reply = ps->getPacket(rx);
2234  uint64_t pid;
2235 
2236  CtlPkt cpr;
2237  if (reply.type == Forest::CONNECT || reply.type == Forest::DISCONNECT ||
2238  reply.type == Forest::SUB_UNSUB) {
2239  pid = ntohl(reply.payload()[0]); pid <<= 32;
2240  pid |= ntohl(reply.payload()[1]);
2241  } else if (reply.type == Forest::NET_SIG) {
2242  cpr.reset(reply); pid = cpr.seqNum;
2243  } else {
2244  string s;
2245  cerr << "RouterCore::handleControlReply: unexpected reply "
2246  << reply.toString(s);
2247  ps->free(rx); return;
2248  }
2249 
2250  map<uint64_t,ControlInfo>::iterator pp = pending->find(pid);
2251  if (pp == pending->end()) {
2252  // this is a reply to a request we never sent, or
2253  // possibly, a reply to a request we gave up on
2254  string s;
2255  cerr << "RouterCore::handleControlReply: unexpected reply "
2256  << reply.toString(s);
2257  ps->free(rx); return;
2258  }
2259  // handle signalling packets
2260  if (reply.type == Forest::NET_SIG) {
2261  if (cpr.mode == CtlPkt::NEG_REPLY) {
2262  string s;
2263  cerr << "RouterCore::handleControlReply: got negative "
2264  "reply to "
2265  << ps->getPacket(pp->second.px).toString(s);
2266  cerr << "reply=" << reply.toString(s);
2267  } else if (cpr.type == CtlPkt::BOOT_ROUTER) {
2268  if (booting && !setup()) {
2269  cerr << "RouterCore::handleControlReply: "
2270  "setup failed after completion of boot "
2271  "phase\n";
2272  perror("");
2273  pktLog->write(cout);
2274  exit(1);
2275  }
2276  iop->closeBootSock();
2277  booting = false;
2278  }
2279  }
2280 
2281  // free both packets and erase pending entry
2282  ps->free(pp->second.px); ps->free(rx); pending->erase(pp);
2283 }
2284 
2290 void RouterCore::returnToSender(pktx px, CtlPkt& cp) {
2291  Packet& p = ps->getPacket(px);
2292  cp.payload = p.payload();
2293  int paylen = cp.pack();
2294  if (paylen == 0) {
2295  cerr << "RouterCore::returnToSender: control packet formatting "
2296  "error, zero payload length\n";
2297  ps->free(px);
2298  }
2299  p.length = (Packet::OVERHEAD + paylen);
2300  p.flags = 0;
2301  p.dstAdr = p.srcAdr;
2302  p.srcAdr = myAdr;
2303  p.pack();
2304 
2305  if (booting) {
2306  pktLog->log(px,0,true,now);
2307  iop->send(px,0);
2308  return;
2309  }
2310 
2311  int cLnk = ctt->getComtLink(p.comtree,p.inLink);
2312  int qn = ctt->getLinkQ(cLnk);
2313  if (!qm->enq(px,qn,now)) { ps->free(px); }
2314 }
2315 
2316 } // ends namespace