More work on making DLEP RFC compatible
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 29 Aug 2017 14:14:29 +0000 (16:14 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 29 Aug 2017 14:14:29 +0000 (16:14 +0200)
37 files changed:
src-api/common/avl.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_interface.c
src-plugins/generic/dlep/dlep_interface.h
src-plugins/generic/dlep/dlep_reader.c
src-plugins/generic/dlep/dlep_reader.h
src-plugins/generic/dlep/dlep_session.c
src-plugins/generic/dlep/dlep_session.h
src-plugins/generic/dlep/dlep_writer.c
src-plugins/generic/dlep/dlep_writer.h
src-plugins/generic/dlep/ext_base_ip/ip.c [new file with mode: 0644]
src-plugins/generic/dlep/ext_base_ip/ip.h [new file with mode: 0644]
src-plugins/generic/dlep/ext_base_ip/ip_radio.c [new file with mode: 0644]
src-plugins/generic/dlep/ext_base_ip/ip_radio.h [new file with mode: 0644]
src-plugins/generic/dlep/ext_base_ip/ip_router.c [new file with mode: 0644]
src-plugins/generic/dlep/ext_base_ip/ip_router.h [new file with mode: 0644]
src-plugins/generic/dlep/ext_base_metric/metric.c
src-plugins/generic/dlep/ext_base_proto/proto.c
src-plugins/generic/dlep/ext_base_proto/proto.h
src-plugins/generic/dlep/ext_base_proto/proto_radio.c
src-plugins/generic/dlep/ext_base_proto/proto_router.c
src-plugins/generic/dlep/ext_l1_statistics/l1_statistics.c
src-plugins/generic/dlep/ext_l2_statistics/l2_statistics.c
src-plugins/generic/dlep/radio/dlep_radio_interface.c
src-plugins/generic/dlep/radio/dlep_radio_session.c
src-plugins/generic/dlep/router/dlep_router_interface.c
src-plugins/generic/dlep/router/dlep_router_session.c
src-plugins/generic/dlep/router/dlep_router_session.h
src-plugins/subsystems/oonf_http.c
src-plugins/subsystems/oonf_layer2.c
src-plugins/subsystems/oonf_layer2.h
src-plugins/subsystems/oonf_stream_socket.c
src-plugins/subsystems/oonf_stream_socket.h
src-plugins/subsystems/oonf_telnet.c

index 8ef514c..2d1dbab 100644 (file)
 #include "list.h"
 #include "container_of.h"
 
+/**
+ * Static initializer for AVL tree
+ * @param avl avl_tree variable (not pointer!)
+ * @param avl_comp comparator to be used
+ * @param dups true if duplicates are allowed, false otherwise
+ */
+#define AVL_STATIC_INIT(avl, avl_comp, dups) { .list_head = { .next = &avl.list_head, .prev = &avl.list_head }, .root = NULL, .count = 0, .allow_dups = dups, .comp = avl_comp}
+
 /**
  * This element is a member of a avl-tree. It must be contained in all
  * larger structs that should be put into a tree.
index a51424e..fce0b1b 100644 (file)
@@ -8,6 +8,7 @@ SET (router_only_source ext_base_proto/proto_router.c
                         router/dlep_router_interface.c
                         router/dlep_router_session.c)
 SET (common_source      ext_base_metric/metric.c
+                        ext_base_ip/ip.c
                         ext_base_proto/proto.c
                         ext_l1_statistics/l1_statistics.c
                         ext_l2_statistics/l2_statistics.c
index bfe872e..ee68924 100644 (file)
@@ -172,7 +172,7 @@ dlep_extension_get_ids(uint16_t *length) {
  * @return -1 if an error happened, 0 otherwise
  */
 int
-dlep_extension_router_process_peer_init_ack(
+dlep_extension_router_process_session_init_ack(
     struct dlep_extension *ext, struct dlep_session *session) {
   if (session->restrict_signal != DLEP_SESSION_INITIALIZATION_ACK) {
     /* ignore unless we are in initialization mode */
@@ -189,7 +189,7 @@ dlep_extension_router_process_peer_init_ack(
  * @return -1 if an error happened, 0 otherwise
  */
 int
-dlep_extension_router_process_peer_update(
+dlep_extension_router_process_session_update(
     struct dlep_extension *ext, struct dlep_session *session) {
   if (session->restrict_signal != DLEP_ALL_SIGNALS) {
     /* ignore unless we have an established session */
@@ -251,7 +251,7 @@ dlep_extension_router_process_destination(
  * @return -1 if an error happened, 0 otherwise
  */
 int
-dlep_extension_radio_write_peer_init_ack(
+dlep_extension_radio_write_session_init_ack(
     struct dlep_extension *ext, struct dlep_session *session,
     const struct netaddr *neigh __attribute__((unused))) {
   struct oonf_layer2_net *l2net;
@@ -322,7 +322,7 @@ dlep_extension_radio_write_peer_init_ack(
  * @return -1 if an error happened, 0 otherwise
  */
 int
-dlep_extension_radio_write_peer_update(
+dlep_extension_radio_write_session_update(
     struct dlep_extension *ext, struct dlep_session *session,
     const struct netaddr *neigh __attribute__((unused))) {
   struct oonf_layer2_net *l2net;
index a66373c..ebf2071 100644 (file)
@@ -341,16 +341,16 @@ EXPORT void dlep_extension_add_processing(struct dlep_extension *, bool radio,
   struct dlep_extension_implementation *proc, size_t proc_count);
 EXPORT const uint16_t *dlep_extension_get_ids(uint16_t *length);
 
-EXPORT int dlep_extension_router_process_peer_init_ack(
+EXPORT int dlep_extension_router_process_session_init_ack(
   struct dlep_extension *, struct dlep_session *session);
-EXPORT int dlep_extension_router_process_peer_update(
+EXPORT int dlep_extension_router_process_session_update(
   struct dlep_extension *, struct dlep_session *session);
 EXPORT int dlep_extension_router_process_destination(
   struct dlep_extension *, struct dlep_session *session);
-EXPORT int dlep_extension_radio_write_peer_init_ack(
+EXPORT int dlep_extension_radio_write_session_init_ack(
   struct dlep_extension *ext, struct dlep_session *session,
   const struct netaddr *neigh);
-EXPORT int dlep_extension_radio_write_peer_update(
+EXPORT int dlep_extension_radio_write_session_update(
   struct dlep_extension *ext, struct dlep_session *session,
   const struct netaddr *neigh);
 EXPORT int dlep_extension_radio_write_destination(
index 63556a9..68f9542 100644 (file)
@@ -73,10 +73,13 @@ enum {
  */
 enum dlep_extensions {
   /*! number of DLEP base extensions */
-  DLEP_EXTENSION_BASE_COUNT      =  2,
+  DLEP_EXTENSION_BASE_COUNT      =  3,
 
   /*! DLEP protocol/session handling */
-  DLEP_EXTENSION_BASE_PROTO      = -2,
+  DLEP_EXTENSION_BASE_PROTO      = -3,
+
+  /*! DLEP metrics defined by base RFC */
+  DLEP_EXTENSION_BASE_IP         = -2,
 
   /*! DLEP metrics defined by base RFC */
   DLEP_EXTENSION_BASE_METRIC     = -1,
@@ -120,16 +123,16 @@ enum dlep_signals {
   DLEP_SESSION_INITIALIZATION_ACK   =  2,
 
   /*! Radio update interface scope data */
-  DLEP_PEER_UPDATE                  =  3,
+  DLEP_SESSION_UPDATE               =  3,
 
   /*! Router acknowledges interface data update */
-  DLEP_PEER_UPDATE_ACK              =  4,
+  DLEP_SESSION_UPDATE_ACK           =  4,
 
   /*! Radio/Router terminates DLEP session */
-  DLEP_PEER_TERMINATION             =  5,
+  DLEP_SESSION_TERMINATION          =  5,
 
   /*! Radio/Router acknowledge end of DLEP session */
-  DLEP_PEER_TERMINATION_ACK         =  6,
+  DLEP_SESSION_TERMINATION_ACK      =  6,
 
   /*! Radio announces a new neighbor with metrics */
   DLEP_DESTINATION_UP               =  7,
index c997505..737840c 100644 (file)
@@ -60,6 +60,16 @@ static void _cb_send_multicast(struct dlep_session *session, int af_family);
 
 static const char _DLEP_PREFIX[] = DLEP_RFC8175_PREFIX;
 
+static struct avl_tree _radio_if_tree =
+    AVL_STATIC_INIT(_radio_if_tree, avl_comp_strcasecmp, false);
+static struct avl_tree _router_if_tree =
+    AVL_STATIC_INIT(_router_if_tree, avl_comp_strcasecmp, false);
+
+struct avl_tree *
+dlep_if_get_tree(bool radio) {
+  return radio ? &_radio_if_tree : &_router_if_tree;
+}
+
 /**
  * Add a new interface to this dlep instance
  * @param interf pointer to interface
@@ -96,6 +106,9 @@ dlep_if_add(struct dlep_if *interf, const char *ifname,
     return -1;
   }
 
+  /* remember if this is a radio interface */
+  interf->radio = radio;
+
   /* initialize stream list */
   avl_init(&interf->session_tree, avl_comp_netaddr_socket, false);
 
@@ -111,6 +124,9 @@ dlep_if_add(struct dlep_if *interf, const char *ifname,
       radio ? DLEP_UDP_PEER_DISCOVERY : DLEP_UDP_PEER_OFFER;
   interf->session.writer.out = &interf->udp_out;
 
+  /* add to tree */
+  avl_insert(dlep_if_get_tree(radio), &interf->_node);
+
   /* inform all extension */
   avl_for_each_element(dlep_extension_get_tree(), ext, _node) {
     if (radio) {
@@ -151,11 +167,18 @@ dlep_if_remove(struct dlep_if *interface) {
     }
   }
 
+  /* remove from tree */
+  avl_remove(dlep_if_get_tree(interface->radio), &interface->_node);
+
   /* close UDP interface */
   oonf_packet_remove_managed(&interface->udp, true);
 
   /* kill dlep session */
   dlep_session_remove(&interface->session);
+
+  /* free allocated memory data */
+  oonf_packet_free_managed_config(&interface->udp_config);
+  abuf_free(&interface->udp_out);
 }
 /**
  * Callback to receive UDP data through oonf_packet_managed API
@@ -207,7 +230,13 @@ _cb_receive_udp(struct oonf_packet_socket *pkt,
 
   processed = dlep_session_process_buffer(&interf->session, buffer, length, true);
   if (processed < 0) {
-    return ;
+    /* Session is now most likely invalid */
+    return;
+  }
+
+  if (interf->session.restrict_signal == DLEP_KILL_SESSION) {
+    /* Session was terminated */
+    return;
   }
 
   if ((size_t)processed < length) {
index 207fd68..1410da0 100644 (file)
@@ -73,13 +73,17 @@ struct dlep_if {
   /*! true if radio should only accept a single session */
   bool single_session;
 
+  /*! true if this interface is used for DLEP radio */
+  bool radio;
+
   /*! hook into session tree, interface name is the key */
   struct avl_node _node;
 
-  /*! tree of all radio sessions */
+  /*! tree of all sessions of same type (radio/router) on this interface */
   struct avl_tree session_tree;
 };
 
+struct avl_tree *dlep_if_get_tree(bool radio);
 int dlep_if_add(struct dlep_if *interf, const char *ifname,
     const struct oonf_layer2_origin *l2_origin,
     enum oonf_log_source log_src, bool radio);
index 7444c3c..0a9bd0a 100644 (file)
@@ -196,6 +196,58 @@ dlep_reader_ipv6_tlv(struct netaddr *ipv6, bool *add,
   return netaddr_from_binary(ipv6, &ptr[1], 16, AF_INET6);
 }
 
+/**
+ * Parse DLEP IPv4 subnet TLV
+ * @param ipv4 pointer to address storage
+ * @param add pointer to boolean for flag storage
+ * @param session dlep session
+ * @param value dlep value to parse, NULL for using the first
+ *   DLEP_IPV4_SUBNET_TLV value
+ * @return -1 if an error happened, 0 otherwise
+ */
+int
+dlep_reader_ipv4_subnet_tlv(struct netaddr *ipv4, bool *add,
+    struct dlep_session *session, struct dlep_parser_value *value) {
+  const uint8_t *ptr;
+
+  if (!value) {
+    value = dlep_session_get_tlv_value(session, DLEP_IPV4_SUBNET_TLV);
+    if (!value) {
+      return -1;
+    }
+  }
+
+  ptr = dlep_session_get_tlv_binary(session, value);
+  *add = (ptr[0] & DLEP_IP_ADD) == DLEP_IP_ADD;
+  return netaddr_from_binary(ipv4, &ptr[1], 4, AF_INET);
+}
+
+/**
+ * Parse DLEP IPv6 subnet TLV
+ * @param ipv6 pointer to address storage
+ * @param add pointer to boolean for flag storage
+ * @param session dlep session
+ * @param value dlep value to parse, NULL for using the first
+ *   DLEP_IPV6_SUBNET_TLV value
+ * @return -1 if an error happened, 0 otherwise
+ */
+int
+dlep_reader_ipv6_subnet_tlv(struct netaddr *ipv6, bool *add,
+    struct dlep_session *session, struct dlep_parser_value *value) {
+  const uint8_t *ptr;
+
+  if (!value) {
+    value = dlep_session_get_tlv_value(session, DLEP_IPV6_SUBNET_TLV);
+    if (!value) {
+      return -1;
+    }
+  }
+
+  ptr = dlep_session_get_tlv_binary(session, value);
+  *add = (ptr[0] & DLEP_IP_ADD) == DLEP_IP_ADD;
+  return netaddr_from_binary(ipv6, &ptr[1], 16, AF_INET6);
+}
+
 /**
  * Parse a DLEP IPv4 conpoint TLV
  * @param addr pointer to address storage
index f84e64f..635904a 100644 (file)
@@ -63,6 +63,10 @@ int dlep_reader_ipv4_tlv(struct netaddr *ipv4, bool *add,
     struct dlep_session *session, struct dlep_parser_value *value);
 int dlep_reader_ipv6_tlv(struct netaddr *ipv6, bool *add,
     struct dlep_session *session, struct dlep_parser_value *value);
+int dlep_reader_ipv4_subnet_tlv(struct netaddr *ipv6, bool *add,
+    struct dlep_session *session, struct dlep_parser_value *value);
+int dlep_reader_ipv6_subnet_tlv(struct netaddr *ipv6, bool *add,
+    struct dlep_session *session, struct dlep_parser_value *value);
 int dlep_reader_ipv4_conpoint_tlv(
     struct netaddr *addr, uint16_t *port, bool *tls,
     struct dlep_session *session, struct dlep_parser_value *value);
index 67e96de..1bd4fcd 100644 (file)
@@ -170,6 +170,7 @@ dlep_session_add(struct dlep_session *session, const char *l2_ifname,
 
   i = 0;
   avl_for_each_element( dlep_extension_get_tree(), ext, _node) {
+    OONF_DEBUG(session->log_source, "Add extension %d to session", ext->id);
     parser->extensions[i] = ext;
     i++;
   }
@@ -181,6 +182,8 @@ dlep_session_add(struct dlep_session *session, const char *l2_ifname,
     return -1;
   }
 
+  avl_init(&session->_ip_prefix_modification, avl_comp_netaddr, false);
+
   OONF_INFO(session->log_source, "Add session on %s",
       session->l2_listener.name);
   return 0;
@@ -231,9 +234,9 @@ dlep_session_terminate(struct dlep_session *session) {
   }
 
   dlep_session_generate_signal(
-      session, DLEP_PEER_TERMINATION, NULL);
+      session, DLEP_SESSION_TERMINATION, NULL);
   session->cb_send_buffer(session, 0);
-  session->restrict_signal = DLEP_PEER_TERMINATION_ACK;
+  session->restrict_signal = DLEP_SESSION_TERMINATION_ACK;
 }
 
 /**
@@ -305,12 +308,18 @@ dlep_session_process_tcp(struct oonf_stream_session *tcp_session,
       abuf_getptr(&tcp_session->in),
       abuf_getlen(&tcp_session->in), false);
 
-  OONF_DEBUG(session->log_source,
-      "Processed %" PRINTF_SSIZE_T_SPECIFIER " bytes", processed);
   if (processed < 0) {
+    /* session is most likely invalid now */
+    return STREAM_SESSION_CLEANUP;
+  }
+
+  if (session->restrict_signal == DLEP_KILL_SESSION) {
     return STREAM_SESSION_CLEANUP;
   }
 
+  OONF_DEBUG(session->log_source,
+    "Processed %" PRINTF_SSIZE_T_SPECIFIER " bytes", processed);
+
   abuf_pull(&tcp_session->in, processed);
 
   if (abuf_getlen(session->writer.out) > 0) {
@@ -359,6 +368,9 @@ dlep_session_process_buffer(
       break;
     }
 
+    if (session->restrict_signal == DLEP_KILL_SESSION) {
+      return offset;
+    }
     length -= result;
     offset += result;
   }
@@ -370,9 +382,10 @@ dlep_session_process_buffer(
  * @param session dlep session
  * @param ptr pointer to buffer with DLEP signal/message
  * @param length length of buffer
- * @return numberr of bytes parsed, 0 if an error happened
+ * @return number of bytes parsed, 0 if a generic error happened,
+ *   negative to return a parser result enum
  */
-size_t
+ssize_t
 dlep_session_process_signal(struct dlep_session *session,
     const void *ptr, size_t length, bool is_udp) {
   enum dlep_parser_error result;
@@ -436,6 +449,10 @@ dlep_session_process_signal(struct dlep_session *session,
   result = _process_tlvs(session,
       signal_type, signal_length, &buffer[4]);
 
+  if (result == DLEP_NEW_PARSER_TERMINDATED) {
+    /* session is now invalid, end parser */
+    return result;
+  }
   if (result != DLEP_NEW_PARSER_OKAY) {
     OONF_WARN(session->log_source, "Parser error: %d", result);
     _send_terminate(session);
@@ -478,6 +495,9 @@ dlep_session_add_local_neighbor(struct dlep_session *session,
   /* initialize backpointer */
   local->session = session;
 
+
+  avl_init(&local->_ip_prefix_modification, avl_comp_netaddr, false);
+
   return local;
 }
 
@@ -534,6 +554,30 @@ dlep_session_get_local_l2_neighbor(struct dlep_session *session,
   return l2neigh;
 }
 
+struct oonf_layer2_neigh *
+dlep_session_get_l2_from_neighbor(struct dlep_local_neighbor *dlep_neigh) {
+  struct oonf_layer2_neigh *l2neigh;
+  struct oonf_layer2_net *l2net;
+#ifdef OONF_LOG_INFO
+  struct netaddr_str nbuf;
+#endif
+
+  l2net = oonf_layer2_net_get(dlep_neigh->session->l2_listener.name);
+  if (!l2net) {
+    OONF_DEBUG(dlep_neigh->session->log_source, "Could not find l2net %s for new neighbor",
+        dlep_neigh->session->l2_listener.name);
+    return NULL;
+  }
+
+  l2neigh = oonf_layer2_neigh_get(l2net, &dlep_neigh->neigh_addr);
+  if (!l2neigh) {
+    OONF_INFO(dlep_neigh->session->log_source, "Could not find l2neigh "
+        "for neighbor %s", netaddr_to_string(&nbuf, &dlep_neigh->neigh_addr));
+    return NULL;
+  }
+  return l2neigh;
+}
+
 /**
  * Generate a DLEP signal/message
  * @param session dlep session
@@ -812,10 +856,10 @@ static void
 _send_terminate(struct dlep_session *session) {
   if (session->restrict_signal != DLEP_UDP_PEER_DISCOVERY
       && session->restrict_signal != DLEP_UDP_PEER_OFFER) {
-    dlep_session_generate_signal(session, DLEP_PEER_TERMINATION, NULL);
+    dlep_session_generate_signal(session, DLEP_SESSION_TERMINATION, NULL);
 
-    session->restrict_signal = DLEP_PEER_TERMINATION_ACK;
-    session->next_restrict_signal = DLEP_PEER_TERMINATION_ACK;
+    session->restrict_signal = DLEP_SESSION_TERMINATION_ACK;
+    session->next_restrict_signal = DLEP_SESSION_TERMINATION_ACK;
   }
 }
 
index 4073803..6b78d06 100644 (file)
@@ -68,29 +68,32 @@ enum dlep_parser_error {
   /*! parsing successful */
   DLEP_NEW_PARSER_OKAY                  =  0,
 
+  /*! Signal terminates session, session is now invalid! */
+  DLEP_NEW_PARSER_TERMINDATED           = -1,
+
   /*! signal too short, incomplete TLV header */
-  DLEP_NEW_PARSER_INCOMPLETE_TLV_HEADER = -1,
+  DLEP_NEW_PARSER_INCOMPLETE_TLV_HEADER = -2,
 
   /*! signal too short, incomplete TLV */
-  DLEP_NEW_PARSER_INCOMPLETE_TLV        = -2,
+  DLEP_NEW_PARSER_INCOMPLETE_TLV        = -3,
 
   /*! TLV type is not supported by session */
-  DLEP_NEW_PARSER_UNSUPPORTED_TLV       = -3,
+  DLEP_NEW_PARSER_UNSUPPORTED_TLV       = -4,
 
   /*! TLV length is not supported */
-  DLEP_NEW_PARSER_ILLEGAL_TLV_LENGTH    = -4,
+  DLEP_NEW_PARSER_ILLEGAL_TLV_LENGTH    = -5,
 
   /*! mandatory TLV is missing */
-  DLEP_NEW_PARSER_MISSING_MANDATORY_TLV = -5,
+  DLEP_NEW_PARSER_MISSING_MANDATORY_TLV = -6,
 
   /*! this TLV must not be used more than once */
-  DLEP_NEW_PARSER_DUPLICATE_TLV         = -6,
+  DLEP_NEW_PARSER_DUPLICATE_TLV         = -7,
 
   /*! out of memory error */
-  DLEP_NEW_PARSER_OUT_OF_MEMORY         = -7,
+  DLEP_NEW_PARSER_OUT_OF_MEMORY         = -8,
 
   /*! internal parser error, inconsistent data structures */
-  DLEP_NEW_PARSER_INTERNAL_ERROR        = -8,
+  DLEP_NEW_PARSER_INTERNAL_ERROR        = -9,
 };
 
 /**
@@ -209,6 +212,9 @@ struct dlep_local_neighbor {
   /*! true if the neighbor changes since the last update */
   bool changed;
 
+  /*! true if iterative updates are be used for destination IPs */
+  bool destination_ip_iterative;
+
   /*! mac address of the neighbors wireless interface */
   struct netaddr neigh_addr;
 
@@ -218,7 +224,10 @@ struct dlep_local_neighbor {
   /*! timeout for acknowledgement signal */
   struct oonf_timer_instance _ack_timeout;
 
-  /*! hook into the sessions treee of neighbors */
+  /*! tree of modifications which should be put into the next destination update */
+  struct avl_tree _ip_prefix_modification;
+
+  /*! hook into the sessions tree of neighbors */
   struct avl_node _node;
 };
 
@@ -242,6 +251,17 @@ struct dlep_session_config {
   bool send_proxied;
 };
 
+/**
+ * Records the state of the peer regarding PEER UPDATE messages
+ */
+enum dlep_peer_state {
+  DLEP_PEER_WAIT_FOR_INIT,
+  DLEP_PEER_WAIT_FOR_UPDATE_ACK,
+  DLEP_PEER_SEND_UPDATE,
+  DLEP_PEER_IDLE,
+  DLEP_PEER_TERMINATED,
+};
+
 /**
  * Generic DLEP session, might be radio or router
  */
@@ -298,6 +318,15 @@ struct dlep_session {
   /*! remote endpoint of current communication */
   union netaddr_socket remote_socket;
 
+  /*! timeout for acknowledgement signal */
+  struct oonf_timer_instance _ack_timeout;
+
+  /*! true if we cannot send a peer update at the moment */
+  enum dlep_peer_state _peer_state;
+
+  /*! tree of modifications which should be put into the next peer update */
+  struct avl_tree _ip_prefix_modification;
+
   /*! tree of all dlep sessions of an interface */
   struct avl_node _node;
 };
@@ -317,7 +346,7 @@ enum oonf_stream_session_state dlep_session_process_tcp(
     struct dlep_session *session);
 ssize_t dlep_session_process_buffer(
     struct dlep_session *session, const void *buffer, size_t length, bool is_udp);
-size_t dlep_session_process_signal(struct dlep_session *session,
+ssize_t dlep_session_process_signal(struct dlep_session *session,
     const void *buffer, size_t length, bool is_udp);
 int dlep_session_generate_signal(struct dlep_session *session,
     int32_t signal, const struct netaddr *neighbor);
@@ -333,6 +362,8 @@ void dlep_session_remove_local_neighbor(
     struct dlep_session *session, struct dlep_local_neighbor *local);
 struct oonf_layer2_neigh *dlep_session_get_local_l2_neighbor(
     struct dlep_session *session, const struct netaddr *neigh);
+struct oonf_layer2_neigh *dlep_session_get_l2_from_neighbor(
+    struct dlep_local_neighbor *dlep_neigh);
 
 /**
  * get the dlep session tlv
index b62b63e..30cc61e 100644 (file)
@@ -205,47 +205,46 @@ dlep_writer_add_mac_tlv(struct dlep_writer *writer,
 }
 
 /**
- * Write a DLEP IPv4 address TLV
+ * Write a DLEP IPv4/IPv6 address/subnet TLV
  * @param writer dlep writer
- * @param ipv4 IPv4 address
+ * @param ip IPv4 address
  * @param add true if address should be added, false to remove it
  */
-void
-dlep_writer_add_ipv4_tlv(struct dlep_writer *writer,
-    const struct netaddr *ipv4, bool add) {
-  uint8_t value[5];
-
-  if (netaddr_get_address_family(ipv4) != AF_INET) {
-    return;
-  }
+int
+dlep_writer_add_ip_tlv(struct dlep_writer *writer,
+    const struct netaddr *ip, bool add) {
+  uint8_t value[18];
 
   value[0] = add ? DLEP_IP_ADD : DLEP_IP_REMOVE;
-  netaddr_to_binary(&value[1], ipv4, 4);
-
-  dlep_writer_add_tlv(writer,
-      DLEP_IPV4_ADDRESS_TLV, value, sizeof(value));
-}
-
-/**
- * Write a DLEP IPv6 address TLV
- * @param writer dlep writer
- * @param ipv6 IPv6 address
- * @param add true if address should be added, false to remove it
- */
-void
-dlep_writer_add_ipv6_tlv(struct dlep_writer *writer,
-    const struct netaddr *ipv6, bool add) {
-  uint8_t value[17];
-
-  if (netaddr_get_address_family(ipv6) != AF_INET6) {
-    return;
+  netaddr_to_binary(&value[1], ip, 16);
+
+  switch (netaddr_get_address_family(ip)) {
+    case AF_INET:
+      value[5] = netaddr_get_prefix_length(ip);
+      if (value[5] != 32) {
+        dlep_writer_add_tlv(writer,
+            DLEP_IPV4_SUBNET_TLV, value, 6);
+      }
+      else {
+        dlep_writer_add_tlv(writer,
+            DLEP_IPV4_ADDRESS_TLV, value, 5);
+      }
+      break;
+    case AF_INET6:
+      value[17] = netaddr_get_prefix_length(ip);
+      if (value[17] != 128) {
+        dlep_writer_add_tlv(writer,
+            DLEP_IPV6_SUBNET_TLV, value, 18);
+      }
+      else {
+        dlep_writer_add_tlv(writer,
+            DLEP_IPV6_ADDRESS_TLV, value, 17);
+      }
+      break;
+    default:
+      return -1;
   }
-
-  value[0] = add ? DLEP_IP_ADD : DLEP_IP_REMOVE;
-  netaddr_to_binary(&value[1], ipv6, 16);
-
-  dlep_writer_add_tlv(writer,
-      DLEP_IPV6_ADDRESS_TLV, value, sizeof(value));
+  return 0;
 }
 
 /**
index a9d4c92..4eb7cd4 100644 (file)
@@ -69,10 +69,8 @@ void dlep_writer_add_peer_type_tlv(struct dlep_writer *writer,
     const char *peer_type, bool access_control);
 int dlep_writer_add_mac_tlv(struct dlep_writer *writer,
     const struct netaddr *mac);
-void dlep_writer_add_ipv4_tlv(struct dlep_writer *writer,
+int dlep_writer_add_ip_tlv(struct dlep_writer *writer,
     const struct netaddr *ipv4, bool add);
-void dlep_writer_add_ipv6_tlv(struct dlep_writer *writer,
-    const struct netaddr *ipv6, bool add);
 void dlep_writer_add_ipv4_conpoint_tlv(struct dlep_writer *writer,
     const struct netaddr *addr, uint16_t port, bool tls);
 void dlep_writer_add_ipv6_conpoint_tlv(struct dlep_writer *writer,
diff --git a/src-plugins/generic/dlep/ext_base_ip/ip.c b/src-plugins/generic/dlep/ext_base_ip/ip.c
new file mode 100644 (file)
index 0000000..e4e80ff
--- /dev/null
@@ -0,0 +1,478 @@
+
+/*
+ * 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 "ip.h"
+
+#include "common/common_types.h"
+#include "common/avl.h"
+#include "common/autobuf.h"
+#include "subsystems/oonf_layer2.h"
+#include "subsystems/oonf_timer.h"
+
+#include "dlep/dlep_iana.h"
+#include "dlep/dlep_extension.h"
+#include "dlep/dlep_interface.h"
+#include "dlep/dlep_reader.h"
+#include "dlep/dlep_writer.h"
+
+struct _prefix_storage {
+  struct netaddr prefix;
+
+  bool add;
+
+  struct avl_node _node;
+};
+
+static void _cleanup_session(struct dlep_session *);
+static int _radio_write_session_update(struct dlep_extension *ext,
+    struct dlep_session *session, const struct netaddr *neigh);
+static int _radio_write_destination_update(struct dlep_extension *ext,
+    struct dlep_session *session, const struct netaddr *neigh);
+static enum dlep_parser_error _router_process_session_update(
+    struct dlep_extension *ext, struct dlep_session *session);
+static enum dlep_parser_error _router_process_destination_update(
+    struct dlep_extension *ext, struct dlep_session *session);
+
+static void _cb_add_if_ip(void *ptr);
+static void _cb_remove_if_ip(void *ptr);
+static void _cb_add_neigh_ip(void *ptr);
+static void _cb_remove_neigh_ip(void *ptr);
+
+/* peer initialization ack/peer update/destination update */
+static const uint16_t _ip_tlvs[] = {
+    DLEP_IPV4_ADDRESS_TLV,
+    DLEP_IPV4_SUBNET_TLV,
+    DLEP_IPV6_ADDRESS_TLV,
+    DLEP_IPV6_SUBNET_TLV,
+};
+
+/* supported signals of this extension */
+static struct dlep_extension_signal _signals[] = {
+    {
+        .id = DLEP_SESSION_UPDATE,
+        .supported_tlvs = _ip_tlvs,
+        .supported_tlv_count = ARRAYSIZE(_ip_tlvs),
+        .add_radio_tlvs = _radio_write_session_update,
+        .process_router = _router_process_session_update,
+    },
+    {
+        .id = DLEP_DESTINATION_UPDATE,
+        .supported_tlvs = _ip_tlvs,
+        .supported_tlv_count = ARRAYSIZE(_ip_tlvs),
+        .add_radio_tlvs = _radio_write_destination_update,
+        .process_router = _router_process_destination_update,
+    },
+};
+
+/* supported TLVs of this extension */
+static struct dlep_extension_tlv _tlvs[] = {
+    { DLEP_MAC_ADDRESS_TLV, 6,8 },
+    { DLEP_IPV4_ADDRESS_TLV, 5,5 },
+    { DLEP_IPV4_SUBNET_TLV, 6,6 },
+    { DLEP_IPV6_ADDRESS_TLV, 17,17 },
+    { DLEP_IPV6_SUBNET_TLV, 18,18 },
+};
+
+/* DLEP base extension, radio side */
+static struct dlep_extension _base_ip = {
+  .id = DLEP_EXTENSION_BASE_IP,
+  .name = "base metric",
+
+  .signals = _signals,
+  .signal_count = ARRAYSIZE(_signals),
+  .tlvs = _tlvs,
+  .tlv_count = ARRAYSIZE(_tlvs),
+
+  .cb_session_cleanup_radio = _cleanup_session,
+  .cb_session_cleanup_router = _cleanup_session,
+};
+
+static struct oonf_class _prefix_class = {
+  .name = "dlep ip prefix",
+  .size = sizeof(struct _prefix_storage),
+};
+
+static struct oonf_class_extension _l2_interface_ip_listener = {
+  .ext_name = "dlep l2 if-ip",
+  .class_name = LAYER2_CLASS_NETWORK_ADDRESS,
+
+  .cb_add = _cb_add_if_ip,
+  .cb_remove = _cb_remove_if_ip,
+};
+
+static struct oonf_class_extension _l2_neighbor_ip_listener = {
+  .ext_name = "dlep l2 neigh-ip",
+  .class_name = LAYER2_CLASS_NEIGHBOR_ADDRESS,
+
+  .cb_add = _cb_add_neigh_ip,
+  .cb_remove = _cb_remove_neigh_ip,
+};
+
+/**
+ * Initialize the base metric DLEP extension
+ * @return this extension
+ */
+struct dlep_extension *
+dlep_base_ip_init(void) {
+  dlep_extension_add(&_base_ip);
+  oonf_class_add(&_prefix_class);
+  oonf_class_extension_add(&_l2_interface_ip_listener);
+  oonf_class_extension_add(&_l2_neighbor_ip_listener);
+
+  return &_base_ip;
+}
+
+void
+dlep_base_ip_cleanup(void) {
+  oonf_class_extension_remove(&_l2_neighbor_ip_listener);
+  oonf_class_extension_remove(&_l2_interface_ip_listener);
+  oonf_class_remove(&_prefix_class);
+}
+
+static
+void _cleanup_session(struct dlep_session *session) {
+  struct dlep_local_neighbor *l2neigh;
+  struct _prefix_storage *storage, *storage_it;
+
+  /* remove all stored changes for neighbors */
+  avl_for_each_element(&session->local_neighbor_tree, l2neigh, _node) {
+    avl_for_each_element_safe(&l2neigh->_ip_prefix_modification, storage, _node, storage_it) {
+      avl_remove(&l2neigh->_ip_prefix_modification, &storage->_node);
+      oonf_class_free(&_prefix_class, storage);
+    }
+  }
+
+  /* remove all stored changes for the local peer */
+  avl_for_each_element_safe(&session->_ip_prefix_modification, storage, _node, storage_it) {
+    avl_remove(&session->_ip_prefix_modification, &storage->_node);
+    oonf_class_free(&_prefix_class, storage);
+  }
+}
+
+static int
+_radio_write_session_update(struct dlep_extension *ext __attribute__((unused)),
+    struct dlep_session *session, const struct netaddr *neigh __attribute__((unused))) {
+  struct _prefix_storage *storage, *storage_it;
+
+  struct netaddr_str nbuf;
+
+  avl_for_each_element(&session->_ip_prefix_modification, storage, _node) {
+    if (dlep_writer_add_ip_tlv(&session->writer, &storage->prefix, storage->add)) {
+        OONF_WARN(session->log_source, "Cannot add '%s' (%s) to session update",
+            netaddr_to_string(&nbuf, &storage->prefix),
+            storage->add ? "add" : "remove");
+        return -1;
+    }
+  }
+
+  /* no error, now remove elements from temporary storage */
+  avl_for_each_element_safe(&session->_ip_prefix_modification, storage, _node, storage_it) {
+    avl_remove(&session->_ip_prefix_modification, &storage->_node);
+    oonf_class_free(&_prefix_class, storage);
+  }
+  return 0;
+}
+
+static int
+_radio_write_destination_update(struct dlep_extension *ext __attribute__((unused)),
+    struct dlep_session *session, const struct netaddr *neigh) {
+  struct dlep_local_neighbor *dlep_neigh;
+  struct _prefix_storage *storage, *storage_it;
+
+  struct netaddr_str nbuf;
+
+  dlep_neigh = dlep_session_get_local_neighbor(session, neigh);
+  if (!dlep_neigh) {
+    OONF_WARN(session->log_source, "Could not find dlep_neighbor "
+        "for neighbor %s", netaddr_to_string(&nbuf, neigh));
+    return -1;
+  }
+
+  /* send every attached IP towards the router */
+  avl_for_each_element(&dlep_neigh->_ip_prefix_modification, storage, _node) {
+    if (dlep_writer_add_ip_tlv(&session->writer, &storage->prefix, storage->add)) {
+      OONF_WARN(session->log_source, "Cannot add '%s' (%s) to destination update",
+          netaddr_to_string(&nbuf, &storage->prefix),
+          storage->add ? "add" : "remove");
+      return -1;
+    }
+  }
+
+  /* no error, now remove elements from temporary storage */
+  avl_for_each_element_safe(&dlep_neigh->_ip_prefix_modification, storage, _node, storage_it) {
+    avl_remove(&dlep_neigh->_ip_prefix_modification, &storage->_node);
+    oonf_class_free(&_prefix_class, storage);
+  }
+  return 0;
+}
+
+static void
+_process_session_ip_tlvs(const struct oonf_layer2_origin *origin,
+    struct oonf_layer2_net *l2net, struct netaddr *ip, bool add) {
+  struct oonf_layer2_peer_address *l2addr;
+
+  if (add) {
+    oonf_layer2_net_add_ip(l2net, origin, ip);
+  }
+  else if ((l2addr = oonf_layer2_net_get_ip(l2net, ip))){
+    oonf_layer2_net_remove_ip(l2addr, origin);
+  }
+}
+
+static enum dlep_parser_error
+_router_process_session_update(struct dlep_extension *ext __attribute((unused)),
+    struct dlep_session *session) {
+  struct oonf_layer2_net *l2net;
+  struct netaddr ip;
+  struct dlep_parser_value *value;
+  bool add_ip;
+
+  l2net = oonf_layer2_net_get(session->l2_listener.name);
+  if (!l2net) {
+    return 0;
+  }
+
+  /* ipv4 address */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV4_ADDRESS_TLV);
+  while (value) {
+    if (dlep_reader_ipv4_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_session_ip_tlvs(session->l2_origin, l2net, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+
+  /* ipv6 address */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV6_ADDRESS_TLV);
+  while (value) {
+    if (dlep_reader_ipv6_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_session_ip_tlvs(session->l2_origin, l2net, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+
+  /* ipv4 subnet */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV4_SUBNET_TLV);
+  while (value) {
+    if (dlep_reader_ipv4_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_session_ip_tlvs(session->l2_origin, l2net, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+
+  /* ipv6 subnet */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV6_SUBNET_TLV);
+  while (value) {
+    if (dlep_reader_ipv4_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_session_ip_tlvs(session->l2_origin, l2net, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+  return 0;
+}
+
+static void
+_process_destination_ip_tlv(const struct oonf_layer2_origin *origin,
+    struct oonf_layer2_neigh *l2neigh, struct netaddr *ip, bool add) {
+  struct oonf_layer2_neighbor_address *l2addr;
+
+  if (add) {
+    oonf_layer2_neigh_add_ip(l2neigh, origin, ip);
+  }
+  else if ((l2addr = oonf_layer2_neigh_get_ip(l2neigh, ip))){
+    oonf_layer2_neigh_remove_ip(l2addr, origin);
+  }
+}
+
+static enum dlep_parser_error
+_router_process_destination_update(struct dlep_extension *ext __attribute((unused)),
+    struct dlep_session *session) {
+  struct oonf_layer2_net *l2net;
+  struct oonf_layer2_neigh *l2neigh;
+  struct netaddr mac, ip;
+  struct dlep_parser_value *value;
+  bool add_ip;
+
+  if (dlep_reader_mac_tlv(&mac, session, NULL)) {
+    OONF_INFO(session->log_source, "mac tlv missing");
+    return -1;
+  }
+
+  l2net = oonf_layer2_net_get(session->l2_listener.name);
+  if (!l2net) {
+    return 0;
+  }
+  l2neigh = oonf_layer2_neigh_add(l2net, &mac);
+  if (!l2neigh) {
+    return 0;
+  }
+
+  /* ipv4 address */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV4_ADDRESS_TLV);
+  while (value) {
+    if (dlep_reader_ipv4_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_destination_ip_tlv(session->l2_origin, l2neigh, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+
+  /* ipv6 address */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV6_ADDRESS_TLV);
+  while (value) {
+    if (dlep_reader_ipv6_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_destination_ip_tlv(session->l2_origin, l2neigh, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+
+  /* ipv4 subnet */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV4_SUBNET_TLV);
+  while (value) {
+    if (dlep_reader_ipv4_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_destination_ip_tlv(session->l2_origin, l2neigh, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+
+  /* ipv6 subnet */
+  value = dlep_session_get_tlv_value(session, DLEP_IPV6_SUBNET_TLV);
+  while (value) {
+    if (dlep_reader_ipv4_tlv(&ip, &add_ip, session, value)) {
+      return -1;
+    }
+    _process_destination_ip_tlv(session->l2_origin, l2neigh, &ip, add_ip);
+    value = dlep_session_get_next_tlv_value(session, value);
+  }
+  return 0;
+}
+
+static void
+_add_prefix(struct avl_tree *tree, struct netaddr *addr, bool add) {
+  struct _prefix_storage *storage;
+
+  storage = avl_find_element(tree, addr, storage, _node);
+  if (storage) {
+    storage->add = add;
+    return;
+  }
+
+  storage = oonf_class_malloc(&_prefix_class);
+  if (!storage) {
+    return;
+  }
+
+  /* copy key and put into tree */
+  memcpy(&storage->prefix, addr, sizeof(*addr));
+  storage->_node.key = &storage->prefix;
+  avl_insert(tree, &storage->_node);
+
+  storage->add = add;
+}
+
+static void
+_modify_if_ip(const char *if_name, struct netaddr *prefix, bool add) {
+  struct dlep_if *dlep_interface;
+  struct dlep_session *session;
+
+  avl_for_each_element(dlep_if_get_tree(true), dlep_interface, _node) {
+    if (strcmp(dlep_interface->l2_ifname, if_name) == 0) {
+      avl_for_each_element(&dlep_interface->session_tree, session, _node) {
+        _add_prefix(&session->_ip_prefix_modification, prefix, add);
+      }
+    }
+  }
+}
+
+static void
+_cb_add_if_ip(void *ptr){
+  struct oonf_layer2_peer_address *peer_ip = ptr;
+  _modify_if_ip(peer_ip->l2net->name, &peer_ip->ip, true);
+}
+
+static void
+_cb_remove_if_ip(void *ptr) {
+  struct oonf_layer2_peer_address *peer_ip = ptr;
+  _modify_if_ip(peer_ip->l2net->name, &peer_ip->ip, false);
+}
+
+static void
+_modify_neigh_ip(const char *if_name, struct netaddr *neighbor,
+    struct netaddr *prefix, bool add) {
+  struct dlep_if *dlep_interface;
+  struct dlep_local_neighbor *dlep_neighbor;
+  struct dlep_session *session;
+
+  avl_for_each_element(dlep_if_get_tree(true), dlep_interface, _node) {
+    if (strcmp(dlep_interface->l2_ifname, if_name) == 0) {
+      avl_for_each_element(&dlep_interface->session_tree, session, _node) {
+        dlep_neighbor = dlep_session_get_local_neighbor(session, neighbor);
+        if (dlep_neighbor) {
+          _add_prefix(&dlep_neighbor->_ip_prefix_modification, prefix, add);
+        }
+      }
+    }
+  }
+}
+
+static void
+_cb_add_neigh_ip(void *ptr) {
+  struct oonf_layer2_neighbor_address *neigh_ip = ptr;
+  _modify_neigh_ip(neigh_ip->l2neigh->network->name,
+      &neigh_ip->l2neigh->addr, &neigh_ip->ip, true);
+}
+
+static void
+_cb_remove_neigh_ip(void *ptr) {
+  struct oonf_layer2_neighbor_address *neigh_ip = ptr;
+  _modify_neigh_ip(neigh_ip->l2neigh->network->name,
+      &neigh_ip->l2neigh->addr, &neigh_ip->ip, false);
+}
diff --git a/src-plugins/generic/dlep/ext_base_ip/ip.h b/src-plugins/generic/dlep/ext_base_ip/ip.h
new file mode 100644 (file)
index 0000000..bab064d
--- /dev/null
@@ -0,0 +1,58 @@
+
+/*
+ * 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_IP_H_
+#define _DLEP_IP_H_
+
+#include "common/common_types.h"
+#include "common/netaddr.h"
+
+#include "dlep/dlep_extension.h"
+#include "dlep/dlep_session.h"
+
+struct dlep_extension *dlep_base_ip_init(void);
+void dlep_base_ip_cleanup(void);
+
+#endif /* _DLEP_IP_H_ */
diff --git a/src-plugins/generic/dlep/ext_base_ip/ip_radio.c b/src-plugins/generic/dlep/ext_base_ip/ip_radio.c
new file mode 100644 (file)
index 0000000..ec06bec
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * ip_radio.c
+ *
+ *  Created on: 23.08.2017
+ *      Author: rogge
+ */
+
+
diff --git a/src-plugins/generic/dlep/ext_base_ip/ip_radio.h b/src-plugins/generic/dlep/ext_base_ip/ip_radio.h
new file mode 100644 (file)
index 0000000..6bbd491
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * ip_radio.h
+ *
+ *  Created on: 23.08.2017
+ *      Author: rogge
+ */
+
+#ifndef _DLEP_IP_RADIO_H_
+#define _DLEP_IP_RADIO_H_
+
+
+
+#endif /* _DLEP_IP_RADIO_H_ */
diff --git a/src-plugins/generic/dlep/ext_base_ip/ip_router.c b/src-plugins/generic/dlep/ext_base_ip/ip_router.c
new file mode 100644 (file)
index 0000000..a56487a
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * ip_router.c
+ *
+ *  Created on: 23.08.2017
+ *      Author: rogge
+ */
+
+
diff --git a/src-plugins/generic/dlep/ext_base_ip/ip_router.h b/src-plugins/generic/dlep/ext_base_ip/ip_router.h
new file mode 100644 (file)
index 0000000..29d918b
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * ip_router.h
+ *
+ *  Created on: 23.08.2017
+ *      Author: rogge
+ */
+
+#ifndef _DLEP_IP_ROUTER_H_
+#define _DLEP_IP_ROUTER_H_
+
+
+
+#endif /* _DLEP_IP_ROUTER_H_ */
index eac922f..c4d151b 100644 (file)
@@ -112,15 +112,15 @@ static struct dlep_extension_signal _signals[] = {
         .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_peer_init_ack,
-        .process_router = dlep_extension_router_process_peer_init_ack,
+        .add_radio_tlvs = dlep_extension_radio_write_session_init_ack,
+        .process_router = dlep_extension_router_process_session_init_ack,
     },
     {
-        .id = DLEP_PEER_UPDATE,
+        .id = DLEP_SESSION_UPDATE,
         .supported_tlvs = _peer_update_tlvs,
         .supported_tlv_count = ARRAYSIZE(_peer_update_tlvs),
-        .add_radio_tlvs = dlep_extension_radio_write_peer_update,
-        .process_router = dlep_extension_router_process_peer_update,
+        .add_radio_tlvs = dlep_extension_radio_write_session_update,
+        .process_router = dlep_extension_router_process_session_update,
     },
     {
         .id = DLEP_DESTINATION_UP,
index 629738b..f9f4dda 100644 (file)
@@ -231,24 +231,24 @@ static struct dlep_extension_signal _signals[] = {
         .mandatory_tlv_count = ARRAYSIZE(_session_initack_mandatory),
     },
     {
-        .id = DLEP_PEER_UPDATE,
+        .id = DLEP_SESSION_UPDATE,
         .supported_tlvs = _peer_update_tlvs,
         .supported_tlv_count = ARRAYSIZE(_peer_update_tlvs),
         .duplicate_tlvs = _peer_update_duplicates,
         .duplicate_tlv_count = ARRAYSIZE(_peer_update_duplicates),
     },
     {
-        .id = DLEP_PEER_UPDATE_ACK,
+        .id = DLEP_SESSION_UPDATE_ACK,
         .supported_tlvs = _peer_updateack_tlvs,
         .supported_tlv_count = ARRAYSIZE(_peer_updateack_tlvs),
     },
     {
-        .id = DLEP_PEER_TERMINATION,
+        .id = DLEP_SESSION_TERMINATION,
         .supported_tlvs = _peer_termination_tlvs,
         .supported_tlv_count = ARRAYSIZE(_peer_termination_tlvs),
     },
     {
-        .id = DLEP_PEER_TERMINATION_ACK,
+        .id = DLEP_SESSION_TERMINATION_ACK,
         .supported_tlvs = _peer_terminationack_tlvs,
         .supported_tlv_count = ARRAYSIZE(_peer_terminationack_tlvs),
     },
@@ -319,10 +319,6 @@ static struct dlep_extension_tlv _tlvs[] = {
     { DLEP_HEARTBEAT_INTERVAL_TLV, 4,4 },
     { DLEP_EXTENSIONS_SUPPORTED_TLV, 2, 65534 },
     { DLEP_MAC_ADDRESS_TLV, 6,8 },
-    { DLEP_IPV4_ADDRESS_TLV, 5,5 },
-    { DLEP_IPV6_ADDRESS_TLV, 17,17 },
-    { DLEP_IPV4_SUBNET_TLV, 5,5 },
-    { DLEP_IPV6_SUBNET_TLV, 17,17 },
     { DLEP_MDRR_TLV, 8,8 },
     { DLEP_MDRT_TLV, 8,8 },
     { DLEP_CDRR_TLV, 8,8 },
@@ -502,12 +498,13 @@ dlep_base_proto_print_peer_type(struct dlep_session *session) {
  * @return -1 if an error happened, 0 otherwise
  */
 int
-dlep_base_proto_process_peer_termination(
+dlep_base_proto_process_session_termination(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
   dlep_base_proto_print_status(session);
 
-  return dlep_session_generate_signal(session, DLEP_PEER_TERMINATION_ACK, NULL);
+  session->_peer_state = DLEP_PEER_TERMINATED;
+  return dlep_session_generate_signal(session, DLEP_SESSION_TERMINATION_ACK, NULL);
 }
 
 /**
@@ -517,12 +514,10 @@ dlep_base_proto_process_peer_termination(
  * @return -1 if an error happened, 0 otherwise
  */
 int
-dlep_base_proto_process_peer_termination_ack(
+dlep_base_proto_process_session_termination_ack(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
-  if (session->cb_end_session) {
-    session->cb_end_session(session);
-  }
+  session->restrict_signal = DLEP_KILL_SESSION;
   return 0;
 }
 
@@ -583,7 +578,7 @@ _cb_remote_heartbeat(struct oonf_timer_instance *ptr) {
 
   session = container_of(ptr, struct dlep_session, remote_heartbeat_timeout);
 
-  if (session->restrict_signal == DLEP_PEER_TERMINATION_ACK) {
+  if (session->restrict_signal == DLEP_SESSION_TERMINATION_ACK) {
     /* peer termination ACK is missing! */
 
     /* stop local heartbeats */
index 86a8f18..dcc07c1 100644 (file)
@@ -58,9 +58,9 @@ void dlep_base_proto_start_remote_heartbeat(struct dlep_session *session);
 void dlep_base_proto_stop_timers(struct dlep_session *session);
 enum dlep_status dlep_base_proto_print_status(struct dlep_session *session);
 void dlep_base_proto_print_peer_type(struct dlep_session *session);
-int dlep_base_proto_process_peer_termination(
+int dlep_base_proto_process_session_termination(
     struct dlep_extension *, struct dlep_session *);
-int dlep_base_proto_process_peer_termination_ack(
+int dlep_base_proto_process_session_termination_ack(
     struct dlep_extension *, struct dlep_session *);
 int dlep_base_proto_process_heartbeat(
     struct dlep_extension *, struct dlep_session *);
index b9da398..591367a 100644 (file)
@@ -66,14 +66,11 @@ static void _cb_init_radio(struct dlep_session *);
 static void _cb_cleanup_radio(struct dlep_session *);
 
 static int _radio_process_peer_discovery(struct dlep_extension *, struct dlep_session *);
-static int _radio_process_peer_init(struct dlep_extension *, struct dlep_session *);
-static int _radio_process_peer_update(struct dlep_extension *, struct dlep_session *);
-static int _radio_process_peer_update_ack(struct dlep_extension *, struct dlep_session *);
-static int _radio_process_destination_up(struct dlep_extension *, struct dlep_session *);
+static int _radio_process_session_init(struct dlep_extension *, struct dlep_session *);
+static int _radio_process_session_update(struct dlep_extension *, struct dlep_session *);
+static int _radio_process_session_update_ack(struct dlep_extension *, struct dlep_session *);
 static int _radio_process_destination_up_ack(struct dlep_extension *, struct dlep_session *);
-static int _radio_process_destination_down(struct dlep_extension *, struct dlep_session *);
 static int _radio_process_destination_down_ack(struct dlep_extension *, struct dlep_session *);
-static int _radio_process_destination_update(struct dlep_extension *, struct dlep_session *);
 static int _radio_process_link_char_request(struct dlep_extension *, struct dlep_session *);
 
 static int _radio_write_peer_offer(struct dlep_extension *,
@@ -107,51 +104,46 @@ static struct dlep_extension_implementation _radio_signals[] = {
     },
     {
         .id = DLEP_SESSION_INITIALIZATION,
-        .process = _radio_process_peer_init,
+        .process = _radio_process_session_init,
     },
     {
         .id = DLEP_SESSION_INITIALIZATION_ACK,
         .add_tlvs = _radio_write_session_init_ack,
     },
     {
-        .id = DLEP_PEER_UPDATE,
-        .process = _radio_process_peer_update,
+        .id = DLEP_SESSION_UPDATE,
+        .process = _radio_process_session_update,
     },
     {
-        .id = DLEP_PEER_UPDATE_ACK,
-        .process = _radio_process_peer_update_ack,
+        .id = DLEP_SESSION_UPDATE_ACK,
+        .process = _radio_process_session_update_ack,
     },
     {
-        .id = DLEP_PEER_TERMINATION,
-        .process = dlep_base_proto_process_peer_termination,
+        .id = DLEP_SESSION_TERMINATION,
+        .process = dlep_base_proto_process_session_termination,
     },
     {
-        .id = DLEP_PEER_TERMINATION_ACK,
-        .process = dlep_base_proto_process_peer_termination_ack,
+        .id = DLEP_SESSION_TERMINATION_ACK,
+        .process = dlep_base_proto_process_session_termination_ack,
     },
     {
         .id = DLEP_DESTINATION_UP,
-        .process = _radio_process_destination_up,
         .add_tlvs = dlep_base_proto_write_mac_only,
     },
     {
         .id = DLEP_DESTINATION_UP_ACK,
         .process = _radio_process_destination_up_ack,
-        .add_tlvs = dlep_base_proto_write_mac_only,
     },
     {
         .id = DLEP_DESTINATION_DOWN,
-        .process = _radio_process_destination_down,
         .add_tlvs = dlep_base_proto_write_mac_only,
     },
     {
         .id = DLEP_DESTINATION_DOWN_ACK,
         .process = _radio_process_destination_down_ack,
-        .add_tlvs = dlep_base_proto_write_mac_only,
     },
     {
         .id = DLEP_DESTINATION_UPDATE,
-        .process = _radio_process_destination_update,
         .add_tlvs = dlep_base_proto_write_mac_only,
     },
     {
@@ -249,7 +241,7 @@ _radio_process_peer_discovery(
  * @return -1 if an error happened, 0 otherwise
  */
 static int
-_radio_process_peer_init(
+_radio_process_session_init(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
   struct oonf_layer2_net *l2net;
@@ -321,7 +313,7 @@ _radio_process_peer_init(
     }
   }
   session->next_restrict_signal = DLEP_ALL_SIGNALS;
-
+  session->_peer_state = DLEP_PEER_IDLE;
   return 0;
 }
 
@@ -332,11 +324,11 @@ _radio_process_peer_init(
  * @return -1 if an error happened, 0 otherwise
  */
 static int
-_radio_process_peer_update(
+_radio_process_session_update(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
   /* we don't support IP address exchange with the router at the moment */
-  return dlep_session_generate_signal(session, DLEP_PEER_UPDATE_ACK, NULL);
+  return dlep_session_generate_signal(session, DLEP_SESSION_UPDATE_ACK, NULL);
 }
 
 /**
@@ -346,32 +338,21 @@ _radio_process_peer_update(
  * @return always 0
  */
 static int
-_radio_process_peer_update_ack(
+_radio_process_session_update_ack(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
   dlep_base_proto_print_status(session);
-  return 0;
-}
-
-/**
- * Process the destination up message
- * @param ext (this) dlep extension
- * @param session dlep session
- * @return -1 if an error happened, 0 otherwise
- */
-static int
-_radio_process_destination_up(
-    struct dlep_extension *ext __attribute__((unused)),
-    struct dlep_session *session) {
-  struct netaddr mac;
-  if (dlep_reader_mac_tlv(&mac, session, NULL)) {
-    OONF_INFO(session->log_source, "No mac TLV found");
-    return -1;
+  if (session->_peer_state == DLEP_PEER_SEND_UPDATE) {
+    if (dlep_session_generate_signal(session, DLEP_SESSION_UPDATE, NULL)) {
+      // TODO: do we need to terminate here?
+      return -1;
+    }
+    session->_peer_state = DLEP_PEER_WAIT_FOR_UPDATE_ACK;
   }
-
-  /* we don't support IP address exchange with the router at the moment */
-  return dlep_session_generate_signal(
-      session, DLEP_DESTINATION_UP_ACK, &mac);
+  else {
+    session->_peer_state = DLEP_PEER_IDLE;
+  }
+  return 0;
 }
 
 /**
@@ -406,26 +387,6 @@ _radio_process_destination_up_ack(
   return 0;
 }
 
-/**
- * Process the destination down message
- * @param ext (this) dlep extension
- * @param session dlep session
- * @return -1 if an error happened, 0 otherwise
- */
-static int
-_radio_process_destination_down(
-    struct dlep_extension *ext __attribute__((unused)),
-    struct dlep_session *session) {
-  struct netaddr mac;
-  if (dlep_reader_mac_tlv(&mac, session, NULL)) {
-    return -1;
-  }
-
-  /* we don't support IP address exchange with the router at the moment */
-  return dlep_session_generate_signal(
-      session, DLEP_DESTINATION_DOWN_ACK, &mac);
-}
-
 /**
  * Process the destination down ack message
  * @param ext (this) dlep extension
@@ -452,20 +413,6 @@ _radio_process_destination_down_ack(
   return 0;
 }
 
-/**
- * Process the destination update message
- * @param ext (this) dlep extension
- * @param session dlep session
- * @return always 0
- */
-static int
-_radio_process_destination_update(
-    struct dlep_extension *ext __attribute__((unused)),
-    struct dlep_session *session __attribute__((unused))) {
-  /* TODO: IP address change processing ? */
-  return 0;
-}
-
 /**
  * Process the link characteristic message
  * @param ext (this) dlep extension
@@ -710,7 +657,6 @@ _l2_neigh_removed(struct oonf_layer2_neigh *l2neigh,
           radio_session->session.cfg.heartbeat_interval * 2);
     }
   }
-
 }
 
 /**
index d9198ad..1804797 100644 (file)
@@ -64,9 +64,9 @@ static void _cb_cleanup_router(struct dlep_session *);
 static void _cb_create_peer_discovery(struct oonf_timer_instance *);
 
 static int _router_process_peer_offer(struct dlep_extension *, struct dlep_session *);
-static int _router_process_peer_init_ack(struct dlep_extension *, struct dlep_session *);
-static int _router_process_peer_update(struct dlep_extension *, struct dlep_session *);
-static int _router_process_peer_update_ack(struct dlep_extension *, struct dlep_session *);
+static int _router_process_session_init_ack(struct dlep_extension *, struct dlep_session *);
+static int _router_process_session_update(struct dlep_extension *, struct dlep_session *);
+static int _router_process_session_update_ack(struct dlep_extension *, struct dlep_session *);
 static int _router_process_destination_up(struct dlep_extension *, struct dlep_session *);
 static int _router_process_destination_up_ack(struct dlep_extension *, struct dlep_session *);
 static int _router_process_destination_down(struct dlep_extension *, struct dlep_session *);
@@ -94,23 +94,23 @@ static struct dlep_extension_implementation _router_signals[] = {
     },
     {
         .id = DLEP_SESSION_INITIALIZATION_ACK,
-        .process = _router_process_peer_init_ack,
+        .process = _router_process_session_init_ack,
     },
     {
-        .id = DLEP_PEER_UPDATE,
-        .process = _router_process_peer_update,
+        .id = DLEP_SESSION_UPDATE,
+        .process = _router_process_session_update,
     },
     {
-        .id = DLEP_PEER_UPDATE_ACK,
-        .process = _router_process_peer_update_ack,
+        .id = DLEP_SESSION_UPDATE_ACK,
+        .process = _router_process_session_update_ack,
     },
     {
-        .id = DLEP_PEER_TERMINATION,
-        .process = dlep_base_proto_process_peer_termination,
+        .id = DLEP_SESSION_TERMINATION,
+        .process = dlep_base_proto_process_session_termination,
     },
     {
-        .id = DLEP_PEER_TERMINATION_ACK,
-        .process = dlep_base_proto_process_peer_termination_ack,
+        .id = DLEP_SESSION_TERMINATION_ACK,
+        .process = dlep_base_proto_process_session_termination_ack,
     },
     {
         .id = DLEP_DESTINATION_UP,
@@ -358,7 +358,7 @@ _router_process_peer_offer(
  * @return -1 if an error happened, 0 otherwise
  */
 static int
-_router_process_peer_init_ack(
+_router_process_session_init_ack(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
   struct oonf_layer2_net *l2net;
@@ -427,7 +427,7 @@ _router_process_peer_init_ack(
  * @return -1 if an error happened, 0 otherwise
  */
 static int
-_router_process_peer_update(
+_router_process_session_update(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
   struct oonf_layer2_net *l2net;
@@ -445,11 +445,9 @@ _router_process_peer_update(
     return -1;
   }
 
-  /* we don't support IP address exchange at the moment */
-
   /* generate ACK */
   return dlep_session_generate_signal(
-      session, DLEP_PEER_UPDATE_ACK, NULL);
+      session, DLEP_SESSION_UPDATE_ACK, NULL);
 }
 
 /**
@@ -459,7 +457,7 @@ _router_process_peer_update(
  * @return -1 if an error happened, 0 otherwise
  */
 static int
-_router_process_peer_update_ack(
+_router_process_session_update_ack(
     struct dlep_extension *ext __attribute__((unused)),
     struct dlep_session *session) {
   dlep_base_proto_print_status(session);
index 4a8c9b6..412e124 100644 (file)
@@ -70,7 +70,7 @@ static int dlep_writer_map_bandwidth(struct dlep_writer *writer,
     struct oonf_layer2_data *data, uint16_t tlv, uint16_t length);
 
 /* peer initialization ack */
-static const uint16_t _peer_initack_tlvs[] = {
+static const uint16_t _session_initack_tlvs[] = {
     DLEP_FREQUENCY_TLV,
     DLEP_BANDWIDTH_TLV,
     DLEP_NOISE_LEVEL_TLV,
@@ -81,7 +81,7 @@ static const uint16_t _peer_initack_tlvs[] = {
     DLEP_SIGNAL_RX_TLV,
     DLEP_SIGNAL_TX_TLV,
 };
-static const uint16_t _peer_initack_mandatory[] = {
+static const uint16_t _session_initack_mandatory[] = {
     DLEP_FREQUENCY_TLV,
     DLEP_BANDWIDTH_TLV,
 };
@@ -113,19 +113,19 @@ static const uint16_t _dst_mandatory[] = {
 static struct dlep_extension_signal _signals[] = {
     {
         .id = DLEP_SESSION_INITIALIZATION_ACK,
-        .supported_tlvs = _peer_initack_tlvs,
-        .supported_tlv_count = ARRAYSIZE(_peer_initack_tlvs),
-        .mandatory_tlvs = _peer_initack_mandatory,
-        .mandatory_tlv_count = ARRAYSIZE(_peer_initack_mandatory),
-        .add_radio_tlvs = dlep_extension_radio_write_peer_init_ack,
-        .process_router = dlep_extension_router_process_peer_init_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,
     },
     {
-        .id = DLEP_PEER_UPDATE,
+        .id = DLEP_SESSION_UPDATE,
         .supported_tlvs = _peer_update_tlvs,
         .supported_tlv_count = ARRAYSIZE(_peer_update_tlvs),
-        .add_radio_tlvs = dlep_extension_radio_write_peer_update,
-        .process_router = dlep_extension_router_process_peer_update,
+        .add_radio_tlvs = dlep_extension_radio_write_session_update,
+        .process_router = dlep_extension_router_process_session_update,
     },
     {
         .id = DLEP_DESTINATION_UP,
index f556c72..4d719f9 100644 (file)
@@ -54,7 +54,7 @@
 #include "dlep/ext_l2_statistics/l2_statistics.h"
 
 /* peer initialization ack */
-static const uint16_t _peer_initack_tlvs[] = {
+static const uint16_t _session_initack_tlvs[] = {
     DLEP_FRAMES_R_TLV,
     DLEP_FRAMES_T_TLV,
     DLEP_FRAMES_RETRIES_TLV,
@@ -63,13 +63,13 @@ static const uint16_t _peer_initack_tlvs[] = {
     DLEP_BYTES_T_TLV,
     DLEP_THROUGHPUT_T_TLV,
 };
-static const uint16_t _peer_initack_mandatory[] = {
+static const uint16_t _session_initack_mandatory[] = {
     DLEP_FRAMES_R_TLV,
     DLEP_FRAMES_T_TLV,
 };
 
 /* peer update */
-static const uint16_t _peer_update_tlvs[] = {
+static const uint16_t _peer_session_tlvs[] = {
     DLEP_FRAMES_R_TLV,
     DLEP_FRAMES_T_TLV,
     DLEP_FRAMES_RETRIES_TLV,
@@ -98,19 +98,19 @@ static const uint16_t _dst_mandatory[] = {
 static struct dlep_extension_signal _signals[] = {
     {
         .id = DLEP_SESSION_INITIALIZATION_ACK,
-        .supported_tlvs = _peer_initack_tlvs,
-        .supported_tlv_count = ARRAYSIZE(_peer_initack_tlvs),
-        .mandatory_tlvs = _peer_initack_mandatory,
-        .mandatory_tlv_count = ARRAYSIZE(_peer_initack_mandatory),
-        .add_radio_tlvs = dlep_extension_radio_write_peer_init_ack,
-        .process_router = dlep_extension_router_process_peer_init_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,
     },
     {
-        .id = DLEP_PEER_UPDATE,
-        .supported_tlvs = _peer_update_tlvs,
-        .supported_tlv_count = ARRAYSIZE(_peer_update_tlvs),
-        .add_radio_tlvs = dlep_extension_radio_write_peer_update,
-        .process_router = dlep_extension_router_process_peer_update,
+        .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,
     },
     {
         .id = DLEP_DESTINATION_UP,
index f0d665c..0eb0f6f 100644 (file)
@@ -60,8 +60,9 @@
 #include "dlep/radio/dlep_radio.h"
 #include "dlep/radio/dlep_radio_interface.h"
 
-#include "dlep/ext_base_proto/proto_radio.h"
 #include "dlep/ext_base_metric/metric.h"
+#include "dlep/ext_base_ip/ip.h"
+#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/radio/dlep_radio_internal.h"
@@ -70,8 +71,6 @@
 static void _cleanup_interface(struct dlep_radio_if *interface);
 
 /* DLEP interfaces */
-static struct avl_tree _interface_tree;
-
 static struct oonf_class _interface_class = {
   .name = "DLEP radio session",
   .size = sizeof(struct dlep_radio_if),
@@ -93,12 +92,12 @@ static struct oonf_layer2_origin _l2_origin = {
 int
 dlep_radio_interface_init(void) {
   oonf_class_add(&_interface_class);
-  avl_init(&_interface_tree, avl_comp_strcasecmp, false);
 
   dlep_extension_init();
   dlep_session_init();
   dlep_radio_session_init();
   dlep_base_proto_radio_init();
+  dlep_base_ip_init();
   dlep_base_metric_init();
   dlep_l1_statistics_init();
   dlep_l2_statistics_init();
@@ -115,7 +114,7 @@ void
 dlep_radio_interface_cleanup(void) {
   struct dlep_radio_if *interf, *it;
 
-  avl_for_each_element_safe(&_interface_tree, interf, interf._node, it) {
+  avl_for_each_element_safe(dlep_if_get_tree(true), interf, interf._node, it) {
     dlep_radio_remove_interface(interf);
   }
 
@@ -133,7 +132,7 @@ struct dlep_radio_if *
 dlep_radio_get_by_layer2_if(const char *l2_ifname) {
   struct dlep_radio_if *interf;
 
-  return avl_find_element(&_interface_tree, l2_ifname, interf, interf._node);
+  return avl_find_element(dlep_if_get_tree(true), l2_ifname, interf, interf._node);
 }
 
 /**
@@ -145,7 +144,7 @@ struct dlep_radio_if *
 dlep_radio_get_by_datapath_if(const char *ifname) {
   struct dlep_radio_if *interf;
 
-  avl_for_each_element(&_interface_tree, interf, interf._node) {
+  avl_for_each_element(dlep_if_get_tree(true), interf, interf._node) {
     if (strcmp(interf->interf.udp_config.interface, ifname) == 0) {
       return interf;
     }
@@ -178,9 +177,6 @@ dlep_radio_add_interface(const char *ifname) {
     return NULL;
   }
 
-  /* add to global tree of sessions */
-  avl_insert(&_interface_tree, &interface->interf._node);
-
   /* configure TCP server socket */
   interface->tcp.config.session_timeout = 120000; /* 120 seconds */
   interface->tcp.config.maximum_input_buffer = 4096;
@@ -207,10 +203,8 @@ dlep_radio_remove_interface(struct dlep_radio_if *interface) {
   /* cleanup generic interface */
   dlep_if_remove(&interface->interf);
 
-  /* remove from interface tree */
-  avl_remove(&_interface_tree, &interface->interf._node);
-
   /* free memory */
+  oonf_stream_free_managed_config(&interface->tcp_config);
   free (interface->interf.session.cfg.peer_type);
   abuf_free(&interface->interf.udp_out);
   oonf_class_free(&_interface_class, interface);
@@ -244,7 +238,7 @@ dlep_radio_terminate_all_sessions(void) {
 
   _shutting_down = true;
 
-  avl_for_each_element(&_interface_tree, interf, interf._node) {
+  avl_for_each_element(dlep_if_get_tree(true), interf, interf._node) {
     avl_for_each_element(&interf->interf.session_tree, radio_session, _node) {
       dlep_session_terminate(&radio_session->session);
     }
index a9c5a5b..e386e7e 100644 (file)
@@ -96,8 +96,8 @@ void
 dlep_radio_session_initialize_tcp_callbacks(
     struct oonf_stream_config *config) {
   config->memcookie = &_radio_session_class;
-  config->init = _cb_incoming_tcp;
-  config->cleanup = _cb_tcp_lost;
+  config->init_session = _cb_incoming_tcp;
+  config->cleanup_session = _cb_tcp_lost;
   config->receive_data = _cb_tcp_receive_data;
 }
 
index 7578cf8..33033e0 100644 (file)
@@ -65,8 +65,9 @@
 #include "dlep/router/dlep_router.h"
 #include "dlep/router/dlep_router_interface.h"
 
-#include "dlep/ext_base_proto/proto_router.h"
+#include "dlep/ext_base_ip/ip.h"
 #include "dlep/ext_base_metric/metric.h"
+#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/router/dlep_router_internal.h"
@@ -74,8 +75,6 @@
 
 static void _cleanup_interface(struct dlep_router_if *interface);
 
-static struct avl_tree _interface_tree;
-
 static struct oonf_class _router_if_class = {
   .name = "DLEP router interface",
   .size = sizeof(struct dlep_router_if),
@@ -95,13 +94,13 @@ static struct oonf_layer2_origin _l2_origin = {
 void
 dlep_router_interface_init(void) {
   oonf_class_add(&_router_if_class);
-  avl_init(&_interface_tree, avl_comp_strcasecmp, false);
 
   dlep_extension_init();
   dlep_session_init();
   dlep_router_session_init();
   dlep_base_proto_router_init();
   dlep_base_metric_init();
+  dlep_base_ip_init();
   dlep_l1_statistics_init();
   dlep_l2_statistics_init();
 
@@ -118,12 +117,13 @@ void
 dlep_router_interface_cleanup(void) {
   struct dlep_router_if *interf, *it;
 
-  avl_for_each_element_safe(&_interface_tree, interf, interf._node, it) {
+  avl_for_each_element_safe(dlep_if_get_tree(false), interf, interf._node, it) {
     dlep_router_remove_interface(interf);
   }
 
   oonf_class_remove(&_router_if_class);
 
+  dlep_base_ip_cleanup();
   dlep_router_session_cleanup();
   dlep_extension_cleanup();
   oonf_layer2_remove_origin(&_l2_origin);
@@ -138,7 +138,7 @@ struct dlep_router_if *
 dlep_router_get_by_layer2_if(const char *l2_ifname) {
   struct dlep_router_if *interf;
 
-  return avl_find_element(&_interface_tree, l2_ifname, interf, interf._node);
+  return avl_find_element(dlep_if_get_tree(false), l2_ifname, interf, interf._node);
 }
 
 /**
@@ -150,7 +150,7 @@ struct dlep_router_if *
 dlep_router_get_by_datapath_if(const char *ifname) {
   struct dlep_router_if *interf;
 
-  avl_for_each_element(&_interface_tree, interf, interf._node) {
+  avl_for_each_element(dlep_if_get_tree(false), interf, interf._node) {
     if (strcmp(interf->interf.udp_config.interface, ifname) == 0) {
       return interf;
     }
@@ -184,9 +184,6 @@ dlep_router_add_interface(const char *ifname) {
     return NULL;
   }
 
-  /* add to global tree of sessions */
-  avl_insert(&_interface_tree, &interface->interf._node);
-
   OONF_DEBUG(LOG_DLEP_ROUTER, "Add session %s", ifname);
   return interface;
 }
@@ -205,7 +202,6 @@ dlep_router_remove_interface(struct dlep_router_if *interface) {
 
   /* remove session */
   free (interface->interf.session.cfg.peer_type);
-  avl_remove(&_interface_tree, &interface->interf._node);
   oonf_class_free(&_router_if_class, interface);
 }
 
@@ -263,7 +259,7 @@ dlep_router_terminate_all_sessions(void) {
 
   _shutting_down = true;
 
-  avl_for_each_element(&_interface_tree, interf, interf._node) {
+  avl_for_each_element(dlep_if_get_tree(false), interf, interf._node) {
     avl_for_each_element(&interf->interf.session_tree, router_session, _node) {
       dlep_session_terminate(&router_session->session);
     }
index 6d2283d..3cfda8b 100644 (file)
@@ -64,6 +64,7 @@
 #include "dlep/router/dlep_router_internal.h"
 #include "dlep/router/dlep_router_session.h"
 
+static void _cb_socket_terminated(struct oonf_stream_socket *stream_socket);
 static void _cb_tcp_lost(struct oonf_stream_session *);
 static enum oonf_stream_session_state _cb_tcp_receive_data(struct oonf_stream_session *);
 static void _cb_send_buffer(struct dlep_session *session, int af_family);
@@ -140,7 +141,8 @@ dlep_router_add_session(struct dlep_router_if *interf,
   router_session->tcp.config.session_timeout = 120000; /* 120 seconds */
   router_session->tcp.config.maximum_input_buffer = 4096;
   router_session->tcp.config.allowed_sessions = 3;
-  router_session->tcp.config.cleanup = _cb_tcp_lost;
+  router_session->tcp.config.cleanup_session = _cb_tcp_lost;
+  router_session->tcp.config.cleanup_socket = _cb_socket_terminated;
   router_session->tcp.config.receive_data = _cb_tcp_receive_data;
 
   OONF_DEBUG(LOG_DLEP_ROUTER, "Connect DLEP session from %s to %s",
@@ -191,7 +193,6 @@ dlep_router_add_session(struct dlep_router_if *interf,
     }
   }
 
-
   return router_session;
 }
 
@@ -203,10 +204,23 @@ void
 dlep_router_remove_session(struct dlep_router_session *router_session) {
   if (router_session->stream) {
     oonf_stream_close(router_session->stream);
+    router_session->stream = NULL;
   }
-  oonf_stream_remove(&router_session->tcp, true);
+  oonf_stream_remove(&router_session->tcp, false);
 }
 
+/**
+ * Callback triggered when tcp socket (not session) has been terminated
+ * @param stream_socket terminated socket
+ */
+static void
+_cb_socket_terminated(struct oonf_stream_socket *stream_socket) {
+  struct dlep_router_session *router_session;
+
+  router_session = container_of(stream_socket, struct dlep_router_session, tcp);
+
+  oonf_class_free(&_router_session_class, router_session);
+}
 /**
  * Callback triggered when tcp session was lost and will be removed
  * @param tcp_session tcp session
@@ -233,10 +247,11 @@ _cb_tcp_lost(struct oonf_stream_session *tcp_session) {
   /* kill embedded session object */
   dlep_session_remove(&router_session->session);
 
-
   /* remove from session tree of interface */
-  avl_remove(&router_session->interface->interf.session_tree,
-      &router_session->_node);
+  if (avl_is_node_added(&router_session->_node)) {
+    avl_remove(&router_session->interface->interf.session_tree,
+        &router_session->_node);
+  }
 }
 
 /**
index 000212f..8e362cb 100644 (file)
@@ -72,7 +72,7 @@ enum dlep_router_session_state {
  * DLEP session of a router
  */
 struct dlep_router_session {
-  /*! basic struct for tcp stream, must be first in struct! */
+  /*! basic struct for tcp stream */
   struct oonf_stream_session *stream;
 
   /*! TCP client socket for session */
index c3ee71b..1f0e08d 100644 (file)
@@ -174,7 +174,7 @@ static struct oonf_stream_managed _http_managed_socket = {
     .allowed_sessions = 10,
     .receive_data = _cb_receive_data,
     .create_error = _cb_create_error,
-    .cleanup = _cb_cleanup_session,
+    .cleanup_session = _cb_cleanup_session,
   },
 };
 
index 40c761a..c1986ac 100644 (file)
@@ -436,7 +436,7 @@ oonf_layer2_net_add_ip(struct oonf_layer2_net *l2net,
  */
 int
 oonf_layer2_net_remove_ip(
-    struct oonf_layer2_peer_address *ip, struct oonf_layer2_origin *origin) {
+    struct oonf_layer2_peer_address *ip, const struct oonf_layer2_origin *origin) {
   if (ip->origin != origin) {
     return -1;
   }
index aa051c7..468af2e 100644 (file)
@@ -366,7 +366,7 @@ EXPORT struct oonf_layer2_peer_address *oonf_layer2_net_add_ip(
     struct oonf_layer2_net *l2net,
     const struct oonf_layer2_origin *origin, const struct netaddr *ip);
 EXPORT int oonf_layer2_net_remove_ip(
-    struct oonf_layer2_peer_address *ip, struct oonf_layer2_origin *origin);
+    struct oonf_layer2_peer_address *ip, const struct oonf_layer2_origin *origin);
 EXPORT struct oonf_layer2_neighbor_address *oonf_layer2_net_get_best_neighbor_match(
     const struct netaddr *addr);
 
index 063a123..76f35ed 100644 (file)
@@ -231,6 +231,10 @@ oonf_stream_remove(struct oonf_stream_socket *stream_socket, bool force) {
 
   oonf_socket_remove(&stream_socket->scheduler_entry);
   os_fd_close(&stream_socket->scheduler_entry.fd);
+
+  if (stream_socket->config.cleanup_socket) {
+    stream_socket->config.cleanup_socket(stream_socket);
+  }
 }
 
 /**
@@ -456,8 +460,8 @@ oonf_stream_copy_managed_config(struct oonf_stream_managed_config *dst,
  */
 static void
 _stream_close(struct oonf_stream_session *session) {
-  if (session->stream_socket->config.cleanup) {
-    session->stream_socket->config.cleanup(session);
+  if (session->stream_socket->config.cleanup_session) {
+    session->stream_socket->config.cleanup_session(session);
   }
 
   oonf_timer_stop(&session->timeout);
@@ -675,8 +679,8 @@ _create_session(struct oonf_stream_socket *stream_socket,
   oonf_socket_set_read(&session->scheduler_entry, true);
   oonf_socket_set_write(&session->scheduler_entry, true);
 
-  if (stream_socket->config.init) {
-    if (stream_socket->config.init(session)) {
+  if (stream_socket->config.init_session) {
+    if (stream_socket->config.init_session(session)) {
       goto parse_request_error;
     }
   }
index ed38374..27e35ce 100644 (file)
@@ -193,13 +193,19 @@ struct oonf_stream_config {
    * @param session stream session
    * @return -1 if an error happened, 0 otherwise
    */
-  int (*init)(struct oonf_stream_session *session);
+  int (*init_session)(struct oonf_stream_session *session);
 
   /**
    * Callback to notify that a stream session will be terminated
    * @param session stream session
    */
-  void (*cleanup)(struct oonf_stream_session *session);
+  void (*cleanup_session)(struct oonf_stream_session *session);
+
+  /**
+   * Callback to notify that the socket has been terminated
+   * @param socket terminated stream socket
+   */
+  void (*cleanup_socket)(struct oonf_stream_socket *stream_socket);
 
   /**
    * Callback to notify that an error happened and the user might
index b36a7f9..ca1dc13 100644 (file)
@@ -163,8 +163,8 @@ static struct oonf_stream_managed _telnet_managed = {
     .session_timeout = 120000, /* 120 seconds */
     .allowed_sessions = 3,
     .memcookie = &_telnet_memcookie,
-    .init = _cb_telnet_init,
-    .cleanup = _cb_telnet_cleanup,
+    .init_session = _cb_telnet_init,
+    .cleanup_session = _cb_telnet_cleanup,
     .receive_data = _cb_telnet_receive_data,
     .create_error = _cb_telnet_create_error,
   },