From: Ethan Jackson Date: Wed, 12 Jan 2011 22:55:18 +0000 (-0800) Subject: lib: Simplify rtnetlink routing functionality. X-Git-Tag: v1.1.0~488 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=a132aa969e44d563df76f783935d48057e9378b2;p=sliver-openvswitch.git lib: Simplify rtnetlink routing functionality. 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. --- diff --git a/lib/automake.mk b/lib/automake.mk index 269ab897f..fee55b2f3 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -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 diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index b006a677b..2d0d9845a 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -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" @@ -46,16 +46,7 @@ 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(); } /* 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 index 000000000..dd215f75f --- /dev/null +++ b/lib/route-table.c @@ -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 + +#include "route-table.h" + +#include +#include +#include +#include +#include + +#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); +} diff --git a/lib/route-table.h b/lib/route-table.h new file mode 100644 index 000000000..e7e1921a4 --- /dev/null +++ b/lib/route-table.h @@ -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 +#include + +#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 index 549236e65..000000000 --- a/lib/rtnetlink-route.c +++ /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 - -#include "rtnetlink-route.h" - -#include -#include -#include -#include - -#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 index c9290d374..000000000 --- a/lib/rtnetlink-route.h +++ /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 -#include - -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 */