forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
NetMgrDoowon.cpp
1 
9 #include "NetMgr.h"
10 #include "CpHandler.h"
11 
12 using namespace forest;
13 
23 int main(int argc, char *argv[]) {
24  uint32_t finTime;
25  //std::cout << "argv: "<<argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << endl;
26  if (argc != 4 || sscanf(argv[3],"%d", &finTime) != 1)
27  fatal("usage: NetMgr topoFile prefixFile finTime");
28  if (!init(argv[1])) {
29  fatal("NetMgr: initialization failure");
30  }
31  if (!readPrefixInfo(argv[2]))
32  fatal("can't read prefix address info");
33  sub->run(finTime);
34  exit(0);
35 }
36 
37 namespace forest {
38 
42 bool init(const char *topoFile) {
43  Misc::getTimeNs(); // initialize time reference
44  int nPkts = 10000;
45  ps = new PacketStoreTs(nPkts+1);
46 
47  logger = new Logger();
48 
49  // read NetInfo data structure from file
50  int maxNode = 100000; int maxLink = 10000;
51  int maxRtr = 5000; int maxCtl = 200;
52  int maxComtree = 10000;
53  net = new NetInfo(maxNode, maxLink, maxRtr, maxCtl);
54  comtrees = new ComtInfo(maxComtree,*net);
55  ifstream fs; fs.open(topoFile);
56  if (fs.fail() || !net->read(fs) || !comtrees->read(fs)) {
57  cerr << "NetMgr::init: could not read topology file, or error "
58  "in topology file\n";
59  return false;
60  }
61  fs.close();
62 
63  // mark all routers as DOWN
64  for (int rtr = net->firstRouter(); rtr != 0;
65  rtr = net->nextRouter(rtr)) {
66  net->setStatus(rtr,NetInfo::DOWN);
67  }
68 
69  // find node information for netMgr and cliMgr and initialize
70  // associated data
71  myAdr = 0; cliMgrAdr = comtCtlAdr = 0;
72  ipa_t rtrIp;
73  for (int c = net->firstController(); c != 0;
74  c = net->nextController(c)) {
75  net->setStatus(c,NetInfo::DOWN);
76  string s;
77  if (net->getNodeName(c,s) == "netMgr") {
78  myIp = net->getLeafIpAdr(c);
79  myAdr = net->getNodeAdr(c);
80  int lnk = net->firstLinkAt(c);
81  int rtr = net->getPeer(c,lnk);
82  int llnk = net->getLLnum(lnk,rtr);
83  int iface = net->getIface(llnk,rtr);
84  if (iface == 0) {
85  cerr << "NetMgr:init: can't find ip address "
86  << "of access router\n";
87  }
88  netMgr = c; nmRtr = rtr;
89  rtrIp = net->getIfIpAdr(rtr,iface);
90  rtrAdr = net->getNodeAdr(rtr);
91  } else if (net->getNodeName(c,s) == "cliMgr") {
92  cliMgrAdr = net->getNodeAdr(c);
93  } else if (net->getNodeName(c,s) == "comtCtl") {
95  }
96  }
97 
98  ipp_t rtrPort = 0; // until router boots
99  uint64_t nonce = 0; // likewise
100  sub = new Substrate(myAdr,myIp,rtrAdr,rtrIp,rtrPort,nonce,500,
102  if (!sub->init()) {
103  logger->log("init: can't initialize substrate",2);
104  return false;
105  }
106  sub->setRtrReady(false);
107 
108  if (myAdr == 0 || cliMgrAdr == 0) {
109  cerr << "could not find netMgr or cliMgr in topology file\n";
110  return false;
111  }
112  return true;
113 }
114 
115 void cleanup() {
116  delete ps; delete net; delete comtrees; delete sub;
117 }
118 
133 void* handler(void *qp) {
134  Queue& inq = ((Substrate::QueuePair *) qp)->in;
135  Queue& outq = ((Substrate::QueuePair *) qp)->out;
136  CpHandler cph(&inq, &outq, myAdr, logger, ps);
137 
138  while (true) {
139  pktx px = inq.deq();
140  bool success = false;
141  if (px < 0) {
142  // in this case, p is really a negated socket number
143  // for a remote client
144  std::cout << "[DEBUG] -- px < 0 " << px << std::endl;
145  int sock = -px;
146  success = handleConsole(sock, cph);
147  std::cout << "[DEBUG] -- outside of handleConsole " << success << std::endl;
148  } else {
149  Packet& p = ps->getPacket(px);
150  string s;
151  CtlPkt cp(p.payload(),p.length-Forest::OVERHEAD);
152  cp.unpack();
153  switch (cp.type) {
154  case CtlPkt::CLIENT_CONNECT:
155  case CtlPkt::CLIENT_DISCONNECT:
156  success = handleConDisc(px,cp,cph);
157  break;
158  case CtlPkt::NEW_SESSION:
159  success = handleNewSession(px,cp,cph);
160  break;
161  case CtlPkt::CANCEL_SESSION:
162  success = handleCancelSession(px,cp,cph);
163  break;
164  case CtlPkt::BOOT_LEAF:
165  cph.setTunnel(p.tunIp,p.tunPort);
166  // allow just one node to boot at a time
167  net->lock();
168  success = handleBootLeaf(px,cp,cph);
169  net->unlock();
170  cph.setTunnel(0,0);
171  break;
172  case CtlPkt::BOOT_ROUTER:
173  cph.setTunnel(p.tunIp,p.tunPort);
174  // allow just one node to boot at a time
175  net->lock();
176  success = handleBootRouter(px,cp,cph);
177  net->unlock();
178  cph.setTunnel(0,0);
179  break;
180  default:
181  cph.errReply(px,cp,"invalid control packet "
182  "type for NetMgr");
183  break;
184  }
185  }
186  if (!success) {
187  string s;
188  cerr << "handler: operation failed\n"
189  << ps->getPacket(px).toString(s);
190  }
191  ps->free(px); // release px now that we're done
192  outq.enq(0); // signal completion to main thread
193  }
194 }
195 
202 bool handleConsole(int sock, CpHandler& cph) {
203  std::cout << "[DEBUG] -- inside of handleConsole" << std::endl;
204  NetBuffer buf(sock,1024);
205 
206  // login user at remote console using password in netMgrUsers file
207  // command processing loop
208  string cmd, reply = "";
209  while (buf.readAlphas(cmd)) {
210  std::cout << "[DEBUG] -- CMD: " << cmd << std::endl;
211  // reply = "success";
212  if (cmd == "getNet") {
213  getNet(buf,reply);
214  } else if (cmd == "getLinkTable") {
215  getLinkSet(buf,reply,cph);
216  // more of these (getIfaceTable, getComtree,...)
217  } else if (cmd == "over" && buf.nextLine()) {
218  // ignore
219  } else if (cmd == "overAndOut" && buf.nextLine()) {
220  break;
221  } else {
222  reply = "unrecognized input";
223  }
224 
225  if (sock == -1) break;
226 
227  reply += "over\n";
228  cout << "TOTAL\n" << reply << endl;
229  Np4d::sendString(sock,reply);
230  }
231  return true;
232 }
233 
234 void getNet(NetBuffer& buf, string& reply) {
235  // return net->toString(s) where net is the netInfo object
236  // net->toString(reply);
237  std::cout << "[DEBUG] -- " << __FUNCTION__ << "() \n" << reply << std::endl;
238 }
239 
240 void getLinkSet(NetBuffer& buf, string& reply, CpHandler& cph) {
241  // get list of links from router
242  // for each link in list, get the link table entry from router
243  // return each link to the Console, with one link per line,
244  // each line starting with the word link, followed by the
245  // link number and remaining fields, with spaces separating items
246  string router;
247  CtlPkt repCp; pktx rp;
248  if (buf.verify(':') && buf.readName(router) && !router.empty() && router.size() >= 2){
249  std::cout << "[DEBUG] -- " << __FUNCTION__ << "() \n" << router << std::endl;
250  int rNum = net->getNodeNum(router);
251  std::cout << "[DEBUG] -- " << __FUNCTION__ << "() \n" << net->getNodeAdr(rNum) << std::endl;
252  int firstLinkNum = 1;
253  int numOfLinks = 3; //default is 10
254  while (firstLinkNum != 0){
255  rp = cph.getLinkSet(net->getNodeAdr(rNum), repCp, firstLinkNum, numOfLinks);
256  cout << __FILE__ << " " << __FUNCTION__ << " first link num " << firstLinkNum << " numOfLinks " << numOfLinks << endl;
257  firstLinkNum = repCp.nextLinkNum;
258  cout << __FILE__ << " " << __FUNCTION__ << " Next link num " << repCp.nextLinkNum << endl;
259  if (repCp.lt == NULL) {
260  reply = "No information for " + router + "\n";
261  }
262  else{
263  stringstream ss;
264  string ip, fAdr, peerType;
265  cout << __FUNCTION__ << " " << repCp.lt << endl;
266  cout << __FUNCTION__ << " first " << repCp.lt->firstLink() << endl;
267  for (int i = repCp.lt->firstLink(); i != 0; i = repCp.lt->nextLink(i)) {
268  Np4d::ip2string(repCp.lt->getPeerIpAdr(i),ip);
269  Forest::fAdr2string(repCp.lt->getPeerAdr(i), fAdr);
270  Forest::nodeType2string(repCp.lt->getPeerType(i), peerType);
271  ss << i << " " << repCp.lt->getIface(i) << " " << ip << " " << repCp.lt->getPeerPort(i);
272  ss << " " << peerType << " " << fAdr << " ";
273  ss << "(" << repCp.lt->getRates(i).bitRateUp << "," << repCp.lt->getRates(i).bitRateDown\
274  << "," << repCp.lt->getRates(i).pktRateUp << "," << repCp.lt->getRates(i).pktRateDown << ")"<< "\r\n";
275  }
276  cout << __FILE__ << " " << ss.str();
277  reply += ss.str();
278  }
279  }
280  } else {
281  reply = "Unrecognized input - for example r1";
282  }
283 
284 }
285 
298 bool handleConDisc(pktx px, CtlPkt& cp, CpHandler& cph) {
299  Packet& p = ps->getPacket(px);
300 
301  // send positive reply back to router
302  CtlPkt repCp(cp.type, CtlPkt::POS_REPLY, cp.seqNum);
303  cph.sendReply(repCp,p.srcAdr);
304 
305  // now, send notification to client manager
306  pktx reply;
307  if (cp.type == CtlPkt::CLIENT_CONNECT)
308  reply = cph.clientConnect(cliMgrAdr,cp.adr1,p.srcAdr,repCp);
309  else
310  reply = cph.clientDisconnect(cliMgrAdr,cp.adr1,p.srcAdr,repCp);
311  if (reply == 0) return false;
312  ps->free(reply);
313  return true;
314 }
315 
328 bool handleNewSession(pktx px, CtlPkt& cp, CpHandler& cph) {
329  Packet& p = ps->getPacket(px);
330  // determine which router to use
331  fAdr_t rtrAdr;
332  if (!findCliRtr(cp.ip1,rtrAdr)) {
333  cph.errReply(px,cp,"No router assigned to client's IP");
334  return true;
335  }
336  int rtr = net->getNodeNum(rtrAdr);
337  RateSpec clientRates = cp.rspec1;
338 
339  // find first iface for this router - refine this later
340  int iface = 1;
341  while (iface < net->getNumIf(rtr) && !net->validIf(rtr,iface)) iface++;
342 
343  // generate nonce to be used by client in connect packet
344  uint64_t nonce = generateNonce();
345 
346  fAdr_t clientAdr = setupLeaf(0,px,cp,rtr,iface,nonce,cph);
347  if (clientAdr == 0) return false;
348 
349  // send positive reply back to sender
350  CtlPkt repCp(CtlPkt::NEW_SESSION,CtlPkt::POS_REPLY,cp.seqNum);
351  repCp.adr1 = clientAdr; repCp.adr2 = rtrAdr; repCp.adr3 = comtCtlAdr;
352  repCp.ip1 = net->getIfIpAdr(rtr,iface);
353  repCp.port1 = net->getIfPort(rtr,iface);
354  repCp.nonce = nonce;
355  cph.sendReply(repCp,p.srcAdr);
356  return true;
357 }
358 
376 fAdr_t setupLeaf(int leaf, pktx px, CtlPkt& cp, int rtr, int iface,
377  uint64_t nonce, CpHandler& cph, bool useTunnel) {
378 
379  Forest::ntyp_t leafType; int leafLink; fAdr_t leafAdr; RateSpec rates;
380 
381  // first add the link at the router
382  fAdr_t rtrAdr = net->getNodeAdr(rtr);
383  fAdr_t dest = (useTunnel ? 0 : rtrAdr);
384  pktx reply; CtlPkt repCp;
385  if (leaf == 0) { // dynamic client
386  leafType = Forest::CLIENT; leafLink = 0;
387  leafAdr = 0; rates = cp.rspec1;
388  reply = cph.addLink(dest,leafType,iface,nonce,repCp);
389  if (!processReply(px,cp,reply,repCp,cph,
390  "could not add link to leaf"))
391  return 0;
392  leafLink = repCp.link; leafAdr = repCp.adr1;
393  } else { // static leaf with specified parameters
394  leafType = net->getNodeType(leaf);
395  int lnk = net->firstLinkAt(leaf);
396  leafLink = net->getLLnum(lnk,rtr);
397  leafAdr = net->getNodeAdr(leaf);
398  rates = net->getLinkRates(lnk);
399  ipa_t leafIp = net->getLeafIpAdr(leaf);
400  reply = cph.addLink(dest,leafType,iface,leafLink,
401  leafIp,0,leafAdr,nonce,repCp);
402  if (!processReply(px,cp,reply,repCp,cph,
403  "could not add link to leaf"))
404  return 0;
405  }
406 
407  // next set the link rate
408  reply = cph.modLink(dest,leafLink,rates,repCp);
409  if (!processReply(px,cp,reply,repCp,cph,"could not set link rates"))
410  return 0;
411 
412  // now add the new leaf to the leaf connection comtree
413  reply = cph.addComtreeLink(dest,Forest::CONNECT_COMT,
414  leafLink,-1,repCp);
415  if (!processReply(px,cp,reply,repCp,cph,"could not add leaf to "
416  "connection comtree"))
417  return 0;
418 
419  // now modify comtree link rate
420  int ctx = comtrees->getComtIndex(Forest::CONNECT_COMT);
421  rates = comtrees->getDefLeafRates(ctx);
422  comtrees->releaseComtree(ctx);
423  reply = cph.modComtreeLink(dest,Forest::CONNECT_COMT,leafLink,
424  rates,repCp);
425  if (!processReply(px,cp,reply,repCp,cph,"could not set rate on "
426  "connection comtree"))
427  return 0;
428 
429  // now add the new leaf to the client signaling comtree
430  reply = cph.addComtreeLink(dest,Forest::CLIENT_SIG_COMT,
431  leafLink,-1,repCp);
432  if (!processReply(px,cp,reply,repCp,cph,"could not add leaf to client "
433  "signalling comtree"))
434  return 0;
435 
436  // and modify its comtree link rate
438  rates = comtrees->getDefLeafRates(ctx);
439  comtrees->releaseComtree(ctx);
440  reply = cph.modComtreeLink(dest,Forest::CLIENT_SIG_COMT,leafLink,
441  rates,repCp);
442  if (!processReply(px,cp,reply,repCp,cph,"could not set rate on client "
443  "signaling comtree"))
444  return 0;
445 
446  if (leafType == Forest::CLIENT) return leafAdr;
447 
448  // for controllers, also add to the network signaling comtree
449  reply = cph.addComtreeLink(dest,Forest::NET_SIG_COMT,
450  leafLink,-1,repCp);
451  if (!processReply(px,cp,reply,repCp,cph,"could not add leaf to network "
452  "signalling comtree"))
453  return 0;
454 
455  // and modify comtree link rate
457  rates = comtrees->getDefLeafRates(ctx);
458  comtrees->releaseComtree(ctx);
459  reply = cph.modComtreeLink(dest,Forest::NET_SIG_COMT,leafLink,
460  rates,repCp);
461  if (!processReply(px,cp,reply,repCp,cph,"could not set rate on network "
462  "signaling comtree"))
463  return 0;
464  return leafAdr;
465 }
466 
473 bool handleCancelSession(pktx px, CtlPkt& cp, CpHandler& cph) {
474  Packet& p = ps->getPacket(px);
475  fAdr_t clientAdr = cp.adr1;
476  fAdr_t rtrAdr = cp.adr2;
477 
478  // verify that clientAdr is in range for router
479  int rtr = net->getNodeNum(rtrAdr);
480  if (rtr == 0) {
481  cph.errReply(px,cp,"no router with specified address");
482  return 0;
483  }
484  pair<fAdr_t,fAdr_t> range;
485  net->getLeafRange(rtr, range);
486  if (clientAdr < range.first || clientAdr > range.second) {
487  cph.errReply(px,cp,"client address not in router's range");
488  return false;
489  }
490 
491  pktx reply; CtlPkt repCp;
492  reply = cph.dropLink(rtrAdr,0,clientAdr,repCp);
493  if (!processReply(px,cp,reply,repCp,cph,"could not drop link "
494  "at router"))
495  return false;
496 
497  // send positive reply back to sender
498  repCp.reset(CtlPkt::CANCEL_SESSION,CtlPkt::POS_REPLY,cp.seqNum);
499  cph.sendReply(repCp,p.srcAdr);
500  return true;
501 }
502 
514 bool handleBootLeaf(pktx px, CtlPkt& cp, CpHandler& cph) {
515  Packet& p = ps->getPacket(px);
516 
517  // first, find leaf in NetInfo object
518  int leaf;
519  for (leaf = net->firstLeaf(); leaf != 0; leaf = net->nextLeaf(leaf)) {
520  if (net->getLeafIpAdr(leaf) == p.tunIp) break;
521  }
522  if (leaf == 0) {
523  cph.errReply(px,cp,"unknown leaf address");
524  return false;
525  }
526 
527  if (net->getStatus(leaf) == NetInfo::UP) {
528  // final reply lost or delayed, resend and quit
529  CtlPkt repCp(CtlPkt::BOOT_LEAF,CtlPkt::POS_REPLY,cp.seqNum);
530  cph.sendReply(repCp,0);
531  return true;
532  }
533 
534  int lnk = net->firstLinkAt(leaf);
535  int rtr = net->getPeer(leaf,lnk);
536  fAdr_t rtrAdr = net->getNodeAdr(rtr);
537 
538  net->setStatus(leaf,NetInfo::BOOTING);
539 
540  if (net->getStatus(rtr) != NetInfo::UP) {
541  cph.errReply(px,cp,"access router is not yet up");
542  net->setStatus(leaf,NetInfo::DOWN);
543  return false;
544  }
545 
546  // find first iface for this router - refine this later
547  int iface = 1;
548  while (iface < net->getNumIf(rtr) && !net->validIf(rtr,iface)) iface++;
549  uint64_t nonce = generateNonce();
550 
551  // add link at router and configure rates/comtrees
552  CtlPkt repCp;
553  if (setupLeaf(leaf,px,cp,rtr,iface,nonce,cph) == 0) {
554  net->setStatus(leaf,NetInfo::DOWN);
555  return false;
556  }
557 
558  // Send configuration parameters to leaf
559  // 0 destination address tells cph/substrate to send using
560  // cph's tunnel parameters; this sends it to leaf
561  int reply = cph.configLeaf(0,net->getNodeAdr(leaf),rtrAdr,
562  net->getIfIpAdr(rtr,iface),
563  net->getIfPort(rtr,iface), nonce, repCp);
564  if (!processReply(px,cp,reply,repCp,cph,"could not configure "
565  "leaf node")) {
566  net->setStatus(leaf,NetInfo::DOWN);
567  return false;
568  }
569 
570  // finally, send positive ack
571  repCp.reset(CtlPkt::BOOT_LEAF,CtlPkt::POS_REPLY,cp.seqNum);
572  cph.sendReply(repCp,0); // 0 sends it directly back to leaf
573  net->setStatus(leaf,NetInfo::UP);
574 
575  logger->log("completed leaf boot request",0,p);
576  return true;
577 }
578 
580 uint64_t generateNonce() {
581  uint64_t nonce;
582  do {
583  nonce = Misc::currentTime(); // in seconds since epoch
584  nonce *= random();
585  } while (nonce == 0);
586  return nonce;
587 }
588 
608 bool processReply(pktx px, CtlPkt& cp, pktx reply, CtlPkt& repCp,
609  CpHandler& cph, const string& msg) {
610  if (reply == 0) {
611  cph.errReply(px,cp,msg + " (no response from target)");
612  ps->free(reply);
613  return false;
614  }
615  if (repCp.mode != CtlPkt::POS_REPLY) {
616  string s;
617  cph.errReply(px,cp,msg + " (" + repCp.toString(s) + ")");
618  ps->free(reply);
619  return false;
620  }
621  ps->free(reply);
622  return true;
623 }
624 
642 bool handleBootRouter(pktx px, CtlPkt& cp, CpHandler& cph) {
643  Packet& p = ps->getPacket(px);
644 
645  // find rtr index based on source address
646  ipa_t rtrAdr = p.srcAdr;
647 string s;
648 cerr << "got boot request from " << Forest::fAdr2string(rtrAdr,s) << endl;
649  int rtr;
650  for (rtr = net->firstRouter(); rtr != 0; rtr = net->nextRouter(rtr)) {
651  if (net->getNodeAdr(rtr) == rtrAdr) break;
652  }
653  if (rtr == 0) {
654  cph.errReply(px,cp,"boot request from unknown router "
655  "rejected\n");
656  logger->log("handleBootRequest: received boot request from "
657  "unknown router\n",2,p);
658  return true;
659  }
660 
661 cerr << "A\n";
662  if (net->getStatus(rtr) == NetInfo::UP) {
663  // final reply lost or delayed, resend and quit
664  CtlPkt repCp(CtlPkt::BOOT_ROUTER,CtlPkt::POS_REPLY,cp.seqNum);
665  cph.sendReply(repCp,0);
666  return true;
667  }
668 
669 cerr << "B\n";
670  net->setStatus(rtr,NetInfo::BOOTING);
671 
672  // configure leaf address range
673  CtlPkt repCp;
674  pair<fAdr_t,fAdr_t> leafRange; net->getLeafRange(rtr,leafRange);
675  int reply = cph.setLeafRange(0,leafRange.first,leafRange.second,repCp);
676  if (!processReply(px,cp,reply,repCp,cph,
677  "could not configure leaf range")) {
678  net->setStatus(rtr,NetInfo::DOWN);
679  return false;
680  }
681 
682 cerr << "C\n";
683  // add/configure interfaces
684  // for each interface in table, do an add iface
685  int nmLnk = net->getLLnum(net->firstLinkAt(netMgr),nmRtr);
686  int nmIface = net->getIface(nmLnk,nmRtr);
687  for (int i = 1; i <= net->getNumIf(rtr); i++) {
688  if (!net->validIf(rtr,i)) continue;
689  int reply = cph.addIface(0,i,net->getIfIpAdr(rtr,i),
690  net->getIfRates(rtr,i),repCp);
691  if (!processReply(px,cp,reply,repCp,cph,
692  "could not add interface at router")) {
693  net->setStatus(rtr,NetInfo::DOWN);
694  return false;
695  }
696  net->setIfPort(rtr,i,repCp.port1);
697  // if this is the network manager's router, configure port
698  // in substrate
699  if (rtr == nmRtr && i == nmIface) {
700  sub->setRtrPort(repCp.port1);
701  }
702  }
703 
704  // add/configure links to other routers
705  for (int lnk = net->firstLinkAt(rtr); lnk != 0;
706  lnk = net->nextLinkAt(rtr,lnk)) {
707  int peer = net->getPeer(rtr,lnk);
708  if (net->getNodeType(peer) != Forest::ROUTER) continue;
709  if (!setupEndpoint(lnk,rtr,px,cp,cph,true)) {
710  net->setStatus(rtr,NetInfo::DOWN);
711  return false;
712  }
713  }
714 
715  // add/configure comtrees
716  for (int ctx = comtrees->firstComtree(); ctx != 0;
717  ctx = comtrees->nextComtree(ctx)) {
718  fAdr_t rtrAdr = net->getNodeAdr(rtr);
719  if (!comtrees->isComtNode(ctx,rtrAdr)) continue;
720  if (!setupComtree(ctx,rtr,px,cp,cph,true)) {
721  comtrees->releaseComtree(ctx);
722  net->setStatus(rtr,NetInfo::DOWN);
723  return false;
724  }
725  }
726 
727  // if this is net manager's router, configure link
728  if (rtr == nmRtr) {
729  uint64_t nonce = generateNonce();
730  sub->setNonce(nonce);
731  if (setupLeaf(netMgr,px,cp,rtr,nmIface,nonce,cph,true) == 0) {
732  fatal("cannot configure NetMgr's access link");
733  }
734  }
735 
736  // finally, send positive reply
737  repCp.reset(CtlPkt::BOOT_ROUTER,CtlPkt::POS_REPLY,cp.seqNum);
738  cph.sendReply(repCp,0);
739  net->setStatus(rtr,NetInfo::UP);
740 
741  if (rtr == nmRtr) sub->setRtrReady(true);
742 
743  logger->log("completed boot request",0,p);
744  return true;
745 }
746 
760 bool setupEndpoint(int lnk, int rtr, pktx px, CtlPkt& cp, CpHandler& cph,
761  bool useTunnel) {
762  int llnk = net->getLLnum(lnk,rtr);
763  int iface = net->getIface(llnk,rtr);
764  fAdr_t rtrAdr = net->getNodeAdr(rtr);
765 
766  int peer = net->getPeer(rtr,lnk);
767  fAdr_t peerAdr = net->getNodeAdr(peer);
768  int plnk = net->getLLnum(lnk,peer);
769  int i = net->getIface(plnk,peer);
770  ipa_t peerIp = net->getIfIpAdr(peer,i);
771  ipp_t peerPort = 0;
772 
773  uint64_t nonce;
774  if (net->getStatus(peer) != NetInfo::UP) {
775  nonce = generateNonce();
776  net->setNonce(lnk,nonce);
777  } else {
778  peerPort = net->getIfPort(peer,i);
779  nonce = net->getNonce(lnk);
780  }
781  CtlPkt repCp;
782  fAdr_t dest = (useTunnel ? 0 : rtrAdr);
783  int reply = cph.addLink(dest,Forest::ROUTER,iface,llnk,peerIp,
784  peerPort,peerAdr,nonce,repCp);
785  if (!processReply(px,cp,reply,repCp,cph,"could not add link at router"))
786  return false;
787 
788  // now, send modify link message, to set data rates
789  RateSpec rs = net->getLinkRates(lnk);
790  if (rtr == net->getLeft(lnk)) rs.flip();
791  reply = cph.modLink(dest,llnk,rs,repCp);
792  if (!processReply(px,cp,reply,repCp,cph,
793  "could not set link rates at router"))
794  return false;
795  return true;
796 }
797 
806 bool setupComtree(int ctx, int rtr, pktx px, CtlPkt& cp, CpHandler& cph,
807  bool useTunnel) {
808  fAdr_t rtrAdr = net->getNodeAdr(rtr);
809 
810  comt_t comt = comtrees->getComtree(ctx);
811 
812  // first step is to add comtree at router
813  CtlPkt repCp;
814  fAdr_t dest = (useTunnel ? 0 : rtrAdr);
815  int reply = cph.addComtree(dest,comt,repCp);
816  if (!processReply(px,cp,reply,repCp,cph,
817  "could not add comtree at router"))
818  return false;
819 
820  // next, add links to the comtree and set their data rates
821  int plnk = comtrees->getPlink(ctx,rtrAdr);
822  int parent = net->getPeer(rtr,plnk);
823  for (int lnk = net->firstLinkAt(rtr); lnk != 0;
824  lnk = net->nextLinkAt(rtr,lnk)) {
825  if (!comtrees->isComtLink(ctx,lnk)) continue;
826  int peer = net->getPeer(rtr,lnk);
827  if (net->getNodeType(peer) != Forest::ROUTER) continue;
828 
829  // get information about this link
830  int llnk = net->getLLnum(lnk,rtr);
831  fAdr_t peerAdr = net->getNodeAdr(peer);
832  bool peerCoreFlag = comtrees->isCoreNode(ctx,peerAdr);
833 
834  // first, add comtree link
835  reply = cph.addComtreeLink(dest,comt,llnk,
836  peerCoreFlag,repCp);
837  if (!processReply(px,cp,reply,repCp,cph,
838  "could not add comtree link at router"))
839  return false;
840 
841  // now, set link rates
842  RateSpec rs;
843  if (peer == parent) {
844  rs = comtrees->getLinkRates(ctx,rtrAdr);
845  rs.flip();
846  } else {
847  rs = comtrees->getLinkRates(ctx,peerAdr);
848  }
849  reply = cph.modComtreeLink(dest,comt,llnk,rs,repCp);
850  if (!processReply(px,cp,reply,repCp,cph,
851  "could not set comtree link rates at router"))
852  return false;
853  }
854  // finally, we need to modify overall comtree attributes
855  reply = cph.modComtree(dest,comt,net->getLLnum(plnk,rtr),
856  comtrees->isCoreNode(ctx,rtrAdr),repCp);
857  if (!processReply(px,cp,reply,repCp,cph,
858  "could not set comtree parameters"))
859  return false;
860  return true;
861 }
862 
868 bool findCliRtr(ipa_t cliIp, fAdr_t& rtrAdr) {
869  string cip;
870  Np4d::ip2string(cliIp,cip);
871  for (unsigned int i = 0; i < (unsigned int) numPrefixes; ++i) {
872  string ip = prefixes[i].prefix;
873  unsigned int j = 0;
874  while (j < ip.size() && j < cip.size()) {
875  if (ip[j] != '*' && cip[j] != ip[j]) break;
876  if (ip[j] == '*' ||
877  (j+1 == ip.size() && j+1 == cip.size())) {
878  rtrAdr = prefixes[i].rtrAdr;
879  return true;
880  }
881  j++;
882  }
883  }
884  // if no prefix for client address, select router at random
885  int i = randint(0,net->getNumRouters()-1);
886  for (int r = net->firstRouter(); r != 0; r = net->nextRouter(r)) {
887  if (i-- == 0) {
888  rtrAdr = net->getNodeAdr(r); return true;
889  }
890  }
891  return false; // should never reach here
892 }
893 
898 bool readPrefixInfo(char filename[]) {
899  ifstream ifs; ifs.open(filename);
900  if(ifs.fail()) return false;
901  Misc::skipBlank(ifs);
902  int i = 0;
903  while(!ifs.eof()) {
904  string pfix; fAdr_t rtrAdr;
905  ifs >> pfix;
906  if(!Forest::readForestAdr(ifs,rtrAdr))
907  break;
908  prefixes[i].prefix = pfix;
909  prefixes[i].rtrAdr = rtrAdr;
910  Misc::skipBlank(ifs);
911  i++;
912  }
913  numPrefixes = i;
914  cout << "read address info for " << numPrefixes << " prefixes" << endl;
915  return true;
916 }
917 
961 } // ends namespace