Fixes for multi-topology routing
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 30 Jul 2015 10:54:46 +0000 (12:54 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 30 Jul 2015 10:54:46 +0000 (12:54 +0200)
14 files changed:
src-api/config/cfg_db.c
src-api/config/cfg_db.h
src-plugins/nhdp/ff_dat_metric/ff_dat_metric.c
src-plugins/nhdp/nhdp/nhdp_db.h
src-plugins/nhdp/nhdp/nhdp_domain.c
src-plugins/nhdp/nhdp/nhdp_domain.h
src-plugins/nhdp/nhdp/nhdp_interfaces.h
src-plugins/nhdp/nhdpinfo/nhdpinfo.c
src-plugins/olsrv2/netjsoninfo/netjsoninfo.c
src-plugins/olsrv2/olsrv2/olsrv2_reader.c
src-plugins/olsrv2/olsrv2/olsrv2_routing.c
src-plugins/olsrv2/olsrv2/olsrv2_writer.c
src-plugins/olsrv2/olsrv2info/olsrv2info.c
src-plugins/subsystems/oonf_rfc5444.c

index 56a7c8d..7949d95 100644 (file)
@@ -404,6 +404,27 @@ cfg_db_get_entry_value(struct cfg_db *db, const char *section_type,
   return NULL;
 }
 
+/**
+ * Retrieve the value for a section entry
+ * @param section named section, often taken from cfg_schema_section
+ * @param schema_entry schema_entry with key and default
+ * @return value of the db entry, default from schema_entry otherwise
+ */
+const struct const_strarray *
+cfg_db_get_schema_entry_value(struct cfg_named_section *section,
+    struct cfg_schema_entry *schema_entry) {
+  struct cfg_entry *entry;
+
+  if (section) {
+    entry = cfg_db_get_entry(section, schema_entry->key.entry);
+    if (entry) {
+      return (struct const_strarray *)&entry->val;
+    }
+  }
+
+  return &schema_entry->def;
+}
+
 /**
  * Removes an element from a configuration entry list
  * @param db pointer to configuration database
index 9053b41..8008d7f 100644 (file)
@@ -138,6 +138,8 @@ EXPORT int cfg_db_remove_entry(struct cfg_db *, const char *section_type,
     const char *section_name, const char *entry_name);
 EXPORT const struct const_strarray *cfg_db_get_entry_value(struct cfg_db *db,
     const char *section_type, const char *section_name, const char *entry_name);
+EXPORT const struct const_strarray *cfg_db_get_schema_entry_value(
+    struct cfg_named_section *section, struct cfg_schema_entry *entry);
 
 EXPORT int cfg_db_remove_element(struct cfg_db *, const char *section_type,
     const char *section_name, const char *entry_name, const char *value);
index 9669a16..703a05a 100644 (file)
@@ -827,7 +827,8 @@ _link_to_string(struct nhdp_metric_str *buf, uint32_t metric) {
         * (uint32_t)DATFF_LINKSPEED_RANGE;
   }
   else if (metric > DATFF_LINKCOST_MAXIMUM) {
-    value = 0;
+    strscpy(buf->buf, "infinite", sizeof(*buf));
+    return buf->buf;
   }
   else {
     value = (uint32_t)(DATFF_LINKSPEED_MINIMUM) * (uint32_t)(DATFF_LINKSPEED_RANGE) / metric;
@@ -845,24 +846,10 @@ _link_to_string(struct nhdp_metric_str *buf, uint32_t metric) {
  */
 static const char *
 _path_to_string(struct nhdp_metric_str *buf, uint32_t metric, uint8_t hopcount) {
-  struct isonumber_str ibuf;
-  uint64_t value;
-
-  metric = metric / hopcount;
-
-  if (metric < DATFF_LINKCOST_MINIMUM) {
-    value = (uint32_t)DATFF_LINKSPEED_MINIMUM
-        * (uint32_t)DATFF_LINKSPEED_RANGE;
-  }
-  else if (metric > DATFF_LINKCOST_MAXIMUM) {
-    value = 0;
-  }
-  else {
-    value = (uint32_t)(DATFF_LINKSPEED_MINIMUM) * (uint32_t)(DATFF_LINKSPEED_RANGE) / metric;
-  }
+  struct nhdp_metric_str mbuf;
 
   snprintf(buf->buf, sizeof(*buf), "%s (%u hops)",
-      isonumber_from_u64(&ibuf, value, "bit/s", 0, true, false), hopcount);
+      _link_to_string(&mbuf, metric / hopcount), hopcount);
   return buf->buf;
 }
 
