TableBasedRouter.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2005 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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             // create route entry, post new route event
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     // the bundle daemon should have recorded a new entry in the
00147     // forwarding log for the given link to note that custody transfer
00148     // timed out, and of course the bundle should still be in the
00149     // pending list.
00150     //
00151     // therefore, trying again to forward the bundle should match
00152     // either the previous link or any other route
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     // if the link is open and not busy, send the bundle to it
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     // if the link is available and not open, open it
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     // otherwise, we can't do anything, so just log a bundle of
00196     // reasons why
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     // get_matching only returns results that match the this_link_only
00278     // link, if it's not null
00279     route_table_->get_matching(bundle->dest_, this_link_only, &matches);
00280 
00281     // sort the list by route priority, breaking ties with the total
00282     // bytes in flight
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 } // namespace dtn

Generated on Fri Dec 22 14:48:00 2006 for DTN Reference Implementation by  doxygen 1.5.1