Add route information to link 63/195363/3
authorYu <jiung.yu@samsung.com>
Thu, 13 Dec 2018 01:39:40 +0000 (10:39 +0900)
committerYu <jiung.yu@samsung.com>
Fri, 14 Dec 2018 09:08:37 +0000 (18:08 +0900)
Change-Id: Ia6273b5fdfd708e486e9f96b3c04a923eb2395ec
Signed-off-by: Yu Jiung <jiung.yu@samsung.com>
src/inm-rtnl.c

index 885ad1ebd325f5f84bad5d48572401a8608da8d4..109ab7fc8096ccab60ceea19d5fe038cebfb93c3 100644 (file)
@@ -57,6 +57,12 @@ typedef struct {
        int state;
 } inm_rtnl_neigh_s;
 
+typedef struct {
+       int if_idx;
+       char *dest;
+       char *gateway;
+       int type;
+} inm_rtnl_route_s;
 
 typedef struct {
        char *iface_name;
@@ -258,6 +264,7 @@ static inline void __link_fill_info(struct rtnl_link *p_rtnl_link, inm_rtnl_link
 
 static void __addr_destroy(void *user_data);
 static void __neigh_destroy(void *user_data);
+static void __route_destroy(void *user_data);
 
 static void __link_destroy(void *user_data)
 {
@@ -269,6 +276,7 @@ static void __link_destroy(void *user_data)
        p_link = (inm_rtnl_link_s *)user_data;
        g_list_free_full(p_link->list_addr, __addr_destroy);
        g_list_free_full(p_link->list_neigh, __neigh_destroy);
+       g_list_free_full(p_link->list_route, __route_destroy);
        g_free(p_link->iface_name);
        g_free(p_link);
 }
@@ -874,17 +882,148 @@ static inline void __rtnl_route_log(struct rtnl_route *p_rtnl_route)
        }
 }
 
