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 "BundleRouter.h"
00040 #include "RouteTable.h"
00041 #include "bundling/Bundle.h"
00042 #include "bundling/BundleActions.h"
00043 #include "bundling/BundleDaemon.h"
00044 #include "bundling/BundleList.h"
00045 #include "contacts/Contact.h"
00046 #include "contacts/ContactManager.h"
00047
00048 #include "reg/Registration.h"
00049 #include "reg/RegistrationTable.h"
00050 #include <stdlib.h>
00051
00052 #include "LinkStateRouter.h"
00053 #include "LinkStateGraph.h"
00054
00055 namespace dtn {
00056
00057 #define ROUTER_BCAST_EID "str://linkstate.router"
00058
00059 LinkStateRouter::LinkStateRouter()
00060 : BundleRouter("LinkStateRouter", "linkstate")
00061 {
00062 }
00063
00064 void
00065 LinkStateRouter::initialize()
00066 {
00067 reg_=new LSRegistration(this);
00068 BundleDaemon::instance()->post(new RegistrationAddedEvent(reg_, EVENTSRC_ADMIN));
00069 }
00070
00071 void
00072 LinkStateRouter::handle_contact_up(ContactUpEvent* event)
00073 {
00074 BundleRouter::handle_contact_up(event);
00075 LinkStateGraph::Vertex *peer, *local;
00076
00077 log_info("Contact Up. Adding edges %s <-> %s",
00078 BundleDaemon::instance()->local_eid().c_str(),
00079 event->contact_->link()->nexthop());
00080
00081
00082
00083 local=graph_.getVertex(BundleDaemon::instance()->local_eid().c_str());
00084 peer=graph_.getVertex(event->contact_->link()->nexthop());
00085
00086
00087
00088
00089
00090
00091 LinkStateGraph::Edge *e=graph_.addEdge(local, peer, 1);
00092 if(e) flood_announcement(e, true);
00093
00094
00095
00096
00097 e=graph_.getEdge(local,peer);
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 std::set<LinkStateGraph::Edge*> edges=graph_.edges();
00109 for(std::set<LinkStateGraph::Edge*>::iterator i=edges.begin(); i!=edges.end(); i++)
00110 send_announcement((*i), event->contact_->link(), 1);
00111 }
00112
00113 void
00114 LinkStateRouter::handle_contact_down(ContactDownEvent* event)
00115 {
00116
00117
00118
00119
00120 LinkStateGraph::Vertex *peer, *local;
00121
00122 log_info("Contact Down. Removing edges %s <-> %s",
00123 BundleDaemon::instance()->local_eid().c_str(),
00124 event->contact_->link()->nexthop());
00125
00126 peer=graph_.getVertex(event->contact_->link()->nexthop());
00127 local=graph_.getVertex(BundleDaemon::instance()->local_eid().c_str());
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 LinkStateGraph::Edge *e=local->outgoing_edges_[peer];
00155 if(e) {
00156 graph_.removeEdge(e);
00157 flood_announcement(e,false);
00158 }
00159 e=local->incoming_edges_[peer];
00160 if(e) {
00161 graph_.removeEdge(e);
00162 flood_announcement(e,false);
00163 }
00164
00165 BundleRouter::handle_contact_down(event);
00166 }
00167
00168 void
00169 LinkStateRouter::handle_bundle_received(BundleReceivedEvent* event)
00170 {
00171 Bundle* bundle=event->bundleref_.object();
00172
00173
00174 if(bundle->owner_ != "") {
00175 log_debug("Skipping bundle ID %u owned by %s.\n",bundle->bundleid_,bundle->owner_.c_str());
00176 return;
00177 }
00178
00179 ContactManager* cm = BundleDaemon::instance()->contactmgr();
00180
00181
00182
00183
00184
00185
00186
00187 const char* local_eid = BundleDaemon::instance()->local_eid().c_str();
00188 LinkStateGraph::Vertex* nextHop=
00189 graph_.findNextHop(graph_.getVertex(local_eid),
00190
00191 graph_.getMatchingVertex(bundle->dest_.c_str()));
00192
00193 if(!nextHop) {
00194 log_debug("No LSRoute to destination %s",bundle->dest_.c_str());
00195 return;
00196 }
00197
00198 log_debug("Next hop from %s to %s is %s.",
00199 local_eid,
00200 bundle->dest_.c_str(),
00201 nextHop->eid_);
00202
00203
00204 EndpointID eid(nextHop->eid_);
00205 ASSERT(eid.valid());
00206
00207 Link* link=cm->find_link_to(NULL, "", eid);
00208
00209 ASSERT(link!=0);
00210
00211
00212
00213 actions_->send_bundle(bundle, link, ForwardingInfo::FORWARD_ACTION,
00214 CustodyTimerSpec::defaults_);
00215 }
00216
00217 void
00218 LinkStateRouter::get_routing_state(oasys::StringBuffer* buf)
00219 {
00220
00221 graph_.dumpGraph(buf);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230 void
00231 LinkStateRouter::flood_announcement(LinkStateGraph::Edge* edge, bool exists)
00232 {
00233 ContactManager* cm = BundleDaemon::instance()->contactmgr();
00234 oasys::ScopeLock l(cm->lock(), "flood_announcement");
00235
00236 const LinkSet* links=cm->links();
00237 for(LinkSet::const_iterator i=links->begin(); i!=links->end(); i++)
00238 send_announcement(edge, (*i), exists);
00239 }
00240
00241 void
00242 LinkStateRouter::send_announcement(LinkStateGraph::Edge* edge,
00243 Link* outgoing_link, bool exists)
00244 {
00245 LinkStateAnnouncement lsa;
00246 memset(&lsa,0,sizeof(lsa));
00247
00248
00249
00250
00251 sprintf(lsa.from,"%s",(edge->from_)->eid_);
00252 sprintf(lsa.to,"%s",(edge->to_)->eid_);
00253 if(exists)
00254 lsa.cost=edge->cost_;
00255 else
00256 lsa.cost=LinkStateAnnouncement::LINK_DOWN;
00257
00258 lsa.type=LS_ANNOUNCEMENT;
00259
00260
00261 Bundle *b=new Bundle();
00262 b->source_.assign(BundleDaemon::instance()->local_eid());
00263 b->replyto_.assign(EndpointID::NULL_EID());
00264 b->custodian_.assign(EndpointID::NULL_EID());
00265 b->dest_.assign(ROUTER_BCAST_EID);
00266 b->payload_.set_data((const u_char*)&lsa,sizeof(lsa));
00267
00268
00269 actions_->inject_bundle(b);
00270 actions_->send_bundle(b, outgoing_link, ForwardingInfo::FORWARD_ACTION,
00271 CustodyTimerSpec::defaults_);
00272 }
00273
00274 LinkStateRouter::LSRegistration::LSRegistration(LinkStateRouter* router)
00275 : Registration(Registration::LINKSTATEROUTER_REGID,
00276 EndpointID(ROUTER_BCAST_EID),
00277 Registration::DEFER, 0)
00278 {
00279 logpathf("/reg/admin");
00280
00281 router_=router;
00282
00283 BundleDaemon::post(new RegistrationAddedEvent(this, EVENTSRC_ADMIN));
00284 }
00285
00286 void
00287 LinkStateRouter::LSRegistration::deliver_bundle(Bundle* bundle)
00288 {
00289 u_char typecode;
00290
00291 log_info("LSRegistration Consuming bundle");
00292
00293 size_t payload_len = bundle->payload_.length();
00294 const u_char* data = 0;
00295
00296 oasys::StringBuffer payload_buf(payload_len);
00297
00298 if (payload_len == 0) {
00299 log_err("linkstate registration got 0 byte bundle *%p", bundle);
00300 goto done;
00301 }
00302
00303 data = bundle->payload_.read_data(0, payload_len, (u_char*)payload_buf.data());
00304
00305
00306 typecode=*data;
00307
00308 switch(typecode) {
00309 case LS_ANNOUNCEMENT:
00310 {
00311 LinkStateAnnouncement *lsa=(LinkStateAnnouncement*)data;
00312
00313 LinkStateGraph *graph=router_->graph();
00314 LinkStateGraph::Edge *edge;
00315
00316 if(lsa->cost==LinkStateAnnouncement::LINK_DOWN) {
00317 LinkStateGraph::Vertex *from=graph->getVertex(lsa->from);
00318 if(!from) {
00319 log_debug("No such vertex %s.",lsa->from);
00320 return;
00321 }
00322
00323 LinkStateGraph::Vertex *to=graph->getVertex(lsa->to);
00324 if(!(edge=from->outgoing_edges_[to]))
00325 {
00326 log_debug("No such edge %s -> %s.",lsa->from,lsa->to);
00327 return;
00328 }
00329 graph->removeEdge(edge);
00330 }
00331
00332
00333 if((edge=graph->addEdge(graph->getVertex(lsa->from), graph->getVertex(lsa->to), lsa->cost)))
00334 {
00335 router_->flood_announcement(edge, true);
00336 }
00337
00338 break;
00339 }
00340 default:
00341 log_warn("unexpected admin bundle with type 0x%x *%p",
00342 typecode, bundle);
00343 }
00344
00345 done:
00346 BundleDaemon::post(new BundleDeliveredEvent(bundle, this));
00347 }
00348
00349 }