[Xorp-hackers] Bug in route_table_decision::find_winner

Euan Harris euan.harris at cl.cam.ac.uk
Thu Jun 14 09:49:38 PDT 2007


Hi,

I think I've found a bug in the path attribute comparisons in the  
route selection algorithm.   In some circumstances the loop that is  
supposed to select the routes with the best values of a particular  
attribute will also select one or more routes which have poorer  
values for that attribute.

Here is an example from the local preference stage; the same loop is  
replicated for all the other attributes except MED:

route_table_decision::find_winner

>     int test_pref = local_pref(alternatives.front().route(),
> 			       alternatives.front().peer_handler());
>     i = alternatives.begin(); i++;
>     while(i!=alternatives.end()) {
> 	int lp = local_pref(i->route(), i->peer_handler());
> 	XLOG_ASSERT(lp >= 0);
> 	//prefer higher preference
> 	if (lp < test_pref) {
> 	    i = alternatives.erase(i);
> 	} else if (lp > test_pref) {
> 	    test_pref = lp;
> 	    alternatives.pop_front();
> 	    i++;
> 	} else {
> 	    i++;
> 	}
>     }

The loop is supposed to select the routes with the highest local  
preference values.   If alternatives has three routes with local  
preference values [100, 100, 200] at the start then after the loop  
finishes it should only contain [200].   However the actual result is  
[100, 200] - the loop does not delete the second 100 preference route.

Another example:  a starting list of [50, 50,  
50,100,100,100,100,200,100,200,200] should be [200, 200, 200] after  
filtering but will instead be [50, 100, 100, 100, 100, 200, 200,  
200].   In this case the loop encountered new maximum values twice  
and so popped off the top two 50 pref routes but none of the 100s.

The problem is that when the loop finds a new maximum preference  
value it only pops the first route from the list:

> 	} else if (lp > test_pref) {
> 	    test_pref = lp;
> 	    alternatives.pop_front();
> 	    i++;
> 	} else {

If more than one route with that preference value has been seen all  
the others will be left on the list.   To be correct the loop should  
erase all routes from the beginning of the list to the new maximum:

> 	} else if (lp > test_pref) {
> 	    test_pref = lp;
> 	    alternatives.erase(alternatives.begin(), i);
> 	    i++;
> 	} else {

This bug would cause the wrong route to be selected if, for  
instance,  a route with lower local preference erroneously passed  
through local preference filtering and then beat a route with higher  
local preference on AS path length.

I've attached a patch against CVS HEAD which fixes the 7 filter loops  
like this in route_table_decision::find_winner and adds a test  
demonstrating the bug to test_decision{.cc,.reference}.   Apply with  
patch -p0 in the toplevel directory.

Thanks,
Euan

-------------- next part --------------
A non-text attachment was scrubbed...
Name: decision-bug.patch.gz
Type: application/x-gzip
Size: 1447 bytes
Desc: not available
Url : http://mailman.ICSI.Berkeley.EDU/pipermail/xorp-hackers/attachments/20070614/a590fd5b/attachment.gz 


More information about the Xorp-hackers mailing list