IBR-DTN  1.0.0
FloodRoutingExtension.cpp
Go to the documentation of this file.
1 /*
2  * FloodRoutingExtension.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
24 #include "core/NodeEvent.h"
27 #include "net/ConnectionEvent.h"
28 #include "core/Node.h"
29 #include "net/ConnectionManager.h"
30 #include "Configuration.h"
31 #include "core/BundleCore.h"
32 
33 #include <ibrdtn/data/MetaBundle.h>
34 #include <ibrcommon/thread/MutexLock.h>
35 #include <ibrcommon/Logger.h>
36 
37 #include <functional>
38 #include <list>
39 #include <algorithm>
40 #include <iomanip>
41 #include <ios>
42 #include <iostream>
43 #include <memory>
44 
45 #include <stdlib.h>
46 #include <typeinfo>
47 
48 namespace dtn
49 {
50  namespace routing
51  {
52  const std::string FloodRoutingExtension::TAG = "FloodRoutingExtension";
53 
55  {
56  // write something to the syslog
57  IBRCOMMON_LOGGER_TAG(FloodRoutingExtension::TAG, info) << "Initializing flooding routing module" << IBRCOMMON_LOGGER_ENDL;
58  }
59 
61  {
62  join();
63  }
64 
66  {
67  // transfer the next bundle to this destination
68  _taskqueue.push( new SearchNextBundleTask( peer ) );
69  }
70 
72  {
73  // new bundles trigger a recheck for all neighbors
74  const std::set<dtn::core::Node> nl = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
75 
76  for (std::set<dtn::core::Node>::const_iterator iter = nl.begin(); iter != nl.end(); ++iter)
77  {
78  const dtn::core::Node &n = (*iter);
79 
80  if (n.getEID() != peer)
81  {
82  // trigger all routing modules to search for bundles to forward
83  eventDataChanged(n.getEID());
84  }
85  }
86  }
87 
89  {
90  // reset the task queue
91  _taskqueue.reset();
92 
93  // routine checked for throw() on 15.02.2013
94  try {
95  // run the thread
96  start();
97  } catch (const ibrcommon::ThreadException &ex) {
98  IBRCOMMON_LOGGER_TAG(FloodRoutingExtension::TAG, error) << "componentUp failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
99  }
100  }
101 
103  {
104  try {
105  // stop the thread
106  stop();
107  join();
108  } catch (const ibrcommon::ThreadException &ex) {
109  IBRCOMMON_LOGGER_TAG(FloodRoutingExtension::TAG, error) << "componentDown failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
110  }
111  }
112 
113  const std::string FloodRoutingExtension::getTag() const throw ()
114  {
115  return "flooding";
116  }
117 
119  {
120  _taskqueue.abort();
121  }
122 
124  {
126  {
127  public:
128  BundleFilter(const NeighborDatabase::NeighborEntry &entry, const std::set<dtn::core::Node> &neighbors, const dtn::core::FilterContext &context, const dtn::net::ConnectionManager::protocol_list &plist)
129  : _entry(entry), _neighbors(neighbors), _plist(plist), _context(context)
130  {};
131 
132  virtual ~BundleFilter() {};
133 
134  virtual dtn::data::Size limit() const throw () { return _entry.getFreeTransferSlots(); };
135 
136  virtual bool addIfSelected(dtn::storage::BundleResult &result, const dtn::data::MetaBundle &meta) const throw (dtn::storage::BundleSelectorException)
137  {
138  // check Scope Control Block - do not forward bundles with hop limit == 0
139  if (meta.hopcount == 0)
140  {
141  return false;
142  }
143 
144  // do not forward local bundles
147  )
148  {
149  return false;
150  }
151 
152  // check Scope Control Block - do not forward non-group bundles with hop limit <= 1
154  {
155  return false;
156  }
157 
158  // do not forward bundles addressed to this neighbor,
159  // because this is handled by neighbor routing extension
160  if (_entry.eid == meta.destination.getNode())
161  {
162  return false;
163  }
164 
165  // if this is a singleton bundle ...
167  {
168  const dtn::core::Node n(meta.destination.getNode());
169 
170  // do not forward the bundle if the final destination is available
171  if (_neighbors.find(n) != _neighbors.end())
172  {
173  return false;
174  }
175  }
176 
177  // do not forward bundles already known by the destination
178  if (_entry.has(meta))
179  {
180  return false;
181  }
182 
183  // update filter context
184  dtn::core::FilterContext context = _context;
185  context.setMetaBundle(meta);
186 
187  // check bundle filter for each possible path
188  for (dtn::net::ConnectionManager::protocol_list::const_iterator it = _plist.begin(); it != _plist.end(); ++it)
189  {
190  const dtn::core::Node::Protocol &p = (*it);
191 
192  // update context with current protocol
193  context.setProtocol(p);
194 
195  // execute filtering
197 
199  {
200  // put the selected bundle with targeted interface into the result-set
201  static_cast<RoutingResult&>(result).put(meta, p);
202  return true;
203  }
204  }
205 
206  return false;
207  };
208 
209  private:
210  const NeighborDatabase::NeighborEntry &_entry;
211  const std::set<dtn::core::Node> &_neighbors;
213  const dtn::core::FilterContext &_context;
214  };
215 
216  // list for bundles
217  RoutingResult list;
218 
219  // set of known neighbors
220  std::set<dtn::core::Node> neighbors;
221 
222  while (true)
223  {
224  try {
225  Task *t = _taskqueue.poll();
226  std::auto_ptr<Task> killer(t);
227 
228  IBRCOMMON_LOGGER_DEBUG_TAG(FloodRoutingExtension::TAG, 50) << "processing task " << t->toString() << IBRCOMMON_LOGGER_ENDL;
229 
230  try {
231  try {
232  SearchNextBundleTask &task = dynamic_cast<SearchNextBundleTask&>(*t);
233 
234  // clear the result list
235  list.clear();
236 
237  // lock the neighbor database while searching for bundles
238  {
239  NeighborDatabase &db = (**this).getNeighborDB();
240 
241  ibrcommon::MutexLock l(db);
242  NeighborDatabase::NeighborEntry &entry = db.get(task.eid, true);
243 
244  // check if enough transfer slots available (threshold reached)
245  if (!entry.isTransferThresholdReached())
247 
249  // get current neighbor list
251  } else {
252  // "prefer direct" option disabled - clear the list of neighbors
253  neighbors.clear();
254  }
255 
256  // get a list of protocols supported by both, the local BPA and the remote peer
259 
260  // create a filter context
261  dtn::core::FilterContext context;
262  context.setPeer(entry.eid);
263  context.setRouting(*this);
264 
265  // get the bundle filter of the neighbor
266  BundleFilter filter(entry, neighbors, context, plist);
267 
268  // some debug
269  IBRCOMMON_LOGGER_DEBUG_TAG(FloodRoutingExtension::TAG, 40) << "search some bundles not known by " << task.eid.getString() << IBRCOMMON_LOGGER_ENDL;
270 
271  // query all bundles from the storage
272  (**this).getSeeker().get(filter, list);
273  }
274 
275  // send the bundles as long as we have resources
276  for (RoutingResult::const_iterator iter = list.begin(); iter != list.end(); ++iter)
277  {
278  try {
279  // transfer the bundle to the neighbor
280  transferTo(task.eid, (*iter).first, (*iter).second);
281  } catch (const NeighborDatabase::AlreadyInTransitException&) { };
282  }
283  } catch (const NeighborDatabase::NoMoreTransfersAvailable &ex) {
284  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
285  } catch (const NeighborDatabase::EntryNotFoundException &ex) {
286  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
287  } catch (const NodeNotAvailableException &ex) {
288  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
289  } catch (const dtn::storage::NoBundleFoundException &ex) {
290  IBRCOMMON_LOGGER_DEBUG_TAG(TAG, 10) << "task " << t->toString() << " aborted: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
291  } catch (const std::bad_cast&) { };
292  } catch (const ibrcommon::Exception &ex) {
293  IBRCOMMON_LOGGER_DEBUG_TAG(FloodRoutingExtension::TAG, 20) << "task failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
294  }
295  } catch (const std::exception &ex) {
296  IBRCOMMON_LOGGER_DEBUG_TAG(FloodRoutingExtension::TAG, 15) << "terminated due to " << ex.what() << IBRCOMMON_LOGGER_ENDL;
297  return;
298  }
299 
300  yield();
301  }
302  }
303 
304  /****************************************/
305 
306  FloodRoutingExtension::SearchNextBundleTask::SearchNextBundleTask(const dtn::data::EID &e)
307  : eid(e)
308  { }
309 
310  FloodRoutingExtension::SearchNextBundleTask::~SearchNextBundleTask()
311  { }
312 
313  std::string FloodRoutingExtension::SearchNextBundleTask::toString()
314  {
315  return "SearchNextBundleTask: " + eid.getString();
316  }
317  }
318 }
static Configuration & getInstance(bool reset=false)
const std::set< dtn::core::Node > getNeighbors()
static dtn::data::EID local
Definition: BundleCore.h:79
bool get(dtn::data::PrimaryBlock::FLAGS flag) const
Definition: MetaBundle.cpp:160
std::list< dtn::core::Node::Protocol > protocol_list
virtual void eventDataChanged(const dtn::data::EID &peer)
NeighborDatabase::NeighborEntry & get(const dtn::data::EID &eid, bool noCached=false)
dtn::net::ConnectionManager & getConnectionManager()
Definition: BundleCore.cpp:260
BundleFilter::ACTION evaluate(BundleFilter::TABLE table, const FilterContext &context) const
Definition: BundleCore.cpp:617
void setProtocol(const dtn::core::Node::Protocol &protocol)
const Configuration::Network & getNetwork() const
void setPeer(const dtn::data::EID &endpoint)
void transferTo(const dtn::data::EID &destination, const dtn::data::MetaBundle &meta, const dtn::core::Node::Protocol)
void setMetaBundle(const dtn::data::MetaBundle &data)
EID getNode() const
Definition: EID.cpp:528
const protocol_set getSupportedProtocols()
dtn::data::EID destination
Definition: MetaBundle.h:60
size_t Size
Definition: Number.h:34
virtual const std::string getTag() const
const dtn::data::EID & getEID() const
Definition: Node.cpp:406
void setRouting(const dtn::routing::RoutingExtension &routing)
static BundleCore & getInstance()
Definition: BundleCore.cpp:82
virtual void eventBundleQueued(const dtn::data::EID &peer, const dtn::data::MetaBundle &meta)