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 #include <oasys/util/OptParser.h>
00039
00040 #include "Link.h"
00041 #include "ContactManager.h"
00042 #include "AlwaysOnLink.h"
00043 #include "OndemandLink.h"
00044 #include "ScheduledLink.h"
00045 #include "OpportunisticLink.h"
00046
00047 #include "bundling/BundleDaemon.h"
00048 #include "bundling/BundleEvent.h"
00049 #include "conv_layers/ConvergenceLayer.h"
00050 #include "naming/EndpointIDOpt.h"
00051
00052 namespace dtn {
00053
00054
00056 Link::Params Link::default_params_ = {
00057 default_params_.mtu_ = 0,
00058 default_params_.min_retry_interval_ = 5,
00059 default_params_.max_retry_interval_ = 10 * 60,
00060 default_params_.idle_close_time_ = 0
00061 };
00062
00063
00064 Link*
00065 Link::create_link(const std::string& name, link_type_t type,
00066 ConvergenceLayer* cl, const char* nexthop,
00067 int argc, const char* argv[],
00068 const char** invalid_argp)
00069 {
00070 Link* link;
00071 switch(type) {
00072 case ALWAYSON: link = new AlwaysOnLink(name, cl, nexthop); break;
00073 case ONDEMAND: link = new OndemandLink(name, cl, nexthop); break;
00074 case SCHEDULED: link = new ScheduledLink(name, cl, nexthop); break;
00075 case OPPORTUNISTIC: link = new OpportunisticLink(name, cl, nexthop); break;
00076 default: PANIC("bogus link_type_t");
00077 }
00078
00079
00080
00081 int count = link->parse_args(argc, argv, invalid_argp);
00082 if (count == -1) {
00083 delete link;
00084 return NULL;
00085 }
00086
00087 argc -= count;
00088
00089
00090
00091 ASSERT(link->clayer_);
00092 if (!link->clayer_->init_link(link, argc, argv)) {
00093 delete link;
00094 return NULL;
00095 }
00096
00097 link->logf(oasys::LOG_INFO, "new link *%p", link);
00098
00099
00100
00101
00102
00103 link->set_initial_state();
00104
00105 return link;
00106 }
00107
00108
00109 Link::Link(const std::string& name, link_type_t type,
00110 ConvergenceLayer* cl, const char* nexthop)
00111 : Logger("Link", "/dtn/link/%s", name.c_str()),
00112 type_(type),
00113 state_(UNAVAILABLE),
00114 nexthop_(nexthop),
00115 name_(name),
00116 reliable_(false),
00117 contact_("Link"),
00118 clayer_(cl),
00119 cl_info_(NULL),
00120 remote_eid_(EndpointID::NULL_EID())
00121 {
00122 ASSERT(clayer_);
00123
00124 params_ = default_params_;
00125 retry_interval_ = 0;
00126
00127 memset(&stats_, 0, sizeof(Stats));
00128 }
00129
00130
00131 Link::Link(const oasys::Builder&)
00132 : Logger("Link", "/dtn/link/UNKNOWN!!!"),
00133 type_(LINK_INVALID),
00134 state_(UNAVAILABLE),
00135 nexthop_(""),
00136 name_(""),
00137 reliable_(false),
00138 contact_("Link"),
00139 clayer_(NULL),
00140 cl_info_(NULL),
00141 remote_eid_(EndpointID::NULL_EID())
00142 {
00143 }
00144
00145
00146 void
00147 Link::serialize(oasys::SerializeAction* a)
00148 {
00149 std::string cl_name;
00150 std::string type_str;
00151
00152 if (a->action_code() == oasys::Serialize::UNMARSHAL) {
00153 a->process("type", &type_str);
00154 type_ = str_to_link_type(type_str.c_str());
00155 ASSERT(type_ != LINK_INVALID);
00156 } else {
00157 type_str = link_type_to_str(type_);
00158 a->process("type", &type_str);
00159 }
00160
00161 a->process("nexthop", &nexthop_);
00162 a->process("name", &name_);
00163 a->process("reliable", &reliable_);
00164
00165 if (a->action_code() == oasys::Serialize::UNMARSHAL) {
00166 a->process("clayer", &cl_name);
00167 clayer_ = ConvergenceLayer::find_clayer(cl_name.c_str());
00168 ASSERT(clayer_);
00169 } else {
00170 cl_name = clayer_->name();
00171 a->process("clayer", &cl_name);
00172 }
00173
00174 a->process("remote_eid", &remote_eid_);
00175 a->process("min_retry_interval", ¶ms_.min_retry_interval_);
00176 a->process("max_retry_interval", ¶ms_.max_retry_interval_);
00177 a->process("idle_close_time", ¶ms_.idle_close_time_);
00178
00179 if (a->action_code() == oasys::Serialize::UNMARSHAL) {
00180 logpathf("/dtn/link/%s", name_.c_str());
00181 }
00182 }
00183
00184
00185 int
00186 Link::parse_args(int argc, const char* argv[], const char** invalidp)
00187 {
00188 oasys::OptParser p;
00189
00190 p.addopt(new dtn::EndpointIDOpt("remote_eid", &remote_eid_));
00191 p.addopt(new oasys::BoolOpt("reliable", &reliable_));
00192 p.addopt(new oasys::UIntOpt("mtu", ¶ms_.mtu_));
00193 p.addopt(new oasys::UIntOpt("min_retry_interval",
00194 ¶ms_.min_retry_interval_));
00195 p.addopt(new oasys::UIntOpt("max_retry_interval",
00196 ¶ms_.max_retry_interval_));
00197 p.addopt(new oasys::UIntOpt("idle_close_time",
00198 ¶ms_.idle_close_time_));
00199
00200 int ret = p.parse_and_shift(argc, argv, invalidp);
00201 if (ret == -1) {
00202 return -1;
00203 }
00204
00205 if (params_.min_retry_interval_ == 0 ||
00206 params_.max_retry_interval_ == 0)
00207 {
00208 *invalidp = "invalid retry interval";
00209 return -1;
00210 }
00211
00212 if (params_.idle_close_time_ != 0 && type_ == ALWAYSON)
00213 {
00214 *invalidp = "idle_close_time must be zero for always on link";
00215 return -1;
00216 }
00217
00218 return ret;
00219 }
00220
00221
00222 void
00223 Link::set_initial_state()
00224 {
00225 }
00226
00227
00228 Link::~Link()
00229 {
00230
00231
00232
00233
00234
00235
00236
00237
00238 ASSERT(!isopen());
00239 ASSERT(cl_info_ == NULL);
00240 }
00241
00242
00243 void
00244 Link::set_state(state_t new_state)
00245 {
00246 log_debug("set_state %s -> %s",
00247 state_to_str(state_), state_to_str(new_state));
00248
00249 #define ASSERT_STATE(condition) \
00250 if (!(condition)) { \
00251 log_err("set_state %s -> %s: expected %s", \
00252 state_to_str(state_), \
00253 state_to_str(new_state), \
00254 #condition); \
00255 }
00256
00257 switch(new_state) {
00258 case UNAVAILABLE:
00259 break;
00260
00261 case AVAILABLE:
00262 ASSERT_STATE(state_ == OPEN || state_ == UNAVAILABLE);
00263 break;
00264
00265 case OPENING:
00266 ASSERT_STATE(state_ == AVAILABLE || state_ == UNAVAILABLE);
00267 break;
00268
00269 case OPEN:
00270 ASSERT_STATE(state_ == OPENING || state_ == BUSY ||
00271 state_ == UNAVAILABLE );
00272 break;
00273
00274 case BUSY:
00275 ASSERT_STATE(state_ == OPEN);
00276 break;
00277
00278 default:
00279 NOTREACHED;
00280 }
00281 #undef ASSERT_STATE
00282
00283 state_ = new_state;
00284 }
00285
00286
00287 void
00288 Link::open()
00289 {
00290 log_debug("Link::open");
00291
00292 if (state_ != AVAILABLE) {
00293 log_crit("Link::open in state %s: expected state AVAILABLE",
00294 state_to_str(state_));
00295 return;
00296 }
00297
00298 set_state(OPENING);
00299
00300
00301
00302
00303 ASSERT(contact_ == NULL);
00304 contact_ = new Contact(this);
00305 clayer()->open_contact(contact_);
00306
00307 stats_.contact_attempts_++;
00308
00309 log_debug("*%p new contact %p", this, contact_.object());
00310 }
00311
00312
00313 void
00314 Link::close()
00315 {
00316 log_debug("Link::close");
00317
00318
00319 if (contact_ == NULL) {
00320 log_err("Link::close with no contact");
00321 return;
00322 }
00323
00324
00325
00326 clayer()->close_contact(contact_);
00327 ASSERT(contact_->cl_info() == NULL);
00328
00329
00330
00331 contact_ = NULL;
00332
00333 log_debug("Link::close complete");
00334 }
00335
00336
00337 int
00338 Link::format(char* buf, size_t sz) const
00339 {
00340 return snprintf(buf, sz, "%s [%s %s %s %s]",
00341 name(), nexthop(), remote_eid_.c_str(),
00342 link_type_to_str(type_), state_to_str(state_));
00343 }
00344
00345
00346 void
00347 Link::dump(oasys::StringBuffer* buf)
00348 {
00349 buf->appendf("Link %s:\n"
00350 "type: %s\n"
00351 "state: %s\n"
00352 "nexthop: %s\n"
00353 "remote eid: %s\n"
00354 "mtu: %u\n"
00355 "min_retry_interval: %u\n"
00356 "max_retry_interval: %u\n",
00357 name(),
00358 link_type_to_str(type_),
00359 state_to_str(state_),
00360 nexthop(),
00361 remote_eid_.c_str(),
00362 params_.mtu_,
00363 params_.min_retry_interval_,
00364 params_.max_retry_interval_);
00365
00366 clayer_->dump_link(this, buf);
00367 }
00368
00369
00370 void
00371 Link::dump_stats(oasys::StringBuffer* buf)
00372 {
00373 buf->appendf("%u contact_attempts -- "
00374 "%u contacts -- "
00375 "%u bundles_transmitted -- "
00376 "%u bytes_transmitted -- "
00377 "%u bundles_inflight -- "
00378 "%u bytes_inflight ",
00379 stats_.contact_attempts_,
00380 stats_.contacts_,
00381 stats_.bundles_transmitted_,
00382 stats_.bytes_transmitted_,
00383 stats_.bundles_inflight_,
00384 stats_.bytes_inflight_);
00385 }
00386
00387 }