--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/cmd/RouteCommand.cc Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2004-2006 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <dtn-config.h>
+#endif
+
+#include <oasys/util/StringBuffer.h>
+#include <oasys/serialize/XMLSerialize.h>
+
+#include "RouteCommand.h"
+#include "CompletionNotifier.h"
+
+#include "contacts/Link.h"
+#include "contacts/ContactManager.h"
+
+#include "bundling/BundleEvent.h"
+#include "bundling/BundleDaemon.h"
+
+#include "routing/BundleRouter.h"
+#include "routing/RouteEntry.h"
+#include "routing/ExternalRouter.h"
+#include "routing/DTLSRConfig.h"
+
+namespace dtn {
+
+RouteCommand::RouteCommand()
+ : TclCommand("route")
+{
+ bind_var(new oasys::StringOpt("type", &BundleRouter::config_.type_,
+ "type", "Which routing algorithm to use "
+ "(default static).\n"
+ " valid options:\n"
+ " static\n"
+ " prophet\n"
+ " flood\n"
+ " dtlsr\n"
+ " tca_router\n"
+ " tca_gateway\n"
+ " external"));
+
+ bind_var(new oasys::BoolOpt("add_nexthop_routes",
+ &BundleRouter::config_.add_nexthop_routes_,
+ "Whether or not to automatically add routes "
+ "for next hop links (default is true)\n"
+ " valid options: true or false\n"));
+
+ add_to_help("add <dest> <link/endpoint> [opts]", "add a route");
+
+ add_to_help("del <dest> <link/endpoint>", "delete a route");
+
+ add_to_help("dump", "dump all of the static routes");
+
+ bind_var(new oasys::BoolOpt("open_discovered_links",
+ &BundleRouter::config_.open_discovered_links_,
+ "Whether or not to automatically open "
+ "discovered opportunistic links (default is true)\n"
+ " valid options: true or false\n"));
+
+ bind_var(new oasys::IntOpt("default_priority",
+ &BundleRouter::config_.default_priority_,
+ "priority",
+ "Default priority for new routes "
+ "(default 0)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::IntOpt("max_route_to_chain",
+ &BundleRouter::config_.max_route_to_chain_,
+ "length",
+ "Maximum number of route_to links to follow "
+ "(default 10)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::UIntOpt("subscription_timeout",
+ &BundleRouter::config_.subscription_timeout_,
+ "timeout",
+ "Default timeout for upstream subscription "
+ "(default 600)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::StringOpt("dtlsr_area",
+ &DTLSRConfig::instance()->area_,
+ "area", "Administrative area for the local node "
+ "(default "")\n"
+ " valid options: string\n"));
+
+
+ bind_var(new oasys::EnumOpt("dtlsr_weight_fn",
+ DTLSRConfig::instance()->weight_opts_,
+ (int*)&DTLSRConfig::instance()->weight_fn_,
+ "fn", "Weight function for the graph "
+ "(default 10.0)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::UIntOpt("dtlsr_weight_shift",
+ &DTLSRConfig::instance()->weight_shift_,
+ "shift", "Scale the weight on down links"
+ "Factor by which to age the cost of a link "
+ "based on its uptime, "
+ "as a link's uptime goes to zero, the cost "
+ "increases by 10x the original cost "
+ "(default 0)\n"
+ " valid options: number\n"));
+
+
+ bind_var(new oasys::DoubleOpt("dtlsr_uptime_factor",
+ &DTLSRConfig::instance()->uptime_factor_,
+ "pct", "Aging pct for cost of down links"
+ "(default 10.0)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::BoolOpt("dtlsr_keep_down_links",
+ &DTLSRConfig::instance()->keep_down_links_,
+ "Whether or not to retain down links in the graph "
+ "(default is true)\n"
+ " valid options: true or false\n"));
+
+ bind_var(new oasys::UIntOpt("dtlsr_recompute_delay",
+ &DTLSRConfig::instance()->recompute_delay_,
+ "seconds",
+ "Delay to compute routes after LSA arrives "
+ "(default 1)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::UIntOpt("dtlsr_aging_interval",
+ &DTLSRConfig::instance()->aging_interval_,
+ "seconds",
+ "Interval to locally recompute routes "
+ "(default 5)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::UIntOpt("dtlsr_lsa_interval",
+ &DTLSRConfig::instance()->lsa_interval_,
+ "seconds",
+ "Interval to periodically send LSAs "
+ "(default 3600)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::UIntOpt("dtlsr_min_lsa_interval",
+ &DTLSRConfig::instance()->min_lsa_interval_,
+ "seconds",
+ "Minimum interval to periodically send LSAs "
+ "(default 5)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::UIntOpt("dtlsr_lsa_lifetime",
+ &DTLSRConfig::instance()->lsa_lifetime_,
+ "seconds",
+ "Lifetime of LSA bundles "
+ "(default 86400)\n"
+ " valid options: number\n"));
+
+#if defined(XERCES_C_ENABLED) && defined(EXTERNAL_DP_ENABLED)
+ bind_var(new oasys::UInt16Opt("server_port",
+ &ExternalRouter::server_port,
+ "port",
+ "UDP port for IPC with external router(s) "
+ "(default 8001)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::UInt16Opt("hello_interval",
+ &ExternalRouter::hello_interval,
+ "interval",
+ "Seconds between hello messages with external router(s)"
+ "(default 30)\n"
+ " valid options: number\n"));
+
+ bind_var(new oasys::StringOpt("schema", &ExternalRouter::schema,
+ "file",
+ "The external router interface "
+ "message schema "
+ "(default /router.xsd)\n"
+ " valid options: string\n"));
+
+ bind_var(new oasys::BoolOpt("xml_server_validation",
+ &ExternalRouter::server_validation,
+ "Perform xml validation on plug-in "
+ "interface messages (default is true)\n"
+ " valid options: true or false\n"));
+
+ bind_var(new oasys::BoolOpt("xml_client_validation",
+ &ExternalRouter::client_validation,
+ "Include meta-info in xml messages "
+ "so plug-in routers"
+ "can perform validation (default is false)\n"
+ " valid options: true or false\n"));
+#endif
+}
+
+int
+RouteCommand::exec(int argc, const char** argv, Tcl_Interp* interp)
+{
+ (void)interp;
+
+ if (argc < 2) {
+ resultf("need a route subcommand");
+ return TCL_ERROR;
+ }
+
+ const char* cmd = argv[1];
+
+ if (strcmp(cmd, "add") == 0) {
+ // route add <dest> <link/endpoint> <args>
+ if (argc < 4) {
+ wrong_num_args(argc, argv, 2, 4, INT_MAX);
+ return TCL_ERROR;
+ }
+
+ const char* dest_str = argv[2];
+
+ EndpointIDPattern dest(dest_str);
+ if (!dest.valid()) {
+ resultf("invalid destination eid %s", dest_str);
+ return TCL_ERROR;
+ }
+
+ const char* next_hop = argv[3];
+
+ RouteEntry* entry;
+ LinkRef link;
+ EndpointIDPattern route_to;
+
+ link = BundleDaemon::instance()->contactmgr()->find_link(next_hop);
+ if (link != NULL) {
+ entry = new RouteEntry(dest, link);
+ } else if (route_to.assign(next_hop)) {
+ entry = new RouteEntry(dest, route_to);
+ } else {
+ resultf("next hop %s is not a valid link or endpoint id",
+ next_hop);
+ return TCL_ERROR;
+ }
+
+ // skip over the consumed arguments and parse optional ones.
+ // any invalid options are shifted into argv[0]
+ argc -= 4;
+ argv += 4;
+ if (argc != 0 && (entry->parse_options(argc, argv) != argc))
+ {
+ resultf("invalid argument '%s'", argv[0]);
+ return TCL_ERROR;
+ }
+
+ // post the event -- if the daemon has been started, we wait
+ // for the event to be consumed, otherwise we just return
+ // immediately. this allows the command to have the
+ // appropriate semantics both in the static config file and in
+ // an interactive mode
+
+ if (BundleDaemon::instance()->started()) {
+ BundleDaemon::post_and_wait(new RouteAddEvent(entry),
+ CompletionNotifier::notifier());
+ } else {
+ BundleDaemon::post(new RouteAddEvent(entry));
+ }
+
+ return TCL_OK;
+ }
+
+ else if (strcmp(cmd, "del") == 0) {
+ // route del <dest>
+ if (argc != 3) {
+ wrong_num_args(argc, argv, 2, 3, 3);
+ return TCL_ERROR;
+ }
+
+ EndpointIDPattern pat(argv[2]);
+ if (!pat.valid()) {
+ resultf("invalid endpoint id pattern '%s'", argv[2]);
+ return TCL_ERROR;
+ }
+
+ if (BundleDaemon::instance()->started()) {
+ BundleDaemon::post_and_wait(new RouteDelEvent(pat),
+ CompletionNotifier::notifier());
+ } else {
+ BundleDaemon::post(new RouteDelEvent(pat));
+ }
+
+ return TCL_OK;
+ }
+
+ else if (strcmp(cmd, "dump") == 0) {
+ oasys::StringBuffer buf;
+ BundleDaemon::instance()->get_routing_state(&buf);
+ set_result(buf.c_str());
+ return TCL_OK;
+ }
+
+ else if (strcmp(cmd, "dump_tcl") == 0) {
+ // XXX/demmer this could be done better
+ oasys::StringBuffer buf;
+ BundleDaemon::instance()->router()->tcl_dump_state(&buf);
+ set_result(buf.c_str());
+ return TCL_OK;
+ }
+
+ else if (strcmp(cmd, "recompute_routes") == 0) {
+ oasys::Time t = oasys::Time::now();
+ BundleDaemon::instance()->router()->recompute_routes();
+ resultf("%u", t.elapsed_ms());
+ return TCL_OK;
+ }
+
+ else if (strcmp(cmd, "local_eid") == 0) {
+ if (argc == 2) {
+ // route local_eid
+ set_result(BundleDaemon::instance()->local_eid().c_str());
+ return TCL_OK;
+
+ } else if (argc == 3) {
+ // route local_eid <eid?>
+ BundleDaemon::instance()->set_local_eid(argv[2]);
+ if (! BundleDaemon::instance()->local_eid().valid()) {
+ resultf("invalid eid '%s'", argv[2]);
+ return TCL_ERROR;
+ }
+ if (! BundleDaemon::instance()->local_eid().known_scheme()) {
+ resultf("local eid '%s' has unknown scheme", argv[2]);
+ return TCL_ERROR;
+ }
+ } else {
+ wrong_num_args(argc, argv, 2, 2, 3);
+ return TCL_ERROR;
+ }
+ }
+
+ else {
+ resultf("unimplemented route subcommand %s", cmd);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+} // namespace dtn