00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include "BundleRouter.h"
00022 #include "RouteTable.h"
00023
00024 namespace dtn {
00025
00026
00027 RouteTable::RouteTable(const std::string& router_name)
00028 : Logger("RouteTable", "/dtn/routing/%s/table", router_name.c_str())
00029 {
00030 }
00031
00032
00033 RouteTable::~RouteTable()
00034 {
00035 }
00036
00037
00038 bool
00039 RouteTable::add_entry(RouteEntry* entry)
00040 {
00041 oasys::ScopeLock l(&lock_, "RouteTable::add_entry");
00042
00043 log_debug("add_route *%p", entry);
00044
00045 route_table_.push_back(entry);
00046
00047 return true;
00048 }
00049
00050
00051 bool
00052 RouteTable::del_entry(const EndpointIDPattern& dest, const LinkRef& next_hop)
00053 {
00054 oasys::ScopeLock l(&lock_, "RouteTable::del_entry");
00055
00056 RouteEntryVec::iterator iter;
00057 RouteEntry* entry;
00058
00059 for (iter = route_table_.begin(); iter != route_table_.end(); ++iter) {
00060 entry = *iter;
00061
00062 if (entry->dest_pattern().equals(dest) && entry->link() == next_hop) {
00063 log_debug("del_entry *%p", entry);
00064
00065 route_table_.erase(iter);
00066 delete entry;
00067 return true;
00068 }
00069 }
00070
00071 log_debug("del_entry %s -> %s: no match!",
00072 dest.c_str(), next_hop->nexthop());
00073 return false;
00074 }
00075
00076
00077 size_t
00078 RouteTable::del_entries(const EndpointIDPattern& dest)
00079 {
00080 oasys::ScopeLock l(&lock_, "RouteTable::del_entries");
00081 return del_matching_entries(RouteEntry::DestMatches(dest));
00082 }
00083
00084
00085 size_t
00086 RouteTable::del_entries_for_nexthop(const LinkRef& next_hop)
00087 {
00088 oasys::ScopeLock l(&lock_, "RouteTable::del_entries_for_nexthop");
00089 return del_matching_entries(RouteEntry::NextHopMatches(next_hop));
00090 }
00091
00092
00093 void
00094 RouteTable::clear()
00095 {
00096 oasys::ScopeLock l(&lock_, "RouteTable::clear");
00097
00098 RouteEntryVec::iterator iter;
00099 for (iter = route_table_.begin(); iter != route_table_.end(); ++iter) {
00100 delete *iter;
00101 }
00102 route_table_.clear();
00103 }
00104
00105
00106 size_t
00107 RouteTable::get_matching(const EndpointID& eid,
00108 const LinkRef& next_hop,
00109 RouteEntryVec* entry_vec) const
00110 {
00111 oasys::ScopeLock l(&lock_, "RouteTable::get_matching");
00112
00113 bool loop = false;
00114 log_debug("get_matching %s (link %s)...", eid.c_str(),
00115 next_hop != NULL ? next_hop->name() : "NULL");
00116 size_t ret = get_matching_helper(eid, next_hop, entry_vec, &loop, 0);
00117 if (loop) {
00118 log_warn("route destination %s caused route table lookup loop",
00119 eid.c_str());
00120 }
00121 return ret;
00122 }
00123
00124
00125 size_t
00126 RouteTable::get_matching_helper(const EndpointID& eid,
00127 const LinkRef& next_hop,
00128 RouteEntryVec* entry_vec,
00129 bool* loop,
00130 int level) const
00131 {
00132 RouteEntryVec::const_iterator iter;
00133 RouteEntry* entry;
00134 size_t count = 0;
00135
00136 for (iter = route_table_.begin(); iter != route_table_.end(); ++iter)
00137 {
00138 entry = *iter;
00139
00140 log_debug("check entry *%p", entry);
00141
00142 if (! entry->dest_pattern().match(eid)) {
00143 continue;
00144 }
00145
00146 if (entry->link() == NULL)
00147 {
00148 ASSERT(entry->route_to().length() != 0);
00149
00150 if (level >= BundleRouter::config_.max_route_to_chain_) {
00151 *loop = true;
00152 continue;
00153 }
00154
00155 count += get_matching_helper(entry->route_to(), next_hop,
00156 entry_vec, loop, level + 1);
00157 }
00158 else if (next_hop == NULL || entry->link() == next_hop)
00159 {
00160 if (std::find(entry_vec->begin(), entry_vec->end(), entry) == entry_vec->end()) {
00161 log_debug("match entry *%p", entry);
00162 entry_vec->push_back(entry);
00163 ++count;
00164 } else {
00165 log_debug("entry *%p already in matches... ignoring", entry);
00166 }
00167 }
00168 }
00169
00170 log_debug("get_matching %s done (level %d), %zu match(es)", eid.c_str(), level, count);
00171 return count;
00172 }
00173
00174
00175 void
00176 RouteTable::dump(oasys::StringBuffer* buf) const
00177 {
00178 oasys::ScopeLock l(&lock_, "RouteTable::dump");
00179
00180 oasys::StringVector long_strings;
00181
00182
00183 size_t dest_eid_width = 10;
00184 size_t source_eid_width = 6;
00185 size_t next_hop_width = 10;
00186
00187 RouteEntryVec::const_iterator iter;
00188 for (iter = route_table_.begin(); iter != route_table_.end(); ++iter) {
00189 RouteEntry* e = *iter;
00190 dest_eid_width = std::max(dest_eid_width,
00191 e->dest_pattern().length());
00192 source_eid_width = std::max(source_eid_width,
00193 e->source_pattern().length());
00194 next_hop_width = std::max(next_hop_width,
00195 (e->link() != NULL) ?
00196 e->link()->name_str().length() :
00197 e->route_to().length());
00198 }
00199
00200 dest_eid_width = std::min(dest_eid_width, (size_t)25);
00201 source_eid_width = std::min(source_eid_width, (size_t)15);
00202 next_hop_width = std::min(next_hop_width, (size_t)15);
00203
00204 RouteEntry::dump_header(buf, dest_eid_width, source_eid_width, next_hop_width);
00205
00206 for (iter = route_table_.begin(); iter != route_table_.end(); ++iter) {
00207 (*iter)->dump(buf, &long_strings,
00208 dest_eid_width, source_eid_width, next_hop_width);
00209 }
00210
00211 if (long_strings.size() > 0) {
00212 buf->appendf("\nLong EIDs/Links referenced above:\n");
00213 for (u_int i = 0; i < long_strings.size(); ++i) {
00214 buf->appendf("\t[%d]: %s\n", i, long_strings[i].c_str());
00215 }
00216 buf->appendf("\n");
00217 }
00218
00219 buf->append("\nClass of Service (COS) bits:\n"
00220 "\tB: Bulk N: Normal E: Expedited\n\n");
00221 }
00222
00223
00224 const RouteEntryVec *
00225 RouteTable::route_table()
00226 {
00227 ASSERTF(lock_.is_locked_by_me(),
00228 "RouteTable::route_table must be called while holding lock");
00229 return &route_table_;
00230 }
00231
00232 }