Fixes for netlink layer to prevent overloading from multiple triggered
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 27 Sep 2017 12:43:17 +0000 (14:43 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 27 Sep 2017 12:43:17 +0000 (14:43 +0200)
interface scans. Unify routing netlink sockets and add more debugging output.

src-plugins/subsystems/os_linux/os_interface_linux.c
src-plugins/subsystems/os_linux/os_routing_linux.c
src-plugins/subsystems/os_linux/os_system_linux.c

index 5c7c345..e99746a 100644 (file)
@@ -874,9 +874,10 @@ _query_interface_links(void) {
     return;
   }
 
-  OONF_DEBUG(LOG_OS_INTERFACE, "Request all interfaces");
+  OONF_DEBUG(LOG_OS_INTERFACE, "Request all interface links");
 
   _trigger_link_query = false;
+  _link_query_in_progress = true;
 
   /* get pointers for netlink message */
   msg = (void *)&buffer[0];
@@ -910,8 +911,9 @@ _query_interface_addresses(void) {
   }
 
   _trigger_address_query = false;
+  _address_query_in_progress = true;
 
-  OONF_DEBUG(LOG_OS_INTERFACE, "Request all interfaces");
+  OONF_DEBUG(LOG_OS_INTERFACE, "Request all interface addresses");
 
   /* get pointers for netlink message */
   msg = (void *)&buffer[0];
@@ -1417,6 +1419,7 @@ _process_bad_end_of_query(void) {
 static void
 _cb_query_error(uint32_t seq __attribute((unused)),
     int error __attribute((unused))) {
+  OONF_DEBUG(LOG_OS_INTERFACE, "Received error %d for query %u", error, seq);
   _process_bad_end_of_query();
 }
 
@@ -1426,6 +1429,7 @@ _cb_query_error(uint32_t seq __attribute((unused)),
  */
 static void
 _cb_query_done(uint32_t seq __attribute((unused))) {
+  OONF_DEBUG(LOG_OS_INTERFACE, "Query %u done", seq);
   _process_end_of_query();
 }
 
@@ -1434,6 +1438,7 @@ _cb_query_done(uint32_t seq __attribute((unused))) {
  */
 static void
 _cb_query_timeout(void) {
+  OONF_DEBUG(LOG_OS_INTERFACE, "Query timeout");
   _process_bad_end_of_query();
 }
 
index 89f11d8..3c7a03a 100644 (file)
@@ -83,7 +83,6 @@ static int _routing_set(struct nlmsghdr *msg, struct os_route *route,
 
 static void _routing_finished(struct os_route *route, int error);
 static void _cb_rtnetlink_message(struct nlmsghdr *);
-static void _cb_rtnetlink_event_message(struct nlmsghdr *);
 static void _cb_rtnetlink_error(uint32_t seq, int err);
 static void _cb_rtnetlink_done(uint32_t seq);
 static void _cb_rtnetlink_timeout(void);
@@ -129,12 +128,6 @@ static struct os_system_netlink _rtnetlink_socket = {
   .cb_timeout = _cb_rtnetlink_timeout,
 };
 
-static struct os_system_netlink _rtnetlink_event_socket = {
-  .name = "routing listener",
-  .used_by = &_oonf_os_routing_subsystem,
-  .cb_message = _cb_rtnetlink_event_message,
-};
-
 static struct avl_tree _rtnetlink_feedback;
 static struct list_entity _rtnetlink_listener;
 
@@ -166,17 +159,10 @@ _init(void) {
   if (os_system_linux_netlink_add(&_rtnetlink_socket, NETLINK_ROUTE)) {
     return -1;
   }
-
-  if (os_system_linux_netlink_add(&_rtnetlink_event_socket, NETLINK_ROUTE)) {
+  if (os_system_linux_netlink_add_mc(&_rtnetlink_socket, _rtnetlink_mcast, ARRAYSIZE(_rtnetlink_mcast))) {
     os_system_linux_netlink_remove(&_rtnetlink_socket);
     return -1;
   }
-
-  if (os_system_linux_netlink_add_mc(&_rtnetlink_event_socket, _rtnetlink_mcast, ARRAYSIZE(_rtnetlink_mcast))) {
-    os_system_linux_netlink_remove(&_rtnetlink_socket);
-    os_system_linux_netlink_remove(&_rtnetlink_event_socket);
-    return -1;
-  }
   avl_init(&_rtnetlink_feedback, avl_comp_uint32, false);
   list_init_head(&_rtnetlink_listener);
 
@@ -196,7 +182,6 @@ _cleanup(void) {
   }
 
   os_system_linux_netlink_remove(&_rtnetlink_socket);
-  os_system_linux_netlink_remove(&_rtnetlink_event_socket);
 }
 
 /**
@@ -458,7 +443,7 @@ _routing_set(struct nlmsghdr *msg, struct os_route *route,
   /* add attributes */
   if (netaddr_get_address_family(&route->p.src_ip) != AF_UNSPEC) {
     /* add src-ip */
-    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_event_socket,
+    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_socket,
         msg, RTA_PREFSRC, &route->p.src_ip)) {
       return -1;
     }
@@ -468,7 +453,7 @@ _routing_set(struct nlmsghdr *msg, struct os_route *route,
     rt_msg->rtm_flags |= RTNH_F_ONLINK;
 
     /* add gateway */
-    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_event_socket,
+    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_socket,
         msg, RTA_GATEWAY, &route->p.gw)) {
       return -1;
     }
@@ -478,7 +463,7 @@ _routing_set(struct nlmsghdr *msg, struct os_route *route,
     rt_msg->rtm_dst_len = netaddr_get_prefix_length(&route->p.key.dst);
 
     /* add destination */
-    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_event_socket,
+    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_socket,
         msg, RTA_DST, &route->p.key.dst)) {
       return -1;
     }
@@ -489,7 +474,7 @@ _routing_set(struct nlmsghdr *msg, struct os_route *route,
     rt_msg->rtm_src_len = netaddr_get_prefix_length(&route->p.key.src);
 
     /* add source-specific routing prefix */
-    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_event_socket,
+    if (os_system_linux_netlink_addnetaddr(&_rtnetlink_socket,
         msg, RTA_SRC, &route->p.key.src)) {
       return -1;
     }
@@ -497,7 +482,7 @@ _routing_set(struct nlmsghdr *msg, struct os_route *route,
 
   if (route->p.metric != -1) {
     /* add metric */
-    if (os_system_linux_netlink_addreq(&_rtnetlink_event_socket,
+    if (os_system_linux_netlink_addreq(&_rtnetlink_socket,
         msg, RTA_PRIORITY, &route->p.metric, sizeof(route->p.metric))) {
       return -1;
     }
@@ -505,7 +490,7 @@ _routing_set(struct nlmsghdr *msg, struct os_route *route,
 
   if (route->p.if_index) {
     /* add interface*/
-    if (os_system_linux_netlink_addreq(&_rtnetlink_event_socket,
+    if (os_system_linux_netlink_addreq(&_rtnetlink_socket,
         msg, RTA_OIF, &route->p.if_index, sizeof(route->p.if_index))) {
       return -1;
     }
@@ -643,11 +628,14 @@ _match_routes(struct os_route *filter, struct os_route *route) {
  */
 static void
 _cb_rtnetlink_message(struct nlmsghdr *msg) {
+  struct os_route_listener *listener;
   struct os_route *filter;
   struct os_route rt;
   int result;
 
-  OONF_DEBUG(LOG_OS_ROUTING, "Got message: %d %d", msg->nlmsg_seq, msg->nlmsg_type);
+  struct os_route_str rbuf;
+
+  OONF_DEBUG(LOG_OS_ROUTING, "Got message: %d %d 0x%04x", msg->nlmsg_seq, msg->nlmsg_type, msg->nlmsg_flags);
 
   if (msg->nlmsg_type != RTM_NEWROUTE && msg->nlmsg_type != RTM_DELROUTE) {
     return;
@@ -660,41 +648,22 @@ _cb_rtnetlink_message(struct nlmsghdr *msg) {
     return;
   }
 
-  /* check for feedback for ongoing route commands */
-  filter = avl_find_element(&_rtnetlink_feedback, &msg->nlmsg_seq, filter, _internal._node);
-  if (filter) {
-    if (filter->cb_get != NULL && _match_routes(filter, &rt)) {
-      filter->cb_get(filter, &rt);
-    }
-  }
-}
-
-/**
- * Handle incoming rtnetlink messages
- * @param msg netlink header including message
- */
-static void
-_cb_rtnetlink_event_message(struct nlmsghdr *msg) {
-  struct os_route_listener *listener;
-  struct os_route rt;
-  int result;
-
-  OONF_DEBUG(LOG_OS_ROUTING, "Got event message: %d %d", msg->nlmsg_seq, msg->nlmsg_type);
+  OONF_DEBUG(LOG_OS_ROUTING, "Content: %s", os_routing_to_string(&rbuf, &rt.p));
 
-  if (msg->nlmsg_type != RTM_NEWROUTE && msg->nlmsg_type != RTM_DELROUTE) {
-    return;
-  }
-
-  if ((result = _routing_parse_nlmsg(&rt, msg))) {
-    if (result < 0) {
-      OONF_WARN(LOG_OS_ROUTING, "Error while processing route reply");
+  if (msg->nlmsg_seq == 0) {
+    /* send route events to listeners */
+    list_for_each_element(&_rtnetlink_listener, listener, _internal._node) {
+      listener->cb_get(&rt, msg->nlmsg_type == RTM_NEWROUTE);
     }
-    return;
   }
-
-  /* send route events to listeners */
-  list_for_each_element(&_rtnetlink_listener, listener, _internal._node) {
-    listener->cb_get(&rt, msg->nlmsg_type == RTM_NEWROUTE);
+  else {
+    /* check for feedback for ongoing route commands */
+    filter = avl_find_element(&_rtnetlink_feedback, &msg->nlmsg_seq, filter, _internal._node);
+    if (filter) {
+      if (filter->cb_get != NULL && _match_routes(filter, &rt)) {
+        filter->cb_get(filter, &rt);
+      }
+    }
   }
 }
 
index 593dcae..2f37193 100644 (file)
@@ -145,8 +145,6 @@ static struct oonf_subsystem _oonf_os_system_subsystem = {
 };
 DECLARE_OONF_PLUGIN(_oonf_os_system_subsystem);
 
-static uint32_t _socket_count = 0;
-
 /* tracking of used netlink sequence numbers */
 static uint32_t _seq_used = 0;
 
@@ -309,9 +307,6 @@ os_system_linux_netlink_add(struct os_system_netlink *nl, int protocol) {
   memset(&addr, 0, sizeof(addr));
   addr.nl_family = AF_NETLINK;
 
-  addr.nl_pid = getpid() + (_socket_count << 22);
-  _socket_count++;
-
 #if defined(SO_RCVBUF)
   recvbuf = 65536*16;
   if (setsockopt(nl->socket.fd.fd, SOL_SOCKET, SO_RCVBUF,
@@ -338,11 +333,13 @@ os_system_linux_netlink_add(struct os_system_netlink *nl, int protocol) {
   return 0;
 
 os_add_netlink_fail:
+  os_fd_invalidate(&nl->socket.fd);
   if (fd != -1) {
     close(fd);
   }
   free (nl->in);
   abuf_free(&nl->out);
+  fd = -1;
   return -1;
 }
 
@@ -352,11 +349,13 @@ os_add_netlink_fail:
  */
 void
 os_system_linux_netlink_remove(struct os_system_netlink *nl) {
-  oonf_socket_remove(&nl->socket);
+  if (os_fd_is_initialized(&nl->socket.fd)) {
+    oonf_socket_remove(&nl->socket);
 
-  os_fd_close(&nl->socket.fd);
-  free (nl->in);
-  abuf_free(&nl->out);
+    os_fd_close(&nl->socket.fd);
+    free (nl->in);
+    abuf_free(&nl->out);
+  }
 }
 
 /**
@@ -408,7 +407,9 @@ os_system_linux_netlink_send(struct os_system_netlink *nl,
   nl->out_messages++;
 
   /* trigger write */
-  oonf_socket_set_write(&nl->socket, true);
+  if (nl->msg_in_transit == 0) {
+    oonf_socket_set_write(&nl->socket, true);
+  }
   return _seq_used;
 }
 
@@ -524,6 +525,7 @@ _flush_netlink_buffer(struct os_system_netlink *nl) {
   int err;
 
   if (nl->msg_in_transit > 0) {
+    oonf_socket_set_write(&nl->socket, false);
     return;
   }