index dab2bc2..062faf3 100644 (file)
 #ifndef NHDP_DB_H_
 #define NHDP_DB_H_
 
+struct nhdp_neighbor;
+struct nhdp_link;
+struct nhdp_l2hop;
+struct nhdp_laddr;
+
 #include "common/common_types.h"
 #include "common/avl.h"
 #include "common/list.h"
index 2a0a3af..aad89cc 100644 (file)
@@ -325,7 +325,6 @@ nhdp_domain_init_link(struct nhdp_link *lnk) {
   int i;
 
   /* initialize metrics */
-
   for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
     lnk->_domaindata[i].metric.in = RFC7181_METRIC_MAX;
     lnk->_domaindata[i].metric.out = RFC7181_METRIC_MAX;
@@ -818,7 +817,7 @@ nhdp_domain_set_flooding_mpr(struct nhdp_domain_mpr *mpr, uint8_t ext) {
 bool
 nhdp_domain_set_incoming_metric(struct nhdp_domain_metric *metric,
     struct nhdp_link *lnk, uint32_t metric_in) {
-  struct nhdp_link_domaindata *domaindata;
+  struct nhdp_link_domaindata *linkdata;
   struct nhdp_domain *domain;
   uint32_t old_metric;
   bool changed;
@@ -826,10 +825,9 @@ nhdp_domain_set_incoming_metric(struct nhdp_domain_metric *metric,
   changed = false;
   list_for_each_element(&_domain_list, domain, _node) {
     if (domain->metric == metric) {
-      domaindata = nhdp_domain_get_linkdata(domain, lnk);
-      old_metric = domaindata->metric.in;
-      domaindata->metric.in = metric_in;
-
+      linkdata = nhdp_domain_get_linkdata(domain, lnk);
+      old_metric = linkdata->metric.in;
+      linkdata->metric.in = metric_in;
       changed |= (old_metric != metric_in);
     }
   }
@@ -1017,9 +1015,10 @@ _apply_metric(struct nhdp_domain *domain, const char *metric_name) {
   domain->metric = metric;
 
   /* activate metric */
-  if (metric->enable) {
+  if (metric->_refcount == 0 && metric->enable) {
     metric->enable();
   }
+  metric->_refcount++;
 }
 
 /**
@@ -1028,8 +1027,11 @@ _apply_metric(struct nhdp_domain *domain, const char *metric_name) {
  */
 static void
 _remove_metric(struct nhdp_domain *domain) {
-  if (domain->metric->disable) {
-    domain->metric->disable();
+  domain->metric->_refcount--;
+  if (!domain->metric->_refcount) {
+    if (domain->metric->disable) {
+      domain->metric->disable();
+    }
   }
   strscpy(domain->metric_name, CFG_DOMAIN_NO_METRIC, sizeof(domain->metric_name));
   domain->metric = &_no_metric;
index 3d66657..97c15cd 100644 (file)
@@ -46,6 +46,7 @@
 #include "common/list.h"
 #include "subsystems/oonf_rfc5444.h"
 
+#include "nhdp/nhdp_interfaces.h"
 #include "nhdp/nhdp_db.h"
 
 #define NHDP_CLASS_DOMAIN             "nhdp_domain"
@@ -91,6 +92,9 @@ struct nhdp_domain_metric {
   void (*enable)(void);
   void (*disable)(void);
 
+  /* reference count */
+  int _refcount;
+
   /* node for tree of metrics */
   struct avl_node _node;
 };
@@ -216,7 +220,6 @@ EXPORT bool nhdp_domain_set_incoming_metric(
 EXPORT struct list_entity *nhdp_domain_get_list(void);
 EXPORT struct list_entity *nhdp_domain_get_listener_list(void);
 
-
 /**
  * @param domain NHDP domain
  * @param lnk NHDP link
index 6f4132b..d3f734e 100644 (file)
@@ -44,6 +44,7 @@
 
 struct nhdp_interface;
 struct nhdp_interface_addr;
+struct nhdp_interface_domaindata;
 
 #include "common/common_types.h"
 #include "common/avl.h"
@@ -78,9 +79,10 @@ struct nhdp_interface {
   uint64_t n_hold_time;
   uint64_t i_hold_time;
 
-  /* ACL for incoming HELLO messages through this interface */
+  /* ACL for interface addresses that should be included into HELLOs */
   struct netaddr_acl ifaddr_filter;
 
+
   /*
    * true if this interface has a neighbor that should be reached through
    * IPv4/IPv6 for flooding. This is set by the nhdp interface code.
index 285e32a..398c1d5 100644 (file)
@@ -318,6 +318,7 @@ static struct abuf_template_data _td_twohop_addr[] = {
     { _tde_if_key, ARRAYSIZE(_tde_if_key) },
     { _tde_link_key, ARRAYSIZE(_tde_link_key) },
     { _tde_twohop_addr, ARRAYSIZE(_tde_twohop_addr) },
+    { _tde_domain_metric, ARRAYSIZE(_tde_domain_metric) },
 };
 static struct abuf_template_data _td_neigh[] = {
     { _tde_neigh_key, ARRAYSIZE(_tde_neigh_key) },
index ff1be9b..664f9d5 100644 (file)
@@ -133,17 +133,24 @@ _print_graph_edge(struct json_session *session,
     uint32_t out, uint32_t in, bool outgoing_tree) {
   struct nhdp_metric_str mbuf;
 
+  if (out >= RFC7181_METRIC_INFINITE) {
+    return;
+  }
+
   json_start_object(session, NULL);
   _print_json_netaddr(session, "source", src);
   _print_json_netaddr(session, "target", dst);
+
   _print_json_number(session, "weight", out);
   if (in) {
     json_start_object(session, "properties");
     _print_json_string(session, "weight_txt",
         nhdp_domain_get_link_metric_value(&mbuf, domain, out));
-    _print_json_number(session, "in", in);
-    _print_json_string(session, "in_txt",
-        nhdp_domain_get_link_metric_value(&mbuf, domain, in));
+    if (in < RFC7181_METRIC_INFINITE) {
+      _print_json_number(session, "in", in);
+      _print_json_string(session, "in_txt",
+          nhdp_domain_get_link_metric_value(&mbuf, domain, in));
+    }
     _print_json_string(session, "outgoing_tree",
         json_getbool(outgoing_tree));
     json_end_object(session);
@@ -158,6 +165,10 @@ _print_graph_end(struct json_session *session,
     uint32_t out, uint8_t hopcount) {
   struct nhdp_metric_str mbuf;
 
+  if (out >= RFC7181_METRIC_INFINITE) {
+    return;
+  }
+
   json_start_object(session, NULL);
   _print_json_netaddr(session, "source", src);
   _print_json_netaddr(session, "target", &prefix->dst);
index 68091d8..6937fbc 100644 (file)
@@ -370,22 +370,20 @@ _cb_addresstlvs(struct rfc5444_reader_tlvblock_context *context __attribute__((u
 
   for (tlv = _olsrv2_address_tlvs[IDX_ADDRTLV_NBR_ADDR_TYPE].tlv;
       tlv; tlv = tlv->next_entry) {
-    /* find routing domain */
-    domain = nhdp_domain_get_by_ext(tlv->type_ext);
-    if (domain == NULL) {
-      continue;
-    }
-
     /* parse originator neighbor */
     if ((tlv->single_value[0] & RFC7181_NBR_ADDR_TYPE_ORIGINATOR) != 0) {
       edge = olsrv2_tc_edge_add(_current.node, &context->addr);
       if (edge) {
         OONF_DEBUG(LOG_OLSRV2_R, "Address is originator");
         edge->ansn = _current.node->ansn;
-        edge->cost[domain->index] = cost_out[domain->index];
 
-        if (edge->inverse->virtual) {
-          edge->inverse->cost[domain->index] = cost_in[domain->index];
+        for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
+          if (cost_out[i] < RFC7181_METRIC_INFINITE) {
+            edge->cost[domain->index] = cost_out[domain->index];
+          }
+          if (edge->inverse->virtual && cost_in[i] < RFC7181_METRIC_INFINITE) {
+            edge->inverse->cost[domain->index] = cost_in[domain->index];
+          }
         }
       }
     }
@@ -395,7 +393,11 @@ _cb_addresstlvs(struct rfc5444_reader_tlvblock_context *context __attribute__((u
       if (end) {
         OONF_DEBUG(LOG_OLSRV2_R, "Address is routable, but not originator");
         end->ansn = _current.node->ansn;
-        end->cost[domain->index] = cost_out[domain->index];
+        for (i=0; i<NHDP_MAXIMUM_DOMAINS; i++) {
+          if (cost_out[i] < RFC7181_METRIC_INFINITE) {
+            end->cost[domain->index] = cost_out[domain->index];
+          }
+        }
       }
     }
   }
index 1491081..44ecef7 100644 (file)
@@ -366,8 +366,9 @@ olsrv2_routing_get_filter_list(void) {
 static void
 _run_dijkstra(struct nhdp_domain *domain, int af_family,
     bool use_non_ss, bool use_ss) {
-  OONF_INFO(LOG_OLSRV2_ROUTING, "Run dijkstra %d: %s/%s",
-      domain->index, use_non_ss ? "true" : "false", use_ss ? "true" : "false");
+  OONF_INFO(LOG_OLSRV2_ROUTING, "Run %s dijkstra on domain %d: %s/%s",
+      af_family == AF_INET ? "ipv4" : "ipv6", domain->index,
+      use_non_ss ? "true" : "false", use_ss ? "true" : "false");
 
   /* add direct neighbors to working queue */
   _add_one_hop_nodes(domain, af_family, use_non_ss, use_ss);
@@ -720,9 +721,6 @@ _add_one_hop_nodes(struct nhdp_domain *domain, int af_family,
       continue;
     }
 
-    OONF_DEBUG(LOG_OLSRV2_ROUTING, "Add node %s",
-        netaddr_to_string(&nbuf, &neigh->originator));
-
     neigh_metric = nhdp_domain_get_neighbordata(domain, neigh);
 
     if (neigh_metric->metric.in > RFC7181_METRIC_MAX
@@ -731,6 +729,9 @@ _add_one_hop_nodes(struct nhdp_domain *domain, int af_family,
       continue;
     }
 
+    OONF_DEBUG(LOG_OLSRV2_ROUTING, "Add one-hop node %s",
+        netaddr_to_string(&nbuf, &neigh->originator));
+
     /* found node for neighbor, add to worker list */
     _insert_into_working_tree(&node->target, neigh,
         neigh_metric->metric.out, 0, 0, 0, true,
index 9e158fa..084a4a8 100644 (file)
@@ -121,7 +121,7 @@ olsrv2_writer_init(struct oonf_rfc5444_protocol *protocol) {
   _protocol = protocol;
 
   _olsrv2_message = rfc5444_writer_register_message(
-      &_protocol->writer, RFC5444_MSGTYPE_TC, true);
+      &_protocol->writer, RFC5444_MSGTYPE_TC, false);
   if (_olsrv2_message == NULL) {
     OONF_WARN(LOG_OLSRV2, "Could not register OLSRV2 TC message");
     return -1;
@@ -220,9 +220,11 @@ _cb_finishMessageHeader(struct rfc5444_writer *writer,
     struct rfc5444_writer_address *first __attribute__((unused)),
     struct rfc5444_writer_address *last __attribute__((unused)),
     bool fragented __attribute__((unused))) {
+  uint16_t seqno;
 
-  rfc5444_writer_set_msg_seqno(writer, message,
-      oonf_rfc5444_get_next_message_seqno(_protocol));
+  seqno = oonf_rfc5444_get_next_message_seqno(_protocol);
+  OONF_DEBUG(LOG_OLSRV2_W, "Set message sequence number to %u", seqno);
+  rfc5444_writer_set_msg_seqno(writer, message, seqno);
 }
 
 /**
@@ -292,6 +294,10 @@ _generate_neighbor_metric_tlvs(struct rfc5444_writer *writer,
     OONF_DEBUG(LOG_OLSRV2_W, "Neighbor is chosen by domain %u as MPR", domain->index);
 
     metric_in = neigh_domain->metric.in;
+    if (metric_in > RFC7181_METRIC_MAX) {
+      /*  */
+      continue;
+    }
     if (rfc7181_metric_encode(&metric_in_encoded, metric_in)) {
       OONF_DEBUG(LOG_OLSRV2_W, "Encoding of metric %u failed", metric_in);
       /* invalid incoming metric, do not mention it in the TC */
@@ -309,7 +315,7 @@ _generate_neighbor_metric_tlvs(struct rfc5444_writer *writer,
       /* incoming and outgoing metric are the same */
       rfc7181_metric_set_flag(&metric_in_encoded, RFC7181_LINKMETRIC_OUTGOING_NEIGH);
     }
-    else {
+    else if (metric_out <= RFC7181_METRIC_MAX){
       /* two different link metrics */
       rfc7181_metric_set_flag(&metric_out_encoded, RFC7181_LINKMETRIC_OUTGOING_NEIGH);
       second_tlv = true;
index 5365892..1edb8ae 100644 (file)
@@ -700,6 +700,7 @@ _cb_create_text_edge(struct oonf_viewer_template *template) {
   struct olsrv2_tc_node *node;
   struct olsrv2_tc_edge *edge;
   struct nhdp_domain *domain;
+  uint32_t metric;
 
   avl_for_each_element(olsrv2_tc_get_tree(), node, _originator_node) {
     _initialize_node_values(node);
@@ -715,11 +716,13 @@ _cb_create_text_edge(struct oonf_viewer_template *template) {
       _initialize_edge_values(edge);
 
       list_for_each_element(nhdp_domain_get_list(), domain, _node) {
-        _initialize_domain_values(domain);
-        _initialize_domain_link_metric_values(domain,
-            olsrv2_tc_edge_get_metric(domain, edge));
+        metric = olsrv2_tc_edge_get_metric(domain, edge);
+        if (metric < RFC7181_METRIC_INFINITE) {
+          _initialize_domain_values(domain);
+          _initialize_domain_link_metric_values(domain, metric);
 
-        oonf_viewer_output_print_line(template);
+          oonf_viewer_output_print_line(template);
+        }
       }
     }
   }
index cb9255d..3b63874 100644 (file)
@@ -251,7 +251,7 @@ static const char *_dependencies[] = {
 };
 
 static struct oonf_subsystem _oonf_rfc5444_subsystem = {
-  .name = "rfc5444",
+  .name = OONF_RFC5444_SUBSYSTEM,
   .dependencies = _dependencies,
   .dependencies_count = ARRAYSIZE(_dependencies),
   .init = _init,
@@ -263,6 +263,9 @@ DECLARE_OONF_PLUGIN(_oonf_rfc5444_subsystem);
 /* static blocking of RFC5444 output */
 static bool _block_output = false;
 
+/* additional logging targets */
+enum oonf_log_source LOG_RFC5444_R, LOG_RFC5444_W;
+
 /**
  * Initialize RFC5444 handling system
  * @return -1 if an error happened, 0 otherwise
@@ -305,6 +308,8 @@ _init(void) {
   rfc5444_reader_init(&_printer);
   rfc5444_print_add(&_printer_session, &_printer);
 
+  LOG_RFC5444_R = oonf_log_register_source(OONF_RFC5444_SUBSYSTEM "_r");
+  LOG_RFC5444_W = oonf_log_register_source(OONF_RFC5444_SUBSYSTEM "_w");
   return 0;
 }
 
@@ -943,7 +948,8 @@ _destroy_target(struct oonf_rfc5444_target *target) {
  * @param error text prefix when error happens during packet parsing
  */
 static void
-_print_packet_to_buffer(union netaddr_socket *sock __attribute__((unused)),
+_print_packet_to_buffer(enum oonf_log_source source,
+    union netaddr_socket *sock __attribute__((unused)),
     struct oonf_rfc5444_interface *interf __attribute__((unused)),
     uint8_t *ptr, size_t len,
     const char *success __attribute__((unused)),
@@ -951,21 +957,21 @@ _print_packet_to_buffer(union netaddr_socket *sock __attribute__((unused)),
   enum rfc5444_result result;
   struct netaddr_str buf;
 
-  if (oonf_log_mask_test(log_global_mask, LOG_RFC5444, LOG_SEVERITY_DEBUG)) {
+  if (oonf_log_mask_test(log_global_mask, source, LOG_SEVERITY_DEBUG)) {
     abuf_clear(&_printer_buffer);
     abuf_hexdump(&_printer_buffer, "", ptr, len);
 
     result = rfc5444_reader_handle_packet(&_printer, ptr, len);
     if (result) {
-      OONF_WARN(LOG_RFC5444, "%s %s for printing: %s (%d)",
+      OONF_WARN(source, "%s %s for printing: %s (%d)",
           error, netaddr_socket_to_string(&buf, sock), rfc5444_strerror(result), result);
-      OONF_WARN_NH(LOG_RFC5444, "%s", abuf_getptr(&_printer_buffer));
+      OONF_WARN_NH(source, "%s", abuf_getptr(&_printer_buffer));
     }
     else {
-      OONF_DEBUG(LOG_RFC5444, "%s %s through %s:",
+      OONF_DEBUG(source, "%s %s through %s:",
           success, netaddr_socket_to_string(&buf, sock), interf->name);
 
-      OONF_DEBUG_NH(LOG_RFC5444, "%s", abuf_getptr(&_printer_buffer));
+      OONF_DEBUG_NH(source, "%s", abuf_getptr(&_printer_buffer));
     }
   }
 }
@@ -1002,7 +1008,14 @@ _cb_receive_data(struct oonf_packet_socket *sock,
       sock == &interf->_socket.multicast_v4
       || sock == &interf->_socket.multicast_v6;
 
-  _print_packet_to_buffer(from, interf, ptr, length,
+  if (strcmp(interf->name, RFC5444_UNICAST_INTERFACE) == 0 &&
+      (netaddr_is_in_subnet(&NETADDR_IPV4_LINKLOCAL, &source_ip)
+          || netaddr_is_in_subnet(&NETADDR_IPV6_LINKLOCAL, &source_ip))) {
+    OONF_DEBUG(LOG_RFC5444, "Ignore linklocal traffic on generic unicast interface");
+    return;
+  }
+
+  _print_packet_to_buffer(LOG_RFC5444_R, from, interf, ptr, length,
       "Incoming RFC5444 packet from",
       "Error while parsing incoming RFC5444 packet from");
 
@@ -1037,7 +1050,7 @@ _cb_send_multicast_packet(struct rfc5444_writer *writer __attribute__((unused)),
   netaddr_socket_init(&sock, &t->dst, t->interface->protocol->port,
       t->interface->_socket._if_listener.interface->data.index);
 
-  _print_packet_to_buffer(&sock, t->interface, ptr, len,
+  _print_packet_to_buffer(LOG_RFC5444_W, &sock, t->interface, ptr, len,
       "Outgoing RFC5444 packet to",
       "Error while parsing outgoing RFC5444 packet to");
 
@@ -1067,7 +1080,7 @@ _cb_send_unicast_packet(struct rfc5444_writer *writer __attribute__((unused)),
   netaddr_socket_init(&sock, &t->dst, t->interface->protocol->port,
       t->interface->_socket._if_listener.interface->data.index);
 
-  _print_packet_to_buffer(&sock, t->interface, ptr, len,
+  _print_packet_to_buffer(LOG_RFC5444_W, &sock, t->interface, ptr, len,
       "Outgoing RFC5444 packet to",
       "Error while parsing outgoing RFC5444 packet to");