diff options
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r-- | bgpd/bgp_route.c | 3262 |
1 files changed, 2030 insertions, 1232 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index aabd264a..bcf23db5 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -36,6 +36,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "workqueue.h" #include "bgpd/bgpd.h" + +#include "bgpd/bgp_peer.h" + #include "bgpd/bgp_table.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_attr.h" @@ -58,18 +61,18 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; extern const char *bgp_origin_long_str[]; - + static struct bgp_node * bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, struct prefix_rd *prd) { struct bgp_node *rn; struct bgp_node *prn = NULL; - + assert (table); if (!table) return NULL; - + if (safi == SAFI_MPLS_VPN) { prn = bgp_node_get (table, (struct prefix *) prd); @@ -88,7 +91,7 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix return rn; } - + /* Allocate bgp_info_extra */ static struct bgp_info_extra * bgp_info_extra_new (void) @@ -105,11 +108,11 @@ bgp_info_extra_free (struct bgp_info_extra **extra) { if ((*extra)->damp_info) bgp_damp_info_free ((*extra)->damp_info, 0); - + (*extra)->damp_info = NULL; - + XFREE (MTYPE_BGP_ROUTE_EXTRA, *extra); - + *extra = NULL; } } @@ -138,10 +141,8 @@ bgp_info_free (struct bgp_info *binfo) { if (binfo->attr) bgp_attr_unintern (&binfo->attr); - - bgp_info_extra_free (&binfo->extra); - peer_unlock (binfo->peer); /* bgp_info peer reference */ + bgp_info_extra_free (&binfo->extra); XFREE (MTYPE_BGP_ROUTE, binfo); } @@ -158,7 +159,7 @@ bgp_info_unlock (struct bgp_info *binfo) { assert (binfo && binfo->lock > 0); binfo->lock--; - + if (binfo->lock == 0) { #if 0 @@ -176,42 +177,67 @@ bgp_info_unlock (struct bgp_info *binfo) zlog_backtrace (LOG_DEBUG); } #endif - + return binfo; } void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri) { - struct bgp_info *top; + bgp_peer peer = ri->peer ; + struct bgp_info** routes_head ; - top = rn->info; - - ri->next = rn->info; - ri->prev = NULL; - if (top) - top->prev = ri; + /* add to list of routes for this bgp_node */ + ri->rn = rn ; + ri->info_next = rn->info; + ri->info_prev = NULL; + if (rn->info != NULL) + ((struct bgp_info*)rn->info)->info_prev = ri; rn->info = ri; - + + /* add to list of routes for this peer */ + routes_head = &(peer->routes_head[rn->table->afi][rn->table->safi]) ; + ri->routes_next = *routes_head ; + ri->routes_prev = NULL ; + if (*routes_head != NULL) + (*routes_head)->routes_prev = ri ; + *routes_head = ri ; + bgp_info_lock (ri); bgp_lock_node (rn); - peer_lock (ri->peer); /* bgp_info peer reference */ + bgp_peer_lock (peer); /* bgp_info peer reference */ } -/* Do the actual removal of info from RIB, for use by bgp_process +/* Do the actual removal of info from RIB, for use by bgp_process completion callback *only* */ static void bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri) { - if (ri->next) - ri->next->prev = ri->prev; - if (ri->prev) - ri->prev->next = ri->next; + bgp_peer peer = ri->peer ; + struct bgp_info** routes_head ; + + assert(ri->rn == rn) ; + + /* remove from list of routes for the bgp_node */ + if (ri->info_next) + ri->info_next->info_prev = ri->info_prev; + if (ri->info_prev) + ri->info_prev->info_next = ri->info_next; else - rn->info = ri->next; - - bgp_info_unlock (ri); - bgp_unlock_node (rn); + rn->info = ri->info_next; + + /* remove from list of routes for the peer */ + routes_head = &(peer->routes_head[rn->table->afi][rn->table->safi]) ; + if (ri->routes_next != NULL) + ri->routes_next->routes_prev = ri->routes_prev ; + if (ri->routes_prev != NULL) + ri->routes_prev->routes_next = ri->routes_next ; + else + *routes_head = ri->routes_next ; + + bgp_info_unlock (ri); /* fewer references to bgp_info */ + bgp_unlock_node (rn); /* fewer references to bgp_node */ + bgp_peer_unlock (peer); /* fewer references to peer */ } void @@ -233,7 +259,7 @@ bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri) SET_FLAG (ri->flags, BGP_INFO_VALID); } -/* Adjust pcount as required */ +/* Adjust pcount as required */ static void bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) { @@ -244,13 +270,13 @@ bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) if (rn->table->type != BGP_TABLE_MAIN || ri->peer == ri->peer->bgp->peer_self) return; - + if (BGP_INFO_HOLDDOWN (ri) && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) { - + UNSET_FLAG (ri->flags, BGP_INFO_COUNTED); - + /* slight hack, but more robust against errors. */ if (ri->peer->pcount[rn->table->afi][rn->table->safi]) ri->peer->pcount[rn->table->afi][rn->table->safi]--; @@ -260,9 +286,9 @@ bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) __func__, ri->peer->host); zlog_backtrace (LOG_WARNING); zlog_warn ("%s: Please report to Quagga bugzilla", __func__); - } + } } - else if (!BGP_INFO_HOLDDOWN (ri) + else if (!BGP_INFO_HOLDDOWN (ri) && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) { SET_FLAG (ri->flags, BGP_INFO_COUNTED); @@ -278,11 +304,11 @@ void bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag) { SET_FLAG (ri->flags, flag); - + /* early bath if we know it's not a flag that changes useability state */ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE)) return; - + bgp_pcount_adjust (rn, ri); } @@ -290,11 +316,11 @@ void bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag) { UNSET_FLAG (ri->flags, flag); - + /* early bath if we know it's not a flag that changes useability state */ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE)) return; - + bgp_pcount_adjust (rn, ri); } @@ -331,6 +357,7 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) int internal_as_route = 0; int confed_as_route = 0; int ret; + bgp_peer_sort_t new_sort, exist_sort ; /* 0. Null check. */ if (new == NULL) @@ -358,7 +385,7 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) 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) @@ -385,14 +412,14 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) { int exist_hops = aspath_count_hops (exist->attr->aspath); int exist_confeds = aspath_count_confeds (exist->attr->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); - + if ( aspath_hops < (exist_hops + exist_confeds)) return 1; if ( aspath_hops > (exist_hops + exist_confeds)) @@ -401,7 +428,7 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) else { int newhops = aspath_count_hops (new->attr->aspath); - + if (newhops < exist_hops) return 1; if (newhops > exist_hops) @@ -422,7 +449,7 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) && aspath_count_confeds (exist->attr->aspath) > 0 && aspath_count_hops (new->attr->aspath) == 0 && aspath_count_hops (exist->attr->aspath) == 0); - + if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED) || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) && confed_as_route) @@ -439,18 +466,18 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) return 0; } - /* 7. Peer type check. */ - if (peer_sort (new->peer) == BGP_PEER_EBGP - && peer_sort (exist->peer) == BGP_PEER_IBGP) + /* 7. Peer type check. CONFED and iBGP rank equal, "internal" (RFC5065) + */ + new_sort = peer_sort(new->peer) ; + exist_sort = peer_sort(exist->peer) ; + + if ((new_sort == BGP_PEER_EBGP) && (exist_sort == BGP_PEER_IBGP)) return 1; - if (peer_sort (new->peer) == BGP_PEER_EBGP - && peer_sort (exist->peer) == BGP_PEER_CONFED) + if ((new_sort == BGP_PEER_EBGP) && (exist_sort == BGP_PEER_CONFED)) return 1; - if (peer_sort (new->peer) == BGP_PEER_IBGP - && peer_sort (exist->peer) == BGP_PEER_EBGP) + if ((new_sort == BGP_PEER_IBGP) && (exist_sort == BGP_PEER_EBGP)) return 0; - if (peer_sort (new->peer) == BGP_PEER_CONFED - && peer_sort (exist->peer) == BGP_PEER_EBGP) + if ((new_sort == BGP_PEER_CONFED) && (exist_sort == BGP_PEER_EBGP)) return 0; /* 8. IGP metric check. */ @@ -458,7 +485,7 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) { uint32_t newm = (new->extra ? new->extra->igpmetric : 0); uint32_t existm = (exist->extra ? exist->extra->igpmetric : 0); - + if (newm < existm) return 1; if (newm > existm) @@ -472,8 +499,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) - && peer_sort (new->peer) == BGP_PEER_EBGP - && peer_sort (exist->peer) == BGP_PEER_EBGP) + && (new_sort == BGP_PEER_EBGP) + && (exist_sort == BGP_PEER_EBGP) ) { if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED)) return 1; @@ -532,31 +559,31 @@ bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr, #define FILTER_EXIST_WARN(F,f,filter) \ if (BGP_DEBUG (update, UPDATE_IN) \ - && !(F ## _IN (filter))) \ + && !(F ## _IN_LIST (filter))) \ plog_warn (peer->log, "%s: Could not find configured input %s-list %s!", \ peer->host, #f, F ## _IN_NAME(filter)); - + if (DISTRIBUTE_IN_NAME (filter)) { FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); - - if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY) + + if (access_list_apply (DISTRIBUTE_IN_LIST (filter), p) == FILTER_DENY) return FILTER_DENY; } if (PREFIX_LIST_IN_NAME (filter)) { FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); - - if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY) + + if (prefix_list_apply (PREFIX_LIST_IN_LIST(filter), p) == PREFIX_DENY) return FILTER_DENY; } - + if (FILTER_LIST_IN_NAME (filter)) { FILTER_EXIST_WARN(FILTER_LIST, as, filter); - - if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY) + + if (as_list_apply (FILTER_LIST_IN_LIST (filter), attr->aspath)== AS_FILTER_DENY) return FILTER_DENY; } - + return FILTER_PERMIT; #undef FILTER_EXIST_WARN } @@ -571,28 +598,29 @@ bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr, #define FILTER_EXIST_WARN(F,f,filter) \ if (BGP_DEBUG (update, UPDATE_OUT) \ - && !(F ## _OUT (filter))) \ + && !(F ## _OUT_LIST (filter))) \ plog_warn (peer->log, "%s: Could not find configured output %s-list %s!", \ peer->host, #f, F ## _OUT_NAME(filter)); if (DISTRIBUTE_OUT_NAME (filter)) { FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); - - if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY) + + if (access_list_apply (DISTRIBUTE_OUT_LIST (filter), p) == FILTER_DENY) return FILTER_DENY; } - if (PREFIX_LIST_OUT_NAME (filter)) { + if (PREFIX_LIST_OUT_REF (filter)) { FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); - - if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY) + + if (prefix_list_apply (PREFIX_LIST_OUT_LIST (filter), p) == PREFIX_DENY) return FILTER_DENY; } if (FILTER_LIST_OUT_NAME (filter)) { FILTER_EXIST_WARN(FILTER_LIST, as, filter); - - if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY) + + if (as_list_apply (FILTER_LIST_OUT_LIST (filter), attr->aspath) + == AS_FILTER_DENY) return FILTER_DENY; } @@ -606,18 +634,19 @@ bgp_community_filter (struct peer *peer, struct attr *attr) { if (attr->community) { + bgp_peer_sort_t sort = peer_sort(peer) ; + /* NO_ADVERTISE check. */ if (community_include (attr->community, COMMUNITY_NO_ADVERTISE)) return 1; /* NO_EXPORT check. */ - if (peer_sort (peer) == BGP_PEER_EBGP && + if ((sort == BGP_PEER_EBGP) && community_include (attr->community, COMMUNITY_NO_EXPORT)) return 1; /* NO_EXPORT_SUBCONFED check. */ - if (peer_sort (peer) == BGP_PEER_EBGP - || peer_sort (peer) == BGP_PEER_CONFED) + if ((sort == BGP_PEER_EBGP) || (sort == BGP_PEER_CONFED)) if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED)) return 1; } @@ -636,139 +665,447 @@ bgp_cluster_filter (struct peer *peer, struct attr *attr) cluster_id = peer->bgp->cluster_id; else cluster_id = peer->bgp->router_id; - + if (cluster_loop_check (attr->extra->cluster, cluster_id)) return 1; } return 0; } - -static int + +/*------------------------------------------------------------------------------ + * Process given attributes against any in route-map. + * + * If the result is RMAP_PERMIT, then returns address of newly internalised + * version of the attributes. + * + * If the result is RMAP_DENY, then returns NULL. + * + * The structure pointed to by attr is untouched. + * + * NB: All the elements of the incoming attr must have been internalised. + * + * This is because a copy -- bgp_attr_dup() -- of those attributes is handed + * to the route-map. Any element of the attributes which is changed is + * overwritten by the route-map -- and if it has a 0 reference count, the + * element will be deleted. Unfortunately, that leaves a dangling reference + * in the original attr. + */ +static struct attr* bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi) { struct bgp_filter *filter; - struct bgp_info info; - route_map_result_t ret; + struct attr rmap_attr_s ; + struct attr* rmap_attr ; + struct attr* use_attr ; - filter = &peer->filter[afi][safi]; + rmap_attr = NULL ; - /* Apply default weight value. */ + /* Apply default weight value. */ if (peer->weight) - (bgp_attr_extra_get (attr))->weight = peer->weight; + { + rmap_attr = &rmap_attr_s ; + bgp_attr_dup (rmap_attr, attr) ; + + (bgp_attr_extra_get (rmap_attr))->weight = peer->weight; + } ; /* Route map apply. */ + filter = &peer->filter[afi][safi]; + if (ROUTE_MAP_IN_NAME (filter)) { - /* Duplicate current value to new strucutre for modification. */ - info.peer = peer; - info.attr = attr; + struct bgp_info info_s = { 0 } ; + route_map_result_t ret; - SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN); + if (rmap_attr == NULL) + { + rmap_attr = &rmap_attr_s ; + bgp_attr_dup (rmap_attr, attr) ; + } ; - /* Apply BGP route map to the attribute. */ - ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info); + /* Duplicate current value to new structure for modification. */ + info_s.peer = peer; + info_s.attr = rmap_attr; + + SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN); + + /* Apply BGP route map to the attribute. */ + ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info_s); peer->rmap_type = 0; if (ret == RMAP_DENYMATCH) - { - /* Free newly generated AS path and community by route-map. */ - bgp_attr_flush (attr); - return RMAP_DENY; - } + { + /* Discard any new elements set by the route-map -- these will have + * reference counts == 0. + * + * Discard any "extra" part of the duplicated attributes. + */ + bgp_attr_flush (rmap_attr); + bgp_attr_extra_free (rmap_attr); + + return NULL ; + } ; + } ; + + /* If the attributes may have changed, intern the result. + * + * Otherwise, intern the incoming stuff + */ + if (rmap_attr != NULL) + { + use_attr = bgp_attr_intern(rmap_attr) ; + + bgp_attr_extra_free (rmap_attr) ; + } + else + use_attr = bgp_attr_intern(attr) ; + + return use_attr ; +} ; + +/*------------------------------------------------------------------------------ + * Structure to capture route-server route. + * + * Main purpose of this is to do any required rs-in route-map once when + * updating a set of route server clients, and not at all if there are no + * route server clients for the given afi/safi. + */ +struct rs_route +{ + bool rs_in_applied ; /* whether rs-in applied yet */ + bool rs_in_deny ; /* answer when it has been */ + + /* The orig_attr MUST have all elements interned, but may or may not be + * interned itself. + */ + struct attr* orig_attr ; /* attributes before rs-in applied */ + + /* The rs_in_attr is interned when the pointer is set. + * + * The pointer is NULL if the rs-in has not been applied, and remains NULL + * if the answer is RMAP_DENY. + */ + struct attr* rs_in_attr ; /* attributes after rs-in applied */ + + /* The other attributes of the route */ + + struct peer* peer ; + + afi_t afi ; + safi_t safi ; + + struct prefix* p ; + + int type ; + int sub_type ; + + struct prefix_rd* prd ; + u_char* tag ; +}; + +/*------------------------------------------------------------------------------ + * Set up an rs_route object. + */ +static void +bgp_rs_route_init(struct rs_route* rt, afi_t afi, safi_t safi, + struct attr* attr, struct peer* peer, struct prefix* p, + int type, int sub_type, struct prefix_rd* prd, u_char* tag) +{ + rt->rs_in_applied = false ; + rt->rs_in_deny = 0 ; /* invalid while !rs_in_applied */ + rt->rs_in_attr = NULL ; /* nothing yet */ + + rt->orig_attr = attr ; + + rt->peer = peer ; + rt->afi = afi ; + rt->safi = safi ; + rt->p = p ; + rt->type = type ; + rt->sub_type = sub_type ; + rt->prd = prd ; + rt->tag = tag ; +} ; + +/*------------------------------------------------------------------------------ + * Reset an rs_route object. + * + * Discards any rs_in_attr and clears the rs_in_applied flag. + * + * Leaves everything else -- so can be reused pretty much as is. + */ +static void +bgp_rs_route_reset(struct rs_route* rt) +{ + if (rt->rs_in_attr != NULL) + { + bgp_attr_unintern(&rt->rs_in_attr) ; + rt->rs_in_attr = NULL ; + } ; + + rt->rs_in_applied = false ; +} ; + +/*------------------------------------------------------------------------------ + * Process rt->orig_attr against any rs-in route-map. + * + * If the result is RMAP_PERMIT, then rt->rs_in_attr will be set to a newly + * internalised version of the attributes. + * + * If the result is RMAP_DENY, then rt->rs_in_attr is left NULL. + * + * The structure pointed to by rt->orig_attr is untouched. + * + * NB: All the elements of the incoming rt->orig_attr must have been + * internalised. + * + * This is because a copy -- bgp_attr_dup() -- of those attributes is handed + * to the route-map. Any element of the attributes which is changed is + * overwritten by the route-map -- and if it has a 0 reference count, the + * element will be deleted. Unfortunately, that leaves a dangling reference + * in the original rt->orig_attr. + * + * NB: must NOT be called more than once for the same "rt", hence the + * "rs_in_applied" flag. + */ +static void +bgp_rs_input_modifier (struct rs_route* rt) +{ + struct bgp_filter *filter; + + assert(! rt->rs_in_applied && (rt->rs_in_attr == NULL)) ; + + rt->rs_in_applied = true ; + + /* Route map apply. */ + filter = &rt->peer->filter[rt->afi][rt->safi]; + + if (ROUTE_MAP_RS_IN_NAME (filter)) + { + struct bgp_info info_s = { 0 } ; + route_map_result_t ret ; + struct attr* rmap_attr ; + struct attr rmap_attr_s ; + + rmap_attr = &rmap_attr_s ; + bgp_attr_dup(rmap_attr, rt->orig_attr) ; + + /* Duplicate current value to new structure for modification. */ + info_s.peer = rt->peer; + info_s.attr = rmap_attr ; + + SET_FLAG (rt->peer->rmap_type, PEER_RMAP_TYPE_RS_IN); + + /* Apply BGP route map to the attribute. */ + ret = route_map_apply(ROUTE_MAP_RS_IN(filter), rt->p, RMAP_BGP, &info_s) ; + + rt->peer->rmap_type = 0; + + if (ret == RMAP_DENYMATCH) + { + /* Discard any new elements set by the route-map -- these will have + * reference counts == 0. + */ + bgp_attr_flush (rmap_attr); + + rt->rs_in_deny = true ; /* NB: rs_in_attr is NULL */ + } + else + { + rt->rs_in_attr = bgp_attr_intern(rmap_attr) ; + rt->rs_in_deny = false ; + } ; + + /* Discard any "extra" part of the duplicated attributes. */ + bgp_attr_extra_free (rmap_attr); } - return RMAP_PERMIT; -} - -static int -bgp_export_modifier (struct peer *rsclient, struct peer *peer, - struct prefix *p, struct attr *attr, afi_t afi, safi_t safi) + else + { + /* Simply intern the original */ + rt->rs_in_attr = bgp_attr_intern(rt->orig_attr) ; + rt->rs_in_deny = false ; + } ; +} ; + +/*------------------------------------------------------------------------------ + * Take the already interned client_attr, and if required apply the export + * route-map for the peer. + * + * If not DENY, returns interned client_attr, which may or may not have changed. + * + * If DENY, returns NULL and the client_attr will have been uninterned. + */ +static struct attr* +bgp_export_modifier (struct peer *rsclient, struct rs_route* rt, + struct attr* client_attr) { struct bgp_filter *filter; - struct bgp_info info; - route_map_result_t ret; - filter = &peer->filter[afi][safi]; + /* Route map apply. */ + filter = &rt->peer->filter[rt->afi][rt->safi]; - /* Route map apply. */ if (ROUTE_MAP_EXPORT_NAME (filter)) { - /* Duplicate current value to new strucutre for modification. */ - info.peer = rsclient; - info.attr = attr; + struct bgp_info info_s = { 0 } ; + struct attr rmap_attr_s ; + struct attr* rmap_attr ; + route_map_result_t ret; + + rmap_attr = &rmap_attr_s ; + bgp_attr_dup (rmap_attr, client_attr) ; + + /* Duplicate current value to new structure for modification. */ + info_s.peer = rsclient; + info_s.attr = rmap_attr ; SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_EXPORT); - /* Apply BGP route map to the attribute. */ - ret = route_map_apply (ROUTE_MAP_EXPORT (filter), p, RMAP_BGP, &info); + /* Apply BGP route map to the attribute. */ + ret = route_map_apply(ROUTE_MAP_EXPORT(filter), rt->p, RMAP_BGP, &info_s); rsclient->rmap_type = 0; if (ret == RMAP_DENYMATCH) { - /* Free newly generated AS path and community by route-map. */ - bgp_attr_flush (attr); - return RMAP_DENY; - } - } - return RMAP_PERMIT; -} + /* Discard any new elements set by the route-map -- these will have + * reference counts == 0. + */ + bgp_attr_flush (rmap_attr); -static int -bgp_import_modifier (struct peer *rsclient, struct peer *peer, - struct prefix *p, struct attr *attr, afi_t afi, safi_t safi) + bgp_attr_unintern(&client_attr) ; + + client_attr = NULL ; + } + else + { + /* Intern the result of the rmap and unintern the old version + * + * Done in this order so that any unchanged elements in rmap_attr + * gain a reference before they are released from the old interned + * attributes. + */ + struct attr* old_attr ; + + old_attr = client_attr ; + client_attr = bgp_attr_intern(rmap_attr) ; + bgp_attr_unintern(&old_attr) ; + } ; + + /* Discard any "extra" part of the duplicated attributes. */ + bgp_attr_extra_free (rmap_attr) ; + } ; + + return client_attr ; +} ; + +/*------------------------------------------------------------------------------ + * Take the already interned client_attr, and if required apply the import + * route-map for the route server client. + * + * If not DENY, returns interned client_attr, which may or may not have changed. + * + * If DENY, returns NULL and the client_attr will have been uninterned. + */ +static struct attr* +bgp_import_modifier (struct peer *rsclient, struct rs_route* rt, + struct attr* client_attr) { struct bgp_filter *filter; - struct bgp_info info; - route_map_result_t ret; + struct attr rmap_attr_s ; + struct attr* rmap_attr ; - filter = &rsclient->filter[afi][safi]; + rmap_attr = NULL ; - /* Apply default weight value. */ - if (peer->weight) - (bgp_attr_extra_get (attr))->weight = peer->weight; + /* Apply default weight value. */ + if (rt->peer->weight) + { + rmap_attr = &rmap_attr_s ; + bgp_attr_dup (rmap_attr, client_attr) ; + + (bgp_attr_extra_get (rmap_attr))->weight = rt->peer->weight; + } ; + + /* Route map apply. */ + filter = &rsclient->filter[rt->afi][rt->safi]; - /* Route map apply. */ if (ROUTE_MAP_IMPORT_NAME (filter)) { - /* Duplicate current value to new strucutre for modification. */ - info.peer = peer; - info.attr = attr; + struct bgp_info info_s = { 0 } ; + route_map_result_t ret ; - SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT); + if (rmap_attr == NULL) + { + rmap_attr = &rmap_attr_s ; + bgp_attr_dup (rmap_attr, client_attr) ; + } ; + + /* Duplicate current value to new structure for modification. */ + /* TODO: should this be rt->peer or rsclient ?? */ + info_s.peer = rt->peer; + info_s.attr = rmap_attr; + + SET_FLAG (rt->peer->rmap_type, PEER_RMAP_TYPE_IMPORT); /* Apply BGP route map to the attribute. */ - ret = route_map_apply (ROUTE_MAP_IMPORT (filter), p, RMAP_BGP, &info); + ret = route_map_apply(ROUTE_MAP_IMPORT(filter), rt->p, RMAP_BGP, &info_s); - peer->rmap_type = 0; + rt->peer->rmap_type = 0; if (ret == RMAP_DENYMATCH) { - /* Free newly generated AS path and community by route-map. */ - bgp_attr_flush (attr); - return RMAP_DENY; + /* Discard any new elements set by the route-map -- these will have + * reference counts == 0. + * + * Discard any "extra" part of the duplicated attributes. + */ + bgp_attr_flush (rmap_attr); + bgp_attr_extra_free (rmap_attr); + + bgp_attr_unintern(&client_attr) ; + + return NULL ; } } - return RMAP_PERMIT; -} - + + /* If the attributes may have changed, intern the new result and unintern the + * old version + * + * Done in this order so that any unchanged elements in rmap_attr gain + * an extra reference before they are released from the old interned + * attributes. + */ + if (rmap_attr != NULL) + { + struct attr* old_attr ; + + old_attr = client_attr ; + client_attr = bgp_attr_intern(rmap_attr) ; + bgp_attr_unintern(&old_attr) ; + + bgp_attr_extra_free (rmap_attr) ; + } ; + + return client_attr ; +} ; + static int bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi) { - int ret; char buf[SU_ADDRSTRLEN]; struct bgp_filter *filter; struct peer *from; struct bgp *bgp; int transparent; int reflect; + bgp_peer_sort_t sort, from_sort ; from = ri->peer; filter = &peer->filter[afi][safi]; bgp = peer->bgp; - + if (DISABLE_BGP_ANNOUNCE) return 0; @@ -814,7 +1151,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, transparent = 0; /* If community is not disabled check the no-export and local. */ - if (! transparent && bgp_community_filter (peer, ri->attr)) + if (! transparent && bgp_community_filter (peer, ri->attr)) return 0; /* If the attribute has originator-id and it is same as remote @@ -823,7 +1160,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, { if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->extra->originator_id)) { - if (BGP_DEBUG (filter, FILTER)) + if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_DEBUG, "%s [Update:SEND] %s/%d originator-id is same as remote router-id", peer->host, @@ -832,7 +1169,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, return 0; } } - + /* ORF prefix-list filter check */ if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) @@ -859,8 +1196,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* AS path loop check. */ if (aspath_loop_check (ri->attr->aspath, peer->as)) { - if (BGP_DEBUG (filter, FILTER)) - zlog (peer->log, LOG_DEBUG, + if (BGP_DEBUG (filter, FILTER)) + zlog (peer->log, LOG_DEBUG, "%s [Update:SEND] suppress announcement to peer AS %u is AS path.", peer->host, peer->as); return 0; @@ -872,17 +1209,20 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, { if (aspath_loop_check(ri->attr->aspath, bgp->confed_id)) { - if (BGP_DEBUG (filter, FILTER)) - zlog (peer->log, LOG_DEBUG, + if (BGP_DEBUG (filter, FILTER)) + zlog (peer->log, LOG_DEBUG, "%s [Update:SEND] suppress announcement to peer AS %u is AS path.", peer->host, bgp->confed_id); return 0; - } + } } /* Route-Reflect check. */ - if (peer_sort (from) == BGP_PEER_IBGP && peer_sort (peer) == BGP_PEER_IBGP) + from_sort = peer_sort (from) ; + sort = peer_sort (peer) ; + + if ((from_sort == BGP_PEER_IBGP) && (sort == BGP_PEER_IBGP)) reflect = 1; else reflect = 0; @@ -909,13 +1249,12 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, return 0; } } - + /* For modify attribute, copy it to temporary structure. */ bgp_attr_dup (attr, ri->attr); - + /* If local-preference is not set. */ - if ((peer_sort (peer) == BGP_PEER_IBGP - || peer_sort (peer) == BGP_PEER_CONFED) + if (((sort == BGP_PEER_IBGP) || (sort == BGP_PEER_CONFED)) && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))) { attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); @@ -923,7 +1262,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } /* Remove MED if its an EBGP peer - will get overwritten by route-maps */ - if (peer_sort (peer) == BGP_PEER_EBGP + if ((sort == BGP_PEER_EBGP) && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) { if (ri->peer != bgp->peer_self && ! transparent @@ -936,7 +1275,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) && ((p->family == AF_INET && attr->nexthop.s_addr) #ifdef HAVE_IPV6 - || (p->family == AF_INET6 && + || (p->family == AF_INET6 && ! IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) #endif /* HAVE_IPV6 */ ))) @@ -946,10 +1285,10 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) || (p->family == AF_INET && attr->nexthop.s_addr == 0) #ifdef HAVE_IPV6 - || (p->family == AF_INET6 && + || (p->family == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) #endif /* HAVE_IPV6 */ - || (peer_sort (peer) == BGP_PEER_EBGP + || ((sort == BGP_PEER_EBGP) && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0)) { /* Set IPv4 nexthop. */ @@ -966,7 +1305,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, if (p->family == AF_INET6) { /* IPv6 global nexthop must be included. */ - memcpy (&attr->extra->mp_nexthop_global, &peer->nexthop.v6_global, + memcpy (&attr->extra->mp_nexthop_global, &peer->nexthop.v6_global, IPV6_MAX_BYTELEN); attr->extra->mp_nexthop_len = 16; } @@ -976,8 +1315,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, #ifdef HAVE_IPV6 if (p->family == AF_INET6) { - /* Left nexthop_local unchanged if so configured. */ - if ( CHECK_FLAG (peer->af_flags[afi][safi], + /* Left nexthop_local unchanged if so configured. */ + if ( CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) ) { if ( IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_local) ) @@ -987,16 +1326,16 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } /* Default nexthop_local treatment for non-RS-Clients */ - else + else { /* Link-local address should not be transit to different peer. */ attr->extra->mp_nexthop_len = 16; /* Set link-local address for shared network peer. */ - if (peer->shared_network + if (peer->shared_network && ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) { - memcpy (&attr->extra->mp_nexthop_local, &peer->nexthop.v6_local, + memcpy (&attr->extra->mp_nexthop_local, &peer->nexthop.v6_local, IPV6_MAX_BYTELEN); attr->extra->mp_nexthop_len = 32; } @@ -1015,7 +1354,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, #endif /* HAVE_IPV6 */ /* If this is EBGP peer and remove-private-AS is set. */ - if (peer_sort (peer) == BGP_PEER_EBGP + if ((sort == BGP_PEER_EBGP) && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && aspath_private_as_check (attr->aspath)) attr->aspath = aspath_empty_get (); @@ -1024,33 +1363,42 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) ) { - struct bgp_info info; - struct attr dummy_attr = { 0 }; - - info.peer = peer; - info.attr = attr; + struct bgp_info info_s = { 0 } ; + struct attr dummy_attr_s ; + struct attr* dummy_attr ; + route_map_result_t ret; + + info_s.peer = peer; /* The route reflector is not allowed to modify the attributes of the reflected IBGP routes. */ - if (peer_sort (from) == BGP_PEER_IBGP - && peer_sort (peer) == BGP_PEER_IBGP) + if ((from_sort == BGP_PEER_IBGP) && (sort == BGP_PEER_IBGP)) { - bgp_attr_dup (&dummy_attr, attr); - info.attr = &dummy_attr; + dummy_attr = &dummy_attr_s ; + bgp_attr_dup (dummy_attr, attr); + info_s.attr = dummy_attr; } + else + { + dummy_attr = NULL ; + info_s.attr = attr; + } ; - SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); + SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); if (ri->extra && ri->extra->suppress) - ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); + ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info_s); else - ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); + ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info_s); peer->rmap_type = 0; - - if (dummy_attr.extra) - bgp_attr_extra_free (&dummy_attr); - + + if (dummy_attr != NULL) + { + bgp_attr_flush (dummy_attr) ; + bgp_attr_extra_free (dummy_attr) ; + } ; + if (ret == RMAP_DENYMATCH) { bgp_attr_flush (attr); @@ -1064,10 +1412,8 @@ static int bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi) { - int ret; char buf[SU_ADDRSTRLEN]; struct bgp_filter *filter; - struct bgp_info info; struct peer *from; struct bgp *bgp; @@ -1103,7 +1449,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, peer's id. */ if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) { - if (IPV4_ADDR_SAME (&rsclient->remote_id, + if (IPV4_ADDR_SAME (&rsclient->remote_id, &ri->attr->extra->originator_id)) { if (BGP_DEBUG (filter, FILTER)) @@ -1186,11 +1532,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, if (p->family == AF_INET6) { struct attr_extra *attre = attr->extra; - + assert (attr->extra); - + /* Left nexthop_local unchanged if so configured. */ - if ( CHECK_FLAG (rsclient->af_flags[afi][safi], + if ( CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) ) { if ( IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local) ) @@ -1198,11 +1544,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, else attre->mp_nexthop_len=16; } - + /* Default nexthop_local treatment for RS-Clients */ - else - { - /* Announcer and RS-Client are both in the same network */ + else + { + /* Announcer and RS-Client are both in the same network */ if (rsclient->shared_network && from->shared_network && (rsclient->ifindex == from->ifindex)) { @@ -1238,15 +1584,18 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, /* Route map & unsuppress-map apply. */ if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) ) { - info.peer = rsclient; - info.attr = attr; + struct bgp_info info_s = { 0 } ; + route_map_result_t ret; + + info_s.peer = rsclient; + info_s.attr = attr; SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_OUT); if (ri->extra && ri->extra->suppress) - ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); + ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info_s); else - ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); + ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info_s); rsclient->rmap_type = 0; @@ -1275,11 +1624,11 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair * struct bgp_info *ri1; struct bgp_info *ri2; struct bgp_info *nextri = NULL; - + /* bgp deterministic-med */ new_select = NULL; if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - for (ri1 = rn->info; ri1; ri1 = ri1->next) + for (ri1 = rn->info; ri1; ri1 = ri1->info_next) { if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK)) continue; @@ -1287,8 +1636,8 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair * continue; new_select = ri1; - if (ri1->next) - for (ri2 = ri1->next; ri2; ri2 = ri2->next) + if (ri1->info_next) + for (ri2 = ri1->info_next; ri2; ri2 = ri2->info_next) { if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK)) continue; @@ -1315,20 +1664,20 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair * /* Check old selected route and new selected route. */ old_select = NULL; new_select = NULL; - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) + for (ri = rn->info; (ri != NULL) && (nextri = ri->info_next, 1); ri = nextri) { if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) old_select = ri; if (BGP_INFO_HOLDDOWN (ri)) { - /* reap REMOVED routes, if needs be + /* reap REMOVED routes, if needs be * selected route must stay for a while longer though */ if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) && (ri != old_select)) bgp_info_reap (rn, ri); - + continue; } @@ -1344,7 +1693,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair * if (bgp_info_cmp (bgp, ri, new_select)) new_select = ri; } - + result->old = old_select; result->new = new_select; @@ -1361,7 +1710,7 @@ bgp_process_announce_selected (struct peer *peer, struct bgp_info *selected, p = &rn->p; /* Announce route to Established peer. */ - if (peer->status != Established) + if (peer->state != bgp_peer_pEstablished) return 0; /* Address family configuration check. */ @@ -1384,43 +1733,68 @@ bgp_process_announce_selected (struct peer *peer, struct bgp_info *selected, bgp_adj_out_unset (rn, peer, p, afi, safi); break; case BGP_TABLE_RSCLIENT: - /* Announcement to peer->conf. If the route is filtered, + /* Announcement to peer->conf. If the route is filtered, withdraw it. */ - if (selected && + if (selected && bgp_announce_check_rsclient (selected, peer, p, &attr, afi, safi)) bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected); else bgp_adj_out_unset (rn, peer, p, afi, safi); break; } - + bgp_attr_extra_free (&attr); - + return 0; } -struct bgp_process_queue +struct bgp_process_queue { - struct bgp *bgp; - struct bgp_node *rn; - afi_t afi; - safi_t safi; + struct bgp* bgp ; + struct bgp_node* head ; + struct bgp_node* tail ; }; +WQ_ARGS_SIZE_OK(bgp_process_queue) ; + static wq_item_status -bgp_process_rsclient (struct work_queue *wq, void *data) +bgp_process_rsclient (struct work_queue *wq, work_queue_item item) { - struct bgp_process_queue *pq = data; - struct bgp *bgp = pq->bgp; - struct bgp_node *rn = pq->rn; - afi_t afi = pq->afi; - safi_t safi = pq->safi; + struct bgp_process_queue *pq = work_queue_item_args(item) ; + struct bgp *bgp = pq->bgp ; + struct bgp_node *rn ; + afi_t afi ; + safi_t safi ; struct bgp_info *new_select; struct bgp_info *old_select; struct bgp_info_pair old_and_new; struct listnode *node, *nnode; - struct peer *rsclient = rn->table->owner; - + struct bgp_table *table ; + struct peer *rsclient ; + + assert(wq->spec.data == item) ; + + /* Is there anything left on the queue ? */ + rn = pq->head ; + if (rn == NULL) + return WQ_SUCCESS ; + + /* hack off queue and prepare to process */ + + dassert((rn->on_wq != 0) && (rn->lock > 0)) ; + + pq->head = rn->wq_next ; + rn->wq_next = NULL ; /* Keep tidy */ + rn->on_wq = 0 ; + + table = rn->table ; + rsclient = table->owner; + afi = table->afi; + safi = table->safi; + + dassert(table->lock > 0) ; + dassert(rsclient->lock > 0) ; + /* Best path selection. */ bgp_best_selection (bgp, rn, &old_and_new); new_select = old_and_new.new; @@ -1462,41 +1836,70 @@ bgp_process_rsclient (struct work_queue *wq, void *data) if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) bgp_info_reap (rn, old_select); - - UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); - return WQ_SUCCESS; + + bgp_unlock_node (rn); + bgp_table_unlock (table); /* NB: *after* node, in case table is deleted */ + bgp_unlock (bgp); + + if (pq->head == NULL) + return WQ_SUCCESS ; + else + return WQ_REQUEUE ; } static wq_item_status -bgp_process_main (struct work_queue *wq, void *data) -{ - struct bgp_process_queue *pq = data; - struct bgp *bgp = pq->bgp; - struct bgp_node *rn = pq->rn; - afi_t afi = pq->afi; - safi_t safi = pq->safi; - struct prefix *p = &rn->p; +bgp_process_main (struct work_queue *wq, work_queue_item item) +{ + struct bgp_process_queue *pq = work_queue_item_args(item) ; + struct bgp *bgp = pq->bgp ; + struct bgp_node *rn ; + afi_t afi ; + safi_t safi ; + struct prefix *p ; struct bgp_info *new_select; struct bgp_info *old_select; struct bgp_info_pair old_and_new; struct listnode *node, *nnode; + struct bgp_table *table ; struct peer *peer; - + + assert(wq->spec.data == item) ; + + /* Is there anything left on the queue ? */ + rn = pq->head ; + if (rn == NULL) + return WQ_SUCCESS ; + + /* hack off queue and prepare to process */ + + dassert((rn->on_wq != 0) && (rn->lock > 0)) ; + + pq->head = rn->wq_next ; + rn->wq_next = NULL ; /* Keep tidy */ + rn->on_wq = 0 ; + + table = rn->table ; + afi = table->afi; + safi = table->safi; + + dassert(table->lock > 0) ; + + p = &rn->p ; + /* Best path selection. */ bgp_best_selection (bgp, rn, &old_and_new); old_select = old_and_new.old; new_select = old_and_new.new; /* Nothing to do. */ - if (old_select && old_select == new_select) + if (old_select && (old_select == new_select)) { if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED)) { if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED)) bgp_zebra_announce (p, old_select, bgp); - - UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); - return WQ_SUCCESS; + + goto finish ; /* was return ! */ } } @@ -1516,106 +1919,182 @@ bgp_process_main (struct work_queue *wq, void *data) } /* FIB update. */ - if (safi == SAFI_UNICAST && ! bgp->name && - ! bgp_option_check (BGP_OPT_NO_FIB)) + if ((safi == SAFI_UNICAST) && (bgp->name == NULL) && + ! bgp_option_check (BGP_OPT_NO_FIB)) { - if (new_select - && new_select->type == ZEBRA_ROUTE_BGP - && new_select->sub_type == BGP_ROUTE_NORMAL) + if (new_select && (new_select->type == ZEBRA_ROUTE_BGP) + && (new_select->sub_type == BGP_ROUTE_NORMAL)) bgp_zebra_announce (p, new_select, bgp); else { /* Withdraw the route from the kernel. */ - if (old_select - && old_select->type == ZEBRA_ROUTE_BGP - && old_select->sub_type == BGP_ROUTE_NORMAL) + if (old_select && (old_select->type == ZEBRA_ROUTE_BGP) + && (old_select->sub_type == BGP_ROUTE_NORMAL)) bgp_zebra_withdraw (p, old_select); } } - - /* Reap old select bgp_info, it it has been removed */ + + /* Reap old select bgp_info, it it has been removed */ if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) bgp_info_reap (rn, old_select); - - UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); - return WQ_SUCCESS; -} -static void -bgp_processq_del (struct work_queue *wq, void *data) -{ - struct bgp_process_queue *pq = data; - struct bgp_table *table = pq->rn->table; - - bgp_unlock (pq->bgp); - bgp_unlock_node (pq->rn); - bgp_table_unlock (table); - XFREE (MTYPE_BGP_PROCESS_QUEUE, pq); + /* Finish up */ + +finish: + bgp_unlock_node (rn) ; + bgp_table_unlock (table) ; /* NB: *after* node, in case table is deleted */ + bgp_unlock (bgp) ; + + if (pq->head == NULL) + return WQ_SUCCESS ; + else + return WQ_REQUEUE ; } +/*------------------------------------------------------------------------------ + * Delete item from work queue + */ static void -bgp_process_queue_init (void) +bgp_processq_del (struct work_queue *wq, work_queue_item item) { - bm->process_main_queue - = work_queue_new (bm->master, "process_main_queue"); - bm->process_rsclient_queue - = work_queue_new (bm->master, "process_rsclient_queue"); - - if ( !(bm->process_main_queue && bm->process_rsclient_queue) ) + struct bgp_process_queue *pq = work_queue_item_args(item) ; + struct bgp_node *rn ; + + assert(wq->spec.data == item) ; + + while ((rn = pq->head) != NULL) { - zlog_err ("%s: Failed to allocate work queue", __func__); - exit (1); - } - - bm->process_main_queue->spec.workfunc = &bgp_process_main; - bm->process_main_queue->spec.del_item_data = &bgp_processq_del; - bm->process_main_queue->spec.max_retries = 0; - bm->process_main_queue->spec.hold = 50; - - memcpy (bm->process_rsclient_queue, bm->process_main_queue, - sizeof (struct work_queue *)); - bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient; -} + struct bgp_table *table ; + + dassert((rn->on_wq != 0) && (rn->lock > 0)) ; + + pq->head = rn->wq_next ; + rn->wq_next = NULL ; /* Keep tidy */ + rn->on_wq = 0 ; + + table = rn->table ; + + dassert(table->lock > 0) ; + + bgp_unlock_node (rn); + bgp_table_unlock (table); /* NB: *after* node, in case table is deleted */ + bgp_unlock (pq->bgp); + } ; + + wq->spec.data = NULL ; +} ; +/*------------------------------------------------------------------------------ + * Create new work queue for given bgp instance and given type of table + */ +static work_queue +bgp_process_queue_init (struct bgp* bgp, bgp_table_t type) +{ + work_queue wq ; + const char* name ; + wq_workfunc* workfunc ; + work_queue* p_wq ; + + switch (type) + { + case BGP_TABLE_MAIN: + p_wq = &bgp->process_main_queue ; + name = "process_main_queue" ; + workfunc = &bgp_process_main ; + break ; + case BGP_TABLE_RSCLIENT: + p_wq = &bgp->process_rsclient_queue ; + name = "process_rsclient_queue" ; + workfunc = &bgp_process_rsclient ; + break ; + default: + zabort("invalid BGP table type") ; + } ; + + wq = work_queue_new (bm->master, name) ; + + wq->spec.data = NULL ; + wq->spec.errorfunc = NULL ; + wq->spec.workfunc = workfunc ; + wq->spec.del_item_data = &bgp_processq_del ; + wq->spec.completion_func = NULL ; + wq->spec.max_retries = 0 ; + wq->spec.hold = 50 ; + + return *p_wq = wq ; +} + +/*------------------------------------------------------------------------------ + * Place given route node on appropriate work queue, so that best path + * selection etc. can take place later. + */ void bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) { - struct bgp_process_queue *pqnode; - - /* already scheduled for processing? */ - if (CHECK_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED)) - return; - - if ( (bm->process_main_queue == NULL) || - (bm->process_rsclient_queue == NULL) ) - bgp_process_queue_init (); - - pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE, - sizeof (struct bgp_process_queue)); - if (!pqnode) + work_queue_item item ; + struct bgp_process_queue *pq ; + struct work_queue* wq ; + + /* already scheduled for processing? */ + if (rn->on_wq) return; - /* all unlocked in bgp_processq_del */ - bgp_table_lock (rn->table); - pqnode->rn = bgp_lock_node (rn); - pqnode->bgp = bgp; - bgp_lock (bgp); - pqnode->afi = afi; - pqnode->safi = safi; - + /* get the required work queue -- making it if necessary */ switch (rn->table->type) { case BGP_TABLE_MAIN: - work_queue_add (bm->process_main_queue, pqnode); + wq = bgp->process_main_queue ; + if (wq == NULL) + wq = bgp_process_queue_init(bgp, BGP_TABLE_MAIN) ; break; case BGP_TABLE_RSCLIENT: - work_queue_add (bm->process_rsclient_queue, pqnode); + wq = bgp->process_rsclient_queue ; + if (wq == NULL) + wq = bgp_process_queue_init(bgp, BGP_TABLE_RSCLIENT) ; break; + default: + zabort("invalid rn->table->type") ; + } + + /* get the work queue item -- making it if necessary */ + item = wq->spec.data ; + if (item == NULL) + { + /* TODO: sort out assumption that item == args */ + item = wq->spec.data = work_queue_item_add(wq) ; + pq = work_queue_item_args(item) ; + + pq->bgp = bgp ; + pq->head = NULL ; + pq->tail = NULL ; } - + else + pq = work_queue_item_args(item) ; + + /* all unlocked when processed or deleted */ + bgp_lock (bgp); + bgp_table_lock (rn->table); + bgp_lock_node (rn); + + /* add to the queue */ + if (pq->head == NULL) + pq->head = rn ; + else + pq->tail->wq_next = rn ; + + pq->tail = rn ; + rn->wq_next = NULL ; + + rn->on_wq = 1 ; + return; } +/*============================================================================*/ + +/*------------------------------------------------------------------------------ + * Max Prefix Overflow timer expired -- turn off overflow status and enable. + */ static int bgp_maximum_prefix_restart_timer (struct thread *thread) { @@ -1624,17 +2103,44 @@ bgp_maximum_prefix_restart_timer (struct thread *thread) peer = THREAD_ARG (thread); peer->t_pmax_restart = NULL; + assert(CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) ; + if (BGP_DEBUG (events, EVENTS)) zlog_debug ("%s Maximum-prefix restart timer expired, restore peering", peer->host); - peer_clear (peer); + UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); + + bgp_peer_enable(peer); return 0; } +/*------------------------------------------------------------------------------ + * If there is an active max prefix restart timer, cancel it now. + * + * NB: clears PEER_STATUS_PREFIX_OVERFLOW, but does NOT enable the peer. + */ +void +bgp_maximum_prefix_cancel_timer (struct peer *peer) +{ + if (peer->t_pmax_restart) + { + assert(CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) ; + + BGP_TIMER_OFF (peer->t_pmax_restart); + if (BGP_DEBUG (events, EVENTS)) + zlog_debug ("%s Maximum-prefix restart timer cancelled", peer->host) ; + } ; + + UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW) ; +} ; + +/*------------------------------------------------------------------------------ + * Number of prefixes has overflowed. + */ int -bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, +bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi, int always) { if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) @@ -1650,17 +2156,18 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, " "limit %ld", afi_safi_print (afi, safi), peer->host, peer->pcount[afi][safi], peer->pmax[afi][safi]); + SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - return 0; + return 0; { u_int8_t ndata[7]; if (safi == SAFI_MPLS_VPN) safi = BGP_SAFI_VPNV4; - + ndata[0] = (afi >> 8); ndata[1] = afi; ndata[2] = safi; @@ -1670,22 +2177,23 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, ndata[6] = (peer->pmax[afi][safi]); SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); - bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7); + /* Disable the peer, the timer routine will reenable. */ + bgp_peer_down_error_with_data(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7); } /* restart timer start */ if (peer->pmax_restart[afi][safi]) - { - peer->v_pmax_restart = peer->pmax_restart[afi][safi] * 60; + { + peer->v_pmax_restart = peer->pmax_restart[afi][safi] * 60; - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("%s Maximum-prefix restart timer started for %d secs", - peer->host, peer->v_pmax_restart); + if (BGP_DEBUG (events, EVENTS)) + zlog_debug ("%s Maximum-prefix restart timer started for %d secs", + peer->host, peer->v_pmax_restart); - BGP_TIMER_ON (peer->t_pmax_restart, bgp_maximum_prefix_restart_timer, - peer->v_pmax_restart); - } + BGP_TIMER_ON (peer->t_pmax_restart, bgp_maximum_prefix_restart_timer, + peer->v_pmax_restart); + } return 1; } @@ -1709,7 +2217,10 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, return 0; } -/* Unconditionally remove the route from the RIB, without taking +/*============================================================================*/ + +/*------------------------------------------------------------------------------ + * Unconditionally remove the route from the RIB, without taking * damping into consideration (eg, because the session went down) */ static void @@ -1717,10 +2228,10 @@ bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, afi_t afi, safi_t safi) { bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); - + if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) bgp_info_delete (rn, ri); /* keep historical info */ - + bgp_process (peer->bgp, rn, afi, safi); } @@ -1730,104 +2241,119 @@ bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, { int status = BGP_DAMP_NONE; - /* apply dampening, if result is suppressed, we'll be retaining + /* apply dampening, if result is suppressed, we'll be retaining * the bgp_info in the RIB for historical reference. */ if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer_sort (peer) == BGP_PEER_EBGP) - if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0)) + if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0)) == BGP_DAMP_SUPPRESSED) { bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); return; } - + bgp_rib_remove (rn, ri, peer, afi, safi); } +/*------------------------------------------------------------------------------ + * Update the given RS Client's RIB with the given route from the given peer. + * + * The peer's rs-in route-map once for all the rsclients who are to receive + * the route. + * + * Then export and import route-maps for the peer and the rsclient respectively. + */ static void -bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, - struct attr *attr, struct peer *peer, struct prefix *p, int type, - int sub_type, struct prefix_rd *prd, u_char *tag) +bgp_update_rsclient (struct peer *rsclient, struct rs_route* rt) { - struct bgp_node *rn; + struct attr* client_attr ; struct bgp *bgp; - struct attr new_attr = { 0 }; - struct attr *attr_new; - struct attr *attr_new2; + struct bgp_node *rn; struct bgp_info *ri; - struct bgp_info *new; const char *reason; char buf[SU_ADDRSTRLEN]; - /* Do not insert announces from a rsclient into its own 'bgp_table'. */ - if (peer == rsclient) + /* Do not insert announces from a rsclient into its own 'bgp_table'. */ + if (rt->peer == rsclient) return; - bgp = peer->bgp; - rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, prd); + /* Apply rs_in policy. */ + if (!rt->rs_in_applied) + bgp_rs_input_modifier(rt) ; - /* Check previously received route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type) + client_attr = NULL ; /* no attributes, yet */ + + /* Find node for this route */ + bgp = rt->peer->bgp; + rn = bgp_afi_node_get (rsclient->rib[rt->afi][rt->safi], rt->afi, rt->safi, + rt->p, rt->prd); + + /* Check previously received route. */ + for (ri = rn->info; ri; ri = ri->info_next) + if (ri->peer == rt->peer && ri->type == rt->type + && ri->sub_type == rt->sub_type) break; - /* AS path loop check. */ - if (aspath_loop_check (attr->aspath, rsclient->as) > peer->allowas_in[afi][safi]) + /* If rs-in denies the route, stop now */ + if (rt->rs_in_deny) + { + reason = "rs-in-policy;"; + goto filtered; + } ; + + /* AS path loop check. */ + if (aspath_loop_check (rt->rs_in_attr->aspath, rsclient->as) > + rt->peer->allowas_in[rt->afi][rt->safi]) { reason = "as-path contains our own AS;"; goto filtered; } - /* Route reflector originator ID check. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) - && IPV4_ADDR_SAME (&rsclient->remote_id, &attr->extra->originator_id)) + /* Route reflector originator ID check. */ + if (rt->rs_in_attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) + && IPV4_ADDR_SAME (&rsclient->remote_id, + &rt->rs_in_attr->extra->originator_id)) { reason = "originator is us;"; goto filtered; } - - bgp_attr_dup (&new_attr, attr); - /* Apply export policy. */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) && - bgp_export_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY) + /* Need own internalised version of the rs_in attributes */ + client_attr = bgp_attr_intern(rt->rs_in_attr) ; + + /* Apply export policy. */ + if (CHECK_FLAG(rt->peer->af_flags[rt->afi][rt->safi], + PEER_FLAG_RSERVER_CLIENT)) { - reason = "export-policy;"; - goto filtered; - } + client_attr = bgp_export_modifier (rsclient, rt, client_attr) ; + if (client_attr == NULL) + { + reason = "export-policy;"; + goto filtered; + } ; + } ; - attr_new2 = bgp_attr_intern (&new_attr); - /* Apply import policy. */ - if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY) + client_attr = bgp_import_modifier (rsclient, rt, client_attr) ; + if (client_attr == NULL) { - bgp_attr_unintern (&attr_new2); - reason = "import-policy;"; goto filtered; } - attr_new = bgp_attr_intern (&new_attr); - bgp_attr_unintern (&attr_new2); - /* IPv4 unicast next hop check. */ - if (afi == AFI_IP && safi == SAFI_UNICAST) + if (rt->afi == AFI_IP && rt->safi == SAFI_UNICAST) { /* Next hop must not be 0.0.0.0 nor Class E address. */ - if (new_attr.nexthop.s_addr == 0 - || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000) + if (client_attr->nexthop.s_addr == 0 + || ntohl (client_attr->nexthop.s_addr) >= 0xe0000000) { - bgp_attr_unintern (&attr_new); - reason = "martian next-hop;"; goto filtered; } } - - /* new_attr isn't passed to any functions after here */ - bgp_attr_extra_free (&new_attr); - + /* If the update is implicit withdraw. */ if (ri) { @@ -1835,109 +2361,106 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* Same attribute comes in. */ if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) - && attrhash_cmp (ri->attr, attr_new)) + && attrhash_cmp (ri->attr, client_attr)) { bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED); if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, + zlog (rt->peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s...duplicate ignored", - peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, rsclient->host); + rt->peer->host, + inet_ntop(rt->p->family, &rt->p->u.prefix, + buf, SU_ADDRSTRLEN), + rt->p->prefixlen, rsclient->host); - bgp_unlock_node (rn); - bgp_attr_unintern (&attr_new); + /* Discard the duplicate interned attributes */ + bgp_attr_unintern (&client_attr); - return; + /* Unlock node -- locked in bgp_afi_node_get() */ + bgp_unlock_node (rn); + return; /* FIN <<<<<<<<<<<<<<<<<<< */ } /* Withdraw/Announce before we fully processed the withdraw */ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) bgp_info_restore (rn, ri); - - /* Received Logging. */ - if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s", - peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, rsclient->host); - /* The attribute is changed. */ + /* The attribute is changed. */ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - /* Update to new attribute. */ + /* Discard the old attribute */ bgp_attr_unintern (&ri->attr); - ri->attr = attr_new; - + } + else + { + /* Make new BGP info. */ + ri = bgp_info_new (); + ri->type = rt->type; + ri->sub_type = rt->sub_type; + ri->peer = rt->peer; + ri->uptime = bgp_clock (); +#if 0 /* TODO: do we need this ?? */ /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) memcpy ((bgp_info_extra_get (ri))->tag, tag, 3); +#endif - bgp_info_set_flag (rn, ri, BGP_INFO_VALID); + /* Register new BGP information. */ + bgp_info_add (rn, ri); + } ; - /* Process change. */ - bgp_process (bgp, rn, afi, safi); - bgp_unlock_node (rn); + /* Set the new attributes and update any MPLS tag. + * + * Any old attributes have been discarded. + * + * Note that we are here passing responsibility for the client_attr to the + * ri entry. + */ + ri->attr = client_attr ; - return; - } + if (rt->safi == SAFI_MPLS_VPN) + memcpy ((bgp_info_extra_get (ri))->tag, rt->tag, 3); - /* Received Logging. */ + /* Received Logging. */ if (BGP_DEBUG (update, UPDATE_IN)) - { - zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s", - peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, rsclient->host); - } + zlog (rt->peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s", + rt->peer->host, + inet_ntop(rt->p->family, &rt->p->u.prefix, buf, SU_ADDRSTRLEN), + rt->p->prefixlen, rsclient->host); - /* Make new BGP info. */ - new = bgp_info_new (); - new->type = type; - new->sub_type = sub_type; - new->peer = peer; - new->attr = attr_new; - new->uptime = bgp_clock (); + /* Process change. */ + bgp_info_set_flag (rn, ri, BGP_INFO_VALID); + bgp_process (bgp, rn, rt->afi, rt->safi); - /* Update MPLS tag. */ - if (safi == SAFI_MPLS_VPN) - memcpy ((bgp_info_extra_get (new))->tag, tag, 3); - - bgp_info_set_flag (rn, new, BGP_INFO_VALID); - - /* Register new BGP information. */ - bgp_info_add (rn, new); - - /* route_node_get lock */ + /* Unlock node -- locked in bgp_afi_node_get() */ bgp_unlock_node (rn); - - /* Process change. */ - bgp_process (bgp, rn, afi, safi); - - bgp_attr_extra_free (&new_attr); - - return; - filtered: + return; /* FIN <<<<<<<<<<<<<<<<<<< */ + + /* Deal with route which has been filtered out. + * + * If there was a previous route, then remove it. + * + * If have an interned client attributes, then discard those. + */ + filtered: /* This BGP update is filtered. Log the reason then update BGP entry. */ if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, + zlog (rt->peer->log, LOG_DEBUG, "%s rcvd UPDATE about %s/%d -- DENIED for RS-client %s due to: %s", - peer->host, - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, rsclient->host, reason); + rt->peer->host, + inet_ntop (rt->p->family, &rt->p->u.prefix, buf, SU_ADDRSTRLEN), + rt->p->prefixlen, rsclient->host, reason); if (ri) - bgp_rib_remove (rn, ri, peer, afi, safi); + bgp_rib_remove (rn, ri, rt->peer, rt->afi, rt->safi); + + if (client_attr != NULL) + bgp_attr_unintern (&client_attr); bgp_unlock_node (rn); - - if (new_attr.extra) - bgp_attr_extra_free (&new_attr); - return; } @@ -1956,7 +2479,7 @@ bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, prd); /* Lookup withdrawn route. */ - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type) break; @@ -1978,20 +2501,23 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type, struct prefix_rd *prd, u_char *tag, int soft_reconfig) { - int ret; int aspath_loop_count = 0; struct bgp_node *rn; struct bgp *bgp; - struct attr new_attr = { 0 }; - struct attr *attr_new; + struct attr* use_attr ; struct bgp_info *ri; struct bgp_info *new; const char *reason; char buf[SU_ADDRSTRLEN]; + bgp_peer_sort_t sort ; + + use_attr = NULL ; /* nothing to use, yet */ bgp = peer->bgp; rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - + + sort = peer_sort(peer) ; + /* When peer's soft reconfiguration enabled. Record input packet in Adj-RIBs-In. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) @@ -1999,7 +2525,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, bgp_adj_in_set (rn, peer, attr); /* Check previously received route. */ - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type) break; @@ -2009,7 +2535,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, if (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) aspath_loop_count = 1; - if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count) + if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count) { reason = "as-path contains our own AS;"; goto filtered; @@ -2049,21 +2575,20 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, } /* Apply incoming route-map. */ - bgp_attr_dup (&new_attr, attr); - - if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY) + use_attr = bgp_input_modifier(peer, p, attr, afi, safi) ; + if (use_attr == NULL) { reason = "route-map;"; goto filtered; } /* IPv4 unicast next hop check. */ - if (afi == AFI_IP && safi == SAFI_UNICAST) + if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { /* If the peer is EBGP and nexthop is not on connected route, discard it. */ - if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1 - && ! bgp_nexthop_check_ebgp (afi, &new_attr) + if ((sort == BGP_PEER_EBGP) && (peer->ttl == 1) + && ! bgp_nexthop_check_ebgp (afi, use_attr) && ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) { reason = "non-connected next-hop;"; @@ -2072,33 +2597,31 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Next hop must not be 0.0.0.0 nor Class E address. Next hop must not be my own address. */ - if (bgp_nexthop_self (afi, &new_attr) - || new_attr.nexthop.s_addr == 0 - || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000) + if (bgp_nexthop_self (afi, use_attr) + || (use_attr->nexthop.s_addr == 0) + || (ntohl (use_attr->nexthop.s_addr) >= 0xe0000000)) { reason = "martian next-hop;"; goto filtered; } } - attr_new = bgp_attr_intern (&new_attr); - /* If the update is implicit withdraw. */ if (ri) { ri->uptime = bgp_clock (); /* Same attribute comes in. */ - if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) - && attrhash_cmp (ri->attr, attr_new)) + if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) + && attrhash_cmp (ri->attr, use_attr)) { bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED); if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) - && peer_sort (peer) == BGP_PEER_EBGP + && (sort == BGP_PEER_EBGP) && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) { - if (BGP_DEBUG (update, UPDATE_IN)) + if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), @@ -2112,7 +2635,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, } else /* Duplicate - odd */ { - if (BGP_DEBUG (update, UPDATE_IN)) + if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d...duplicate ignored", peer->host, @@ -2127,10 +2650,9 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, } } - bgp_unlock_node (rn); - bgp_attr_unintern (&attr_new); - bgp_attr_extra_free (&new_attr); - + bgp_attr_unintern (&use_attr); + + bgp_unlock_node (rn); return 0; } @@ -2138,7 +2660,8 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d, flapped quicker than processing", + zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d, " + "flapped quicker than processing", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); @@ -2146,7 +2669,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, } /* Received Logging. */ - if (BGP_DEBUG (update, UPDATE_IN)) + if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), @@ -2158,25 +2681,25 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* The attribute is changed. */ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - + /* implicit withdraw, decrement aggregate and pcount here. * only if update is accepted, they'll increment below. */ bgp_aggregate_decrement (bgp, p, ri, afi, safi); - + /* Update bgp route dampening information. */ if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) - && peer_sort (peer) == BGP_PEER_EBGP) + && (sort == BGP_PEER_EBGP)) { /* This is implicit withdraw so we should update dampening information. */ if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) - bgp_damp_withdraw (ri, rn, afi, safi, 1); + bgp_damp_withdraw (ri, rn, afi, safi, 1); } - + /* Update to new attribute. */ bgp_attr_unintern (&ri->attr); - ri->attr = attr_new; + ri->attr = use_attr ; /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) @@ -2184,24 +2707,24 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Update bgp route dampening information. */ if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) - && peer_sort (peer) == BGP_PEER_EBGP) + && (sort == BGP_PEER_EBGP)) { + int ret ; /* Now we do normal update dampening. */ ret = bgp_damp_update (ri, rn, afi, safi); if (ret == BGP_DAMP_SUPPRESSED) { bgp_unlock_node (rn); - bgp_attr_extra_free (&new_attr); return 0; } } /* Nexthop reachability check. */ if ((afi == AFI_IP || afi == AFI_IP6) - && safi == SAFI_UNICAST - && (peer_sort (peer) == BGP_PEER_IBGP - || peer_sort (peer) == BGP_PEER_CONFED - || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) + && safi == SAFI_UNICAST + && ( (sort == BGP_PEER_IBGP) + || (sort == BGP_PEER_CONFED) + || ((sort == BGP_PEER_EBGP) && (peer->ttl != 1)) || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))) { if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL)) @@ -2216,14 +2739,13 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, bgp_aggregate_increment (bgp, p, ri, afi, safi); bgp_process (bgp, rn, afi, safi); + bgp_unlock_node (rn); - bgp_attr_extra_free (&new_attr); - return 0; } /* Received Logging. */ - if (BGP_DEBUG (update, UPDATE_IN)) + if (BGP_DEBUG (update, UPDATE_IN)) { zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d", peer->host, @@ -2236,7 +2758,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, new->type = type; new->sub_type = sub_type; new->peer = peer; - new->attr = attr_new; + new->attr = use_attr; new->uptime = bgp_clock (); /* Update MPLS tag. */ @@ -2246,9 +2768,9 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Nexthop reachability check. */ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST - && (peer_sort (peer) == BGP_PEER_IBGP - || peer_sort (peer) == BGP_PEER_CONFED - || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) + && ( (sort == BGP_PEER_IBGP) + || (sort == BGP_PEER_CONFED) + || ((sort == BGP_PEER_EBGP) && (peer->ttl != 1)) || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))) { if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL)) @@ -2261,23 +2783,24 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Increment prefix */ bgp_aggregate_increment (bgp, p, new, afi, safi); - + /* Register new BGP information. */ bgp_info_add (rn, new); - - /* route_node_get lock */ - bgp_unlock_node (rn); - - bgp_attr_extra_free (&new_attr); - + /* If maximum prefix count is configured and current prefix - count exeed it. */ + count exceeds it. */ if (bgp_maximum_prefix_overflow (peer, afi, safi, 0)) - return -1; + { + bgp_unlock_node (rn); + return -1; + } ; /* Process change. */ bgp_process (bgp, rn, afi, safi); + /* route_node_get lock */ + bgp_unlock_node (rn); + return 0; /* This BGP update is filtered. Log the reason then update BGP @@ -2290,13 +2813,13 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen, reason); - if (ri) + if (ri != NULL) bgp_rib_remove (rn, ri, peer, afi, safi); + if (use_attr != NULL) + bgp_attr_unintern (&use_attr); + bgp_unlock_node (rn); - - bgp_attr_extra_free (&new_attr); - return 0; } @@ -2310,25 +2833,41 @@ bgp_update (struct peer *peer, struct prefix *p, struct attr *attr, struct bgp *bgp; int ret; + /* For all neighbors, update the main RIB */ ret = bgp_update_main (peer, p, attr, afi, safi, type, sub_type, prd, tag, soft_reconfig); + /* Update all Route-Server Client RIBs */ bgp = peer->bgp; - /* Process the update for each RS-client. */ - for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient)) + if (bgp->rsclient != NULL) { - if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) - bgp_update_rsclient (rsclient, afi, safi, attr, peer, p, type, - sub_type, prd, tag); - } + struct rs_route rt_s ; + /* Prepare the rs_route object, ready to update all rs clients active + * in this afi/safi. + */ + bgp_rs_route_init(&rt_s, afi, safi, attr, peer, p, type, sub_type, + prd, tag) ; + + /* Process the update for each RS-client. */ + for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient)) + if (CHECK_FLAG(rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) + bgp_update_rsclient (rsclient, &rt_s) ; + + /* Reset the rs_route object -- in particular discard any interned + * rs_in_attr which may have been created. + */ + bgp_rs_route_reset(&rt_s) ; + } ; + + /* Return result from bgp_update_main */ return ret; } int -bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, - afi_t afi, safi_t safi, int type, int sub_type, +bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, + afi_t afi, safi_t safi, int type, int sub_type, struct prefix_rd *prd, u_char *tag) { struct bgp *bgp; @@ -2348,7 +2887,7 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, } /* Logging. */ - if (BGP_DEBUG (update, UPDATE_IN)) + if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_DEBUG, "%s rcvd UPDATE about %s/%d -- withdrawn", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), @@ -2364,7 +2903,7 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, bgp_adj_in_unset (rn, peer); /* Lookup withdrawn route. */ - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type) break; @@ -2372,7 +2911,7 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) bgp_rib_withdraw (rn, ri, peer, afi, safi); else if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, + zlog (peer->log, LOG_DEBUG, "%s Can't find the route %s/%d", peer->host, inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); @@ -2382,7 +2921,7 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, return 0; } - + void bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) { @@ -2390,16 +2929,14 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) struct attr attr = { 0 }; struct aspath *aspath = { 0 }; struct prefix p; - struct bgp_info binfo; struct peer *from; - int ret = RMAP_DENYMATCH; - + if (!(afi == AFI_IP || afi == AFI_IP6)) return; - + bgp = peer->bgp; from = bgp->peer_self; - + bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); aspath = attr.aspath; attr.local_pref = bgp->default_local_pref; @@ -2412,23 +2949,23 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) { struct attr_extra *ae; attr.extra = NULL; - + ae = bgp_attr_extra_get (&attr); attr.extra = ae; - + str2prefix ("::/0", &p); /* IPv6 global nexthop must be included. */ - memcpy (&ae->mp_nexthop_global, &peer->nexthop.v6_global, + memcpy (&ae->mp_nexthop_global, &peer->nexthop.v6_global, IPV6_MAX_BYTELEN); ae->mp_nexthop_len = 16; - + /* If the peer is on shared nextwork and we have link-local nexthop set it. */ - if (peer->shared_network + if (peer->shared_network && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) { - memcpy (&ae->mp_nexthop_local, &peer->nexthop.v6_local, + memcpy (&ae->mp_nexthop_local, &peer->nexthop.v6_local, IPV6_MAX_BYTELEN); ae->mp_nexthop_len = 32; } @@ -2437,13 +2974,16 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) if (peer->default_rmap[afi][safi].name) { - binfo.peer = bgp->peer_self; - binfo.attr = &attr; + struct bgp_info info_s = { 0 } ; + route_map_result_t ret; + + info_s.peer = bgp->peer_self ; + info_s.attr = &attr; SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); ret = route_map_apply (peer->default_rmap[afi][safi].map, &p, - RMAP_BGP, &binfo); + RMAP_BGP, &info_s); bgp->peer_self->rmap_type = 0; @@ -2465,11 +3005,11 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE); bgp_default_update_send (peer, &attr, afi, safi, from); } - + bgp_attr_extra_free (&attr); aspath_unintern (&aspath); } - + static void bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_table *table, int rsclient) @@ -2477,7 +3017,7 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_node *rn; struct bgp_info *ri; struct attr attr = { 0 }; - + if (! table) table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi]; @@ -2486,7 +3026,7 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, bgp_default_originate (peer, afi, safi, 0); for (rn = bgp_table_top (table); rn; rn = bgp_route_next(rn)) - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) && ri->peer != peer) { if ( (rsclient) ? @@ -2495,7 +3035,7 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, bgp_adj_out_set (rn, peer, &rn->p, &attr, afi, safi, ri); else bgp_adj_out_unset (rn, peer, &rn->p, afi, safi); - + bgp_attr_extra_free (&attr); } } @@ -2506,7 +3046,7 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) struct bgp_node *rn; struct bgp_table *table; - if (peer->status != Established) + if (peer->state != bgp_peer_pEstablished) return; if (! peer->afc_nego[afi][safi]) @@ -2533,28 +3073,46 @@ bgp_announce_route_all (struct peer *peer) { afi_t afi; safi_t safi; - + for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) bgp_announce_route (peer, afi, safi); } - + static void bgp_soft_reconfig_table_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, struct bgp_table *table) { struct bgp_node *rn; struct bgp_adj_in *ain; + struct rs_route rt_s ; if (! table) table = rsclient->bgp->rib[afi][safi]; + /* Prepare the rs_route object, setting all the parts common to all routes + * which are about to announce to the rs client. + */ + bgp_rs_route_init(&rt_s, afi, safi, NULL, NULL, NULL, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL) ; + + /* Announce everything in the table. */ for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ain = rn->adj_in; ain; ain = ain->next) + for (ain = rn->adj_in; ain; ain = ain->adj_next) { - bgp_update_rsclient (rsclient, afi, safi, ain->attr, ain->peer, - &rn->p, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL); - } + rt_s.orig_attr = ain->attr ; + rt_s.peer = ain->peer ; + rt_s.p = &rn->p ; + + bgp_update_rsclient (rsclient, &rt_s) ; + + /* Reset the rs_route object -- which discards any interned rs_in_attr + * which may have been created and clears the rs_in_applied flag. + * + * Leaves everything else ! + */ + bgp_rs_route_reset(&rt_s) ; + } ; } void @@ -2562,7 +3120,7 @@ bgp_soft_reconfig_rsclient (struct peer *rsclient, afi_t afi, safi_t safi) { struct bgp_table *table; struct bgp_node *rn; - + if (safi != SAFI_MPLS_VPN) bgp_soft_reconfig_table_rsclient (rsclient, afi, safi, NULL); @@ -2572,7 +3130,7 @@ bgp_soft_reconfig_rsclient (struct peer *rsclient, afi_t afi, safi_t safi) if ((table = rn->info) != NULL) bgp_soft_reconfig_table_rsclient (rsclient, afi, safi, table); } - + static void bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_table *table) @@ -2585,7 +3143,7 @@ bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi, table = peer->bgp->rib[afi][safi]; for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ain = rn->adj_in; ain; ain = ain->next) + for (ain = rn->adj_in; ain; ain = ain->adj_next) { if (ain->peer == peer) { @@ -2608,7 +3166,7 @@ bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi) struct bgp_node *rn; struct bgp_table *table; - if (peer->status != Established) + if (peer->state != bgp_peer_pEstablished) return; if (safi != SAFI_MPLS_VPN) @@ -2619,7 +3177,332 @@ bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi) if ((table = rn->info) != NULL) bgp_soft_reconfig_table (peer, afi, safi, table); } - + +/*============================================================================== + * Clearing. + * + * There are two (quite different) forms of clearing: + * + * 1. Normal clearing -- mass withdraw of given peer's routes for all + * or individual AFI/SAFI. + * + * This is clears the routes *from* the given peer. + * + * Note that normal clearing deals with the main RIB and any RS Client + * RIBs that may also contain routes. + * + * 2. RS Client clearing -- dismantling of RS Client RIB for an AFI/SAFI. + * + * This clears out the routes *for* the given RS Client. + * + *------------------------------------------------------------------------------ + * Normal clearing + * + * This is used in two ways: + * + * 1. when a peer falls out of Established state. + * + * See: bgp_clear_route_all(). + * + * All the peer's routes in all AFI/SAFI are withdrawn, but may be subject + * to NSF. + * + * 2. when an individual AFI/SAFI is disabled. + * + * See: bgp_clear_route(). + * + * [This appears to be for Dynamic Capabilities only.] + * TODO: discover whether NSF affects Dynamic Capability route clear. + * + * All the peer's routes in the AFI/SAFI are withdrawn. (NSF ??). + * + * Normal clearing affects: + * + * 1. the main RIB in all relevant AFI/SAFI. + * + * 2. all RS Client RIBs in all relevant AFI/SAFI + * + * Any routes (ie bgp_info objects) in the affected tables are either marked + * stale or are removed all together. + * + * Any adj_in (soft reconfig) and adj_out (announcement state) objects are + * removed. + * + * The peer's: + * + * struct bgp_info* routes_head[AFI_MAX][SAFI_MAX] ; + * + * This list threads through every use of all routes which belong to + * the peer, in all RIBs. + * + * struct bgp_adj_in* adj_in_head[AFI_MAX][SAFI_MAX] ; + * + * This list threads through every copy of all routes which belong to the + * peer and which have been preserved for soft reconfiguration, in all RIBs. + * + * struct bgp_adj_out* adj_out_head[AFI_MAX][SAFI_MAX] ; + * + * This list threads through every route which has been selected for the + * peer, in all RIBs. + * + * Are maintained for exactly this purpose. + * + * NB: this is now a linear process, because the lists identify the stuff to + * be processed. + * + * Not much work is required to remove a route -- the consequences are + * dealt with by the relevant processing work queue. + * + * In theory it would be better to break up the work. A peer who announces + * 500,000 prefixes has a fair amount to do here. A peer who announces + * 10,000 prefixes to 1,000 RS Clients has 10,000,000 routes to withdraw. + * + * Nevertheless, a really hard case looks like less than 10secs work... + * For the time being, the simplicity of living without a clearing work + * queue task is preferred -- and the + * + * [The old code walked the main RIB, and then every RS Client RIB, searching + * for bgp_node objects which had bgp_info from the given peer. It then issued + * a work queue task to do the actual change (which was probably more work than + * doing the change straight away).] + * + * [The MPLS VPN stuff has a two level RIB, which the above probably doesn't + * work for... more work required, here.] + * + * TODO: fix bgp_clear_route() and MPLS VPN !! + * + *------------------------------------------------------------------------------ + * RS Client Clearing + * + * This is done when a given RS Client RIB is about to be dismantled. + * + * This walks the RS Client RIB and discards all bgp_info, adj_in and adj_out. + * (This is unconditional -- no NSF gets in the way.) + * + */ + +/*------------------------------------------------------------------------------ + * Normal clearing of a a given peer's routes. + * + * The following lists are processed: + * + * * struct bgp_info* routes_head + * + * Walks this and clears each route. + * + * * struct bgp_adj_in* adj_in_head + * * struct bgp_adj_out* adj_out_head + * + * These two are simply emptied out. + * + * NB: in the latest scheme of things this is completed immediately... + * + * ...however, retain the ability for this to kick off background or other + * activity. + * + * Returns: true <=> clearing has completed + * + */ +extern bool +bgp_clear_routes(struct peer *peer, afi_t afi, safi_t safi, bool nsf) +{ + struct bgp_info* ri ; + struct bgp_info* next_ri ; + struct bgp_adj_in* adj_in ; + struct bgp_adj_out* adj_out ; + struct bgp_adj_in** adj_in_head ; + struct bgp_adj_out** adj_out_head ; + + next_ri = peer->routes_head[afi][safi] ; + + /* If NSF requested and nsf configured for this afi/safi, do nsf and + * set flag to indicate that at least one afi/safi may have stale routes. + */ + nsf = nsf && peer->nsf[afi][safi] ; + if (nsf) + SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT) ; + + /* TODO: fix bgp_clear_route_normal() so can clear an MPLS VPN table.... */ + if (next_ri != NULL) + assert(safi != SAFI_MPLS_VPN) ; + + while (next_ri != NULL) + { + /* The current bgp_info object may vanish, so bank the next */ + ri = next_ri ; + next_ri = ri->routes_next ; + + assert (peer == ri->peer) ; + + if (nsf && ! CHECK_FLAG (ri->flags, BGP_INFO_STALE) + && ! CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) + bgp_info_set_flag (ri->rn, ri, BGP_INFO_STALE); + else + bgp_rib_remove (ri->rn, ri, peer, afi, safi); + } ; + + /* Empty out all adjacencies */ + adj_in_head = &(peer->adj_in_head[afi][safi]) ; + while ((adj_in = *adj_in_head) != NULL) + { + assert(adj_in->route_prev == NULL) ; + bgp_adj_in_remove (adj_in->rn, adj_in) ; + assert(adj_in != *adj_in_head) ; + } ; + + adj_out_head = &(peer->adj_out_head[afi][safi]) ; + while ((adj_out = *adj_out_head) != NULL) + { + assert(adj_out->route_prev == NULL) ; + bgp_adj_out_remove (adj_out->rn, adj_out, peer, afi, safi) ; + assert(adj_out != *adj_out_head) ; + } ; + + return true ; +} ; + +/*------------------------------------------------------------------------------ + * Normal clearing of given peer for all AFI/SAFI -- respecting NSF if required. + * + * NB: in the latest scheme of things this is completed immediately... + * + * ...however, retain the ability to run this in the background with the + * peer in bgp_peer_pClearing. + * + * Returns: true <=> all clearing completed + * so false => something running in the background. + */ +extern bool +bgp_clear_all_routes (struct peer *peer, bool nsf) +{ + bool completed ; + afi_t afi; + safi_t safi; + + assert(peer->state == bgp_peer_pClearing) ; + + UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT) ; + + completed = true ; + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (!bgp_clear_routes(peer, afi, safi, nsf)) + completed = false ; + + return completed ; +} ; + +/*------------------------------------------------------------------------------ + * Clear Route Server RIB for given AFI/SAFI -- unconditionally + * + * This is used to dismantle a Route Server Client's RIB -- this is removing + * all the routes from all *other* Route Server Clients that have been placed + * in this Clients RIB. + * + * Walks all the nodes in the table and discards all routes, all adj_in and + * all adj_out. + * + * Does nothing if there is no RIB for that AFI/SAFI. + */ +extern void +bgp_clear_rsclient_rib(struct peer* rsclient, afi_t afi, safi_t safi) +{ + struct bgp_node *rn ; + struct bgp_table* table ; + + table = rsclient->rib[afi][safi] ; + + if (table == NULL) + return ; /* Ignore unconfigured afi/safi or similar */ + + /* TODO: fix bgp_clear_rsclient_rib() so that will clear an MPLS VPN table. */ + passert(table->safi != SAFI_MPLS_VPN) ; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + { + struct bgp_info *ri; + struct bgp_info *next_ri ; + struct bgp_adj_in *ain; + struct bgp_adj_out *aout; + + next_ri = rn->info ; + while(next_ri != NULL) + { + ri = next_ri ; + next_ri = ri->info_next ; /* bank this */ + + bgp_rib_remove (rn, ri, rsclient, table->afi, table->safi); + } ; + + while ((ain = rn->adj_in) != NULL) + { + assert(ain->adj_prev == NULL) ; + bgp_adj_in_remove (rn, ain); + assert(ain != rn->adj_in) ; + } ; + + while ((aout = rn->adj_out) != NULL) + { + assert(aout->adj_prev == NULL) ; + bgp_adj_out_remove (rn, aout, aout->peer, table->afi, table->safi) ; + assert(aout != rn->adj_out) ; + } ; + } + return ; +} + +/*------------------------------------------------------------------------------ + * Walk main RIB and remove any adj_in for given peer. + * + * TODO: walk peer->bgp_adj_in_head[afi][safi] -- but check which table ? + */ +void +bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_adj_in *ain; + + table = peer->bgp->rib[afi][safi]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (ain = rn->adj_in; ain ; ain = ain->adj_next) + if (ain->peer == peer) + { + bgp_adj_in_remove (rn, ain); + break; + } +} ; + +/*------------------------------------------------------------------------------ + * Walk main RIB and remove all stale routes for the given peer. + * + * NB: is required to complete immediately ! + * + * TODO: walk peer->routes_head[afi][safi] + */ +void +bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_table *table; + + table = peer->bgp->rib[afi][safi]; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + { + for (ri = rn->info; ri; ri = ri->info_next) + if (ri->peer == peer) + { + if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) + bgp_rib_remove (rn, ri, peer, afi, safi); + break; + } + } +} + +#if 0 struct bgp_clear_node_queue { @@ -2627,19 +3510,21 @@ struct bgp_clear_node_queue enum bgp_clear_route_type purpose; }; +WQ_ARGS_SIZE_OK(bgp_clear_node_queue) ; + static wq_item_status -bgp_clear_route_node (struct work_queue *wq, void *data) +bgp_clear_route_node (struct work_queue *wq, work_queue_item item) { - struct bgp_clear_node_queue *cnq = data; + struct bgp_clear_node_queue *cnq = work_queue_item_args(item) ; struct bgp_node *rn = cnq->rn; struct peer *peer = wq->spec.data; struct bgp_info *ri; afi_t afi = rn->table->afi; safi_t safi = rn->table->safi; - + assert (rn && peer); - - for (ri = rn->info; ri; ri = ri->next) + + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == peer || cnq->purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT) { /* graceful restart STALE flag set. */ @@ -2656,33 +3541,39 @@ bgp_clear_route_node (struct work_queue *wq, void *data) } static void -bgp_clear_node_queue_del (struct work_queue *wq, void *data) +bgp_clear_node_queue_del (struct work_queue *wq, work_queue_item item) { - struct bgp_clear_node_queue *cnq = data; + struct bgp_clear_node_queue *cnq = work_queue_item_args(item) ; struct bgp_node *rn = cnq->rn; struct bgp_table *table = rn->table; - - bgp_unlock_node (rn); + + bgp_unlock_node (rn); bgp_table_unlock (table); - XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cnq); } static void bgp_clear_node_complete (struct work_queue *wq) { struct peer *peer = wq->spec.data; - - /* Tickle FSM to start moving again */ - BGP_EVENT_ADD (peer, Clearing_Completed); - peer_unlock (peer); /* bgp_clear_route */ + /* Flush the event queue and ensure the peer is shut down */ + bgp_peer_stop(peer); + BGP_EVENT_FLUSH (peer); + if (peer->state == bgp_peer_pClearing) + { + peer_change_status (peer, bgp_peer_pIdle); + /* enable peer if required */ + bgp_peer_enable(peer); + } + + bgp_peer_unlock (peer); /* bgp_clear_route */ } static void bgp_clear_node_queue_init (struct peer *peer) { char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")]; - + snprintf (wname, sizeof(wname), "clear %s", peer->host); #undef CLEAR_QUEUE_NAME_LEN @@ -2696,112 +3587,22 @@ bgp_clear_node_queue_init (struct peer *peer) peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del; peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete; peer->clear_node_queue->spec.max_retries = 0; - + /* we only 'lock' this peer reference when the queue is actually active */ peer->clear_node_queue->spec.data = peer; } -static void -bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, - struct bgp_table *table, struct peer *rsclient, - enum bgp_clear_route_type purpose) -{ - struct bgp_node *rn; - - - if (! table) - table = (rsclient) ? rsclient->rib[afi][safi] : peer->bgp->rib[afi][safi]; - - /* If still no table => afi/safi isn't configured at all or smth. */ - if (! table) - return; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - struct bgp_info *ri; - struct bgp_adj_in *ain; - struct bgp_adj_out *aout; - - if (rn->info == NULL) - continue; - - /* XXX:TODO: This is suboptimal, every non-empty route_node is - * queued for every clearing peer, regardless of whether it is - * relevant to the peer at hand. - * - * Overview: There are 3 different indices which need to be - * scrubbed, potentially, when a peer is removed: - * - * 1 peer's routes visible via the RIB (ie accepted routes) - * 2 peer's routes visible by the (optional) peer's adj-in index - * 3 other routes visible by the peer's adj-out index - * - * 3 there is no hurry in scrubbing, once the struct peer is - * removed from bgp->peer, we could just GC such deleted peer's - * adj-outs at our leisure. - * - * 1 and 2 must be 'scrubbed' in some way, at least made - * invisible via RIB index before peer session is allowed to be - * brought back up. So one needs to know when such a 'search' is - * complete. - * - * Ideally: - * - * - there'd be a single global queue or a single RIB walker - * - rather than tracking which route_nodes still need to be - * examined on a peer basis, we'd track which peers still - * aren't cleared - * - * Given that our per-peer prefix-counts now should be reliable, - * this may actually be achievable. It doesn't seem to be a huge - * problem at this time, - */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT) - { - struct bgp_clear_node_queue *cnq; - - /* both unlocked in bgp_clear_node_queue_del */ - bgp_table_lock (rn->table); - bgp_lock_node (rn); - cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE, - sizeof (struct bgp_clear_node_queue)); - cnq->rn = rn; - cnq->purpose = purpose; - work_queue_add (peer->clear_node_queue, cnq); - break; - } - - for (ain = rn->adj_in; ain; ain = ain->next) - if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT) - { - bgp_adj_in_remove (rn, ain); - bgp_unlock_node (rn); - break; - } - for (aout = rn->adj_out; aout; aout = aout->next) - if (aout->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT) - { - bgp_adj_out_remove (rn, aout, peer, afi, safi); - bgp_unlock_node (rn); - break; - } - } - return; -} - void -bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi, - enum bgp_clear_route_type purpose) +bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi) { - struct bgp_node *rn; - struct bgp_table *table; - struct peer *rsclient; - struct listnode *node, *nnode; +//struct bgp_node *rn; +//struct bgp_table *table; +//struct peer *rsclient; +//struct listnode *node, *nnode; + +//if (peer->clear_node_queue == NULL) +// bgp_clear_node_queue_init (peer); - if (peer->clear_node_queue == NULL) - bgp_clear_node_queue_init (peer); - /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to * Idle until it receives a Clearing_Completed event. This protects * against peers which flap faster than we can we clear, which could @@ -2814,37 +3615,45 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi, * on the process_main queue. Fast-flapping could cause that queue * to grow and grow. */ - if (!peer->clear_node_queue->thread) - peer_lock (peer); /* bgp_clear_node_complete */ +//if (!peer->clear_node_queue->thread) + bgp_peer_lock (peer); /* bgp_clear_node_complete */ switch (purpose) { case BGP_CLEAR_ROUTE_NORMAL: + if (peer->routes_head[afi][safi] == NULL) + break ; + if (safi != SAFI_MPLS_VPN) - bgp_clear_route_table (peer, afi, safi, NULL, NULL, purpose); + bgp_clear_route_normal(peer, afi, safi) ; else +/* TODO: how to deal with SAFI_MPLS_VPN in bgp_clear_route ?? */ + passert(0) ; +#if 0 for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) if ((table = rn->info) != NULL) bgp_clear_route_table (peer, afi, safi, table, NULL, purpose); - +#endif +#if 0 for (ALL_LIST_ELEMENTS (peer->bgp->rsclient, node, nnode, rsclient)) if (CHECK_FLAG(rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) bgp_clear_route_table (peer, afi, safi, NULL, rsclient, purpose); +#endif break; case BGP_CLEAR_ROUTE_MY_RSCLIENT: - bgp_clear_route_table (peer, afi, safi, NULL, peer, purpose); + bgp_clear_route_table (peer, peer->rib[afi][safi]) ; break; default: assert (0); break; } - + /* If no routes were cleared, nothing was added to workqueue, the - * completion function won't be run by workqueue code - call it here. + * completion function won't be run by workqueue code - call it here. * XXX: Actually, this assumption doesn't hold, see * bgp_clear_route_table(), we queue all non-empty nodes. * @@ -2862,62 +3671,17 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi, * pre-Established, avoiding above list and table scans. Once we're * sure it is safe.. */ - if (!peer->clear_node_queue->thread) - bgp_clear_node_complete (peer->clear_node_queue); -} - -void -bgp_clear_route_all (struct peer *peer) -{ - afi_t afi; - safi_t safi; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL); -} + /* The following was in bgp_clear_node_complete */ -void -bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi) -{ - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_adj_in *ain; - - table = peer->bgp->rib[afi][safi]; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ain = rn->adj_in; ain ; ain = ain->next) - if (ain->peer == peer) - { - bgp_adj_in_remove (rn, ain); - bgp_unlock_node (rn); - break; - } + bgp_peer_unlock (peer); /* bgp_clear_route */ } +#endif -void -bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi) -{ - struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_table *table; - - table = peer->bgp->rib[afi][safi]; +/*============================================================================*/ - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer) - { - if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) - bgp_rib_remove (rn, ri, peer, afi, safi); - break; - } - } -} - -/* Delete all kernel routes. */ +#if 0 +/* Delete all kernel routes. */ void bgp_cleanup_routes (void) { @@ -2932,32 +3696,32 @@ bgp_cleanup_routes (void) table = bgp->rib[AFI_IP][SAFI_UNICAST]; for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP + && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_NORMAL) bgp_zebra_withdraw (&rn->p, ri); table = bgp->rib[AFI_IP6][SAFI_UNICAST]; for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP + && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_NORMAL) bgp_zebra_withdraw (&rn->p, ri); } } +#endif void bgp_reset (void) { - vty_reset (); bgp_zclient_reset (); access_list_reset (); prefix_list_reset (); } - + /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr value. */ int @@ -2970,9 +3734,9 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) int ret; /* Check peer status. */ - if (peer->status != Established) + if (peer->state != bgp_peer_pEstablished) return 0; - + pnt = packet->nlri; lim = pnt + packet->length; @@ -2984,7 +3748,7 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) /* Fetch prefix length. */ p.prefixlen = *pnt++; p.family = afi2family (packet->afi); - + /* Already checked in nlri_sanity_check(). We do double check here. */ if ((packet->afi == AFI_IP && p.prefixlen > 32) @@ -3006,16 +3770,16 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) { if (IN_CLASSD (ntohl (p.u.prefix4.s_addr))) { - /* - * From draft-ietf-idr-bgp4-22, Section 6.3: + /* + * From draft-ietf-idr-bgp4-22, Section 6.3: * If a BGP router receives an UPDATE message with a * semantically incorrect NLRI field, in which a prefix is * semantically incorrect (eg. an unexpected multicast IP * address), it should ignore the prefix. */ - zlog (peer->log, LOG_ERR, + zlog (peer->log, LOG_ERR, "IPv4 unicast NLRI is multicast address %s", - inet_ntoa (p.u.prefix4)); + safe_inet_ntoa (p.u.prefix4)); return -1; } @@ -3029,7 +3793,7 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) { char buf[BUFSIZ]; - zlog (peer->log, LOG_WARNING, + zlog (peer->log, LOG_WARNING, "IPv6 link-local NLRI received %s ignore this NLRI", inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); @@ -3040,10 +3804,10 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) /* Normal process. */ if (attr) - ret = bgp_update (peer, &p, attr, packet->afi, packet->safi, + ret = bgp_update (peer, &p, attr, packet->afi, packet->safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0); else - ret = bgp_withdraw (peer, &p, attr, packet->afi, packet->safi, + ret = bgp_withdraw (peer, &p, attr, packet->afi, packet->safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL); /* Address family configuration mismatch or maximum-prefix count @@ -3077,16 +3841,16 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt, while (pnt < end) { prefixlen = *pnt++; - + /* Prefix length check. */ if ((afi == AFI_IP && prefixlen > 32) || (afi == AFI_IP6 && prefixlen > 128)) { - plog_err (peer->log, + plog_err (peer->log, "%s [Error] Update packet error (wrong prefix length %d)", peer->host, prefixlen); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_INVAL_NETWORK); + bgp_peer_down_error(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); return -1; } @@ -3095,12 +3859,12 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt, if (pnt + psize > end) { - plog_err (peer->log, + plog_err (peer->log, "%s [Error] Update packet error" " (prefix data overflow prefix size is %d)", peer->host, psize); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_INVAL_NETWORK); + bgp_peer_down_error(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); return -1; } @@ -3114,13 +3878,13 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt, "%s [Error] Update packet error" " (prefix length mismatch with total length)", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_INVAL_NETWORK); + bgp_peer_down_error(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); return -1; } return 0; } - + static struct bgp_static * bgp_static_new (void) { @@ -3145,7 +3909,7 @@ bgp_static_withdraw_rsclient (struct bgp *bgp, struct peer *rsclient, rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, NULL); /* Check selected route and self inserted route. */ - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_STATIC) @@ -3169,13 +3933,11 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, { struct bgp_node *rn; struct bgp_info *ri; - struct bgp_info *new; - struct bgp_info info; - struct attr *attr_new; - struct attr attr = {0 }; - struct attr new_attr = { .extra = 0 }; + struct attr static_attr_s ; + struct attr* static_attr ; + struct attr* client_attr ; + struct rs_route rt_s ; struct bgp *bgp; - int ret; char buf[SU_ADDRSTRLEN]; bgp = rsclient->bgp; @@ -3186,135 +3948,152 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, NULL); - bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); + /* Construct the static route attributes. + * + * Starts with an empty aspath, which is interned. No other elements are + * interned and the object itself is not interned. + */ + static_attr = &static_attr_s ; + bgp_attr_default_set (static_attr, BGP_ORIGIN_IGP); + + static_attr->nexthop = bgp_static->igpnexthop; + static_attr->med = bgp_static->igpmetric; + static_attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - attr.nexthop = bgp_static->igpnexthop; - attr.med = bgp_static->igpmetric; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - if (bgp_static->atomic) - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); - - /* Apply network route-map for export to this rsclient. */ + static_attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); + + /* Apply network route-map for export to this rsclient. + * + * Create interned attributes client_attr, either from route-map result, or + * from the static_attr. + */ if (bgp_static->rmap.name) { - struct attr attr_tmp = attr; - info.peer = rsclient; - info.attr = &attr_tmp; - + struct bgp_info info_s = { 0 } ; + struct attr rmap_attr_s ; + struct attr* rmap_attr ; + route_map_result_t ret; + + rmap_attr = &rmap_attr_s ; + bgp_attr_dup(rmap_attr, static_attr) ; + + info_s.peer = rsclient ; + info_s.attr = rmap_attr ; + SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_EXPORT); SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_NETWORK); - ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); + ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info_s); rsclient->rmap_type = 0; if (ret == RMAP_DENYMATCH) { - /* Free uninterned attribute. */ - bgp_attr_flush (&attr_tmp); + /* Free uninterned attribute. */ + bgp_attr_flush (rmap_attr) ; + bgp_attr_extra_free (rmap_attr); + + /* Unintern original. */ + aspath_unintern (&static_attr->aspath); + bgp_attr_extra_free (static_attr); - /* Unintern original. */ - aspath_unintern (&attr.aspath); bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi); - bgp_attr_extra_free (&attr); - + return; - } - attr_new = bgp_attr_intern (&attr_tmp); + } ; + + client_attr = bgp_attr_intern(rmap_attr) ; + bgp_attr_extra_free (rmap_attr) ; } else - attr_new = bgp_attr_intern (&attr); - - bgp_attr_dup(&new_attr, attr_new); - + client_attr = bgp_attr_intern (static_attr) ; + + /* Have now finished with the static_attr */ + aspath_unintern (&static_attr->aspath); + bgp_attr_extra_free (static_attr); + + /* run the import route-map for the rsclient. */ + bgp_rs_route_init(&rt_s, afi, safi, NULL, bgp->peer_self, p, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL) ; + SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - if (bgp_import_modifier (rsclient, bgp->peer_self, p, &new_attr, afi, safi) - == RMAP_DENY) + client_attr = bgp_import_modifier (rsclient, &rt_s, client_attr) ; + + bgp->peer_self->rmap_type = 0; + + if (client_attr == NULL) { /* This BGP update is filtered. Log the reason then update BGP entry. */ if (BGP_DEBUG (update, UPDATE_IN)) - zlog (rsclient->log, LOG_DEBUG, - "Static UPDATE about %s/%d -- DENIED for RS-client %s due to: import-policy", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, rsclient->host); + zlog (rsclient->log, LOG_DEBUG, + "Static UPDATE about %s/%d -- DENIED for RS-client %s due to: " + "import-policy", + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen, rsclient->host); bgp->peer_self->rmap_type = 0; - bgp_attr_unintern (&attr_new); - aspath_unintern (&attr.aspath); - bgp_attr_extra_free (&attr); - bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi); - + return; } - bgp->peer_self->rmap_type = 0; - - bgp_attr_unintern (&attr_new); - attr_new = bgp_attr_intern (&new_attr); - bgp_attr_extra_free (&new_attr); + /* Apply the client_attr */ - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_STATIC) break; if (ri) { - if (attrhash_cmp (ri->attr, attr_new) && - !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + if (attrhash_cmp (ri->attr, client_attr) && + !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { - bgp_unlock_node (rn); - bgp_attr_unintern (&attr_new); - aspath_unintern (&attr.aspath); - bgp_attr_extra_free (&attr); - return; - } + /* No point duplicating */ + bgp_attr_unintern (&client_attr); + } else { - /* The attribute is changed. */ + /* The attribute is changed. */ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - /* Rewrite BGP route information. */ + /* Rewrite BGP route information. */ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) bgp_info_restore(rn, ri); + bgp_attr_unintern (&ri->attr); - ri->attr = attr_new; + ri->attr = client_attr ; ri->uptime = bgp_clock (); - /* Process change. */ + /* Process change. */ bgp_process (bgp, rn, afi, safi); - bgp_unlock_node (rn); - aspath_unintern (&attr.aspath); - bgp_attr_extra_free (&attr); - return; } - } - - /* Make new BGP info. */ - new = bgp_info_new (); - new->type = ZEBRA_ROUTE_BGP; - new->sub_type = BGP_ROUTE_STATIC; - new->peer = bgp->peer_self; - SET_FLAG (new->flags, BGP_INFO_VALID); - new->attr = attr_new; - new->uptime = bgp_clock (); - /* Register new BGP information. */ - bgp_info_add (rn, new); - - /* route_node_get lock */ - bgp_unlock_node (rn); - - /* Process change. */ + bgp_unlock_node (rn); + return ; + } ; + + /* Make new BGP info. */ + ri = bgp_info_new (); + ri->type = rt_s.type ; + ri->sub_type = rt_s.sub_type ; + ri->peer = rt_s.peer ; + ri->attr = client_attr ; + ri->uptime = bgp_clock (); + + SET_FLAG (ri->flags, BGP_INFO_VALID); + + /* Register new BGP information. */ + bgp_info_add (rn, ri); + + /* Process change. */ bgp_process (bgp, rn, afi, safi); - /* Unintern original. */ - aspath_unintern (&attr.aspath); - bgp_attr_extra_free (&attr); + /* route_node_get lock */ + bgp_unlock_node (rn); } static void @@ -3324,10 +4103,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, struct bgp_node *rn; struct bgp_info *ri; struct bgp_info *new; - struct bgp_info info; struct attr attr = { 0 }; struct attr *attr_new; - int ret; assert (bgp_static); if (!bgp_static) @@ -3336,7 +4113,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL); bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); - + attr.nexthop = bgp_static->igpnexthop; attr.med = bgp_static->igpmetric; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); @@ -3348,17 +4125,20 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, if (bgp_static->rmap.name) { struct attr attr_tmp = attr; - info.peer = bgp->peer_self; - info.attr = &attr_tmp; + struct bgp_info info_s = { 0 } ; + route_map_result_t ret; + + info_s.peer = bgp->peer_self; + info_s.attr = &attr_tmp; SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); + ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info_s); bgp->peer_self->rmap_type = 0; if (ret == RMAP_DENYMATCH) - { + { /* Free uninterned attribute. */ bgp_attr_flush (&attr_tmp); @@ -3373,7 +4153,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, else attr_new = bgp_attr_intern (&attr); - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_STATIC) break; @@ -3424,13 +4204,13 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, /* Aggregate address increment. */ bgp_aggregate_increment (bgp, p, new, afi, safi); - + /* Register new BGP information. */ bgp_info_add (rn, new); - + /* route_node_get lock */ bgp_unlock_node (rn); - + /* Process change. */ bgp_process (bgp, rn, afi, safi); @@ -3461,7 +4241,7 @@ bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi, { struct bgp_node *rn; struct bgp_info *new; - + rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); /* Make new BGP info. */ @@ -3477,13 +4257,13 @@ bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi, /* Aggregate address increment. */ bgp_aggregate_increment (bgp, p, new, afi, safi); - + /* Register new BGP information. */ bgp_info_add (rn, new); /* route_node_get lock */ bgp_unlock_node (rn); - + /* Process change. */ bgp_process (bgp, rn, afi, safi); } @@ -3498,8 +4278,8 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL); /* Check selected route and self inserted route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self + for (ri = rn->info; ri; ri = ri->info_next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_STATIC) break; @@ -3546,8 +4326,8 @@ bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi, rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); /* Check selected route and self inserted route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self + for (ri = rn->info; ri; ri = ri->info_next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_STATIC) break; @@ -3567,7 +4347,7 @@ bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi, /* Configure static BGP network. When user don't run zebra, static route should be installed as valid. */ static int -bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str, +bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str, afi_t afi, safi_t safi, const char *rmap, int backdoor) { int ret; @@ -3603,11 +4383,11 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str, bgp_static = rn->info; /* Check previous routes are installed into BGP. */ - if (bgp_static->valid && bgp_static->backdoor != backdoor) + if (bgp_static->valid && (bgp_static->backdoor != backdoor)) need_update = 1; - + bgp_static->backdoor = backdoor; - + if (rmap) { if (bgp_static->rmap.name) @@ -3633,7 +4413,7 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str, bgp_static->valid = 0; bgp_static->igpmetric = 0; bgp_static->igpnexthop.s_addr = 0; - + if (rmap) { if (bgp_static->rmap.name) @@ -3696,7 +4476,7 @@ bgp_static_unset (struct vty *vty, struct bgp *bgp, const char *ip_str, } bgp_static = rn->info; - + /* Update BGP RIB. */ if (! bgp_static->backdoor) bgp_static_withdraw (bgp, &p, afi, safi); @@ -3726,7 +4506,7 @@ bgp_static_delete (struct bgp *bgp) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) if (rn->info != NULL) - { + { if (safi == SAFI_MPLS_VPN) { table = rn->info; @@ -3823,7 +4603,7 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str, /* Configure static BGP network. */ int -bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str, +bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str, const char *tag_str) { int ret; @@ -3886,7 +4666,7 @@ bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str, return CMD_SUCCESS; } - + DEFUN (bgp_network, bgp_network_cmd, "network A.B.C.D/M", @@ -3930,7 +4710,7 @@ DEFUN (bgp_network_mask, { int ret; char prefix_str[BUFSIZ]; - + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); if (! ret) { @@ -3954,7 +4734,7 @@ DEFUN (bgp_network_mask_route_map, { int ret; char prefix_str[BUFSIZ]; - + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); if (! ret) { @@ -3977,7 +4757,7 @@ DEFUN (bgp_network_mask_backdoor, { int ret; char prefix_str[BUFSIZ]; - + ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str); if (! ret) { @@ -4059,7 +4839,7 @@ DEFUN (no_bgp_network, "Specify a network to announce via BGP\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_static_unset (vty, vty->index, argv[0], AFI_IP, + return bgp_static_unset (vty, vty->index, argv[0], AFI_IP, bgp_node_safi (vty)); } @@ -4099,7 +4879,7 @@ DEFUN (no_bgp_network_mask, return CMD_WARNING; } - return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, + return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, bgp_node_safi (vty)); } @@ -4141,7 +4921,7 @@ DEFUN (no_bgp_network_mask_natural, return CMD_WARNING; } - return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, + return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, bgp_node_safi (vty)); } @@ -4230,6 +5010,7 @@ ALIAS_DEPRECATED (bgp_network, "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (bgp_network_backdoor, bgp_network_backdoor_ttl_cmd, "network A.B.C.D/M backdoor pathlimit <0-255>", @@ -4238,6 +5019,7 @@ ALIAS_DEPRECATED (bgp_network_backdoor, "Specify a BGP backdoor route\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (bgp_network_mask, bgp_network_mask_ttl_cmd, "network A.B.C.D mask A.B.C.D pathlimit <0-255>", @@ -4247,6 +5029,7 @@ ALIAS_DEPRECATED (bgp_network_mask, "Network mask\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (bgp_network_mask_backdoor, bgp_network_mask_backdoor_ttl_cmd, "network A.B.C.D mask A.B.C.D backdoor pathlimit <0-255>", @@ -4257,6 +5040,7 @@ ALIAS_DEPRECATED (bgp_network_mask_backdoor, "Specify a BGP backdoor route\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (bgp_network_mask_natural, bgp_network_mask_natural_ttl_cmd, "network A.B.C.D pathlimit <0-255>", @@ -4264,14 +5048,16 @@ ALIAS_DEPRECATED (bgp_network_mask_natural, "Network number\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (bgp_network_mask_natural_backdoor, bgp_network_mask_natural_backdoor_ttl_cmd, - "network A.B.C.D backdoor pathlimit (1-255>", + "network A.B.C.D backdoor pathlimit <1-255>", "Specify a network to announce via BGP\n" "Network number\n" "Specify a BGP backdoor route\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (no_bgp_network, no_bgp_network_ttl_cmd, "no network A.B.C.D/M pathlimit <0-255>", @@ -4280,6 +5066,7 @@ ALIAS_DEPRECATED (no_bgp_network, "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (no_bgp_network, no_bgp_network_backdoor_ttl_cmd, "no network A.B.C.D/M backdoor pathlimit <0-255>", @@ -4289,6 +5076,7 @@ ALIAS_DEPRECATED (no_bgp_network, "Specify a BGP backdoor route\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (no_bgp_network, no_bgp_network_mask_ttl_cmd, "no network A.B.C.D mask A.B.C.D pathlimit <0-255>", @@ -4299,6 +5087,7 @@ ALIAS_DEPRECATED (no_bgp_network, "Network mask\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (no_bgp_network_mask, no_bgp_network_mask_backdoor_ttl_cmd, "no network A.B.C.D mask A.B.C.D backdoor pathlimit <0-255>", @@ -4310,6 +5099,7 @@ ALIAS_DEPRECATED (no_bgp_network_mask, "Specify a BGP backdoor route\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (no_bgp_network_mask_natural, no_bgp_network_mask_natural_ttl_cmd, "no network A.B.C.D pathlimit <0-255>", @@ -4318,6 +5108,7 @@ ALIAS_DEPRECATED (no_bgp_network_mask_natural, "Network number\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (no_bgp_network_mask_natural, no_bgp_network_mask_natural_backdoor_ttl_cmd, "no network A.B.C.D backdoor pathlimit <0-255>", @@ -4327,6 +5118,7 @@ ALIAS_DEPRECATED (no_bgp_network_mask_natural, "Specify a BGP backdoor route\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + #ifdef HAVE_IPV6 ALIAS_DEPRECATED (ipv6_bgp_network, ipv6_bgp_network_ttl_cmd, @@ -4335,6 +5127,7 @@ ALIAS_DEPRECATED (ipv6_bgp_network, "IPv6 prefix <network>/<length>\n" "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") + ALIAS_DEPRECATED (no_ipv6_bgp_network, no_ipv6_bgp_network_ttl_cmd, "no network X:X::X:X/M pathlimit <0-255>", @@ -4344,8 +5137,8 @@ ALIAS_DEPRECATED (no_ipv6_bgp_network, "AS-Path hopcount limit attribute\n" "AS-Pathlimit TTL, in number of AS-Path hops\n") #endif /* HAVE_IPV6 */ - -/* Aggreagete address: + +/* Aggregate address: advertise-map Set condition to advertise attribute as-set Generate AS set path information @@ -4383,11 +5176,11 @@ static void bgp_aggregate_free (struct bgp_aggregate *aggregate) { XFREE (MTYPE_BGP_AGGREGATE, aggregate); -} +} static void bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, - afi_t afi, safi_t safi, struct bgp_info *del, + afi_t afi, safi_t safi, struct bgp_info *del, struct bgp_aggregate *aggregate) { struct bgp_table *table; @@ -4430,7 +5223,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, { match = 0; - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) { if (BGP_INFO_HOLDDOWN (ri)) continue; @@ -4507,7 +5300,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, if (rinew) { aggregate->count++; - + if (aggregate->summary_only) (bgp_info_extra_get (rinew))->suppress++; @@ -4598,7 +5391,7 @@ bgp_aggregate_increment (struct bgp *bgp, struct prefix *p, } void -bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p, +bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p, struct bgp_info *del, afi_t afi, safi_t safi) { struct bgp_node *child; @@ -4647,7 +5440,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, return; if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) return; - + /* If routes exists below this node, generate aggregate routes. */ top = bgp_node_get (table, p); for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) @@ -4655,7 +5448,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, { match = 0; - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) { if (BGP_INFO_HOLDDOWN (ri)) continue; @@ -4702,7 +5495,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, aggregate->count++; } } - + /* If this node is suppressed, process the change. */ if (match) bgp_process (bgp, rn, afi, safi); @@ -4724,14 +5517,14 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, bgp_info_add (rn, new); bgp_unlock_node (rn); - + /* Process change. */ bgp_process (bgp, rn, afi, safi); } } void -bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, +bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, struct bgp_aggregate *aggregate) { struct bgp_table *table; @@ -4754,7 +5547,7 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, { match = 0; - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) { if (BGP_INFO_HOLDDOWN (ri)) continue; @@ -4784,8 +5577,8 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, /* Delete aggregate route from BGP table. */ rn = bgp_node_get (table, p); - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self + for (ri = rn->info; ri; ri = ri->info_next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP && ri->sub_type == BGP_ROUTE_AGGREGATE) break; @@ -4886,7 +5679,7 @@ bgp_aggregate_set (struct vty *vty, const char *prefix_str, { vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE); bgp_unlock_node (rn); - return CMD_WARNING; + return CMD_WARNING; } } @@ -5180,7 +5973,7 @@ DEFUN (ipv6_aggregate_address_summary_only, "Aggregate prefix\n" "Filter more specific routes from updates\n") { - return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST, + return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST, AGGREGATE_SUMMARY_ONLY, 0); } @@ -5241,7 +6034,7 @@ ALIAS (no_ipv6_aggregate_address_summary_only, "Aggregate prefix\n" "Filter more specific routes from updates\n") #endif /* HAVE_IPV6 */ - + /* Redistribute route treatment. */ void bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, @@ -5251,13 +6044,11 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, struct listnode *node, *nnode; struct bgp_info *new; struct bgp_info *bi; - struct bgp_info info; struct bgp_node *bn; struct attr attr = { 0 }; struct attr attr_new = { 0 }; struct attr *new_attr; afi_t afi; - int ret; /* Make default attribute. */ bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); @@ -5282,13 +6073,16 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, /* Apply route-map. */ if (bgp->rmap[afi][type].map) { - info.peer = bgp->peer_self; - info.attr = &attr_new; + struct bgp_info info_s = { 0 } ; + route_map_result_t ret; + + info_s.peer = bgp->peer_self; + info_s.attr = &attr_new; SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE); ret = route_map_apply (bgp->rmap[afi][type].map, p, RMAP_BGP, - &info); + &info_s); bgp->peer_self->rmap_type = 0; @@ -5297,7 +6091,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, /* Free uninterned attribute. */ bgp_attr_flush (&attr_new); bgp_attr_extra_free (&attr_new); - + /* Unintern original. */ aspath_unintern (&attr.aspath); bgp_attr_extra_free (&attr); @@ -5306,17 +6100,17 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, } } - bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], + bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL); - + new_attr = bgp_attr_intern (&attr_new); bgp_attr_extra_free (&attr_new); - - for (bi = bn->info; bi; bi = bi->next) + + for (bi = bn->info; bi; bi = bi->info_next) if (bi->peer == bgp->peer_self && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) break; - + if (bi) { if (attrhash_cmp (bi->attr, new_attr) && @@ -5332,7 +6126,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, { /* The attribute is changed. */ bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED); - + /* Rewrite BGP route information. */ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) bgp_info_restore(bn, bi); @@ -5341,7 +6135,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, bgp_attr_unintern (&bi->attr); bi->attr = new_attr; bi->uptime = bgp_clock (); - + /* Process change. */ bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST); bgp_process (bgp, bn, afi, SAFI_UNICAST); @@ -5349,7 +6143,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, aspath_unintern (&attr.aspath); bgp_attr_extra_free (&attr); return; - } + } } new = bgp_info_new (); @@ -5389,7 +6183,7 @@ bgp_redistribute_delete (struct prefix *p, u_char type) { rn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL); - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == bgp->peer_self && ri->type == type) break; @@ -5417,7 +6211,7 @@ bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type) for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) { - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) if (ri->peer == bgp->peer_self && ri->type == type) break; @@ -5430,13 +6224,13 @@ bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type) } } } - + /* Static function to display route. */ static void route_vty_out_route (struct prefix *p, struct vty *vty) { int len; - u_int32_t destination; + u_int32_t destination; char buf[BUFSIZ]; if (p->family == AF_INET) @@ -5500,7 +6294,7 @@ route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo) if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as)) vty_out (vty, "i"); else - vty_out (vty, " "); + vty_out (vty, " "); } /* called from terminal list command */ @@ -5509,10 +6303,10 @@ route_vty_out (struct vty *vty, struct prefix *p, struct bgp_info *binfo, int display, safi_t safi) { struct attr *attr; - - /* short status lead text */ + + /* short status lead text */ route_vty_short_status_out (vty, binfo); - + /* print prefix and mask */ if (! display) route_vty_out_route (p, vty); @@ -5521,23 +6315,23 @@ route_vty_out (struct vty *vty, struct prefix *p, /* Print attribute */ attr = binfo->attr; - if (attr) + if (attr) { if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) vty_out (vty, "%-16s", - inet_ntoa (attr->extra->mp_nexthop_global_in)); + safe_inet_ntoa (attr->extra->mp_nexthop_global_in)); else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + vty_out (vty, "%-16s", safe_inet_ntoa (attr->nexthop)); } -#ifdef HAVE_IPV6 +#ifdef HAVE_IPV6 else if (p->family == AF_INET6) { int len; char buf[BUFSIZ]; - len = vty_out (vty, "%s", + len = vty_out (vty, "%s", inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, buf, BUFSIZ)); len = 16 - len; @@ -5559,7 +6353,7 @@ route_vty_out (struct vty *vty, struct prefix *p, vty_out (vty, " "); vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0)); - + /* Print aspath */ if (attr->aspath) aspath_print_vty (vty, "%s", attr->aspath, " "); @@ -5568,7 +6362,7 @@ route_vty_out (struct vty *vty, struct prefix *p, vty_out (vty, "%s", bgp_origin_str[attr->origin]); } vty_out (vty, "%s", VTY_NEWLINE); -} +} /* called from terminal list command */ void @@ -5584,22 +6378,22 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, route_vty_out_route (p, vty); /* Print attribute */ - if (attr) + if (attr) { if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) vty_out (vty, "%-16s", - inet_ntoa (attr->extra->mp_nexthop_global_in)); + safe_inet_ntoa (attr->extra->mp_nexthop_global_in)); else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + vty_out (vty, "%-16s", safe_inet_ntoa (attr->nexthop)); } #ifdef HAVE_IPV6 else if (p->family == AF_INET6) { int len; char buf[BUFSIZ]; - + assert (attr->extra); len = vty_out (vty, "%s", @@ -5622,9 +6416,9 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, vty_out (vty, "%7u", attr->local_pref); else vty_out (vty, " "); - + vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0)); - + /* Print aspath */ if (attr->aspath) aspath_print_vty (vty, "%s", attr->aspath, " "); @@ -5634,7 +6428,7 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, } vty_out (vty, "%s", VTY_NEWLINE); -} +} void route_vty_out_tag (struct vty *vty, struct prefix *p, @@ -5642,13 +6436,13 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, { struct attr *attr; u_int32_t label = 0; - + if (!binfo->extra) return; - - /* short status lead text */ + + /* short status lead text */ route_vty_short_status_out (vty, binfo); - + /* print prefix and mask */ if (! display) route_vty_out_route (p, vty); @@ -5657,24 +6451,24 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, /* Print attribute */ attr = binfo->attr; - if (attr) + if (attr) { if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) vty_out (vty, "%-16s", - inet_ntoa (attr->extra->mp_nexthop_global_in)); + safe_inet_ntoa (attr->extra->mp_nexthop_global_in)); else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + vty_out (vty, "%-16s", safe_inet_ntoa (attr->nexthop)); } -#ifdef HAVE_IPV6 +#ifdef HAVE_IPV6 else if (p->family == AF_INET6) { assert (attr->extra); char buf[BUFSIZ]; char buf1[BUFSIZ]; if (attr->extra->mp_nexthop_len == 16) - vty_out (vty, "%s", + vty_out (vty, "%s", inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, buf, BUFSIZ)); else if (attr->extra->mp_nexthop_len == 32) @@ -5683,7 +6477,7 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, buf, BUFSIZ), inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, buf1, BUFSIZ)); - + } #endif /* HAVE_IPV6 */ } @@ -5693,7 +6487,7 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, vty_out (vty, "notag/%d", label); vty_out (vty, "%s", VTY_NEWLINE); -} +} /* dampening route */ static void @@ -5704,9 +6498,9 @@ damp_route_vty_out (struct vty *vty, struct prefix *p, int len; char timebuf[BGP_UPTIME_LEN]; - /* short status lead text */ + /* short status lead text */ route_vty_short_status_out (vty, binfo); - + /* print prefix and mask */ if (! display) route_vty_out_route (p, vty); @@ -5745,15 +6539,15 @@ flap_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_damp_info *bdi; char timebuf[BGP_UPTIME_LEN]; int len; - + if (!binfo->extra) return; - + bdi = binfo->extra->damp_info; /* short status lead text */ route_vty_short_status_out (vty, binfo); - + /* print prefix and mask */ if (! display) route_vty_out_route (p, vty); @@ -5773,7 +6567,7 @@ flap_route_vty_out (struct vty *vty, struct prefix *p, vty_out (vty, " "); else vty_out (vty, "%*s ", len, " "); - + vty_out (vty, "%s ", peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN)); @@ -5798,17 +6592,14 @@ flap_route_vty_out (struct vty *vty, struct prefix *p, } static void -route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, +route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, struct bgp_info *binfo, afi_t afi, safi_t safi) { - char buf[INET6_ADDRSTRLEN]; - char buf1[BUFSIZ]; + char buf[SU_ADDRSTRLEN]; struct attr *attr; int sockunion_vty_out (struct vty *, union sockunion *); -#ifdef HAVE_CLOCK_MONOTONIC - time_t tbuf; -#endif - + time_t tbuf ; + attr = binfo->attr; if (attr) @@ -5828,25 +6619,27 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) vty_out (vty, ", (stale)"); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))) - vty_out (vty, ", (aggregated by %u %s)", + vty_out (vty, ", (aggregated by %u %s)", attr->extra->aggregator_as, - inet_ntoa (attr->extra->aggregator_addr)); - if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) + safe_inet_ntoa (attr->extra->aggregator_addr)); + if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT)) vty_out (vty, ", (Received from a RR-client)"); - if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) + if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], + PEER_FLAG_RSERVER_CLIENT)) vty_out (vty, ", (Received from a RS-client)"); if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) vty_out (vty, ", (history entry)"); else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) vty_out (vty, ", (suppressed due to dampening)"); vty_out (vty, "%s", VTY_NEWLINE); - + /* Line2 display Next-hop, Neighbor, Router-id */ if (p->family == AF_INET) { vty_out (vty, " %s", safi == SAFI_MPLS_VPN ? - inet_ntoa (attr->extra->mp_nexthop_global_in) : - inet_ntoa (attr->nexthop)); + safe_inet_ntoa (attr->extra->mp_nexthop_global_in) : + safe_inet_ntoa (attr->nexthop)); } #ifdef HAVE_IPV6 else @@ -5860,21 +6653,23 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (binfo->peer == bgp->peer_self) { - vty_out (vty, " from %s ", + vty_out (vty, " from %s ", p->family == AF_INET ? "0.0.0.0" : "::"); - vty_out (vty, "(%s)", inet_ntoa(bgp->router_id)); + vty_out (vty, "(%s)", safe_inet_ntoa(bgp->router_id)); } else { if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) - vty_out (vty, " (inaccessible)"); + vty_out (vty, " (inaccessible)"); else if (binfo->extra && binfo->extra->igpmetric) vty_out (vty, " (metric %d)", binfo->extra->igpmetric); - vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); + vty_out (vty, " from %s", + sockunion2str (&binfo->peer->su, buf, sizeof(buf))); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id)); + vty_out (vty, " (%s)", safe_inet_ntoa (attr->extra->originator_id)); else - vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ)); + vty_out (vty, " (%s)", + inet_ntop (AF_INET, &binfo->peer->remote_id, buf, sizeof(buf))); } vty_out (vty, "%s", VTY_NEWLINE); @@ -5884,17 +6679,18 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, { vty_out (vty, " (%s)%s", inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, - buf, INET6_ADDRSTRLEN), + buf, sizeof(buf)), VTY_NEWLINE); } #endif /* HAVE_IPV6 */ - /* Line 3 display Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */ + /* Line 3 display: + * Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */ vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]); - + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) vty_out (vty, ", metric %u", attr->med); - + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) vty_out (vty, ", localpref %u", attr->local_pref); else @@ -5902,7 +6698,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (attr->extra && attr->extra->weight != 0) vty_out (vty, ", weight %u", attr->extra->weight); - + if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) vty_out (vty, ", valid"); @@ -5910,9 +6706,10 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, { if (binfo->peer->as == binfo->peer->local_as) vty_out (vty, ", internal"); - else - vty_out (vty, ", %s", - (bgp_confederation_peers_check(bgp, binfo->peer->as) ? "confed-external" : "external")); + else + vty_out (vty, ", %s", + (bgp_confederation_peers_check(bgp, binfo->peer->as) + ? "confed-external" : "external")); } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) vty_out (vty, ", aggregated, local"); @@ -5923,56 +6720,52 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) vty_out (vty, ", atomic-aggregate"); - + if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) vty_out (vty, ", best"); vty_out (vty, "%s", VTY_NEWLINE); - + /* Line 4 display Community */ if (attr->community) vty_out (vty, " Community: %s%s", attr->community->str, VTY_NEWLINE); - + /* Line 5 display Extended-community */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) - vty_out (vty, " Extended Community: %s%s", + vty_out (vty, " Extended Community: %s%s", attr->extra->ecommunity->str, VTY_NEWLINE); - + /* Line 6 display Originator, Cluster-id */ if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) { assert (attr->extra); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - vty_out (vty, " Originator: %s", - inet_ntoa (attr->extra->originator_id)); + vty_out (vty, " Originator: %s", + safe_inet_ntoa (attr->extra->originator_id)); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) { int i; vty_out (vty, ", Cluster list: "); for (i = 0; i < attr->extra->cluster->length / 4; i++) - vty_out (vty, "%s ", - inet_ntoa (attr->extra->cluster->list[i])); + vty_out (vty, "%s ", + safe_inet_ntoa (attr->extra->cluster->list[i])); } vty_out (vty, "%s", VTY_NEWLINE); } - + if (binfo->extra && binfo->extra->damp_info) bgp_damp_info_vty (vty, binfo); /* Line 7 display Uptime */ -#ifdef HAVE_CLOCK_MONOTONIC - tbuf = time(NULL) - (bgp_clock() - binfo->uptime); + tbuf = bgp_wall_clock(binfo->uptime); vty_out (vty, " Last update: %s", ctime(&tbuf)); -#else - vty_out (vty, " Last update: %s", ctime(&binfo->uptime)); -#endif /* HAVE_CLOCK_MONOTONIC */ } vty_out (vty, "%s", VTY_NEWLINE); -} - +} + #define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,%s r RIB-failure, S Stale, R Removed%s" #define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s" #define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path%s" @@ -6022,12 +6815,12 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router output_count = 0; /* Start processing of routes. */ - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) if (rn->info != NULL) { display = 0; - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) { if (type == bgp_show_type_flap_statistics || type == bgp_show_type_flap_address @@ -6049,7 +6842,7 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router || type == bgp_show_type_flap_regexp) { regex_t *regex = output_arg; - + if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH) continue; } @@ -6057,7 +6850,7 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router || type == bgp_show_type_flap_prefix_list) { struct prefix_list *plist = output_arg; - + if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT) continue; } @@ -6073,18 +6866,19 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router || type == bgp_show_type_flap_route_map) { struct route_map *rmap = output_arg; - struct bgp_info binfo; - struct attr dummy_attr = { 0 }; - int ret; + struct attr dummy_attr = { 0 }; + struct bgp_info info_s = { 0 } ; + route_map_result_t ret; bgp_attr_dup (&dummy_attr, ri->attr); - binfo.peer = ri->peer; - binfo.attr = &dummy_attr; + info_s.peer = ri->peer; + info_s.attr = &dummy_attr; + + /* TODO: check if routemap may be setting stuff */ + ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &info_s); - ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo); - bgp_attr_extra_free (&dummy_attr); - + if (ret == RMAP_DENYMATCH) continue; } @@ -6175,7 +6969,7 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router if (header) { - vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (*router_id), VTY_NEWLINE); + vty_out (vty, "BGP table version is 0, local router ID is %s%s", safe_inet_ntoa (*router_id), VTY_NEWLINE); vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); if (type == bgp_show_type_dampend_paths @@ -6264,8 +7058,8 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, struct prefix *p; struct peer *peer; struct listnode *node, *nnode; - char buf1[INET6_ADDRSTRLEN]; - char buf2[INET6_ADDRSTRLEN]; + char buf[SU_ADDRSTRLEN]; + char buf_rd[RD_ADDRSTRLEN]; int count = 0; int best = 0; int suppress = 0; @@ -6277,12 +7071,12 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, p = &rn->p; vty_out (vty, "BGP routing table entry for %s%s%s/%d%s", (safi == SAFI_MPLS_VPN ? - prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), + prefix_rd2str (prd, buf_rd, sizeof(buf_rd)) : ""), safi == SAFI_MPLS_VPN ? ":" : "", - inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN), + inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)), p->prefixlen, VTY_NEWLINE); - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) { count++; if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) @@ -6327,8 +7121,9 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, if (bgp_adj_out_lookup (peer, p, afi, safi, rn)) { if (! first) - vty_out (vty, " Advertised to non peer-group peers:%s ", VTY_NEWLINE); - vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN)); + vty_out (vty, " Advertised to non peer-group peers:%s ", + VTY_NEWLINE); + vty_out (vty, " %s", sutoa(&peer->su).str); first = 1; } } @@ -6339,7 +7134,7 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, /* Display specified route of BGP table. */ static int -bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, +bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, struct bgp_table *rib, const char *ip_str, afi_t afi, safi_t safi, struct prefix_rd *prd, int prefix_check) @@ -6357,7 +7152,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, ret = str2prefix (ip_str, &match); if (! ret) { - vty_out (vty, "address is malformed%s", VTY_NEWLINE); + vty_out (vty, "%% address is malformed%s", VTY_NEWLINE); return CMD_WARNING; } @@ -6376,23 +7171,22 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, if ((rm = bgp_node_match (table, &match)) != NULL) { - if (prefix_check && rm->p.prefixlen != match.prefixlen) - { - bgp_unlock_node (rm); - continue; - } - - for (ri = rm->info; ri; ri = ri->next) + if (prefix_check && rm->p.prefixlen == match.prefixlen) { - if (header) + for (ri = rm->info; ri; ri = ri->info_next) { - route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p, - AFI_IP, SAFI_MPLS_VPN); - - header = 0; + if (header) + { + route_vty_out_detail_header (vty, bgp, rm, + (struct prefix_rd *)&rn->p, + AFI_IP, SAFI_MPLS_VPN); + + header = 0; + } + display++; + route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, + SAFI_MPLS_VPN); } - display++; - route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN); } bgp_unlock_node (rm); @@ -6408,7 +7202,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, { if (! prefix_check || rn->p.prefixlen == match.prefixlen) { - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) { if (header) { @@ -6460,8 +7254,8 @@ bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str, return CMD_WARNING; } } - - return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str, + + return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str, afi, safi, prd, prefix_check); } @@ -6489,7 +7283,7 @@ DEFUN (show_ip_bgp_ipv4, if (strncmp (argv[0], "m", 1) == 0) return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, bgp_show_type_normal, NULL); - + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL); } @@ -6853,7 +7647,7 @@ DEFUN (show_bgp_view, vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } - + return bgp_show (vty, bgp, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL); } @@ -6861,11 +7655,11 @@ ALIAS (show_bgp_view, show_bgp_view_ipv6_cmd, "show bgp view WORD ipv6", SHOW_STR - BGP_STR + BGP_STR "BGP view\n" "View name\n" "Address family\n") - + DEFUN (show_bgp_view_route, show_bgp_view_route_cmd, "show bgp view WORD X:X::X:X", @@ -6894,10 +7688,10 @@ DEFUN (show_bgp_view_prefix, SHOW_STR BGP_STR "BGP view\n" - "View name\n" + "View name\n" "IPv6 prefix <network>/<length>\n") { - return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1); } ALIAS (show_bgp_view_prefix, @@ -6908,7 +7702,7 @@ ALIAS (show_bgp_view_prefix, "BGP view\n" "View name\n" "Address family\n" - "IPv6 prefix <network>/<length>\n") + "IPv6 prefix <network>/<length>\n") /* old command */ DEFUN (show_ipv6_mbgp, @@ -6946,10 +7740,10 @@ DEFUN (show_ipv6_mbgp_prefix, return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1); } #endif - + static int -bgp_show_regexp (struct vty *vty, int argc, const char **argv, afi_t afi, +bgp_show_regexp (struct vty *vty, int argc, argv_t argv, afi_t afi, safi_t safi, enum bgp_show_type type) { int i; @@ -6958,7 +7752,7 @@ bgp_show_regexp (struct vty *vty, int argc, const char **argv, afi_t afi, int first; regex_t *regex; int rc; - + first = 0; b = buffer_new (1024); for (i = 0; i < argc; i++) @@ -6993,7 +7787,7 @@ bgp_show_regexp (struct vty *vty, int argc, const char **argv, afi_t afi, return rc; } -DEFUN (show_ip_bgp_regexp, +DEFUN (show_ip_bgp_regexp, show_ip_bgp_regexp_cmd, "show ip bgp regexp .LINE", SHOW_STR @@ -7006,7 +7800,7 @@ DEFUN (show_ip_bgp_regexp, bgp_show_type_regexp); } -DEFUN (show_ip_bgp_flap_regexp, +DEFUN (show_ip_bgp_flap_regexp, show_ip_bgp_flap_regexp_cmd, "show ip bgp flap-statistics regexp .LINE", SHOW_STR @@ -7020,7 +7814,7 @@ DEFUN (show_ip_bgp_flap_regexp, bgp_show_type_flap_regexp); } -DEFUN (show_ip_bgp_ipv4_regexp, +DEFUN (show_ip_bgp_ipv4_regexp, show_ip_bgp_ipv4_regexp_cmd, "show ip bgp ipv4 (unicast|multicast) regexp .LINE", SHOW_STR @@ -7041,7 +7835,7 @@ DEFUN (show_ip_bgp_ipv4_regexp, } #ifdef HAVE_IPV6 -DEFUN (show_bgp_regexp, +DEFUN (show_bgp_regexp, show_bgp_regexp_cmd, "show bgp regexp .LINE", SHOW_STR @@ -7053,7 +7847,7 @@ DEFUN (show_bgp_regexp, bgp_show_type_regexp); } -ALIAS (show_bgp_regexp, +ALIAS (show_bgp_regexp, show_bgp_ipv6_regexp_cmd, "show bgp ipv6 regexp .LINE", SHOW_STR @@ -7063,7 +7857,7 @@ ALIAS (show_bgp_regexp, "A regular-expression to match the BGP AS paths\n") /* old command */ -DEFUN (show_ipv6_bgp_regexp, +DEFUN (show_ipv6_bgp_regexp, show_ipv6_bgp_regexp_cmd, "show ipv6 bgp regexp .LINE", SHOW_STR @@ -7077,7 +7871,7 @@ DEFUN (show_ipv6_bgp_regexp, } /* old command */ -DEFUN (show_ipv6_mbgp_regexp, +DEFUN (show_ipv6_mbgp_regexp, show_ipv6_mbgp_regexp_cmd, "show ipv6 mbgp regexp .LINE", SHOW_STR @@ -7090,7 +7884,7 @@ DEFUN (show_ipv6_mbgp_regexp, bgp_show_type_regexp); } #endif /* HAVE_IPV6 */ - + static int bgp_show_prefix_list (struct vty *vty, const char *prefix_list_str, afi_t afi, safi_t safi, enum bgp_show_type type) @@ -7101,14 +7895,14 @@ bgp_show_prefix_list (struct vty *vty, const char *prefix_list_str, afi_t afi, if (plist == NULL) { vty_out (vty, "%% %s is not a valid prefix-list name%s", - prefix_list_str, VTY_NEWLINE); + prefix_list_str, VTY_NEWLINE); return CMD_WARNING; } return bgp_show (vty, NULL, afi, safi, type, plist); } -DEFUN (show_ip_bgp_prefix_list, +DEFUN (show_ip_bgp_prefix_list, show_ip_bgp_prefix_list_cmd, "show ip bgp prefix-list WORD", SHOW_STR @@ -7121,7 +7915,7 @@ DEFUN (show_ip_bgp_prefix_list, bgp_show_type_prefix_list); } -DEFUN (show_ip_bgp_flap_prefix_list, +DEFUN (show_ip_bgp_flap_prefix_list, show_ip_bgp_flap_prefix_list_cmd, "show ip bgp flap-statistics prefix-list WORD", SHOW_STR @@ -7135,7 +7929,7 @@ DEFUN (show_ip_bgp_flap_prefix_list, bgp_show_type_flap_prefix_list); } -DEFUN (show_ip_bgp_ipv4_prefix_list, +DEFUN (show_ip_bgp_ipv4_prefix_list, show_ip_bgp_ipv4_prefix_list_cmd, "show ip bgp ipv4 (unicast|multicast) prefix-list WORD", SHOW_STR @@ -7156,7 +7950,7 @@ DEFUN (show_ip_bgp_ipv4_prefix_list, } #ifdef HAVE_IPV6 -DEFUN (show_bgp_prefix_list, +DEFUN (show_bgp_prefix_list, show_bgp_prefix_list_cmd, "show bgp prefix-list WORD", SHOW_STR @@ -7168,7 +7962,7 @@ DEFUN (show_bgp_prefix_list, bgp_show_type_prefix_list); } -ALIAS (show_bgp_prefix_list, +ALIAS (show_bgp_prefix_list, show_bgp_ipv6_prefix_list_cmd, "show bgp ipv6 prefix-list WORD", SHOW_STR @@ -7178,7 +7972,7 @@ ALIAS (show_bgp_prefix_list, "IPv6 prefix-list name\n") /* old command */ -DEFUN (show_ipv6_bgp_prefix_list, +DEFUN (show_ipv6_bgp_prefix_list, show_ipv6_bgp_prefix_list_cmd, "show ipv6 bgp prefix-list WORD", SHOW_STR @@ -7192,7 +7986,7 @@ DEFUN (show_ipv6_bgp_prefix_list, } /* old command */ -DEFUN (show_ipv6_mbgp_prefix_list, +DEFUN (show_ipv6_mbgp_prefix_list, show_ipv6_mbgp_prefix_list_cmd, "show ipv6 mbgp prefix-list WORD", SHOW_STR @@ -7205,7 +7999,7 @@ DEFUN (show_ipv6_mbgp_prefix_list, bgp_show_type_prefix_list); } #endif /* HAVE_IPV6 */ - + static int bgp_show_filter_list (struct vty *vty, const char *filter, afi_t afi, safi_t safi, enum bgp_show_type type) @@ -7215,14 +8009,14 @@ bgp_show_filter_list (struct vty *vty, const char *filter, afi_t afi, as_list = as_list_lookup (filter); if (as_list == NULL) { - vty_out (vty, "%% %s is not a valid AS-path access-list name%s", filter, VTY_NEWLINE); + vty_out (vty, "%% %s is not a valid AS-path access-list name%s", filter, VTY_NEWLINE); return CMD_WARNING; } return bgp_show (vty, NULL, afi, safi, type, as_list); } -DEFUN (show_ip_bgp_filter_list, +DEFUN (show_ip_bgp_filter_list, show_ip_bgp_filter_list_cmd, "show ip bgp filter-list WORD", SHOW_STR @@ -7235,7 +8029,7 @@ DEFUN (show_ip_bgp_filter_list, bgp_show_type_filter_list); } -DEFUN (show_ip_bgp_flap_filter_list, +DEFUN (show_ip_bgp_flap_filter_list, show_ip_bgp_flap_filter_list_cmd, "show ip bgp flap-statistics filter-list WORD", SHOW_STR @@ -7249,7 +8043,7 @@ DEFUN (show_ip_bgp_flap_filter_list, bgp_show_type_flap_filter_list); } -DEFUN (show_ip_bgp_ipv4_filter_list, +DEFUN (show_ip_bgp_ipv4_filter_list, show_ip_bgp_ipv4_filter_list_cmd, "show ip bgp ipv4 (unicast|multicast) filter-list WORD", SHOW_STR @@ -7264,13 +8058,13 @@ DEFUN (show_ip_bgp_ipv4_filter_list, if (strncmp (argv[0], "m", 1) == 0) return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_MULTICAST, bgp_show_type_filter_list); - + return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_UNICAST, bgp_show_type_filter_list); } #ifdef HAVE_IPV6 -DEFUN (show_bgp_filter_list, +DEFUN (show_bgp_filter_list, show_bgp_filter_list_cmd, "show bgp filter-list WORD", SHOW_STR @@ -7282,7 +8076,7 @@ DEFUN (show_bgp_filter_list, bgp_show_type_filter_list); } -ALIAS (show_bgp_filter_list, +ALIAS (show_bgp_filter_list, show_bgp_ipv6_filter_list_cmd, "show bgp ipv6 filter-list WORD", SHOW_STR @@ -7292,7 +8086,7 @@ ALIAS (show_bgp_filter_list, "Regular expression access list name\n") /* old command */ -DEFUN (show_ipv6_bgp_filter_list, +DEFUN (show_ipv6_bgp_filter_list, show_ipv6_bgp_filter_list_cmd, "show ipv6 bgp filter-list WORD", SHOW_STR @@ -7306,7 +8100,7 @@ DEFUN (show_ipv6_bgp_filter_list, } /* old command */ -DEFUN (show_ipv6_mbgp_filter_list, +DEFUN (show_ipv6_mbgp_filter_list, show_ipv6_mbgp_filter_list_cmd, "show ipv6 mbgp filter-list WORD", SHOW_STR @@ -7319,7 +8113,7 @@ DEFUN (show_ipv6_mbgp_filter_list, bgp_show_type_filter_list); } #endif /* HAVE_IPV6 */ - + static int bgp_show_route_map (struct vty *vty, const char *rmap_str, afi_t afi, safi_t safi, enum bgp_show_type type) @@ -7330,14 +8124,14 @@ bgp_show_route_map (struct vty *vty, const char *rmap_str, afi_t afi, if (! rmap) { vty_out (vty, "%% %s is not a valid route-map name%s", - rmap_str, VTY_NEWLINE); + rmap_str, VTY_NEWLINE); return CMD_WARNING; } return bgp_show (vty, NULL, afi, safi, type, rmap); } -DEFUN (show_ip_bgp_route_map, +DEFUN (show_ip_bgp_route_map, show_ip_bgp_route_map_cmd, "show ip bgp route-map WORD", SHOW_STR @@ -7350,7 +8144,7 @@ DEFUN (show_ip_bgp_route_map, bgp_show_type_route_map); } -DEFUN (show_ip_bgp_flap_route_map, +DEFUN (show_ip_bgp_flap_route_map, show_ip_bgp_flap_route_map_cmd, "show ip bgp flap-statistics route-map WORD", SHOW_STR @@ -7364,7 +8158,7 @@ DEFUN (show_ip_bgp_flap_route_map, bgp_show_type_flap_route_map); } -DEFUN (show_ip_bgp_ipv4_route_map, +DEFUN (show_ip_bgp_ipv4_route_map, show_ip_bgp_ipv4_route_map_cmd, "show ip bgp ipv4 (unicast|multicast) route-map WORD", SHOW_STR @@ -7384,7 +8178,7 @@ DEFUN (show_ip_bgp_ipv4_route_map, bgp_show_type_route_map); } -DEFUN (show_bgp_route_map, +DEFUN (show_bgp_route_map, show_bgp_route_map_cmd, "show bgp route-map WORD", SHOW_STR @@ -7396,7 +8190,7 @@ DEFUN (show_bgp_route_map, bgp_show_type_route_map); } -ALIAS (show_bgp_route_map, +ALIAS (show_bgp_route_map, show_bgp_ipv6_route_map_cmd, "show bgp ipv6 route-map WORD", SHOW_STR @@ -7404,7 +8198,7 @@ ALIAS (show_bgp_route_map, "Address family\n" "Display routes matching the route-map\n" "A route-map to match on\n") - + DEFUN (show_ip_bgp_cidr_only, show_ip_bgp_cidr_only_cmd, "show ip bgp cidr-only", @@ -7448,7 +8242,7 @@ DEFUN (show_ip_bgp_ipv4_cidr_only, return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_cidr_only, NULL); } - + DEFUN (show_ip_bgp_community_all, show_ip_bgp_community_all_cmd, "show ip bgp community", @@ -7475,7 +8269,7 @@ DEFUN (show_ip_bgp_ipv4_community_all, if (strncmp (argv[0], "m", 1) == 0) return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, bgp_show_type_community_all, NULL); - + return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_community_all, NULL); } @@ -7526,10 +8320,11 @@ DEFUN (show_ipv6_mbgp_community_all, bgp_show_type_community_all, NULL); } #endif /* HAVE_IPV6 */ - + static int -bgp_show_community (struct vty *vty, const char *view_name, int argc, - const char **argv, int exact, afi_t afi, safi_t safi) +bgp_show_community (struct vty *vty, const char *view_name, + int argc, argv_t argv, + int exact, afi_t afi, safi_t safi) { struct community *com; struct buffer *b; @@ -7543,19 +8338,19 @@ bgp_show_community (struct vty *vty, const char *view_name, int argc, { bgp = bgp_lookup_by_name (view_name); if (bgp == NULL) - { - vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE); - return CMD_WARNING; - } + { + vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE); + return CMD_WARNING; + } } else { bgp = bgp_get_default (); if (bgp == NULL) - { - vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); - return CMD_WARNING; - } + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } } b = buffer_new (1024); @@ -7565,11 +8360,12 @@ bgp_show_community (struct vty *vty, const char *view_name, int argc, buffer_putc (b, ' '); else { - if ((strcmp (argv[i], "unicast") == 0) || (strcmp (argv[i], "multicast") == 0)) + if ( (strcmp (argv[i], "unicast") == 0) + || (strcmp (argv[i], "multicast") == 0) ) continue; first = 1; } - + buffer_putstr (b, argv[i]); } buffer_putc (b, '\0'); @@ -7620,7 +8416,7 @@ ALIAS (show_ip_bgp_community, "Do not send outside local AS (well-known community)\n" "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") - + ALIAS (show_ip_bgp_community, show_ip_bgp_community3_cmd, "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", @@ -7640,7 +8436,7 @@ ALIAS (show_ip_bgp_community, "Do not send outside local AS (well-known community)\n" "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") - + ALIAS (show_ip_bgp_community, show_ip_bgp_community4_cmd, "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", @@ -7680,10 +8476,11 @@ DEFUN (show_ip_bgp_ipv4_community, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") { - if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_MULTICAST); - - return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST); + safi_t safi ; + + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST ; + + return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, safi); } ALIAS (show_ip_bgp_ipv4_community, @@ -7704,7 +8501,7 @@ ALIAS (show_ip_bgp_ipv4_community, "Do not send outside local AS (well-known community)\n" "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") - + ALIAS (show_ip_bgp_ipv4_community, show_ip_bgp_ipv4_community3_cmd, "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", @@ -7727,7 +8524,7 @@ ALIAS (show_ip_bgp_ipv4_community, "Do not send outside local AS (well-known community)\n" "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") - + ALIAS (show_ip_bgp_ipv4_community, show_ip_bgp_ipv4_community4_cmd, "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", @@ -8021,10 +8818,11 @@ DEFUN (show_ip_bgp_ipv4_community_exact, "Do not export to next AS (well-known community)\n" "Exact match of the communities") { - if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_MULTICAST); - - return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST); + safi_t safi ; + + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST ; + + return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, safi); } ALIAS (show_ip_bgp_ipv4_community_exact, @@ -8070,7 +8868,7 @@ ALIAS (show_ip_bgp_ipv4_community_exact, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n" "Exact match of the communities") - + ALIAS (show_ip_bgp_ipv4_community_exact, show_ip_bgp_ipv4_community4_exact_cmd, "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", @@ -8156,7 +8954,7 @@ ALIAS (show_bgp_community, "Do not send outside local AS (well-known community)\n" "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") - + ALIAS (show_bgp_community, show_bgp_community3_cmd, "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", @@ -8447,7 +9245,7 @@ ALIAS (show_bgp_community_exact, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n" "Exact match of the communities") - + ALIAS (show_bgp_community_exact, show_bgp_ipv6_community4_exact_cmd, "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match", @@ -8555,7 +9353,7 @@ ALIAS (show_ipv6_bgp_community_exact, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n" "Exact match of the communities") - + /* old command */ DEFUN (show_ipv6_mbgp_community, show_ipv6_mbgp_community_cmd, @@ -8718,7 +9516,7 @@ ALIAS (show_ipv6_mbgp_community_exact, "Do not export to next AS (well-known community)\n" "Exact match of the communities") #endif /* HAVE_IPV6 */ - + static int bgp_show_community_list (struct vty *vty, const char *com, int exact, afi_t afi, safi_t safi) @@ -8766,7 +9564,7 @@ DEFUN (show_ip_bgp_ipv4_community_list, { if (strncmp (argv[0], "m", 1) == 0) return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_MULTICAST); - + return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_UNICAST); } @@ -8800,7 +9598,7 @@ DEFUN (show_ip_bgp_ipv4_community_list_exact, { if (strncmp (argv[0], "m", 1) == 0) return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_MULTICAST); - + return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_UNICAST); } @@ -8905,7 +9703,7 @@ DEFUN (show_ipv6_mbgp_community_list_exact, return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_MULTICAST); } #endif /* HAVE_IPV6 */ - + static int bgp_show_prefix_longer (struct vty *vty, const char *prefix, afi_t afi, safi_t safi, enum bgp_show_type type) @@ -9051,7 +9849,7 @@ DEFUN (show_ipv6_mbgp_prefix_longer, #endif /* HAVE_IPV6 */ static struct peer * -peer_lookup_in_view (struct vty *vty, const char *view_name, +peer_lookup_in_view (struct vty *vty, const char *view_name, const char *ip_str) { int ret; @@ -9067,7 +9865,7 @@ peer_lookup_in_view (struct vty *vty, const char *view_name, { vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE); return NULL; - } + } } else { @@ -9079,7 +9877,7 @@ peer_lookup_in_view (struct vty *vty, const char *view_name, } } - /* Get peer sockunion. */ + /* Get peer sockunion. */ ret = str2sockunion (ip_str, &su); if (ret < 0) { @@ -9094,10 +9892,10 @@ peer_lookup_in_view (struct vty *vty, const char *view_name, vty_out (vty, "No such neighbor%s", VTY_NEWLINE); return NULL; } - + return peer; } - + enum bgp_stats { BGP_STATS_MAXBITLEN = 0, @@ -9149,7 +9947,7 @@ ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval) unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG); unsigned long res = (newtot * TALLY_SIGFIG) / count; unsigned long ret = newtot / count; - + if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2)) return ret + 1; else @@ -9164,7 +9962,7 @@ bgp_table_stats_walker (struct thread *t) struct bgp_node *top; struct bgp_table_stats *ts = THREAD_ARG (t); unsigned int space = 0; - + if (!(top = bgp_table_top (ts->table))) return 0; @@ -9177,7 +9975,7 @@ bgp_table_stats_walker (struct thread *t) space = IPV6_MAX_BITLEN; break; } - + ts->counts[BGP_STATS_MAXBITLEN] = space; for (rn = top; rn; rn = bgp_route_next (rn)) @@ -9185,13 +9983,13 @@ bgp_table_stats_walker (struct thread *t) struct bgp_info *ri; struct bgp_node *prn = rn->parent; unsigned int rinum = 0; - + if (rn == top) continue; - + if (!rn->info) continue; - + ts->counts[BGP_STATS_PREFIXES]++; ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen; @@ -9201,11 +9999,11 @@ bgp_table_stats_walker (struct thread *t) ts->counts[BGP_STATS_AVGPLEN], rn->p.prefixlen); #endif - + /* check if the prefix is included by any other announcements */ while (prn && !prn->info) prn = prn->parent; - + if (prn == NULL || prn == top) { ts->counts[BGP_STATS_UNAGGREGATEABLE]++; @@ -9215,36 +10013,36 @@ bgp_table_stats_walker (struct thread *t) } else if (prn->info) ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; - - for (ri = rn->info; ri; ri = ri->next) + + for (ri = rn->info; ri; ri = ri->info_next) { rinum++; ts->counts[BGP_STATS_RIB]++; - + if (ri->attr && (CHECK_FLAG (ri->attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)))) ts->counts[BGP_STATS_AGGREGATES]++; - + /* as-path stats */ if (ri->attr && ri->attr->aspath) { unsigned int hops = aspath_count_hops (ri->attr->aspath); unsigned int size = aspath_size (ri->attr->aspath); as_t highest = aspath_highest (ri->attr->aspath); - + ts->counts[BGP_STATS_ASPATH_COUNT]++; - + if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS]) ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops; - + if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE]) ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size; - + ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops; ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size; #if 0 - ts->counts[BGP_STATS_ASPATH_AVGHOPS] + ts->counts[BGP_STATS_ASPATH_AVGHOPS] = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT], ts->counts[BGP_STATS_ASPATH_AVGHOPS], hops); @@ -9266,25 +10064,25 @@ bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) { struct bgp_table_stats ts; unsigned int i; - + if (!bgp->rib[afi][safi]) { vty_out (vty, "%% No RIB exist for the AFI/SAFI%s", VTY_NEWLINE); return CMD_WARNING; } - + memset (&ts, 0, sizeof (ts)); ts.table = bgp->rib[afi][safi]; thread_execute (bm->master, bgp_table_stats_walker, &ts, 0); vty_out (vty, "BGP %s RIB statistics%s%s", afi_safi_print (afi, safi), VTY_NEWLINE, VTY_NEWLINE); - + for (i = 0; i < BGP_STATS_MAX; i++) { if (!table_stats_strs[i]) continue; - + switch (i) { #if 0 @@ -9301,7 +10099,7 @@ bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) vty_out (vty, "%-30s: ", table_stats_strs[i]); vty_out (vty, "%12.2f", ts.counts[i] ? - (float)ts.counts[i] / + (float)ts.counts[i] / (float)ts.counts[BGP_STATS_ASPATH_COUNT] : 0); break; @@ -9309,7 +10107,7 @@ bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) vty_out (vty, "%-30s: ", table_stats_strs[i]); vty_out (vty, "%12.2f", ts.counts[i] ? - (float)ts.counts[i] / + (float)ts.counts[i] / (float)ts.counts[BGP_STATS_PREFIXES] : 0); break; @@ -9319,27 +10117,27 @@ bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) if (ts.counts[BGP_STATS_MAXBITLEN] < 9) break; vty_out (vty, "%30s: ", "%% announced "); - vty_out (vty, "%12.2f%s", - 100 * (float)ts.counts[BGP_STATS_SPACE] / + vty_out (vty, "%12.2f%s", + 100 * (float)ts.counts[BGP_STATS_SPACE] / (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]), VTY_NEWLINE); vty_out (vty, "%30s: ", "/8 equivalent "); - vty_out (vty, "%12.2f%s", - (float)ts.counts[BGP_STATS_SPACE] / + vty_out (vty, "%12.2f%s", + (float)ts.counts[BGP_STATS_SPACE] / (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)), VTY_NEWLINE); if (ts.counts[BGP_STATS_MAXBITLEN] < 25) break; vty_out (vty, "%30s: ", "/24 equivalent "); - vty_out (vty, "%12.2f", - (float)ts.counts[BGP_STATS_SPACE] / + vty_out (vty, "%12.2f", + (float)ts.counts[BGP_STATS_SPACE] / (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24))); break; default: vty_out (vty, "%-30s: ", table_stats_strs[i]); vty_out (vty, "%12llu", ts.counts[i]); } - + vty_out (vty, "%s", VTY_NEWLINE); } return CMD_SUCCESS; @@ -9352,7 +10150,7 @@ bgp_table_stats_vty (struct vty *vty, const char *name, struct bgp *bgp; afi_t afi; safi_t safi; - + if (name) bgp = bgp_lookup_by_name (name); else @@ -9454,7 +10252,7 @@ ALIAS (show_bgp_statistics_view, "Address family\n" "Address Family modifier\n" "BGP RIB advertisement statistics\n") - + enum bgp_pcounts { PCOUNT_ADJ_IN = 0, @@ -9496,25 +10294,25 @@ bgp_peer_count_walker (struct thread *t) struct bgp_node *rn; struct peer_pcounts *pc = THREAD_ARG (t); const struct peer *peer = pc->peer; - + for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn)) { struct bgp_adj_in *ain; struct bgp_info *ri; - - for (ain = rn->adj_in; ain; ain = ain->next) + + for (ain = rn->adj_in; ain; ain = ain->adj_next) if (ain->peer == peer) pc->count[PCOUNT_ADJ_IN]++; - for (ri = rn->info; ri; ri = ri->next) + for (ri = rn->info; ri; ri = ri->info_next) { char buf[SU_ADDRSTRLEN]; - + if (ri->peer != peer) continue; - + pc->count[PCOUNT_ALL]++; - + if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)) pc->count[PCOUNT_DAMPED]++; if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) @@ -9527,7 +10325,7 @@ bgp_peer_count_walker (struct thread *t) pc->count[PCOUNT_VALID]++; if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) pc->count[PCOUNT_PFCNT]++; - + if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) { pc->count[PCOUNT_COUNTED]++; @@ -9561,28 +10359,28 @@ bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi) { struct peer_pcounts pcounts = { .peer = peer }; unsigned int i; - + if (!peer || !peer->bgp || !peer->afc[afi][safi] || !peer->bgp->rib[afi][safi]) { vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); return CMD_WARNING; } - + memset (&pcounts, 0, sizeof(pcounts)); pcounts.peer = peer; pcounts.table = peer->bgp->rib[afi][safi]; - + /* in-place call via thread subsystem so as to record execution time * stats for the thread-walk (i.e. ensure this can't be blamed on * on just vty_read()). */ thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0); - - vty_out (vty, "Prefix counts for %s, %s%s", + + vty_out (vty, "Prefix counts for %s, %s%s", peer->host, afi_safi_print (afi, safi), VTY_NEWLINE); vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE); - vty_out (vty, "%sCounts from RIB table walk:%s%s", + vty_out (vty, "%sCounts from RIB table walk:%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); for (i = 0; i < PCOUNT_MAX; i++) @@ -9596,7 +10394,7 @@ bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi) vty_out (vty, "Please report this bug, with the above command output%s", VTY_NEWLINE); } - + return CMD_SUCCESS; } @@ -9613,10 +10411,10 @@ DEFUN (show_ip_bgp_neighbor_prefix_counts, { struct peer *peer; - peer = peer_lookup_in_view (vty, NULL, argv[0]); - if (! peer) + peer = peer_lookup_in_view (vty, NULL, argv[0]); + if (! peer) return CMD_WARNING; - + return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST); } @@ -9633,10 +10431,10 @@ DEFUN (show_bgp_ipv6_neighbor_prefix_counts, { struct peer *peer; - peer = peer_lookup_in_view (vty, NULL, argv[0]); - if (! peer) + peer = peer_lookup_in_view (vty, NULL, argv[0]); + if (! peer) return CMD_WARNING; - + return bgp_peer_counts (vty, peer, AFI_IP6, SAFI_UNICAST); } @@ -9685,7 +10483,7 @@ DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts, peer = peer_lookup_in_view (vty, NULL, argv[0]); if (! peer) return CMD_WARNING; - + return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN); } @@ -9711,11 +10509,11 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, table = bgp->rib[afi][safi]; output_count = 0; - + if (! in && CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE)) { - vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "BGP table version is 0, local router ID is %s%s", safe_inet_ntoa (bgp->router_id), VTY_NEWLINE); vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); @@ -9727,12 +10525,12 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) if (in) { - for (ain = rn->adj_in; ain; ain = ain->next) + for (ain = rn->adj_in; ain; ain = ain->adj_next) if (ain->peer == peer) { if (header1) { - vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "BGP table version is 0, local router ID is %s%s", safe_inet_ntoa (bgp->router_id), VTY_NEWLINE); vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); header1 = 0; @@ -9743,7 +10541,7 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, header2 = 0; } if (ain->attr) - { + { route_vty_out_tmp (vty, &rn->p, ain->attr, safi); output_count++; } @@ -9751,12 +10549,12 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, } else { - for (adj = rn->adj_out; adj; adj = adj->next) + for (adj = rn->adj_out; adj; adj = adj->adj_next) if (adj->peer == peer) { if (header1) { - vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "BGP table version is 0, local router ID is %s%s", safe_inet_ntoa (bgp->router_id), VTY_NEWLINE); vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE); header1 = 0; @@ -9767,13 +10565,13 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, header2 = 0; } if (adj->attr) - { + { route_vty_out_tmp (vty, &rn->p, adj->attr, safi); output_count++; } } } - + if (output_count != 0) vty_out (vty, "%sTotal number of prefixes %ld%s", VTY_NEWLINE, output_count, VTY_NEWLINE); @@ -9781,7 +10579,7 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, static int peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, int in) -{ +{ if (! peer || ! peer->afc[afi][safi]) { vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); @@ -9820,9 +10618,9 @@ DEFUN (show_ip_bgp_view_neighbor_advertised_route, else peer = peer_lookup_in_view (vty, NULL, argv[0]); - if (! peer) + if (! peer) return CMD_WARNING; - + return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 0); } @@ -9884,7 +10682,7 @@ DEFUN (show_bgp_view_neighbor_advertised_route, peer = peer_lookup_in_view (vty, NULL, argv[0]); if (! peer) - return CMD_WARNING; + return CMD_WARNING; return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 0); } @@ -9949,7 +10747,7 @@ ALIAS (show_bgp_view_neighbor_advertised_route, "Neighbor to display information about\n" "Neighbor to display information about\n" "Display the routes advertised to a BGP neighbor\n") - + ALIAS (show_bgp_view_neighbor_advertised_route, show_bgp_ipv6_neighbor_advertised_route_cmd, "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) advertised-routes", @@ -9972,7 +10770,7 @@ ALIAS (show_bgp_view_neighbor_advertised_route, "Neighbor to display information about\n" "Neighbor to display information about\n" "Display the routes advertised to a BGP neighbor\n") - + /* old command */ DEFUN (ipv6_mbgp_neighbor_advertised_route, ipv6_mbgp_neighbor_advertised_route_cmd, @@ -9989,12 +10787,12 @@ DEFUN (ipv6_mbgp_neighbor_advertised_route, peer = peer_lookup_in_view (vty, NULL, argv[0]); if (! peer) - return CMD_WARNING; + return CMD_WARNING; return peer_adj_routes (vty, peer, AFI_IP6, SAFI_MULTICAST, 0); } #endif /* HAVE_IPV6 */ - + DEFUN (show_ip_bgp_view_neighbor_received_routes, show_ip_bgp_view_neighbor_received_routes_cmd, "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X) received-routes", @@ -10051,7 +10849,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_routes, peer = peer_lookup_in_view (vty, NULL, argv[1]); if (! peer) return CMD_WARNING; - + if (strncmp (argv[0], "m", 1) == 0) return peer_adj_routes (vty, peer, AFI_IP, SAFI_MULTICAST, 1); @@ -10182,7 +10980,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter, prefix_bgp_show_prefix_list (vty, AFI_IP, name); } } - else + else { sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_UNICAST); count = prefix_bgp_show_prefix_list (NULL, AFI_IP, name); @@ -10321,11 +11119,11 @@ DEFUN (show_bgp_view_neighbor_received_prefix_filter, /* BGP structure lookup. */ bgp = bgp_lookup_by_name (argv[0]); if (bgp == NULL) - { + { vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } - + su = sockunion_str2su (argv[1]); if (su == NULL) return CMD_WARNING; @@ -10359,7 +11157,7 @@ ALIAS (show_bgp_view_neighbor_received_prefix_filter, "Display information received from a BGP neighbor\n" "Display the prefixlist filter\n") #endif /* HAVE_IPV6 */ - + static int bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_type type) @@ -10369,7 +11167,7 @@ bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi, vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); return CMD_WARNING; } - + return bgp_show (vty, peer->bgp, afi, safi, type, &peer->su); } @@ -10389,7 +11187,7 @@ DEFUN (show_ip_bgp_neighbor_routes, peer = peer_lookup_in_view (vty, NULL, argv[0]); if (! peer) return CMD_WARNING; - + return bgp_show_neighbor_route (vty, peer, AFI_IP, SAFI_UNICAST, bgp_show_type_neighbor); } @@ -10410,7 +11208,7 @@ DEFUN (show_ip_bgp_neighbor_flap, peer = peer_lookup_in_view (vty, NULL, argv[0]); if (! peer) return CMD_WARNING; - + return bgp_show_neighbor_route (vty, peer, AFI_IP, SAFI_UNICAST, bgp_show_type_flap_neighbor); } @@ -10431,7 +11229,7 @@ DEFUN (show_ip_bgp_neighbor_damp, peer = peer_lookup_in_view (vty, NULL, argv[0]); if (! peer) return CMD_WARNING; - + return bgp_show_neighbor_route (vty, peer, AFI_IP, SAFI_UNICAST, bgp_show_type_damp_neighbor); } @@ -10455,7 +11253,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_routes, peer = peer_lookup_in_view (vty, NULL, argv[1]); if (! peer) return CMD_WARNING; - + if (strncmp (argv[0], "m", 1) == 0) return bgp_show_neighbor_route (vty, peer, AFI_IP, SAFI_MULTICAST, bgp_show_type_neighbor); @@ -10631,8 +11429,8 @@ DEFUN (show_ip_bgp_view_rsclient_route, VTY_NEWLINE); return CMD_WARNING; } - - return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST], + + return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST], (argc == 3) ? argv[2] : argv[1], AFI_IP, SAFI_UNICAST, NULL, 0); } @@ -10770,7 +11568,7 @@ DEFUN (show_ip_bgp_view_rsclient_prefix, if (! peer) return CMD_WARNING; - + if (! peer->afc[AFI_IP][SAFI_UNICAST]) { vty_out (vty, "%% Activate the neighbor for the address family first%s", @@ -10785,8 +11583,8 @@ DEFUN (show_ip_bgp_view_rsclient_prefix, VTY_NEWLINE); return CMD_WARNING; } - - return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST], + + return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST], (argc == 3) ? argv[2] : argv[1], AFI_IP, SAFI_UNICAST, NULL, 1); } @@ -10901,7 +11699,7 @@ DEFUN (show_bgp_view_neighbor_routes, peer = peer_lookup_in_view (vty, argv[0], argv[1]); else peer = peer_lookup_in_view (vty, NULL, argv[0]); - + if (! peer) return CMD_WARNING; @@ -10999,7 +11797,7 @@ ALIAS (show_bgp_view_neighbor_flap, "Neighbor to display information about\n" "Neighbor to display information about\n" "Display flap statistics of the routes learned from neighbor\n") - + ALIAS (show_bgp_view_neighbor_routes, show_bgp_neighbor_routes_cmd, "show bgp neighbors (A.B.C.D|X:X::X:X) routes", @@ -11051,7 +11849,7 @@ DEFUN (ipv6_mbgp_neighbor_routes, peer = peer_lookup_in_view (vty, NULL, argv[0]); if (! peer) return CMD_WARNING; - + return bgp_show_neighbor_route (vty, peer, AFI_IP6, SAFI_MULTICAST, bgp_show_type_neighbor); } @@ -11511,7 +12309,7 @@ ALIAS (show_bgp_view_ipv6_safi_rsclient_prefix, "IP prefix <network>/<length>, e.g., 3ffe::/16\n") #endif /* HAVE_IPV6 */ - + struct bgp_table *bgp_distance_table; struct bgp_distance @@ -11536,7 +12334,7 @@ bgp_distance_free (struct bgp_distance *bdistance) } static int -bgp_distance_set (struct vty *vty, const char *distance_str, +bgp_distance_set (struct vty *vty, const char *distance_str, const char *ip_str, const char *access_list_str) { int ret; @@ -11583,7 +12381,7 @@ bgp_distance_set (struct vty *vty, const char *distance_str, } static int -bgp_distance_unset (struct vty *vty, const char *distance_str, +bgp_distance_unset (struct vty *vty, const char *distance_str, const char *ip_str, const char *access_list_str) { int ret; @@ -11788,7 +12586,7 @@ DEFUN (no_bgp_distance_source_access_list, bgp_distance_unset (vty, argv[0], argv[1], argv[2]); return CMD_SUCCESS; } - + DEFUN (bgp_damp_set, bgp_damp_set_cmd, "bgp dampening <1-45> <1-20000> <1-20000> <1-255>", @@ -11883,11 +12681,11 @@ DEFUN (show_ip_bgp_flap_statistics, return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_flap_statistics, NULL); } - + /* Display specified route of BGP table. */ static int -bgp_clear_damp_route (struct vty *vty, const char *view_name, - const char *ip_str, afi_t afi, safi_t safi, +bgp_clear_damp_route (struct vty *vty, const char *view_name, + const char *ip_str, afi_t afi, safi_t safi, struct prefix_rd *prd, int prefix_check) { int ret; @@ -11931,14 +12729,15 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name, if (safi == SAFI_MPLS_VPN) { - for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) + for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; + rn = bgp_route_next (rn)) { if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) continue; if ((table = rn->info) != NULL) if ((rm = bgp_node_match (table, &match)) != NULL) - { + { if (! prefix_check || rm->p.prefixlen == match.prefixlen) { ri = rm->info; @@ -11946,17 +12745,16 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name, { if (ri->extra && ri->extra->damp_info) { - ri_temp = ri->next; + ri_temp = ri->info_next; bgp_damp_info_free (ri->extra->damp_info, 1); ri = ri_temp; } else - ri = ri->next; + ri = ri->info_next; } } - bgp_unlock_node (rm); - } + } } } else @@ -11970,15 +12768,14 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name, { if (ri->extra && ri->extra->damp_info) { - ri_temp = ri->next; + ri_temp = ri->info_next; bgp_damp_info_free (ri->extra->damp_info, 1); ri = ri_temp; } else - ri = ri->next; + ri = ri->info_next; } } - bgp_unlock_node (rn); } } @@ -12047,7 +12844,7 @@ DEFUN (clear_ip_bgp_dampening_address_mask, return bgp_clear_damp_route (vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 0); } - + static int bgp_config_write_network_vpnv4 (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, int *write) @@ -12061,11 +12858,11 @@ bgp_config_write_network_vpnv4 (struct vty *vty, struct bgp *bgp, u_int32_t label; char buf[SU_ADDRSTRLEN]; char rdbuf[RD_ADDRSTRLEN]; - + /* Network configuration. */ for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn)) if ((table = prn->info) != NULL) - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) if ((bgp_static = rn->info) != NULL) { p = &rn->p; @@ -12079,7 +12876,7 @@ bgp_config_write_network_vpnv4 (struct vty *vty, struct bgp *bgp, label = decode_label (bgp_static->tag); vty_out (vty, " network %s/%d rd %s tag %d", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen, rdbuf, label); vty_out (vty, "%s", VTY_NEWLINE); @@ -12098,12 +12895,12 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, struct bgp_static *bgp_static; struct bgp_aggregate *bgp_aggregate; char buf[SU_ADDRSTRLEN]; - + if (afi == AFI_IP && safi == SAFI_MPLS_VPN) return bgp_config_write_network_vpnv4 (vty, bgp, afi, safi, write); /* Network configuration. */ - for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) + for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) if ((bgp_static = rn->info) != NULL) { p = &rn->p; @@ -12114,7 +12911,7 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, /* "network" configuration display. */ if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) { - u_int32_t destination; + u_int32_t destination; struct in_addr netmask; destination = ntohl (p->u.prefix4.s_addr); @@ -12130,18 +12927,18 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, /* Natural mask is not display. */ } else - vty_out (vty, " mask %s", inet_ntoa (netmask)); + vty_out (vty, " mask %s", safe_inet_ntoa (netmask)); } else { vty_out (vty, " network %s/%d", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); } if (bgp_static->rmap.name) vty_out (vty, " route-map %s", bgp_static->rmap.name); - else + else { if (bgp_static->backdoor) vty_out (vty, " backdoor"); @@ -12166,7 +12963,7 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, masklen2ip (p->prefixlen, &netmask); vty_out (vty, " aggregate-address %s %s", inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - inet_ntoa (netmask)); + safe_inet_ntoa (netmask)); } else { @@ -12177,7 +12974,7 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, if (bgp_aggregate->as_set) vty_out (vty, " as-set"); - + if (bgp_aggregate->summary_only) vty_out (vty, " summary-only"); @@ -12203,12 +13000,12 @@ bgp_config_write_distance (struct vty *vty, struct bgp *bgp) vty_out (vty, " distance bgp %d %d %d%s", bgp->distance_ebgp, bgp->distance_ibgp, bgp->distance_local, VTY_NEWLINE); - + for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn)) if ((bdistance = rn->info) != NULL) { vty_out (vty, " distance %d %s/%d %s%s", bdistance->distance, - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, + safe_inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, bdistance->access_list ? bdistance->access_list : "", VTY_NEWLINE); } @@ -12277,7 +13074,7 @@ bgp_route_init (void) install_element (BGP_IPV4_NODE, &no_bgp_network_route_map_cmd); install_element (BGP_IPV4_NODE, &no_bgp_network_mask_route_map_cmd); install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_route_map_cmd); - + install_element (BGP_IPV4_NODE, &aggregate_address_cmd); install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd); install_element (BGP_IPV4_NODE, &aggregate_address_summary_only_cmd); @@ -12312,6 +13109,7 @@ bgp_route_init (void) install_element (BGP_IPV4M_NODE, &no_bgp_network_route_map_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_route_map_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_route_map_cmd); + install_element (BGP_IPV4M_NODE, &aggregate_address_cmd); install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd); install_element (BGP_IPV4M_NODE, &aggregate_address_summary_only_cmd); @@ -12423,7 +13221,7 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd); - + /* Restricted node: VIEW_NODE - (set of dangerous commands) */ install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd); @@ -12666,16 +13464,16 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_view_neighbor_flap_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_flap_cmd); install_element (VIEW_NODE, &show_bgp_view_neighbor_damp_cmd); - install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd); install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd); install_element (VIEW_NODE, &show_bgp_view_rsclient_route_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd); install_element (VIEW_NODE, &show_bgp_view_rsclient_prefix_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd); - + /* Restricted: - * VIEW_NODE - (set of dangerous commands) - (commands dependent on prev) + * VIEW_NODE - (set of dangerous commands) - (commands dependent on prev) */ install_element (RESTRICTED_NODE, &show_bgp_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_cmd); @@ -12797,13 +13595,13 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd); install_element (ENABLE_NODE, &show_bgp_view_rsclient_prefix_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd); - + /* Statistics */ install_element (ENABLE_NODE, &show_bgp_statistics_cmd); install_element (ENABLE_NODE, &show_bgp_statistics_vpnv4_cmd); install_element (ENABLE_NODE, &show_bgp_statistics_view_cmd); install_element (ENABLE_NODE, &show_bgp_statistics_view_vpnv4_cmd); - + /* old command */ install_element (VIEW_NODE, &show_ipv6_bgp_cmd); install_element (VIEW_NODE, &show_ipv6_bgp_route_cmd); @@ -12841,7 +13639,7 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ipv6_mbgp_community_list_cmd); install_element (VIEW_NODE, &show_ipv6_mbgp_community_list_exact_cmd); install_element (VIEW_NODE, &show_ipv6_mbgp_prefix_longer_cmd); - + /* old command */ install_element (ENABLE_NODE, &show_ipv6_bgp_cmd); install_element (ENABLE_NODE, &show_ipv6_bgp_route_cmd); @@ -12917,7 +13715,7 @@ bgp_route_init (void) install_element (BGP_IPV4_NODE, &bgp_damp_set3_cmd); install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd); install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd); - + /* Deprecated AS-Pathlimit commands */ install_element (BGP_NODE, &bgp_network_ttl_cmd); install_element (BGP_NODE, &bgp_network_mask_ttl_cmd); @@ -12925,35 +13723,35 @@ bgp_route_init (void) install_element (BGP_NODE, &bgp_network_backdoor_ttl_cmd); install_element (BGP_NODE, &bgp_network_mask_backdoor_ttl_cmd); install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd); - + install_element (BGP_NODE, &no_bgp_network_ttl_cmd); install_element (BGP_NODE, &no_bgp_network_mask_ttl_cmd); install_element (BGP_NODE, &no_bgp_network_mask_natural_ttl_cmd); install_element (BGP_NODE, &no_bgp_network_backdoor_ttl_cmd); install_element (BGP_NODE, &no_bgp_network_mask_backdoor_ttl_cmd); install_element (BGP_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd); - + install_element (BGP_IPV4_NODE, &bgp_network_ttl_cmd); install_element (BGP_IPV4_NODE, &bgp_network_mask_ttl_cmd); install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_ttl_cmd); install_element (BGP_IPV4_NODE, &bgp_network_backdoor_ttl_cmd); install_element (BGP_IPV4_NODE, &bgp_network_mask_backdoor_ttl_cmd); install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd); - + install_element (BGP_IPV4_NODE, &no_bgp_network_ttl_cmd); install_element (BGP_IPV4_NODE, &no_bgp_network_mask_ttl_cmd); install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_ttl_cmd); install_element (BGP_IPV4_NODE, &no_bgp_network_backdoor_ttl_cmd); install_element (BGP_IPV4_NODE, &no_bgp_network_mask_backdoor_ttl_cmd); install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd); - + install_element (BGP_IPV4M_NODE, &bgp_network_ttl_cmd); install_element (BGP_IPV4M_NODE, &bgp_network_mask_ttl_cmd); install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_ttl_cmd); install_element (BGP_IPV4M_NODE, &bgp_network_backdoor_ttl_cmd); install_element (BGP_IPV4M_NODE, &bgp_network_mask_backdoor_ttl_cmd); install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd); - + install_element (BGP_IPV4M_NODE, &no_bgp_network_ttl_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_ttl_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_ttl_cmd); |