00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "TableBasedRouter.h"
00040 #include "RouteTable.h"
00041 #include "bundling/BundleActions.h"
00042 #include "bundling/BundleDaemon.h"
00043 #include "contacts/Contact.h"
00044 #include "contacts/Link.h"
00045
00046 namespace dtn {
00047
00048
00049 TableBasedRouter::TableBasedRouter(const char* classname,
00050 const std::string& name)
00051 : BundleRouter(classname, name)
00052 {
00053 route_table_ = new RouteTable(name);
00054 }
00055
00056
00057 void
00058 TableBasedRouter::add_route(RouteEntry *entry)
00059 {
00060 route_table_->add_entry(entry);
00061 check_next_hop(entry->next_hop_);
00062 }
00063
00064
00065 void
00066 TableBasedRouter::del_route(const EndpointIDPattern& dest)
00067 {
00068 route_table_->del_entries(dest);
00069 }
00070
00071
00072 void
00073 TableBasedRouter::handle_event(BundleEvent* event)
00074 {
00075 dispatch_event(event);
00076 }
00077
00078
00079 void
00080 TableBasedRouter::handle_bundle_received(BundleReceivedEvent* event)
00081 {
00082 Bundle* bundle = event->bundleref_.object();
00083 log_debug("handle bundle received: *%p", bundle);
00084 fwd_to_matching(bundle);
00085 }
00086
00087
00088 void
00089 TableBasedRouter::handle_bundle_transmit_failed(BundleTransmitFailedEvent* event)
00090 {
00091 Bundle* bundle = event->bundleref_.object();
00092 log_debug("handle bundle transmit failed: *%p", bundle);
00093 fwd_to_matching(bundle);
00094 }
00095
00096
00097 void
00098 TableBasedRouter::handle_route_add(RouteAddEvent* event)
00099 {
00100 add_route(event->entry_);
00101 }
00102
00103
00104 void
00105 TableBasedRouter::handle_route_del(RouteDelEvent* event)
00106 {
00107 del_route(event->dest_);
00108 }
00109
00110
00111 void
00112 TableBasedRouter::handle_contact_up(ContactUpEvent* event)
00113 {
00114 check_next_hop(event->contact_->link());
00115 }
00116
00117
00118 void
00119 TableBasedRouter::handle_link_available(LinkAvailableEvent* event)
00120 {
00121 check_next_hop(event->link_);
00122 }
00123
00124
00125 void
00126 TableBasedRouter::handle_link_created(LinkCreatedEvent* event)
00127 {
00128 if (Config.add_nexthop_routes_) {
00129 Link* link = event->link_;
00130 EndpointID eid = link->remote_eid();
00131
00132 if (! eid.equals(EndpointID::NULL_EID()) ) {
00133
00134 RouteEntry *entry = new RouteEntry(
00135 EndpointIDPattern(eid.str() + std::string("/*")), link);
00136 entry->action_ = ForwardingInfo::FORWARD_ACTION;
00137 BundleDaemon::post(new RouteAddEvent(entry));
00138 }
00139 }
00140 }
00141
00142
00143 void
00144 TableBasedRouter::handle_custody_timeout(CustodyTimeoutEvent* event)
00145 {
00146
00147
00148
00149
00150
00151
00152
00153 fwd_to_matching(event->bundle_.object());
00154 }
00155
00156
00157 void
00158 TableBasedRouter::get_routing_state(oasys::StringBuffer* buf)
00159 {
00160 EndpointIDVector long_eids;
00161 buf->appendf("Route table for %s router:\n\n", name_.c_str());
00162 route_table_->dump(buf, &long_eids);
00163
00164 if (long_eids.size() > 0) {
00165 buf->appendf("\nLong Endpoint IDs referenced above:\n");
00166 for (u_int i = 0; i < long_eids.size(); ++i) {
00167 buf->appendf("\t[%d]: %s\n", i, long_eids[i].c_str());
00168 }
00169 buf->appendf("\n");
00170 }
00171
00172 buf->append("\nClass of Service (COS) bits:\n"
00173 "\tB: Bulk N: Normal E: Expedited\n\n");
00174 }
00175
00176
00177 void
00178 TableBasedRouter::fwd_to_nexthop(Bundle* bundle, RouteEntry* route)
00179 {
00180 Link* link = route->next_hop_;
00181
00182
00183 if (link->isopen() && !link->isbusy()) {
00184 log_debug("sending *%p to *%p", bundle, link);
00185 actions_->send_bundle(bundle, link,
00186 route->action_, route->custody_timeout_);
00187 }
00188
00189
00190 else if (link->isavailable() && (!link->isopen()) && (!link->isopening())) {
00191 log_debug("opening *%p because a message is intended for it", link);
00192 actions_->open_link(link);
00193 }
00194
00195
00196
00197 else {
00198 if (!link->isavailable()) {
00199 log_debug("can't forward *%p to *%p because link not available",
00200 bundle, link);
00201 } else if (! link->isopen()) {
00202 log_debug("can't forward *%p to *%p because link not open",
00203 bundle, link);
00204 } else if (link->isbusy()) {
00205 log_debug("can't forward *%p to *%p because link is busy",
00206 bundle, link);
00207 } else {
00208 log_debug("can't forward *%p to *%p", bundle, link);
00209 }
00210 }
00211 }
00212
00213
00214 bool
00215 TableBasedRouter::should_fwd(const Bundle* bundle, RouteEntry* route)
00216 {
00217 ForwardingInfo info;
00218 bool found = bundle->fwdlog_.get_latest_entry(route->next_hop_, &info);
00219
00220 if (found) {
00221 ASSERT(info.state_ != ForwardingInfo::NONE);
00222 } else {
00223 ASSERT(info.state_ == ForwardingInfo::NONE);
00224 }
00225
00226 if (info.state_ == ForwardingInfo::TRANSMITTED ||
00227 info.state_ == ForwardingInfo::IN_FLIGHT)
00228 {
00229 log_debug("should_fwd bundle %d: "
00230 "skip %s due to forwarding log entry %s",
00231 bundle->bundleid_, route->next_hop_->name(),
00232 ForwardingInfo::state_to_str(info.state_));
00233 return false;
00234 }
00235
00236 if (route->action_ == ForwardingInfo::FORWARD_ACTION) {
00237 size_t count;
00238
00239 count = bundle->fwdlog_.
00240 get_transmission_count(ForwardingInfo::FORWARD_ACTION, true);
00241 if (count > 0) {
00242 log_debug("should_fwd bundle %d: "
00243 "skip %s since already transmitted (count %zu)",
00244 bundle->bundleid_, route->next_hop_->name(), count);
00245 return false;
00246 } else {
00247 log_debug("should_fwd bundle %d: "
00248 "link %s ok since transmission count=%zu",
00249 bundle->bundleid_, route->next_hop_->name(), count);
00250 }
00251 }
00252
00253 if (info.state_ == ForwardingInfo::TRANSMIT_FAILED) {
00254 log_debug("should_fwd bundle %d: "
00255 "match %s: forwarding log entry %s TRANSMIT_FAILED %d",
00256 bundle->bundleid_, route->next_hop_->name(),
00257 ForwardingInfo::state_to_str(info.state_),
00258 bundle->bundleid_);
00259
00260 } else {
00261 log_debug("should_fwd bundle %d: "
00262 "match %s: forwarding log entry %s",
00263 bundle->bundleid_, route->next_hop_->name(),
00264 ForwardingInfo::state_to_str(info.state_));
00265 }
00266
00267 return true;
00268 }
00269
00270
00271 int
00272 TableBasedRouter::fwd_to_matching(Bundle* bundle, Link* this_link_only)
00273 {
00274 RouteEntryVec matches;
00275 RouteEntryVec::iterator iter;
00276
00277
00278
00279 route_table_->get_matching(bundle->dest_, this_link_only, &matches);
00280
00281
00282
00283 matches.sort_by_priority();
00284
00285 int count = 0;
00286 for (iter = matches.begin(); iter != matches.end(); ++iter)
00287 {
00288 if (! should_fwd(bundle, *iter)) {
00289 continue;
00290 }
00291
00292 fwd_to_nexthop(bundle, *iter);
00293 ++count;
00294 }
00295
00296 log_debug("fwd_to_matching bundle id %d: %d matches",
00297 bundle->bundleid_, count);
00298 return count;
00299 }
00300
00301
00302 void
00303 TableBasedRouter::check_next_hop(Link* next_hop)
00304 {
00305 log_debug("check_next_hop %s: checking pending bundle list...",
00306 next_hop->nexthop());
00307
00308 oasys::ScopeLock l(pending_bundles_->lock(),
00309 "TableBasedRouter::check_next_hop");
00310 BundleList::iterator iter;
00311 for (iter = pending_bundles_->begin();
00312 iter != pending_bundles_->end();
00313 ++iter)
00314 {
00315 fwd_to_matching(*iter, next_hop);
00316 }
00317 }
00318
00319 }