forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
RouterControl.cpp
Go to the documentation of this file.
1 
9 #include "RouterControl.h"
10 
11 using namespace forest;
12 
13 RouterControl::RouterControl(Router *rtr1, int thx,
14  Quu<int> inQ1, Quu<pair<int,int>> outQ1)
15  : rtr(rtr1), myThx(thx), inQ(inQ1), outQ(outQ1) {
16 }
17 
18 void RouterControl::start(RouterControl *self) { self->run(); }
19 
20 void RouterControl::run() {
21  while (true) {
22  pktx px = inQ.deq(); // wait for incoming request packet
23  Packet& p = rtr->ps->getPacket(px);
25  return;
26  CtlPkt cp(p);
27  handleRequest(px,cp);
28  }
29 }
30 
37  Packet& p = rtr->ps->getPacket(px);
38 
39  switch (cp.type) {
40 
41  // configuring logical interfaces
42  case CtlPkt::ADD_IFACE: addIface(cp,rcp); break;
43  case CtlPkt::DROP_IFACE: dropIface(cp,rcp); break;
44  case CtlPkt::GET_IFACE: getIface(cp,rcp); break;
45  case CtlPkt::MOD_IFACE: modIface(cp,rcp); break;
46  case CtlPkt::GET_IFACE_SET: getIfaceSet(cp,rcp); break;
47 
48  // configuring links
49  case CtlPkt::ADD_LINK: addLink(cp,rcp); break;
50  case CtlPkt::DROP_LINK: dropLink(cp,rcp); break;
51  case CtlPkt::GET_LINK: getLink(cp,rcp); break;
52  case CtlPkt::MOD_LINK: modLink(cp,rcp); break;
53  case CtlPkt::GET_LINK_SET: getLinkSet(cp,rcp); break;
54 
55  // configuring comtrees
56  case CtlPkt::ADD_COMTREE: addComtree(cp,rcp); break;
57  case CtlPkt::DROP_COMTREE: dropComtree(cp,rcp); break;
58  case CtlPkt::GET_COMTREE: getComtree(cp,rcp); break;
59  case CtlPkt::MOD_COMTREE: modComtree(cp,rcp); break;
60  case CtlPkt::GET_COMTREE_SET: getComtreeSet(cp,rcp); break;
61 
62  case CtlPkt::ADD_COMTREE_LINK: addComtreeLink(cp,rcp); break;
63  case CtlPkt::DROP_COMTREE_LINK: dropComtreeLink(cp,rcp); break;
64  case CtlPkt::GET_COMTREE_LINK: getComtreeLink(cp,rcp); break;
65  case CtlPkt::MOD_COMTREE_LINK: modComtreeLink(cp,rcp); break;
66 
67  // configuring routes
68  case CtlPkt::ADD_ROUTE: addRoute(cp,rcp); break;
69  case CtlPkt::DROP_ROUTE: dropRoute(cp,rcp); break;
70  case CtlPkt::GET_ROUTE: getRoute(cp,rcp); break;
71  case CtlPkt::MOD_ROUTE: modRoute(cp,rcp); break;
72  case CtlPkt::GET_ROUTE_SET: getRouteSet(cp,rcp); break;
73 
74  // configuring filters and retrieving pacets
75  case CtlPkt::ADD_FILTER: addFilter(cp,rcp); break;
76  case CtlPkt::DROP_FILTER: dropFilter(cp,rcp); break;
77  case CtlPkt::GET_FILTER: getFilter(cp,rcp); break;
78  case CtlPkt::MOD_FILTER: modFilter(cp,rcp); break;
79  case CtlPkt::GET_FILTER_SET: getFilterSet(cp,rcp); break;
80  case CtlPkt::GET_LOGGED_PACKETS: getLoggedPackets(cp,rcp); break;
81  case CtlPkt::ENABLE_PACKET_LOG: enablePacketLog(cp,rcp); break;
82 
83  // setting parameters
84  case CtlPkt::SET_LEAF_RANGE: setLeafRange(cp,rcp); break;
85 
86  // comtree setup
87  case CtlPkt::JOIN: joinComtree(cp); break
88  case CtlPkt::LEAVE: leaveComtree(cp); break
89  case CtlPkt::ADD_BRANCH: addBranch(cp); break
90  case CtlPkt::PRUNE: prune(cp); break
91  case CtlPkt::CONFIRM: confirm(cp); break
92  case CtlPkt::ABORT: abort(cp); break
93 
94  default:
95  cerr << "unrecognized control packet type " << cp.type
96  << endl;
97  rcp.errMsg = "invalid control packet for router";
98  rcp.mode = CtlPkt::NEG_REPLY;
99  break;
100  }
101  returnToSender(px,cp);
102  return;
103 }
104 
111  Packet& p = rtr->ps->getPacket(px);
112  p.length = Packet::OVERHEAD + cp.paylen;
113  p.length = (p.length + 3)/4; // round up to next multiple of 4
114  p.flags = 0;
115  p.dstAdr = p.srcAdr;
116  p.srcAdr = rtr->myAdr;
117  p.pack();
118  outQ.enq(pair<int,int>(myThx,px));
119 }
120 
127  int iface; ipa_t ip; RateSpec rates;
128  if (!cp.xtrAddIface(iface, ip, rates)) {
129  cp.fmtError("unable to unpack control packet"); return;
130  }
131  rates.bitRateUp = max(min(rates.bitRateUp,
133  rates.bitRateDown = max(min(rates.bitRateDown,
135  rates.pktRateUp = max(min(rates.pktRateUp,
137  rates.pktRateDown = max(min(rates.pktRateDown,
139 
140  unique_lock iftLock(rtr->iftMtx);
141  if (rtr->ift->valid(iface)) {
142  cp.fmtError("addIface: requested interface "
143  "conflicts with existing interface");
144  return;
145  } else if (!rtr->ift->addEntry(iface, cp.ip1, 0, rs)) {
146  cp.fmtError("addIface: cannot add interface");
147  return;
148  } else if (!rtr->setupIface(iface)) {
149  cp.fmtError("addIface: could not setup interface");
150  return;
151  }
152  IfaceTable::Entry& ifte = rtr->ift->getEntry(iface);
153  cp.fmtAddIfaceReply(ifte.ipa, ifte.port);
154 }
155 
162  int iface; if (!cp.xtrDropIface(iface)) {
163  cp.fmtError("unable to unpack control packet"); return;
164  }
165  unique_lock iftLock(rtr->iftMtx);
166  rtr->ift->removeEntry(iface);
167  cp.fmtDropIfaceReply();
168 }
169 
176  int iface; if (!cp.xtrGetIface(iface)) {
177  cp.fmtError("unable to unpack control packet"); return;
178  }
179  unique_lock iftLock(rtr->iftMtx);
180  if (rtr->ift->valid(iface)) {
181  IfaceTable::Entry& ifte = rtr->ift->getEntry(iface);
182  cp.fmtGetIfaceReply(iface, ifte.ipa, ifte.port,
183  ifte.rates, ifte.availRates);
184  return;
185  }
186  rcp.fmtError("get iface: invalid interface");
187 }
188 
196  int iface; RateSpec rates;
197  if (!cp.xtrModIface(iface, rates)) {
198  cp.fmtError("unable to unpack control packet"); return;
199  }
200  unique_lock iftLock(rtr->iftMtx);
201  if (rtr->ift->valid(iface)) {
202  IfaceTable::Entry& ifte = rtr->ift->getEntry(iface);
203  ifte.rates = rates
204  cp.fmtModIfaceReply(); return;
205  }
206  cp.fmtError("mod iface: invalid interface");
207 }
208 
219  int iface, count;
220  if (!cp.xtrGetIfaceSet(iface, count)) {
221  cp.fmtError("unable to unpack control packet"); return;
222  }
223  unique_lock iftLock(rtr->iftMtx);
224  if (iface == 0) iface = rtr->ift->firstIface(); // 0 means 1st iface
225  else if (!rtr->ift->valid(iface)) {
226  cp.fmtError("get iface set: invalid iface number");
227  return;
228  }
229  count = min(10, count);
230  int i = 0; string s;
231  while (i < count && iface != 0) {
232  s.append(to_string(ifIndex) + " "
233  + rtr->ift->entry2string(ifIndex));
234  if (s.length() > 1300) {
235  cp.fmtError("getIfaceSet: reply string too long");
236  return
237  }
238  i++; iface = rtr->ift->nextIface(iface);
239  }
240  cp.fmtGetIfaceSetReply(i, iface, s);
241 }
242 
243 void RouterControl::addLink(CtlPkt& cp) {
244  Forest::ntyp_t ntyp; int iface, lnk; ipa_t peerIp; ipp_t peerPort;
245  fAdr_t peerAdr; uint64_t nonce;
246  if (!cp.xtrAddLink(ntyp, iface, lnk, peerIp, peerPort, peerAdr, nonce)) {
247  cp.fmtError("unable to unpack control packet"); return;
248  }
249  if (peerType == Forest::ROUTER && peerAdr == 0) {
250  cp.fmtError("add link: adding link to router, but no peer "
251  "address supplied");
252  return;
253  }
254 
255  // lock both iface table and link table
256  unique_lock iftLock(rtr->iftMtx,defer_lock);
257  unique_lock ltLock( rtr->ltMtx,defer_lock);
258  lock(iftLock, ltLock);
259 
260  if (rtr->lt->lookup(peerIp, peerPort) != 0 ||
261  (lnk != 0 && rtr->lt->valid(lnk))) {
262  cp.fmtError("add link: new link conflicts with existing link");
263  return;
264  }
265 
266  IfaceTable::Entry& ifte = rtr->ift->getEntry(iface);
267 
268  // first ensure that the interface has enough
269  // capacity to support a new link of minimum capacity
272  if (!rs.leq(ifte.availRates)) {
273  cp.fmtError("add link: requested link "
274  "exceeds interface capacity");
275  return;
276  }
277 
278  // setting up link
279  // case 1: adding link to leaf; peer (ip,port) not known, use nonce
280  // subcase - lnk, peer forest address is known
281  // (for preconfigured leaf)
282  // subcase - lnk, peer address to be assigned by router
283  // case 2: adding link to router not yet up; port not known, use nonce
284  // lnk, peer address specified
285  // case 3: adding link to a router that is already up
286  // lnk, peer address specified, peer (ip,port) specified
287 
288  // add table entry with (ip,port) or nonce
289  // note: when rtr->lt->addEntry succeeds, link rates are
290  // initialized to Forest minimum rates
291  lnk = rtr->lt->addEntry(lnk,peerIp,peerPort,nonce);
292  if (lnk == 0) {
293  cp.fmtError("add link: cannot add requested link");
294  return;
295  }
296  LinkTable::Entry& lte = rtr->lt->getEntry(lnk);
297 
298  if (peerType == Forest::ROUTER) {
299  lte.peerAdr = peerAdr;
300  } else { // case 1
301  lte.peerAdr = 0;
302  if (peerAdr == 0) lte.peerAdr = rtr->allocLeafAdr();
303  else if (rtr->allocLeafAdr(peerAdr)) lte.peerAdr = peerAdr;
304  if (lte.peerAdr == 0) {
305  rtr->lt->removeEntry(lnk);
306  cp.fmtError("add link: cannot add link using "
307  "specified address";
308  return;
309  }
310  }
311 
312  ifte.availRates.subtract(rs);
313  lte.iface = iface;
314  lte.peerType = peerType;
315  lte.isConnected = false;
316  sm->clearLnkStats(lnk);
317  if (peerType == Forest::ROUTER && peerIp != 0 && peerPort != 0) {
318  // link to a router that's already up, so send connect
319  pktx px = rtr->ps->alloc();
320  Packet& p = rtr->ps->getPacket(px);
321 
322  p.length = Forest::OVERHEAD + 8;
323  p.type = Forest::CONNECT; p.flags = 0;
325  p.srcAdr = myAdr; p.dstAdr = lte.peerAdr;
326  int64_t seqNum = rtr->nextSeqNum();
327  (p.payload())[0] = htonl((int32_t) ((seqNum>>32) & 0xffffffff));
328  (p.payload())[1] = htonl((int32_t) (seqNum & 0xffffffff));
329  p.payload()[2] = htonl((uint32_t) (lte.nonce >> 32));
330  p.payload()[3] = htonl((uint32_t) (lte.nonce & 0xffffffff));
331  p.outLink = lnk;
332  p.pack();
333  p.hdrErrUpdate();p.payErrUpdate();
334  outQ.enq(pair<int,int>(myThx,px));
335  }
336  cp.fmtAddLinkReply(lnk,peerAdr);
337  return;
338 }
339 
348  int lnk; fAdr_t peerAdr;
349  if (!cp.xtrDropLink(lnk,peerAdr)) {
350  cp.fmtError("unable to unpack control packet"); return;
351  }
352 
353  unique_lock iftLock(rtr->iftMtx,defer_lock);
354  unique_lock ltLock( rtr->ltMtx,defer_lock);
355  unique_lock cttLock(rtr->cttMtx,defer_lock);
356  unique_lock rtLock( rtr->rtMtx,defer_lock);
357  lock(iftLock, ltLock, cttLock, rtrLock);
358 
359  if (lnk == 0) lnk = rtr->lt->lookup(peerAdr);
360 
361  // remove all routes for all comtrees that use this link
362  Dlist comtList = rtr->ctt->getComtList(lnk);
363  for (int ctx = comtList.first(); ctx != 0; ctx = comtList.next()) {
364  rtr->lt->purge(rtr->ctt->getComtree(ctx),
365  rtr->ctt->getClnkNum(ctx,lnk));
366  }
367  // now remove the link from all comtrees that it
368  // this may remove some comtrees as well
369  rtr->ctt->purgeLink(lnk);
370 
371  // now update the interface's ratespec and free the peer's address
372  LinkTable::Entry& lte = rtr->lt->getEntry(lnk);
373  IfaceTable::Entry& ifte = rtr->ift->getEntry(lte.iface);
374  ifte.availRates.add(lte.rates);
375  freeLeafAdr(lte.peerAdr); // ignores addresses outside leaf adr range
376 
377  // and finally, remove the link from the link table
378  rtr->lt->removeEntry(lnk);
379  cp.fmtDropLinkReply();
380 }
381 
382 void RouterControl::getLink(CtlPkt& cp) {
383  int lnk;
384  if (!cp.xtrGetLink(lnk)) {
385  cp.fmtError("unable to unpack control packet"); return;
386  }
387  unique_lock ltLock(rtr->ltMtx);
388  if (rtr->lt->valid(lnk)) {
389  cp.fmtGetLinkReply(lnk, lte.iface, lte.peerIp, lte.peerPort,
390  lte.peerType, lte.peerAdr, lte.rates,
391  lte.availRates);
392  return;
393  }
394  cp.fmtError("get link: invalid link number";
395  return;
396 }
397 
409  int lnk, count;
410  xtrGetLinkSet(lnk,count);
411 
412  unique_lock ltLock(rtr->ltMtx);
413  if (lnk == 0) lnk = rtr->lt->firstLink(); // 0 means start with first
414  else if (!rtr->lt->valid(lnk)) {
415  cp.fmtError("get link set: invalid link number";
416  return;
417  }
418  count = min(10,count);
419  int i = 0;
420  string s;
421  while (i < count && lnk != 0) {
422  rcp.stringData.append(to_string(lnk) + " ");
423  rcp.stringData.append(rtr->lt->link2string(lnk) + "\n");
424  if (rcp.stringData.length() > 1300) {
425  cp.fmtError( "get link set: error while formatting "
426  "reply";
427  return;
428  }
429  i++; lnk = rtr->lt->nextLink(lnk);
430  }
431  cp.fmtGetLinkSetReply(count, lnk);
432  return;
433 }
434 
435 void RouterControl::modLink(CtlPkt& cp) {
436  int lnk; RateSpec rates;
437  if (!cp.xtrModLink(lnk,rates)) {
438  cp.fmtError("unable to unpack control packet"); return;
439  }
440 
441  unique_lock iftLock(rtr->iftMtx,defer_lock);
442  unique_lock ltLock(rtr->ltMtx,defer_lock);
443  lock(iftLock, ltLock);
444 
445  if (!rtr->lt->valid(lnk)) {
446  cp.fmtError("get link: invalid link number";
447  return;
448  }
449  LinkTable::Entry& lte = rtr->lt->getEntry(lnk);
450  IfaceTable::Entry& ifte = rtr->ift->getEntry(lte.iface);
451  RateSpec delta = rates;
452  delta.subtract(lte.rates);
453  if (!delta.leq(ifte.availRates)) {
454  string s;
455  cp.fmtError("mod link: request " + rates.toString(s) +
456  "exceeds interface capacity";
457  return;
458  }
459  ifte.availRates.subtract(delta);
460  lte.rates = rates;
461  lte.availRates.add(delta);
462  rtr->qm->setLinkRates(lnk,rates);
463  cp.fmtModLinkReply():
464  return;
465 }
466 
467 void RouterControl::addComtree(CtlPkt& cp) {
468  comt_t comt;
469  if (!cp.xtrAddComtree(comt)) {
470  cp.fmtError("unable to unpack control packet"); return;
471  }
472 
473  unique_lock cttLock(rtr->cttMtx);
474  if(rtr->ctt->validComtree(comt) || rtr->ctt->addEntry(comt) != 0) {
475  cp.fmtAddComtreeReply();
476  return;
477  }
478  cp.fmtError("add comtree: cannot add comtree";
479  return;
480 }
481 
482 void RouterControl::dropComtree(CtlPkt& cp) {
483  comt_t comt;
484  if (!cp.xtrDropComtree(comt)) {
485  cp.fmtError("unable to unpack control packet"); return;
486  }
487 
488  unique_lock ltLock(rtr->ltMtx,defer_lock);
489  unique_lock cttLock(rtr->cttMtx,defer_lock);
490  unique_lock rtLock(rtr->rtMtx,defer_lock);
491  lock(ltLock, cttLock, rtLock);
492 
493  int ctx = rtr->ctt->getComtIndex(comt);
494  if (ctx == 0) {
495  cp.fmtError("dropComtree: no such comtree";
496  return;
497  }
498  ComtreeTable::Entry& cte = rtr->ctt->getEntry(ctx);
499  int plink = cte.pLnk;
500 
501  int cLnk = rtr->ctt->firstComtLink(ctx);
502  RateSpec pRates;
503  while (cLnk != 0) {
504  // remove all routes involving this comtree
505  rtr->lt->purge(comt,cLnk);
506 
507  // return assigned link bandwidth to link
508  int lnk = rtr->ctt->getLink(ctx,cLnk);
509  RouteTable::entry& lte = rtr->lt->getEntry(lnk);
510  lte.availRates.add(cte.rates);
511 
512  // return availRates on parent link
513  if (lnk == cte.pLnk) pRates = lte.availRates;
514 
515  // de-allocate queue
516  qm->freeQ(rtr->ctt->getLinkQ(cLnk));
517 
518  rtr->ctt->removeLink(ctx,cLnk);
519  cLnk = rtr->ctt->firstComtLink(ctx);
520  }
521  rtr->ctt->removeEntry(ctx); // and finally drop entry in comtree table
522  cp.fmtDropComtreeReply(pRates);
523  return;
524 }
525 
526 void RouterControl::getComtree(CtlPkt& cp) {
527  comt_t comt;
528  if (!cp.xtrGetComtree(comt)) {
529  cp.fmtError("unable to unpack control packet"); return;
530  }
531 
532  unique_lock cttLock(rtr->cttMtx);
533  int ctx = rtr->ctt->getComtIndex(comt);
534  if (ctx == 0) {
535  cp.fmtError("get comtree: invalid comtree";
536  return;
537  }
538  ComtreeTable::Entry& cte = rtr->ctt->getEntry(ctx);
539  cp.fmtGetComtreeReply(comt, cte.coreFlag, cte.pLnk,
540  rtr->ctt->getLinkCount(ctx));
541  return;
542 }
543 
544 void RouterControl::modComtree(CtlPkt& cp) {
545  comt_t comt, int coreFlag, int plnk;
546  if (!cp.xtrModComtree(comt, coreFlag, plnk)) {
547  cp.fmtError("unable to unpack control packet"); return;
548  }
549  unique_lock cttLock(rtr->cttMtx);
550 
551  int ctx = rtr->ctt->getComtIndex(comt);
552  if (ctx != 0) {
553  ComtreeTable::Entry& cte = rtr->ctt->getEntry(ctx);
554  if (coreFlag >= 0)
555  cte.coreFlag = coreFlag;
556  if (cp.link != 0) {
557  if (plnk != 0 && !rtr->ctt->isLink(ctx,plnk)) {
558  cp.fmtError("specified link does "
559  "not belong to comtree";
560  return;
561  }
562  if (plnk != 0 && !rtr->ctt->isRtrLink(ctx,plnk)) {
563  cp.fmtError("specified link does "
564  "not connect to a router";
565  return;
566  }
567  cte.pLnk = plnk;
568  cte.pClnk = rtr->ctt->getClnkNum(comt,plnk);
569  }
570  cp.fmtModComtreeReply();
571  return;
572  }
573  cp.fmtError("modify comtree: invalid comtree";
574  return;
575 }
576 
588  comt_t comt; int count;
589  if (!cp.xtrGetComtreeSet(comt,count)) {
590  cp.fmtError("unable to unpack control packet"); return;
591  }
592 
593  unique_lock cttLock(rtr->cttMtx);
594  int ctx;
595  if (comt == 0) // 0 means first
596  ctx = rtr->ctt->firstComtIndex();
597  else
598  ctx = rtr->ctt->getComtIndex(comt);
599  if (ctx == 0) {
600  cp.fmtError("get comtree set: invalid comtree number";
601  return;
602  }
603  count = min(10,count);
604  int i = 0;
605  while (i < count && ctx != 0) {
606  rcp.stringData.append(rtr->ctt->entry2string(ctx));
607  if (rcp.stringData.length() > 1300) {
608  cp.fmtError( "get comtee set: error while formatting "
609  "reply";
610  return;
611  }
612  i++; ctx = rtr->ctt->nextComtIndex(ctx);
613  }
614  cp.fmtGetComtreeSetReply(i, ctx == 0 ? 0 : rtr->ctt->getComtree(ctx));
615  return;
616 }
617 
618 void RouterControl::addComtreeLink(CtlPkt& cp) {
619  comt_t comt; int lnk, coreFlag; ipa_t peerIp; ipp_t peerPort;
620  fAdr_t peerAdr;
621  xtrAddComtreeLink(comt,lnk,coreFlag,peerIp,peerPort,peerAdr);
622 
623  unique_lock ltLock(rtr->ltMtx,defer_lock);
624  unique_lock cttLock(rtr->cttMtx,defer_lock);
625  unique_lock rtLock(rtr->rtMtx,defer_lock);
626  lock(ltLock, cttLock, rtLock);
627  int ctx = rtr->ctt->getComtIndex(comt);
628  if (ctx == 0) {
629  cp.fmtError("add comtree link: invalid comtree";
630  return;
631  }
632  if (lnk == 0 && cp.ip1 != 0 && cp.port1 != 0) {
633  lnk = rtr->lt->lookup(cp.ip1, cp.port1);
634  } else if (lnk == 0 && peerAdr != 0) {
635  lnk = rtr->lt->lookup(peerAdr);
636  }
637  if (!rtr->lt->valid(lnk)) {
638  cp.fmtError("add comtree link: invalid link or "
639  "peer IP and port";
640  return;
641  }
642  LinkTable::Entry& rte = rtr->lt->getEntry(lnk);
643  ComtreeTable::Entry& cte = rtr->ctt->getEntry(ctx);
644  bool isRtr = false;
645  if (lte.peerType == Forest::ROUTER) {
646  isRtr = true;
647  if (!coreFlag) {
648  cp.fmtError("add comtree link: must specify "
649  "core flag on links to routers";
650  return;
651  }
652  }
653  int cLnk = rtr->ctt->getClnkNum(comt,lnk);
654  if (cLnk != 0) {
655  cp.fmtError("addComtreeLink: specified "
656  "link already in comtree";
657  return;
658  }
659  // define new comtree link
660  if (!rtr->ctt->addLink(ctx,lnk,isRtr,coreFlag)) {
661  cp.fmtError("add comtree link: cannot add "
662  "requested comtree link";
663  return;
664  }
665  cLnk = rtr->ctt->getClnkNum(comt,lnk);
666  ComtreeTable::ClnkInfo& cli = rtr->ctt->getClinkInfo(ctx,cLnk);
667  cli.dest = 0;
668 
669  // add unicast route to cLnk if peer is a leaf or a router
670  // in a different zip code
671  if (lte.peerType != Forest::ROUTER) {
672  int rtx = rtr->rt->getRtx(comt,peerAdr);
673  if (rtx == 0) rtr->rt->addEntry(comt,lte.peerAdr,cLnk);
674  } else {
675  int zipPeer = Forest::zipCode(lte.peerAdr);
676  if (zipPeer != Forest::zipCode(myAdr)) {
677  fAdr_t dest = Forest::forestAdr(zipPeer,0);
678  int rtx = rtr->rt->getRtx(comt,dest);
679  if (rtx == 0) rtr->rt->addEntry(comt,dest,cLnk);
680  }
681  }
682 
683  // allocate queue and bind it to lnk and comtree link
684  int qid = qm->allocQ(lnk);
685  if (qid == 0) {
686  rtr->ctt->removeLink(ctx,cLnk);
687  cp.fmtError("add comtree link: no queues "
688  "available for link";
689  return;
690  }
691  cli.qnum = qid;
692 
693  // adjust rates for link comtree and queue
696  if (!minRates.leq(lte.availRates)) {
697  cp.fmtError("add comtree link: request "
698  "exceeds link capacity";
699  return;
700  }
701  lte.availRates.subtract(minRates);
702  cli.rates = minRates;
703 
704  qm->setQRates(qid,minRates);
705  if (isRtr) qm->setQLimits(qid,500,1000000);
706  else qm->setQLimits(qid,500,1000000);
707  sm->clearQuStats(qid);
708  cp.fmtAddComtreeLinkReply(lnk,lte.availRates);
709  return;
710 }
711 
712 void RouterControl::dropComtreeLink(CtlPkt& cp) {
713  comt_t comt; int lnk; ipa_t peerIp; ipp_t peerPort; fAdr_t peerAdr;
714  xtrDropComtreeLink(comt, lnk, peerIp, peerPort, peerAdr);
715 
716  unique_lock ltLock(rtr->ltMtx,defer_lock);
717  unique_lock cttLock(rtr->cttMtx,defer_lock);
718  unique_lock rtLock(rtr->rtMtx,defer_lock);
719  lock(ltLock, cttLock, rtLock);
720  int ctx = rtr->ctt->getComtIndex(comt);
721  if (ctx == 0) {
722  cp.fmtError("drop comtree link: invalid comtree";
723  return;
724  }
725  if (lnk == 0 && cp.ip1 != 0 && cp.port1 != 0) {
726  lnk = rtr->lt->lookup(cp.ip1, cp.port1);
727  } else if (lnk == 0 && peerAdr != 0) {
728  lnk = rtr->lt->lookup(cp.adr1);
729  }
730  if (!rtr->lt->valid(lnk)) {
731  cp.fmtError("drop comtree link: invalid link "
732  "or peer IP and port";
733  return;
734  }
735  LinkTable::Entry& lte = rtr->lt->getEntry(lnk);
736  int cLnk = rtr->ctt->getComtLink(comt,lnk);
737  if (cLnk != 0) {
738  // remove all routes involving this comtree
739  rtr->lt->purge(comt,cLnk);
740 
741  // return assigned link bandwidth to link
742  ComtreeTable::ClnkInfo& cli = rtr->ctt->getClnkInfo(ctx,cLnk);
743  lte.availRates.add(cli.rates);
744 
745  // de-allocate queue
746  qm->freeQ(cli.qnum);
747 
748  rtr->ctt->removeLink(ctx,cLnk);
749  }
751  return;
752 }
753 
754 void RouterControl::modComtreeLink(CtlPkt& cp) {
755  comt_t comt; int lnk; RateSpec rates;
756  if (!cp.xtrModComtreeLink(comt,lnk,rates)) {
757  cp.fmtError("unable to unpack control packet"); return;
758  }
759 
760  unique_lock ltLock(rtr->ltMtx,defer_lock);
761  unique_lock cttLock(rtr->cttMtx,defer_lock);
762  lock(ltLock, cttLock);
763  int ctx = rtr->ctt->getComtIndex(comt);
764  if (ctx == 0) {
765  cp.fmtError("modify comtree link: invalid comtree";
766  return;
767  }
768  if (!rtr->lt->valid(lnk)) {
769  cp.fmtError("modify comtree link: invalid link number";
770  return;
771  }
772  int cLnk = rtr->ctt->getComtLink(comt,lnk);
773  if (cLnk == 0) {
774  cp.fmtError("modify comtree link: specified link "
775  "not defined in specified comtree";
776  return;
777  }
778  LinkTable::Entry& lte = rtr->lt->getEntry(lnk);
779  ComtreeTable::Entry& ctte = rtr->ctt->getEntry(ctx);
780  ComtreeTable::ClnkInfo& cli = rtr->ctt->getClnkInfo(ctx,cLnk);
781 
782  cli.dest = dest;
783  RateSpec diff = rates; diff.subtract(cli.rates);
784  if (!diff.leq(lte.availRates)) {
785  cp.fmtError("modify comtree link: new rate spec "
786  "exceeds available link capacity";
787  return;
788  }
789  lte.availRates.subtract(diff);
790  cli.rates = rates;
791  cp.fmtModComtreeLink(lte.availRates); // return available rate on link
792  return;
793 }
794 
795 void RouterControl::getComtreeLink(CtlPkt& cp) {
796  comt_t comt; int lnk;
797  if (!cp.xtrGetComtreeLink(comt,lnk)) {
798  cp.fmtError("unable to unpack control packet"); return;
799  }
800 
801  unique_lock ltLock(rtr->ltMtx,defer_lock);
802  unique_lock cttLock(rtr->cttMtx,defer_lock);
803  lock(ltLock, cttLock);
804  int ctx = rtr->ctt->getComtIndex(comt);
805  if (ctx == 0) {
806  cp.fmtError("get comtree link: invalid comtree";
807  return;
808  }
809  if (!rtr->lt->valid(lnk)) {
810  cp.fmtError("get comtree link: invalid link number";
811  return;
812  }
813  int cLnk = rtr->ctt->getClnkNum(comt,lnk);
814  if (cLnk == 0) {
815  cp.fmtError("getComtreeLink: specified link "
816  "not defined in specified comtree";
817  return;
818  }
819  ComtreeTable::ClnkInfo& cli = rtr->ctt->getClnkInfo(ctx,cLnk);
820  cp.fmtGetComtreeLinkReply(comt,lnk,cli.rates,qid,cli.dest);
821  return;
822 }
823 
824 void RouterControl::addRoute(CtlPkt& cp) {
825  comt_t comt; fAdr_t destAdr; int lnk;
826  if (!cp.xtrAddRoute(comt, destAdr, lnk)) {
827  cp.fmtError("unable to unpack control packet"); return;
828  }
829 
830  unique_lock cttLock(rtr->cttMtx,defer_lock);
831  unique_lock rtLock(rtr->rtMtx,defer_lock);
832  lock(cttLock, rtLock);
833  if (!rtr->ctt->validComtree(comt)) {
834  cp.fmtError("comtree not defined at this router\n";
835  return;
836  }
837  if (!Forest::validUcastAdr(destAdr) && !Forest::mcastAdr(destAdr)) {
838  cp.fmtError("invalid address\n";
839  return;
840  }
841  int cLnk = rtr->ctt->getComtLink(comt,lnk);
842  int rtx = rtr->rt->getRteIndex(comt,destAdr);
843  if (rtx != 0) {
844  cp.fmtError("add route: requested route "
845  "conflicts with existing route";
846  return;
847  } else if (rtr->rt->addEntry(comt, destAdr, lnk)) {
848  cp.fmtAddRouteReply();
849  return;
850  }
851  cp.fmtError("add route: cannot add route";
852  return;
853 }
854 
855 void RouterControl::dropRoute(CtlPkt& cp) {
856  comt_t comt; fAdr_t destAdr;
857  if (!cp.xtrDropRoute(comt, destAdr)) {
858  cp.fmtError("unable to unpack control packet"); return;
859  }
860 
861  unique_lock cttLock(rtr->cttMtx,defer_lock);
862  unique_lock rtLock(rtr->rtMtx,defer_lock);
863  lock(cttLock, rtLock);
864  if (!rtr->ctt->validComtree(comt)) {
865  cp.fmtError("comtree not defined at this router\n";
866  return;
867  }
868  if (!Forest::validUcastAdr(destAdr) && !Forest::mcastAdr(destAdr)) {
869  cp.fmtError("invalid address\n";
870  return;
871  }
872  rtr->rt->removeEntry(rtr->rt->getRtx(comt,destAdr));
873  cp.fmtDropRouteReply();
874  return;
875 }
876 
877 void RouterControl::getRoute(CtlPkt& cp) {
878  comt_t comt; fAdr_t destAdr;
879  if (!cp.xtrGetRoute(comt, destAdr)) {
880  cp.fmtError("unable to unpack control packet"); return;
881  }
882 
883  unique_lock cttLock(rtr->cttMtx,defer_lock);
884  unique_lock rtLock(rtr->rtMtx,defer_lock);
885  lock(cttLock, rtLock);
886  if (!rtr->ctt->validComtree(comt)) {
887  cp.fmtError("comtree not defined at this router\n";
888  return;
889  }
890  if (!Forest::validUcastAdr(destAdr) && !Forest::mcastAdr(destAdr)) {
891  cp.fmtError("invalid address\n";
892  return;
893  }
894  int rtx = rtr->rt->getRtx(comt,destAdr);
895  if (rtx != 0) {
896  int lnk = (Forest::validUcastAdr(destAdr) ?
897  rtr->ctt->getLink(rtr->rt->firstComtLink(rtx)) : 0);
898  cp.fmtGetRoute(comt,destAdr,lnk,rtr->rt->getLinkCount(rtx));
899  return;
900  }
901  cp.fmtError("get route: no route for specified address";
902  return;
903 }
904 
905 void RouterControl::modRoute(CtlPkt& cp) {
906  comt_t comt; fAdr_t destAdr; int lnk;
907  if (!cp.xtrModRoute(comt, destAdr, lnk)) {
908  cp.fmtError("unable to unpack control packet"); return;
909  }
910 
911  unique_lock cttLock(rtr->cttMtx,defer_lock);
912  unique_lock rtLock(rtr->rtMtx,defer_lock);
913  lock(cttLock, rtLock);
914  if (!rtr->ctt->validComtree(comt)) {
915  cp.fmtError("comtree not defined at this router\n";
916  return;
917  }
918  if (!Forest::validUcastAdr(destAdr) && !Forest::mcastAdr(destAdr)) {
919  cp.fmtError("invalid address\n";
920  return;
921  }
922  int rtx = rtr->rt->getRtx(comt,destAdr);
923  if (rtx != 0) {
924  if (cp.link != 0) {
925  if (Forest::mcastAdr(destAdr)) {
926  cp.fmtError("modify route: cannot "
927  "set link in multicast route";
928  return;
929  }
930  rtr->rt->setLink(rtx,cp.link);
931  }
932  cp.fmtReply();
933  return;
934  }
935  cp.fmtError("modify route: invalid route";
936  return;
937 }
938 
950  int rtx, count;
951  xtrGetRouteSet(rtx, count);
952 
953  unique_lock cttLock(rtr->cttMtx,defer_lock);
954  unique_lock rtLock(rtr->rtMtx,defer_lock);
955  lock(cttLock, rtLock);
956 // think about re-doing this to use (comt,dest) pairs rather than rtx values
957  if (rtx == 0) {
958  rtx = rtr->rt->firstRtx(); // 0 means first route
959  } else if (!rtr->rt->validRtx(rtx)) {
960  cp.fmtError("get route set: invalid route number";
961  return;
962  }
963  count = min(10,count);
964  int i = 0;
965  while (i < count && rtx != 0) {
966  rcp.stringData.append(rtr->rt->entry2string(rtx));
967  if (rcp.stringData.length() > 1300) {
968  cp.fmtError( "get route set: error while formatting "
969  "reply";
970  return;
971  }
972  i++; rtx = rtr->rt->nextRtx(rIndex);
973  }
974  cp.fmtGetRouteSetReply(count, rtx);
975  return;
976 }
977 
989  if (!cp.xtrAddFilter()) {
990  cp.fmtError("unable to unpack control packet"); return;
991  }
992 
993  fltx fx = pktLog->addFilter();
994  if (fx == 0) {
995  cp.fmtError("add filter: cannot add filter";
996  return;
997  }
998  cp.fmtAddFilterReply(fx);
999  return;
1000 }
1001 
1002 void RouterControl::dropFilter(CtlPkt& cp) {
1003  int fx;
1004  if (!cp.xtrDropFilter(fx)) {
1005  cp.fmtError("unable to unpack control packet"); return;
1006  }
1007  pktLog->dropFilter(fx);
1008  cp.fmtReply();
1009  return;
1010 }
1011 
1012 void RouterControl::getFilter(CtlPkt& cp) {
1013  fltx fx;
1014  if (!cp.xtrGetFilter(fx)) {
1015  cp.fmtError("unable to unpack control packet"); return;
1016  }
1017 
1018  if (!pktLog->validFilter(fx)) {
1019  cp.fmtError("get filter: invalid filter index";
1020  return;
1021  }
1022  PacketFilter& f = pktLog->getFilter(fx);
1024  return;
1025 }
1026 
1027 void RouterControl::modFilter(CtlPkt& cp) {
1028  fltx fx; string s;
1029  if (!cp.xtrModFilter(fx,s)) {
1030  cp.fmtError("unable to unpack control packet"); return;
1031  }
1032  if (!pktLog->validFilter(fx)) {
1033  cp.fmtError("mod filter: invalid filter index";
1034  return;
1035  }
1036  PacketFilter& f = pktLog->getFilter(fx);
1037  f.fromString(s);
1038  cp.fmtReply();
1039  return;
1040 }
1041 
1053  fltx fx; int count;
1054  if (!cp.xtrGetFilterSet(fx, count)) {
1055  cp.fmtError("unable to unpack control packet"); return;
1056  }
1057 
1058  if (fx == 0) {
1059  fx = pktLog->firstFilter(); // 0 means start with first filter
1060  } else if (!pktLog->validFilter(fx)) {
1061  cp.fmtError("get filter set: invalid filter index";
1062  return;
1063  }
1064  count = min(10,count);
1065  int i = 0;
1066  stringstream ss;
1067  while (i < count && fx != 0) {
1068  PacketFilter& f = pktLog->getFilter(fx);
1069  ss << fx << " " << f.toString() << "\n";
1070 
1071  if (ss.str().length() > 1300) {
1072  cp.fmtError("get filter set: error while "
1073  "formatting reply";
1074  return;
1075  }
1076  i++; fx = pktLog->nextFilter(fx);
1077  }
1078  cp.fmtGetFilterSetReply(fx, count, ss.str());
1079  return;
1080 }
1081 
1089  if (!cp.xtrGetLoggedPackets()) {
1090  cp.fmtError("unable to unpack control packet"); return;
1091  }
1092  string s;
1093  int count = pktLog->extract(1300, s);
1094  cp.fmtGetLoggedPacketsReply(count,s);
1095  return;
1096 }
1097 
1105  // if this client has another op in progress, add request to list
1106  // of pending operations and return
1107  // if comtree exists at this router
1108  // if client already in comtree, send positive reply and return
1109  // if any non-local ops in progress, add request to list of
1110  // pending operations and return
1111  // add client to comtree, allocating rates appropriately
1112  // add operation to set of pending local operations
1113  // send addNode report to comtree controller and return
1114 }
1115 
1123 }
1124 
1132 }
1133 
1141 }
1142 
1150 }
1151 
1158 void RouterControl::abort(CtlPkt& cp) {
1159 }
1160 
1161 
1162 } // ends namespace