Add more linklayer data options and a better query function
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 24 Apr 2018 11:51:49 +0000 (13:51 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 24 Apr 2018 11:51:49 +0000 (13:51 +0200)
src-plugins/subsystems/oonf_layer2.c
src-plugins/subsystems/oonf_layer2.h

index 7599783..6bd4291 100644 (file)
@@ -92,7 +92,6 @@ static const struct oonf_layer2_metadata _metadata_neigh[OONF_LAYER2_NEIGH_COUNT
     .fraction = 3 },
   [OONF_LAYER2_NEIGH_TX_BITRATE] = { .key = "tx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
   [OONF_LAYER2_NEIGH_RX_BITRATE] = { .key = "rx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
-  [OONF_LAYER2_NEIGH_RX_BC_BITRATE] = { .key = "rx_bc_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
   [OONF_LAYER2_NEIGH_TX_MAX_BITRATE] = { .key = "tx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
   [OONF_LAYER2_NEIGH_RX_MAX_BITRATE] = { .key = "rx_max_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
   [OONF_LAYER2_NEIGH_TX_BYTES] = { .key = "tx_bytes", .type = OONF_LAYER2_INTEGER_DATA, .unit = "byte" },
@@ -100,12 +99,19 @@ static const struct oonf_layer2_metadata _metadata_neigh[OONF_LAYER2_NEIGH_COUNT
   [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" },
+  [OONF_LAYER2_NEIGH_RX_THROUGHPUT] = { .key = "rx_throughput", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
   [OONF_LAYER2_NEIGH_TX_RETRIES] = { .key = "tx_retries", .type = OONF_LAYER2_INTEGER_DATA },
+  [OONF_LAYER2_NEIGH_RX_RETRIES] = { .key = "rx_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_RX_FAILED] = { .key = "rx_failed", .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 },
+  [OONF_LAYER2_NEIGH_RX_BC_BITRATE] = { .key = "rx_bc_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
+  [OONF_LAYER2_NEIGH_RX_BC_LOSS] = { .key = "rx_bc_loss", .type = OONF_LAYER2_INTEGER_DATA, .fraction = 3 },
+  [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_RADIO_HOPCOUNT] = { .key = "radio_hopcount", .type = OONF_LAYER2_INTEGER_DATA },
+  [OONF_LAYER2_NEIGH_IP_HOPCOUNT] = { .key = "ip_hopcount", .type = OONF_LAYER2_INTEGER_DATA },
 };
 
 /* layer2 network metadata */
@@ -122,10 +128,13 @@ static const struct oonf_layer2_metadata _metadata_net[OONF_LAYER2_NET_COUNT] =
   [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_TX_BC_BITRATE] = { .key = "tx_bc_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
   [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 },
+  [OONF_LAYER2_NET_RADIO_MULTIHOP] = { .key = "radio_multihop", .type = OONF_LAYER2_BOOLEAN_DATA },
+  [OONF_LAYER2_NET_BAND_UP_DOWN] = { .key = "band_updown", .type = OONF_LAYER2_BOOLEAN_DATA },
 };
 
 static const char *_network_type[OONF_LAYER2_TYPE_COUNT] = {
@@ -172,6 +181,10 @@ static struct oonf_class _l2neigh_addr_class = {
   .name = LAYER2_CLASS_NEIGHBOR_ADDRESS,
   .size = sizeof(struct oonf_layer2_neighbor_address),
 };
+static struct oonf_class _lid_class = {
+  .name = LAYER2_CLASS_LID,
+  .size = sizeof(struct oonf_layer2_lid),
+};
 
 static struct avl_tree _oonf_layer2_net_tree;
 
@@ -179,6 +192,10 @@ static struct avl_tree _oonf_originator_tree;
 
 static struct avl_tree _local_peer_ips_tree;
 
+static struct avl_tree _lid_tree;
+
+static uint32_t _lid_originator_count;
+
 /**
  * Subsystem constructor
  * @return always returns 0
@@ -190,10 +207,14 @@ _init(void) {
   oonf_class_add(&_l2dst_class);
   oonf_class_add(&_l2net_addr_class);
   oonf_class_add(&_l2neigh_addr_class);
+  oonf_class_add(&_lid_class);
 
   avl_init(&_oonf_layer2_net_tree, avl_comp_strcasecmp, false);
   avl_init(&_oonf_originator_tree, avl_comp_strcasecmp, false);
   avl_init(&_local_peer_ips_tree, avl_comp_netaddr, true);
+  avl_init(&_lid_tree, avl_comp_netaddr, false);
+
+  _lid_originator_count = 0;
   return 0;
 }
 
@@ -203,11 +224,17 @@ _init(void) {
 static void
 _cleanup(void) {
   struct oonf_layer2_net *l2net, *l2n_it;
+  struct oonf_layer2_lid *lid, *lid_it;
 
   avl_for_each_element_safe(&_oonf_layer2_net_tree, l2net, _node, l2n_it) {
     _net_remove(l2net);
   }
+  avl_for_each_element_safe(&_lid_tree, lid, _node, lid_it) {
+    avl_remove(&_lid_tree, &lid->_node);
+    oonf_class_free(&_lid_class, lid);
+  }
 
+  oonf_class_remove(&_lid_class);
   oonf_class_remove(&_l2neigh_addr_class);
   oonf_class_remove(&_l2net_addr_class);
   oonf_class_remove(&_l2dst_class);
@@ -223,6 +250,11 @@ void
 oonf_layer2_origin_add(struct oonf_layer2_origin *origin) {
   origin->_node.key = origin->name;
   avl_insert(&_oonf_originator_tree, &origin->_node);
+
+  if (origin->lid) {
+    origin->lid_index = _lid_originator_count;
+    _lid_originator_count++;
+  }
 }
 
 /**
@@ -684,6 +716,57 @@ oonf_layer2_net_get_best_neighbor_match(const struct netaddr *addr) {
 }
 
 /**
+ * Generate a layer2 key based on an originator and a MAC. Enumerate
+ * new keys without explicitly storing them.
+ * @param key destination buffer for key
+ * @param origin originator for link-id creation
+ * @param mac mac address part of key
+ * @return -1 if an error happened, 0 otherwise
+ */
+int
+oonf_layer2_neigh_generate_lid(struct oonf_layer2_neigh_key *key,
+    struct oonf_layer2_origin *origin, const struct netaddr *mac) {
+  struct oonf_layer2_lid *lid;
+  uint32_t u32;
+
+  if (!origin->lid) {
+    return -1;
+  }
+
+  if (netaddr_get_address_family(mac) != AF_MAC48 && netaddr_get_address_family(mac) != AF_EUI64) {
+    return -1;
+  }
+
+  if (!(lid = avl_find_element(&_lid_tree, mac, lid, _node))) {
+    lid = oonf_class_malloc(&_lid_class);
+    if (!lid) {
+      return -1;
+    }
+
+    memcpy(&lid->mac, mac, sizeof(*mac));
+    lid->_node.key = &lid->mac;
+    avl_insert(&_lid_tree, &lid->_node);
+    lid->next_id = 1;
+  }
+
+  /* copy mac */
+  memcpy(&key->addr, mac, sizeof(*mac));
+
+  /* TODO: make LID length configurable */
+
+  /* generate new link-id */
+  u32 = htonl(lid->next_id);
+  memcpy(&key->link_id[0], &u32, 4);
+  key->link_id_length = 4;
+
+  /* keep track which originator orderer this LID */
+  key->link_id[0] = origin->lid_index & 0xff;
+
+  lid->next_id++;
+  return 0;
+}
+
+/**
  * Add a layer-2 neighbor to a addr.
  * @param l2net layer-2 addr object
  * @param key unique key for neighbor
@@ -855,28 +938,32 @@ oonf_layer2_neigh_add_ip(
   struct oonf_layer2_neighbor_address *l2addr;
 
   l2addr = oonf_layer2_neigh_get_remote_ip(l2neigh, ip);
-  if (!l2addr) {
-    l2addr = oonf_class_malloc(&_l2neigh_addr_class);
-    if (!l2addr) {
-      return NULL;
-    }
+  if (l2addr) {
+    l2addr->origin = origin;
+    return l2addr;
+  }
 
-    /* copy data */
-    memcpy(&l2addr->ip, ip, sizeof(*ip));
+  l2addr = oonf_class_malloc(&_l2neigh_addr_class);
+  if (!l2addr) {
+    return NULL;
+  }
 
-    /* set back reference */
-    l2addr->l2neigh = l2neigh;
+  /* copy data */
+  memcpy(&l2addr->ip, ip, sizeof(*ip));
 
-    /* add to tree */
-    l2addr->_neigh_node.key = &l2addr->ip;
-    avl_insert(&l2neigh->remote_neighbor_ips, &l2addr->_neigh_node);
-    l2addr->_net_node.key = &l2addr->ip;
-    avl_insert(&l2neigh->network->remote_neighbor_ips, &l2addr->_net_node);
+  /* set back reference */
+  l2addr->l2neigh = l2neigh;
 
-    oonf_class_event(&_l2neigh_addr_class, l2addr, OONF_OBJECT_ADDED);
-  }
+  /* add to tree */
+  l2addr->_neigh_node.key = &l2addr->ip;
+  avl_insert(&l2neigh->remote_neighbor_ips, &l2addr->_neigh_node);
+  l2addr->_net_node.key = &l2addr->ip;
+  avl_insert(&l2neigh->network->remote_neighbor_ips, &l2addr->_net_node);
 
+  /* remember originator */
   l2addr->origin = origin;
+
+  oonf_class_event(&_l2neigh_addr_class, l2addr, OONF_OBJECT_ADDED);
   return l2addr;
 }
 
@@ -958,10 +1045,12 @@ oonf_layer2_destination_remove(struct oonf_layer2_destination *l2dst) {
  * @param ifname name of interface
  * @param l2neigh_addr neighbor mac address
  * @param idx data index
+ * @param get_default true to return default (net) data if no neighbor data available
  * @return pointer to linklayer data, NULL if no value available
  */
-const struct oonf_layer2_data *
-oonf_layer2_neigh_query(const char *ifname, const struct netaddr *l2neigh_addr, enum oonf_layer2_neighbor_index idx) {
+struct oonf_layer2_data *
+oonf_layer2_neigh_query(const char *ifname, const struct netaddr *l2neigh_addr,
+      enum oonf_layer2_neighbor_index idx, bool get_default) {
   struct oonf_layer2_net *l2net;
   struct oonf_layer2_neigh *l2neigh;
   struct oonf_layer2_data *data;
@@ -981,6 +1070,10 @@ oonf_layer2_neigh_query(const char *ifname, const struct netaddr *l2neigh_addr,
     }
   }
 
+  if (!get_default) {
+    return NULL;
+  }
+
   /* look for network specific default */
   data = &l2net->neighdata[idx];
   if (oonf_layer2_data_has_value(data)) {
@@ -990,14 +1083,41 @@ oonf_layer2_neigh_query(const char *ifname, const struct netaddr *l2neigh_addr,
 }
 
 /**
+ * Get neighbor specific data, add interface and neighbor if necessary
+ * @param ifname name of interface
+ * @param l2neigh_addr neighbor mac address
+ * @param idx data index
+ * @return pointer to linklayer data, NULL if no value available
+ */
+struct oonf_layer2_data *
+oonf_layer2_neigh_add_path(const char *ifname, const struct netaddr *l2neigh_addr, enum oonf_layer2_neighbor_index idx) {
+    struct oonf_layer2_net *l2net;
+  struct oonf_layer2_neigh *l2neigh;
+
+  /* query layer2 database about neighbor */
+  l2net = oonf_layer2_net_add(ifname);
+  if (l2net == NULL) {
+    return NULL;
+  }
+
+  /* look for neighbor specific data */
+  l2neigh = oonf_layer2_neigh_add(l2net, l2neigh_addr);
+  if (l2neigh == NULL) {
+    return NULL;
+  }
+
+  return &l2neigh->data[idx];
+}
+
+/**
  * Get neighbor specific data, either from neighbor or from the networks default
  * @param l2neigh pointer to layer2 neighbor
  * @param idx data index
  * @return pointer to linklayer data, NULL if no value available
  */
-const struct oonf_layer2_data *
-oonf_layer2_neigh_get_data(const struct oonf_layer2_neigh *l2neigh, enum oonf_layer2_neighbor_index idx) {
-  const struct oonf_layer2_data *data;
+struct oonf_layer2_data *
+oonf_layer2_neigh_get_data(struct oonf_layer2_neigh *l2neigh, enum oonf_layer2_neighbor_index idx) {
+  struct oonf_layer2_data *data;
 
   data = &l2neigh->data[idx];
   if (oonf_layer2_data_has_value(data)) {
index 6b2de33..88d9d9a 100644 (file)
@@ -69,6 +69,9 @@
 /*! memory class for layer2 neighbor address */
 #define LAYER2_CLASS_NEIGHBOR_ADDRESS "layer2_neighbor_address"
 
+/*! memory class for layer2 tracking of next link-id per neighbor */
+#define LAYER2_CLASS_LID "layer2_lid"
+
 enum {
   /*! maximum length of link id for layer2 neighbors */
   OONF_LAYER2_MAX_LINK_ID = 16,
@@ -170,6 +173,12 @@ struct oonf_layer2_origin {
   /*! priority of this originator */
   enum oonf_layer2_origin_priority priority;
 
+  /*! true if this originator creates l2neighbor LID entries */
+  bool lid;
+
+  /* index number of the originator for LID creation */
+  uint32_t lid_index;
+
   /*! node for tree of originators */
   struct avl_node _node;
 };
@@ -270,7 +279,10 @@ enum oonf_layer2_network_index
   /*! total time in ns the channel was transmitting */
   OONF_LAYER2_NET_CHANNEL_TX,
 
-  /*! maixmum size of an IP packet for this interface */
+  /*! outgoing broadcast bitrate in bit/s */
+  OONF_LAYER2_NET_TX_BC_BITRATE,
+
+  /*! maixmum size of an ethernet/IP packet the router is allowed to send */
   OONF_LAYER2_NET_MTU,
 
   /*! true if unicast traffic is necessary for ratecontrol */
@@ -282,6 +294,15 @@ enum oonf_layer2_network_index
   /*! true if interface does not support incoming broadcast/multicast */
   OONF_LAYER2_NET_TX_ONLY_UNICAST,
 
+  /*! true if radio provides multihop forwarding transparently */
+  OONF_LAYER2_NET_RADIO_MULTIHOP,
+
+  /*!
+   * true if first frequency is uplink, second is downlink.
+   * false if reported frequencies can be used for both reception/transmission
+   */
+  OONF_LAYER2_NET_BAND_UP_DOWN,
+
   /*! number of layer2 network metrics */
   OONF_LAYER2_NET_COUNT,
 };
@@ -316,9 +337,6 @@ enum oonf_layer2_neighbor_index
   /*! incoming bitrate in bit/s */
   OONF_LAYER2_NEIGH_RX_BITRATE,
 
-  /*! incoming broadcast bitrate in bit/s */
-  OONF_LAYER2_NEIGH_RX_BC_BITRATE,
-
   /*! maximum possible outgoing bitrate in bit/s */
   OONF_LAYER2_NEIGH_TX_MAX_BITRATE,
 
@@ -338,25 +356,49 @@ enum oonf_layer2_neighbor_index
   OONF_LAYER2_NEIGH_RX_FRAMES,
 
   /*! average outgoing throughput in bit/s */
+  OONF_LAYER2_NEIGH_RX_THROUGHPUT,
+
+  /*! average incoming throughput in bit/s */
   OONF_LAYER2_NEIGH_TX_THROUGHPUT,
 
+  /*! total number of frame retransmission of other radio*/
+  OONF_LAYER2_NEIGH_RX_RETRIES,
+
   /*! total number of frame retransmission */
   OONF_LAYER2_NEIGH_TX_RETRIES,
 
+  /*! total number of failed frame receptions */
+  OONF_LAYER2_NEIGH_RX_FAILED,
+
   /*! total number of failed frame transmissions */
   OONF_LAYER2_NEIGH_TX_FAILED,
 
+  /*! relative transmission link quality (0-100) */
+  OONF_LAYER2_NEIGH_TX_RLQ,
+
+  /*! relative receiver link quality (0-100) */
+  OONF_LAYER2_NEIGH_RX_RLQ,
+
+  /*! incoming broadcast bitrate in bit/s */
+  OONF_LAYER2_NEIGH_RX_BC_BITRATE,
+
+  /*! incoming broadcast loss in 1/1000 */
+  OONF_LAYER2_NEIGH_RX_BC_LOSS,
+
   /*! latency to neighbor in microseconds */
   OONF_LAYER2_NEIGH_LATENCY,
 
   /*! available resources of radio (0-100) */
   OONF_LAYER2_NEIGH_RESOURCES,
 
-  /*! relative transmission link quality (0-100) */
-  OONF_LAYER2_NEIGH_TX_RLQ,
+  /*! number of radio hops to neighbor, only available for multihop capable radios */
+  OONF_LAYER2_NEIGH_RADIO_HOPCOUNT,
 
-  /*! relative receiver link quality (0-100) */
-  OONF_LAYER2_NEIGH_RX_RLQ,
+  /*!
+   *IP hopcount (including ethernet between radio and router) to neighbor router,
+   * only available for multihop capable radios
+   */
+  OONF_LAYER2_NEIGH_IP_HOPCOUNT,
 
   /*! number of neighbor metrics */
   OONF_LAYER2_NEIGH_COUNT,
@@ -508,6 +550,14 @@ struct oonf_layer2_destination {
   struct avl_node _node;
 };
 
+struct oonf_layer2_lid {
+  struct netaddr mac;
+
+  uint32_t next_id;
+
+  struct avl_node _node;
+};
+
 EXPORT void oonf_layer2_origin_add(struct oonf_layer2_origin *origin);
 EXPORT void oonf_layer2_origin_remove(struct oonf_layer2_origin *origin);
 
@@ -536,6 +586,7 @@ EXPORT int oonf_layer2_net_remove_ip(struct oonf_layer2_peer_address *ip, const
 EXPORT struct oonf_layer2_neighbor_address *oonf_layer2_net_get_best_neighbor_match(const struct netaddr *addr);
 EXPORT struct avl_tree *oonf_layer2_net_get_remote_ip_tree(void);
 
+EXPORT int oonf_layer2_neigh_generate_lid(struct oonf_layer2_neigh_key *, struct oonf_layer2_origin *origin, const struct netaddr *mac);
 EXPORT struct oonf_layer2_neigh *oonf_layer2_neigh_add_lid(struct oonf_layer2_net *, const struct oonf_layer2_neigh_key *key);
 EXPORT bool oonf_layer2_neigh_cleanup(struct oonf_layer2_neigh *l2neigh, const struct oonf_layer2_origin *origin);
 EXPORT bool oonf_layer2_neigh_remove(struct oonf_layer2_neigh *l2neigh, const struct oonf_layer2_origin *origin);
@@ -551,10 +602,12 @@ EXPORT struct oonf_layer2_destination *oonf_layer2_destination_add(
   struct oonf_layer2_neigh *l2neigh, const struct netaddr *destination, const struct oonf_layer2_origin *origin);
 EXPORT void oonf_layer2_destination_remove(struct oonf_layer2_destination *);
 
-EXPORT const struct oonf_layer2_data *oonf_layer2_neigh_query(
-  const char *ifname, const struct netaddr *l2neigh, enum oonf_layer2_neighbor_index idx);
-EXPORT const struct oonf_layer2_data *oonf_layer2_neigh_get_data(
-  const struct oonf_layer2_neigh *l2neigh, enum oonf_layer2_neighbor_index idx);
+EXPORT struct oonf_layer2_data *oonf_layer2_neigh_query(
+  const char *ifname, const struct netaddr *l2neigh, enum oonf_layer2_neighbor_index idx, bool get_default);
+EXPORT struct oonf_layer2_data *oonf_layer2_neigh_add_path(
+  const char *ifname, const struct netaddr *l2neigh_addr, enum oonf_layer2_neighbor_index idx);
+EXPORT struct oonf_layer2_data *oonf_layer2_neigh_get_data(
+  struct oonf_layer2_neigh *l2neigh, enum oonf_layer2_neighbor_index idx);
 
 EXPORT const struct oonf_layer2_metadata *oonf_layer2_neigh_metadata_get(enum oonf_layer2_neighbor_index);
 EXPORT const struct oonf_layer2_metadata *oonf_layer2_net_metadata_get(enum oonf_layer2_network_index);