IBR-DTNSuite
0.8
|
00001 /* 00002 * StaticRoutingExtension.cpp 00003 * 00004 * Created on: 16.02.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "Configuration.h" 00009 #include "routing/StaticRoutingExtension.h" 00010 #include "routing/QueueBundleEvent.h" 00011 #include "routing/StaticRouteChangeEvent.h" 00012 #include "net/TransferAbortedEvent.h" 00013 #include "net/TransferCompletedEvent.h" 00014 #include "net/ConnectionEvent.h" 00015 #include "routing/RequeueBundleEvent.h" 00016 #include "core/NodeEvent.h" 00017 #include "storage/SimpleBundleStorage.h" 00018 #include "core/TimeEvent.h" 00019 00020 #include <ibrdtn/utils/Clock.h> 00021 00022 #include <ibrcommon/Logger.h> 00023 #include <ibrcommon/thread/MutexLock.h> 00024 00025 #include <typeinfo> 00026 #include <memory> 00027 00028 namespace dtn 00029 { 00030 namespace routing 00031 { 00032 StaticRoutingExtension::StaticRoutingExtension() 00033 : next_expire(0) 00034 { 00035 } 00036 00037 StaticRoutingExtension::~StaticRoutingExtension() 00038 { 00039 stop(); 00040 join(); 00041 00042 // delete all static routes 00043 for (std::list<StaticRoute*>::iterator iter = _routes.begin(); 00044 iter != _routes.end(); iter++) 00045 { 00046 StaticRoute *route = (*iter); 00047 delete route; 00048 } 00049 } 00050 00051 void StaticRoutingExtension::__cancellation() 00052 { 00053 _taskqueue.abort(); 00054 } 00055 00056 void StaticRoutingExtension::run() 00057 { 00058 class BundleFilter : public dtn::storage::BundleStorage::BundleFilterCallback 00059 { 00060 public: 00061 BundleFilter(const NeighborDatabase::NeighborEntry &entry, const std::list<const StaticRoute*> &routes) 00062 : _entry(entry), _routes(routes) 00063 {}; 00064 00065 virtual ~BundleFilter() {}; 00066 00067 virtual size_t limit() const { return 10; }; 00068 00069 virtual bool shouldAdd(const dtn::data::MetaBundle &meta) const 00070 { 00071 // check Scope Control Block - do not forward bundles with hop limit == 0 00072 if (meta.hopcount == 0) 00073 { 00074 return false; 00075 } 00076 00077 // do not forward any routing control message 00078 // this is done by the neighbor routing module 00079 if (isRouting(meta.source)) 00080 { 00081 return false; 00082 } 00083 00084 // do not forward local bundles 00085 if ((meta.destination.getNode() == dtn::core::BundleCore::local) 00086 && meta.get(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON) 00087 ) 00088 { 00089 return false; 00090 } 00091 00092 // check Scope Control Block - do not forward non-group bundles with hop limit <= 1 00093 if ((meta.hopcount <= 1) && (meta.get(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON))) 00094 { 00095 return false; 00096 } 00097 00098 // do not forward to any blacklisted destination 00099 const dtn::data::EID dest = meta.destination.getNode(); 00100 if (_blacklist.find(dest) != _blacklist.end()) 00101 { 00102 return false; 00103 } 00104 00105 // do not forward bundles already known by the destination 00106 if (_entry.has(meta)) 00107 { 00108 return false; 00109 } 00110 00111 // search for one rule that match 00112 for (std::list<const StaticRoute*>::const_iterator iter = _routes.begin(); 00113 iter != _routes.end(); iter++) 00114 { 00115 const StaticRoute &route = (**iter); 00116 00117 if (route.match(meta.destination)) 00118 { 00119 return true; 00120 } 00121 } 00122 00123 return false; 00124 }; 00125 00126 void blacklist(const dtn::data::EID& id) 00127 { 00128 _blacklist.insert(id); 00129 }; 00130 00131 private: 00132 std::set<dtn::data::EID> _blacklist; 00133 const NeighborDatabase::NeighborEntry &_entry; 00134 const std::list<const StaticRoute*> _routes; 00135 }; 00136 00137 // announce static routes here 00138 const std::multimap<std::string, std::string> &routes = dtn::daemon::Configuration::getInstance().getNetwork().getStaticRoutes(); 00139 00140 for (std::multimap<std::string, std::string>::const_iterator iter = routes.begin(); iter != routes.end(); iter++) 00141 { 00142 const dtn::data::EID nexthop((*iter).second); 00143 dtn::routing::StaticRouteChangeEvent::raiseEvent(dtn::routing::StaticRouteChangeEvent::ROUTE_ADD, nexthop, (*iter).first); 00144 } 00145 00146 dtn::storage::BundleStorage &storage = (**this).getStorage(); 00147 00148 while (true) 00149 { 00150 NeighborDatabase &db = (**this).getNeighborDB(); 00151 00152 try { 00153 Task *t = _taskqueue.getnpop(true); 00154 std::auto_ptr<Task> killer(t); 00155 00156 IBRCOMMON_LOGGER_DEBUG(5) << "processing static routing task " << t->toString() << IBRCOMMON_LOGGER_ENDL; 00157 00158 try { 00159 SearchNextBundleTask &task = dynamic_cast<SearchNextBundleTask&>(*t); 00160 00161 std::list<const StaticRoute*> routes; 00162 00163 // look for routes to this node 00164 for (std::list<StaticRoute*>::const_iterator iter = _routes.begin(); 00165 iter != _routes.end(); iter++) 00166 { 00167 const StaticRoute *route = (*iter); 00168 if (route->getDestination() == task.eid) 00169 { 00170 // add to the valid routes 00171 routes.push_back(route); 00172 } 00173 } 00174 00175 if (routes.size() > 0) 00176 { 00177 // this destination is not handles by any static route 00178 ibrcommon::MutexLock l(db); 00179 NeighborDatabase::NeighborEntry &entry = db.get(task.eid); 00180 00181 // get the bundle filter of the neighbor 00182 BundleFilter filter(entry, routes); 00183 00184 // some debug 00185 IBRCOMMON_LOGGER_DEBUG(40) << "search some bundles not known by " << task.eid.getString() << IBRCOMMON_LOGGER_ENDL; 00186 00187 // blacklist the neighbor itself, because this is handled by neighbor routing extension 00188 filter.blacklist(task.eid); 00189 00190 // query all bundles from the storage 00191 const std::list<dtn::data::MetaBundle> list = storage.get(filter); 00192 00193 // send the bundles as long as we have resources 00194 for (std::list<dtn::data::MetaBundle>::const_iterator iter = list.begin(); iter != list.end(); iter++) 00195 { 00196 try { 00197 // transfer the bundle to the neighbor 00198 transferTo(entry, *iter); 00199 } catch (const NeighborDatabase::AlreadyInTransitException&) { }; 00200 } 00201 } 00202 } catch (const NeighborDatabase::NoMoreTransfersAvailable&) { 00203 } catch (const NeighborDatabase::NeighborNotAvailableException&) { 00204 } catch (const std::bad_cast&) { }; 00205 00206 try { 00207 const ProcessBundleTask &task = dynamic_cast<ProcessBundleTask&>(*t); 00208 IBRCOMMON_LOGGER_DEBUG(50) << "search static route for " << task.bundle.toString() << IBRCOMMON_LOGGER_ENDL; 00209 00210 // look for routes to this node 00211 for (std::list<StaticRoutingExtension::StaticRoute*>::const_iterator iter = _routes.begin(); 00212 iter != _routes.end(); iter++) 00213 { 00214 const StaticRoutingExtension::StaticRoute &route = (**iter); 00215 IBRCOMMON_LOGGER_DEBUG(50) << "check static route: " << route.toString() << IBRCOMMON_LOGGER_ENDL; 00216 try { 00217 if (route.match(task.bundle.destination)) 00218 { 00219 ibrcommon::MutexLock l(db); 00220 NeighborDatabase::NeighborEntry &n = db.get(route.getDestination()); 00221 00222 // transfer the bundle to the neighbor 00223 transferTo(n, task.bundle); 00224 } 00225 } catch (const NeighborDatabase::NeighborNotAvailableException&) { 00226 // neighbor is not available, can not forward this bundle 00227 } catch (const NeighborDatabase::NoMoreTransfersAvailable&) { 00228 } catch (const NeighborDatabase::AlreadyInTransitException&) { }; 00229 } 00230 } catch (const std::bad_cast&) { }; 00231 00232 try { 00233 const RouteChangeTask &task = dynamic_cast<RouteChangeTask&>(*t); 00234 00235 // delete all similar routes 00236 for (std::list<StaticRoute*>::iterator iter = _routes.begin(); 00237 iter != _routes.end();) 00238 { 00239 StaticRoute *route = (*iter); 00240 if (route->toString() == task.route->toString()) 00241 { 00242 delete route; 00243 _routes.erase(iter++); 00244 } 00245 else 00246 { 00247 iter++; 00248 } 00249 } 00250 00251 if (task.type == RouteChangeTask::ROUTE_ADD) 00252 { 00253 _routes.push_back(task.route); 00254 _taskqueue.push( new SearchNextBundleTask(task.route->getDestination()) ); 00255 00256 ibrcommon::MutexLock l(_expire_lock); 00257 if (next_expire > task.route->getExpiration()) 00258 { 00259 next_expire = task.route->getExpiration(); 00260 } 00261 } 00262 else 00263 { 00264 delete task.route; 00265 00266 // force a expiration process 00267 ibrcommon::MutexLock l(_expire_lock); 00268 next_expire = 1; 00269 } 00270 } catch (const bad_cast&) { }; 00271 00272 try { 00273 dynamic_cast<ClearRoutesTask&>(*t); 00274 00275 // delete all static routes 00276 for (std::list<StaticRoute*>::iterator iter = _routes.begin(); 00277 iter != _routes.end(); iter++) 00278 { 00279 StaticRoute *route = (*iter); 00280 delete route; 00281 } 00282 _routes.clear(); 00283 00284 ibrcommon::MutexLock l(_expire_lock); 00285 next_expire = 0; 00286 } catch (const bad_cast&) { }; 00287 00288 try { 00289 const ExpireTask &task = dynamic_cast<ExpireTask&>(*t); 00290 00291 ibrcommon::MutexLock l(_expire_lock); 00292 next_expire = 0; 00293 00294 // search for expired items 00295 for (std::list<StaticRoute*>::iterator iter = _routes.begin(); 00296 iter != _routes.end();) 00297 { 00298 StaticRoute *route = (*iter); 00299 00300 if (route->getExpiration() < task.timestamp) 00301 { 00302 delete route; 00303 _routes.erase(iter++); 00304 } 00305 else 00306 { 00307 if ((next_expire == 0) || (next_expire > route->getExpiration())) 00308 { 00309 next_expire = route->getExpiration(); 00310 } 00311 00312 iter++; 00313 } 00314 } 00315 } catch (const bad_cast&) { }; 00316 00317 } catch (const std::exception &ex) { 00318 IBRCOMMON_LOGGER_DEBUG(20) << "static routing failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00319 return; 00320 } 00321 00322 yield(); 00323 } 00324 } 00325 00326 void StaticRoutingExtension::notify(const dtn::core::Event *evt) 00327 { 00328 try { 00329 const QueueBundleEvent &queued = dynamic_cast<const QueueBundleEvent&>(*evt); 00330 _taskqueue.push( new ProcessBundleTask(queued.bundle, queued.origin) ); 00331 return; 00332 } catch (const std::bad_cast&) { }; 00333 00334 try { 00335 const dtn::core::NodeEvent &nodeevent = dynamic_cast<const dtn::core::NodeEvent&>(*evt); 00336 const dtn::core::Node &n = nodeevent.getNode(); 00337 00338 if (nodeevent.getAction() == NODE_AVAILABLE) 00339 { 00340 _taskqueue.push( new SearchNextBundleTask(n.getEID()) ); 00341 } 00342 return; 00343 } catch (const std::bad_cast&) { }; 00344 00345 try { 00346 const dtn::net::ConnectionEvent &ce = dynamic_cast<const dtn::net::ConnectionEvent&>(*evt); 00347 00348 if (ce.state == dtn::net::ConnectionEvent::CONNECTION_UP) 00349 { 00350 // send all (multi-hop) bundles in the storage to the neighbor 00351 _taskqueue.push( new SearchNextBundleTask(ce.peer) ); 00352 } 00353 return; 00354 } catch (const std::bad_cast&) { }; 00355 00356 // The bundle transfer has been aborted 00357 try { 00358 const dtn::net::TransferAbortedEvent &aborted = dynamic_cast<const dtn::net::TransferAbortedEvent&>(*evt); 00359 _taskqueue.push( new SearchNextBundleTask(aborted.getPeer()) ); 00360 return; 00361 } catch (const std::bad_cast&) { }; 00362 00363 // A bundle transfer was successful 00364 try { 00365 const dtn::net::TransferCompletedEvent &completed = dynamic_cast<const dtn::net::TransferCompletedEvent&>(*evt); 00366 _taskqueue.push( new SearchNextBundleTask(completed.getPeer()) ); 00367 return; 00368 } catch (const std::bad_cast&) { }; 00369 00370 // each second, look for expired routes 00371 try { 00372 const dtn::core::TimeEvent &time = dynamic_cast<const dtn::core::TimeEvent&>(*evt); 00373 00374 ibrcommon::MutexLock l(_expire_lock); 00375 if ((next_expire != 0) && (next_expire < time.getUnixTimestamp())) 00376 { 00377 _taskqueue.push( new ExpireTask( time.getUnixTimestamp() ) ); 00378 } 00379 return; 00380 } catch (const bad_cast&) { }; 00381 00382 // on route change, generate a task 00383 try { 00384 const dtn::routing::StaticRouteChangeEvent &route = dynamic_cast<const dtn::routing::StaticRouteChangeEvent&>(*evt); 00385 00386 if (route.type == dtn::routing::StaticRouteChangeEvent::ROUTE_CLEAR) 00387 { 00388 _taskqueue.push( new ClearRoutesTask() ); 00389 return; 00390 } 00391 00392 StaticRoute *r = NULL; 00393 00394 if (route.pattern.length() > 0) 00395 { 00396 r = new RegexRoute(route.pattern, route.nexthop); 00397 } 00398 else 00399 { 00400 size_t et = dtn::utils::Clock::getUnixTimestamp() + route.timeout; 00401 r = new EIDRoute(route.destination, route.nexthop, et); 00402 } 00403 00404 switch (route.type) 00405 { 00406 case dtn::routing::StaticRouteChangeEvent::ROUTE_ADD: 00407 _taskqueue.push( new RouteChangeTask( RouteChangeTask::ROUTE_ADD, r ) ); 00408 break; 00409 00410 case dtn::routing::StaticRouteChangeEvent::ROUTE_DEL: 00411 _taskqueue.push( new RouteChangeTask( RouteChangeTask::ROUTE_DEL, r ) ); 00412 break; 00413 00414 default: 00415 break; 00416 } 00417 00418 return; 00419 } catch (const bad_cast&) { }; 00420 } 00421 00422 // virtual destructor 00423 StaticRoutingExtension::StaticRoute::~StaticRoute() {}; 00424 00425 StaticRoutingExtension::RegexRoute::RegexRoute(const std::string ®ex, const dtn::data::EID &dest) 00426 : _dest(dest), _regex_str(regex), _invalid(false) 00427 { 00428 if ( regcomp(&_regex, regex.c_str(), 0) ) 00429 { 00430 IBRCOMMON_LOGGER(error) << "Could not compile regex: " << regex << IBRCOMMON_LOGGER_ENDL; 00431 _invalid = true; 00432 } 00433 } 00434 00435 StaticRoutingExtension::RegexRoute::~RegexRoute() 00436 { 00437 if (!_invalid) 00438 regfree(&_regex); 00439 } 00440 00441 StaticRoutingExtension::RegexRoute::RegexRoute(const StaticRoutingExtension::RegexRoute &obj) 00442 : _dest(obj._dest), _regex_str(obj._regex_str), _invalid(obj._invalid) 00443 { 00444 if ( regcomp(&_regex, _regex_str.c_str(), 0) ) 00445 { 00446 _invalid = true; 00447 } 00448 } 00449 00450 StaticRoutingExtension::RegexRoute& StaticRoutingExtension::RegexRoute::operator=(const StaticRoutingExtension::RegexRoute &obj) 00451 { 00452 if (!_invalid) 00453 { 00454 regfree(&_regex); 00455 } 00456 00457 _dest = obj._dest; 00458 _regex_str = obj._regex_str; 00459 _invalid = obj._invalid; 00460 00461 if (!_invalid) 00462 { 00463 if ( regcomp(&_regex, obj._regex_str.c_str(), 0) ) 00464 { 00465 IBRCOMMON_LOGGER(error) << "Could not compile regex: " << _regex_str << IBRCOMMON_LOGGER_ENDL; 00466 _invalid = true; 00467 } 00468 } 00469 00470 return *this; 00471 } 00472 00473 bool StaticRoutingExtension::RegexRoute::match(const dtn::data::EID &eid) const 00474 { 00475 if (_invalid) return false; 00476 00477 const std::string dest = eid.getString(); 00478 00479 // test against the regular expression 00480 int reti = regexec(&_regex, dest.c_str(), 0, NULL, 0); 00481 00482 if( !reti ) 00483 { 00484 // the expression match 00485 return true; 00486 } 00487 else if( reti == REG_NOMATCH ) 00488 { 00489 // the expression not match 00490 return false; 00491 } 00492 else 00493 { 00494 char msgbuf[100]; 00495 regerror(reti, &_regex, msgbuf, sizeof(msgbuf)); 00496 IBRCOMMON_LOGGER(error) << "Regex match failed: " << std::string(msgbuf) << IBRCOMMON_LOGGER_ENDL; 00497 return false; 00498 } 00499 } 00500 00501 const dtn::data::EID& StaticRoutingExtension::RegexRoute::getDestination() const 00502 { 00503 return _dest; 00504 } 00505 00506 const std::string StaticRoutingExtension::RegexRoute::toString() const 00507 { 00508 std::stringstream ss; 00509 ss << _regex_str << " => " << _dest.getString(); 00510 return ss.str(); 00511 } 00512 00513 StaticRoutingExtension::EIDRoute::EIDRoute(const dtn::data::EID &match, const dtn::data::EID &nexthop, size_t et) 00514 : _nexthop(nexthop), _match(match), expiretime(et) 00515 { 00516 } 00517 00518 StaticRoutingExtension::EIDRoute::~EIDRoute() 00519 { 00520 } 00521 00522 bool StaticRoutingExtension::EIDRoute::match(const dtn::data::EID &eid) const 00523 { 00524 return (_match == eid.getNode()); 00525 } 00526 00527 const dtn::data::EID& StaticRoutingExtension::EIDRoute::getDestination() const 00528 { 00529 return _nexthop; 00530 } 00531 00536 const std::string StaticRoutingExtension::EIDRoute::toString() const 00537 { 00538 std::stringstream ss; 00539 ss << _match.getString() << " => " << _nexthop.getString(); 00540 return ss.str(); 00541 } 00542 00543 size_t StaticRoutingExtension::EIDRoute::getExpiration() const 00544 { 00545 return expiretime; 00546 } 00547 00548 /****************************************/ 00549 00550 StaticRoutingExtension::SearchNextBundleTask::SearchNextBundleTask(const dtn::data::EID &e) 00551 : eid(e) 00552 { } 00553 00554 StaticRoutingExtension::SearchNextBundleTask::~SearchNextBundleTask() 00555 { } 00556 00557 std::string StaticRoutingExtension::SearchNextBundleTask::toString() 00558 { 00559 return "SearchNextBundleTask: " + eid.getString(); 00560 } 00561 00562 /****************************************/ 00563 00564 StaticRoutingExtension::ProcessBundleTask::ProcessBundleTask(const dtn::data::MetaBundle &meta, const dtn::data::EID &o) 00565 : bundle(meta), origin(o) 00566 { } 00567 00568 StaticRoutingExtension::ProcessBundleTask::~ProcessBundleTask() 00569 { } 00570 00571 std::string StaticRoutingExtension::ProcessBundleTask::toString() 00572 { 00573 return "ProcessBundleTask: " + bundle.toString(); 00574 } 00575 00576 /****************************************/ 00577 00578 StaticRoutingExtension::ClearRoutesTask::ClearRoutesTask() 00579 { 00580 } 00581 00582 StaticRoutingExtension::ClearRoutesTask::~ClearRoutesTask() 00583 { 00584 } 00585 00586 std::string StaticRoutingExtension::ClearRoutesTask::toString() 00587 { 00588 return "ClearRoutesTask"; 00589 } 00590 00591 /****************************************/ 00592 00593 StaticRoutingExtension::RouteChangeTask::RouteChangeTask(CHANGE_TYPE t, StaticRoute *r) 00594 : type(t), route(r) 00595 { 00596 00597 } 00598 00599 StaticRoutingExtension::RouteChangeTask::~RouteChangeTask() 00600 { 00601 00602 } 00603 00604 std::string StaticRoutingExtension::RouteChangeTask::toString() 00605 { 00606 return "RouteChangeTask: " + (*route).toString(); 00607 } 00608 00609 /****************************************/ 00610 00611 StaticRoutingExtension::ExpireTask::ExpireTask(size_t t) 00612 : timestamp(t) 00613 { 00614 00615 } 00616 00617 StaticRoutingExtension::ExpireTask::~ExpireTask() 00618 { 00619 00620 } 00621 00622 std::string StaticRoutingExtension::ExpireTask::toString() 00623 { 00624 std::stringstream ss; 00625 ss << "ExpireTask: " << timestamp; 00626 return ss.str(); 00627 } 00628 } 00629 }