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