summaryrefslogtreecommitdiff
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_route.c151
1 files changed, 77 insertions, 74 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f80bcfa9..cb15c152 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -322,20 +322,24 @@ static int
bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
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 exist_pref;
u_int32_t new_med;
u_int32_t exist_med;
- u_int32_t new_weight = 0;
- u_int32_t exist_weight = 0;
+ u_int32_t new_weight;
+ u_int32_t exist_weight;
+ uint32_t newm, existm;
struct in_addr new_id;
struct in_addr exist_id;
int new_cluster;
int exist_cluster;
- int internal_as_route = 0;
- int confed_as_route = 0;
+ int internal_as_route;
+ int confed_as_route;
int ret;
- uint32_t newm, existm;
*paths_eq = 0;
@@ -345,60 +349,59 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
if (exist == NULL)
return 1;
+ newattr = new->attr;
+ existattr = exist->attr;
+ newattre = newattr->extra;
+ existattre = existattr->extra;
+
/* 1. Weight check. */
- if (new->attr->extra)
- new_weight = new->attr->extra->weight;
- if (exist->attr->extra)
- exist_weight = exist->attr->extra->weight;
+ new_weight = exist_weight = 0;
+
+ if (newattre)
+ new_weight = newattre->weight;
+ if (existattre)
+ exist_weight = existattre->weight;
+
if (new_weight > exist_weight)
return 1;
if (new_weight < exist_weight)
return 0;
/* 2. Local preference check. */
- if (new->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- new_pref = new->attr->local_pref;
- else
- new_pref = bgp->default_local_pref;
+ new_pref = exist_pref = bgp->default_local_pref;
+
+ if (newattr->flag & ATTR_FLAG_BIT (BGP_ATTR_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)
return 1;
if (new_pref < exist_pref)
return 0;
- /* 3. Local route check. */
- if (new->sub_type == BGP_ROUTE_STATIC)
- return 1;
- if (exist->sub_type == BGP_ROUTE_STATIC)
- return 0;
-
- if (new->sub_type == BGP_ROUTE_REDISTRIBUTE)
- return 1;
- if (exist->sub_type == BGP_ROUTE_REDISTRIBUTE)
- return 0;
-
- if (new->sub_type == BGP_ROUTE_AGGREGATE)
- return 1;
- if (exist->sub_type == BGP_ROUTE_AGGREGATE)
- return 0;
+ /* 3. Local route check. We prefer:
+ * - BGP_ROUTE_STATIC
+ * - BGP_ROUTE_AGGREGATE
+ * - BGP_ROUTE_REDISTRIBUTE
+ */
+ if (! (new->sub_type == BGP_ROUTE_NORMAL))
+ return 1;
+ if (! (exist->sub_type == BGP_ROUTE_NORMAL))
+ return 0;
/* 4. AS path length check. */
if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
{
- int exist_hops = aspath_count_hops (exist->attr->aspath);
- int exist_confeds = aspath_count_confeds (exist->attr->aspath);
+ int exist_hops = aspath_count_hops (existattr->aspath);
+ int exist_confeds = aspath_count_confeds (existattr->aspath);
if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
{
int aspath_hops;
- aspath_hops = aspath_count_hops (new->attr->aspath);
- aspath_hops += aspath_count_confeds (new->attr->aspath);
+ aspath_hops = aspath_count_hops (newattr->aspath);
+ aspath_hops += aspath_count_confeds (newattr->aspath);
if ( aspath_hops < (exist_hops + exist_confeds))
return 1;
@@ -407,7 +410,7 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
}
else
{
- int newhops = aspath_count_hops (new->attr->aspath);
+ int newhops = aspath_count_hops (newattr->aspath);
if (newhops < exist_hops)
return 1;
@@ -417,24 +420,24 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
}
/* 5. Origin check. */
- if (new->attr->origin < exist->attr->origin)
+ if (newattr->origin < existattr->origin)
return 1;
- if (new->attr->origin > exist->attr->origin)
+ if (newattr->origin > existattr->origin)
return 0;
/* 6. MED check. */
- internal_as_route = (aspath_count_hops (new->attr->aspath) == 0
- && aspath_count_hops (exist->attr->aspath) == 0);
- confed_as_route = (aspath_count_confeds (new->attr->aspath) > 0
- && aspath_count_confeds (exist->attr->aspath) > 0
- && aspath_count_hops (new->attr->aspath) == 0
- && aspath_count_hops (exist->attr->aspath) == 0);
+ internal_as_route = (aspath_count_hops (newattr->aspath) == 0
+ && aspath_count_hops (existattr->aspath) == 0);
+ confed_as_route = (aspath_count_confeds (newattr->aspath) > 0
+ && aspath_count_confeds (existattr->aspath) > 0
+ && aspath_count_hops (newattr->aspath) == 0
+ && aspath_count_hops (existattr->aspath) == 0);
if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
|| (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
&& confed_as_route)
- || aspath_cmp_left (new->attr->aspath, exist->attr->aspath)
- || aspath_cmp_left_confed (new->attr->aspath, exist->attr->aspath)
+ || aspath_cmp_left (newattr->aspath, existattr->aspath)
+ || aspath_cmp_left_confed (newattr->aspath, existattr->aspath)
|| internal_as_route)
{
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. */
- if (new->peer->sort == BGP_PEER_EBGP
- && exist->peer->sort == BGP_PEER_IBGP)
- return 1;
- if (new->peer->sort == BGP_PEER_EBGP
- && exist->peer->sort == BGP_PEER_CONFED)
+ new_sort = new->peer->sort;
+ exist_sort = exist->peer->sort;
+
+ if (new_sort == BGP_PEER_EBGP
+ && (exist_sort == BGP_PEER_IBGP || exist_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)
+ if (exist_sort == BGP_PEER_EBGP
+ && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED))
return 0;
/* 8. IGP metric check. */
- newm = (new->extra ? new->extra->igpmetric : 0);
- existm = (exist->extra ? exist->extra->igpmetric : 0);
+ newm = existm = 0;
+
+ if (new->extra)
+ newm = new->extra->igpmetric;
+ if (exist->extra)
+ existm = exist->extra->igpmetric;
+
if (newm < existm)
ret = 1;
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
preferred route based on the additional decision criteria below. */
if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)
- && new->peer->sort == BGP_PEER_EBGP
- && exist->peer->sort == BGP_PEER_EBGP)
+ && new_sort == BGP_PEER_EBGP
+ && exist_sort == BGP_PEER_EBGP)
{
if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED))
return 1;
@@ -503,12 +508,12 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
}
/* 11. Rourter-ID comparision. */
- if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- new_id.s_addr = new->attr->extra->originator_id.s_addr;
+ if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+ new_id.s_addr = newattre->originator_id.s_addr;
else
new_id.s_addr = new->peer->remote_id.s_addr;
- if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- exist_id.s_addr = exist->attr->extra->originator_id.s_addr;
+ if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+ exist_id.s_addr = existattre->originator_id.s_addr;
else
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;
/* 12. Cluster length comparision. */
- if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- new_cluster = new->attr->extra->cluster->length;
- else
- new_cluster = 0;
- if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- exist_cluster = exist->attr->extra->cluster->length;
- else
- exist_cluster = 0;
+ new_cluster = exist_cluster = 0;
+
+ if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
+ new_cluster = newattre->cluster->length;
+ if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
+ exist_cluster = existattre->cluster->length;
if (new_cluster < exist_cluster)
return 1;