lib: Simplify rtnetlink routing functionality.
authorEthan Jackson <ethan@nicira.com>
Wed, 12 Jan 2011 22:55:18 +0000 (14:55 -0800)
committerEthan Jackson <ethan@nicira.com>
Fri, 14 Jan 2011 19:19:32 +0000 (11:19 -0800)
This commit removes the rtnetlink-route module and replaces it with
a much simpler to use route-table module.  The route-table uses
rtnetlink to maintain a routing table which may be used to query
the egress interface of particular addresses.

This commit also converts netdev-vport to use the new route-table
module.

lib/automake.mk
lib/netdev-vport.c
lib/route-table.c [new file with mode: 0644]
lib/route-table.h [new file with mode: 0644]
lib/rtnetlink-route.c [deleted file]
lib/rtnetlink-route.h [deleted file]

index 269ab897f817f3d8016ee09fff0076be8c5f5033..fee55b2f352bc2f86348dec73eed54a4cc45d248 100644 (file)
@@ -194,8 +194,8 @@ lib_libopenvswitch_a_SOURCES += \
        lib/rtnetlink.h \
        lib/rtnetlink-link.c \
        lib/rtnetlink-link.h \
-       lib/rtnetlink-route.c \
-       lib/rtnetlink-route.h
+       lib/route-table.c \
+       lib/route-table.h
 endif
 
 if HAVE_OPENSSL
index b006a677b4224f3c719e8338d15996929b9a2635..2d0d9845af037c96db89a2ea977d167353be72e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Nicira Networks.
+ * Copyright (c) 2010, 2011 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
 #include "openvswitch/tunnel.h"
 #include "packets.h"
 #include "rtnetlink.h"
-#include "rtnetlink-route.h"
+#include "route-table.h"
 #include "rtnetlink-link.h"
 #include "shash.h"
 #include "socket-util.h"
 VLOG_DEFINE_THIS_MODULE(netdev_vport);
 
 static struct hmap name_map;
-static struct hmap route_map;
 static struct rtnetlink_notifier netdev_vport_link_notifier;
