From: Ethan Jackson Date: Fri, 14 Jan 2011 00:29:31 +0000 (-0800) Subject: route-table: Handle route updates more robustly. X-Git-Tag: v1.1.0~486 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=f0e167f0dbadbe2a8d684f63ad9faf68d8cb9884;p=sliver-openvswitch.git route-table: Handle route updates more robustly. The kernel does not broadcast rtnetlink route messages in all cases one would expect. This can cause stale entires to end up in the route table which may cause incorrect results for route_table_get_ifindex() queries. This commit causes rtnetlink route messages to dump the entire route table on the next route_table_get_ifindex() query. --- diff --git a/lib/route-table.c b/lib/route-table.c index 440db8fd4..e21e80c2d 100644 --- a/lib/route-table.c +++ b/lib/route-table.c @@ -62,9 +62,12 @@ static unsigned int register_count = 0; static struct rtnetlink *rtn = NULL; static struct route_table_msg rtmsg; static struct rtnetlink_notifier notifier; + +static bool route_table_valid = false; static struct hmap route_map; static int route_table_reset(void); +static void route_table_handle_msg(const struct route_table_msg *); 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 *); @@ -86,6 +89,10 @@ route_table_get_ifindex(ovs_be32 ip_, int *ifindex) *ifindex = 0; + if (!route_table_valid) { + route_table_reset(); + } + rn = route_node_lookup_by_ip(ip); if (rn) { @@ -173,6 +180,7 @@ route_table_reset(void) static struct nl_sock *rtnl_sock; route_map_clear(); + route_table_valid = true; error = nl_sock_create(NETLINK_ROUTE, 0, 0, 0, &rtnl_sock); if (error) { @@ -194,7 +202,7 @@ route_table_reset(void) struct route_table_msg msg; if (route_table_parse(&reply, &msg)) { - route_table_change(&msg, NULL); + route_table_handle_msg(&msg); } } @@ -260,35 +268,23 @@ route_table_parse(struct ofpbuf *buf, struct route_table_msg *change) } static void -route_table_change(const struct route_table_msg *change, void *aux OVS_UNUSED) +route_table_change(const struct route_table_msg *change OVS_UNUSED, + void *aux OVS_UNUSED) { - if (!change) { - VLOG_DBG_RL(&rl, "received NULL change message"); - route_table_reset(); - } else if (!change->relevant) { - VLOG_DBG_RL(&rl, "ignoring irrelevant change message"); - } 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) { + route_table_valid = false; +} + +static void +route_table_handle_msg(const struct route_table_msg *change) +{ + if (change->relevant && change->nlmsg_type == RTM_NEWROUTE && + !route_node_lookup(&change->rd)) { struct route_node *rn; - rn = route_node_lookup(&change->rd); + rn = xzalloc(sizeof *rn); + memcpy(&rn->rd, &change->rd, sizeof change->rd); - if (rn) { - hmap_remove(&route_map, &rn->node); - free(rn); - } else { - VLOG_DBG_RL(&rl, "skipping deletion of non-existent route entry"); - } + hmap_insert(&route_map, &rn->node, hash_route_data(&rn->rd)); } }