X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Froute-table.c;h=e21e80c2d3d93da6b4e3a3cfaa9614dc2f183d04;hb=a46c577af5c5855939ca3192a56396e15bebf0f8;hp=dd215f75fb9226a1be90974e4e247214df1e7536;hpb=a132aa969e44d563df76f783935d48057e9378b2;p=openvswitch diff --git a/lib/route-table.c b/lib/route-table.c index dd215f75..e21e80c2 100644 --- a/lib/route-table.c +++ b/lib/route-table.c @@ -46,6 +46,7 @@ struct route_data { /* A digested version of a route message sent down by the kernel to indicate * that a route has changed. */ struct route_table_msg { + bool relevant; /* Should this message be processed? */ int nlmsg_type; /* e.g. RTM_NEWROUTE, RTM_DELROUTE. */ struct route_data rd; /* Data parsed from this message. */ }; @@ -61,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 *); @@ -85,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) { @@ -172,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) { @@ -193,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); } } @@ -232,6 +241,16 @@ route_table_parse(struct ofpbuf *buf, struct route_table_msg *change) } memset(change, 0, sizeof *change); + change->relevant = true; + + if (rtm->rtm_scope == RT_SCOPE_NOWHERE) { + change->relevant = false; + } + + if (rtm->rtm_type != RTN_UNICAST && + rtm->rtm_type != RTN_LOCAL) { + change->relevant = false; + } change->nlmsg_type = nlmsg->nlmsg_type; change->rd.rtm_dst_len = rtm->rtm_dst_len; @@ -249,33 +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->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); + route_table_valid = false; +} - 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)); } }