+static void inline __route_copy(inm_rtnl_route_s *src, inm_rtnl_route_s *dst)
+{
+       if (!src || !dst)
+               return;
+
+       dst->type = src->type;
+       dst->if_idx = src->if_idx;
+       CHECK_STRING_AND_COPY(src->dest, dst->dest);
+       CHECK_STRING_AND_COPY(src->gateway, dst->gateway);
+}
+
+static gint __route_compare(const void *src_data, const void *dst_data)
+{
+       inm_rtnl_route_s *src;
+       inm_rtnl_route_s *dst;
+       gint res;
+
+       if (!src_data || !dst_data)
+               return -1;
+
+       src = (inm_rtnl_route_s *)src_data;
+       dst = (inm_rtnl_route_s *)dst_data;
+
+       res = dst->if_idx - src->if_idx;
+       if (res != 0)
+               return res;
+
+       res = g_strcmp0(src->dest, dst->dest);
+       if (res != 0)
+               return res;
+
+       res = g_strcmp0(src->gateway, dst->gateway);
+
+       return res;
+}
+
+static inline void __route_fill_info(struct rtnl_route *p_rtnl_route, inm_rtnl_route_s *p_route)
+{
+       char buf[128] = {0,};
+       struct rtnl_nexthop *p_nh;
+       char *p_str = NULL;
+
+       if (!p_rtnl_route || !p_route)
+               return;
+
+       p_route->type = rtnl_route_get_type(p_rtnl_route);
+       p_str = nl_addr2str(rtnl_route_get_dst(p_rtnl_route), buf, sizeof(buf));
+       CHECK_STRING_AND_COPY(p_str, p_route->dest);
+
+       if (rtnl_route_get_nnexthops(p_rtnl_route) > 0) {
+               p_nh = rtnl_route_nexthop_n(p_rtnl_route, 0);
+               p_route->if_idx = rtnl_route_nh_get_ifindex(p_nh);
+
+               p_str = NULL;
+               p_str = nl_addr2str(rtnl_route_nh_get_gateway(p_nh), buf, sizeof(buf));
+               CHECK_STRING_AND_COPY(p_str, p_route->gateway);
+       }
+}
+
+static void __route_destroy(void *user_data)
+{
+       inm_rtnl_route_s *p_route;
+       if (!user_data)
+               return;
+
+       p_route = (inm_rtnl_route_s *)user_data;
+       g_free(p_route->dest);
+       g_free(p_route->gateway);
+       g_free(p_route);
+}
+
+static inline void __route_add(inm_rtnl_route_s *p_route)
+{
+       GList *p_list;
+       inm_rtnl_link_s *link = NULL;
+       inm_rtnl_route_s *tmp = NULL;
+
+       link = __link_find(p_route->if_idx);
+       if (!link)
+               return;
+
+       p_list = g_list_find_custom(link->list_route,
+                       p_route,
+                       __route_compare);
+       if (p_list) {
+               __route_copy(p_route, (inm_rtnl_route_s *)p_list->data);
+       } else {
+               tmp = (inm_rtnl_route_s *)g_try_malloc0(sizeof(inm_rtnl_route_s));
+               if (!tmp)
+                       return;
+               __route_copy(p_route, tmp);
+               link->list_route = g_list_prepend(link->list_route, tmp);
+       }
+}
+
+static inline void __route_remove(inm_rtnl_route_s *p_route)
+{
+       GList *p_list;
+       inm_rtnl_link_s *link = NULL;
+       inm_rtnl_route_s *tmp = NULL;
+
+       link = __link_find(p_route->if_idx);
+       if (!link)
+               return;
+
+       p_list = g_list_find_custom(link->list_route,
+                       p_route,
+                       __route_compare);
+       if (p_list) {
+               tmp = (inm_rtnl_route_s *)p_list->data;
+               link->list_route = g_list_remove(link->list_route, tmp);
+               __route_destroy(tmp);
+       }
+}
+
 static void __route_recv_cb(int action,
                struct nl_object *obj,
                void *user_data)
 {
-       __INM_FUNC_ENTER__;
+       inm_rtnl_route_s *p_route = NULL;
 
+       __INM_FUNC_ENTER__;
        if (!obj) {
                __INM_FUNC_EXIT__;
                return;
        }
 
+       p_route = (inm_rtnl_route_s *)g_try_malloc0(sizeof(inm_rtnl_route_s));
+       if (!p_route) {
+               INM_LOGE("route mem alloc failed");
+               __INM_FUNC_EXIT__;
+               return;
+       }
+
+       __route_fill_info((struct rtnl_route *)obj, p_route);
+       if (action == NL_ACT_NEW || action == NL_ACT_CHANGE)
+               __route_add(p_route);
+       else if (action == NL_ACT_DEL)
+               __route_remove(p_route);
+
+       __route_destroy(p_route);
+
        util_foreach_nl_data(&(nl_data_arr[INM_UTIL_RTNL_TYPE_ROUTE]),
                        rtnl_obj_cbs[INM_UTIL_RTNL_TYPE_ROUTE].foreach_cb,
                        rtnl_obj_cbs[INM_UTIL_RTNL_TYPE_ROUTE].user_data);
@@ -894,13 +1033,25 @@ static void __route_recv_cb(int action,
 
 static void __route_foreach_cb(struct nl_object *obj, void *user_data)
 {
-       __INM_FUNC_ENTER__;
+       inm_rtnl_route_s *p_route = NULL;
 
+       __INM_FUNC_ENTER__;
        if (!obj) {
                __INM_FUNC_EXIT__;
                return;
        }
 
+       p_route = (inm_rtnl_route_s *)g_try_malloc0(sizeof(inm_rtnl_route_s));
+       if (!p_route) {
+               INM_LOGE("route mem alloc failed");
+               __INM_FUNC_EXIT__;
+               return;
+       }
+
+       __route_fill_info((struct rtnl_route *)obj, p_route);
+       __route_add(p_route);
+       __route_destroy(p_route);
+
        __rtnl_route_log((struct rtnl_route *)obj);
 
        __INM_FUNC_EXIT__;