RoutingTableLogger.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. //
  2. // Copyright (C) 2013 Opensim Ltd.
  3. //
  4. // This program is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public License
  6. // as published by the Free Software Foundation; either version 2
  7. // of the License, or (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with this program; if not, see <http://www.gnu.org/licenses/>.
  16. //
  17. #include <fstream>
  18. #include "inet/common/INETDefs.h"
  19. #include "inet/common/scenario/IScriptable.h"
  20. #include "inet/networklayer/contract/IRoutingTable.h"
  21. #include "inet/networklayer/contract/IL3AddressType.h"
  22. using namespace std;
  23. namespace inet {
  24. struct DestFilter
  25. {
  26. vector<L3Address> destAddresses;
  27. vector<int> prefixLengths;
  28. DestFilter(const char *str);
  29. bool matches(IRoute *route);
  30. };
  31. DestFilter::DestFilter(const char *str)
  32. {
  33. if (str)
  34. {
  35. cStringTokenizer tokenizer(str);
  36. while (tokenizer.hasMoreTokens())
  37. {
  38. const char *dest = tokenizer.nextToken();
  39. const char *end = strchr(dest, '/');
  40. if (end)
  41. {
  42. destAddresses.push_back(L3Address(string(dest,end).c_str()));
  43. prefixLengths.push_back(atoi(end+1));
  44. }
  45. else
  46. {
  47. L3Address destAddr = L3Address(dest);
  48. destAddresses.push_back(destAddr);
  49. prefixLengths.push_back(destAddr.getAddressType()->getMaxPrefixLength());
  50. }
  51. }
  52. }
  53. }
  54. bool DestFilter::matches(IRoute *route)
  55. {
  56. if (destAddresses.empty())
  57. return true;
  58. for (int i = 0; i < (int)destAddresses.size(); ++i)
  59. {
  60. L3Address &dest = destAddresses[i];
  61. int prefixLength = prefixLengths[i];
  62. if (route->getDestinationAsGeneric().matches(dest, prefixLength))
  63. return true;
  64. }
  65. return false;
  66. }
  67. class INET_API RoutingTableLogger : public cSimpleModule, public IScriptable
  68. {
  69. ofstream out;
  70. protected:
  71. virtual void initialize();
  72. virtual void finish();
  73. virtual void processCommand(const cXMLElement &node);
  74. private:
  75. IRoutingTable *findRoutingTableInNode(cModule *node);
  76. void dumpRoutes(cModule *node, IRoutingTable *rt, DestFilter &filter);
  77. };
  78. Define_Module(RoutingTableLogger);
  79. void RoutingTableLogger::initialize()
  80. {
  81. const char *filename = par("outputFile");
  82. if (filename && (*filename))
  83. {
  84. out.open(filename);
  85. if (out.fail())
  86. throw cRuntimeError("Failed to open output file: %s", filename);
  87. }
  88. }
  89. void RoutingTableLogger::finish()
  90. {
  91. out << "END" << endl;
  92. }
  93. void RoutingTableLogger::processCommand(const cXMLElement &command)
  94. {
  95. Enter_Method_Silent();
  96. const char *tag = command.getTagName();
  97. if (!strcmp(tag, "dump-routes"))
  98. {
  99. const char *nodes = command.getAttribute("nodes");
  100. if (!nodes)
  101. throw cRuntimeError("missing @nodes attribute");
  102. DestFilter filter(command.getAttribute("dest"));
  103. cStringTokenizer tokenizer(nodes);
  104. while(tokenizer.hasMoreTokens())
  105. {
  106. const char *nodeName = tokenizer.nextToken();
  107. cModule *node = getModuleByPath(nodeName);
  108. if (!node)
  109. throw cRuntimeError("module '%s' not found at %s", nodeName, command.getSourceLocation());
  110. IRoutingTable *rt = findRoutingTableInNode(node);
  111. dumpRoutes(node, rt, filter);
  112. }
  113. }
  114. }
  115. IRoutingTable *RoutingTableLogger::findRoutingTableInNode(cModule *node)
  116. {
  117. for (cModule::SubmoduleIterator i(node); !i.end(); ++i)
  118. {
  119. IRoutingTable *rt = dynamic_cast<IRoutingTable*>(*i);
  120. if (rt)
  121. return rt;
  122. }
  123. return NULL;
  124. }
  125. void RoutingTableLogger::dumpRoutes(cModule *node, IRoutingTable *rt, DestFilter &filter)
  126. {
  127. out << node->getFullName() << " " << simTime() << endl;
  128. for (int i = 0; i < rt->getNumRoutes(); ++i)
  129. {
  130. IRoute *route = rt->getRoute(i);
  131. if (filter.matches(route))
  132. {
  133. out << route->getDestinationAsGeneric() << "/" << route->getPrefixLength()
  134. << " " << route->getNextHopAsGeneric()
  135. << " " << (route->getInterface() ? route->getInterface()->getName() : "*")
  136. << " " << IRoute::sourceTypeName(route->getSourceType()) << " " << route->getMetric()
  137. << endl;
  138. }
  139. }
  140. }
  141. } // namespace inet