2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 06:45:17 +00:00

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.
This commit is contained in:
Ethan Jackson
2011-01-13 16:29:31 -08:00
parent db2dede403
commit f0e167f0db

View File

@@ -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;
route_table_valid = false;
}
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) {
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));
}
}