if (v->cost == LS_INFINITY || v->nexthop.s_addr == 0)
if (v->cost >= LS_INFINITY || v->nexthop.s_addr == 0)
spf_calc(struct area *area){	struct lsa_tree		*tree = &area->lsa_tree;	struct vertex		*v, *w;	struct lsa_rtr_link	*rtr_link = NULL;	struct lsa_net_link	*net_link;	struct rt_node		*r;	u_int32_t		 cost2, d;	int			 i;	struct in_addr		 addr, adv_rtr, a;	enum dst_type		 type;	log_debug("spf_calc: calculation started, area ID %s",	    inet_ntoa(area->id));	/* clear SPF tree */	spf_tree_clr(area);	cand_list_clr();	/* initialize SPF tree */	if ((v = spf_root = lsa_find(area, LSA_TYPE_ROUTER, rde_router_id(),	    rde_router_id())) == NULL)		/* empty area because no interface is active */		return;	area->transit = 0;	spf_root->cost = 0;	w = NULL;	/* calculate SPF tree */	do {		/* loop links */		for (i = 0; i < lsa_num_links(v); i++) {			switch (v->type) {			case LSA_TYPE_ROUTER:				rtr_link = get_rtr_link(v, i);				switch (rtr_link->type) {				case LINK_TYPE_STUB_NET:					/* skip */					continue;				case LINK_TYPE_POINTTOPOINT:				case LINK_TYPE_VIRTUAL:					/* find router LSA */					w = lsa_find(area, LSA_TYPE_ROUTER,					    rtr_link->id, rtr_link->id);					break;				case LINK_TYPE_TRANSIT_NET:					/* find network LSA */					w = lsa_find_net(area, rtr_link->id);					break;				default:					fatalx("spf_calc: invalid link type");				}				break;			case LSA_TYPE_NETWORK:				net_link = get_net_link(v, i);				/* find router LSA */				w = lsa_find(area, LSA_TYPE_ROUTER,				    net_link->att_rtr, net_link->att_rtr);				break;			default:				fatalx("spf_calc: invalid LSA type");			}			if (w == NULL) {				log_debug("spf_calc: w = NULL");				continue;			}			if (w->lsa->hdr.age == MAX_AGE) {				log_debug("spf_calc: age = MAX_AGE");				continue;			}			if (!linked(w, v)) {				log_debug("spf_calc: w has no link to v");				continue;			}			if (v->type == LSA_TYPE_ROUTER)				d = v->cost + ntohs(rtr_link->metric);			else				d = v->cost;			if (cand_list_present(w)) {				if (d > w->cost)					continue;				if (d < w->cost) {					w->cost = d;					w->prev = v;				}				calc_next_hop(w, v);			} else {				if (w->cost == LS_INFINITY ||				    w->prev == NULL) {					w->cost = d;					cand_list_add(w);					w->prev = v;					calc_next_hop(w, v);				}			}		}		/* cand_list_dump(); */		/* get next vertex */		v = cand_list_pop();		w = NULL;	} while (v != NULL);	/* calculate route table */	RB_FOREACH(v, lsa_tree, tree) {		lsa_age(v);		if (ntohs(v->lsa->hdr.age) == MAX_AGE)			continue;		switch (v->type) {		case LSA_TYPE_ROUTER:			/* stub networks */			if (v->cost == LS_INFINITY || v->nexthop.s_addr == 0)				continue;			for (i = 0; i < lsa_num_links(v); i++) {				rtr_link = get_rtr_link(v, i);				if (rtr_link->type != LINK_TYPE_STUB_NET)					continue;				addr.s_addr = rtr_link->id;				adv_rtr.s_addr = htonl(v->adv_rtr);				rt_update(addr, mask2prefixlen(rtr_link->data),				    v->nexthop, v->cost +				    ntohs(rtr_link->metric), 0, area->id,				    adv_rtr, PT_INTRA_AREA, DT_NET,				    v->lsa->data.rtr.flags,				    v->prev == spf_root);			}			/* router, only add border and as-external routers */			if ((v->lsa->data.rtr.flags & (OSPF_RTR_B |			    OSPF_RTR_E)) == 0)				continue;			addr.s_addr = htonl(v->ls_id);			adv_rtr.s_addr = htonl(v->adv_rtr);			rt_update(addr, 32, v->nexthop, v->cost, 0, area->id,			    adv_rtr, PT_INTRA_AREA, DT_RTR,			    v->lsa->data.rtr.flags, 0);			break;		case LSA_TYPE_NETWORK:			if (v->cost >= LS_INFINITY || v->nexthop.s_addr == 0)				continue;			addr.s_addr = htonl(v->ls_id) & v->lsa->data.net.mask;			adv_rtr.s_addr = htonl(v->adv_rtr);			rt_update(addr, mask2prefixlen(v->lsa->data.net.mask),			    v->nexthop, v->cost, 0, area->id, adv_rtr,			    PT_INTRA_AREA, DT_NET, 0, v->prev == spf_root);			break;		case LSA_TYPE_SUM_NETWORK:		case LSA_TYPE_SUM_ROUTER:			/* if ABR only look at area 0.0.0.0 LSA */			/* ignore self-originated stuff */			if (v->nbr->self)				continue;			/* TODO type 3 area address range check */			if ((w = lsa_find(area, LSA_TYPE_ROUTER,			    htonl(v->adv_rtr),			    htonl(v->adv_rtr))) == NULL)				continue;			v->nexthop = w->nexthop;			v->cost = w->cost +			    (ntohl(v->lsa->data.sum.metric) & LSA_METRIC_MASK);			if (v->cost >= LS_INFINITY || v->nexthop.s_addr == 0)				continue;			adv_rtr.s_addr = htonl(v->adv_rtr);			if (v->type == LSA_TYPE_SUM_NETWORK) {				addr.s_addr = htonl(v->ls_id) &				    v->lsa->data.sum.mask;				rt_update(addr,				    mask2prefixlen(v->lsa->data.sum.mask),				    v->nexthop, v->cost, 0, area->id, adv_rtr,				    PT_INTER_AREA, DT_NET, 0, 0);			} else {				addr.s_addr = htonl(v->ls_id);				rt_update(addr, 32, v->nexthop, v->cost, 0,				    area->id, adv_rtr, PT_INTER_AREA, DT_RTR,				    v->lsa->data.rtr.flags, 0);			}			break;		default:			/* as-external LSA are stored in a different tree */			fatalx("spf_calc: invalid LSA type");		}	}	/* calculate as-external routes */	RB_FOREACH(v, lsa_tree, &rdeconf->lsa_tree) {		lsa_age(v);		if (ntohs(v->lsa->hdr.age) == MAX_AGE)			continue;		switch (v->type) {		case LSA_TYPE_EXTERNAL:			/* ignore self-originated stuff */			if (v->nbr->self)				continue;			if ((r = rt_lookup(DT_RTR, htonl(v->adv_rtr))) == NULL)				continue;			if (v->lsa->data.asext.fw_addr != 0 &&			    (r = rt_lookup(DT_NET,			    v->lsa->data.asext.fw_addr)) == NULL)				continue;#if 0			if (r->p_type != PT_INTRA_AREA &&			    r->p_type != PT_INTER_AREA)				continue;#endif			/* XXX RFC1583Compatibility */			if (r->connected) {				if (v->lsa->data.asext.fw_addr != 0)					v->nexthop.s_addr =					    v->lsa->data.asext.fw_addr;				else					v->nexthop.s_addr = htonl(v->adv_rtr);			} else				v->nexthop = r->nexthop;			if (ntohl(v->lsa->data.asext.metric) &			    LSA_ASEXT_E_FLAG) {				v->cost = r->cost;				cost2 = ntohl(v->lsa->data.asext.metric) &				     LSA_METRIC_MASK;				type = PT_TYPE2_EXT;			} else {				v->cost = r->cost +				    (ntohl(v->lsa->data.asext.metric) &				     LSA_METRIC_MASK);				cost2 = 0;				type = PT_TYPE1_EXT;			}			a.s_addr = 0;			adv_rtr.s_addr = htonl(v->adv_rtr);			addr.s_addr = htonl(v->ls_id) & v->lsa->data.asext.mask;			rt_update(addr, mask2prefixlen(v->lsa->data.asext.mask),			    v->nexthop, v->cost, cost2, a, adv_rtr, type,			    DT_NET, 0, 0);			break;		default:			fatalx("spf_calc: invalid LSA type");		}	}	/* spf_dump(area); */	log_debug("spf_calc: calculation ended, area ID %s",	    inet_ntoa(area->id));	area->num_spf_calc++;	start_spf_timer();	return;}