forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
NetMgr.cpp
Go to the documentation of this file.
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 
26  if (argc != 4 ||
27  sscanf(argv[3],"%d", &finTime) != 1)
28  fatal("usage: NetMgr topoFile prefixFile finTime");
29  if (!init(argv[1])) {
30  fatal("NetMgr: initialization failure");
31  }
32  if (!readPrefixInfo(argv[2]))
33  fatal("can't read prefix address info");
34  sub->run(finTime);
35  exit(0);
36 }
37 
38 namespace forest {
39 
43 bool init(const char *topoFile) {
44  Misc::getTimeNs(); // initialize time reference
45  int nPkts = 10000;
46  ps = new PacketStoreTs(nPkts+1);
47 
48  logger = new Logger();
49 
50  // read NetInfo data structure from file
51  int maxNode = 100000; int maxLink = 10000;
52  int maxRtr = 5000; int maxCtl = 200;
53  int maxComtree = 10000;
54  net = new NetInfo(maxNode, maxLink, maxRtr, maxCtl);
55  comtrees = new ComtInfo(maxComtree,*net);
56  admTbl = new AdminTable(100);
57 
58  dummyRecord = new char[RECORD_SIZE];
59  for (char *p = dummyRecord; p < dummyRecord+RECORD_SIZE; p++) *p = ' ';
60  dummyRecord[0] = '-'; dummyRecord[RECORD_SIZE-1] = '\n';
61 
62  ifstream fs; fs.open(topoFile);
63  if (fs.fail() || !net->read(fs) || !comtrees->read(fs)) {
64  cerr << "NetMgr::init: could not read topology file, or error "
65  "in topology file\n";
66  return false;
67  }
68  fs.close();
69 
70  // mark all routers as DOWN
71  for (int rtr = net->firstRouter(); rtr != 0;
72  rtr = net->nextRouter(rtr)) {
73  net->setStatus(rtr,NetInfo::DOWN);
74  }
75 
76  // find node information for netMgr and cliMgr and initialize
77  // associated data
78  myAdr = 0; cliMgrAdr = comtCtlAdr = 0;
79  ipa_t rtrIp;
80  for (int c = net->firstController(); c != 0;
81  c = net->nextController(c)) {
82  net->setStatus(c,NetInfo::DOWN);
83  string s;
84  if (net->getNodeName(c,s) == "netMgr") {
85  myIp = net->getLeafIpAdr(c);
86  myAdr = net->getNodeAdr(c);
87  int lnk = net->firstLinkAt(c);
88  int rtr = net->getPeer(c,lnk);
89  int llnk = net->getLLnum(lnk,rtr);
90  int iface = net->getIface(llnk,rtr);
91  if (iface == 0) {
92  cerr << "NetMgr:init: can't find ip address "
93  << "of access router\n";
94  }
95  netMgr = c; nmRtr = rtr;
96  rtrIp = net->getIfIpAdr(rtr,iface);
97  rtrAdr = net->getNodeAdr(rtr);
98  } else if (net->getNodeName(c,s) == "cliMgr") {
99  cliMgrAdr = net->getNodeAdr(c);
100  } else if (net->getNodeName(c,s) == "comtCtl") {
101  comtCtlAdr = net->getNodeAdr(c);
102  }
103  }
104 
105  ipp_t rtrPort = 0; // until router boots
106  uint64_t nonce = 0; // likewise
107  sub = new Substrate(myAdr,myIp,rtrAdr,rtrIp,rtrPort,nonce,500,
109  if (!sub->init()) {
110  logger->log("init: can't initialize substrate",2);
111  return false;
112  }
113  sub->setRtrReady(false);
114 
115  if (myAdr == 0 || cliMgrAdr == 0) {
116  cerr << "could not find netMgr or cliMgr in topology file\n";
117  return false;
118  }
119 
120  maxRecord = 0;
121  // read adminData file
122  adminFile.open("adminData");
123  if (!adminFile.good() || !admTbl->read(adminFile)) {
124  logger->log("NetMgr::init: could not read adminData "
125  "file",2);
126  return false;
127  }
128  adminFile.clear();
129 
130 
131  // if size of file is not equal to count*RECORD_SIZE
132  // re-write the file using padded records
133  int n = admTbl->getMaxAdx();
134  adminFile.seekp(0,ios_base::end);
135  long len = adminFile.tellp();
136  if (len != (n+1)*RECORD_SIZE) {
137  for (int adx = 0; adx <= n; adx++) writeAdminRecord(adx);
138  }
139  if (pthread_mutex_init(&adminFileLock,NULL) != 0) {
140  logger->log("NetMgr::init: could not initialize lock "
141  "on client data file",2);
142  return false;
143  }
144 
145  return true;
146 }
147 
148 void cleanup() {
149  delete ps; delete net; delete comtrees; delete sub;
150 }
151 
166 void* handler(void *qp) {
167  Queue& inq = ((Substrate::QueuePair *) qp)->in;
168  Queue& outq = ((Substrate::QueuePair *) qp)->out;
169  CpHandler cph(&inq, &outq, myAdr, logger, ps);
170 
171  while (true) {
172  pktx px = inq.deq();
173  bool success = false;
174  if (px < 0) {
175  // in this case, p is really a negated socket number
176  // for a remote client
177  int sock = -px;
178  success = handleConsole(sock, cph);
179  } else {
180  Packet& p = ps->getPacket(px);
181  CtlPkt cp(p.payload(),p.length-Forest::OVERHEAD);
182  cp.unpack();
183  switch (cp.type) {
184  case CtlPkt::CLIENT_CONNECT:
185  case CtlPkt::CLIENT_DISCONNECT:
186  success = handleConDisc(px,cp,cph);
187  break;
188  case CtlPkt::NEW_SESSION:
189  success = handleNewSession(px,cp,cph);
190  break;
191  case CtlPkt::CANCEL_SESSION:
192  success = handleCancelSession(px,cp,cph);
193  break;
194  case CtlPkt::BOOT_LEAF:
195  cph.setTunnel(p.tunIp,p.tunPort);
196  // allow just one node to boot at a time
197  net->lock();
198  success = handleBootLeaf(px,cp,cph);
199  net->unlock();
200  cph.setTunnel(0,0);
201  break;
202  case CtlPkt::BOOT_ROUTER:
203  cph.setTunnel(p.tunIp,p.tunPort);
204  // allow just one node to boot at a time
205  net->lock();
206  success = handleBootRouter(px,cp,cph);
207  net->unlock();
208  cph.setTunnel(0,0);
209  break;
210  default:
211  cph.errReply(px,cp,"invalid control packet "
212  "type for NetMgr");
213  break;
214  }
215  }
216  if (!success) {
217  string s;
218  cerr << "handler: operation failed\n"
219  << ps->getPacket(px).toString(s);
220  }
221  ps->free(px); // release px now that we're done
222  outq.enq(0); // signal completion to main thread
223  }
224 }
225 
234 bool handleConsole(int sock, CpHandler& cph) {
235  NetBuffer buf(sock,1024);
236  string cmd, reply, adminName;
237  bool loggedIn;
238 
239  // verify initial "greeting"
240  if (!buf.readLine(cmd) || cmd != "Forest-Console-v1") {
241  Np4d::sendString(sock,"misformatted initial dialog\n"
242  "overAndOut\n");
243  return false;
244  }
245  // main processing loop for requests from client
246  loggedIn = false;
247  while (buf.readAlphas(cmd)) {
248 cerr << "cmd=" << cmd << endl;
249  reply.assign("success\n");
250  if (cmd == "over") {
251  // shouldn't happen, but ignore it, if it does
252  buf.nextLine(); continue;
253  } else if (cmd == "overAndOut") {
254  buf.nextLine(); return true;
255  } else if (cmd == "login") {
256  loggedIn = login(buf,adminName,reply);
257  } else if (!loggedIn) {
258  continue; // must login before anything else
259  } else if (cmd == "newAccount") {
260  newAccount(buf,adminName,reply);
261  } else if (cmd == "getProfile") {
262  getProfile(buf,adminName,reply);
263  } else if (cmd == "updateProfile") {
264  updateProfile(buf,adminName,reply);
265  } else if (cmd == "changePassword") {
266  changePassword(buf,adminName,reply);
267  } else if (cmd == "getNet") {
268  string s; net->toString(s);
269  reply.append(s);
270  } else if (cmd == "getLinkTable") {
271  getLinkTable(buf,reply, cph);
272  } else if (cmd == "getComtreeTable") {
273  getComtreeTable(buf,reply, cph);
274  } else if (cmd == "getIfaceTable") {
275  getIfaceTable(buf,reply,cph);
276  } else if (cmd == "getRouteTable") {
277  getRouteTable(buf,reply,cph);
278  } else if (cmd == "addFilter") {
279  addFilter(buf,reply,cph);
280  } else if (cmd == "modFilter") {
281  modFilter(buf,reply,cph);
282  } else if (cmd == "dropFilter") {
283  dropFilter(buf,reply,cph);
284  } else if (cmd == "getFilter") {
285  getFilter(buf,reply,cph);
286  } else if (cmd == "getFilterSet") {
287  getFilterSet(buf,reply,cph);
288  } else if (cmd == "getLoggedPackets") {
289  getLoggedPackets(buf,reply,cph);
290  } else if (cmd == "enableLocalLog") {
291  enableLocalLog(buf,reply,cph);
292  } else {
293  reply = "unrecognized input\n";
294  }
295 cerr << "sending reply: " << reply;
296  reply.append("over\n");
297  Np4d::sendString(sock,reply);
298  }
299  return true;
300 cerr << "terminating" << endl;
301 }
302 
303 
304 
305 
315 bool login(NetBuffer& buf, string& adminName, string& reply) {
316  string pwd, s1, s2;
317  if (buf.verify(':') && buf.readName(adminName) && buf.nextLine() &&
318  buf.readAlphas(s1) && s1 == "password" &&
319  buf.verify(':') && buf.readWord(pwd) && buf.nextLine() &&
320  buf.readLine(s2) && s2 == "over") {
321  int adx =admTbl->getAdmin(adminName);
322  // locks adx
323  if (adx == 0) {
324  reply = "login failed: try again\n";
325  return false;
326  } else if (admTbl->checkPassword(adx,pwd)) {
327  admTbl->releaseAdmin(adx);
328  return true;
329  } else {
330  admTbl->releaseAdmin(adx);
331  reply = "login failed: try again\n";
332  return false;
333  }
334  } else {
335  reply = "misformatted login request\n";
336  return false;
337  }
338 }
339 
349 bool newAccount(NetBuffer& buf, string& adminName, string& reply) {
350  string newName, pwd, s1, s2;
351  if (buf.verify(':') && buf.readName(newName) && buf.nextLine() &&
352  buf.readAlphas(s1) && s1 == "password" &&
353  buf.verify(':') && buf.readWord(pwd) && buf.nextLine() &&
354  buf.readLine(s2) && s2 == "over") {
355  int adx =admTbl->getAdmin(newName);
356  // locks adx
357  if (adx != 0) {
358  admTbl->releaseAdmin(adx);
359  reply = "name not available, select another\n";
360  return false;
361  }
362  adx = admTbl->addAdmin(newName,pwd);
363  if (adx != 0) {
364  writeAdminRecord(adx);
365  admTbl->releaseAdmin(adx);
366  return true;
367  } else {
368  reply = "unable to add admin\n";
369  return false;
370  }
371  } else {
372  reply = "misformatted new admin request\n";
373  return false;
374  }
375 }
376 
384 void getProfile(NetBuffer& buf, string& adminName, string& reply) {
385  string s, targetName;
386  if (!buf.verify(':') || !buf.readName(targetName) ||
387  !buf.nextLine() || !buf.readLine(s) || s != "over") {
388  reply = "misformatted get profile request"; return;
389  }
390  int tadx = admTbl->getAdmin(targetName);
391  reply = "realName: \"" + admTbl->getRealName(tadx) + "\"\n";
392  reply += "email: " + admTbl->getEmail(tadx) + "\n";
393  admTbl->releaseAdmin(tadx);
394 }
395 
405 void updateProfile(NetBuffer& buf, string& adminName, string& reply) {
406  string s, targetName;
407  if (!buf.verify(':') || !buf.readName(targetName) ||
408  !buf.nextLine()) {
409  reply = "misformatted updateProfile request\n"; return;
410  }
411  // read profile information from admin
412  string item; RateSpec rates;
413  string realName, email;
414  while (buf.readAlphas(item)) {
415  if (item == "realName" && buf.verify(':') &&
416  buf.readString(realName) && buf.nextLine()) {
417  // that's all for now
418  } else if (item == "email" && buf.verify(':') &&
419  buf.readWord(email) && buf.nextLine()) {
420  // that's all for now
421  } else if (item == "over" && buf.nextLine()) {
422  break;
423  } else {
424  reply = "misformatted update profile request (" +
425  item + ")\n";
426  return;
427  }
428  }
429  int tadx = admTbl->getAdmin(targetName);
430  if (realName.length() > 0) admTbl->setRealName(tadx,realName);
431  if (email.length() > 0) admTbl->setEmail(tadx,email);
432  writeAdminRecord(tadx);
433  admTbl->releaseAdmin(tadx);
434  return;
435 }
436 
446 void changePassword(NetBuffer& buf, string& adminName, string& reply) {
447  string targetName, pwd;
448  if (!buf.verify(':') || !buf.readName(targetName) ||
449  !buf.readWord(pwd) || !buf.nextLine()) {
450  reply = "misformatted change password request\n"; return;
451  }
452  int tadx = admTbl->getAdmin(targetName);
453  admTbl->setPassword(tadx,pwd);
454  writeAdminRecord(tadx);
455  admTbl->releaseAdmin(tadx);
456  return;
457 }
458 
465 void addFilter(NetBuffer& buf, string& reply, CpHandler& cph) {
466  string rtrName; int rtr;
467  if (!buf.verify(':') || !buf.readName(rtrName) ||
468  (rtr = net->getNodeNum(rtrName)) == 0) {
469  reply.assign("invalid request\n"); return;
470  }
471  fAdr_t radr = net->getNodeAdr(rtr);
472  pktx repx; CtlPkt repCp;
473  repCp.reset();
474  repx = cph.addFilter(radr, repCp);
475  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
476  reply.assign("could not add log filter\n"); return;
477  }
478  stringstream ss; ss << repCp.index1;
479  reply.append(ss.str());
480  //string index = to_string(repCp.index1);
481  //reply.append(index);
482  reply.append("\n");
483 }
484 
491 void modFilter(NetBuffer& buf, string& reply, CpHandler& cph){
492  string rtrName; int rtr, fx = -1;
493  string filterString;
494  if (!buf.verify(':') || !buf.readName(rtrName) ||
495  ((rtr = net->getNodeNum(rtrName)) == 0) ||
496  !buf.readInt(fx) || (fx < 0) ||
497  !buf.nextLine() || !buf.readLine(filterString)){
498  reply.assign("invalid request\n"); return;
499  }
500  fAdr_t radr = net->getNodeAdr(rtr);
501  pktx repx; CtlPkt repCp;
502  repCp.reset();
503  repx = cph.modFilter(radr, fx, filterString, repCp);
504  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
505  reply.assign("could not modify log filter\n"); return;
506  }
507 }
508 
515 void dropFilter(NetBuffer& buf, string& reply, CpHandler& cph){
516  string rtrName; int rtr, fx = -1;
517  if (!buf.verify(':') || !buf.readName(rtrName) ||
518  ((rtr = net->getNodeNum(rtrName)) == 0) ||
519  !buf.readInt(fx) || (fx < 0)){
520  reply.assign("invalid request\n"); return;
521  }
522  fAdr_t radr = net->getNodeAdr(rtr);
523  pktx repx; CtlPkt repCp;
524  repCp.reset();
525  repx = cph.dropFilter(radr, fx, repCp);
526  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
527  reply.assign("could not drop log filter\n"); return;
528  }
529 }
530 
538 void getFilter(NetBuffer& buf, string& reply, CpHandler& cph){
539  string rtrName; int rtr, fx = -1;
540  if (!buf.verify(':') || !buf.readName(rtrName) ||
541  ((rtr = net->getNodeNum(rtrName)) == 0) ||
542  !buf.readInt(fx) || (fx < 0)){
543  reply.assign("invalid request\n"); return;
544  }
545  fAdr_t radr = net->getNodeAdr(rtr);
546  pktx repx; CtlPkt repCp;
547  repCp.reset();
548  repx = cph.getFilter(radr, fx, repCp);
549  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
550  reply.assign("could not get log filter\n"); return;
551  }
552  reply.append(repCp.stringData);
553  reply.append("\n");
554 }
555 
564 void getFilterSet(NetBuffer& buf, string& reply, CpHandler& cph){
565  string rtrName; int rtr;
566  if (!buf.verify(':') || !buf.readName(rtrName) ||
567  ((rtr = net->getNodeNum(rtrName)) == 0)){
568  reply.assign("invalid request\n"); return;
569  }
570  fAdr_t radr = net->getNodeAdr(rtr);
571  pktx repx; CtlPkt repCp;
572  int fx = 0;
573  while(true){
574  repCp.reset();
575  repx = cph.getFilterSet(radr, fx, 10, repCp);
576  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
577  reply.assign("could not get filter set \n"); return;
578  }
579  reply.append(repCp.stringData);
580  if(repCp.index2 == 0) return;
581  fx = repCp.index2;
582  }
583 }
584 
593 void getLoggedPackets(NetBuffer& buf, string& reply, CpHandler& cph){
594  string rtrName; int rtr;
595  if (!buf.verify(':') || !buf.readName(rtrName) ||
596  ((rtr = net->getNodeNum(rtrName)) == 0)){
597  reply.assign("invalid request\n"); return;
598  }
599  fAdr_t radr = net->getNodeAdr(rtr);
600  pktx repx; CtlPkt repCp;
601  repCp.reset();
602  repx = cph.getLoggedPackets(radr, repCp);
603  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
604  reply.assign("could not get logged packets \n"); return;
605  }
606  reply.append(repCp.stringData);
607  reply.append("\n");
608 }
609 
616 void enableLocalLog(NetBuffer& buf, string& reply, CpHandler& cph){
617  string rtrName; int rtr; bool on;
618  if (!buf.verify(':') || !buf.readName(rtrName) ||
619  ((rtr = net->getNodeNum(rtrName)) == 0) ||
620  !buf.readBit(on)){
621  reply.assign("invalid request\n"); return;
622  }
623  fAdr_t radr = net->getNodeAdr(rtr);
624  pktx repx; CtlPkt repCp;
625  repCp.reset();
626  repx = cph.enableLocalLog(radr, on, repCp);
627  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
628  reply.assign("could not get logged packets \n"); return;
629  }
630 }
631 
638 void getLinkTable(NetBuffer& buf, string& reply, CpHandler& cph) {
639  string rtrName; int rtr;
640  if (!buf.verify(':') || !buf.readName(rtrName) ||
641  (rtr = net->getNodeNum(rtrName)) == 0) {
642  reply.assign("invalid request\n"); return;
643  }
644  fAdr_t radr = net->getNodeAdr(rtr);
645  int lnk = 0;
646  pktx repx; CtlPkt repCp;
647  while (true) {
648  repCp.reset();
649  repx = cph.getLinkSet(radr, lnk, 10, repCp);
650  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
651  reply.assign("could not read link table\n"); return;
652  }
653  reply.append(repCp.stringData);
654  if (repCp.index2 == 0) return;
655  lnk = repCp.index2;
656  }
657 }
658 
665 void getComtreeTable(NetBuffer& buf, string& reply, CpHandler& cph) {
666  string rtrName; int rtr;
667  if (!buf.verify(':') || !buf.readName(rtrName) ||
668  (rtr = net->getNodeNum(rtrName)) == 0) {
669  reply.assign("invalid request\n"); return;
670  }
671  fAdr_t radr = net->getNodeAdr(rtr);
672  int lnk = 0;
673  pktx repx; CtlPkt repCp;
674  while (true) {
675  repCp.reset();
676  repx = cph.getComtreeSet(radr, lnk, 10, repCp);
677  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
678  reply.assign("could not read comtree table\n"); return;
679  }
680  reply.append(repCp.stringData);
681  if (repCp.index2 == 0) return;
682  lnk = repCp.index2;
683  }
684 }
685 
692 void getIfaceTable(NetBuffer& buf, string& reply, CpHandler& cph) {
693  string rtrName; int rtr;
694  if (!buf.verify(':') || !buf.readName(rtrName) ||
695  (rtr = net->getNodeNum(rtrName)) == 0) {
696  reply.assign("invalid request\n"); return;
697  }
698  fAdr_t radr = net->getNodeAdr(rtr);
699  int lnk = 0;
700  pktx repx; CtlPkt repCp;
701  while (true) {
702  repCp.reset();
703  repx = cph.getIfaceSet(radr, lnk, 10, repCp);
704  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
705  reply.assign("could not read iface table\n"); return;
706  }
707  reply.append(repCp.stringData);
708  if (repCp.index2 == 0) return;
709  lnk = repCp.index2;
710  }
711 }
712 
719 void getRouteTable(NetBuffer& buf, string& reply, CpHandler& cph) {
720  string rtrName; int rtr;
721  if (!buf.verify(':') || !buf.readName(rtrName) ||
722  (rtr = net->getNodeNum(rtrName)) == 0) {
723  reply.assign("invalid request\n"); return;
724  }
725  fAdr_t radr = net->getNodeAdr(rtr);
726  int lnk = 0;
727  pktx repx; CtlPkt repCp;
728  while (true) {
729  repCp.reset();
730  repx = cph.getRouteSet(radr, lnk, 10, repCp);
731  if (repx == 0 || repCp.mode != CtlPkt::POS_REPLY) {
732  reply.assign("could not read route table\n"); return;
733  }
734  reply.append(repCp.stringData);
735  if (repCp.index2 == 0) return;
736  lnk = repCp.index2;
737  }
738 }
739 
752 bool handleConDisc(pktx px, CtlPkt& cp, CpHandler& cph) {
753  Packet& p = ps->getPacket(px);
754 
755  // send positive reply back to router
756  CtlPkt repCp(cp.type, CtlPkt::POS_REPLY, cp.seqNum);
757  cph.sendReply(repCp,p.srcAdr);
758 
759  // now, send notification to client manager
760  pktx reply;
761  if (cp.type == CtlPkt::CLIENT_CONNECT)
762  reply = cph.clientConnect(cliMgrAdr,cp.adr1,p.srcAdr,repCp);
763  else
764  reply = cph.clientDisconnect(cliMgrAdr,cp.adr1,p.srcAdr,repCp);
765  if (reply == 0) return false;
766  ps->free(reply);
767  return true;
768 }
769 
782 bool handleNewSession(pktx px, CtlPkt& cp, CpHandler& cph) {
783  Packet& p = ps->getPacket(px);
784  // determine which router to use
785  fAdr_t rtrAdr;
786  if (!findCliRtr(cp.ip1,rtrAdr)) {
787  cph.errReply(px,cp,"No router assigned to client's IP");
788  return true;
789  }
790  int rtr = net->getNodeNum(rtrAdr);
791  RateSpec clientRates = cp.rspec1;
792 
793  // find first iface for this router - refine this later
794  int iface = 1;
795  while (iface < net->getNumIf(rtr) && !net->validIf(rtr,iface)) iface++;
796 
797  // generate nonce to be used by client in connect packet
798  uint64_t nonce = generateNonce();
799 
800  fAdr_t clientAdr = setupLeaf(0,px,cp,rtr,iface,nonce,cph);
801  if (clientAdr == 0) return false;
802 
803  // send positive reply back to sender
804  CtlPkt repCp(CtlPkt::NEW_SESSION,CtlPkt::POS_REPLY,cp.seqNum);
805  repCp.adr1 = clientAdr; repCp.adr2 = rtrAdr; repCp.adr3 = comtCtlAdr;
806  repCp.ip1 = net->getIfIpAdr(rtr,iface);
807  repCp.port1 = net->getIfPort(rtr,iface);
808  repCp.nonce = nonce;
809  cph.sendReply(repCp,p.srcAdr);
810  return true;
811 }
812 
830 fAdr_t setupLeaf(int leaf, pktx px, CtlPkt& cp, int rtr, int iface,
831  uint64_t nonce, CpHandler& cph, bool useTunnel) {
832 
833  Forest::ntyp_t leafType; int leafLink; fAdr_t leafAdr; RateSpec rates;
834 
835  // first add the link at the router
836  fAdr_t rtrAdr = net->getNodeAdr(rtr);
837  fAdr_t dest = (useTunnel ? 0 : rtrAdr);
838  pktx reply; CtlPkt repCp;
839  if (leaf == 0) { // dynamic client
840  leafType = Forest::CLIENT; leafLink = 0;
841  leafAdr = 0; rates = cp.rspec1;
842  reply = cph.addLink(dest,leafType,iface,nonce,repCp);
843  if (!processReply(px,cp,reply,repCp,cph,
844  "could not add link to leaf"))
845  return 0;
846  leafLink = repCp.link; leafAdr = repCp.adr1;
847  } else { // static leaf with specified parameters
848  leafType = net->getNodeType(leaf);
849  int lnk = net->firstLinkAt(leaf);
850  leafLink = net->getLLnum(lnk,rtr);
851  leafAdr = net->getNodeAdr(leaf);
852  rates = net->getLinkRates(lnk);
853  ipa_t leafIp = net->getLeafIpAdr(leaf);
854  reply = cph.addLink(dest,leafType,iface,leafLink,
855  leafIp,0,leafAdr,nonce,repCp);
856  if (!processReply(px,cp,reply,repCp,cph,
857  "could not add link to leaf"))
858  return 0;
859  }
860 
861  // next set the link rate
862  reply = cph.modLink(dest,leafLink,rates,repCp);
863  if (!processReply(px,cp,reply,repCp,cph,"could not set link rates"))
864  return 0;
865 
866  // now add the new leaf to the leaf connection comtree
867  reply = cph.addComtreeLink(dest,Forest::CONNECT_COMT,
868  leafLink,-1,repCp);
869  if (!processReply(px,cp,reply,repCp,cph,"could not add leaf to "
870  "connection comtree"))
871  return 0;
872 
873  // now modify comtree link rate
874  int ctx = comtrees->getComtIndex(Forest::CONNECT_COMT);
875  rates = comtrees->getDefLeafRates(ctx);
876  comtrees->releaseComtree(ctx);
877  reply = cph.modComtreeLink(dest,Forest::CONNECT_COMT,leafLink,
878  rates,repCp);
879  if (!processReply(px,cp,reply,repCp,cph,"could not set rate on "
880  "connection comtree"))
881  return 0;
882 
883  // now add the new leaf to the client signaling comtree
884  reply = cph.addComtreeLink(dest,Forest::CLIENT_SIG_COMT,
885  leafLink,-1,repCp);
886  if (!processReply(px,cp,reply,repCp,cph,"could not add leaf to client "
887  "signalling comtree"))
888  return 0;
889 
890  // and modify its comtree link rate
892  rates = comtrees->getDefLeafRates(ctx);
893  comtrees->releaseComtree(ctx);
894  reply = cph.modComtreeLink(dest,Forest::CLIENT_SIG_COMT,leafLink,
895  rates,repCp);
896  if (!processReply(px,cp,reply,repCp,cph,"could not set rate on client "
897  "signaling comtree"))
898  return 0;
899 
900  if (leafType == Forest::CLIENT) return leafAdr;
901 
902  // for controllers, also add to the network signaling comtree
903  reply = cph.addComtreeLink(dest,Forest::NET_SIG_COMT,
904  leafLink,-1,repCp);
905  if (!processReply(px,cp,reply,repCp,cph,"could not add leaf to network "
906  "signalling comtree"))
907  return 0;
908 
909  // and modify comtree link rate
911  rates = comtrees->getDefLeafRates(ctx);
912  comtrees->releaseComtree(ctx);
913  reply = cph.modComtreeLink(dest,Forest::NET_SIG_COMT,leafLink,
914  rates,repCp);
915  if (!processReply(px,cp,reply,repCp,cph,"could not set rate on network "
916  "signaling comtree"))
917  return 0;
918  return leafAdr;
919 }
920 
927 bool handleCancelSession(pktx px, CtlPkt& cp, CpHandler& cph) {
928  Packet& p = ps->getPacket(px);
929  fAdr_t clientAdr = cp.adr1;
930  fAdr_t rtrAdr = cp.adr2;
931 
932  // verify that clientAdr is in range for router
933  int rtr = net->getNodeNum(rtrAdr);
934  if (rtr == 0) {
935  cph.errReply(px,cp,"no router with specified address");
936  return 0;
937  }
938  pair<fAdr_t,fAdr_t> range;
939  net->getLeafRange(rtr, range);
940  if (clientAdr < range.first || clientAdr > range.second) {
941  cph.errReply(px,cp,"client address not in router's range");
942  return false;
943  }
944 
945  pktx reply; CtlPkt repCp;
946  reply = cph.dropLink(rtrAdr,0,clientAdr,repCp);
947  if (!processReply(px,cp,reply,repCp,cph,"could not drop link "
948  "at router"))
949  return false;
950 
951  // send positive reply back to sender
952  repCp.reset(CtlPkt::CANCEL_SESSION,CtlPkt::POS_REPLY,cp.seqNum);
953  cph.sendReply(repCp,p.srcAdr);
954  return true;
955 }
956 
968 bool handleBootLeaf(pktx px, CtlPkt& cp, CpHandler& cph) {
969  Packet& p = ps->getPacket(px);
970 
971  // first, find leaf in NetInfo object
972  int leaf;
973  for (leaf = net->firstLeaf(); leaf != 0; leaf = net->nextLeaf(leaf)) {
974  if (net->getLeafIpAdr(leaf) == p.tunIp) break;
975  }
976  if (leaf == 0) {
977  cph.errReply(px,cp,"unknown leaf address");
978  return false;
979  }
980 
981  if (net->getStatus(leaf) == NetInfo::UP) {
982  // final reply lost or delayed, resend and quit
983  CtlPkt repCp(CtlPkt::BOOT_LEAF,CtlPkt::POS_REPLY,cp.seqNum);
984  cph.sendReply(repCp,0);
985  return true;
986  }
987 
988  int lnk = net->firstLinkAt(leaf);
989  int rtr = net->getPeer(leaf,lnk);
990  fAdr_t rtrAdr = net->getNodeAdr(rtr);
991 
992  net->setStatus(leaf,NetInfo::BOOTING);
993 
994  if (net->getStatus(rtr) != NetInfo::UP) {
995  cph.errReply(px,cp,"access router is not yet up");
996  net->setStatus(leaf,NetInfo::DOWN);
997  return false;
998  }
999 
1000  // find first iface for this router - refine this later
1001  int iface = 1;
1002  while (iface < net->getNumIf(rtr) && !net->validIf(rtr,iface)) iface++;
1003  uint64_t nonce = generateNonce();
1004 
1005  // add link at router and configure rates/comtrees
1006  CtlPkt repCp;
1007  if (setupLeaf(leaf,px,cp,rtr,iface,nonce,cph) == 0) {
1008  net->setStatus(leaf,NetInfo::DOWN);
1009  return false;
1010  }
1011 
1012  // Send configuration parameters to leaf
1013  // 0 destination address tells cph/substrate to send using
1014  // cph's tunnel parameters; this sends it to leaf
1015  int reply = cph.configLeaf(0,net->getNodeAdr(leaf),rtrAdr,
1016  net->getIfIpAdr(rtr,iface),
1017  net->getIfPort(rtr,iface), nonce, repCp);
1018  if (!processReply(px,cp,reply,repCp,cph,"could not configure "
1019  "leaf node")) {
1020  net->setStatus(leaf,NetInfo::DOWN);
1021  return false;
1022  }
1023 
1024  // finally, send positive ack
1025  repCp.reset(CtlPkt::BOOT_LEAF,CtlPkt::POS_REPLY,cp.seqNum);
1026  cph.sendReply(repCp,0); // 0 sends it directly back to leaf
1027  net->setStatus(leaf,NetInfo::UP);
1028 
1029  logger->log("completed leaf boot request",0,p);
1030  return true;
1031 }
1032 
1034 uint64_t generateNonce() {
1035  uint64_t nonce;
1036  do {
1037  nonce = Misc::currentTime(); // in seconds since epoch
1038  nonce *= random();
1039  } while (nonce == 0);
1040  return nonce;
1041 }
1042 
1062 bool processReply(pktx px, CtlPkt& cp, pktx reply, CtlPkt& repCp,
1063  CpHandler& cph, const string& msg) {
1064  if (reply == 0) {
1065  cph.errReply(px,cp,msg + " (no response from target)");
1066  ps->free(reply);
1067  return false;
1068  }
1069  if (repCp.mode != CtlPkt::POS_REPLY) {
1070  string s;
1071  cph.errReply(px,cp,msg + " (" + repCp.toString(s) + ")");
1072  ps->free(reply);
1073  return false;
1074  }
1075  ps->free(reply);
1076  return true;
1077 }
1078 
1096 bool handleBootRouter(pktx px, CtlPkt& cp, CpHandler& cph) {
1097  Packet& p = ps->getPacket(px);
1098 
1099  // find rtr index based on source address
1100  ipa_t rtrAdr = p.srcAdr;
1101 string s;
1102 cerr << "got boot request from " << Forest::fAdr2string(rtrAdr,s) << endl;
1103  int rtr;
1104  for (rtr = net->firstRouter(); rtr != 0; rtr = net->nextRouter(rtr)) {
1105  if (net->getNodeAdr(rtr) == rtrAdr) break;
1106  }
1107  if (rtr == 0) {
1108  cph.errReply(px,cp,"boot request from unknown router "
1109  "rejected\n");
1110  logger->log("handleBootRequest: received boot request from "
1111  "unknown router\n",2,p);
1112  return true;
1113  }
1114 
1115  if (net->getStatus(rtr) == NetInfo::UP) {
1116  // final reply lost or delayed, resend and quit
1117  CtlPkt repCp(CtlPkt::BOOT_ROUTER,CtlPkt::POS_REPLY,cp.seqNum);
1118  cph.sendReply(repCp,0);
1119  return true;
1120  }
1121 
1122  net->setStatus(rtr,NetInfo::BOOTING);
1123 
1124  // configure leaf address range
1125  CtlPkt repCp;
1126  pair<fAdr_t,fAdr_t> leafRange; net->getLeafRange(rtr,leafRange);
1127  int reply = cph.setLeafRange(0,leafRange.first,leafRange.second,repCp);
1128  if (!processReply(px,cp,reply,repCp,cph,
1129  "could not configure leaf range")) {
1130  net->setStatus(rtr,NetInfo::DOWN);
1131  return false;
1132  }
1133 
1134  // add/configure interfaces
1135  // for each interface in table, do an add iface
1136  int nmLnk = net->getLLnum(net->firstLinkAt(netMgr),nmRtr);
1137  int nmIface = net->getIface(nmLnk,nmRtr);
1138  for (int i = 1; i <= net->getNumIf(rtr); i++) {
1139  if (!net->validIf(rtr,i)) continue;
1140  int reply = cph.addIface(0,i,net->getIfIpAdr(rtr,i),
1141  net->getIfRates(rtr,i),repCp);
1142  if (!processReply(px,cp,reply,repCp,cph,
1143  "could not add interface at router")) {
1144  net->setStatus(rtr,NetInfo::DOWN);
1145  return false;
1146  }
1147  net->setIfPort(rtr,i,repCp.port1);
1148  // if this is the network manager's router, configure port
1149  // in substrate
1150  if (rtr == nmRtr && i == nmIface) {
1151  sub->setRtrPort(repCp.port1);
1152  }
1153  }
1154 
1155  // add/configure links to other routers
1156  for (int lnk = net->firstLinkAt(rtr); lnk != 0;
1157  lnk = net->nextLinkAt(rtr,lnk)) {
1158  int peer = net->getPeer(rtr,lnk);
1159  if (net->getNodeType(peer) != Forest::ROUTER) continue;
1160  if (!setupEndpoint(lnk,rtr,px,cp,cph,true)) {
1161  net->setStatus(rtr,NetInfo::DOWN);
1162  return false;
1163  }
1164  }
1165 
1166 Add code for special case of neighbor comtree.
1167 Include all links.
1168 Drop comtree 1 from topoFiles
1169 
1170  // add/configure comtrees
1171  for (int ctx = comtrees->firstComtree(); ctx != 0;
1172  ctx = comtrees->nextComtree(ctx)) {
1173  fAdr_t rtrAdr = net->getNodeAdr(rtr);
1174  if (!comtrees->isComtNode(ctx,rtrAdr)) continue;
1175  if (!setupComtree(ctx,rtr,px,cp,cph,true)) {
1176  comtrees->releaseComtree(ctx);
1177  net->setStatus(rtr,NetInfo::DOWN);
1178  return false;
1179  }
1180  }
1181 
1182  // if this is net manager's router, configure link
1183  if (rtr == nmRtr) {
1184  uint64_t nonce = generateNonce();
1185  sub->setNonce(nonce);
1186  if (setupLeaf(netMgr,px,cp,rtr,nmIface,nonce,cph,true) == 0) {
1187  fatal("cannot configure NetMgr's access link");
1188  }
1189  }
1190 
1191  // finally, send positive reply
1192 // may want to switch back to having a separate START packet,
1193 // to eliminate long delay between Boot request and reply
1194  repCp.reset(CtlPkt::BOOT_ROUTER,CtlPkt::POS_REPLY,cp.seqNum);
1195  cph.sendReply(repCp,0);
1196  net->setStatus(rtr,NetInfo::UP);
1197 
1198  if (rtr == nmRtr) sub->setRtrReady(true);
1199 
1200  logger->log("completed boot request",0,p);
1201  return true;
1202 }
1203 
1217 bool setupEndpoint(int lnk, int rtr, pktx px, CtlPkt& cp, CpHandler& cph,
1218  bool useTunnel) {
1219  int llnk = net->getLLnum(lnk,rtr);
1220  int iface = net->getIface(llnk,rtr);
1221  fAdr_t rtrAdr = net->getNodeAdr(rtr);
1222 
1223  int peer = net->getPeer(rtr,lnk);
1224  fAdr_t peerAdr = net->getNodeAdr(peer);
1225  int plnk = net->getLLnum(lnk,peer);
1226  int i = net->getIface(plnk,peer);
1227  ipa_t peerIp = net->getIfIpAdr(peer,i);
1228  ipp_t peerPort = 0;
1229 
1230  uint64_t nonce;
1231  if (net->getStatus(peer) != NetInfo::UP) {
1232  nonce = generateNonce();
1233  net->setNonce(lnk,nonce);
1234  } else {
1235  peerPort = net->getIfPort(peer,i);
1236  nonce = net->getNonce(lnk);
1237  }
1238  CtlPkt repCp;
1239  fAdr_t dest = (useTunnel ? 0 : rtrAdr);
1240  int reply = cph.addLink(dest,Forest::ROUTER,iface,llnk,peerIp,
1241  peerPort,peerAdr,nonce,repCp);
1242  if (!processReply(px,cp,reply,repCp,cph,"could not add link at router"))
1243  return false;
1244 
1245  // now, send modify link message, to set data rates
1246  RateSpec rs = net->getLinkRates(lnk);
1247  if (rtr == net->getLeft(lnk)) rs.flip();
1248  reply = cph.modLink(dest,llnk,rs,repCp);
1249  if (!processReply(px,cp,reply,repCp,cph,
1250  "could not set link rates at router"))
1251  return false;
1252  return true;
1253 }
1254 
1263 bool setupComtree(int ctx, int rtr, pktx px, CtlPkt& cp, CpHandler& cph,
1264  bool useTunnel) {
1265  fAdr_t rtrAdr = net->getNodeAdr(rtr);
1266 
1267  comt_t comt = comtrees->getComtree(ctx);
1268 
1269  // first step is to add comtree at router
1270  CtlPkt repCp;
1271  fAdr_t dest = (useTunnel ? 0 : rtrAdr);
1272  int reply = cph.addComtree(dest,comt,repCp);
1273  if (!processReply(px,cp,reply,repCp,cph,
1274  "could not add comtree at router"))
1275  return false;
1276 
1277  // next, add links to the comtree and set their data rates
1278  int plnk = comtrees->getPlink(ctx,rtrAdr);
1279  int parent = net->getPeer(rtr,plnk);
1280  for (int lnk = net->firstLinkAt(rtr); lnk != 0;
1281  lnk = net->nextLinkAt(rtr,lnk)) {
1282  if (!comtrees->isComtLink(ctx,lnk)) continue;
1283  int peer = net->getPeer(rtr,lnk);
1284  if (net->getNodeType(peer) != Forest::ROUTER) continue;
1285 
1286  // get information about this link
1287  int llnk = net->getLLnum(lnk,rtr);
1288  fAdr_t peerAdr = net->getNodeAdr(peer);
1289  bool peerCoreFlag = comtrees->isCoreNode(ctx,peerAdr);
1290 
1291  // first, add comtree link
1292  reply = cph.addComtreeLink(dest,comt,llnk,
1293  peerCoreFlag,repCp);
1294  if (!processReply(px,cp,reply,repCp,cph,
1295  "could not add comtree link at router"))
1296  return false;
1297 
1298  // now, set link rates
1299  RateSpec rs;
1300  if (peer == parent) {
1301  rs = comtrees->getLinkRates(ctx,rtrAdr);
1302  rs.flip();
1303  } else {
1304  rs = comtrees->getLinkRates(ctx,peerAdr);
1305  }
1306  reply = cph.modComtreeLink(dest,comt,llnk,rs,repCp);
1307  if (!processReply(px,cp,reply,repCp,cph,
1308  "could not set comtree link rates at router"))
1309  return false;
1310  }
1311  // finally, we need to modify overall comtree attributes
1312  reply = cph.modComtree(dest,comt,net->getLLnum(plnk,rtr),
1313  comtrees->isCoreNode(ctx,rtrAdr),repCp);
1314  if (!processReply(px,cp,reply,repCp,cph,
1315  "could not set comtree parameters"))
1316  return false;
1317  return true;
1318 }
1319 
1325 bool findCliRtr(ipa_t cliIp, fAdr_t& rtrAdr) {
1326  string cip;
1327  Np4d::ip2string(cliIp,cip);
1328  for (unsigned int i = 0; i < (unsigned int) numPrefixes; ++i) {
1329  string ip = prefixes[i].prefix;
1330  unsigned int j = 0;
1331  while (j < ip.size() && j < cip.size()) {
1332  if (ip[j] != '*' && cip[j] != ip[j]) break;
1333  if (ip[j] == '*' ||
1334  (j+1 == ip.size() && j+1 == cip.size())) {
1335  rtrAdr = prefixes[i].rtrAdr;
1336  return true;
1337  }
1338  j++;
1339  }
1340  }
1341  // if no prefix for client address, select router at random
1342  int i = randint(0,net->getNumRouters()-1);
1343  for (int r = net->firstRouter(); r != 0; r = net->nextRouter(r)) {
1344  if (i-- == 0) {
1345  rtrAdr = net->getNodeAdr(r); return true;
1346  }
1347  }
1348  return false; // should never reach here
1349 }
1350 
1355 bool readPrefixInfo(char filename[]) {
1356  ifstream ifs; ifs.open(filename);
1357  if(ifs.fail()) return false;
1358  Misc::skipBlank(ifs);
1359  int i = 0;
1360  while(!ifs.eof()) {
1361  string pfix; fAdr_t rtrAdr;
1362  ifs >> pfix;
1363  if(!Forest::readForestAdr(ifs,rtrAdr))
1364  break;
1365  prefixes[i].prefix = pfix;
1366  prefixes[i].rtrAdr = rtrAdr;
1367  Misc::skipBlank(ifs);
1368  i++;
1369  }
1370  numPrefixes = i;
1371  cout << "read address info for " << numPrefixes << " prefixes" << endl;
1372  return true;
1373 }
1374 
1379 void writeAdminRecord(int adx) {
1380  if (adx < 0 || adx >= admTbl->getMaxAdmins()) return;
1381 
1382  pthread_mutex_lock(&adminFileLock);
1383  if (maxRecord == 0) {
1384  adminFile.seekp(0,ios_base::end);
1385  maxRecord = adminFile.tellp()/RECORD_SIZE;
1386  }
1387 
1388  // position file pointer, adding dummy records if needed
1389  if (adx > maxRecord) {
1390  adminFile.seekp((maxRecord+1)*RECORD_SIZE);
1391  while (adx > maxRecord) {
1393  maxRecord++;
1394  }
1395  }
1396  adminFile.seekp(adx*RECORD_SIZE);
1397 
1398  if (admTbl->validAdmin(adx)) {
1399  string s;
1400  admTbl->admin2string(adx,s);
1401  s = "+ " + s;
1402  if (s.length() > RECORD_SIZE) {
1403  s.erase(RECORD_SIZE-1); s += "\n";
1404  } else {
1405  s.erase(s.length()-1);
1406  int len = RECORD_SIZE - s.length();
1407  char *p = dummyRecord + s.length();
1408  s.append(p,len);
1409  }
1410  adminFile.write(s.c_str(),RECORD_SIZE);
1411  } else {
1412  //s.assign(dummyRecord,RECORD_SIZE);
1413  adminFile.write(dummyRecord,RECORD_SIZE);
1414  }
1415  adminFile.flush();
1416  maxRecord = max(adx,maxRecord);
1417  pthread_mutex_unlock(&adminFileLock);
1418  return;
1419 }
1420 
1464 } // ends namespace