/** * "Check whether the Bundle should be forwarded to the give route or not" [DTN2] * * @param bundle the Bundle to check * @param route the route to check */ protected boolean should_fwd(final Bundle bundle, RouteEntry route) { if (route == null) return false; EndpointID prevhop = reception_cache_.lookup(bundle); if (prevhop != null) { if (prevhop.equals(route.link().remote_eid()) && !prevhop.equals(EndpointID.NULL_EID())) { Log.d( TAG, String.format( "should_fwd bundle %d: " + "skip %s since bundle arrived from the same node", bundle.bundleid(), route.link().name())); return false; } } return super.should_fwd(bundle, route.link(), route.action()); }
/** * "Check the route table entries that match the given bundle and have not already been found in * the bundle history. If a match is found, call fwd_to_nexthop on it." [DTN2] * * @param bundle the bundle to forward * @return "the number of links on which the bundle was queued (i.e. the number of matching route * entries.)" [DTN2] */ protected int route_bundle(Bundle bundle) { RouteEntryVec matches = new RouteEntryVec(); Log.d(TAG, String.format("route_bundle: checking bundle %d", bundle.bundleid())); // "check to see if forwarding is suppressed to all nodes" [DTN2] if (bundle .fwdlog() .get_count( EndpointIDPattern.WILDCARD_EID(), ForwardingInfo.state_t.SUPPRESSED.getCode(), ForwardingInfo.ANY_ACTION) > 0) { Log.i( TAG, String.format( "route_bundle: " + "ignoring bundle %d since forwarding is suppressed", bundle.bundleid())); return 0; } Link null_link = null; route_table_.get_matching(bundle.dest(), null_link, matches); // "sort the matching routes by priority, allowing subclasses to // override the way in which the sorting occurs" [DTN2] sort_routes(matches); Log.d( TAG, String.format( "route_bundle bundle id %d: checking %d route entry matches", bundle.bundleid(), matches.size())); int count = 0; Iterator<RouteEntry> itr = matches.iterator(); while (itr.hasNext()) { RouteEntry route = itr.next(); Log.d( TAG, String.format( "checking route entry %s link %s (%s)", route.toString(), route.link().name(), route.link())); if (!should_fwd(bundle, route)) { continue; } if (deferred_list(route.link()).list().contains(bundle)) { Log.d( TAG, String.format( "route_bundle bundle %d: " + "ignoring link %s since already deferred", bundle.bundleid(), route.link().name())); continue; } // "because there may be bundles that already have deferred // transmission on the link, we first call check_next_hop to // get them into the queue before trying to route the new // arrival, otherwise it might leapfrog the other deferred // bundles" [DTN2] check_next_hop(route.link()); if (!fwd_to_nexthop(bundle, route)) { continue; } ++count; } Log.d( TAG, String.format( "route_bundle bundle id %d: forwarded on %d links", bundle.bundleid(), count)); return count; }
/** "Try to forward a bundle to a next hop route." [DTN2] */ protected boolean fwd_to_nexthop(Bundle bundle, RouteEntry route) { Link link = route.link(); // "if the link is available and not open, open it" [DTN2] if (link.isNotUnavailable() && (!link.isopen()) && (!link.isopening())) { Log.d(TAG, String.format("opening %s because a message is intended for it", link.name())); actions_.open_link(link); } // "if the link is open and has space in the queue, then queue the // bundle for transmission there" [DTN2] if (link.isopen() && !link.queue_is_full()) { Log.d(TAG, String.format("queuing %d on %s", bundle.bundleid(), link.name())); actions_.queue_bundle(bundle, link, route.action(), route.custody_spec()); return true; } // "otherwise we can't send the bundle now, so put it on the link's // deferred list and log reason why we can't forward it" [DTN2] DeferredList deferred = deferred_list(link); if (!bundle.is_queued_on(deferred.list())) { ForwardingInfo info = new ForwardingInfo( ForwardingInfo.state_t.NONE, route.action(), link.name_str(), 0xffffffff, link.remote_eid(), route.custody_spec()); deferred.add(bundle, info); } else { Log.w( TAG, String.format( "bundle %d already exists on deferred list of link %s", bundle.bundleid(), link.name())); } if (!link.isNotUnavailable()) { Log.d( TAG, String.format( "can't forward bundle %d to %s because link not available", bundle.bundleid(), link.name())); } else if (!link.isopen()) { Log.d( TAG, String.format( TAG, "can't forward bundle %d to %s because link not open", bundle.bundleid(), link.name())); } else if (link.queue_is_full()) { Log.d( TAG, String.format( TAG, "can't forward bundle %d to %s because link queue is full", bundle.bundleid(), link.name())); } else { Log.d(TAG, String.format(TAG, "can't forward %d to %s", bundle.bundleid(), link.name())); } return false; }