bgpd: optimize bgp_info_cmp()

* bgp_route.c: (bgp_info_cmp) Reduce indirections, precalculate some
  values that are used several times, reduce conditionals.

Signed-off-by: Jorge Boncompte [DTI2] <jorge@dti2.net>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
Jorge Boncompte [DTI2] 2012-05-07 16:52:56 +00:00 committed by David Lamparter
parent c76275ee96
commit 8ff56318a8

View File

@ -322,20 +322,24 @@ static int
bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
int *paths_eq) int *paths_eq)
{ {
struct attr *newattr, *existattr;
struct attr_extra *newattre, *existattre;
bgp_peer_sort_t new_sort;
bgp_peer_sort_t exist_sort;
u_int32_t new_pref; u_int32_t new_pref;
u_int32_t exist_pref; u_int32_t exist_pref;
u_int32_t new_med; u_int32_t new_med;
u_int32_t exist_med; u_int32_t exist_med;
u_int32_t new_weight = 0; u_int32_t new_weight;
u_int32_t exist_weight = 0; u_int32_t exist_weight;
uint32_t newm, existm;
struct in_addr new_id; struct in_addr new_id;
struct in_addr exist_id; struct in_addr exist_id;
int new_cluster; int new_cluster;
int exist_cluster; int exist_cluster;
int internal_as_route = 0; int internal_as_route;
int confed_as_route = 0; int confed_as_route;
int ret; int ret;
uint32_t newm, existm;
*paths_eq = 0; *paths_eq = 0;
@ -345,60 +349,59 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
if (exist == NULL) if (exist == NULL)
return 1; return 1;
newattr = new->attr;
existattr = exist->attr;
newattre = newattr->extra;
existattre = existattr->extra;
/* 1. Weight check. */ /* 1. Weight check. */
if (new->attr->extra) new_weight = exist_weight = 0;
new_weight = new->attr->extra->weight;
if (exist->attr->extra) if (newattre)
exist_weight = exist->attr->extra->weight; new_weight = newattre->weight;
if (existattre)
exist_weight = existattre->weight;
if (new_weight > exist_weight) if (new_weight > exist_weight)
return 1; return 1;
if (new_weight < exist_weight) if (new_weight < exist_weight)
return 0; return 0;
/* 2. Local preference check. */ /* 2. Local preference check. */
if (new->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) new_pref = exist_pref = bgp->default_local_pref;
new_pref = new->attr->local_pref;
else if (newattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
new_pref = bgp->default_local_pref; new_pref = newattr->local_pref;
if (existattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
exist_pref = existattr->local_pref;
if (exist->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
exist_pref = exist->attr->local_pref;
else
exist_pref = bgp->default_local_pref;
if (new_pref > exist_pref) if (new_pref > exist_pref)
return 1; return 1;
if (new_pref < exist_pref) if (new_pref < exist_pref)
return 0; return 0;
/* 3. Local route check. */ /* 3. Local route check. We prefer:
if (new->sub_type == BGP_ROUTE_STATIC) * - BGP_ROUTE_STATIC
return 1; * - BGP_ROUTE_AGGREGATE
if (exist->sub_type == BGP_ROUTE_STATIC) * - BGP_ROUTE_REDISTRIBUTE
return 0; */
if (! (new->sub_type == BGP_ROUTE_NORMAL))
if (new->sub_type == BGP_ROUTE_REDISTRIBUTE) return 1;
return 1; if (! (exist->sub_type == BGP_ROUTE_NORMAL))
if (exist->sub_type == BGP_ROUTE_REDISTRIBUTE) return 0;
return 0;
if (new->sub_type == BGP_ROUTE_AGGREGATE)
return 1;
if (exist->sub_type == BGP_ROUTE_AGGREGATE)
return 0;
/* 4. AS path length check. */ /* 4. AS path length check. */
if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE)) if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
{ {
int exist_hops = aspath_count_hops (exist->attr->aspath); int exist_hops = aspath_count_hops (existattr->aspath);
int exist_confeds = aspath_count_confeds (exist->attr->aspath); int exist_confeds = aspath_count_confeds (existattr->aspath);
if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED)) if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
{ {
int aspath_hops; int aspath_hops;
aspath_hops = aspath_count_hops (new->attr->aspath); aspath_hops = aspath_count_hops (newattr->aspath);
aspath_hops += aspath_count_confeds (new->attr->aspath); aspath_hops += aspath_count_confeds (newattr->aspath);
if ( aspath_hops < (exist_hops + exist_confeds)) if ( aspath_hops < (exist_hops + exist_confeds))
return 1; return 1;
@ -407,7 +410,7 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
} }
else else
{ {
int newhops = aspath_count_hops (new->attr->aspath); int newhops = aspath_count_hops (newattr->aspath);
if (newhops < exist_hops) if (newhops < exist_hops)
return 1; return 1;
@ -417,24 +420,24 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
} }
/* 5. Origin check. */ /* 5. Origin check. */
if (new->attr->origin < exist->attr->origin) if (newattr->origin < existattr->origin)
return 1; return 1;
if (new->attr->origin > exist->attr->origin) if (newattr->origin > existattr->origin)
return 0; return 0;
/* 6. MED check. */ /* 6. MED check. */
internal_as_route = (aspath_count_hops (new->attr->aspath) == 0 internal_as_route = (aspath_count_hops (newattr->aspath) == 0
&& aspath_count_hops (exist->attr->aspath) == 0); && aspath_count_hops (existattr->aspath) == 0);
confed_as_route = (aspath_count_confeds (new->attr->aspath) > 0 confed_as_route = (aspath_count_confeds (newattr->aspath) > 0
&& aspath_count_confeds (exist->attr->aspath) > 0 && aspath_count_confeds (existattr->aspath) > 0
&& aspath_count_hops (new->attr->aspath) == 0 && aspath_count_hops (newattr->aspath) == 0
&& aspath_count_hops (exist->attr->aspath) == 0); && aspath_count_hops (existattr->aspath) == 0);
if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED) if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
|| (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
&& confed_as_route) && confed_as_route)
|| aspath_cmp_left (new->attr->aspath, exist->attr->aspath) || aspath_cmp_left (newattr->aspath, existattr->aspath)
|| aspath_cmp_left_confed (new->attr->aspath, exist->attr->aspath) || aspath_cmp_left_confed (newattr->aspath, existattr->aspath)
|| internal_as_route) || internal_as_route)
{ {
new_med = bgp_med_value (new->attr, bgp); new_med = bgp_med_value (new->attr, bgp);
@ -447,22 +450,24 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
} }
/* 7. Peer type check. */ /* 7. Peer type check. */
if (new->peer->sort == BGP_PEER_EBGP new_sort = new->peer->sort;
&& exist->peer->sort == BGP_PEER_IBGP) exist_sort = exist->peer->sort;
if (new_sort == BGP_PEER_EBGP
&& (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED))
return 1; return 1;
if (new->peer->sort == BGP_PEER_EBGP if (exist_sort == BGP_PEER_EBGP
&& exist->peer->sort == BGP_PEER_CONFED) && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED))
return 1;
if (new->peer->sort == BGP_PEER_IBGP
&& exist->peer->sort == BGP_PEER_EBGP)
return 0;
if (new->peer->sort == BGP_PEER_CONFED
&& exist->peer->sort == BGP_PEER_EBGP)
return 0; return 0;
/* 8. IGP metric check. */ /* 8. IGP metric check. */
newm = (new->extra ? new->extra->igpmetric : 0); newm = existm = 0;
existm = (exist->extra ? exist->extra->igpmetric : 0);
if (new->extra)
newm = new->extra->igpmetric;
if (exist->extra)
existm = exist->extra->igpmetric;
if (newm < existm) if (newm < existm)
ret = 1; ret = 1;
if (newm > existm) if (newm > existm)
@ -493,8 +498,8 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
newer path won't displace an older one, even if it was the newer path won't displace an older one, even if it was the
preferred route based on the additional decision criteria below. */ preferred route based on the additional decision criteria below. */
if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID) if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)
&& new->peer->sort == BGP_PEER_EBGP && new_sort == BGP_PEER_EBGP
&& exist->peer->sort == BGP_PEER_EBGP) && exist_sort == BGP_PEER_EBGP)
{ {
if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED)) if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED))
return 1; return 1;
@ -503,12 +508,12 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
} }
/* 11. Rourter-ID comparision. */ /* 11. Rourter-ID comparision. */
if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
new_id.s_addr = new->attr->extra->originator_id.s_addr; new_id.s_addr = newattre->originator_id.s_addr;
else else
new_id.s_addr = new->peer->remote_id.s_addr; new_id.s_addr = new->peer->remote_id.s_addr;
if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
exist_id.s_addr = exist->attr->extra->originator_id.s_addr; exist_id.s_addr = existattre->originator_id.s_addr;
else else
exist_id.s_addr = exist->peer->remote_id.s_addr; exist_id.s_addr = exist->peer->remote_id.s_addr;
@ -518,14 +523,12 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
return 0; return 0;
/* 12. Cluster length comparision. */ /* 12. Cluster length comparision. */
if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) new_cluster = exist_cluster = 0;
new_cluster = new->attr->extra->cluster->length;
else if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
new_cluster = 0; new_cluster = newattre->cluster->length;
if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
exist_cluster = exist->attr->extra->cluster->length; exist_cluster = existattre->cluster->length;
else
exist_cluster = 0;
if (new_cluster < exist_cluster) if (new_cluster < exist_cluster)
return 1; return 1;