diff options
Diffstat (limited to 'ospfd')
| -rw-r--r-- | ospfd/ospf_asbr.c | 70 | ||||
| -rw-r--r-- | ospfd/ospf_asbr.h | 4 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.c | 7 | ||||
| -rw-r--r-- | ospfd/ospf_vty.c | 3 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.c | 30 | ||||
| -rw-r--r-- | ospfd/ospf_zebra.h | 3 | 
6 files changed, 96 insertions, 21 deletions
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index b47c390088..738ac6d8cf 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -168,6 +168,38 @@ void ospf_external_info_delete(struct ospf *ospf, uint8_t type,  	}  } +/* + * ospf_external_info_delete_multi_instance + * + * Delete instances of the external route information for a given route type. + * The preserve_instance parameter may be used to prevent the current instance + * from being deleted. + */ +void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type, struct prefix_ipv4 p, +					      unsigned long preserve_instance) +{ +	struct route_node *rn; +	struct ospf_external *ext; +	struct list *ext_list; +	struct listnode *node; + +	ext_list = ospf->external[type]; +	if (!ext_list) +		return; + +	for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { +		if (ext->instance != preserve_instance) { +			rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p); +			if (rn) { +				ospf_external_info_free(rn->info); +				rn->info = NULL; +				route_unlock_node(rn); +				route_unlock_node(rn); +			} +		} +	} +} +  struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,  						unsigned short instance,  						struct prefix_ipv4 *p) @@ -189,6 +221,44 @@ struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,  	return NULL;  } +/* + * ospf_external_info_default_lookup + * + * For default information criteria, we really don't care about the + * source of the route and there only should be one. + */ +struct external_info *ospf_external_info_default_lookup(struct ospf *ospf) +{ +	struct ospf_external *ext; +	struct external_info *ei; +	struct list *ext_list; +	struct listnode *node; +	struct route_node *rn; +	struct prefix_ipv4 p = { +		.family = AF_INET, +		.prefixlen = 0, +		.prefix.s_addr = INADDR_ANY, +	}; + +	ext_list = ospf->external[DEFAULT_ROUTE]; +	if (!ext_list) +		return (NULL); + +	for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { +		rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p); +		if (rn) { +			route_unlock_node(rn); +			if (rn->info) { +				ei = rn->info; +				if (ei->type != ZEBRA_ROUTE_OSPF || ei->instance != ospf->instance) +					return ei; +			} +		} +	} + +	return NULL; +} +  struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf,  					     struct prefix_ipv4 *p)  { diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index 6158d65f22..648a5a11ae 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -109,6 +109,10 @@ ospf_external_info_add(struct ospf *, uint8_t, unsigned short,  		       route_tag_t, uint32_t metric);  extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short,  				      struct prefix_ipv4); +extern void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type, +						     struct prefix_ipv4 p, +						     unsigned long preserve_instance); +#define OSPF_DELETE_ANY_INSTANCE 0xffffffff  extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,  						       unsigned short,  						       struct prefix_ipv4 *); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 1350487898..7354223397 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2407,15 +2407,10 @@ struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,  static struct external_info *ospf_default_external_info(struct ospf *ospf)  {  	int type; -	struct prefix_ipv4 p;  	struct external_info *default_ei;  	int ret = 0; -	p.family = AF_INET; -	p.prefix.s_addr = 0; -	p.prefixlen = 0; - -	default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, 0, &p); +	default_ei = ospf_external_info_default_lookup(ospf);  	if (!default_ei)  		return NULL; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 0457b13337..27528f6594 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7347,6 +7347,9 @@ DEFPY (show_ip_ospf_database,  	struct in_addr *adv_router_p = NULL;  	json_object *json = NULL; +	if (instance_id != ospf_instance) +		return CMD_NOT_MY_INSTANCE; +  	if (uj)  		json = json_object_new_object();  	if (lsid_str) diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index c7cba1e20f..b718d498ae 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1292,15 +1292,14 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)  	 * originate)ZEBRA_ROUTE_MAX is used to delete the ex-info.  	 * Resolved this inconsistency by maintaining same route type.  	 */ -	if ((is_default_prefix(&pgen)) && (api.type != ZEBRA_ROUTE_OSPF)) +	if ((is_default_prefix(&pgen)) && +	    ((api.type != ZEBRA_ROUTE_OSPF) || (api.instance != ospf->instance)))  		rt_type = DEFAULT_ROUTE;  	if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) -		zlog_debug("%s: cmd %s from client %s: vrf %s(%u), p %pFX, metric %d", -			   __func__, zserv_command_string(cmd), -			   zebra_route_string(api.type), -			   ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix, -			   api.metric); +		zlog_debug("%s: cmd %s from client %s-%d: vrf %s(%u), p %pFX, metric %d", __func__, +			   zserv_command_string(cmd), zebra_route_string(api.type), api.instance, +			   ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix, api.metric);  	if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {  		/* XXX|HACK|TODO|FIXME: @@ -1315,16 +1314,17 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)  			api.tag = ospf->dtag[rt_type];  		/* -		 * Given zebra sends update for a prefix via ADD message, it -		 * should -		 * be considered as an implicit DEL for that prefix with other -		 * source -		 * types. +		 * Given zebra sends an update for a prefix via an ADD message, it +		 * will be considered as an impilict DELETE for that prefix for other +		 * types and instances other than the type and instance associated with +		 * the prefix.  		 */ -		for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) -			if (i != rt_type) -				ospf_external_info_delete(ospf, i, api.instance, -							  p); +		for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { +			unsigned long preserve_instance; + +			preserve_instance = (i == rt_type) ? api.instance : OSPF_DELETE_ANY_INSTANCE; +			ospf_external_info_delete_multi_instance(ospf, i, p, preserve_instance); +		}  		ei = ospf_external_info_add(ospf, rt_type, api.instance, p,  					    ifindex, nexthop, api.tag, diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 86a5678fc4..b83524303f 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -47,6 +47,9 @@ extern uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *,  				   struct ospf_route *);  extern struct ospf_external *ospf_external_lookup(struct ospf *, uint8_t,  						  unsigned short); + +extern struct external_info *ospf_external_info_default_lookup(struct ospf *ospf); +  extern struct ospf_external *ospf_external_add(struct ospf *, uint8_t,  					       unsigned short);  | 