-static struct rtnetlink_notifier netdev_vport_route_notifier;
-
-struct route_node {
-    struct hmap_node node;      /* Node in route_map. */
-    int rta_oif;                /* Egress interface index. */
-    uint32_t rta_dst;           /* Destination address in host byte order. */
-    unsigned char rtm_dst_len;  /* Destination address length. */
-};
 
 struct name_node {
     struct hmap_node node; /* Node in name_map. */
@@ -96,8 +87,6 @@ static int netdev_vport_create(const struct netdev_class *, const char *,
 static void netdev_vport_poll_notify(const struct netdev *);
 
 static void netdev_vport_tnl_iface_init(void);
-static void netdev_vport_route_change(const struct rtnetlink_route_change *,
-                                      void *);
 static void netdev_vport_link_change(const struct rtnetlink_link_change *,
                                      void *);
 static const char *netdev_vport_get_tnl_iface(const struct netdev *netdev);
@@ -147,6 +136,7 @@ static int
 netdev_vport_init(void)
 {
     netdev_vport_tnl_iface_init();
+    route_table_register();
     return 0;
 }
 
@@ -177,6 +167,7 @@ netdev_vport_destroy(struct netdev_dev *netdev_dev_)
 {
     struct netdev_dev_vport *netdev_dev = netdev_dev_vport_cast(netdev_dev_);
 
+    route_table_unregister();
     free(netdev_dev);
 }
 
@@ -447,14 +438,14 @@ static void
 netdev_vport_run(void)
 {
     rtnetlink_link_notifier_run();
-    rtnetlink_route_notifier_run();
+    route_table_run();
 }
 
 static void
 netdev_vport_wait(void)
 {
     rtnetlink_link_notifier_wait();
-    rtnetlink_route_notifier_wait();
+    route_table_wait();
 }
 \f
 /* get_tnl_iface() implementation. */
@@ -473,52 +464,20 @@ name_node_lookup(int ifi_index)
     return NULL;
 }
 
-static struct route_node *
-route_node_lookup(int rta_oif, uint32_t rta_dst, unsigned char rtm_dst_len)
-{
-    uint32_t hash;
-    struct route_node *rn;
-
-    hash = hash_3words(rta_oif, rta_dst, rtm_dst_len);
-    HMAP_FOR_EACH_WITH_HASH(rn, node, hash, &route_map) {
-        if (rn->rta_oif     == rn->rta_oif &&
-            rn->rta_dst     == rn->rta_dst &&
-            rn->rtm_dst_len == rn->rtm_dst_len) {
-            return rn;
-        }
-    }
-
-    return NULL;
-}
-
-/* Resets the name or route map depending on the value of 'is_name'.  Clears
- * the appropriate map, makes an rtnetlink dump request, and calls the change
- * callback for each reply from the kernel. One should probably use
- * netdev_vport_reset_routes or netdev_vport_reset_names instead. */
+/* Queries the kernel for fresh data to populate the name map with. */
 static int
-netdev_vport_reset_name_else_route(bool is_name)
+netdev_vport_reset_names(void)
 {
     int error;
-    int nlmsg_type;
     struct nl_dump dump;
     struct rtgenmsg *rtmsg;
     struct ofpbuf request, reply;
     static struct nl_sock *rtnl_sock;
+    struct name_node *nn, *nn_next;
 
-    if (is_name) {
-        struct name_node *nn, *nn_next;
-
-        HMAP_FOR_EACH_SAFE(nn, nn_next, node, &name_map) {
-            hmap_remove(&name_map, &nn->node);
-            free(nn);
-        }
-    } else {
-        struct route_node *rn, *rn_next;
-
-        HMAP_FOR_EACH_SAFE(rn, rn_next, node, &route_map) {
-            hmap_remove(&route_map, &rn->node);
-            free(rn);
-        }
+    HMAP_FOR_EACH_SAFE(nn, nn_next, node, &name_map) {
+        hmap_remove(&name_map, &nn->node);
+        free(nn);
     }
 
     error = nl_sock_create(NETLINK_ROUTE, 0, 0, 0, &rtnl_sock);
@@ -529,8 +488,7 @@ netdev_vport_reset_name_else_route(bool is_name)
 
     ofpbuf_init(&request, 0);
 
-    nlmsg_type = is_name ? RTM_GETLINK : RTM_GETROUTE;
-    nl_msg_put_nlmsghdr(&request, sizeof *rtmsg, nlmsg_type, NLM_F_REQUEST);
+    nl_msg_put_nlmsghdr(&request, sizeof *rtmsg, RTM_GETLINK, NLM_F_REQUEST);
 
     rtmsg = ofpbuf_put_zeros(&request, sizeof *rtmsg);
     rtmsg->rtgen_family = AF_INET;
@@ -538,18 +496,10 @@ netdev_vport_reset_name_else_route(bool is_name)
     nl_dump_start(&dump, rtnl_sock, &request);
 
     while (nl_dump_next(&dump, &reply)) {
-        if (is_name) {
-            struct rtnetlink_link_change change;
+        struct rtnetlink_link_change change;
 
-            if (rtnetlink_link_parse(&reply, &change)) {
-                netdev_vport_link_change(&change, NULL);
-            }
-        } else {
-            struct rtnetlink_route_change change;
-
-            if (rtnetlink_route_parse(&reply, &change)) {
-                netdev_vport_route_change(&change, NULL);
-            }
+        if (rtnetlink_link_parse(&reply, &change)) {
+            netdev_vport_link_change(&change, NULL);
         }
     }
 
@@ -559,57 +509,6 @@ netdev_vport_reset_name_else_route(bool is_name)
     return error;
 }
 
-static int
-netdev_vport_reset_routes(void)
-{
-    return netdev_vport_reset_name_else_route(false);
-}
-
-static int
-netdev_vport_reset_names(void)
-{
-    return netdev_vport_reset_name_else_route(true);
-}
-
-static void
-netdev_vport_route_change(const struct rtnetlink_route_change *change,
-                         void *aux OVS_UNUSED)
-{
-
-    if (!change) {
-        netdev_vport_reset_routes();
-    } else if (change->nlmsg_type == RTM_NEWROUTE) {
-        uint32_t hash;
-        struct route_node *rn;
-
-        if (route_node_lookup(change->rta_oif, change->rta_dst,
-                              change->rtm_dst_len)) {
-            return;
-        }
-
-        rn              = xzalloc(sizeof *rn);
-        rn->rta_oif     = change->rta_oif;
-        rn->rta_dst     = change->rta_dst;
-        rn->rtm_dst_len = change->rtm_dst_len;
-
-        hash = hash_3words(rn->rta_oif, rn->rta_dst, rn->rtm_dst_len);
-        hmap_insert(&route_map, &rn->node, hash);
-    } else if (change->nlmsg_type == RTM_DELROUTE) {
-        struct route_node *rn;
-
-        rn = route_node_lookup(change->rta_oif, change->rta_dst,
-                               change->rtm_dst_len);
-
-        if (rn) {
-            hmap_remove(&route_map, &rn->node);
-            free(rn);
-        }
-    } else {
-        VLOG_WARN_RL(&rl, "Received unexpected rtnetlink message type %d",
-                     change->nlmsg_type);
-    }
-}
-
 static void
 netdev_vport_link_change(const struct rtnetlink_link_change *change,
                          void *aux OVS_UNUSED)
@@ -641,10 +540,6 @@ netdev_vport_link_change(const struct rtnetlink_link_change *change,
             free(nn);
         }
 
-        /* Link deletions do not result in all of the RTM_DELROUTE messages one
-         * would expect.  For now, go ahead and reset route_map whenever a link
-         * is deleted. */
-        netdev_vport_reset_routes();
     } else {
         VLOG_WARN_RL(&rl, "Received unexpected rtnetlink message type %d",
                      change->nlmsg_type);
@@ -658,16 +553,11 @@ netdev_vport_tnl_iface_init(void)
 
     if (!tnl_iface_is_init) {
         hmap_init(&name_map);
-        hmap_init(&route_map);
 
         rtnetlink_link_notifier_register(&netdev_vport_link_notifier,
-                                          netdev_vport_link_change, NULL);
-
-        rtnetlink_route_notifier_register(&netdev_vport_route_notifier,
-                                          netdev_vport_route_change, NULL);
+                                         netdev_vport_link_change, NULL);
 
         netdev_vport_reset_names();
-        netdev_vport_reset_routes();
         tnl_iface_is_init = true;
     }
 }
@@ -675,44 +565,19 @@ netdev_vport_tnl_iface_init(void)
 static const char *
 netdev_vport_get_tnl_iface(const struct netdev *netdev)
 {
-    int dst_len;
+    int ifindex;
     uint32_t route;
     struct netdev_dev_vport *ndv;
     struct tnl_port_config *config;
-    struct route_node *rn, *rn_def, *rn_iter;
 
     ndv = netdev_dev_vport_cast(netdev_get_dev(netdev));
     config = (struct tnl_port_config *) ndv->config;
-    route = ntohl(config->daddr);
-
-    dst_len = 0;
-    rn      = NULL;
-    rn_def  = NULL;
-
-    HMAP_FOR_EACH(rn_iter, node, &route_map) {
-        if (rn_iter->rtm_dst_len == 0 && rn_iter->rta_dst == 0) {
-            /* Default route. */
-            rn_def = rn_iter;
-        } else if (rn_iter->rtm_dst_len > dst_len) {
-            uint32_t mask = 0xffffffff << (32 - rn_iter->rtm_dst_len);
-            if ((route & mask) == (rn_iter->rta_dst & mask)) {
-                rn      = rn_iter;
-                dst_len = rn_iter->rtm_dst_len;
-            }
-        }
-    }
+    route = config->daddr;
 
-    if (!rn) {
-        rn = rn_def;
-    }
-
-    if (rn) {
-        uint32_t hash;
+    if (route_table_get_ifindex(route, &ifindex)) {
         struct name_node *nn;
-
-        hash = hash_int(rn->rta_oif, 0);
-        HMAP_FOR_EACH_WITH_HASH(nn, node, hash, &name_map) {
-            if (nn->ifi_index == rn->rta_oif) {
+        HMAP_FOR_EACH_WITH_HASH(nn, node, hash_int(ifindex, 0), &name_map) {
+            if (nn->ifi_index == ifindex) {
                 return nn->ifname;
             }
         }
diff --git a/lib/route-table.c b/lib/route-table.c
new file mode 100644 (file)
index 0000000..dd215f7
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2011 Nicira Networks.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "route-table.h"
+
+#include <assert.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+
+#include "hash.h"
+#include "hmap.h"
+#include "netlink.h"
+#include "netlink-socket.h"
+#include "ofpbuf.h"
+#include "rtnetlink.h"
+#include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(route_table);
+
+struct route_data {
+    /* Copied from struct rtmsg. */
+    unsigned char rtm_dst_len;
+
+    /* Extracted from Netlink attributes. */
+    uint32_t rta_dst; /* Destination in host byte order. 0 if missing. */
+    int rta_oif;      /* Output interface index. */
+};
+
+/* A digested version of a route message sent down by the kernel to indicate
+ * that a route has changed. */
+struct route_table_msg {
+    int nlmsg_type;       /* e.g. RTM_NEWROUTE, RTM_DELROUTE. */
+    struct route_data rd; /* Data parsed from this message. */
+};
+
+struct route_node {
+    struct hmap_node node; /* Node in route_map. */
+    struct route_data rd;  /* Data associated with this node. */
+};
+
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+
+static unsigned int register_count = 0;
+static struct rtnetlink *rtn = NULL;
+static struct route_table_msg rtmsg;
+static struct rtnetlink_notifier notifier;
+static struct hmap route_map;
+
+static int route_table_reset(void);
+static bool route_table_parse(struct ofpbuf *, struct route_table_msg *);
+static void route_table_change(const struct route_table_msg *, void *);
+static struct route_node *route_node_lookup(const struct route_data *);
+static struct route_node *route_node_lookup_by_ip(uint32_t ip);
+static void route_map_clear(void);
+static uint32_t hash_route_data(const struct route_data *);
+
+/* Populates 'ifindex' with the interface index traffic destined for 'ip' is
+ * likely to egress.  There is no hard guarantee that traffic destined for 'ip'
+ * will egress out the specified interface.  'ifindex' may refer to an
+ * interface which is not physical (such as a bridge port).
+ *
+ * Returns true if successful, otherwise false. */
+bool
+route_table_get_ifindex(ovs_be32 ip_, int *ifindex)
+{
+    struct route_node *rn;
+    uint32_t ip = ntohl(ip_);
+
+    *ifindex = 0;
+
+    rn = route_node_lookup_by_ip(ip);
+
+    if (rn) {
+        *ifindex = rn->rd.rta_oif;
+        return true;
+    }
+
+    /* Choose a default route. */
+    HMAP_FOR_EACH(rn, node, &route_map) {
+        if (rn->rd.rta_dst == 0 && rn->rd.rtm_dst_len == 0) {
+            *ifindex = rn->rd.rta_oif;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/* Users of the route_table module should register themselves with this
+ * function before making any other route_table function calls. */
+void
+route_table_register(void)
+{
+    if (!register_count) {
+        rtnetlink_parse_func *pf;
+        rtnetlink_notify_func *nf;
+
+        assert(!rtn);
+
+        pf = (rtnetlink_parse_func *)  route_table_parse;
+        nf = (rtnetlink_notify_func *) route_table_change;
+
+        rtn = rtnetlink_create(RTNLGRP_IPV4_ROUTE, pf, &rtmsg);
+        rtnetlink_notifier_register(rtn, &notifier, nf, NULL);
+
+        hmap_init(&route_map);
+        route_table_reset();
+    }
+
+    register_count++;
+}
+
+/* Users of the route_table module should unregister themselves with this
+ * function when they will no longer be making any more route_table fuction
+ * calls. */
+void
+route_table_unregister(void)
+{
+    register_count--;
+
+    if (!register_count) {
+        rtnetlink_destroy(rtn);
+        rtn = NULL;
+
+        route_map_clear();
+        hmap_destroy(&route_map);
+    }
+}
+
+/* Run periodically to update the locally maintained routing table. */
+void
+route_table_run(void)
+{
+    if (rtn) {
+        rtnetlink_notifier_run(rtn);
+    }
+}
+
+/* Causes poll_block() to wake up when route_table updates are required. */
+void
+route_table_wait(void)
+{
+    if (rtn) {
+        rtnetlink_notifier_wait(rtn);
+    }
+}
+
+static int
+route_table_reset(void)
+{
+    int error;
+    struct nl_dump dump;
+    struct rtgenmsg *rtmsg;
+    struct ofpbuf request, reply;
+    static struct nl_sock *rtnl_sock;
+
+    route_map_clear();
+
+    error = nl_sock_create(NETLINK_ROUTE, 0, 0, 0, &rtnl_sock);
+    if (error) {
+        VLOG_WARN_RL(&rl, "failed to reset routing table, "
+                     "cannot create RTNETLINK_ROUTE socket");
+        return error;
+    }
+
+    ofpbuf_init(&request, 0);
+
+    nl_msg_put_nlmsghdr(&request, sizeof *rtmsg, RTM_GETROUTE, NLM_F_REQUEST);
+
+    rtmsg = ofpbuf_put_zeros(&request, sizeof *rtmsg);
+    rtmsg->rtgen_family = AF_INET;
+
+    nl_dump_start(&dump, rtnl_sock, &request);
+
+    while (nl_dump_next(&dump, &reply)) {
+        struct route_table_msg msg;
+
+        if (route_table_parse(&reply, &msg)) {
+            route_table_change(&msg, NULL);
+        }
+    }
+
+    error = nl_dump_done(&dump);
+    nl_sock_destroy(rtnl_sock);
+
+    return error;
+}
+
+
+static bool
+route_table_parse(struct ofpbuf *buf, struct route_table_msg *change)
+{
+    bool parsed;
+
+    static const struct nl_policy policy[] = {
+        [RTA_DST] = { .type = NL_A_U32, .optional = true  },
+        [RTA_OIF] = { .type = NL_A_U32, .optional = false },
+    };
+
+    static struct nlattr *attrs[ARRAY_SIZE(policy)];
+
+    parsed = nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct rtmsg),
+                             policy, attrs, ARRAY_SIZE(policy));
+
+    if (parsed) {
+        const struct rtmsg *rtm;
+        const struct nlmsghdr *nlmsg;
+
+        nlmsg = buf->data;
+        rtm = (const struct rtmsg *) ((const char *) buf->data + NLMSG_HDRLEN);
+
+        if (rtm->rtm_family != AF_INET) {
+            VLOG_DBG_RL(&rl, "received non AF_INET rtnetlink route message");
+            return false;
+        }
+
+        memset(change, 0, sizeof *change);
+
+        change->nlmsg_type     = nlmsg->nlmsg_type;
+        change->rd.rtm_dst_len = rtm->rtm_dst_len;
+        change->rd.rta_oif     = nl_attr_get_u32(attrs[RTA_OIF]);
+
+        if (attrs[RTA_DST]) {
+            change->rd.rta_dst = ntohl(nl_attr_get_be32(attrs[RTA_DST]));
+        }
+
+    } else {
+        VLOG_DBG_RL(&rl, "received unparseable rtnetlink route message");
+    }
+
+    return parsed;
+}
+
+static void
+route_table_change(const struct route_table_msg *change, void *aux OVS_UNUSED)
+{
+    if (!change) {
+        VLOG_DBG_RL(&rl, "received NULL change message");
+        route_table_reset();
+    } else if (change->nlmsg_type == RTM_NEWROUTE) {
+        if (!route_node_lookup(&change->rd)) {
+            struct route_node *rn;
+
+            rn = xzalloc(sizeof *rn);
+            memcpy(&rn->rd, &change->rd, sizeof change->rd);
+
+            hmap_insert(&route_map, &rn->node, hash_route_data(&rn->rd));
+        } else {
+            VLOG_DBG_RL(&rl, "skipping insertion of duplicate route entry");
+        }
+    } else if (change->nlmsg_type == RTM_DELROUTE) {
+        struct route_node *rn;
+
+        rn = route_node_lookup(&change->rd);
+
+        if (rn) {
+            hmap_remove(&route_map, &rn->node);
+            free(rn);
+        } else {
+            VLOG_DBG_RL(&rl, "skipping deletion of non-existent route entry");
+        }
+    }
+}
+
+static struct route_node *
+route_node_lookup(const struct route_data *rd)
+{
+    struct route_node *rn;
+
+    HMAP_FOR_EACH_WITH_HASH(rn, node, hash_route_data(rd), &route_map) {
+        if (!memcmp(&rn->rd, rd, sizeof *rd)) {
+            return rn;
+        }
+    }
+
+    return NULL;
+}
+
+static struct route_node *
+route_node_lookup_by_ip(uint32_t ip)
+{
+    int dst_len;
+    struct route_node *rn, *rn_ret;
+
+    dst_len = -1;
+    rn_ret  = NULL;
+
+    HMAP_FOR_EACH(rn, node, &route_map) {
+        uint32_t mask = 0xffffffff << (32 - rn->rd.rtm_dst_len);
+
+        if (rn->rd.rta_dst == 0 && rn->rd.rtm_dst_len == 0) {
+            /* Default route. */
+            continue;
+        }
+
+        if (rn->rd.rtm_dst_len > dst_len &&
+            (ip & mask) == (rn->rd.rta_dst & mask)) {
+            rn_ret  = rn;
+            dst_len = rn->rd.rtm_dst_len;
+        }
+    }
+
+    return rn_ret;
+}
+
+static void
+route_map_clear(void)
+{
+    struct route_node *rn, *rn_next;
+
+    HMAP_FOR_EACH_SAFE(rn, rn_next, node, &route_map) {
+        hmap_remove(&route_map, &rn->node);
+        free(rn);
+    }
+}
+
+static uint32_t
+hash_route_data(const struct route_data *rd)
+{
+    return hash_bytes(rd, sizeof *rd, 0);
+}
diff --git a/lib/route-table.h b/lib/route-table.h
new file mode 100644 (file)
index 0000000..e7e1921
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Nicira Networks.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ROUTE_TABLE_H
+#define ROUTE_TABLE_H 1
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "openvswitch/types.h"
+
+bool route_table_get_ifindex(ovs_be32 ip, int *ifindex);
+void route_table_register(void);
+void route_table_unregister(void);
+void route_table_run(void);
+void route_table_wait(void);
+
+#endif /* route-table.h */
diff --git a/lib/rtnetlink-route.c b/lib/rtnetlink-route.c
deleted file mode 100644 (file)
index 549236e..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2009, 2010 Nicira Networks.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-
-#include "rtnetlink-route.h"
-
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <linux/rtnetlink.h>
-#include <net/if.h>
-
-#include "netlink.h"
-#include "ofpbuf.h"
-#include "rtnetlink.h"
-
-static struct rtnetlink *rtn = NULL;
-static struct rtnetlink_route_change rtn_change;
-
-/* Parses a rtnetlink message 'buf' into 'change'.  If 'buf' is unparseable,
- * leaves 'change' untouched and returns false.  Otherwise, populates 'change'
- * and returns true. */
-bool
-rtnetlink_route_parse(struct ofpbuf *buf,
-                      struct rtnetlink_route_change *change)
-{
-    bool parsed;
-
-    static const struct nl_policy policy[] = {
-        [RTA_DST] = { .type = NL_A_U32, .optional = true  },
-        [RTA_OIF] = { .type = NL_A_U32, .optional = false },
-    };
-
-    static struct nlattr *attrs[ARRAY_SIZE(policy)];
-
-    parsed = nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct rtmsg),
-                             policy, attrs, ARRAY_SIZE(policy));
-
-    if (parsed) {
-        const struct nlmsghdr *nlmsg;
-        const struct rtmsg *rtm;
-
-        nlmsg = buf->data;
-        rtm = (const struct rtmsg *) ((const char *) buf->data + NLMSG_HDRLEN);
-
-        if (rtm->rtm_family != AF_INET) {
-            return false;
-        }
-
-        change->nlmsg_type  = nlmsg->nlmsg_type;
-        change->rtm_dst_len = rtm->rtm_dst_len;
-        change->rta_oif     = nl_attr_get_u32(attrs[RTA_OIF]);
-        change->rta_dst     = (attrs[RTA_DST]
-                               ? ntohl(nl_attr_get_be32(attrs[RTA_DST]))
-                               : 0);
-    }
-
-    return parsed;
-}
-
-/* Registers 'cb' to be called with auxiliary data 'aux' with route change
- * notifications.  The notifier is stored in 'notifier', which callers must
- * not modify or free.
- *
- * Returns 0 if successful, otherwise a positive errno value. */
-int
-rtnetlink_route_notifier_register(struct rtnetlink_notifier *notifier,
-                                 rtnetlink_route_notify_func *cb, void *aux)
-{
-    rtnetlink_parse_func *pf = (rtnetlink_parse_func *) rtnetlink_route_parse;
-    rtnetlink_notify_func *nf = (rtnetlink_notify_func *) cb;
-
-    if (!rtn) {
-        rtn = rtnetlink_create(RTNLGRP_IPV4_ROUTE, pf, &rtn_change);
-    }
-
-    return rtnetlink_notifier_register(rtn, notifier, nf, aux);
-}
-
-/* Cancels notification on 'notifier', which must have previously been
- * registered with rtnetlink_route_notifier_register(). */
-void
-rtnetlink_route_notifier_unregister(struct rtnetlink_notifier *notifier)
-{
-    rtnetlink_notifier_unregister(rtn, notifier);
-}
-
-/* Calls all of the registered notifiers, passing along any as-yet-unreported
- * address change events. */
-void
-rtnetlink_route_notifier_run(void)
-{
-    if (rtn) {
-        rtnetlink_notifier_run(rtn);
-    }
-}
-
-/* Causes poll_block() to wake up when address change notifications are ready.
- */
-void
-rtnetlink_route_notifier_wait(void)
-{
-    if (rtn) {
-        rtnetlink_notifier_wait(rtn);
-    }
-}
diff --git a/lib/rtnetlink-route.h b/lib/rtnetlink-route.h
deleted file mode 100644 (file)
index c9290d3..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2009 Nicira Networks.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RTNETLINK_ROUTE_H
-#define RTNETLINK_ROUTE_H 1
-
-#include <stdbool.h>
-#include <stdint.h>
-
-struct ofpbuf;
-struct rtnetlink_notifier;
-
-/* A digested version of a route message sent down by the kernel to indicate
- * that a route has changed. */
-struct rtnetlink_route_change {
-    /* Copied from struct nlmsghdr. */
-    int nlmsg_type;               /* e.g. RTM_NEWROUTE, RTM_DELROUTE. */
-
-    /* Copied from struct rtmsg. */
-    unsigned char rtm_dst_len;
-
-    /* Extracted from Netlink attributes. */
-    uint32_t rta_dst; /* Destination in host byte order. 0 if missing. */
-    int rta_oif;      /* Output interface index. */
-};
-
-/* Function called to report that a route has changed.  'change' describes
- * the specific change.  It may be null, in which case the function must assume
- * everything has changed.  'aux' is as specified in the call to
- * rtnetlink_route_notifier_register(). */
-typedef
-void rtnetlink_route_notify_func(const struct rtnetlink_route_change *change,
-                                 void *aux);
-
-bool rtnetlink_route_parse(struct ofpbuf *, struct rtnetlink_route_change *);
-int rtnetlink_route_notifier_register(struct rtnetlink_notifier *,
-                                     rtnetlink_route_notify_func *, void *aux);
-void rtnetlink_route_notifier_unregister(struct rtnetlink_notifier *);
-void rtnetlink_route_notifier_run(void);
-void rtnetlink_route_notifier_wait(void);
-
-#endif /* rtnetlink-route.h */