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
/*
- * 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.
#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. */
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);
netdev_vport_init(void)
{
netdev_vport_tnl_iface_init();
+ route_table_register();
return 0;
}
{
struct netdev_dev_vport *netdev_dev = netdev_dev_vport_cast(netdev_dev_);
+ route_table_unregister();
free(netdev_dev);
}
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. */
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);
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;
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);
}
}
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)
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);
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;
}
}
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;
}
}
--- /dev/null
+/*
+ * 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, ¬ifier, 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);
+}
--- /dev/null
+/*
+ * 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 */
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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 */