More work on RFC compliant DLEP and IP transmission by DLEP
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 12 Sep 2017 08:31:12 +0000 (10:31 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 12 Sep 2017 08:31:12 +0000 (10:31 +0200)
Preparation for "non-bridging neighbors" of DLEP

30 files changed:
src-api/common/isonumber.c
src-api/common/netaddr.c
src-api/common/netaddr.h
src-plugins/generic/dlep/CMakeLists.txt
src-plugins/generic/dlep/dlep_extension.c
src-plugins/generic/dlep/dlep_extension.h
src-plugins/generic/dlep/dlep_iana.h
src-plugins/generic/dlep/dlep_reader.c
src-plugins/generic/dlep/dlep_reader.h
src-plugins/generic/dlep/dlep_writer.c
src-plugins/generic/dlep/dlep_writer.h
src-plugins/generic/dlep/ext_l1_statistics/l1_statistics.c
src-plugins/generic/dlep/ext_l2_statistics/l2_statistics.c
src-plugins/generic/dlep/ext_radio_attributes/radio_attributes.c [new file with mode: 0644]
src-plugins/generic/dlep/ext_radio_attributes/radio_attributes.h [new file with mode: 0644]
src-plugins/generic/dlep/radio/dlep_radio_interface.c
src-plugins/generic/dlep/router/dlep_router_interface.c
src-plugins/generic/eth_listener/eth_listener.c
src-plugins/generic/layer2_config/layer2_config.c
src-plugins/generic/layer2_generator/layer2_generator.c
src-plugins/generic/layer2info/layer2info.c
src-plugins/generic/link_config/link_config.c
src-plugins/generic/nl80211_listener/nl80211_get_station_dump.c
src-plugins/generic/nl80211_listener/nl80211_get_wiphy.c
src-plugins/generic/nl80211_listener/nl80211_listener.c
src-plugins/nhdp/ff_dat_metric/ff_dat_metric.c
src-plugins/nhdp/neighbor_probing/neighbor_probing.c
src-plugins/subsystems/oonf_layer2.c
src-plugins/subsystems/oonf_layer2.h
tests/common/test_common_netaddr.c

index fb37c81..912ba1b 100644 (file)
@@ -119,7 +119,7 @@ isonumber_from_s64(struct isonumber_str *out,
 
   if (_isonumber_u64_to_string(
       outbuf, len, num, unit, fraction, binary, raw)) {
-  return out->buf;
+    return out->buf;
   }
   return NULL;
 }
@@ -169,11 +169,13 @@ isonumber_to_s64(int64_t *dst, const char *iso, int fractions, bool binary) {
  */
 int
 isonumber_to_u64(uint64_t *dst, const char *iso, int fraction, bool binary) {
+  static const char symbol_large[] = " kMGTPE";
+
   uint64_t num;
   uint64_t factor;
   uint64_t multiplicator;
   int frac;
-  char *next = NULL;
+  char *next = NULL, *prefix;
 
   errno = 0;
   num = strtoull(iso, &next, 10);
@@ -218,29 +220,14 @@ isonumber_to_u64(uint64_t *dst, const char *iso, int fraction, bool binary) {
 
     multiplicator = binary ? 1024 : 1000;
 
-    switch (next[0]) {
-      case 'E':
-        factor *= multiplicator;
-        /* fall through */
-      case 'P':
-        factor *= multiplicator;
-        /* fall through */
-      case 'T':
-        factor *= multiplicator;
-        /* fall through */
-      case 'G':
-        factor *= multiplicator;
-        /* fall through */
-      case 'M':
-        factor *= multiplicator;
-        /* fall through */
-      case 'k':
-        factor *= multiplicator;
-        /* fall through */
-      case ' ':
-        break;
-      default:
-        return -1;
+    prefix = strchr(symbol_large, next[0]);
+    if (!prefix) {
+      return -1;
+    }
+
+    while (prefix > next) {
+      factor *= multiplicator;
+      prefix--;
     }
   }
 
index 363baad..c866004 100644 (file)
 #include "common/string.h"
 #include "common/netaddr.h"
 
-static char *_mac_to_string(char *dst, const void *bin, size_t dst_size,
-    size_t bin_size, char separator);
-static int _mac_from_string(void *bin, size_t bin_size,
+static char *_mac_to_string(char *dst, size_t dst_size,
+    const void *bin, size_t bin_size, char separator);
+static char *_uuid_to_string(char *dst, size_t dst_size,
+    const void *bin, size_t bin_size);
+static int _bin_from_hex(void *bin, size_t bin_size,
     const char *src, char separator);
+static int _uuid_from_string(void *bin, size_t bin_size,
+    const char *src);
 static int _subnetmask_to_prefixlen(const char *src);
 static int _read_hexdigit(const char c);
 static bool _binary_is_in_subnet(const struct netaddr *subnet,
@@ -538,10 +542,13 @@ netaddr_to_prefixstring(struct netaddr_str *dst,
       result = inet_ntop(AF_INET6, src->_addr, dst->buf, sizeof(*dst));
       break;
     case AF_MAC48:
-      result = _mac_to_string(dst->buf, src->_addr, sizeof(*dst), 6, ':');
+      result = _mac_to_string(dst->buf, sizeof(*dst), src->_addr, 6, ':');
       break;
     case AF_EUI64:
-      result = _mac_to_string(dst->buf, src->_addr, sizeof(*dst), 8, '-');
+      result = _mac_to_string(dst->buf, sizeof(*dst), src->_addr, 8, '-');
+      break;
+    case AF_UUID:
+      result = _uuid_to_string(dst->buf, sizeof(*dst), src->_addr, 16);
       break;
     case AF_UNSPEC:
       /* fall through */
@@ -658,17 +665,17 @@ netaddr_from_string(struct netaddr *dst, const char *src) {
     dst->_type = AF_MAC48;
     dst->_prefix_len = 48;
     if (colon_count > 0) {
-      result = _mac_from_string(dst->_addr, 6, ptr1, ':');
+      result = _bin_from_hex(dst->_addr, 6, ptr1, ':');
     }
     else {
-      result = _mac_from_string(dst->_addr, 6, ptr1, '-');
+      result = _bin_from_hex(dst->_addr, 6, ptr1, '-');
     }
   }
   else if (colon_count == 0 && !has_point && minus_count == 7) {
     dst->_type = AF_EUI64;
     dst->_prefix_len = 64;
     dst->_addr[7] = 2;
-    result = _mac_from_string(dst->_addr, 8, ptr1, '-');
+    result = _bin_from_hex(dst->_addr, 8, ptr1, '-');
   }
   else if (colon_count == 0 && has_point && minus_count == 0) {
     dst->_type = AF_INET;
@@ -685,6 +692,11 @@ netaddr_from_string(struct netaddr *dst, const char *src) {
     dst->_prefix_len = 128;
     result = inet_pton(AF_INET6, ptr1, dst->_addr) == 1 ? 0 : -1;
   }
+  else if (minus_count == 4 && colon_count == 0 && !has_point) {
+    dst->_type = AF_UUID;
+    dst->_prefix_len = 128;
+    result = _uuid_from_string(dst->_addr, sizeof(dst->_addr), ptr1);
+  }
 
   /* stop if an error happened */
   if (result) {
@@ -970,14 +982,15 @@ inet_pton(int af, const char *src, void *dst)
 /**
  * Converts a binary mac address into a string representation
  * @param dst pointer to target string buffer
- * @param bin pointer to binary source buffer
  * @param dst_size size of string buffer
+ * @param bin pointer to binary source buffer
  * @param bin_size size of binary buffer
- * @param separator character for separating hexadecimal octets
+ * @param separator character for separating hexadecimal octets,
+ *     0 for no separator
  * @return pointer to target buffer, NULL if an error happened
  */
 static char *
-_mac_to_string(char *dst, const void *bin, size_t dst_size,
+_mac_to_string(char *dst, size_t dst_size, const void *bin,
     size_t bin_size, char separator) {
   static const char hex[] = "0123456789abcdef";
   char *last_separator, *_dst;
@@ -999,14 +1012,17 @@ _mac_to_string(char *dst, const void *bin, size_t dst_size,
     last_separator = _dst;
 
     /* write separator */
-    *_dst++ = separator;
+    if (separator) {
+      *_dst++ = separator;
+      dst_size--;
+    }
 
     /* advance source pointer and decrease remaining length of buffer*/
     _bin++;
     bin_size--;
 
     /* calculate remaining destination size */
-    dst_size-=3;
+    dst_size-=2;
   }
 
   *last_separator = 0;
@@ -1014,15 +1030,57 @@ _mac_to_string(char *dst, const void *bin, size_t dst_size,
 }
 
 /**
- * Convert a string mac address into a binary representation
+ * Convert a binary UUID into its string representation
+ * @param dst pointer to target string buffer
+ * @param dst_size size of string buffer
+ * @param src pointer to binary source buffer
+ * @param src_size size of binary buffer
+ * @return pointer to target buffer, NULL if an error happened
+ */
+static char *
+_uuid_to_string(char *dst, size_t dst_size, const void *src, size_t src_size) {
+  static const size_t max_group_len[5] = { 8, 4, 4, 4, 12 };
+  const char *_src;
+  char *_dst;
+  size_t i;
+
+  if (src_size != 16) {
+    return NULL;
+  }
+  if (dst_size < 32 + 4 + 1) {
+    return NULL;
+  }
+
+  _src = src;
+  _dst = dst;
+  for (i=0; i<ARRAYSIZE(max_group_len); i++) {
+    if (!_mac_to_string(_dst, dst_size, _src, max_group_len[i]/2, 0)) {
+      return NULL;
+    }
+
+    _src += (max_group_len[i]/2);
+    _dst += (max_group_len[i]);
+    dst_size -= max_group_len[i];
+
+    if (i < ARRAYSIZE(max_group_len)-1) {
+      *_dst++ = '-';
+      dst_size--;
+    }
+  }
+  return dst;
+}
+
+/**
+ * Convert a hex string (with optional separators) into a binary representation
  * @param bin pointer to target binary buffer
  * @param bin_size pointer to size of target buffer
  * @param src pointer to source string
- * @param separator character used to separate octets in source string
- * @return 0 if sucessfully converted, -1 otherwise
+ * @param separator character used to separate octets in source string,
+ *     0 for no separator
+ * @return number of bytes left in target buffer, -1 if an error happened
  */
 static int
-_mac_from_string(void *bin, size_t bin_size, const char *src, char separator) {
+_bin_from_hex(void *bin, size_t bin_size, const char *src, char separator) {
   uint8_t *_bin;
   int num, digit_2;
 
@@ -1043,15 +1101,69 @@ _mac_from_string(void *bin, size_t bin_size, const char *src, char separator) {
     bin_size--;
 
     if (*src == 0) {
-      return bin_size ? -1 : 0;
+      return bin_size;
     }
-    if (*src++ != separator) {
-      return -1;
+    if (separator) {
+      if (*src++ != separator) {
+        return -1;
+      }
     }
   }
   return -1;
 }
 
+/**
+ * Convert a string UUID into the binary (16 byte) representation
+ * @param bin target buffer
+ * @param bin_size size of target buffer
+ * @param src UUID string
+ * @return -1 if an error happened, 0 otherwise
+ */
+static int
+_uuid_from_string(void *bin, size_t bin_size, const char *src) {
+  static const size_t max_group_len[5] = { 8, 4, 4, 4, 12 };
+  char buffer[32+4+1];
+  char *current_group, *next_group, *_bin;
+  size_t i;
+
+  if (bin_size < 16) {
+    return -1;
+  }
+  if (strlen(src) > 32+4) {
+    return -1;
+  }
+
+  strscpy(buffer, src, sizeof(buffer));
+
+  _bin = bin;
+  current_group = buffer;
+  for (i=0; i<ARRAYSIZE(max_group_len); i++) {
+    next_group = strchr(current_group, '-');
+    if (next_group) {
+      /* zero terminate current group */
+      *next_group++ = 0;
+    }
+    else if (i != ARRAYSIZE(max_group_len)-1) {
+      /* not enough components */
+      return -1;
+    }
+
+    /* check length */
+    if (strlen(current_group) != max_group_len[i]) {
+      return -1;
+    }
+
+    /* parse data, we expect a precise number of hex-numbers */
+    if (_bin_from_hex(_bin, max_group_len[i]/2, current_group, 0)) {
+      return -1;
+    }
+
+    current_group = next_group;
+    _bin = _bin + max_group_len[i]/2;
+  }
+  return 0;
+}
+
 /**
  * Reads a single hexadecimal digit
  * @param c digit to be read
index 3017d9f..4ca1eaf 100644 (file)
@@ -71,6 +71,9 @@ enum {
 
   /*! address family for 64-bit EUI-64 address */
   AF_EUI64 = AF_MAX + 2,
+
+  /*! universal unique identifier (UUID) */
+  AF_UUID = AF_MAX + 3,
 };
 
 enum {
index fce0b1b..2fd137c 100644 (file)
@@ -12,6 +12,7 @@ SET (common_source      ext_base_metric/metric.c
                         ext_base_proto/proto.c
                         ext_l1_statistics/l1_statistics.c
                         ext_l2_statistics/l2_statistics.c
+                        ext_radio_attributes/radio_attributes.c
                         dlep_extension.c
                         dlep_interface.c
                         dlep_session.c
index ee68924..5b22ce9 100644 (file)
@@ -274,8 +274,10 @@ dlep_extension_radio_write_session_init_ack(
 
     l2data = &l2net->neighdata[ext->neigh_mapping[i].layer2];
 
+
     if (!oonf_layer2_has_value(l2data)) {
-      oonf_layer2_set_value(l2data, session->l2_origin,
+      oonf_layer2_data_set_int64(l2data, session->l2_origin,
+          oonf_layer2_get_neigh_metadata(ext->neigh_mapping[i].layer2),
           ext->neigh_mapping[i].default_value);
     }
   }
@@ -289,7 +291,8 @@ dlep_extension_radio_write_session_init_ack(
     l2data = &l2net->data[ext->if_mapping[i].layer2];
 
     if (!oonf_layer2_has_value(l2data)) {
-      oonf_layer2_set_value(l2data, session->l2_origin,
+      oonf_layer2_data_set_int64(l2data, session->l2_origin,
+          oonf_layer2_get_net_metadata(ext->if_mapping[i].layer2),
           ext->if_mapping[i].default_value);
     }
   }
index ebf2071..f866590 100644 (file)
@@ -189,23 +189,27 @@ struct dlep_neighbor_mapping {
   /**
    * callback to transform a TLV into layer2 data
    * @param l2data layer2 data
+   * @param meta metadata description for data
    * @param session dlep session
    * @param tlv tlv id
    * @return -1 if an error happened, 0 otherwise
    */
   int (*from_tlv)(struct oonf_layer2_data *l2data,
+      const struct oonf_layer2_metadata *meta,
       struct dlep_session *session, uint16_t tlv);
 
   /**
    * callback to transform layer2 data into a DLEP tlv
    * @param writer dlep writer
    * @param l2data layer2 data
+   * @param meta metadata description for data
    * @param tlv tlv id
    * @param length tlv length
    * @return -1 if an error happened, 0 otherwise
    */
   int (*to_tlv)(struct dlep_writer *writer,
       struct oonf_layer2_data *l2data,
+      const struct oonf_layer2_metadata *meta,
       uint16_t tlv, uint16_t length);
 };
 
@@ -232,23 +236,27 @@ struct dlep_network_mapping {
   /**
    * callback to transform a TLV into layer2 data
    * @param l2data layer2 data
+   * @param meta metadata description for data
    * @param session dlep session
    * @param tlv tlv id
    * @return -1 if an error happened, 0 otherwise
    */
   int (*from_tlv)(struct oonf_layer2_data *l2data,
+      const struct oonf_layer2_metadata *meta,
       struct dlep_session *session, uint16_t tlv);
 
   /**
    * callback to transform layer2 data into a DLEP tlv
    * @param writer dlep writer
    * @param l2data layer2 data
+   * @param meta metadata description for data
    * @param tlv tlv id
    * @param length tlv length
    * @return -1 if an error happened, 0 otherwise
    */
   int (*to_tlv)(struct dlep_writer *writer,
       struct oonf_layer2_data *l2data,
+      const struct oonf_layer2_metadata *meta,
       uint16_t tlv, uint16_t length);
 };
 
index 68f9542..76a3c7c 100644 (file)
@@ -73,22 +73,25 @@ enum {
  */
 enum dlep_extensions {
   /*! number of DLEP base extensions */
-  DLEP_EXTENSION_BASE_COUNT      =  3,
+  DLEP_EXTENSION_BASE_COUNT       =  3,
 
   /*! DLEP protocol/session handling */
-  DLEP_EXTENSION_BASE_PROTO      = -3,
+  DLEP_EXTENSION_BASE_PROTO       = -3,
 
   /*! DLEP metrics defined by base RFC */
-  DLEP_EXTENSION_BASE_IP         = -2,
+  DLEP_EXTENSION_BASE_IP          = -2,
 
   /*! DLEP metrics defined by base RFC */
-  DLEP_EXTENSION_BASE_METRIC     = -1,
+  DLEP_EXTENSION_BASE_METRIC      = -1,
 
   /*! Additional DLEP physical layer statistics */
-  DLEP_EXTENSION_L1_STATS        = 65520,
+  DLEP_EXTENSION_L1_STATS         = 65520,
 
   /*! Additional DLEP link layer statistics */
-  DLEP_EXTENSION_L2_STATS        = 65521,
+  DLEP_EXTENSION_L2_STATS         = 65521,
+
+  /*! Additional boolean radio attributes */
+  DLEP_EXTENSION_RADIO_ATTRIBUTES = 65522,
 };
 
 /**
@@ -280,6 +283,17 @@ enum dlep_tlvs {
 
   /*! total number of failed transmissions */
   DLEP_FRAMES_FAILED_TLV,
+
+  /* radio attributes */
+
+  /*! true if radio needs unicast traffic for MCS rate selection */
+  DLEP_MCS_BY_PROBING,
+
+  /*! true if radio can only receive unicast traffic */
+  DLEP_RX_ONLY_UNICAST,
+
+  /*! true if radio can only send unicast traffic */
+  DLEP_TX_ONLY_UNICAST,
 };
 
 enum dlep_peer_type_flags {
index 0a9bd0a..c906a22 100644 (file)
@@ -439,12 +439,14 @@ dlep_reader_status(enum dlep_status *status,
 /**
  * Parse a metric TLV and copy it into a layer2 data object
  * @param data pointer to layer2 data object
+ * @param meta metadata description for data
  * @param session dlep session
  * @param dlep_tlv DLEP TLV id
  * @return -1 if an error happened, 0 otherwise
  */
 int
 dlep_reader_map_identity(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv) {
   struct dlep_parser_value *value;
   int64_t l2value;
@@ -479,7 +481,16 @@ dlep_reader_map_identity(struct oonf_layer2_data *data,
         return -1;
     }
 
-    oonf_layer2_set_value(data, session->l2_origin, l2value);
+    switch (meta->type) {
+      case OONF_LAYER2_INTEGER_DATA:
+        oonf_layer2_data_set_int64(data, session->l2_origin, meta, l2value);
+        break;
+      case OONF_LAYER2_BOOLEAN_DATA:
+        oonf_layer2_data_set_bool(data, session->l2_origin, meta, l2value != 0);
+        break;
+      default:
+        return -1;
+    }
   }
   return 0;
 }
@@ -503,7 +514,8 @@ dlep_reader_map_l2neigh_data(struct oonf_layer2_data *data,
   for (i=0; i<ext->neigh_mapping_count; i++) {
     map = &ext->neigh_mapping[i];
 
-    if (map->from_tlv(&data[map->layer2], session, map->dlep)) {
+    if (map->from_tlv(&data[map->layer2],
+        oonf_layer2_get_neigh_metadata(map->layer2), session, map->dlep)) {
       return -(i+1);
     }
   }
@@ -529,7 +541,8 @@ dlep_reader_map_l2net_data(struct oonf_layer2_data *data,
   for (i=0; i<ext->if_mapping_count; i++) {
     map = &ext->if_mapping[i];
 
-    if (map->from_tlv(&data[map->layer2], session, map->dlep)) {
+    if (map->from_tlv(&data[map->layer2],
+        oonf_layer2_get_net_metadata(map->layer2), session, map->dlep)) {
       return -(i+1);
     }
   }
index 635904a..4e1c363 100644 (file)
@@ -82,6 +82,7 @@ int dlep_reader_status(enum dlep_status *status,
     struct dlep_session *session, struct dlep_parser_value *value);
 
 int dlep_reader_map_identity(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv);
 int dlep_reader_map_l2neigh_data(struct oonf_layer2_data *data,
     struct dlep_session *session, struct dlep_extension *ext);
index 30cc61e..cbad0d1 100644 (file)
@@ -382,7 +382,9 @@ dlep_writer_add_supported_extensions(struct dlep_writer *writer,
  */
 int
 dlep_writer_map_identity(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length) {
+    struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length) {
   int64_t l2value64;
   uint64_t tmp64;
   uint32_t tmp32;
@@ -390,12 +392,25 @@ dlep_writer_map_identity(struct dlep_writer *writer,
   uint8_t tmp8;
   void *value;
 
+  if (meta->type != OONF_LAYER2_INTEGER_DATA) {
+    /* bad data type */
+    return -1;
+  }
   if (!oonf_layer2_has_value(data)) {
     /* no data available */
     return 0;
   }
 
-  l2value64 = oonf_layer2_get_value(data);
+  switch (oonf_layer2_data_get_type(data)) {
+    case OONF_LAYER2_INTEGER_DATA:
+      l2value64 = oonf_layer2_get_int64(data);
+      break;
+    case OONF_LAYER2_BOOLEAN_DATA:
+      l2value64 = oonf_layer2_get_boolean(data) ? 1 : 0;
+      break;
+    default:
+      return -1;
+  }
 
   switch (length) {
     case 8:
@@ -449,7 +464,9 @@ dlep_writer_map_l2neigh_data(struct dlep_writer *writer,
       ptr = &def[map->layer2];
     }
 
-    if (map->to_tlv(writer, ptr, map->dlep, map->length)) {
+    if (map->to_tlv(writer, ptr,
+        oonf_layer2_get_neigh_metadata(map->layer2),
+        map->dlep, map->length)) {
       return -(i+1);
     }
   }
@@ -476,6 +493,7 @@ dlep_writer_map_l2net_data(struct dlep_writer *writer,
     map = &ext->if_mapping[i];
 
     if (map->to_tlv(writer, &data[map->layer2],
+        oonf_layer2_get_net_metadata(map->layer2),
         map->dlep, map->length)) {
       return -(i+1);
     }
index 4eb7cd4..dc847dd 100644 (file)
@@ -85,7 +85,8 @@ void dlep_writer_add_supported_extensions(struct dlep_writer *writer,
     const uint16_t *extensions, uint16_t ext_count);
 
 int dlep_writer_map_identity(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length);
+    struct oonf_layer2_data *data, const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length);
 int dlep_writer_map_l2neigh_data(struct dlep_writer *writer,
     struct dlep_extension *ext, struct oonf_layer2_data *data,
     struct oonf_layer2_data *def);
index 412e124..260d1a3 100644 (file)
 #include "dlep/ext_l1_statistics/l1_statistics.h"
 
 static int dlep_reader_map_array(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv,
     enum oonf_layer2_network_index l2idx);
 static int dlep_reader_map_frequency(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv);
 static int dlep_reader_map_bandwidth(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv);
 
 static int dlep_writer_map_array(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length,
+    struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length,
     enum oonf_layer2_network_index l2idx);
 static int dlep_writer_map_frequency(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length);
+    struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length);
 static int dlep_writer_map_bandwidth(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length);
+    struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length);
 
 /* peer initialization ack */
 static const uint16_t _session_initack_tlvs[] = {
@@ -278,6 +287,7 @@ dlep_l1_statistics_init(void) {
  */
 static int
 dlep_reader_map_array(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv,
     enum oonf_layer2_network_index l2idx) {
   struct dlep_parser_value *value;
@@ -306,7 +316,8 @@ dlep_reader_map_array(struct oonf_layer2_data *data,
 
   /* copy into signed integer and set to l2 value */
   memcpy(&l2value, &tmp64[0], 8);
-  oonf_layer2_set_value(data, session->l2_origin, l2value);
+  oonf_layer2_data_set_int64(data, session->l2_origin,
+      oonf_layer2_get_net_metadata(l2idx), l2value);
 
   if (value->length == 16) {
     switch (l2idx) {
@@ -321,7 +332,8 @@ dlep_reader_map_array(struct oonf_layer2_data *data,
     }
 
     memcpy(&l2value, &tmp64[1], 8);
-    oonf_layer2_set_value(data, session->l2_origin, l2value);
+    oonf_layer2_data_set_int64(data, session->l2_origin,
+        meta, l2value);
   }
   return 0;
 }
@@ -329,28 +341,32 @@ dlep_reader_map_array(struct oonf_layer2_data *data,
 /**
  * Read frequency TLV into layer2 database objects
  * @param data layer2 network data array
+ * @param meta metadata description for data
  * @param session dlep session
  * @param dlep_tlv dlep TLV id
  * @return -1 if an error happened, 0 otherwise
  */
 static int
 dlep_reader_map_frequency(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv) {
-  return dlep_reader_map_array(data, session, dlep_tlv,
+  return dlep_reader_map_array(data, meta, session, dlep_tlv,
       OONF_LAYER2_NET_FREQUENCY_1);
 }
 
 /**
  * Read bandwidth TLV into layer2 database objects
  * @param data layer2 network data array
+ * @param meta metadata description for data
  * @param session dlep session
  * @param dlep_tlv dlep TLV id
  * @return -1 if an error happened, 0 otherwise
  */
 static int
 dlep_reader_map_bandwidth(struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
     struct dlep_session *session, uint16_t dlep_tlv) {
-  return dlep_reader_map_array(data, session, dlep_tlv,
+  return dlep_reader_map_array(data, meta, session, dlep_tlv,
       OONF_LAYER2_NET_BANDWIDTH_1);
 }
 
@@ -366,7 +382,9 @@ dlep_reader_map_bandwidth(struct oonf_layer2_data *data,
  */
 int
 dlep_writer_map_array(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length,
+    struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length,
     enum oonf_layer2_network_index l2idx) {
   struct oonf_layer2_data *data2;
   int64_t l2value;
@@ -375,6 +393,10 @@ dlep_writer_map_array(struct dlep_writer *writer,
   if (length != 8 && length != 16) {
     return -1;
   }
+  if (meta->type != OONF_LAYER2_INTEGER_DATA) {
+    return -1;
+  }
+
   if (length == 16) {
     switch (l2idx) {
       case OONF_LAYER2_NET_FREQUENCY_1:
@@ -390,14 +412,14 @@ dlep_writer_map_array(struct dlep_writer *writer,
     }
 
     if (oonf_layer2_has_value(data2)) {
-      l2value = oonf_layer2_get_value(data2);
+      l2value = oonf_layer2_get_int64(data2);
       memcpy(&tmp64[1], &l2value, 8);
       tmp64[1] = htobe64(tmp64[1]);
       length = 16;
     }
   }
 
-  l2value = oonf_layer2_get_value(data);
+  l2value = oonf_layer2_get_int64(data);
   memcpy(&tmp64[0], &l2value, 8);
   tmp64[0] = htobe64(tmp64[0]);
 
@@ -415,8 +437,10 @@ dlep_writer_map_array(struct dlep_writer *writer,
  */
 static int
 dlep_writer_map_frequency(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length) {
-  return dlep_writer_map_array(writer, data, tlv, length,
+    struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length) {
+  return dlep_writer_map_array(writer, data, meta, tlv, length,
       OONF_LAYER2_NET_FREQUENCY_1);
 }
 
@@ -430,7 +454,9 @@ dlep_writer_map_frequency(struct dlep_writer *writer,
  */
 static int
 dlep_writer_map_bandwidth(struct dlep_writer *writer,
-    struct oonf_layer2_data *data, uint16_t tlv, uint16_t length) {
-  return dlep_writer_map_array(writer, data, tlv, length,
+    struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta,
+    uint16_t tlv, uint16_t length) {
+  return dlep_writer_map_array(writer, data, meta, tlv, length,
       OONF_LAYER2_NET_BANDWIDTH_1);
 }
index 4d719f9..8d3e99f 100644 (file)
@@ -63,10 +63,6 @@ static const uint16_t _session_initack_tlvs[] = {
     DLEP_BYTES_T_TLV,
     DLEP_THROUGHPUT_T_TLV,
 };
-static const uint16_t _session_initack_mandatory[] = {
-    DLEP_FRAMES_R_TLV,
-    DLEP_FRAMES_T_TLV,
-};
 
 /* peer update */
 static const uint16_t _peer_session_tlvs[] = {
@@ -100,8 +96,6 @@ static struct dlep_extension_signal _signals[] = {
         .id = DLEP_SESSION_INITIALIZATION_ACK,
         .supported_tlvs = _session_initack_tlvs,
         .supported_tlv_count = ARRAYSIZE(_session_initack_tlvs),
-        .mandatory_tlvs = _session_initack_mandatory,
-        .mandatory_tlv_count = ARRAYSIZE(_session_initack_mandatory),
         .add_radio_tlvs = dlep_extension_radio_write_session_init_ack,
         .process_router = dlep_extension_router_process_session_init_ack,
     },
@@ -148,10 +142,6 @@ static struct dlep_neighbor_mapping _neigh_mappings[] = {
         .dlep          = DLEP_FRAMES_R_TLV,
         .layer2        = OONF_LAYER2_NEIGH_RX_FRAMES,
         .length        = 8,
-
-        .mandatory     = true,
-        .default_value = 0,
-
         .from_tlv      = dlep_reader_map_identity,
         .to_tlv        = dlep_writer_map_identity,
     },
@@ -159,10 +149,6 @@ static struct dlep_neighbor_mapping _neigh_mappings[] = {
         .dlep          = DLEP_FRAMES_T_TLV,
         .layer2        = OONF_LAYER2_NEIGH_TX_FRAMES,
         .length        = 8,
-
-        .mandatory     = true,
-        .default_value = 0,
-
         .from_tlv      = dlep_reader_map_identity,
         .to_tlv        = dlep_writer_map_identity,
     },
diff --git a/src-plugins/generic/dlep/ext_radio_attributes/radio_attributes.c b/src-plugins/generic/dlep/ext_radio_attributes/radio_attributes.c
new file mode 100644 (file)
index 0000000..540cf9c
--- /dev/null
@@ -0,0 +1,140 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
+ * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+/**
+ * @file
+ */
+
+#include "common/common_types.h"
+#include "common/avl.h"
+
+#include "dlep/dlep_extension.h"
+#include "dlep/dlep_iana.h"
+#include "dlep/dlep_reader.h"
+#include "dlep/dlep_writer.h"
+
+#include "dlep/ext_radio_attributes/radio_attributes.h"
+
+/* peer initialization ack */
+static const uint16_t _session_initack_tlvs[] = {
+    DLEP_MCS_BY_PROBING,
+    DLEP_RX_ONLY_UNICAST,
+    DLEP_TX_ONLY_UNICAST,
+};
+
+/* peer update */
+static const uint16_t _peer_session_tlvs[] = {
+    DLEP_MCS_BY_PROBING,
+    DLEP_RX_ONLY_UNICAST,
+    DLEP_TX_ONLY_UNICAST,
+};
+
+/* supported signals of this extension */
+static struct dlep_extension_signal _signals[] = {
+    {
+        .id = DLEP_SESSION_INITIALIZATION_ACK,
+        .supported_tlvs = _session_initack_tlvs,
+        .supported_tlv_count = ARRAYSIZE(_session_initack_tlvs),
+        .add_radio_tlvs = dlep_extension_radio_write_session_init_ack,
+        .process_router = dlep_extension_router_process_session_init_ack,
+    },
+    {
+        .id = DLEP_SESSION_UPDATE,
+        .supported_tlvs = _peer_session_tlvs,
+        .supported_tlv_count = ARRAYSIZE(_peer_session_tlvs),
+        .add_radio_tlvs = dlep_extension_radio_write_session_update,
+        .process_router = dlep_extension_router_process_session_update,
+    },
+};
+
+/* supported TLVs of this extension */
+static struct dlep_extension_tlv _tlvs[] = {
+    { DLEP_MCS_BY_PROBING, 1, 1 },
+    { DLEP_RX_ONLY_UNICAST, 1, 1 },
+    { DLEP_TX_ONLY_UNICAST, 1, 1 },
+};
+
+static struct dlep_network_mapping _net_mappings[] = {
+    {
+        .dlep          = DLEP_MCS_BY_PROBING,
+        .layer2        = OONF_LAYER2_NET_MCS_BY_PROBING,
+        .length        = 1,
+        .from_tlv      = dlep_reader_map_identity,
+        .to_tlv        = dlep_writer_map_identity,
+    },
+    {
+        .dlep          = DLEP_RX_ONLY_UNICAST,
+        .layer2        = OONF_LAYER2_NET_RX_ONLY_UNICAST,
+        .length        = 1,
+        .from_tlv      = dlep_reader_map_identity,
+        .to_tlv        = dlep_writer_map_identity,
+    },
+    {
+        .dlep          = DLEP_TX_ONLY_UNICAST,
+        .layer2        = OONF_LAYER2_NET_TX_ONLY_UNICAST,
+        .length        = 1,
+        .from_tlv      = dlep_reader_map_identity,
+        .to_tlv        = dlep_writer_map_identity,
+    },
+};
+
+/* DLEP base extension, radio side */
+static struct dlep_extension _radio_attributes = {
+  .id = DLEP_EXTENSION_RADIO_ATTRIBUTES,
+  .name = "radio attributes",
+
+  .signals = _signals,
+  .signal_count = ARRAYSIZE(_signals),
+  .tlvs = _tlvs,
+  .tlv_count = ARRAYSIZE(_tlvs),
+  .if_mapping = _net_mappings,
+  .if_mapping_count = ARRAYSIZE(_net_mappings),
+};
+
+/**
+ * Get the layer2 statistics DLEP extension
+ * @return this extension
+ */
+struct dlep_extension *
+dlep_radio_attributes_init(void) {
+  dlep_extension_add(&_radio_attributes);
+  return &_radio_attributes;
+}
diff --git a/src-plugins/generic/dlep/ext_radio_attributes/radio_attributes.h b/src-plugins/generic/dlep/ext_radio_attributes/radio_attributes.h
new file mode 100644 (file)
index 0000000..8cd9e7f
--- /dev/null
@@ -0,0 +1,55 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
+ * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+/**
+ * @file
+ */
+
+#ifndef _DLEP_RADIO_ATTRIBUTES_H_
+#define _DLEP_RADIO_ATTRIBUTES_H_
+
+#include "common/common_types.h"
+
+#include "dlep/dlep_extension.h"
+
+struct dlep_extension *dlep_radio_attributes_init(void);
+
+#endif /* _DLEP_RADIO_ATTRIBUTES_H_ */
index 0eb0f6f..c6dad9f 100644 (file)
@@ -65,6 +65,7 @@
 #include "dlep/ext_base_proto/proto_radio.h"
 #include "dlep/ext_l1_statistics/l1_statistics.h"
 #include "dlep/ext_l2_statistics/l2_statistics.h"
+#include "dlep/ext_radio_attributes/radio_attributes.h"
 #include "dlep/radio/dlep_radio_internal.h"
 #include "dlep/radio/dlep_radio_session.h"
 
@@ -101,6 +102,7 @@ dlep_radio_interface_init(void) {
   dlep_base_metric_init();
   dlep_l1_statistics_init();
   dlep_l2_statistics_init();
+  dlep_radio_attributes_init();
 
   _shutting_down = false;
   return 0;
index 33033e0..bb58a5b 100644 (file)
@@ -70,6 +70,7 @@
 #include "dlep/ext_base_proto/proto_router.h"
 #include "dlep/ext_l1_statistics/l1_statistics.h"
 #include "dlep/ext_l2_statistics/l2_statistics.h"
+#include "dlep/ext_radio_attributes/radio_attributes.h"
 #include "dlep/router/dlep_router_internal.h"
 #include "dlep/router/dlep_router_session.h"
 
@@ -103,6 +104,7 @@ dlep_router_interface_init(void) {
   dlep_base_ip_init();
   dlep_l1_statistics_init();
   dlep_l2_statistics_init();
+  dlep_radio_attributes_init();
 
   _shutting_down = false;
 
index 0df220f..a82c104 100644 (file)
@@ -226,10 +226,10 @@ _cb_transmission_event(struct oonf_timer_instance *ptr __attribute((unused))) {
         os_if->name,
         isonumber_from_s64(&ibuf, ethspeed, "bit/s", 0, false, false));
 
-    oonf_layer2_set_value(&l2net->neighdata[OONF_LAYER2_NEIGH_RX_BITRATE],
-        &_l2_origin, ethspeed);
-    oonf_layer2_set_value(&l2net->neighdata[OONF_LAYER2_NEIGH_TX_BITRATE],
-        &_l2_origin, ethspeed);
+    oonf_layer2_data_set_int64(&l2net->neighdata[OONF_LAYER2_NEIGH_RX_BITRATE],
+        &_l2_origin, oonf_layer2_get_neigh_metadata(OONF_LAYER2_NEIGH_RX_BITRATE), ethspeed);
+    oonf_layer2_data_set_int64(&l2net->neighdata[OONF_LAYER2_NEIGH_TX_BITRATE],
+        &_l2_origin, oonf_layer2_get_neigh_metadata(OONF_LAYER2_NEIGH_TX_BITRATE), ethspeed);
   }
 }
 
index 4bc525b..df15e3b 100644 (file)
@@ -72,9 +72,9 @@ struct l2_config_data {
   enum l2_data_type type;
   struct netaddr mac;
 
-  struct netaddr data_addr;
   int data_idx;
-  int64_t data;
+
+  union oonf_layer2_value data;
 };
 
 struct l2_config_if_data {
@@ -543,6 +543,7 @@ _cb_validate_l2dst(const struct cfg_schema_entry *entry,
  */
 static int
 _parse_l2net_config(struct l2_config_data *storage, const char *value) {
+  const struct oonf_layer2_metadata *meta;
   const char *ptr;
   int idx;
 
@@ -559,12 +560,10 @@ _parse_l2net_config(struct l2_config_data *storage, const char *value) {
     return -1;
   }
 
+  meta = oonf_layer2_get_net_metadata(idx);
   storage->data_idx = idx;
 
-  /* convert number */
-  return isonumber_to_s64(&storage->data, ptr,
-      oonf_layer2_get_net_metadata(idx)->fraction,
-      oonf_layer2_get_net_metadata(idx)->binary);
+  return oonf_layer2_data_parse_string(&storage->data, meta, ptr);
 }
 
 /**
@@ -575,7 +574,7 @@ _parse_l2net_config(struct l2_config_data *storage, const char *value) {
  */
 static int
 _parse_l2net_ip_config(struct l2_config_data *storage, const char *value) {
-  return netaddr_from_string(&storage->data_addr, value);
+  return netaddr_from_string(&storage->data.addr, value);
 }
 
 /**
@@ -607,9 +606,7 @@ _parse_l2neigh_config(struct l2_config_data *storage, const char *value) {
 
   /* convert number */
   ptr = str_cpynextword(sbuf.buf, ptr, sizeof(sbuf));
-  if (isonumber_to_s64(&storage->data, sbuf.buf,
-      oonf_layer2_get_neigh_metadata(idx)->fraction,
-      oonf_layer2_get_neigh_metadata(idx)->binary)) {
+  if (oonf_layer2_data_parse_string(&storage->data, oonf_layer2_get_neigh_metadata(idx), sbuf.buf)) {
     return -1;
   }
 
@@ -644,7 +641,7 @@ _parse_l2_addr_config(struct l2_config_data *storage, const char *value) {
   }
 
   /* copy second address */
-  if (netaddr_from_string(&storage->data_addr, ptr)) {
+  if (netaddr_from_string(&storage->data.addr, ptr)) {
     return -1;
   }
   return 0;
@@ -679,36 +676,36 @@ _configure_if_data(struct l2_config_if_data *if_data) {
 
       switch (entry->type) {
         case L2_NET:
-          oonf_layer2_set_value(&l2net->data[entry->data_idx],
-              &_l2_origin_current, entry->data);
+          oonf_layer2_data_set(&l2net->data[entry->data_idx],
+              &_l2_origin_current, oonf_layer2_get_net_metadata(entry->data_idx), &entry->data);
           break;
         case L2_NET_IP:
           oonf_layer2_net_add_ip(l2net,
-              &_l2_origin_current, &entry->data_addr);
+              &_l2_origin_current, &entry->data.addr);
           break;
         case L2_DEF:
-          oonf_layer2_set_value(&l2net->neighdata[entry->data_idx],
-              &_l2_origin_current, entry->data);
+          oonf_layer2_data_set(&l2net->neighdata[entry->data_idx],
+              &_l2_origin_current, oonf_layer2_get_neigh_metadata(entry->data_idx), &entry->data);
           break;
         case L2_NEIGH:
           l2neigh = oonf_layer2_neigh_add(l2net, &entry->mac);
           if (l2neigh) {
-            oonf_layer2_set_value(&l2neigh->data[entry->data_idx],
-                &_l2_origin_current, entry->data);
+            oonf_layer2_data_set(&l2neigh->data[entry->data_idx],
+                &_l2_origin_current, oonf_layer2_get_neigh_metadata(entry->data_idx), &entry->data);
           }
           break;
         case L2_NEIGH_IP:
           l2neigh = oonf_layer2_neigh_add(l2net, &entry->mac);
           if (l2neigh) {
             oonf_layer2_neigh_add_ip(l2neigh,
-                &_l2_origin_current, &entry->data_addr);
+                &_l2_origin_current, &entry->data.addr);
           }
           break;
         case L2_DST:
           l2neigh = oonf_layer2_neigh_add(l2net, &entry->mac);
           if (l2neigh) {
             oonf_layer2_destination_add(l2neigh,
-                &entry->data_addr, &_l2_origin_current);
+                &entry->data.addr, &_l2_origin_current);
           }
           break;
         default:
@@ -876,6 +873,9 @@ _cb_config_changed(void) {
         if_data->d[i].type = L2_NET;
         i++;
       }
+      else {
+        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
+      }
     }
   }
   if (l2net_ip_entry) {
@@ -885,6 +885,9 @@ _cb_config_changed(void) {
         if_data->d[i].type = L2_NET_IP;
         i++;
       }
+      else {
+        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
+      }
     }
   }
   if (l2def_entry) {
@@ -894,6 +897,9 @@ _cb_config_changed(void) {
         if_data->d[i].type = L2_DEF;
         i++;
       }
+      else {
+        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
+      }
     }
   }
   if (l2neigh_entry) {
@@ -903,6 +909,9 @@ _cb_config_changed(void) {
         if_data->d[i].type = L2_NEIGH;
         i++;
       }
+      else {
+        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
+      }
     }
   }
   if (l2neigh_ip_entry) {
@@ -912,6 +921,9 @@ _cb_config_changed(void) {
         if_data->d[i].type = L2_NEIGH_IP;
         i++;
       }
+      else {
+        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
+      }
     }
   }
   if (l2dst_entry) {
@@ -921,6 +933,9 @@ _cb_config_changed(void) {
         if_data->d[i].type = L2_DST;
         i++;
       }
+      else {
+        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
+      }
     }
   }
 
index 49a7ddb..b3c74d7 100644 (file)
@@ -214,10 +214,12 @@ _cb_l2gen_event(struct oonf_timer_instance *ptr __attribute((unused))) {
   net->last_seen = oonf_clock_getNow();
 
   for (net_idx=0; net_idx<OONF_LAYER2_NET_COUNT; net_idx++) {
-    oonf_layer2_set_value(&net->data[net_idx], &_origin, event_counter);
+    oonf_layer2_data_set_int64(&net->data[net_idx], &_origin,
+        oonf_layer2_get_net_metadata(net_idx), event_counter);
   }
   for (neigh_idx=0; neigh_idx<OONF_LAYER2_NEIGH_COUNT; neigh_idx++) {
-    oonf_layer2_set_value(&net->neighdata[neigh_idx], &_origin, event_counter);
+    oonf_layer2_data_set_int64(&net->neighdata[neigh_idx], &_origin,
+        oonf_layer2_get_neigh_metadata(neigh_idx), event_counter);
   }
 
   if (oonf_layer2_net_commit(net)) {
@@ -240,7 +242,8 @@ _cb_l2gen_event(struct oonf_timer_instance *ptr __attribute((unused))) {
   neigh->last_seen = oonf_clock_getNow();
 
   for (neigh_idx = 0; neigh_idx < OONF_LAYER2_NEIGH_COUNT; neigh_idx++) {
-    oonf_layer2_set_value(&neigh->data[neigh_idx], &_origin, event_counter);
+    oonf_layer2_data_set_int64(&neigh->data[neigh_idx], &_origin,
+        oonf_layer2_get_neigh_metadata(neigh_idx), event_counter);
   }
   oonf_layer2_neigh_commit(neigh);
 }
index cf4f1ad..44aaae1 100644 (file)
@@ -168,13 +168,13 @@ static struct netaddr_str               _value_if_local_addr;
 static struct isonumber_str             _value_if_lastseen;
 static struct netaddr_str               _value_if_peer_ip;
 static char                             _value_if_peer_ip_origin[IF_NAMESIZE];
-static struct isonumber_str             _value_if_data[OONF_LAYER2_NET_COUNT];
+static char                             _value_if_data[OONF_LAYER2_NET_COUNT][64];
 static char                             _value_if_origin[OONF_LAYER2_NET_COUNT][IF_NAMESIZE];
 static struct netaddr_str               _value_neigh_addr;
 static struct isonumber_str             _value_neigh_lastseen;
 static struct netaddr_str               _value_neigh_remote_ip;
 static char                             _value_neigh_remote_ip_origin[IF_NAMESIZE];
-static struct isonumber_str             _value_neigh_data[OONF_LAYER2_NEIGH_COUNT];
+static char                             _value_neigh_data[OONF_LAYER2_NEIGH_COUNT][64];
 static char                             _value_neigh_origin[OONF_LAYER2_NEIGH_COUNT][IF_NAMESIZE];
 
 static struct netaddr_str               _value_dst_addr;
@@ -275,7 +275,7 @@ static struct oonf_viewer_template _templates[] = {
     {
         .data = _td_if_ips,
         .data_size = ARRAYSIZE(_td_if_ips),
-        .json_name = "interface_ips",
+        .json_name = "interface_ip",
         .cb_function = _cb_create_text_interface_ip,
     },
     {
@@ -287,7 +287,7 @@ static struct oonf_viewer_template _templates[] = {
     {
         .data = _td_neigh_ips,
         .data_size = ARRAYSIZE(_td_neigh_ips),
-        .json_name = "neighbor_ips",
+        .json_name = "neighbor_ip",
         .cb_function = _cb_create_text_neighbor_ip,
     },
     {
@@ -342,7 +342,7 @@ _init(void) {
   for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
     _tde_if_data[i].key =
         abuf_getptr(&_key_storage) + abuf_getlen(&_key_storage);
-    _tde_if_data[i].value = _value_if_data[i].buf;
+    _tde_if_data[i].value = _value_if_data[i];
     _tde_if_data[i].string = true;
 
     abuf_puts(&_key_storage, KEY_IF_PREFIX);
@@ -363,7 +363,7 @@ _init(void) {
   for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
     _tde_neigh_data[i].key =
         abuf_getptr(&_key_storage) + abuf_getlen(&_key_storage);
-    _tde_neigh_data[i].value = _value_neigh_data[i].buf;
+    _tde_neigh_data[i].value = _value_neigh_data[i];
     _tde_neigh_data[i].string = true;
 
     abuf_puts(&_key_storage, KEY_NEIGH_PREFIX);
@@ -468,13 +468,8 @@ _initialize_if_data_values(struct oonf_viewer_template *template,
   memset(_value_if_data, 0, sizeof(_value_if_data));
 
   for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
-    if (oonf_layer2_has_value(&data[i])) {
-      isonumber_from_s64(&_value_if_data[i], oonf_layer2_get_value(&data[i]),
-          oonf_layer2_get_net_metadata(i)->unit,
-          oonf_layer2_get_net_metadata(i)->fraction,
-          oonf_layer2_get_net_metadata(i)->binary,
-          template->create_raw);
-    }
+    oonf_layer2_net_data_to_string(_value_if_data[i], sizeof(_value_if_data[i]),
+        &data[i], i, template->create_raw);
   }
 }
 
@@ -536,14 +531,8 @@ _initialize_neigh_data_values(struct oonf_viewer_template *template,
   memset(_value_neigh_data, 0, sizeof(_value_neigh_data));
 
   for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
-    if (oonf_layer2_has_value(&data[i])) {
-      isonumber_from_s64(&_value_neigh_data[i],
-          oonf_layer2_get_value(&data[i]),
-          oonf_layer2_get_neigh_metadata(i)->unit,
-          oonf_layer2_get_neigh_metadata(i)->fraction,
-          oonf_layer2_get_neigh_metadata(i)->binary,
-          template->create_raw);
-    }
+    oonf_layer2_neigh_data_to_string(_value_neigh_data[i], sizeof(_value_neigh_data[i]),
+        &data[i], i, template->create_raw);
   }
 }
 
index 85d5d38..53991ba 100644 (file)
@@ -303,7 +303,8 @@ _parse_strarray(struct strarray *array, const char *ifname,
 
     if (ptr == NULL) {
       /* add network wide data entry */
-      if (!oonf_layer2_set_value(&l2net->neighdata[idx], &_l2_origin_current, value)) {
+      if (!oonf_layer2_data_set_int64(&l2net->neighdata[idx], &_l2_origin_current,
+          oonf_layer2_get_neigh_metadata(idx),value)) {
         OONF_INFO(LOG_LINK_CONFIG, "if-wide %s for %s: %s",
             oonf_layer2_get_neigh_metadata(idx)->key, ifname, hbuf.buf);
       }
@@ -322,7 +323,8 @@ _parse_strarray(struct strarray *array, const char *ifname,
         continue;
       }
 
-      if (!oonf_layer2_set_value(&l2neigh->data[idx], &_l2_origin_current, value)) {
+      if (!oonf_layer2_data_set_int64(&l2neigh->data[idx], &_l2_origin_current,
+          oonf_layer2_get_neigh_metadata(idx),value)) {
         OONF_INFO(LOG_LINK_CONFIG, "%s to neighbor %s on %s: %s",
             oonf_layer2_get_neigh_metadata(idx)->key, nbuf.buf, ifname, hbuf.buf);
       }
index b37d06f..92a044a 100644 (file)
@@ -264,7 +264,7 @@ _handle_traffic(struct oonf_layer2_neigh *l2neigh,
 
   data = &l2neigh->data[idx];
   if (oonf_layer2_has_value(data)) {
-    old_value = oonf_layer2_get_value(data);
+    old_value = oonf_layer2_get_int64(data);
   }
 
   new_value = old_value & UPPER_32_MASK;
index a06b0b8..00164b0 100644 (file)
@@ -288,11 +288,11 @@ _get_max_bitrate(struct nl80211_if *interf, uint8_t *mcs, bool ht20_sgi, bool ht
     /* we don't know the bandwidth of the channel */
     return 0;
   }
-  bandwidth = oonf_layer2_get_value(data);
+  bandwidth = oonf_layer2_get_int64(data);
 
   data = &interf->l2net->data[OONF_LAYER2_NET_BANDWIDTH_2];
   if (oonf_layer2_has_value(data)) {
-    bandwidth += oonf_layer2_get_value(data);
+    bandwidth += oonf_layer2_get_int64(data);
   }
 
   if (bandwidth == 20000000) {
index ac87819..aeec94b 100644 (file)
@@ -372,7 +372,8 @@ nl80211_add_dst(struct oonf_layer2_neigh *l2neigh, const struct netaddr *dstmac)
 bool
 nl80211_change_l2net_data(struct oonf_layer2_net *l2net,
     enum oonf_layer2_network_index idx, uint64_t value) {
-  return oonf_layer2_change_value(&l2net->data[idx], &_layer2_updated_origin, value);
+  return oonf_layer2_data_set_int64(&l2net->data[idx], &_layer2_updated_origin,
+      oonf_layer2_get_net_metadata(idx), value);
 }
 
 /**
@@ -385,7 +386,8 @@ nl80211_change_l2net_data(struct oonf_layer2_net *l2net,
 bool
 nl80211_change_l2net_neighbor_default(struct oonf_layer2_net *l2net,
     enum oonf_layer2_neighbor_index idx, uint64_t value) {
-  return oonf_layer2_change_value(&l2net->neighdata[idx], &_layer2_updated_origin, value);
+  return oonf_layer2_data_set_int64(&l2net->neighdata[idx], &_layer2_updated_origin,
+      oonf_layer2_get_neigh_metadata(idx), value);
 }
 
 /**
@@ -408,7 +410,8 @@ nl80211_cleanup_l2neigh_data(struct oonf_layer2_neigh *l2neigh) {
 bool
 nl80211_change_l2neigh_data(struct oonf_layer2_neigh *l2neigh,
     enum oonf_layer2_neighbor_index idx, uint64_t value) {
-  return oonf_layer2_change_value(&l2neigh->data[idx], &_layer2_updated_origin, value);
+  return oonf_layer2_data_set_int64(&l2neigh->data[idx], &_layer2_updated_origin,
+      oonf_layer2_get_neigh_metadata(idx), value);
 }
 
 /**
index 0623374..d5dc0ec 100644 (file)
@@ -494,6 +494,10 @@ _cb_link_removed(void *ptr) {
   oonf_timer_stop(&data->hello_lost_timer);
 }
 
+/**
+ * Callback triggered when a NHDP interface has been added
+ * @param ptr NHDP interface instance
+ */
 static void
 _cb_nhdpif_added(void *ptr) {
   struct ff_dat_if_config *ifconfig;
@@ -503,6 +507,10 @@ _cb_nhdpif_added(void *ptr) {
   ifconfig->_sampling_timer.class = &_sampling_timer_info;
 }
 
+/**
+ * Callback triggered when a NHDP interface is removed
+ * @param ptr NHDP interface instance
+ */
 static void
 _cb_nhdpif_removed(void *ptr) {
   struct ff_dat_if_config *ifconfig;
@@ -580,7 +588,7 @@ _get_raw_rx_linkspeed(const char *ifname, struct nhdp_link *lnk) {
   rx_bitrate_entry = oonf_layer2_neigh_query(
       ifname, &lnk->remote_mac, OONF_LAYER2_NEIGH_RX_BITRATE);
   if (rx_bitrate_entry) {
-    return oonf_layer2_get_value(rx_bitrate_entry);
+    return oonf_layer2_get_int64(rx_bitrate_entry);
   }
 
   l2net = oonf_layer2_net_get(ifname);
@@ -589,11 +597,12 @@ _get_raw_rx_linkspeed(const char *ifname, struct nhdp_link *lnk) {
     return -1;
   }
 
+  /* search for an entry in the l2 database which reports the remote link IP */
   avl_for_each_element(&l2net->neighbors, l2neigh, _node) {
     if (oonf_layer2_neigh_get_ip(l2neigh, &lnk->if_addr)) {
       rx_bitrate_entry = &l2neigh->data[OONF_LAYER2_NEIGH_RX_BITRATE];
       if (oonf_layer2_has_value(rx_bitrate_entry)) {
-        return oonf_layer2_get_value(rx_bitrate_entry);
+        return oonf_layer2_get_int64(rx_bitrate_entry);
       }
     }
   }
@@ -633,7 +642,10 @@ _get_scaled_rx_linkspeed(struct ff_dat_if_config *ifconfig, struct nhdp_link *ln
   }
 
   /* round up */
-  rx_rate = (raw_rx_rate + DATFF_LINKSPEED_MINIMUM - 1) / DATFF_LINKSPEED_MINIMUM;
+  rx_rate = raw_rx_rate / DATFF_LINKSPEED_MINIMUM;
+  if (raw_rx_rate % DATFF_LINKSPEED_MINIMUM > 0) {
+    rx_rate++;
+  }
   if (rx_rate < 1) {
     OONF_DEBUG(LOG_FF_DAT, "Datarate for link %s (%s) too small: %"PRId64" / %"PRId64,
         netaddr_to_string(&nbuf, &lnk->if_addr),
@@ -921,6 +933,9 @@ _cb_hello_lost(struct oonf_timer_instance *ptr) {
 static bool
 _shall_process_packet(struct nhdp_interface *nhdpif, struct ff_dat_if_config *ifconfig) {
   struct os_interface_listener *if_listener;
+  struct oonf_layer2_data *l2data;
+  struct oonf_layer2_net *l2net;
+
   if (_protocol->input.is_multicast) {
     /* accept multicast */
     return true;
@@ -932,6 +947,17 @@ _shall_process_packet(struct nhdp_interface *nhdpif, struct ff_dat_if_config *if
     return true;
   }
 
+  l2net = oonf_layer2_net_get(if_listener->name);
+  if (l2net) {
+    /* accept for unicast-only interfaces marked in layer2-data */
+    l2data = &l2net->data[OONF_LAYER2_NET_RX_ONLY_UNICAST];
+
+    if (oonf_layer2_has_value(l2data) && oonf_layer2_get_boolean(l2data)) {
+      return true;
+    }
+  }
+
+  /* default to configuration */
   return ifconfig->accept_unicast;
 }
 
index 9278a7f..88ebd7b 100644 (file)
@@ -115,7 +115,8 @@ static struct cfg_schema_entry _probing_entries[] = {
       "Number of bytes used for neighbor probe",
       0, false, 1, 1500),
   CFG_MAP_BOOL(_config, probe_dlep, "probe_dlep", "true",
-      "Probe DLEP interfaces in addition to wireless interfaces"),
+      "Probe DLEP interfaces in addition to wireless interfaces"
+      " if they don't support the 'need probing' flag"),
 };
 
 static struct cfg_schema_section _probing_section = {
@@ -229,6 +230,10 @@ _cleanup(void) {
   oonf_class_extension_remove(&_link_extenstion);
 }
 
+/**
+ * Callback when link is removed to cleanup plugin data
+ * @param ptr NHDP link instance to be removed
+ */
 static void
 _cb_link_removed(void *ptr) {
   struct _probing_link_data *ldata;
@@ -239,9 +244,22 @@ _cb_link_removed(void *ptr) {
   }
 }
 
+/**
+ * Check if a certain interface should be probed
+ * @param net layer2 network instance
+ * @return true if interface should be probed, false otherwise
+ */
 static bool
 _check_if_type(struct oonf_layer2_net *net) {
+  struct oonf_layer2_data *l2data;
+
+  l2data = &net->data[OONF_LAYER2_NET_MCS_BY_PROBING];
+  if (oonf_layer2_has_value(l2data)) {
+    /* we got a direct setting reported for the interface for probing */
+    return oonf_layer2_get_boolean(l2data);
+  }
   if (net->if_dlep) {
+    /* use configuration for DLEP that does not report if probing is necessary */
     return _probe_config.probe_dlep;
   }
 
@@ -314,7 +332,7 @@ _cb_probe_link(struct oonf_timer_instance *ptr __attribute__((unused))) {
 
       /* fix tx-packets */
       last_tx_packets = ldata->last_tx_traffic;
-      ldata->last_tx_traffic = oonf_layer2_get_value(&l2neigh->data[OONF_LAYER2_NEIGH_TX_FRAMES]);
+      ldata->last_tx_traffic = oonf_layer2_get_int64(&l2neigh->data[OONF_LAYER2_NEIGH_TX_FRAMES]);
 
       /* check if link had traffic since last probe check */
       if (last_tx_packets != ldata->last_tx_traffic) {
index 4d724a1..20bbad8 100644 (file)
@@ -46,6 +46,7 @@
 #include "common/avl.h"
 #include "common/avl_comp.h"
 #include "common/common_types.h"
+#include "common/json.h"
 #include "common/netaddr.h"
 #include "config/cfg_schema.h"
 #include "core/oonf_subsystem.h"
@@ -81,37 +82,40 @@ DECLARE_OONF_PLUGIN(_oonf_layer2_subsystem);
 
 /* layer2 neighbor metadata */
 static const struct oonf_layer2_metadata _oonf_layer2_metadata_neigh[OONF_LAYER2_NEIGH_COUNT] = {
-  [OONF_LAYER2_NEIGH_TX_SIGNAL]      = { .key = "tx_signal", .unit = "dBm", .fraction = 3 },
-  [OONF_LAYER2_NEIGH_RX_SIGNAL]      = { .key = "rx_signal", .unit = "dBm", .fraction = 3 },
-  [OONF_LAYER2_NEIGH_TX_BITRATE]     = { .key = "tx_bitrate", .unit = "bit/s", .binary = true },
-  [OONF_LAYER2_NEIGH_RX_BITRATE]     = { .key = "rx_bitrate", .unit = "bit/s", .binary = true },
-  [OONF_LAYER2_NEIGH_TX_MAX_BITRATE] = { .key = "tx_max_bitrate", .unit = "bit/s", .binary = true },
-  [OONF_LAYER2_NEIGH_RX_MAX_BITRATE] = { .key = "rx_max_bitrate", .unit = "bit/s", .binary = true },
-  [OONF_LAYER2_NEIGH_TX_BYTES]       = { .key = "tx_bytes", .unit = "byte", .binary = true },
-  [OONF_LAYER2_NEIGH_RX_BYTES]       = { .key = "rx_bytes", .unit = "byte", .binary = true },
-  [OONF_LAYER2_NEIGH_TX_FRAMES]      = { .key = "tx_frames" },
-  [OONF_LAYER2_NEIGH_RX_FRAMES]      = { .key = "rx_frames" },
-  [OONF_LAYER2_NEIGH_TX_THROUGHPUT]  = { .key = "tx_throughput", .unit = "bit/s", .binary = true },
-  [OONF_LAYER2_NEIGH_TX_RETRIES]     = { .key = "tx_retries" },
-  [OONF_LAYER2_NEIGH_TX_FAILED]      = { .key = "tx_failed" },
-  [OONF_LAYER2_NEIGH_LATENCY]        = { .key = "latency", .unit = "s", .fraction = 6 },
-  [OONF_LAYER2_NEIGH_RESOURCES]      = { .key = "resources" },
-  [OONF_LAYER2_NEIGH_TX_RLQ]         = { .key = "tx_rlq" },
-  [OONF_LAYER2_NEIGH_RX_RLQ]         = { .key = "rx_rlq" },
+  [OONF_LAYER2_NEIGH_TX_SIGNAL]      = { .key = "tx_signal", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .fraction = 3 },
+  [OONF_LAYER2_NEIGH_RX_SIGNAL]      = { .key = "rx_signal", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .fraction = 3 },
+  [OONF_LAYER2_NEIGH_TX_BITRATE]     = { .key = "tx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .binary = true },
+  [OONF_LAYER2_NEIGH_RX_BITRATE]     = { .key = "rx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .binary = true },
+  [OONF_LAYER2_NEIGH_TX_MAX_BITRATE] = { .key = "tx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .binary = true },
+  [OONF_LAYER2_NEIGH_RX_MAX_BITRATE] = { .key = "rx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s", .binary = true },
+  [OONF_LAYER2_NEIGH_TX_BYTES]       = { .key = "tx_bytes", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte", .binary = true },
+  [OONF_LAYER2_NEIGH_RX_BYTES]       = { .key = "rx_bytes", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte", .binary = true },
+  [OONF_LAYER2_NEIGH_TX_FRAMES]      = { .key = "tx_frames", .type = OONF_LAYER2_INTEGER_DATA },
+  [OONF_LAYER2_NEIGH_RX_FRAMES]      = { .key = "rx_frames", .type = OONF_LAYER2_INTEGER_DATA  },
+  [OONF_LAYER2_NEIGH_TX_THROUGHPUT]  = { .key = "tx_throughput", .type = OONF_LAYER2_INTEGER_DATA , .unit = "bit/s", .binary = true },
+  [OONF_LAYER2_NEIGH_TX_RETRIES]     = { .key = "tx_retries", .type = OONF_LAYER2_INTEGER_DATA },
+  [OONF_LAYER2_NEIGH_TX_FAILED]      = { .key = "tx_failed", .type = OONF_LAYER2_INTEGER_DATA  },
+  [OONF_LAYER2_NEIGH_LATENCY]        = { .key = "latency", .type = OONF_LAYER2_INTEGER_DATA , .unit = "s", .fraction = 6 },
+  [OONF_LAYER2_NEIGH_RESOURCES]      = { .key = "resources", .type = OONF_LAYER2_INTEGER_DATA  },
+  [OONF_LAYER2_NEIGH_TX_RLQ]         = { .key = "tx_rlq", .type = OONF_LAYER2_INTEGER_DATA  },
+  [OONF_LAYER2_NEIGH_RX_RLQ]         = { .key = "rx_rlq", .type = OONF_LAYER2_INTEGER_DATA  },
 };
 
 /* layer2 network metadata */
 static const struct oonf_layer2_metadata _oonf_layer2_metadata_net[OONF_LAYER2_NET_COUNT] = {
-  [OONF_LAYER2_NET_FREQUENCY_1]     = { .key = "frequency1", .unit = "Hz" },
-  [OONF_LAYER2_NET_FREQUENCY_2]     = { .key = "frequency2", .unit = "Hz" },
-  [OONF_LAYER2_NET_BANDWIDTH_1]     = { .key = "bandwidth1", .unit = "Hz" },
-  [OONF_LAYER2_NET_BANDWIDTH_2]     = { .key = "bandwidth2", .unit = "Hz" },
-  [OONF_LAYER2_NET_NOISE]           = { .key = "noise", .unit="dBm", .fraction = 3 },
-  [OONF_LAYER2_NET_CHANNEL_ACTIVE]  = { .key = "ch_active", .unit="s", .fraction = 9 },
-  [OONF_LAYER2_NET_CHANNEL_BUSY]    = { .key = "ch_busy", .unit="s", .fraction = 9 },
-  [OONF_LAYER2_NET_CHANNEL_RX]      = { .key = "ch_rx", .unit="s", .fraction = 9 },
-  [OONF_LAYER2_NET_CHANNEL_TX]      = { .key = "ch_tx", .unit="s", .fraction = 9 },
-  [OONF_LAYER2_NET_MTU]             = { .key = "mtu", .unit="byte" },
+  [OONF_LAYER2_NET_FREQUENCY_1]     = { .key = "frequency1", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
+  [OONF_LAYER2_NET_FREQUENCY_2]     = { .key = "frequency2", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
+  [OONF_LAYER2_NET_BANDWIDTH_1]     = { .key = "bandwidth1", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
+  [OONF_LAYER2_NET_BANDWIDTH_2]     = { .key = "bandwidth2", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
+  [OONF_LAYER2_NET_NOISE]           = { .key = "noise", .type = OONF_LAYER2_INTEGER_DATA , .unit="dBm", .fraction = 3 },
+  [OONF_LAYER2_NET_CHANNEL_ACTIVE]  = { .key = "ch_active", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
+  [OONF_LAYER2_NET_CHANNEL_BUSY]    = { .key = "ch_busy", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
+  [OONF_LAYER2_NET_CHANNEL_RX]      = { .key = "ch_rx", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
+  [OONF_LAYER2_NET_CHANNEL_TX]      = { .key = "ch_tx", .type = OONF_LAYER2_INTEGER_DATA , .unit="s", .fraction = 9 },
+  [OONF_LAYER2_NET_MTU]             = { .key = "mtu", .type = OONF_LAYER2_INTEGER_DATA , .unit="byte" },
+  [OONF_LAYER2_NET_MCS_BY_PROBING]  = { .key = "mcs_by_probing", .type = OONF_LAYER2_BOOLEAN_DATA },
+  [OONF_LAYER2_NET_RX_ONLY_UNICAST] = { .key = "rx_only_unicast", .type = OONF_LAYER2_BOOLEAN_DATA },
+  [OONF_LAYER2_NET_TX_ONLY_UNICAST] = { .key = "tx_only_unicast", .type = OONF_LAYER2_BOOLEAN_DATA },
 };
 
 static const char *oonf_layer2_network_type[OONF_LAYER2_TYPE_COUNT] = {
@@ -211,6 +215,69 @@ oonf_layer2_remove_origin(struct oonf_layer2_origin *origin) {
   avl_remove(&_oonf_originator_tree, &origin->_node);
 }
 
+int
+oonf_layer2_data_parse_string(union oonf_layer2_value *value,
+    const struct oonf_layer2_metadata *meta, const char *input) {
+  memset(value, 0, sizeof(*value));
+
+  switch (meta->type) {
+    case OONF_LAYER2_INTEGER_DATA:
+      return isonumber_to_s64(
+          &value->integer, input, meta->fraction, meta->binary);
+
+    case OONF_LAYER2_BOOLEAN_DATA:
+        value->boolean = cfg_get_bool(input);
+        return 0;
+
+    default:
+      return -1;
+  }
+}
+
+int
+oonf_layer2_data_to_string(char *buffer, size_t length,
+    const struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta, bool raw) {
+  struct isonumber_str iso_str;
+
+  switch (meta->type) {
+    case OONF_LAYER2_INTEGER_DATA:
+      if (!isonumber_from_s64(&iso_str, data->_value.integer,
+          meta->unit, meta->fraction, meta->binary, raw)) {
+        return -1;
+      }
+      strscpy(buffer, iso_str.buf, length);
+      return 0;
+
+    case OONF_LAYER2_BOOLEAN_DATA:
+      strscpy(buffer, json_getbool(data->_value.boolean), length);
+      return 0;
+
+    default:
+      return -1;
+  }
+}
+
+bool
+oonf_layer2_data_set(struct oonf_layer2_data *l2data,
+    const struct oonf_layer2_origin *origin,
+    const struct oonf_layer2_metadata *meta,
+    const union oonf_layer2_value *input) {
+  bool changed = false;
+
+  if (l2data->_type == OONF_LAYER2_NO_DATA
+      || l2data->_origin == NULL
+      || l2data->_origin == origin
+      || l2data->_origin->priority < origin->priority) {
+    changed = l2data->_type != meta->type
+        || memcmp(&l2data->_value, input, sizeof(*input)) != 0;
+    memcpy(&l2data->_value, input, sizeof(*input));
+    l2data->_type = meta->type;
+    l2data->_origin = origin;
+  }
+  return changed;
+}
+
 /**
  * Add a layer-2 network to the database
  * @param ifname name of interface
@@ -807,30 +874,6 @@ oonf_layer2_neigh_get_value(const struct oonf_layer2_neigh *l2neigh,
   return NULL;
 }
 
-/**
- * Changes a layer2 data value
- * @param l2data pointer to layer2 data
- * @param origin origin for new data
- * @param value value of new data
- * @return true if value has changed, false otherwise
- */
-bool
-oonf_layer2_change_value(struct oonf_layer2_data *l2data,
-    const struct oonf_layer2_origin *origin, int64_t value) {
-  bool changed = true;
-
-  if (oonf_layer2_has_value(l2data)) {
-    changed = value != oonf_layer2_get_value(l2data);
-  }
-  if (changed) {
-    oonf_layer2_set_value(l2data, origin, value);
-  }
-  else {
-    l2data->_origin = origin;
-  }
-  return changed;
-}
-
 /**
  * get neighbor metric metadata
  * @param idx neighbor metric index
index 468af2e..291c1e3 100644 (file)
@@ -95,20 +95,52 @@ struct oonf_layer2_origin {
   struct avl_node _node;
 };
 
+enum oonf_layer2_data_type {
+  OONF_LAYER2_NO_DATA,
+  OONF_LAYER2_INTEGER_DATA,
+  OONF_LAYER2_BOOLEAN_DATA,
+};
+
+union oonf_layer2_value {
+  int64_t        integer;
+  bool           boolean;
+  struct netaddr addr;
+};
+
 /**
  * Single data entry of layer2 network or neighbor
  */
 struct oonf_layer2_data {
   /*! data value */
-  int64_t _value;
+  union oonf_layer2_value _value;
 
-  /*! true if the data contains value */
-  bool _has_value;
+  /*! type of data contained in this element */
+  enum oonf_layer2_data_type _type;
 
   /*! layer2 originator id */
   const struct oonf_layer2_origin *_origin;
 };
 
+/**
+ * Metadata of layer2 data entry for automatic processing
+ */
+struct oonf_layer2_metadata {
+  /*! type of data */
+  const char key[16];
+
+  /*! data type */
+  enum oonf_layer2_data_type type;
+
+  /*! unit (bit/s, byte, ...) */
+  const char unit[8];
+
+  /*! number of fractional digits of the data */
+  const int fraction;
+
+  /*! true if data is "base" 1024 instead of "base" 1000 */
+  const bool binary;
+};
+
 /**
  * list of layer2 network metrics
  */
@@ -143,6 +175,15 @@ enum oonf_layer2_network_index {
   /*! maixmum size of an IP packet for this interface */
   OONF_LAYER2_NET_MTU,
 
+  /*! true if unicast traffic is necessary for ratecontrol */
+  OONF_LAYER2_NET_MCS_BY_PROBING,
+
+  /*! true if interface does not support incoming broadcast/multicast */
+  OONF_LAYER2_NET_RX_ONLY_UNICAST,
+
+  /*! true if interface does not support incoming broadcast/multicast */
+  OONF_LAYER2_NET_TX_ONLY_UNICAST,
+
   /*! number of layer2 network metrics */
   OONF_LAYER2_NET_COUNT,
 };
@@ -333,26 +374,20 @@ struct oonf_layer2_destination {
   struct avl_node _node;
 };
 
-/**
- * Metadata of layer2 data entry for automatic processing
- */
-struct oonf_layer2_metadata {
-  /*! type of data */
-  const char key[16];
-
-  /*! unit (bit/s, byte, ...) */
-  const char unit[8];
-
-  /*! number of fractional digits of the data */
-  const int fraction;
-
-  /*! true if data is "base" 1024 instead of "base" 1000 */
-  const bool binary;
-};
-
 EXPORT void oonf_layer2_add_origin(struct oonf_layer2_origin *origin);
 EXPORT void oonf_layer2_remove_origin(struct oonf_layer2_origin *origin);
 
+EXPORT int oonf_layer2_data_parse_string(union oonf_layer2_value *value,
+    const struct oonf_layer2_metadata *meta,
+    const char *input);
+EXPORT int oonf_layer2_data_to_string(char *buffer, size_t length,
+    const struct oonf_layer2_data *data,
+    const struct oonf_layer2_metadata *meta, bool raw);
+EXPORT bool oonf_layer2_data_set(struct oonf_layer2_data *data,
+    const struct oonf_layer2_origin *origin,
+    const struct oonf_layer2_metadata *meta,
+    const union oonf_layer2_value *input);
+
 EXPORT struct oonf_layer2_net *oonf_layer2_net_add(const char *ifname);
 EXPORT bool oonf_layer2_net_remove(
     struct oonf_layer2_net *, const struct oonf_layer2_origin *origin);
@@ -398,9 +433,6 @@ EXPORT const struct oonf_layer2_data *oonf_layer2_neigh_query(
 EXPORT const struct oonf_layer2_data *oonf_layer2_neigh_get_value(
     const struct oonf_layer2_neigh *l2neigh, enum oonf_layer2_neighbor_index idx);
 
-EXPORT bool oonf_layer2_change_value(struct oonf_layer2_data *l2data,
-    const struct oonf_layer2_origin *origin, int64_t value);
-
 EXPORT const struct oonf_layer2_metadata *oonf_layer2_get_neigh_metadata(
     enum oonf_layer2_neighbor_index);
 EXPORT const struct oonf_layer2_metadata *oonf_layer2_get_net_metadata(
@@ -488,7 +520,12 @@ oonf_layer2_neigh_get_ip(const struct oonf_layer2_neigh *l2neigh,
  */
 static INLINE bool
 oonf_layer2_has_value(const struct oonf_layer2_data *l2data) {
-  return l2data->_has_value;
+  return l2data->_type != OONF_LAYER2_NO_DATA;
+}
+
+static INLINE enum oonf_layer2_data_type
+oonf_layer2_data_get_type(const struct oonf_layer2_data *l2data) {
+  return l2data->_type;
 }
 
 /**
@@ -496,8 +533,19 @@ oonf_layer2_has_value(const struct oonf_layer2_data *l2data) {
  * @return value of data object
  */
 static INLINE int64_t
-oonf_layer2_get_value(const struct oonf_layer2_data *l2data) {
-  return l2data->_value;
+oonf_layer2_get_int64(const struct oonf_layer2_data *l2data) {
+  assert (l2data->_type == OONF_LAYER2_INTEGER_DATA);
+  return l2data->_value.integer;
+}
+
+/**
+ * @param l2data layer-2 data object
+ * @return value of data object
+ */
+static INLINE bool
+oonf_layer2_get_boolean(const struct oonf_layer2_data *l2data) {
+  assert (l2data->_type == OONF_LAYER2_BOOLEAN_DATA);
+  return l2data->_value.boolean;
 }
 
 /**
@@ -520,26 +568,80 @@ oonf_layer2_set_origin(struct oonf_layer2_data *l2data,
   l2data->_origin = origin;
 }
 
+static INLINE bool
+oonf_layer2_data_from_string(struct oonf_layer2_data *data,
+    const struct oonf_layer2_origin *origin,
+    const struct oonf_layer2_metadata *meta,
+    const char *input) {
+  union oonf_layer2_value value;
+
+  if (oonf_layer2_data_parse_string(&value, meta, input)) {
+    return false;
+  }
+  return oonf_layer2_data_set(data, origin, meta, &value);
+}
+
+static INLINE int
+oonf_layer2_net_data_to_string(char *buffer, size_t length,
+    const struct oonf_layer2_data *data, enum oonf_layer2_network_index idx, bool raw) {
+  return oonf_layer2_data_to_string(buffer, length, data,
+      oonf_layer2_get_net_metadata(idx), raw);
+}
+
+static INLINE int
+oonf_layer2_neigh_data_to_string(char *buffer, size_t length,
+    const struct oonf_layer2_data *data, enum oonf_layer2_neighbor_index idx, bool raw) {
+  return oonf_layer2_data_to_string(buffer, length, data,
+      oonf_layer2_get_neigh_metadata(idx), raw);
+}
+
+/**
+ * Set the value of a layer-2 data object
+ * @param l2data layer-2 data object
+ * @param origin originator of value
+ * @param integer new value for data object
+ * @return true if value was overwrite, false otherwise
+ */
+static INLINE bool
+oonf_layer2_data_set_int64(struct oonf_layer2_data *l2data,
+    const struct oonf_layer2_origin *origin,
+    const struct oonf_layer2_metadata *meta, int64_t integer) {
+  union oonf_layer2_value value = {0};
+  value.integer = integer;
+
+  return oonf_layer2_data_set(l2data, origin, meta, &value);
+}
+
 /**
  * Set the value of a layer-2 data object
  * @param l2data layer-2 data object
  * @param origin originator of value
- * @param value new value for data object
- * @return -1 if value was not overwritte, 0 otherwise
+ * @param boolean new value for data object
+ * @return true if value was overwrite, false otherwise
  */
+static INLINE bool
+oonf_layer2_data_set_bool(struct oonf_layer2_data *l2data,
+    const struct oonf_layer2_origin *origin,
+    const struct oonf_layer2_metadata *meta, bool boolean) {
+  union oonf_layer2_value value = {0};
+  value.boolean = boolean;
+  return oonf_layer2_data_set(l2data, origin, meta, &value);
+}
+
 static INLINE int
-oonf_layer2_set_value(struct oonf_layer2_data *l2data,
-    const struct oonf_layer2_origin *origin, int64_t value) {
-  if (l2data->_origin
-      && l2data->_origin != origin
-      && l2data->_origin->priority >= origin->priority) {
-    /* only overwrite lower priority data */
-    return -1;
-  }
-  l2data->_has_value = true;
-  l2data->_value = value;
-  l2data->_origin = origin;
-  return 0;
+oonf_layer2_net_data_from_string(
+    struct oonf_layer2_data *data, enum oonf_layer2_network_index idx,
+    struct oonf_layer2_origin *origin, const char *input) {
+  return oonf_layer2_data_from_string(
+      data, origin, oonf_layer2_get_net_metadata(idx), input);
+}
+
+static INLINE int
+oonf_layer2_neigh_data_from_string(
+    struct oonf_layer2_data *data, enum oonf_layer2_neighbor_index idx,
+    struct oonf_layer2_origin *origin, const char *input) {
+  return oonf_layer2_data_from_string(
+      data, origin, oonf_layer2_get_neigh_metadata(idx), input);
 }
 
 /**
@@ -548,7 +650,7 @@ oonf_layer2_set_value(struct oonf_layer2_data *l2data,
  */
 static INLINE void
 oonf_layer2_reset_value(struct oonf_layer2_data *l2data) {
-  l2data->_has_value = false;
+  l2data->_type = OONF_LAYER2_NO_DATA;
   l2data->_origin = NULL;
 }
 
index 357d323..e35946a 100644 (file)
@@ -80,6 +80,10 @@ struct netaddr_string_tests string_tests[] = {
 
   /* eui-64 */
   { "10-00-00-00-00-0a-0a-0b", { {0x10,0,0,0, 0,0x0a,0x0a,0x0b, 0,0,0,0, 0,0,0,0}, AF_EUI64, 64 } },
+
+  /* uuid */
+  { "00112233-4455-6677-8899-aabbccddeeff",
+      { { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }, AF_UUID, 128 } },
 };
 
 /* special test cases for netaddr_from_string */
@@ -118,6 +122,8 @@ const char *bad_netaddr_from_string[] = {
   "10-0:0-0-0-",
   "10-0-0-0--0",
   "10-0-0-0-0-0-0-0-0-0-0",
+  "001122-334455-6677-8899-aabbccddeeff",
+  "001122-33-4455-6677-8899-aabbccddeeff",
 };
 
 /* in subnet tests */
@@ -243,7 +249,7 @@ test_netaddr_to_string(void) {
   START_TEST();
 
   /* test successful netaddr to string conversions first */
-  for (i=0; i<sizeof(string_tests) / sizeof(*string_tests); i++) {
+  for (i=0; i<ARRAYSIZE(string_tests); i++) {
     ptr = netaddr_to_string(&strbuf, &string_tests[i].bin);
     CHECK_TRUE(ptr == strbuf.buf, "netaddr_to_string %s return error condition",
         string_tests[i].str);
@@ -266,7 +272,7 @@ test_netaddr_from_string(void) {
   START_TEST();
 
   /* test successful string to netaddr conversions first */
-  for (i=0; i<sizeof(string_tests) / sizeof(*string_tests); i++) {
+  for (i=0; i<ARRAYSIZE(string_tests); i++) {
     ret = netaddr_from_string(&netaddr_buf, string_tests[i].str);
     CHECK_TRUE(ret == 0, "netaddr_from_string (%s) returns %d", string_tests[i].str, ret);
 
@@ -277,7 +283,7 @@ test_netaddr_from_string(void) {
   }
 
   /* test special cases of string to netaddr conversions next */
-  for (i=0; i<sizeof(good_netaddr_from_string) / sizeof(*good_netaddr_from_string); i++) {
+  for (i=0; i<ARRAYSIZE(good_netaddr_from_string); i++) {
     ret = netaddr_from_string(&netaddr_buf, good_netaddr_from_string[i].str);
     CHECK_TRUE(ret == 0, "netaddr_from_string (%s) returns %d", good_netaddr_from_string[i].str, ret);
 
@@ -288,7 +294,7 @@ test_netaddr_from_string(void) {
   }
 
   /* test error cases of string to netaddr conversions next */
-  for (i=0; i<sizeof(bad_netaddr_from_string)/sizeof(*bad_netaddr_from_string); i++) {
+  for (i=0; i<ARRAYSIZE(bad_netaddr_from_string); i++) {
     CHECK_TRUE (0 != netaddr_from_string(&netaddr_buf, bad_netaddr_from_string[i]),
         "netaddr_from_string %s returns %d", bad_netaddr_from_string[i], ret);
   }
@@ -340,8 +346,8 @@ test_netaddr_is_in_subnet(void) {
   size_t a, s;
   START_TEST();
 
-  for (s = 0; s < sizeof(in_subnet_subnets) / sizeof(*in_subnet_subnets); s++) {
-    for (a = 0; a < sizeof(in_subnet_addrs) / sizeof(*in_subnet_addrs); a++) {
+  for (s = 0; s < ARRAYSIZE(in_subnet_subnets); s++) {
+    for (a = 0; a < ARRAYSIZE(in_subnet_addrs); a++) {
       CHECK_TRUE(
           in_subnet_results[a][s] == netaddr_binary_is_in_subnet(&in_subnet_subnets[s], &in_subnet_addrs[a],
               netaddr_get_maxprefix(&in_subnet_addrs[a])/8, in_subnet_addrs[a]._type),