diff options
Diffstat (limited to 'bgpd')
42 files changed, 8954 insertions, 3656 deletions
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index d2775f39..fe1be32e 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -16,7 +16,7 @@ libbgp_a_SOURCES = \ bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \ bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \ bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \ - bgp_encap.c bgp_encap_tlv.c + bgp_encap.c bgp_encap_tlv.c bgp_nht.c noinst_HEADERS = \ bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \ @@ -24,7 +24,7 @@ noinst_HEADERS = \ bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \ bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h \ - bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h + bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h bgpd_SOURCES = bgp_main.c bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@ diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index ecf531f7..43573b59 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -26,12 +26,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "hash.h" #include "thread.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_advertise.h" #include "bgpd/bgp_attr.h" +#include "bgpd/bgp_debug.h" #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_packet.h" #include "bgpd/bgp_fsm.h" @@ -186,10 +188,12 @@ bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj, struct bgp_advertise *adv; struct bgp_advertise_attr *baa; struct bgp_advertise *next; + struct bgp_advertise_fifo *fhead; adv = adj->adv; baa = adv->baa; next = NULL; + fhead = (struct bgp_advertise_fifo *)&peer->sync[afi][safi]->withdraw; if (baa) { @@ -201,10 +205,12 @@ bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj, /* Unintern BGP advertise attribute. */ bgp_advertise_unintern (peer->hash[afi][safi], baa); + + fhead = (struct bgp_advertise_fifo *)&peer->sync[afi][safi]->update; } /* Unlink myself from advertisement FIFO. */ - FIFO_DEL (adv); + BGP_ADV_FIFO_DEL (fhead, adv); /* Free memory. */ bgp_advertise_free (adj->adv); @@ -264,7 +270,24 @@ bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p, /* Add new advertisement to advertisement attribute list. */ bgp_advertise_add (adv->baa, adv); - FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo); + BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo); + + /* + * Schedule write thread (by triggering adjustment of MRAI timer) only if + * update FIFO has grown. Otherwise, it will be done upon the work queue + * being fully processed. Only adjust timer if needed. + */ + if (!BGP_ROUTE_ADV_HOLD(peer->bgp) && + (BGP_ADV_FIFO_COUNT(&peer->sync[afi][safi]->update) >= + peer->bgp->adv_quanta)) + { + if (!peer->radv_adjusted) + { + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("%s scheduling MRAI timer after adj_out_set", peer->host); + bgp_adjust_routeadv(peer); + } + } } void @@ -298,10 +321,24 @@ bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p, adv->adj = adj; /* Add to synchronization entry for withdraw announcement. */ - FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo); - - /* Schedule packet write. */ - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo); + + /* + * Schedule write thread only if withdraw FIFO has grown. Otherwise, + * it will be done upon the work queue being fully processed. + */ + if (!BGP_ROUTE_ADV_HOLD(peer->bgp) && + (BGP_ADV_FIFO_COUNT(&peer->sync[afi][safi]->withdraw) >= + peer->bgp->wd_quanta)) + { + if (!peer->t_write) + { + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("%s scheduling write thread after adj_out_unset", + peer->host); + BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + } + } } else { @@ -391,9 +428,9 @@ bgp_sync_init (struct peer *peer) { sync = XCALLOC (MTYPE_BGP_SYNCHRONISE, sizeof (struct bgp_synchronize)); - FIFO_INIT (&sync->update); - FIFO_INIT (&sync->withdraw); - FIFO_INIT (&sync->withdraw_low); + BGP_ADV_FIFO_INIT (&sync->update); + BGP_ADV_FIFO_INIT (&sync->withdraw); + BGP_ADV_FIFO_INIT (&sync->withdraw_low); peer->sync[afi][safi] = sync; peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp); } diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index 51ba6267..6babc16c 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -23,6 +23,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include <lib/fifo.h> +/* BGP advertise FIFO. */ +struct bgp_advertise_fifo +{ + struct bgp_advertise *next; + struct bgp_advertise *prev; + u_int32_t count; +}; + /* BGP advertise attribute. */ struct bgp_advertise_attr { @@ -124,6 +132,27 @@ struct bgp_synchronize #define BGP_ADJ_OUT_ADD(N,A) BGP_INFO_ADD(N,A,adj_out) #define BGP_ADJ_OUT_DEL(N,A) BGP_INFO_DEL(N,A,adj_out) +#define BGP_ADV_FIFO_ADD(F, N) \ + do { \ + FIFO_ADD((F), (N)); \ + (F)->count++; \ + } while (0) + +#define BGP_ADV_FIFO_DEL(F, N) \ + do { \ + FIFO_DEL((N)); \ + (F)->count--; \ + } while (0) + +#define BGP_ADV_FIFO_INIT(F) \ + do { \ + FIFO_INIT((F)); \ + (F)->count = 0; \ + } while (0) + +#define BGP_ADV_FIFO_COUNT(F) \ + (F)->count + /* Prototypes. */ extern void bgp_adj_out_set (struct bgp_node *, struct peer *, struct prefix *, struct attr *, afi_t, safi_t, struct bgp_info *); diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 6ab29376..71d510ec 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "stream.h" #include "jhash.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" @@ -427,7 +428,7 @@ aspath_count_confeds (struct aspath *aspath) } unsigned int -aspath_count_hops (struct aspath *aspath) +aspath_count_hops (const struct aspath *aspath) { int count = 0; struct assegment *seg = aspath->segments; @@ -471,13 +472,11 @@ aspath_highest (struct aspath *aspath) struct assegment *seg = aspath->segments; as_t highest = 0; unsigned int i; - + while (seg) { for (i = 0; i < seg->length; i++) - if (seg->as[i] > highest - && (seg->as[i] < BGP_PRIVATE_AS_MIN - || seg->as[i] > BGP_PRIVATE_AS_MAX)) + if (seg->as[i] > highest && !BGP_AS_IS_PRIVATE(seg->as[i])) highest = seg->as[i]; seg = seg->next; } @@ -1065,6 +1064,9 @@ aspath_aggregate (struct aspath *as1, struct aspath *as2) if (match != minlen || match != seg1->length || seg1->length != seg2->length) break; + /* We are moving on to the next segment to reset match */ + else + match = 0; seg1 = seg1->next; seg2 = seg2->next; @@ -1146,20 +1148,44 @@ int aspath_private_as_check (struct aspath *aspath) { struct assegment *seg; - + if ( !(aspath && aspath->segments) ) return 0; - + seg = aspath->segments; while (seg) { int i; - + + for (i = 0; i < seg->length; i++) + { + if (!BGP_AS_IS_PRIVATE(seg->as[i])) + return 0; + } + seg = seg->next; + } + return 1; +} + +/* Return True if the entire ASPATH consist of the specified ASN */ +int +aspath_single_asn_check (struct aspath *aspath, as_t asn) +{ + struct assegment *seg; + + if ( !(aspath && aspath->segments) ) + return 0; + + seg = aspath->segments; + + while (seg) + { + int i; + for (i = 0; i < seg->length; i++) { - if ( (seg->as[i] < BGP_PRIVATE_AS_MIN) - || (seg->as[i] > BGP_PRIVATE_AS_MAX) ) + if (seg->as[i] != asn) return 0; } seg = seg->next; @@ -1167,6 +1193,132 @@ aspath_private_as_check (struct aspath *aspath) return 1; } +/* Replace all instances of the target ASN with our own ASN */ +struct aspath * +aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, + as_t our_asn) +{ + struct aspath *new; + struct assegment *seg; + + new = aspath_dup(aspath); + seg = new->segments; + + while (seg) + { + int i; + + for (i = 0; i < seg->length; i++) + { + if (seg->as[i] == target_asn) + seg->as[i] = our_asn; + } + seg = seg->next; + } + + aspath_str_update(new); + return new; +} + +/* Replace all private ASNs with our own ASN */ +struct aspath * +aspath_replace_private_asns (struct aspath *aspath, as_t asn) +{ + struct aspath *new; + struct assegment *seg; + + new = aspath_dup(aspath); + seg = new->segments; + + while (seg) + { + int i; + + for (i = 0; i < seg->length; i++) + { + if (BGP_AS_IS_PRIVATE(seg->as[i])) + seg->as[i] = asn; + } + seg = seg->next; + } + + aspath_str_update(new); + return new; +} + +/* Remove all private ASNs */ +struct aspath * +aspath_remove_private_asns (struct aspath *aspath) +{ + struct aspath *new; + struct assegment *seg; + struct assegment *new_seg; + struct assegment *last_new_seg; + int i; + int j; + int public = 0; + + new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath)); + + new_seg = NULL; + last_new_seg = NULL; + seg = aspath->segments; + while (seg) + { + public = 0; + for (i = 0; i < seg->length; i++) + { + // ASN is public + if (!BGP_AS_IS_PRIVATE(seg->as[i])) + { + public++; + } + } + + // The entire segment is private so skip it + if (!public) + { + seg = seg->next; + continue; + } + + // The entire segment is public so copy it + else if (public == seg->length) + { + new_seg = assegment_dup (seg); + } + + // The segment is a mix of public and private ASNs. Copy as many spots as + // there are public ASNs then come back and fill in only the public ASNs. + else + { + new_seg = assegment_new (seg->type, public); + j = 0; + for (i = 0; i < seg->length; i++) + { + // ASN is public + if (!BGP_AS_IS_PRIVATE(seg->as[i])) + { + new_seg->as[j] = seg->as[i]; + j++; + } + } + } + + // This is the first segment so set the aspath segments pointer to this one + if (!last_new_seg) + new->segments = new_seg; + else + last_new_seg->next = new_seg; + + last_new_seg = new_seg; + seg = seg->next; + } + + aspath_str_update(new); + return new; +} + /* AS path confed check. If aspath contains confed set or sequence then return 1. */ int aspath_confed_check (struct aspath *aspath) @@ -1443,6 +1595,10 @@ aspath_cmp_left (const struct aspath *aspath1, const struct aspath *aspath2) seg1 = aspath1->segments; seg2 = aspath2->segments; + /* If both paths are originated in this AS then we do want to compare MED */ + if (!seg1 && !seg2) + return 1; + /* find first non-confed segments for each */ while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE) || (seg1->type == AS_CONFED_SET))) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index 1311f8a5..134f1f66 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -31,12 +31,20 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define BGP_PRIVATE_AS_MIN 64512U #define BGP_PRIVATE_AS_MAX 65535U +/* Private 4 byte AS range defined in RFC6996. */ +#define BGP_PRIVATE_AS4_MIN 4200000000U +#define BGP_PRIVATE_AS4_MAX 4294967294U + /* we leave BGP_AS_MAX as the 16bit AS MAX number. */ #define BGP_AS_MAX 65535U #define BGP_AS4_MAX 4294967295U /* Transition 16Bit AS as defined by IANA */ #define BGP_AS_TRANS 23456U +#define BGP_AS_IS_PRIVATE(ASN) \ + (((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) || \ + ((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX)) + /* AS_PATH segment data in abstracted form, no limit is placed on length */ struct assegment { @@ -90,11 +98,15 @@ extern void aspath_print_all_vty (struct vty *); extern unsigned int aspath_key_make (void *); extern int aspath_loop_check (struct aspath *, as_t); extern int aspath_private_as_check (struct aspath *); +extern int aspath_single_asn_check (struct aspath *, as_t asn); +extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn); +extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn); +extern struct aspath *aspath_remove_private_asns (struct aspath *aspath); extern int aspath_firstas_check (struct aspath *, as_t); extern int aspath_confed_check (struct aspath *); extern int aspath_left_confed_check (struct aspath *); extern unsigned long aspath_count (void); -extern unsigned int aspath_count_hops (struct aspath *); +extern unsigned int aspath_count_hops (const struct aspath *); extern unsigned int aspath_count_confeds (struct aspath *); extern unsigned int aspath_size (struct aspath *); extern as_t aspath_highest (struct aspath *); diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index f34e6493..bc39f3b8 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -153,7 +153,6 @@ cluster_free (struct cluster_list *cluster) XFREE (MTYPE_CLUSTER, cluster); } -#if 0 static struct cluster_list * cluster_dup (struct cluster_list *cluster) { @@ -172,7 +171,6 @@ cluster_dup (struct cluster_list *cluster) return new; } -#endif static struct cluster_list * cluster_intern (struct cluster_list *cluster) @@ -322,6 +320,23 @@ transit_free (struct transit *transit) XFREE (MTYPE_TRANSIT, transit); } +static struct transit * +transit_dup (struct transit *transit) +{ + struct transit *new; + + new = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit)); + new->length = transit->length; + if (new->length) + { + new->val = XMALLOC (MTYPE_TRANSIT_VAL, transit->length); + memcpy (new->val, transit->val, transit->length); + } + else + new->val = NULL; + + return new; +} static void * transit_hash_alloc (void *p) @@ -458,6 +473,46 @@ bgp_attr_dup (struct attr *new, struct attr *orig) } } +void +bgp_attr_deep_dup (struct attr *new, struct attr *orig) +{ + if (orig->aspath) + new->aspath = aspath_dup(orig->aspath); + + if (orig->community) + new->community = community_dup(orig->community); + + if (orig->extra) + { + if (orig->extra->ecommunity) + new->extra->ecommunity = ecommunity_dup(orig->extra->ecommunity); + if (orig->extra->cluster) + new->extra->cluster = cluster_dup(orig->extra->cluster); + if (orig->extra->transit) + new->extra->transit = transit_dup(orig->extra->transit); + } +} + +void +bgp_attr_deep_free (struct attr *attr) +{ + if (attr->aspath) + aspath_free(attr->aspath); + + if (attr->community) + community_free(attr->community); + + if (attr->extra) + { + if (attr->extra->ecommunity) + ecommunity_free(&attr->extra->ecommunity); + if (attr->extra->cluster) + cluster_free(attr->extra->cluster); + if (attr->extra->transit) + transit_free(attr->extra->transit); + } +} + unsigned long int attr_count (void) { @@ -495,6 +550,7 @@ attrhash_key_make (void *p) MIX(extra->weight); MIX(extra->mp_nexthop_global_in.s_addr); MIX(extra->originator_id.s_addr); + MIX(extra->tag); } if (attr->aspath) @@ -540,6 +596,7 @@ attrhash_cmp (const void *p1, const void *p2) && ae1->aggregator_as == ae2->aggregator_as && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr && ae1->weight == ae2->weight + && ae1->tag == ae2->tag && ae1->mp_nexthop_len == ae2->mp_nexthop_len && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global) && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local) @@ -691,6 +748,7 @@ bgp_attr_default_set (struct attr *attr, u_char origin) attr->aspath = aspath_empty (); attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT; + attr->extra->tag = 0; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN; @@ -717,10 +775,12 @@ bgp_attr_default_intern (u_char origin) return new; } +/* Create the attributes for an aggregate */ struct attr * bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, struct aspath *aspath, - struct community *community, int as_set) + struct community *community, int as_set, + u_char atomic_aggregate) { struct attr attr; struct attr *new; @@ -753,7 +813,7 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, attre.weight = BGP_ATTR_DEFAULT_WEIGHT; attre.mp_nexthop_len = IPV6_MAX_BYTELEN; - if (! as_set) + if (! as_set || atomic_aggregate) attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) @@ -962,19 +1022,18 @@ bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args, CHECK_FLAG (real_flags, attr_flag_str[i].key) ) { - zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"", - LOOKUP (attr_str, attr_code), - CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not", - attr_flag_str[i].str); + zlog_err ("%s attribute must%s be flagged as \"%s\"", + LOOKUP (attr_str, attr_code), + CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not", + attr_flag_str[i].str); seen = 1; } if (!seen) { - zlog (args->peer->log, LOG_DEBUG, - "Strange, %s called for attr %s, but no problem found with flags" - " (real flags 0x%x, desired 0x%x)", - __func__, LOOKUP (attr_str, attr_code), - real_flags, desired_flags); + zlog_debug ("Strange, %s called for attr %s, but no problem found with flags" + " (real flags 0x%x, desired 0x%x)", + __func__, LOOKUP (attr_str, attr_code), + real_flags, desired_flags); } } @@ -1007,7 +1066,6 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) u_int8_t mask = BGP_ATTR_FLAG_EXTLEN; const u_int8_t flags = args->flags; const u_int8_t attr_code = args->type; - struct peer *const peer = args->peer; /* there may be attributes we don't know about */ if (attr_code > attr_flags_values_max) @@ -1021,9 +1079,8 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags) && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags)) { - zlog (peer->log, LOG_ERR, - "%s well-known attributes must have transitive flag set (%x)", - LOOKUP (attr_str, attr_code), flags); + zlog_err ("%s well-known attributes must have transitive flag set (%x)", + LOOKUP (attr_str, attr_code), flags); return 1; } @@ -1034,19 +1091,17 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) { if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)) { - zlog (peer->log, LOG_ERR, - "%s well-known attribute " - "must NOT have the partial flag set (%x)", - LOOKUP (attr_str, attr_code), flags); + zlog_err ("%s well-known attribute " + "must NOT have the partial flag set (%x)", + LOOKUP (attr_str, attr_code), flags); return 1; } if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)) { - zlog (peer->log, LOG_ERR, - "%s optional + transitive attribute " - "must NOT have the partial flag set (%x)", - LOOKUP (attr_str, attr_code), flags); + zlog_err ("%s optional + transitive attribute " + "must NOT have the partial flag set (%x)", + LOOKUP (attr_str, attr_code), flags); return 1; } } @@ -1081,8 +1136,7 @@ bgp_attr_origin (struct bgp_attr_parser_args *args) value). */ if (length != 1) { - zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d", - length); + zlog_err ("Origin attribute length is not one %d", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1098,8 +1152,7 @@ bgp_attr_origin (struct bgp_attr_parser_args *args) && (attr->origin != BGP_ORIGIN_EGP) && (attr->origin != BGP_ORIGIN_INCOMPLETE)) { - zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d", - attr->origin); + zlog_err ("Origin attribute value is invalid %d", attr->origin); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN, args->total); @@ -1130,9 +1183,7 @@ bgp_attr_aspath (struct bgp_attr_parser_args *args) /* In case of IBGP, length will be zero. */ if (! attr->aspath) { - zlog (peer->log, LOG_ERR, - "Malformed AS path from %s, length is %d", - peer->host, length); + zlog_err ("Malformed AS path from %s, length is %d", peer->host, length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0); } @@ -1159,7 +1210,7 @@ bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr) if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) || (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath))) { - zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host); + zlog_err ("Malformed AS path from %s", peer->host); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_AS_PATH); return BGP_ATTR_PARSE_ERROR; @@ -1171,8 +1222,7 @@ bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr) if (peer->sort == BGP_PEER_EBGP && ! aspath_firstas_check (attr->aspath, peer->as)) { - zlog (peer->log, LOG_ERR, - "%s incorrect first AS (must be %u)", peer->host, peer->as); + zlog_err ("%s incorrect first AS (must be %u)", peer->host, peer->as); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_AS_PATH); return BGP_ATTR_PARSE_ERROR; @@ -1206,9 +1256,7 @@ bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path) /* In case of IBGP, length will be zero. */ if (!*as4_path) { - zlog (peer->log, LOG_ERR, - "Malformed AS4 path from %s, length is %d", - peer->host, length); + zlog_err ("Malformed AS4 path from %s, length is %d", peer->host, length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0); @@ -1234,8 +1282,7 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args) /* Check nexthop attribute length. */ if (length != 4) { - zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]", - length); + zlog_err ("Nexthop attribute length isn't four [%d]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -1253,7 +1300,7 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args) { char buf[INET_ADDRSTRLEN]; inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN); - zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf); + zlog_err ("Martian nexthop %s", buf); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, args->total); @@ -1276,8 +1323,7 @@ bgp_attr_med (struct bgp_attr_parser_args *args) /* Length check. */ if (length != 4) { - zlog (peer->log, LOG_ERR, - "MED attribute length isn't four [%d]", length); + zlog_err ("MED attribute length isn't four [%d]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -1302,8 +1348,7 @@ bgp_attr_local_pref (struct bgp_attr_parser_args *args) /* Length check. */ if (length != 4) { - zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]", - length); + zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1330,15 +1375,13 @@ bgp_attr_local_pref (struct bgp_attr_parser_args *args) static int bgp_attr_atomic (struct bgp_attr_parser_args *args) { - struct peer *const peer = args->peer; struct attr *const attr = args->attr; const bgp_size_t length = args->length; /* Length check. */ if (length != 0) { - zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]", - length); + zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1367,8 +1410,7 @@ bgp_attr_aggregator (struct bgp_attr_parser_args *args) if (length != wantedlen) { - zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]", - wantedlen, length); + zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen, length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1398,8 +1440,7 @@ bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args, if (length != 8) { - zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]", - length); + zlog_err ("New Aggregator length is not 8 [%d]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 0); @@ -1562,7 +1603,7 @@ bgp_attr_originator_id (struct bgp_attr_parser_args *args) /* Length check. */ if (length != 4) { - zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length); + zlog_err ("Bad originator ID length %d", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -1588,7 +1629,7 @@ bgp_attr_cluster_list (struct bgp_attr_parser_args *args) /* Check length. */ if (length % 4) { - zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length); + zlog_err ("Bad cluster list length %d", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1698,8 +1739,8 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args, char buf1[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN]; - if (BGP_DEBUG (update, UPDATE_IN)) - zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host, + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug ("%s sent two nexthops %s %s but second one is not a link-local nexthop", peer->host, inet_ntop (AF_INET6, &attre->mp_nexthop_global, buf1, INET6_ADDRSTRLEN), inet_ntop (AF_INET6, &attre->mp_nexthop_local, @@ -1736,7 +1777,7 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args, __func__, peer->host); return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; } - + mp_update->afi = afi; mp_update->safi = safi; mp_update->nlri = stream_pnt (s); @@ -1837,8 +1878,7 @@ bgp_attr_encap( if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS) || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) { - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute flag isn't optional and transitive %d", flag); + zlog_err ("Tunnel Encap attribute flag isn't optional and transitive %d", flag); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, @@ -1851,8 +1891,7 @@ bgp_attr_encap( uint16_t tlv_length; if (length < 4) { - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute not long enough to contain outer T,L"); + zlog_err ("Tunnel Encap attribute not long enough to contain outer T,L"); bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, @@ -1864,7 +1903,7 @@ bgp_attr_encap( length -= 4; if (tlv_length != length) { - zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)", + zlog_err ("%s: tlv_length(%d) != length(%d)", __func__, tlv_length, length); } } @@ -1881,8 +1920,7 @@ bgp_attr_encap( } if (sublength > length) { - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d", + zlog_err ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d", sublength, length); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, @@ -1923,8 +1961,7 @@ bgp_attr_encap( if (length) { /* spurious leftover data */ - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute length is bad: %d leftover octets", length); + zlog_err ("Tunnel Encap attribute length is bad: %d leftover octets", length); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, @@ -1949,15 +1986,10 @@ bgp_attr_unknown (struct bgp_attr_parser_args *args) const u_char flag = args->flags; const bgp_size_t length = args->length; - - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s Unknown attribute is received (type %d, length %d)", - peer->host, type, length); + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug ("%s Unknown attribute is received (type %d, length %d)", + peer->host, type, length); - if (BGP_DEBUG (events, EVENTS)) - zlog (peer->log, LOG_DEBUG, - "Unknown attribute type %d length %d is received", type, length); - /* Forward read pointer of input stream. */ stream_forward_getp (peer->ibuf, length); @@ -2039,9 +2071,7 @@ bgp_attr_check (struct peer *peer, struct attr *attr) if (type) { - zlog (peer->log, LOG_WARNING, - "%s Missing well-known attribute %d / %s", - peer->host, type, LOOKUP (attr_str, type)); + zlog_warn ("%s Missing well-known attribute %d.", peer->host, type); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MISS_ATTR, @@ -2083,10 +2113,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN) { /* XXX warning: long int format, int arg (arg 5) */ - zlog (peer->log, LOG_WARNING, - "%s: error BGP attribute length %lu is smaller than min len", - peer->host, - (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); + zlog_warn ("%s: error BGP attribute length %lu is smaller than min len", + peer->host, + (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, @@ -2106,10 +2135,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) { - zlog (peer->log, LOG_WARNING, - "%s: Extended length set, but just %lu bytes of attr header", - peer->host, - (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); + zlog_warn ("%s: Extended length set, but just %lu bytes of attr header", + peer->host, + (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, @@ -2129,9 +2157,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (CHECK_BITMAP (seen, type)) { - zlog (peer->log, LOG_WARNING, - "%s: error BGP attribute type %d appears twice in a message", - peer->host, type); + zlog_warn ("%s: error BGP attribute type %d appears twice in a message", + peer->host, type); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, @@ -2149,11 +2176,11 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (attr_endp > endp) { - zlog (peer->log, LOG_WARNING, - "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp); - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + zlog_warn ("%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp); + bgp_notify_send_with_data (peer, + BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + startp, attr_endp - startp); return BGP_ATTR_PARSE_ERROR; } @@ -2252,10 +2279,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, /* If hard error occured immediately return to the caller. */ if (ret == BGP_ATTR_PARSE_ERROR) { - zlog (peer->log, LOG_WARNING, - "%s: Attribute %s, parse error", - peer->host, - LOOKUP (attr_str, type)); + zlog_warn ("%s: Attribute %s, parse error", + peer->host, + LOOKUP (attr_str, type)); if (as4_path) aspath_unintern (&as4_path); return ret; @@ -2263,10 +2289,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (ret == BGP_ATTR_PARSE_WITHDRAW) { - zlog (peer->log, LOG_WARNING, - "%s: Attribute %s, parse error - treating as withdrawal", - peer->host, - LOOKUP (attr_str, type)); + zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal", + peer->host, + LOOKUP (attr_str, type)); if (as4_path) aspath_unintern (&as4_path); return ret; @@ -2275,9 +2300,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, /* Check the fetched length. */ if (BGP_INPUT_PNT (peer) != attr_endp) { - zlog (peer->log, LOG_WARNING, - "%s: BGP attribute %s, fetch error", - peer->host, LOOKUP (attr_str, type)); + zlog_warn ("%s: BGP attribute %s, fetch error", + peer->host, LOOKUP (attr_str, type)); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); @@ -2289,9 +2313,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, /* Check final read pointer is same as end pointer. */ if (BGP_INPUT_PNT (peer) != endp) { - zlog (peer->log, LOG_WARNING, - "%s: BGP attribute %s, length mismatch", - peer->host, LOOKUP (attr_str, type)); + zlog_warn ("%s: BGP attribute %s, length mismatch", + peer->host, LOOKUP (attr_str, type)); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); @@ -2547,8 +2570,7 @@ bgp_packet_mpattr_tea( } if (attrlenfield > 0xffff) { - zlog (peer->log, LOG_ERR, - "%s attribute is too long (length=%d), can't send it", + zlog_err ("%s attribute is too long (length=%d), can't send it", attrname, attrlenfield); return; @@ -2705,12 +2727,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, } /* MED attribute. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) || + bgp->maxmed_active) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); stream_putc (s, 4); - stream_putl (s, attr->med); + stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med)); } /* Local preference. */ diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index fe6c2a1a..87310d50 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -93,6 +93,9 @@ struct attr_extra uint16_t encap_tunneltype; /* grr */ struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */ + + /* route tag */ + u_short tag; }; /* BGP core attribute structure. */ @@ -117,6 +120,7 @@ struct attr struct in_addr nexthop; u_int32_t med; u_int32_t local_pref; + ifindex_t nh_ifindex; /* Path origin attribute */ u_char origin; @@ -140,6 +144,10 @@ struct transit #define ATTR_FLAG_BIT(X) (1 << ((X) - 1)) +#define BGP_CLUSTER_LIST_LENGTH(attr) \ + (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \ + (attr)->extra->cluster->length : 0) + typedef enum { BGP_ATTR_PARSE_PROCEED = 0, BGP_ATTR_PARSE_ERROR = -1, @@ -158,6 +166,8 @@ extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *, extern struct attr_extra *bgp_attr_extra_get (struct attr *); extern void bgp_attr_extra_free (struct attr *); extern void bgp_attr_dup (struct attr *, struct attr *); +extern void bgp_attr_deep_dup (struct attr *, struct attr *); +extern void bgp_attr_deep_free (struct attr *); extern struct attr *bgp_attr_intern (struct attr *attr); extern void bgp_attr_unintern_sub (struct attr *); extern void bgp_attr_unintern (struct attr **); @@ -166,7 +176,7 @@ extern struct attr *bgp_attr_default_set (struct attr *attr, u_char); extern struct attr *bgp_attr_default_intern (u_char); extern struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char, struct aspath *, - struct community *, int as_set); + struct community *, int as_set, u_char); extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *, struct stream *, struct attr *, struct prefix *, afi_t, safi_t, diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index b408efdd..d298f8ba 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "privs.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_dump.h" diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index bb06028b..4abdf0c7 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "prefix.h" #include "memory.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_community.h" @@ -707,7 +708,10 @@ community_list_set (struct community_list_handler *ch, if (community_list_dup_check (list, entry)) community_entry_free (entry); else - community_list_entry_add (list, entry); + { + community_list_entry_add (list, entry); + route_map_notify_dependencies(name, RMAP_EVENT_CLIST_ADDED); + } return 0; } @@ -733,6 +737,7 @@ community_list_unset (struct community_list_handler *ch, if (!str) { community_list_delete (list); + route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); return 0; } @@ -758,6 +763,7 @@ community_list_unset (struct community_list_handler *ch, return COMMUNITY_LIST_ERR_CANT_FIND_LIST; community_list_entry_delete (list, entry, style); + route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); return 0; } @@ -826,7 +832,10 @@ extcommunity_list_set (struct community_list_handler *ch, if (community_list_dup_check (list, entry)) community_entry_free (entry); else - community_list_entry_add (list, entry); + { + community_list_entry_add (list, entry); + route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_ADDED); + } return 0; } @@ -852,6 +861,7 @@ extcommunity_list_unset (struct community_list_handler *ch, if (!str) { community_list_delete (list); + route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); return 0; } @@ -877,6 +887,7 @@ extcommunity_list_unset (struct community_list_handler *ch, return COMMUNITY_LIST_ERR_CANT_FIND_LIST; community_list_entry_delete (list, entry, style); + route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); return 0; } diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index ac647239..1c128cc1 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "log.h" #include "thread.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_damp.h" diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 60e2777e..2a4997e8 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "log.h" #include "sockunion.h" #include "filter.h" +#include "memory.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" @@ -38,24 +39,31 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_community.h" unsigned long conf_bgp_debug_as4; -unsigned long conf_bgp_debug_fsm; +unsigned long conf_bgp_debug_neighbor_events; unsigned long conf_bgp_debug_events; unsigned long conf_bgp_debug_packet; unsigned long conf_bgp_debug_filter; unsigned long conf_bgp_debug_keepalive; unsigned long conf_bgp_debug_update; -unsigned long conf_bgp_debug_normal; unsigned long conf_bgp_debug_zebra; +unsigned long conf_bgp_debug_nht; unsigned long term_bgp_debug_as4; -unsigned long term_bgp_debug_fsm; +unsigned long term_bgp_debug_neighbor_events; unsigned long term_bgp_debug_events; unsigned long term_bgp_debug_packet; unsigned long term_bgp_debug_filter; unsigned long term_bgp_debug_keepalive; unsigned long term_bgp_debug_update; -unsigned long term_bgp_debug_normal; unsigned long term_bgp_debug_zebra; +unsigned long term_bgp_debug_nht; + +struct list *bgp_debug_neighbor_events_peers = NULL; +struct list *bgp_debug_keepalive_peers = NULL; +struct list *bgp_debug_update_out_peers = NULL; +struct list *bgp_debug_update_in_peers = NULL; +struct list *bgp_debug_update_prefixes = NULL; +struct list *bgp_debug_zebra_prefixes = NULL; /* messages for BGP-4 status */ const struct message bgp_status_msg[] = @@ -90,7 +98,7 @@ static const struct message bgp_notify_msg[] = { BGP_NOTIFY_OPEN_ERR, "OPEN Message Error"}, { BGP_NOTIFY_UPDATE_ERR, "UPDATE Message Error"}, { BGP_NOTIFY_HOLD_ERR, "Hold Timer Expired"}, - { BGP_NOTIFY_FSM_ERR, "Finite State Machine Error"}, + { BGP_NOTIFY_FSM_ERR, "Neighbor Events Error"}, { BGP_NOTIFY_CEASE, "Cease"}, { BGP_NOTIFY_CAPABILITY_ERR, "CAPABILITY Message Error"}, }; @@ -161,6 +169,151 @@ static const int bgp_notify_capability_msg_max = BGP_NOTIFY_CAPABILITY_MAX; const char *bgp_origin_str[] = {"i","e","?"}; const char *bgp_origin_long_str[] = {"IGP","EGP","incomplete"}; + +/* Given a string return a pointer the corresponding peer structure */ +static struct peer * +bgp_find_peer (struct vty *vty, const char *peer_str) +{ + int ret; + union sockunion su; + struct bgp *bgp; + + bgp = vty->index; + ret = str2sockunion (peer_str, &su); + + /* 'swpX' string */ + if (ret < 0) + return peer_lookup_by_conf_if (bgp, peer_str); + else + return peer_lookup (bgp, &su); +} + +static void +bgp_debug_list_free(struct list *list) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + if (list) + for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) + { + listnode_delete (list, filter); + + if (filter->p) + prefix_free(filter->p); + + if (filter->peer) + peer_unlock (filter->peer); + + XFREE (MTYPE_BGP_DEBUG_FILTER, filter); + } +} + +/* Print the desc along with a list of peers/prefixes this debug is + * enabled for */ +static void +bgp_debug_list_print (struct vty *vty, const char *desc, struct list *list) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + char buf[INET6_ADDRSTRLEN]; + + vty_out (vty, "%s", desc); + + if (list && !list_isempty(list)) + { + vty_out (vty, " for"); + for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) + { + if (filter->peer) + vty_out (vty, " %s", filter->peer->host); + + if (filter->p) + vty_out (vty, " %s/%d", + inet_ntop (filter->p->family, &filter->p->u.prefix, buf, INET6_ADDRSTRLEN), + filter->p->prefixlen); + } + } + + vty_out (vty, "%s", VTY_NEWLINE); +} + +static void +bgp_debug_list_add_entry(struct list *list, struct peer *peer, struct prefix *p) +{ + struct bgp_debug_filter *filter; + + filter = XCALLOC (MTYPE_BGP_DEBUG_FILTER, sizeof (struct bgp_debug_filter)); + + if (peer) + { + peer_lock (peer); + filter->peer = peer; + filter->p = NULL; + } + else if (p) + { + filter->peer = NULL; + filter->p = p; + } + + listnode_add(list, filter); +} + +static int +bgp_debug_list_remove_entry(struct list *list, struct peer *peer, struct prefix *p) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) + { + if (peer && filter->peer == peer) + { + listnode_delete (list, filter); + peer_unlock (filter->peer); + XFREE (MTYPE_BGP_DEBUG_FILTER, filter); + return 1; + } + else if (p && filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) + { + listnode_delete (list, filter); + prefix_free (filter->p); + XFREE (MTYPE_BGP_DEBUG_FILTER, filter); + return 1; + } + } + + return 0; +} + +static int +bgp_debug_list_has_entry(struct list *list, struct peer *peer, struct prefix *p) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) + { + if (peer) + { + if (filter->peer == peer) + { + return 1; + } + } + else if (p) + { + if (filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) + { + return 1; + } + } + } + + return 0; +} + /* Dump attribute. */ int bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size) @@ -276,18 +429,12 @@ bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify, break; } - if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) + if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS) || bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) zlog_info ("%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) %d bytes %s", strcmp (direct, "received") == 0 ? "received from" : "sent to", peer->host, bgp_notify->code, bgp_notify->subcode, code_str, subcode_str, bgp_notify->length, bgp_notify->data ? bgp_notify->data : ""); - else if (BGP_DEBUG (normal, NORMAL)) - plog_debug (peer->log, "%s %s NOTIFICATION %d/%d (%s%s) %d bytes %s", - peer ? peer->host : "", - direct, bgp_notify->code, bgp_notify->subcode, - code_str, subcode_str, bgp_notify->length, - bgp_notify->data ? bgp_notify->data : ""); } /* Debug option setting interface. */ @@ -334,13 +481,6 @@ DEFUN (no_debug_bgp_as4, return CMD_SUCCESS; } -ALIAS (no_debug_bgp_as4, - undebug_bgp_as4_cmd, - "undebug bgp as4", - UNDEBUG_STR - BGP_STR - "BGP AS4 actions\n") - DEFUN (debug_bgp_as4_segment, debug_bgp_as4_segment_cmd, "debug bgp as4 segment", @@ -378,140 +518,163 @@ DEFUN (no_debug_bgp_as4_segment, return CMD_SUCCESS; } -ALIAS (no_debug_bgp_as4_segment, - undebug_bgp_as4_segment_cmd, - "undebug bgp as4 segment", - UNDEBUG_STR - BGP_STR - "BGP AS4 actions\n" - "BGP AS4 aspath segment handling\n") - -DEFUN (debug_bgp_fsm, - debug_bgp_fsm_cmd, - "debug bgp fsm", +/* debug bgp neighbor_events */ +DEFUN (debug_bgp_neighbor_events, + debug_bgp_neighbor_events_cmd, + "debug bgp neighbor-events", DEBUG_STR BGP_STR - "BGP Finite State Machine\n") + "BGP Neighbor Events\n") { if (vty->node == CONFIG_NODE) - DEBUG_ON (fsm, FSM); + DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); else { - TERM_DEBUG_ON (fsm, FSM); - vty_out (vty, "BGP fsm debugging is on%s", VTY_NEWLINE); + TERM_DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); + vty_out (vty, "BGP neighbor-events debugging is on%s", VTY_NEWLINE); } return CMD_SUCCESS; } -DEFUN (no_debug_bgp_fsm, - no_debug_bgp_fsm_cmd, - "no debug bgp fsm", - NO_STR +DEFUN (debug_bgp_neighbor_events_peer, + debug_bgp_neighbor_events_peer_cmd, + "debug bgp neighbor-events (A.B.C.D|X:X::X:X|WORD)", DEBUG_STR BGP_STR - "Finite State Machine\n") + "BGP Neighbor Events\n" + "BGP neighbor IP address to debug\n" + "BGP IPv6 neighbor to debug\n" + "BGP neighbor on interface to debug\n") { + struct peer *peer; + + peer = bgp_find_peer (vty, argv[0]); + if (!peer) + { + vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + if (!bgp_debug_neighbor_events_peers) + bgp_debug_neighbor_events_peers = list_new (); + + if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, peer, NULL)) + { + vty_out (vty, "BGP neighbor-events debugging is already enabled for %s%s", peer->host, VTY_NEWLINE); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, peer, NULL); + if (vty->node == CONFIG_NODE) - DEBUG_OFF (fsm, FSM); + DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); else { - TERM_DEBUG_OFF (fsm, FSM); - vty_out (vty, "BGP fsm debugging is off%s", VTY_NEWLINE); + TERM_DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); + vty_out (vty, "BGP neighbor-events debugging is on for %s%s", argv[0], VTY_NEWLINE); } return CMD_SUCCESS; } -ALIAS (no_debug_bgp_fsm, - undebug_bgp_fsm_cmd, - "undebug bgp fsm", - UNDEBUG_STR - BGP_STR - "Finite State Machine\n") - -DEFUN (debug_bgp_events, - debug_bgp_events_cmd, - "debug bgp events", +DEFUN (no_debug_bgp_neighbor_events, + no_debug_bgp_neighbor_events_cmd, + "no debug bgp neighbor-events", + NO_STR DEBUG_STR BGP_STR - "BGP events\n") + "Neighbor Events\n") { + bgp_debug_list_free(bgp_debug_neighbor_events_peers); + if (vty->node == CONFIG_NODE) - DEBUG_ON (events, EVENTS); + DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); else { - TERM_DEBUG_ON (events, EVENTS); - vty_out (vty, "BGP events debugging is on%s", VTY_NEWLINE); + TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); + vty_out (vty, "BGP neighbor-events debugging is off%s", VTY_NEWLINE); } return CMD_SUCCESS; } -DEFUN (no_debug_bgp_events, - no_debug_bgp_events_cmd, - "no debug bgp events", +DEFUN (no_debug_bgp_neighbor_events_peer, + no_debug_bgp_neighbor_events_peer_cmd, + "no debug bgp neighbor-events (A.B.C.D|X:X::X:X|WORD)", NO_STR DEBUG_STR BGP_STR - "BGP events\n") + "Neighbor Events\n" + "BGP neighbor IP address to debug\n" + "BGP IPv6 neighbor to debug\n" + "BGP neighbor on interface to debug\n") { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (events, EVENTS); - else + int found_peer = 0; + struct peer *peer; + + peer = bgp_find_peer (vty, argv[0]); + if (!peer) + { + vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp_debug_neighbor_events_peers && !list_isempty(bgp_debug_neighbor_events_peers)) { - TERM_DEBUG_OFF (events, EVENTS); - vty_out (vty, "BGP events debugging is off%s", VTY_NEWLINE); + found_peer = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, peer, NULL); + + if (list_isempty(bgp_debug_neighbor_events_peers)) + { + if (vty->node == CONFIG_NODE) + DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); + else + TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); + } } + + if (found_peer) + vty_out (vty, "BGP neighbor-events debugging is off for %s%s", argv[0], VTY_NEWLINE); + else + vty_out (vty, "BGP neighbor-events debugging was not enabled for %s%s", argv[0], VTY_NEWLINE); + return CMD_SUCCESS; } -ALIAS (no_debug_bgp_events, - undebug_bgp_events_cmd, - "undebug bgp events", - UNDEBUG_STR - BGP_STR - "BGP events\n") - -DEFUN (debug_bgp_filter, - debug_bgp_filter_cmd, - "debug bgp filters", +/* debug bgp nht */ +DEFUN (debug_bgp_nht, + debug_bgp_nht_cmd, + "debug bgp nht", DEBUG_STR BGP_STR - "BGP filters\n") + "BGP nexthop tracking events\n") { if (vty->node == CONFIG_NODE) - DEBUG_ON (filter, FILTER); + DEBUG_ON (nht, NHT); else { - TERM_DEBUG_ON (filter, FILTER); - vty_out (vty, "BGP filters debugging is on%s", VTY_NEWLINE); + TERM_DEBUG_ON (nht, NHT); + vty_out (vty, "BGP nexthop tracking debugging is on%s", VTY_NEWLINE); } return CMD_SUCCESS; } -DEFUN (no_debug_bgp_filter, - no_debug_bgp_filter_cmd, - "no debug bgp filters", +DEFUN (no_debug_bgp_nht, + no_debug_bgp_nht_cmd, + "no debug bgp nht", NO_STR DEBUG_STR BGP_STR - "BGP filters\n") + "BGP nexthop tracking events\n") { if (vty->node == CONFIG_NODE) - DEBUG_OFF (filter, FILTER); + DEBUG_OFF (nht, NHT); else { - TERM_DEBUG_OFF (filter, FILTER); - vty_out (vty, "BGP filters debugging is off%s", VTY_NEWLINE); + TERM_DEBUG_OFF (nht, NHT); + vty_out (vty, "BGP nexthop tracking debugging is off%s", VTY_NEWLINE); } return CMD_SUCCESS; } -ALIAS (no_debug_bgp_filter, - undebug_bgp_filter_cmd, - "undebug bgp filters", - UNDEBUG_STR - BGP_STR - "BGP filters\n") - +/* debug bgp keepalives */ DEFUN (debug_bgp_keepalive, debug_bgp_keepalive_cmd, "debug bgp keepalives", @@ -529,6 +692,46 @@ DEFUN (debug_bgp_keepalive, return CMD_SUCCESS; } +DEFUN (debug_bgp_keepalive_peer, + debug_bgp_keepalive_peer_cmd, + "debug bgp keepalives (A.B.C.D|X:X::X:X|WORD)", + DEBUG_STR + BGP_STR + "BGP Neighbor Events\n" + "BGP neighbor IP address to debug\n" + "BGP IPv6 neighbor to debug\n" + "BGP neighbor on interface to debug\n") +{ + struct peer *peer; + + peer = bgp_find_peer (vty, argv[0]); + if (!peer) + { + vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + if (!bgp_debug_keepalive_peers) + bgp_debug_keepalive_peers = list_new (); + + if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, peer, NULL)) + { + vty_out (vty, "BGP keepalive debugging is already enabled for %s%s", peer->host, VTY_NEWLINE); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_keepalive_peers, peer, NULL); + + if (vty->node == CONFIG_NODE) + DEBUG_ON (keepalive, KEEPALIVE); + else + { + TERM_DEBUG_ON (keepalive, KEEPALIVE); + vty_out (vty, "BGP keepalives debugging is on for %s%s", argv[0], VTY_NEWLINE); + } + return CMD_SUCCESS; +} + DEFUN (no_debug_bgp_keepalive, no_debug_bgp_keepalive_cmd, "no debug bgp keepalives", @@ -537,6 +740,8 @@ DEFUN (no_debug_bgp_keepalive, BGP_STR "BGP keepalives\n") { + bgp_debug_list_free(bgp_debug_keepalive_peers); + if (vty->node == CONFIG_NODE) DEBUG_OFF (keepalive, KEEPALIVE); else @@ -547,13 +752,49 @@ DEFUN (no_debug_bgp_keepalive, return CMD_SUCCESS; } -ALIAS (no_debug_bgp_keepalive, - undebug_bgp_keepalive_cmd, - "undebug bgp keepalives", - UNDEBUG_STR +DEFUN (no_debug_bgp_keepalive_peer, + no_debug_bgp_keepalive_peer_cmd, + "no debug bgp keepalives (A.B.C.D|X:X::X:X|WORD)", + NO_STR + DEBUG_STR BGP_STR - "BGP keepalives\n") + "BGP keepalives\n" + "BGP neighbor IP address to debug\n" + "BGP IPv6 neighbor to debug\n" + "BGP neighbor on interface to debug\n") +{ + int found_peer = 0; + struct peer *peer; + + peer = bgp_find_peer (vty, argv[0]); + if (!peer) + { + vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp_debug_keepalive_peers && !list_isempty(bgp_debug_keepalive_peers)) + { + found_peer = bgp_debug_list_remove_entry(bgp_debug_keepalive_peers, peer, NULL); + + if (list_isempty(bgp_debug_keepalive_peers)) + { + if (vty->node == CONFIG_NODE) + DEBUG_OFF (keepalive, KEEPALIVE); + else + TERM_DEBUG_OFF (keepalive, KEEPALIVE); + } + } + if (found_peer) + vty_out (vty, "BGP keepalives debugging is off for %s%s", argv[0], VTY_NEWLINE); + else + vty_out (vty, "BGP keepalives debugging was not enabled for %s%s", argv[0], VTY_NEWLINE); + + return CMD_SUCCESS; +} + +/* debug bgp updates */ DEFUN (debug_bgp_update, debug_bgp_update_cmd, "debug bgp updates", @@ -615,74 +856,299 @@ DEFUN (debug_bgp_update_direct, return CMD_SUCCESS; } -DEFUN (no_debug_bgp_update, - no_debug_bgp_update_cmd, - "no debug bgp updates", - NO_STR +DEFUN (debug_bgp_update_direct_peer, + debug_bgp_update_direct_peer_cmd, + "debug bgp updates (in|out) (A.B.C.D|X:X::X:X|WORD)", DEBUG_STR BGP_STR - "BGP updates\n") + "BGP updates\n" + "Inbound updates\n" + "Outbound updates\n" + "BGP neighbor IP address to debug\n" + "BGP IPv6 neighbor to debug\n" + "BGP neighbor on interface to debug\n") { + struct peer *peer; + int inbound; + + peer = bgp_find_peer (vty, argv[1]); + if (!peer) + { + vty_out (vty, "%s is not a configured peer%s", argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + + + if (!bgp_debug_update_in_peers) + bgp_debug_update_in_peers = list_new (); + + if (!bgp_debug_update_out_peers) + bgp_debug_update_out_peers = list_new (); + + if (strncmp ("i", argv[0], 1) == 0) + inbound = 1; + else + inbound = 0; + + if (inbound) + { + if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, peer, NULL)) + { + vty_out (vty, "BGP inbound update debugging is already enabled for %s%s", peer->host, VTY_NEWLINE); + return CMD_SUCCESS; + } + } + + else + { + if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, peer, NULL)) + { + vty_out (vty, "BGP outbound update debugging is already enabled for %s%s", peer->host, VTY_NEWLINE); + return CMD_SUCCESS; + } + } + + if (inbound) + bgp_debug_list_add_entry(bgp_debug_update_in_peers, peer, NULL); + else + bgp_debug_list_add_entry(bgp_debug_update_out_peers, peer, NULL); + if (vty->node == CONFIG_NODE) { - DEBUG_OFF (update, UPDATE_IN); - DEBUG_OFF (update, UPDATE_OUT); + if (inbound) + { + DEBUG_OFF (update, UPDATE_OUT); + DEBUG_ON (update, UPDATE_IN); + } + else + { + DEBUG_OFF (update, UPDATE_IN); + DEBUG_ON (update, UPDATE_OUT); + } } else { - TERM_DEBUG_OFF (update, UPDATE_IN); - TERM_DEBUG_OFF (update, UPDATE_OUT); - vty_out (vty, "BGP updates debugging is off%s", VTY_NEWLINE); + if (inbound) + { + TERM_DEBUG_OFF (update, UPDATE_OUT); + TERM_DEBUG_ON (update, UPDATE_IN); + vty_out (vty, "BGP updates debugging is on (inbound) for %s%s", argv[1], VTY_NEWLINE); + } + else + { + TERM_DEBUG_OFF (update, UPDATE_IN); + TERM_DEBUG_ON (update, UPDATE_OUT); + vty_out (vty, "BGP updates debugging is on (outbound) for %s%s", argv[1], VTY_NEWLINE); + } } return CMD_SUCCESS; } -ALIAS (no_debug_bgp_update, - undebug_bgp_update_cmd, - "undebug bgp updates", - UNDEBUG_STR +DEFUN (no_debug_bgp_update_direct_peer, + no_debug_bgp_update_direct_peer_cmd, + "no debug bgp updates (in|out) (A.B.C.D|X:X::X:X|WORD)", + NO_STR + DEBUG_STR BGP_STR - "BGP updates\n") + "BGP updates\n" + "Inbound updates\n" + "Outbound updates\n" + "BGP neighbor IP address to debug\n" + "BGP IPv6 neighbor to debug\n" + "BGP neighbor on interface to debug\n") +{ + int inbound; + int found_peer = 0; + struct peer *peer; + + peer = bgp_find_peer (vty, argv[1]); + if (!peer) + { + vty_out (vty, "%s is not a configured peer%s", argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + + if (strncmp ("i", argv[0], 1) == 0) + inbound = 1; + else + inbound = 0; + + if (inbound && bgp_debug_update_in_peers && + !list_isempty(bgp_debug_update_in_peers)) + { + found_peer = bgp_debug_list_remove_entry(bgp_debug_update_in_peers, peer, NULL); + + if (list_isempty(bgp_debug_update_in_peers)) + { + if (vty->node == CONFIG_NODE) + DEBUG_OFF (update, UPDATE_IN); + else + { + TERM_DEBUG_OFF (update, UPDATE_IN); + vty_out (vty, "BGP updates debugging (inbound) is off%s", VTY_NEWLINE); + } + } + } + + if (!inbound && bgp_debug_update_out_peers && + !list_isempty(bgp_debug_update_out_peers)) + { + found_peer = bgp_debug_list_remove_entry(bgp_debug_update_out_peers, peer, NULL); + + if (list_isempty(bgp_debug_update_out_peers)) + { + if (vty->node == CONFIG_NODE) + DEBUG_OFF (update, UPDATE_OUT); + else + { + TERM_DEBUG_OFF (update, UPDATE_OUT); + vty_out (vty, "BGP updates debugging (outbound) is off%s", VTY_NEWLINE); + } + } + } + + if (found_peer) + if (inbound) + vty_out (vty, "BGP updates debugging (inbound) is off for %s%s", argv[1], VTY_NEWLINE); + else + vty_out (vty, "BGP updates debugging (outbound) is off for %s%s", argv[1], VTY_NEWLINE); + else + if (inbound) + vty_out (vty, "BGP updates debugging (inbound) was not enabled for %s%s", argv[1], VTY_NEWLINE); + else + vty_out (vty, "BGP updates debugging (outbound) was not enabled for %s%s", argv[1], VTY_NEWLINE); + + return CMD_SUCCESS; +} -DEFUN (debug_bgp_normal, - debug_bgp_normal_cmd, - "debug bgp", +DEFUN (debug_bgp_update_prefix, + debug_bgp_update_prefix_cmd, + "debug bgp updates prefix (A.B.C.D/M|X:X::X:X/M)", DEBUG_STR - BGP_STR) + BGP_STR + "BGP updates\n" + "Specify a prefix to debug\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "IPv6 prefix <network>/<length>\n") + { + struct prefix *argv_p; + int ret; + + argv_p = prefix_new(); + ret = str2prefix (argv[0], argv_p); + if (!ret) + { + prefix_free(argv_p); + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + + if (!bgp_debug_update_prefixes) + bgp_debug_update_prefixes = list_new (); + + if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) + { + vty_out (vty, "BGP updates debugging is already enabled for %s%s", argv[0], VTY_NEWLINE); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p); + if (vty->node == CONFIG_NODE) - DEBUG_ON (normal, NORMAL); + { + DEBUG_ON (update, UPDATE_PREFIX); + } else { - TERM_DEBUG_ON (normal, NORMAL); - vty_out (vty, "BGP debugging is on%s", VTY_NEWLINE); + TERM_DEBUG_ON (update, UPDATE_PREFIX); + vty_out (vty, "BGP updates debugging is on for %s%s", argv[0], VTY_NEWLINE); } + return CMD_SUCCESS; } -DEFUN (no_debug_bgp_normal, - no_debug_bgp_normal_cmd, - "no debug bgp", +DEFUN (no_debug_bgp_update_prefix, + no_debug_bgp_update_prefix_cmd, + "no debug bgp updates prefix (A.B.C.D/M|X:X::X:X/M)", NO_STR DEBUG_STR - BGP_STR) + BGP_STR + "BGP updates\n" + "Specify a prefix to debug\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "IPv6 prefix <network>/<length>\n") + { + struct prefix *argv_p; + int found_prefix = 0; + int ret; + + argv_p = prefix_new(); + ret = str2prefix (argv[0], argv_p); + if (!ret) + { + prefix_free(argv_p); + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp_debug_update_prefixes && !list_isempty(bgp_debug_update_prefixes)) + { + found_prefix = bgp_debug_list_remove_entry(bgp_debug_update_prefixes, NULL, argv_p); + + if (list_isempty(bgp_debug_update_prefixes)) + { + if (vty->node == CONFIG_NODE) + { + DEBUG_OFF (update, UPDATE_PREFIX); + } + else + { + TERM_DEBUG_OFF (update, UPDATE_PREFIX); + vty_out (vty, "BGP updates debugging (per prefix) is off%s", VTY_NEWLINE); + } + } + } + + if (found_prefix) + vty_out (vty, "BGP updates debugging is off for %s%s", argv[0], VTY_NEWLINE); + else + vty_out (vty, "BGP updates debugging was not enabled for %s%s", argv[0], VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN (no_debug_bgp_update, + no_debug_bgp_update_cmd, + "no debug bgp updates", + NO_STR + DEBUG_STR + BGP_STR + "BGP updates\n") +{ + bgp_debug_list_free(bgp_debug_update_in_peers); + bgp_debug_list_free(bgp_debug_update_out_peers); + bgp_debug_list_free(bgp_debug_update_prefixes); + if (vty->node == CONFIG_NODE) - DEBUG_OFF (normal, NORMAL); + { + DEBUG_OFF (update, UPDATE_IN); + DEBUG_OFF (update, UPDATE_OUT); + DEBUG_OFF (update, UPDATE_PREFIX); + } else { - TERM_DEBUG_OFF (normal, NORMAL); - vty_out (vty, "BGP debugging is off%s", VTY_NEWLINE); + TERM_DEBUG_OFF (update, UPDATE_IN); + TERM_DEBUG_OFF (update, UPDATE_OUT); + TERM_DEBUG_OFF (update, UPDATE_PREFIX); + vty_out (vty, "BGP updates debugging is off%s", VTY_NEWLINE); } return CMD_SUCCESS; } -ALIAS (no_debug_bgp_normal, - undebug_bgp_normal_cmd, - "undebug bgp", - UNDEBUG_STR - BGP_STR) - +/* debug bgp zebra */ DEFUN (debug_bgp_zebra, debug_bgp_zebra_cmd, "debug bgp zebra", @@ -700,6 +1166,51 @@ DEFUN (debug_bgp_zebra, return CMD_SUCCESS; } +DEFUN (debug_bgp_zebra_prefix, + debug_bgp_zebra_prefix_cmd, + "debug bgp zebra prefix (A.B.C.D/M|X:X::X:X/M)", + DEBUG_STR + BGP_STR + "BGP Zebra messages\n" + "Specify a prefix to debug\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "IPv6 prefix <network>/<length>\n") + +{ + struct prefix *argv_p; + int ret; + + argv_p = prefix_new(); + ret = str2prefix (argv[0], argv_p); + if (!ret) + { + prefix_free(argv_p); + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (!bgp_debug_zebra_prefixes) + bgp_debug_zebra_prefixes = list_new(); + + if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, argv_p)) + { + vty_out (vty, "BGP zebra debugging is already enabled for %s%s", argv[0], VTY_NEWLINE); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, argv_p); + + if (vty->node == CONFIG_NODE) + DEBUG_ON (zebra, ZEBRA); + else + { + TERM_DEBUG_ON (zebra, ZEBRA); + vty_out (vty, "BGP zebra debugging is on for %s%s", argv[0], VTY_NEWLINE); + } + + return CMD_SUCCESS; +} + DEFUN (no_debug_bgp_zebra, no_debug_bgp_zebra_cmd, "no debug bgp zebra", @@ -708,6 +1219,8 @@ DEFUN (no_debug_bgp_zebra, BGP_STR "BGP Zebra messages\n") { + bgp_debug_list_free(bgp_debug_zebra_prefixes); + if (vty->node == CONFIG_NODE) DEBUG_OFF (zebra, ZEBRA); else @@ -718,43 +1231,82 @@ DEFUN (no_debug_bgp_zebra, return CMD_SUCCESS; } -ALIAS (no_debug_bgp_zebra, - undebug_bgp_zebra_cmd, - "undebug bgp zebra", - UNDEBUG_STR +DEFUN (no_debug_bgp_zebra_prefix, + no_debug_bgp_zebra_prefix_cmd, + "no debug bgp zebra prefix (A.B.C.D/M|X:X::X:X/M)", + NO_STR + DEBUG_STR BGP_STR - "BGP Zebra messages\n") + "BGP Zebra messages\n" + "Specify a prefix to debug\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "IPv6 prefix <network>/<length>\n") + +{ + struct prefix *argv_p; + int found_prefix = 0; + int ret; + + argv_p = prefix_new(); + ret = str2prefix (argv[0], argv_p); + if (!ret) + { + prefix_free(argv_p); + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (bgp_debug_zebra_prefixes && !list_isempty(bgp_debug_zebra_prefixes)) + { + found_prefix = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, NULL, argv_p); + + if (list_isempty(bgp_debug_zebra_prefixes)) + { + if (vty->node == CONFIG_NODE) + DEBUG_OFF (zebra, ZEBRA); + else + { + TERM_DEBUG_OFF (zebra, ZEBRA); + vty_out (vty, "BGP zebra debugging is off%s", VTY_NEWLINE); + } + } + } -DEFUN (no_debug_bgp_all, - no_debug_bgp_all_cmd, - "no debug all bgp", + if (found_prefix) + vty_out (vty, "BGP zebra debugging is off for %s%s", argv[0], VTY_NEWLINE); + else + vty_out (vty, "BGP zebra debugging was not enabled for %s%s", argv[0], VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN (no_debug_bgp, + no_debug_bgp_cmd, + "no debug bgp", NO_STR DEBUG_STR - "Enable all debugging\n" BGP_STR) { - TERM_DEBUG_OFF (normal, NORMAL); - TERM_DEBUG_OFF (events, EVENTS); + bgp_debug_list_free(bgp_debug_neighbor_events_peers); + bgp_debug_list_free(bgp_debug_keepalive_peers); + bgp_debug_list_free(bgp_debug_update_in_peers); + bgp_debug_list_free(bgp_debug_update_out_peers); + bgp_debug_list_free(bgp_debug_update_prefixes); + bgp_debug_list_free(bgp_debug_zebra_prefixes); + TERM_DEBUG_OFF (keepalive, KEEPALIVE); TERM_DEBUG_OFF (update, UPDATE_IN); TERM_DEBUG_OFF (update, UPDATE_OUT); + TERM_DEBUG_OFF (update, UPDATE_PREFIX); TERM_DEBUG_OFF (as4, AS4); TERM_DEBUG_OFF (as4, AS4_SEGMENT); - TERM_DEBUG_OFF (fsm, FSM); - TERM_DEBUG_OFF (filter, FILTER); + TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); TERM_DEBUG_OFF (zebra, ZEBRA); vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE); return CMD_SUCCESS; } -ALIAS (no_debug_bgp_all, - undebug_bgp_all_cmd, - "undebug all bgp", - UNDEBUG_STR - "Enable all debugging\n" - BGP_STR) - DEFUN (show_debugging_bgp, show_debugging_bgp_cmd, "show debugging bgp", @@ -764,28 +1316,39 @@ DEFUN (show_debugging_bgp, { vty_out (vty, "BGP debugging status:%s", VTY_NEWLINE); - if (BGP_DEBUG (normal, NORMAL)) - vty_out (vty, " BGP debugging is on%s", VTY_NEWLINE); - if (BGP_DEBUG (events, EVENTS)) - vty_out (vty, " BGP events debugging is on%s", VTY_NEWLINE); - if (BGP_DEBUG (keepalive, KEEPALIVE)) - vty_out (vty, " BGP keepalives debugging is on%s", VTY_NEWLINE); - if (BGP_DEBUG (update, UPDATE_IN) && BGP_DEBUG (update, UPDATE_OUT)) - vty_out (vty, " BGP updates debugging is on%s", VTY_NEWLINE); - else if (BGP_DEBUG (update, UPDATE_IN)) - vty_out (vty, " BGP updates debugging is on (inbound)%s", VTY_NEWLINE); - else if (BGP_DEBUG (update, UPDATE_OUT)) - vty_out (vty, " BGP updates debugging is on (outbound)%s", VTY_NEWLINE); - if (BGP_DEBUG (fsm, FSM)) - vty_out (vty, " BGP fsm debugging is on%s", VTY_NEWLINE); - if (BGP_DEBUG (filter, FILTER)) - vty_out (vty, " BGP filter debugging is on%s", VTY_NEWLINE); - if (BGP_DEBUG (zebra, ZEBRA)) - vty_out (vty, " BGP zebra debugging is on%s", VTY_NEWLINE); if (BGP_DEBUG (as4, AS4)) vty_out (vty, " BGP as4 debugging is on%s", VTY_NEWLINE); + if (BGP_DEBUG (as4, AS4_SEGMENT)) vty_out (vty, " BGP as4 aspath segment debugging is on%s", VTY_NEWLINE); + + if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS)) + bgp_debug_list_print (vty, " BGP neighbor-events debugging is on", + bgp_debug_neighbor_events_peers); + + if (BGP_DEBUG (keepalive, KEEPALIVE)) + bgp_debug_list_print (vty, " BGP keepalives debugging is on", + bgp_debug_keepalive_peers); + + if (BGP_DEBUG (nht, NHT)) + vty_out (vty, " BGP next-hop tracking debugging is on%s", VTY_NEWLINE); + + if (BGP_DEBUG (update, UPDATE_PREFIX)) + bgp_debug_list_print (vty, " BGP updates debugging is on for", + bgp_debug_update_prefixes); + + if (BGP_DEBUG (update, UPDATE_IN)) + bgp_debug_list_print (vty, " BGP updates debugging is on (inbound)", + bgp_debug_update_in_peers); + + if (BGP_DEBUG (update, UPDATE_OUT)) + bgp_debug_list_print (vty, " BGP updates debugging is on (outbound)", + bgp_debug_update_out_peers); + + if (BGP_DEBUG (zebra, ZEBRA)) + bgp_debug_list_print (vty, " BGP zebra debugging is on", + bgp_debug_zebra_prefixes); + vty_out (vty, "%s", VTY_NEWLINE); return CMD_SUCCESS; } @@ -795,12 +1358,6 @@ bgp_config_write_debug (struct vty *vty) { int write = 0; - if (CONF_BGP_DEBUG (normal, NORMAL)) - { - vty_out (vty, "debug bgp%s", VTY_NEWLINE); - write++; - } - if (CONF_BGP_DEBUG (as4, AS4)) { vty_out (vty, "debug bgp as4%s", VTY_NEWLINE); @@ -813,12 +1370,6 @@ bgp_config_write_debug (struct vty *vty) write++; } - if (CONF_BGP_DEBUG (events, EVENTS)) - { - vty_out (vty, "debug bgp events%s", VTY_NEWLINE); - write++; - } - if (CONF_BGP_DEBUG (keepalive, KEEPALIVE)) { vty_out (vty, "debug bgp keepalives%s", VTY_NEWLINE); @@ -841,21 +1392,21 @@ bgp_config_write_debug (struct vty *vty) write++; } - if (CONF_BGP_DEBUG (fsm, FSM)) + if (CONF_BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS)) { - vty_out (vty, "debug bgp fsm%s", VTY_NEWLINE); + vty_out (vty, "debug bgp neighbor-events%s", VTY_NEWLINE); write++; } - if (CONF_BGP_DEBUG (filter, FILTER)) + if (CONF_BGP_DEBUG (zebra, ZEBRA)) { - vty_out (vty, "debug bgp filters%s", VTY_NEWLINE); + vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE); write++; } - if (CONF_BGP_DEBUG (zebra, ZEBRA)) + if (CONF_BGP_DEBUG (nht, NHT)) { - vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE); + vty_out (vty, "debug bgp nht%s", VTY_NEWLINE); write++; } @@ -881,51 +1432,189 @@ bgp_debug_init (void) install_element (ENABLE_NODE, &debug_bgp_as4_segment_cmd); install_element (CONFIG_NODE, &debug_bgp_as4_segment_cmd); - install_element (ENABLE_NODE, &debug_bgp_fsm_cmd); - install_element (CONFIG_NODE, &debug_bgp_fsm_cmd); - install_element (ENABLE_NODE, &debug_bgp_events_cmd); - install_element (CONFIG_NODE, &debug_bgp_events_cmd); - install_element (ENABLE_NODE, &debug_bgp_filter_cmd); - install_element (CONFIG_NODE, &debug_bgp_filter_cmd); + install_element (ENABLE_NODE, &debug_bgp_neighbor_events_cmd); + install_element (CONFIG_NODE, &debug_bgp_neighbor_events_cmd); + install_element (ENABLE_NODE, &debug_bgp_nht_cmd); + install_element (CONFIG_NODE, &debug_bgp_nht_cmd); install_element (ENABLE_NODE, &debug_bgp_keepalive_cmd); install_element (CONFIG_NODE, &debug_bgp_keepalive_cmd); install_element (ENABLE_NODE, &debug_bgp_update_cmd); install_element (CONFIG_NODE, &debug_bgp_update_cmd); install_element (ENABLE_NODE, &debug_bgp_update_direct_cmd); install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd); - install_element (ENABLE_NODE, &debug_bgp_normal_cmd); - install_element (CONFIG_NODE, &debug_bgp_normal_cmd); install_element (ENABLE_NODE, &debug_bgp_zebra_cmd); install_element (CONFIG_NODE, &debug_bgp_zebra_cmd); + /* deb bgp updates [in|out] A.B.C.D */ + install_element (ENABLE_NODE, &debug_bgp_update_direct_peer_cmd); + install_element (CONFIG_NODE, &debug_bgp_update_direct_peer_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_update_direct_peer_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_update_direct_peer_cmd); + + /* deb bgp updates prefix A.B.C.D/M */ + install_element (ENABLE_NODE, &debug_bgp_update_prefix_cmd); + install_element (CONFIG_NODE, &debug_bgp_update_prefix_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_update_prefix_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_update_prefix_cmd); + + /* deb bgp zebra prefix A.B.C.D/M */ + install_element (ENABLE_NODE, &debug_bgp_zebra_prefix_cmd); + install_element (CONFIG_NODE, &debug_bgp_zebra_prefix_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_zebra_prefix_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_zebra_prefix_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_as4_cmd); - install_element (ENABLE_NODE, &undebug_bgp_as4_cmd); install_element (CONFIG_NODE, &no_debug_bgp_as4_cmd); install_element (ENABLE_NODE, &no_debug_bgp_as4_segment_cmd); - install_element (ENABLE_NODE, &undebug_bgp_as4_segment_cmd); install_element (CONFIG_NODE, &no_debug_bgp_as4_segment_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd); - install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_fsm_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_events_cmd); - install_element (ENABLE_NODE, &undebug_bgp_events_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_events_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_filter_cmd); - install_element (ENABLE_NODE, &undebug_bgp_filter_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_filter_cmd); + /* deb bgp neighbor-events A.B.C.D */ + install_element (ENABLE_NODE, &debug_bgp_neighbor_events_peer_cmd); + install_element (CONFIG_NODE, &debug_bgp_neighbor_events_peer_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_neighbor_events_peer_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_neighbor_events_peer_cmd); + + /* deb bgp keepalive A.B.C.D */ + install_element (ENABLE_NODE, &debug_bgp_keepalive_peer_cmd); + install_element (CONFIG_NODE, &debug_bgp_keepalive_peer_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_keepalive_peer_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_keepalive_peer_cmd); + + install_element (ENABLE_NODE, &no_debug_bgp_neighbor_events_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_neighbor_events_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_nht_cmd); + install_element (CONFIG_NODE, &no_debug_bgp_nht_cmd); install_element (ENABLE_NODE, &no_debug_bgp_keepalive_cmd); - install_element (ENABLE_NODE, &undebug_bgp_keepalive_cmd); install_element (CONFIG_NODE, &no_debug_bgp_keepalive_cmd); install_element (ENABLE_NODE, &no_debug_bgp_update_cmd); - install_element (ENABLE_NODE, &undebug_bgp_update_cmd); install_element (CONFIG_NODE, &no_debug_bgp_update_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_normal_cmd); - install_element (ENABLE_NODE, &undebug_bgp_normal_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_normal_cmd); install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd); - install_element (ENABLE_NODE, &undebug_bgp_zebra_cmd); install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_all_cmd); - install_element (ENABLE_NODE, &undebug_bgp_all_cmd); + install_element (ENABLE_NODE, &no_debug_bgp_cmd); +} + +/* Return true if this prefix is on the per_prefix_list of prefixes to debug + * for BGP_DEBUG_TYPE + */ +static int +bgp_debug_per_prefix (struct prefix *p, unsigned long term_bgp_debug_type, + unsigned int BGP_DEBUG_TYPE, struct list *per_prefix_list) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + if (term_bgp_debug_type & BGP_DEBUG_TYPE) + { + /* We are debugging all prefixes so return true */ + if (!per_prefix_list || list_isempty(per_prefix_list)) + return 1; + + else + { + if (!p) + return 0; + + for (ALL_LIST_ELEMENTS (per_prefix_list, node, nnode, filter)) + if (filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) + return 1; + + return 0; + } + } + + return 0; +} + +/* Return true if this peer is on the per_peer_list of peers to debug + * for BGP_DEBUG_TYPE + */ +static int +bgp_debug_per_peer(struct peer *peer, unsigned long term_bgp_debug_type, + unsigned int BGP_DEBUG_TYPE, struct list *per_peer_list) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + if (term_bgp_debug_type & BGP_DEBUG_TYPE) + { + /* We are debugging all peers so return true */ + if (!per_peer_list || list_isempty(per_peer_list)) + return 1; + + else + { + if (!peer) + return 0; + + for (ALL_LIST_ELEMENTS (per_peer_list, node, nnode, filter)) + if (filter->peer == peer) + return 1; + + return 0; + } + } + + return 0; +} + +int +bgp_debug_neighbor_events (struct peer *peer) +{ + return bgp_debug_per_peer (peer, + term_bgp_debug_neighbor_events, + BGP_DEBUG_NEIGHBOR_EVENTS, + bgp_debug_neighbor_events_peers); +} + +int +bgp_debug_keepalive (struct peer *peer) +{ + return bgp_debug_per_peer (peer, + term_bgp_debug_keepalive, + BGP_DEBUG_KEEPALIVE, + bgp_debug_keepalive_peers); +} + +int +bgp_debug_update (struct peer *peer, struct prefix *p, unsigned int inbound) +{ + if (inbound) + { + if (bgp_debug_per_peer (peer, term_bgp_debug_update, BGP_DEBUG_UPDATE_IN, + bgp_debug_update_in_peers)) + return 1; + } + + /* outbound */ + else + { + if (bgp_debug_per_peer (peer, term_bgp_debug_update, + BGP_DEBUG_UPDATE_OUT, + bgp_debug_update_out_peers)) + return 1; + } + + + if (BGP_DEBUG (update, UPDATE_PREFIX)) + { + if (bgp_debug_per_prefix (p, term_bgp_debug_update, + BGP_DEBUG_UPDATE_PREFIX, + bgp_debug_update_prefixes)) + return 1; + } + + return 0; +} + +int +bgp_debug_zebra (struct prefix *p) +{ + if (BGP_DEBUG (zebra, ZEBRA)) + { + if (bgp_debug_per_prefix (p, term_bgp_debug_zebra, BGP_DEBUG_ZEBRA, + bgp_debug_zebra_prefixes)) + return 1; + } + + return 0; } diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index ce8547b0..b8ad7b9c 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -59,44 +59,49 @@ extern void bgp_packet_dump (struct stream *); extern int debug (unsigned int option); extern unsigned long conf_bgp_debug_as4; -extern unsigned long conf_bgp_debug_fsm; -extern unsigned long conf_bgp_debug_events; +extern unsigned long conf_bgp_debug_neighbor_events; extern unsigned long conf_bgp_debug_packet; -extern unsigned long conf_bgp_debug_filter; extern unsigned long conf_bgp_debug_keepalive; extern unsigned long conf_bgp_debug_update; -extern unsigned long conf_bgp_debug_normal; extern unsigned long conf_bgp_debug_zebra; +extern unsigned long conf_bgp_debug_nht; extern unsigned long term_bgp_debug_as4; -extern unsigned long term_bgp_debug_fsm; -extern unsigned long term_bgp_debug_events; +extern unsigned long term_bgp_debug_neighbor_events; extern unsigned long term_bgp_debug_packet; -extern unsigned long term_bgp_debug_filter; extern unsigned long term_bgp_debug_keepalive; extern unsigned long term_bgp_debug_update; -extern unsigned long term_bgp_debug_normal; extern unsigned long term_bgp_debug_zebra; +extern unsigned long term_bgp_debug_nht; + +extern struct list *bgp_debug_neighbor_events_peers; +extern struct list *bgp_debug_keepalive_peers; +extern struct list *bgp_debug_update_in_peers; +extern struct list *bgp_debug_update_out_peers; +extern struct list *bgp_debug_update_prefixes; +extern struct list *bgp_debug_zebra_prefixes; + +struct bgp_debug_filter +{ + struct peer *peer; + struct prefix *p; +}; #define BGP_DEBUG_AS4 0x01 #define BGP_DEBUG_AS4_SEGMENT 0x02 -#define BGP_DEBUG_FSM 0x01 -#define BGP_DEBUG_EVENTS 0x01 +#define BGP_DEBUG_NEIGHBOR_EVENTS 0x01 #define BGP_DEBUG_PACKET 0x01 -#define BGP_DEBUG_FILTER 0x01 #define BGP_DEBUG_KEEPALIVE 0x01 #define BGP_DEBUG_UPDATE_IN 0x01 #define BGP_DEBUG_UPDATE_OUT 0x02 -#define BGP_DEBUG_NORMAL 0x01 +#define BGP_DEBUG_UPDATE_PREFIX 0x04 #define BGP_DEBUG_ZEBRA 0x01 +#define BGP_DEBUG_NHT 0x01 #define BGP_DEBUG_PACKET_SEND 0x01 #define BGP_DEBUG_PACKET_SEND_DETAIL 0x02 -#define BGP_DEBUG_PACKET_RECV 0x01 -#define BGP_DEBUG_PACKET_RECV_DETAIL 0x02 - #define CONF_DEBUG_ON(a, b) (conf_bgp_debug_ ## a |= (BGP_DEBUG_ ## b)) #define CONF_DEBUG_OFF(a, b) (conf_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b)) @@ -124,5 +129,9 @@ extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *); extern const struct message bgp_status_msg[]; extern const int bgp_status_msg_max; +extern int bgp_debug_neighbor_events(struct peer *peer); +extern int bgp_debug_keepalive(struct peer *peer); +extern int bgp_debug_update(struct peer *peer, struct prefix *p, unsigned int inbound); +extern int bgp_debug_zebra(struct prefix *p); #endif /* _QUAGGA_BGP_DEBUG_H */ diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 5d69b42c..11b02768 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "prefix.h" #include "command.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_ecommunity.h" diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index 26819fc1..fd282b8e 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -25,6 +25,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "buffer.h" #include "filter.h" +#include "linklist.h" +#include "prefix.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" @@ -48,10 +50,10 @@ struct as_list_master struct as_list_list str; /* Hook function which is executed when new access_list is added. */ - void (*add_hook) (void); + void (*add_hook) (char *); /* Hook function which is executed when access_list is deleted. */ - void (*delete_hook) (void); + void (*delete_hook) (const char *); }; /* Element of AS path filter. */ @@ -145,6 +147,11 @@ as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter) else aslist->head = asfilter; aslist->tail = asfilter; + + /* Run hook function. */ + if (as_list_master.add_hook) + (*as_list_master.add_hook) (aslist->name); + } /* Lookup as_list from list of as_list by name. */ @@ -278,13 +285,7 @@ as_list_get (const char *name) aslist = as_list_lookup (name); if (aslist == NULL) - { - aslist = as_list_insert (name); - - /* Run hook function. */ - if (as_list_master.add_hook) - (*as_list_master.add_hook) (); - } + aslist = as_list_insert (name); return aslist; } @@ -345,6 +346,8 @@ as_list_empty (struct as_list *aslist) static void as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter) { + char *name = strdup (aslist->name); + if (asfilter->next) asfilter->next->prev = asfilter->prev; else @@ -363,7 +366,9 @@ as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter) /* Run hook function. */ if (as_list_master.delete_hook) - (*as_list_master.delete_hook) (); + (*as_list_master.delete_hook) (name); + if (name) + free(name); } static int @@ -396,14 +401,14 @@ as_list_apply (struct as_list *aslist, void *object) /* Add hook function. */ void -as_list_add_hook (void (*func) (void)) +as_list_add_hook (void (*func) (char *)) { as_list_master.add_hook = func; } /* Delete hook function. */ void -as_list_delete_hook (void (*func) (void)) +as_list_delete_hook (void (*func) (const char *)) { as_list_master.delete_hook = func; } @@ -567,7 +572,7 @@ DEFUN (no_ip_as_path_all, /* Run hook function. */ if (as_list_master.delete_hook) - (*as_list_master.delete_hook) (); + (*as_list_master.delete_hook) (argv[0]); return CMD_SUCCESS; } diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h index c1da9041..03447942 100644 --- a/bgpd/bgp_filter.h +++ b/bgpd/bgp_filter.h @@ -33,7 +33,7 @@ extern void bgp_filter_reset (void); extern enum as_filter_type as_list_apply (struct as_list *, void *); extern struct as_list *as_list_lookup (const char *); -extern void as_list_add_hook (void (*func) (void)); -extern void as_list_delete_hook (void (*func) (void)); +extern void as_list_add_hook (void (*func) (char *)); +extern void as_list_delete_hook (void (*func) (const char *)); #endif /* _QUAGGA_BGP_FILTER_H */ diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index c4cfd58e..7dd0b8e2 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -42,6 +42,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_route.h" #include "bgpd/bgp_dump.h" #include "bgpd/bgp_open.h" +#include "bgpd/bgp_advertise.h" +#include "bgpd/bgp_nht.h" #ifdef HAVE_SNMP #include "bgpd/bgp_snmp.h" #endif /* HAVE_SNMP */ @@ -63,11 +65,101 @@ static int bgp_keepalive_timer (struct thread *); /* BGP FSM functions. */ static int bgp_start (struct peer *); -/* BGP start timer jitter. */ -static int -bgp_start_jitter (int time) +static void +peer_xfer_stats (struct peer *peer_dst, struct peer *peer_src) { - return ((random () % (time + 1)) - (time / 2)); + /* Copy stats over. These are only the pre-established state stats */ + peer_dst->open_in += peer_src->open_in; + peer_dst->open_out += peer_src->open_out; + peer_dst->keepalive_in += peer_src->keepalive_in; + peer_dst->keepalive_out += peer_src->keepalive_out; + peer_dst->notify_in += peer_src->notify_in; + peer_dst->notify_out += peer_src->notify_out; + peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in; + peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out; +} + +static struct peer * +peer_xfer_conn(struct peer *from_peer) +{ + struct peer *peer; + afi_t afi; + safi_t safi; + int fd; + int status, pstatus; + + assert(from_peer != NULL); + + peer = from_peer->doppelganger; + + if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + return from_peer; + + BGP_WRITE_OFF(peer->t_write); + BGP_READ_OFF(peer->t_read); + BGP_WRITE_OFF(from_peer->t_write); + BGP_READ_OFF(from_peer->t_read); + + fd = peer->fd; + peer->fd = from_peer->fd; + from_peer->fd = fd; + stream_reset(peer->ibuf); + stream_fifo_clean(peer->obuf); + stream_fifo_clean(from_peer->obuf); + + peer->v_holdtime = from_peer->v_holdtime; + peer->v_keepalive = from_peer->v_keepalive; + peer->routeadv = from_peer->routeadv; + peer->v_routeadv = from_peer->v_routeadv; + peer->v_gr_restart = from_peer->v_gr_restart; + peer->cap = from_peer->cap; + status = peer->status; + pstatus = peer->ostatus; + peer->status = from_peer->status; + peer->ostatus = from_peer->ostatus; + from_peer->status = status; + from_peer->ostatus = pstatus; + peer->remote_id = from_peer->remote_id; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + peer->af_flags[afi][safi] = from_peer->af_flags[afi][safi]; + peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi]; + peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi]; + peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi]; + peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi]; + peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi]; + } + + if (bgp_getsockname(peer) < 0) + { + zlog_err ("%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)", + (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""), + peer->host, peer->fd, from_peer->fd); + bgp_stop(peer); + bgp_stop(from_peer); + return NULL; + } + if (from_peer->status > Active) + { + if (bgp_getsockname(from_peer) < 0) + { + zlog_err ("%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)", + (CHECK_FLAG (from_peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""), + from_peer->host, from_peer->fd, peer->fd); + bgp_stop(from_peer); + from_peer = NULL; + } + } + + BGP_READ_ON(peer->t_read, bgp_read, peer->fd); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); + + if (from_peer) + peer_xfer_stats(peer, from_peer); + + return(peer); } /* Check if suppress start/restart of sessions to peer. */ @@ -81,8 +173,6 @@ bgp_start_jitter (int time) void bgp_timer_set (struct peer *peer) { - int jitter = 0; - switch (peer->status) { case Idle: @@ -95,9 +185,8 @@ bgp_timer_set (struct peer *peer) } else { - jitter = bgp_start_jitter (peer->v_start); BGP_TIMER_ON (peer->t_start, bgp_start_timer, - peer->v_start + jitter); + peer->v_start); } BGP_TIMER_OFF (peer->t_connect); BGP_TIMER_OFF (peer->t_holdtime); @@ -106,7 +195,7 @@ bgp_timer_set (struct peer *peer) break; case Connect: - /* After start timer is expired, the peer moves to Connnect + /* After start timer is expired, the peer moves to Connect status. Make sure start timer is off and connect timer is on. */ BGP_TIMER_OFF (peer->t_start); @@ -205,6 +294,7 @@ bgp_timer_set (struct peer *peer) BGP_TIMER_OFF (peer->t_holdtime); BGP_TIMER_OFF (peer->t_keepalive); BGP_TIMER_OFF (peer->t_routeadv); + break; } } @@ -218,9 +308,8 @@ bgp_start_timer (struct thread *thread) peer = THREAD_ARG (thread); peer->t_start = NULL; - if (BGP_DEBUG (fsm, FSM)) - zlog (peer->log, LOG_DEBUG, - "%s [FSM] Timer (start timer expire).", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (start timer expire).", peer->host); THREAD_VAL (thread) = BGP_Start; bgp_event (thread); /* bgp_event unlocks peer */ @@ -233,18 +322,27 @@ static int bgp_connect_timer (struct thread *thread) { struct peer *peer; + int ret; peer = THREAD_ARG (thread); peer->t_connect = NULL; - if (BGP_DEBUG (fsm, FSM)) - zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)", - peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host); - THREAD_VAL (thread) = ConnectRetry_timer_expired; - bgp_event (thread); /* bgp_event unlocks peer */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) + { + bgp_stop(peer); + ret = -1; + } + else + { + THREAD_VAL (thread) = ConnectRetry_timer_expired; + bgp_event (thread); /* bgp_event unlocks peer */ + ret = 0; + } - return 0; + return ret; } /* BGP holdtime timer. */ @@ -256,10 +354,8 @@ bgp_holdtime_timer (struct thread *thread) peer = THREAD_ARG (thread); peer->t_holdtime = NULL; - if (BGP_DEBUG (fsm, FSM)) - zlog (peer->log, LOG_DEBUG, - "%s [FSM] Timer (holdtime timer expire)", - peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] Timer (holdtime timer expire)", peer->host); THREAD_VAL (thread) = Hold_Timer_expired; bgp_event (thread); /* bgp_event unlocks peer */ @@ -276,10 +372,8 @@ bgp_keepalive_timer (struct thread *thread) peer = THREAD_ARG (thread); peer->t_keepalive = NULL; - if (BGP_DEBUG (fsm, FSM)) - zlog (peer->log, LOG_DEBUG, - "%s [FSM] Timer (keepalive timer expire)", - peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] Timer (keepalive timer expire)", peer->host); THREAD_VAL (thread) = KeepAlive_timer_expired; bgp_event (thread); /* bgp_event unlocks peer */ @@ -288,24 +382,40 @@ bgp_keepalive_timer (struct thread *thread) } static int +bgp_routeq_empty (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++) + { + if (!FIFO_EMPTY(&peer->sync[afi][safi]->withdraw) || + !FIFO_EMPTY(&peer->sync[afi][safi]->update)) + return 0; + } + return 1; +} + +static int bgp_routeadv_timer (struct thread *thread) { struct peer *peer; peer = THREAD_ARG (thread); peer->t_routeadv = NULL; + peer->radv_adjusted = 0; - if (BGP_DEBUG (fsm, FSM)) - zlog (peer->log, LOG_DEBUG, - "%s [FSM] Timer (routeadv timer expire)", - peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] Timer (routeadv timer expire)", peer->host); peer->synctime = bgp_clock (); BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, - peer->v_routeadv); + /* MRAI timer is no longer restarted here, it would be done + * when the FIFO is built. + */ return 0; } @@ -357,7 +467,7 @@ bgp_graceful_restart_timer_expire (struct thread *thread) UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); BGP_TIMER_OFF (peer->t_gr_stale); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) { zlog_debug ("%s graceful restart timer expired", peer->host); zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); @@ -378,7 +488,7 @@ bgp_graceful_stale_timer_expire (struct thread *thread) peer = THREAD_ARG (thread); peer->t_gr_stale = NULL; - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s graceful restart stalepath timer expired", peer->host); /* NSF delete stale route */ @@ -390,11 +500,396 @@ bgp_graceful_stale_timer_expire (struct thread *thread) return 0; } +static int +bgp_update_delay_applicable (struct bgp *bgp) +{ + /* update_delay_over flag should be reset (set to 0) for any new + applicability of the update-delay during BGP process lifetime. + And it should be set after an occurence of the update-delay is over)*/ + if (!bgp->update_delay_over) + return 1; + + return 0; +} + +int +bgp_update_delay_active (struct bgp *bgp) +{ + if (bgp->t_update_delay) + return 1; + + return 0; +} + +int +bgp_update_delay_configured (struct bgp *bgp) +{ + if (bgp->v_update_delay) + return 1; + + return 0; +} + +/* Do the post-processing needed when bgp comes out of the read-only mode + on ending the update delay. */ +void +bgp_update_delay_end (struct bgp *bgp) +{ + THREAD_TIMER_OFF (bgp->t_update_delay); + THREAD_TIMER_OFF (bgp->t_establish_wait); + + /* Reset update-delay related state */ + bgp->update_delay_over = 1; + bgp->established = 0; + bgp->restarted_peers = 0; + bgp->implicit_eors = 0; + bgp->explicit_eors = 0; + + quagga_timestamp(3, bgp->update_delay_end_time, + sizeof(bgp->update_delay_end_time)); + + /* + * Add an end-of-initial-update marker to the main process queues so that + * the route advertisement timer for the peers can be started. Also set + * the zebra and peer update hold flags. These flags are used to achieve + * three stages in the update-delay post processing: + * 1. Finish best-path selection for all the prefixes held on the queues. + * (routes in BGP are updated, and peers sync queues are populated too) + * 2. As the eoiu mark is reached in the bgp process routine, ship all the + * routes to zebra. With that zebra should see updates from BGP close + * to each other. + * 3. Unblock the peer update writes. With that peer update packing with + * the prefixes should be at its maximum. + */ + bgp_add_eoiu_mark(bgp, BGP_TABLE_MAIN); + bgp_add_eoiu_mark(bgp, BGP_TABLE_RSCLIENT); + bgp->main_zebra_update_hold = 1; + bgp->main_peers_update_hold = 1; + bgp->rsclient_peers_update_hold = 1; + + /* Resume the queue processing. This should trigger the event that would take + care of processing any work that was queued during the read-only mode. */ + work_queue_unplug(bm->process_main_queue); + work_queue_unplug(bm->process_rsclient_queue); +} + +/** + * see bgp_fsm.h + */ +void +bgp_start_routeadv (struct bgp *bgp) +{ + struct listnode *node, *nnode; + struct peer *peer; + + zlog_info("bgp_start_routeadv(), update hold status - main: %d, rsclient: %d", + bgp->main_peers_update_hold, bgp->rsclient_peers_update_hold); + + if (bgp->main_peers_update_hold || bgp->rsclient_peers_update_hold) + return; + + quagga_timestamp(3, bgp->update_delay_peers_resume_time, + sizeof(bgp->update_delay_peers_resume_time)); + + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { + if (peer->status != Established) + continue; + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); + } +} + +/** + * see bgp_fsm.h + */ +void +bgp_adjust_routeadv (struct peer *peer) +{ + time_t nowtime = bgp_clock(); + double diff; + unsigned long remain; + + /* Bypass checks for special case of MRAI being 0 */ + if (peer->v_routeadv == 0) + { + /* Stop existing timer, just in case it is running for a different + * duration and schedule write thread immediately. + */ + if (peer->t_routeadv) + BGP_TIMER_OFF(peer->t_routeadv); + + peer->synctime = bgp_clock (); + BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + return; + } + + /* Mark that we've adjusted the timer */ + peer->radv_adjusted = 1; + + + /* + * CASE I: + * If the last update was written more than MRAI back, expire the timer + * instantly so that we can send the update out sooner. + * + * <------- MRAI ---------> + * |-----------------|-----------------------| + * <------------- m ------------> + * ^ ^ ^ + * | | | + * | | current time + * | timer start + * last write + * + * m > MRAI + */ + diff = difftime(nowtime, peer->last_write); + if (diff > (double) peer->v_routeadv) + { + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug ("%s: MRAI timer to expire instantly", peer->host); + return; + } + + /* + * CASE II: + * - Find when to expire the MRAI timer. + * If MRAI timer is not active, assume we can start it now. + * + * <------- MRAI ---------> + * |------------|-----------------------| + * <-------- m ----------><----- r -----> + * ^ ^ ^ + * | | | + * | | current time + * | timer start + * last write + * + * (MRAI - m) < r + */ + if (peer->t_routeadv) + remain = thread_timer_remain_second(peer->t_routeadv); + else + remain = peer->v_routeadv; + diff = peer->v_routeadv - diff; + if (diff <= (double) remain) + { + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff); + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug ("%s: MRAI timer to expire in %f secs", peer->host, diff); + } +} + +static int +bgp_maxmed_onstartup_applicable (struct bgp *bgp) +{ + if (!bgp->maxmed_onstartup_over) + return 1; + + return 0; +} + +int +bgp_maxmed_onstartup_configured (struct bgp *bgp) +{ + if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) + return 1; + + return 0; +} + +int +bgp_maxmed_onstartup_active (struct bgp *bgp) +{ + if (bgp->t_maxmed_onstartup) + return 1; + + return 0; +} + +void +bgp_maxmed_update (struct bgp *bgp) +{ + struct listnode *node, *nnode; + struct peer *peer; + u_char maxmed_active; + u_int32_t maxmed_value; + + if (bgp->v_maxmed_admin) + { + maxmed_active = 1; + maxmed_value = bgp->maxmed_admin_value; + } + else if (bgp->t_maxmed_onstartup) + { + maxmed_active = 1; + maxmed_value = bgp->maxmed_onstartup_value; + } + else + { + maxmed_active = 0; + maxmed_value = BGP_MAXMED_VALUE_DEFAULT; + } + + if (bgp->maxmed_active != maxmed_active || + bgp->maxmed_value != maxmed_value) + { + bgp->maxmed_active = maxmed_active; + bgp->maxmed_value = maxmed_value; + + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + bgp_announce_route_all (peer); + } +} + +/* The maxmed onstartup timer expiry callback. */ +static int +bgp_maxmed_onstartup_timer (struct thread *thread) +{ + struct bgp *bgp; + + zlog_info ("Max med on startup ended - timer expired."); + + bgp = THREAD_ARG (thread); + THREAD_TIMER_OFF (bgp->t_maxmed_onstartup); + bgp->maxmed_onstartup_over = 1; + + bgp_maxmed_update(bgp); + + return 0; +} + +static void +bgp_maxmed_onstartup_begin (struct bgp *bgp) +{ + /* Applicable only once in the process lifetime on the startup */ + if (bgp->maxmed_onstartup_over) + return; + + zlog_info ("Begin maxmed onstartup mode - timer %d seconds", + bgp->v_maxmed_onstartup); + + THREAD_TIMER_ON (bm->master, bgp->t_maxmed_onstartup, + bgp_maxmed_onstartup_timer, + bgp, bgp->v_maxmed_onstartup); + + if (!bgp->v_maxmed_admin) + { + bgp->maxmed_active = 1; + bgp->maxmed_value = bgp->maxmed_onstartup_value; + } + + /* Route announce to all peers should happen after this in bgp_establish() */ +} + +static void +bgp_maxmed_onstartup_process_status_change(struct peer *peer) +{ + if (peer->status == Established && !peer->bgp->established) + { + bgp_maxmed_onstartup_begin(peer->bgp); + } +} + +/* The update delay timer expiry callback. */ +static int +bgp_update_delay_timer (struct thread *thread) +{ + struct bgp *bgp; + + zlog_info ("Update delay ended - timer expired."); + + bgp = THREAD_ARG (thread); + THREAD_TIMER_OFF (bgp->t_update_delay); + bgp_update_delay_end(bgp); + + return 0; +} + +/* The establish wait timer expiry callback. */ +static int +bgp_establish_wait_timer (struct thread *thread) +{ + struct bgp *bgp; + + zlog_info ("Establish wait - timer expired."); + + bgp = THREAD_ARG (thread); + THREAD_TIMER_OFF (bgp->t_establish_wait); + bgp_check_update_delay(bgp); + + return 0; +} + +/* Steps to begin the update delay: + - initialize queues if needed + - stop the queue processing + - start the timer */ +static void +bgp_update_delay_begin (struct bgp *bgp) +{ + struct listnode *node, *nnode; + struct peer *peer; + + if ((bm->process_main_queue == NULL) || + (bm->process_rsclient_queue == NULL)) + bgp_process_queue_init(); + + /* Stop the processing of queued work. Enqueue shall continue */ + work_queue_plug(bm->process_main_queue); + work_queue_plug(bm->process_rsclient_queue); + + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + peer->update_delay_over = 0; + + /* Start the update-delay timer */ + THREAD_TIMER_ON (bm->master, bgp->t_update_delay, bgp_update_delay_timer, + bgp, bgp->v_update_delay); + + if (bgp->v_establish_wait != bgp->v_update_delay) + THREAD_TIMER_ON (bm->master, bgp->t_establish_wait, bgp_establish_wait_timer, + bgp, bgp->v_establish_wait); + + quagga_timestamp(3, bgp->update_delay_begin_time, + sizeof(bgp->update_delay_begin_time)); +} + +static void +bgp_update_delay_process_status_change(struct peer *peer) +{ + if (peer->status == Established) + { + if (!peer->bgp->established++) + { + bgp_update_delay_begin(peer->bgp); + zlog_info ("Begin read-only mode - update-delay timer %d seconds", + peer->bgp->v_update_delay); + } + if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV)) + bgp_update_restarted_peers(peer); + } + if (peer->ostatus == Established && bgp_update_delay_active(peer->bgp)) + { + /* Adjust the update-delay state to account for this flap. + NOTE: Intentionally skipping adjusting implicit_eors or explicit_eors + counters. Extra sanity check in bgp_check_update_delay() should + be enough to take care of any additive discrepancy in bgp eor + counters */ + peer->bgp->established--; + peer->update_delay_over = 0; + } +} + /* Called after event occured, this function change status and reset read/write and timer thread. */ void bgp_fsm_change_status (struct peer *peer, int status) { + bgp_dump_state (peer, peer->status, status); /* Transition into Clearing or Deleted must /always/ clear all routes.. @@ -422,8 +917,26 @@ bgp_fsm_change_status (struct peer *peer, int status) /* Preserve old status and change into new status. */ peer->ostatus = peer->status; peer->status = status; - - if (BGP_DEBUG (normal, NORMAL)) + + if (status == Established) + UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); + + /* If max-med processing is applicable, do the necessary. */ + if (status == Established) + { + if (bgp_maxmed_onstartup_configured(peer->bgp) && + bgp_maxmed_onstartup_applicable(peer->bgp)) + bgp_maxmed_onstartup_process_status_change(peer); + else + peer->bgp->maxmed_onstartup_over = 1; + } + + /* If update-delay processing is applicable, do the necessary. */ + if (bgp_update_delay_configured(peer->bgp) && + bgp_update_delay_applicable(peer->bgp)) + bgp_update_delay_process_status_change(peer); + + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s went from %s to %s", peer->host, LOOKUP (bgp_status_msg, peer->ostatus), @@ -435,7 +948,9 @@ static int bgp_clearing_completed (struct peer *peer) { int rc = bgp_stop(peer); - BGP_EVENT_FLUSH (peer); + + if (rc >= 0) + BGP_EVENT_FLUSH (peer); return rc; } @@ -448,6 +963,7 @@ bgp_stop (struct peer *peer) afi_t afi; safi_t safi; char orf_name[BUFSIZ]; + int ret = 0; /* Can't do this in Clearing; events are used for state transitions */ if (peer->status != Clearing) @@ -470,12 +986,12 @@ bgp_stop (struct peer *peer) if (peer->t_gr_stale) { BGP_TIMER_OFF (peer->t_gr_stale); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); } if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) { - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) { zlog_debug ("%s graceful restart timer started for %d sec", peer->host, peer->v_gr_restart); @@ -553,9 +1069,11 @@ bgp_stop (struct peer *peer) /* Received ORF prefix-filter */ peer->orf_plist[afi][safi] = NULL; - /* ORF received prefix-filter pnt */ - sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); - prefix_bgp_orf_remove_all (afi, orf_name); + if ((peer->status == OpenConfirm) || (peer->status == Established)) { + /* ORF received prefix-filter pnt */ + sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); + prefix_bgp_orf_remove_all (afi, orf_name); + } } /* Reset keepalive and holdtime */ @@ -583,7 +1101,18 @@ bgp_stop (struct peer *peer) peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0; #endif /* 0 */ - return 0; + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) && + !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) + { + peer_delete(peer); + ret = -1; + } + else + { + bgp_peer_conf_if_to_su_update(peer); + } + + return ret; } /* BGP peer is stoped by the error. */ @@ -597,9 +1126,7 @@ bgp_stop_with_error (struct peer *peer) if (peer->v_start >= (60 * 2)) peer->v_start = (60 * 2); - bgp_stop (peer); - - return 0; + return(bgp_stop (peer)); } @@ -610,21 +1137,10 @@ bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code) /* Send notify to remote peer */ bgp_notify_send (peer, code, sub_code); - /* Sweep if it is temporary peer. */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host); - peer_delete (peer); - return -1; - } - /* Clear start timer value to default. */ peer->v_start = BGP_INIT_START_TIMER; - /* bgp_stop needs to be invoked while in Established state */ - bgp_stop(peer); - - return 0; + return(bgp_stop(peer)); } @@ -637,14 +1153,21 @@ bgp_connect_success (struct peer *peer) { zlog_err ("bgp_connect_success peer's fd is negative value %d", peer->fd); + bgp_stop(peer); return -1; } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - bgp_getsockname (peer); + if (bgp_getsockname (peer) < 0) + { + zlog_err ("%s: bgp_getsockname(): failed for peer %s", __FUNCTION__, + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0); /* internal error */ + return -1; + } - if (BGP_DEBUG (normal, NORMAL)) + BGP_READ_ON (peer->t_read, bgp_read, peer->fd); + + if (bgp_debug_neighbor_events(peer)) { char buf1[SU_ADDRSTRLEN]; @@ -655,8 +1178,7 @@ bgp_connect_success (struct peer *peer) zlog_debug ("%s passive open", peer->host); } - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - bgp_open_send (peer); + bgp_open_send (peer); return 0; } @@ -665,8 +1187,7 @@ bgp_connect_success (struct peer *peer) static int bgp_connect_fail (struct peer *peer) { - bgp_stop (peer); - return 0; + return (bgp_stop (peer)); } /* This function is the first starting point of all BGP connection. It @@ -675,11 +1196,14 @@ int bgp_start (struct peer *peer) { int status; + int connected = 0; + + bgp_peer_conf_if_to_su_update(peer); if (BGP_PEER_START_SUPPRESSED (peer)) { - if (BGP_DEBUG (fsm, FSM)) - plog_err (peer->log, "%s [FSM] Trying to start suppressed peer" + if (bgp_debug_neighbor_events(peer)) + zlog_err ("%s [FSM] Trying to start suppressed peer" " - this is never supposed to happen!", peer->host); return -1; } @@ -713,26 +1237,32 @@ bgp_start (struct peer *peer) return 0; } + /* Register to be notified on peer up */ + if ((peer->ttl == 1) || (peer->gtsm_hops == 1)) + connected = 1; + + bgp_find_or_add_nexthop(family2afi(peer->su.sa.sa_family), NULL, peer, + connected); status = bgp_connect (peer); switch (status) { case connect_error: - if (BGP_DEBUG (fsm, FSM)) - plog_debug (peer->log, "%s [FSM] Connect error", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] Connect error", peer->host); BGP_EVENT_ADD (peer, TCP_connection_open_failed); break; case connect_success: - if (BGP_DEBUG (fsm, FSM)) - plog_debug (peer->log, "%s [FSM] Connect immediately success", + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] Connect immediately success", peer->host); BGP_EVENT_ADD (peer, TCP_connection_open); break; case connect_in_progress: /* To check nonblocking connect, we wait until socket is readable or writable. */ - if (BGP_DEBUG (fsm, FSM)) - plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result", + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] Non blocking connect waiting result", peer->host); if (peer->fd < 0) { @@ -751,9 +1281,14 @@ bgp_start (struct peer *peer) static int bgp_reconnect (struct peer *peer) { - bgp_stop (peer); - bgp_start (peer); - return 0; + int ret = 0; + + if (bgp_stop (peer) > 0) + bgp_start (peer); + else + ret = -1; + + return ret; } static int @@ -772,6 +1307,13 @@ bgp_fsm_open (struct peer *peer) static int bgp_fsm_keepalive_expire (struct peer *peer) { + /* + * If there are UPDATE messages to send, no need to send keepalive. The + * peer will note our progress through the UPDATEs. + */ + if (!bgp_routeq_empty(peer)) + return 0; + bgp_keepalive_send (peer); return 0; } @@ -781,7 +1323,7 @@ bgp_fsm_keepalive_expire (struct peer *peer) static int bgp_fsm_event_error (struct peer *peer) { - plog_err (peer->log, "%s [FSM] unexpected packet received in state %s", + zlog_err ("%s [FSM] unexpected packet received in state %s", peer->host, LOOKUP (bgp_status_msg, peer->status)); return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0); @@ -792,8 +1334,8 @@ bgp_fsm_event_error (struct peer *peer) static int bgp_fsm_holdtime_expire (struct peer *peer) { - if (BGP_DEBUG (fsm, FSM)) - plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] Hold timer expire", peer->host); return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0); } @@ -807,6 +1349,19 @@ bgp_establish (struct peer *peer) afi_t afi; safi_t safi; int nsf_af_count = 0; + int ret = 0; + struct peer *other; + + other = peer->doppelganger; + peer = peer_xfer_conn(peer); + if (!peer) + { + zlog_err ("%%Neighbor failed in xfer_conn"); + return -1; + } + + if (other == peer) + ret = 1; /* bgp_establish specific code when xfer_conn happens. */ /* Reset capability open status flag. */ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)) @@ -861,7 +1416,7 @@ bgp_establish (struct peer *peer) if (peer->t_gr_stale) { BGP_TIMER_OFF (peer->t_gr_stale); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); } } @@ -869,7 +1424,7 @@ bgp_establish (struct peer *peer) if (peer->t_gr_restart) { BGP_TIMER_OFF (peer->t_gr_restart); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s graceful restart timer stopped", peer->host); } @@ -893,9 +1448,6 @@ bgp_establish (struct peer *peer) REFRESH_IMMEDIATE, 0); } - if (peer->v_keepalive) - bgp_keepalive_send (peer); - /* First update is deferred until ORF or ROUTE-REFRESH is received */ for (afi = AFI_IP ; afi < AFI_MAX ; afi++) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) @@ -906,15 +1458,34 @@ bgp_establish (struct peer *peer) bgp_announce_route_all (peer); - BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1); + /* Start the route advertisement timer to send updates to the peer - if BGP + * is not in read-only mode. If it is, the timer will be started at the end + * of read-only mode. + */ + if (!bgp_update_delay_active(peer->bgp)) + BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 0); - return 0; + if (peer->doppelganger && (peer->doppelganger->status != Deleted)) + { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("[Event] Deleting stub connection for peer %s", peer->host); + + if (peer->doppelganger->status > Active) + bgp_notify_send (peer->doppelganger, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + else + peer_delete(peer->doppelganger); + } + + return ret; } /* Keepalive packet is received. */ static int bgp_fsm_keepalive (struct peer *peer) { + bgp_update_implicit_eors(peer); + /* peer count update */ peer->keepalive_in++; @@ -934,11 +1505,50 @@ bgp_fsm_update (struct peer *peer) static int bgp_ignore (struct peer *peer) { - if (BGP_DEBUG (fsm, FSM)) - zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [FSM] bgp_ignore called", peer->host); return 0; } +void +bgp_fsm_nht_update(struct peer *peer, int valid) +{ + int ret = 0; + + if (!peer) + return; + + switch (peer->status) + { + case Idle: + if (valid) + BGP_EVENT_ADD(peer, BGP_Start); + break; + case Connect: + ret = bgp_connect_check(peer, 0); + if (!ret && valid) + { + BGP_TIMER_OFF(peer->t_connect); + BGP_EVENT_ADD(peer, ConnectRetry_timer_expired); + } + break; + case Active: + if (valid) + { + BGP_TIMER_OFF(peer->t_connect); + BGP_EVENT_ADD(peer, ConnectRetry_timer_expired); + } + case OpenSent: + case OpenConfirm: + case Established: + case Clearing: + case Deleted: + default: + break; + } +} + + /* Finite State Machine structure */ static const struct { int (*func) (struct peer *); @@ -1108,19 +1718,34 @@ static const char *bgp_event_str[] = int bgp_event (struct thread *thread) { - int ret = 0; int event; - int next; struct peer *peer; + int ret; peer = THREAD_ARG (thread); event = THREAD_VAL (thread); + ret = bgp_event_update(peer, event); + + return (ret); +} + +int +bgp_event_update (struct peer *peer, int event) +{ + int next; + int ret = 0; + struct peer *other; + int passive_conn = 0; + + other = peer->doppelganger; + passive_conn = (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0; + /* Logging this event. */ next = FSM [peer->status -1][event - 1].next_state; - if (BGP_DEBUG (fsm, FSM) && peer->status != next) - plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host, + if (bgp_debug_neighbor_events(peer) && peer->status != next) + zlog_debug ("%s [FSM] %s (%s->%s)", peer->host, bgp_event_str[event], LOOKUP (bgp_status_msg, peer->status), LOOKUP (bgp_status_msg, next)); @@ -1132,13 +1757,28 @@ bgp_event (struct thread *thread) /* When function do not want proceed next job return -1. */ if (ret >= 0) { + if (ret == 1 && next == Established) + { + /* The case when doppelganger swap accurred in bgp_establish. + Update the peer pointer accordingly */ + peer = other; + } + /* If status is changed. */ if (next != peer->status) bgp_fsm_change_status (peer, next); /* Make sure timer is set. */ bgp_timer_set (peer); + + } + else if (!passive_conn && peer->bgp) + { + /* If we got a return value of -1, that means there was an error, restart + * the FSM. If the peer structure was deleted + */ + bgp_fsm_change_status(peer, Idle); + bgp_timer_set(peer); } - return ret; } diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index 752d6e2b..89077857 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -71,11 +71,35 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA thread_cancel_event (bm->master, (P)); \ } while (0) +#define BGP_MSEC_JITTER 10 + /* Prototypes. */ +extern void bgp_fsm_nht_update(struct peer *, int valid); extern int bgp_event (struct thread *); +extern int bgp_event_update (struct peer *, int event); extern int bgp_stop (struct peer *peer); extern void bgp_timer_set (struct peer *); extern void bgp_fsm_change_status (struct peer *peer, int status); extern const char *peer_down_str[]; +extern void bgp_update_delay_end (struct bgp *); +extern void bgp_maxmed_update (struct bgp *); +extern int bgp_maxmed_onstartup_configured (struct bgp *); +extern int bgp_maxmed_onstartup_active (struct bgp *); + +/** + * Start the route advertisement timer (that honors MRAI) for all the + * peers. Typically called at the end of initial convergence, coming + * out of read-only mode. + */ +extern void bgp_start_routeadv (struct bgp *); + +/** + * See if the route advertisement timer needs to be adjusted for a + * peer. For example, if the last update was written to the peer a + * long while back, we don't need to wait for the periodic advertisement + * timer to expire to send the new set of prefixes. It should fire + * instantly and updates should go out sooner. + */ +extern void bgp_adjust_routeadv (struct peer *); #endif /* _QUAGGA_BGP_FSM_H */ diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 11c73cea..2f157652 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "stream.h" #include "vrf.h" #include "workqueue.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr.h" @@ -51,6 +52,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_debug.h" #include "bgpd/bgp_filter.h" #include "bgpd/bgp_zebra.h" +#include "bgpd/bgp_network.h" /* bgpd options, we use GNU getopt library. */ static const struct option longopts[] = @@ -175,7 +177,7 @@ Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS); void sighup (void) { - zlog (NULL, LOG_INFO, "SIGHUP received"); + zlog_info ("SIGHUP received"); /* Terminate all thread. */ bgp_terminate (); @@ -225,13 +227,13 @@ bgp_exit (int status) { struct bgp *bgp; struct listnode *node, *nnode; - int *socket; struct interface *ifp; - extern struct zclient *zlookup; /* it only makes sense for this to be called on a clean exit */ assert (status == 0); + bgp_close(); + /* reverse bgp_master_init */ for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) bgp_delete (bgp); @@ -256,14 +258,6 @@ bgp_exit (int status) work_queue_free (bm->process_rsclient_queue); bm->process_rsclient_queue = NULL; } - - /* reverse bgp_master_init */ - for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket)) - { - if (close ((int)(long)socket) == -1) - zlog_err ("close (%d): %s", (int)(long)socket, safe_strerror (errno)); - } - list_delete (bm->listen_sockets); /* reverse bgp_zebra_init/if_init */ if (retain_mode) @@ -286,11 +280,8 @@ bgp_exit (int status) /* reverse bgp_route_init */ bgp_route_finish (); - /* reverse bgp_route_map_init/route_map_init */ - route_map_finish (); - - /* reverse bgp_scan_init */ - bgp_scan_finish (); + /* cleanup route maps */ + bgp_route_map_terminate(); /* reverse access_list_init */ access_list_add_hook (NULL); @@ -316,10 +307,13 @@ bgp_exit (int status) bgp_address_destroy(); bgp_scan_destroy(); bgp_zebra_destroy(); - if (zlookup) - zclient_free (zlookup); if (bgp_nexthop_buf) stream_free (bgp_nexthop_buf); + if (bgp_ifindices_buf) + stream_free (bgp_ifindices_buf); + + /* reverse bgp_scan_init */ + bgp_scan_finish (); /* reverse bgp_master_init */ if (bm->master) @@ -328,9 +322,6 @@ bgp_exit (int status) if (zlog_default) closezlog (zlog_default); - if (CONF_BGP_DEBUG (normal, NORMAL)) - log_memstats_stderr ("bgpd"); - exit (status); } diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 8e78aafe..3d17ec85 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -74,7 +74,7 @@ bgp_mpath_is_configured (struct bgp *bgp, afi_t afi, safi_t safi) */ int bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi, - int peertype, u_int16_t maxpaths) + int peertype, u_int16_t maxpaths, u_int16_t options) { if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX)) return -1; @@ -83,6 +83,7 @@ bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi, { case BGP_PEER_IBGP: bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths; + bgp->maxpaths[afi][safi].ibgp_flags |= options; break; case BGP_PEER_EBGP: bgp->maxpaths[afi][safi].maxpaths_ebgp = maxpaths; @@ -110,6 +111,7 @@ bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi, { case BGP_PEER_IBGP: bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS; + bgp->maxpaths[afi][safi].ibgp_flags = 0; break; case BGP_PEER_EBGP: bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS; @@ -139,26 +141,45 @@ bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2) compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop); - if (!compare && ae1 && ae2 && (ae1->mp_nexthop_len == ae2->mp_nexthop_len)) + if (!compare && ae1 && ae2) { - switch (ae1->mp_nexthop_len) + if (ae1->mp_nexthop_len == ae2->mp_nexthop_len) + { + switch (ae1->mp_nexthop_len) + { + case 4: + case 12: + compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in, + &ae2->mp_nexthop_global_in); + break; + case 16: + compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, + &ae2->mp_nexthop_global); + break; + case 32: + compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, + &ae2->mp_nexthop_global); + if (!compare) + compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local, + &ae2->mp_nexthop_local); + break; + } + } + + /* This can happen if one IPv6 peer sends you global and link-local + * nexthops but another IPv6 peer only sends you global + */ + else if (ae1->mp_nexthop_len == 16 || ae1->mp_nexthop_len == 32) { - case 4: - case 12: - compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in, - &ae2->mp_nexthop_global_in); - break; - case 16: - compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, - &ae2->mp_nexthop_global); - break; - case 32: compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global); if (!compare) - compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local, - &ae2->mp_nexthop_local); - break; + { + if (ae1->mp_nexthop_len < ae2->mp_nexthop_len) + compare = -1; + else + compare = 1; + } } } @@ -427,7 +448,7 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, struct listnode *mp_node, *mp_next_node; struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; int mpath_changed, debug; - char pfx_buf[INET_ADDRSTRLEN], nh_buf[2][INET_ADDRSTRLEN]; + char pfx_buf[INET6_ADDRSTRLEN], nh_buf[2][INET6_ADDRSTRLEN]; struct bgp_maxpaths_cfg *mpath_cfg = NULL; mpath_changed = 0; @@ -437,8 +458,7 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, old_mpath_count = 0; prev_mpath = new_best; mp_node = listhead (mp_list); - - debug = BGP_DEBUG (events, EVENTS); + debug = bgp_debug_update(NULL, &rn->p, 1) || bgp_debug_update(NULL, &rn->p, 0); if (debug) prefix2str (&rn->p, pfx_buf, sizeof (pfx_buf)); diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h index 2a84d5e1..83db8264 100644 --- a/bgpd/bgp_mpath.h +++ b/bgpd/bgp_mpath.h @@ -24,6 +24,9 @@ #ifndef _QUAGGA_BGP_MPATH_H #define _QUAGGA_BGP_MPATH_H +/* Limit on number of configured maxpaths */ +#define BGP_MAXIMUM_MAXPATHS 255 + /* BGP default maximum-paths */ #define BGP_DEFAULT_MAXPATHS 1 @@ -49,7 +52,8 @@ struct bgp_info_mpath }; /* Functions to support maximum-paths configuration */ -extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t); +extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t, + u_int16_t); extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int); bool bgp_mpath_is_configured_sort (struct bgp *, bgp_peer_sort_t, afi_t, safi_t); bool bgp_mpath_is_configured (struct bgp *, afi_t, safi_t); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 08a4272d..4a8f5eaa 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "memory.h" #include "stream.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -133,16 +134,14 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, /* sanity check against packet data */ if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8) { - plog_err (peer->log, - "%s [Error] Update packet error / VPNv4" - " (prefix length %d less than VPNv4 min length)", + zlog_err ("%s [Error] Update packet error / VPNv4" + " (prefix length %d less than VPNv4 min length)", peer->host, prefixlen); return -1; } if ((pnt + psize) > lim) { - plog_err (peer->log, - "%s [Error] Update packet error / VPNv4" + zlog_err ("%s [Error] Update packet error / VPNv4" " (psize %u exceeds packet size (%u)", peer->host, prefixlen, (uint)(lim-pnt)); @@ -152,8 +151,7 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, /* sanity check against storage for the IP address portion */ if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t) sizeof(p.u)) { - plog_err (peer->log, - "%s [Error] Update packet error / VPNv4" + zlog_err ("%s [Error] Update packet error / VPNv4" " (psize %u exceeds storage size (%zu)", peer->host, prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u)); @@ -163,8 +161,7 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, /* Sanity check against max bitlen of the address family */ if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen (&p)) { - plog_err (peer->log, - "%s [Error] Update packet error / VPNv4" + zlog_err ("%s [Error] Update packet error / VPNv4" " (psize %u exceeds family (%u) max byte len %u)", peer->host, prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, @@ -214,8 +211,7 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, /* Packet length consistency check. */ if (pnt != lim) { - plog_err (peer->log, - "%s [Error] Update packet error / VPNv4" + zlog_err ("%s [Error] Update packet error / VPNv4" " (%zu data remaining after parsing)", peer->host, lim - pnt); return -1; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 51a6f602..283fa344 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -34,6 +34,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "filter.h" #include "bgpd/bgpd.h" +#include "bgpd/bgp_open.h" #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_debug.h" @@ -67,8 +68,7 @@ bgp_md5_set_socket (int socket, union sockunion *su, const char *password) #endif /* HAVE_TCP_MD5SIG */ if (ret < 0) - zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s", - socket, safe_strerror (en)); + zlog_warn ("can't set TCP_MD5SIG option on socket %d: %s", socket, safe_strerror (en)); return ret; } @@ -150,7 +150,7 @@ static void bgp_set_socket_ttl (struct peer *peer, int bgp_sock) { char buf[INET_ADDRSTRLEN]; - int ret; + int ret = 0; /* In case of peer is EBGP, we should set TTL for this connection. */ if (!peer->gtsm_hops && (peer_sort (peer) == BGP_PEER_EBGP)) @@ -222,50 +222,90 @@ bgp_accept (struct thread *thread) /* Set socket send buffer size */ bgp_update_sock_send_buffer_size(bgp_sock); - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf)); - /* Check remote IP address */ peer1 = peer_lookup (NULL, &su); - if (! peer1 || peer1->status == Idle) + if (! peer1) { - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(NULL)) { - if (! peer1) - zlog_debug ("[Event] BGP connection IP address %s is not configured", - inet_sutop (&su, buf)); - else - zlog_debug ("[Event] BGP connection IP address %s is Idle state", - inet_sutop (&su, buf)); + zlog_debug ("[Event] BGP connection IP address %s is not configured", + inet_sutop (&su, buf)); } close (bgp_sock); return -1; } + if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) + { + if (bgp_debug_neighbor_events(peer1)) + zlog_debug ("[Event] connection from %s rejected due to admin shutdown", + inet_sutop (&su, buf)); + close (bgp_sock); + return -1; + } + + /* + * Do not accept incoming connections in Clearing state. This can result + * in incorect state transitions - e.g., the connection goes back to + * Established and then the Clearing_Completed event is generated. Also, + * block incoming connection in Deleted state. + */ + if (peer1->status == Clearing || peer1->status == Deleted) + { + if (bgp_debug_neighbor_events(peer1)) + zlog_debug("[Event] Closing incoming conn for %s (%p) state %d", + peer1->host, peer1, peer1->status); + close (bgp_sock); + return -1; + } + + if (bgp_debug_neighbor_events(peer1)) + zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf)); + + if (peer1->doppelganger) + { + /* We have an existing connection. Kill the existing one and run + with this one. + */ + if (bgp_debug_neighbor_events(peer1)) + zlog_debug ("[Event] New active connection from peer %s, Killing" + " previous active connection", peer1->host); + peer_delete(peer1->doppelganger); + } + bgp_set_socket_ttl (peer1, bgp_sock); - /* Make dummy peer until read Open packet. */ - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("[Event] Make dummy peer structure until read Open packet"); + peer = peer_create (&su, peer1->conf_if, peer1->bgp, peer1->local_as, + peer1->as, 0, 0); - { - char buf[SU_ADDRSTRLEN]; + peer_xfer_config(peer, peer1); + UNSET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); - peer = peer_create_accept (peer1->bgp); - SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); - peer->su = su; - peer->fd = bgp_sock; - peer->status = Active; - peer->local_id = peer1->local_id; - peer->v_holdtime = peer1->v_holdtime; - peer->v_keepalive = peer1->v_keepalive; + peer->doppelganger = peer1; + peer1->doppelganger = peer; + peer->fd = bgp_sock; + bgp_fsm_change_status(peer, Active); + BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */ - /* Make peer's address string. */ - sockunion2str (&su, buf, SU_ADDRSTRLEN); - peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); - } + SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); - BGP_EVENT_ADD (peer, TCP_connection_open); + /* Make dummy peer until read Open packet. */ + if (peer1->status == Established && + CHECK_FLAG (peer1->sflags, PEER_STATUS_NSF_MODE)) + { + /* If we have an existing established connection with graceful restart + * capability announced with one or more address families, then drop + * existing established connection and move state to connect. + */ + peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; + SET_FLAG (peer1->sflags, PEER_STATUS_NSF_WAIT); + bgp_event_update(peer1, TCP_connection_closed); + } + + if (peer_active (peer)) + { + BGP_EVENT_ADD (peer, TCP_connection_open); + } return 0; } @@ -278,11 +318,14 @@ bgp_bind (struct peer *peer) int ret; struct ifreq ifreq; int myerrno; + char *name; - if (! peer->ifname) + if (! peer->ifname && !peer->conf_if) return 0; - strncpy ((char *)&ifreq.ifr_name, peer->ifname, sizeof (ifreq.ifr_name)); + name = (peer->conf_if ? peer->conf_if : peer->ifname); + + strncpy ((char *)&ifreq.ifr_name, name, sizeof (ifreq.ifr_name)); if ( bgpd_privs.change (ZPRIVS_RAISE) ) zlog_err ("bgp_bind: could not raise privs"); @@ -296,8 +339,8 @@ bgp_bind (struct peer *peer) if (ret < 0) { - zlog (peer->log, LOG_INFO, "bind to interface %s failed, errno=%d", - peer->ifname, myerrno); + zlog_info ("bind to interface %s failed, errno=%d", + name, myerrno); return ret; } #endif /* SO_BINDTODEVICE */ @@ -367,6 +410,11 @@ bgp_connect (struct peer *peer) { ifindex_t ifindex = 0; + if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) + { + zlog_debug("Peer address not learnt: Returning from connect"); + return 0; + } /* Make socket for the peer. */ peer->fd = sockunion_socket (&peer->su); if (peer->fd < 0) @@ -402,19 +450,19 @@ bgp_connect (struct peer *peer) /* Update source bind. */ bgp_update_source (peer); - if (peer->ifname) - ifindex = ifname2ifindex (peer->ifname); + if (peer->conf_if || peer->ifname) + ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname); - if (BGP_DEBUG (events, EVENTS)) - plog_debug (peer->log, "%s [Event] Connect start to %s fd %d", - peer->host, peer->host, peer->fd); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [Event] Connect start to %s fd %d", + peer->host, peer->host, peer->fd); /* Connect to the remote peer. */ return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex); } /* After TCP connection is established. Get local address and port. */ -void +int bgp_getsockname (struct peer *peer) { if (peer->su_local) @@ -430,9 +478,13 @@ bgp_getsockname (struct peer *peer) } peer->su_local = sockunion_getsockname (peer->fd); + if (!peer->su_local) return -1; peer->su_remote = sockunion_getpeername (peer->fd); + if (!peer->su_remote) return -1; bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer); + + return 0; } @@ -548,6 +600,9 @@ bgp_close (void) struct listnode *node, *next; struct bgp_listener *listener; + if (bm->listen_sockets == NULL) + return; + for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener)) { thread_cancel (listener->thread); diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h index 12768430..403393e8 100644 --- a/bgpd/bgp_network.h +++ b/bgpd/bgp_network.h @@ -26,7 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA extern int bgp_socket (unsigned short, const char *); extern void bgp_close (void); extern int bgp_connect (struct peer *); -extern void bgp_getsockname (struct peer *); +extern int bgp_getsockname (struct peer *); extern int bgp_md5_set (struct peer *); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 24068141..4be27b47 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -31,59 +31,35 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "hash.h" #include "jhash.h" #include "filter.h" +#include "nexthop.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_nexthop.h" +#include "bgpd/bgp_nht.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_damp.h" #include "zebra/rib.h" #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */ -struct bgp_nexthop_cache *zlookup_query (struct in_addr); -struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *); - -/* Only one BGP scan thread are activated at the same time. */ -static struct thread *bgp_scan_thread = NULL; - -/* BGP import thread */ -static struct thread *bgp_import_thread = NULL; - -/* BGP scan interval. */ -static int bgp_scan_interval; - -/* BGP import interval. */ -static int bgp_import_interval; /* Route table for next-hop lookup cache. */ -static struct bgp_table *bgp_nexthop_cache_table[AFI_MAX]; +struct bgp_table *bgp_nexthop_cache_table[AFI_MAX]; static struct bgp_table *cache1_table[AFI_MAX]; -static struct bgp_table *cache2_table[AFI_MAX]; /* Route table for connected route. */ static struct bgp_table *bgp_connected_table[AFI_MAX]; -/* BGP nexthop lookup query client. */ -struct zclient *zlookup = NULL; - -/* Add nexthop to the end of the list. */ -static void -bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop) +char * +bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size) { - struct nexthop *last; - - for (last = bnc->nexthop; last && last->next; last = last->next) - ; - if (last) - last->next = nexthop; - else - bnc->nexthop = nexthop; - nexthop->prev = last; + prefix2str(&(bnc->node->p), buf, size); + return buf; } -static void +void bnc_nexthop_free (struct bgp_nexthop_cache *bnc) { struct nexthop *nexthop; @@ -96,93 +72,29 @@ bnc_nexthop_free (struct bgp_nexthop_cache *bnc) } } -static struct bgp_nexthop_cache * +struct bgp_nexthop_cache * bnc_new (void) { - return XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache)); + struct bgp_nexthop_cache *bnc; + + bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache)); + LIST_INIT(&(bnc->paths)); + return bnc; } -static void +void bnc_free (struct bgp_nexthop_cache *bnc) { bnc_nexthop_free (bnc); XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc); } -static int -bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2) -{ - if (next1->type != next2->type) - return 0; - - switch (next1->type) - { - case ZEBRA_NEXTHOP_IPV4: - if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)) - return 0; - break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: - if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4) - || next1->ifindex != next2->ifindex) - return 0; - break; - case ZEBRA_NEXTHOP_IFINDEX: - case ZEBRA_NEXTHOP_IFNAME: - if (next1->ifindex != next2->ifindex) - return 0; - break; - case ZEBRA_NEXTHOP_IPV6: - if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) - return 0; - break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: - case ZEBRA_NEXTHOP_IPV6_IFNAME: - if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) - return 0; - if (next1->ifindex != next2->ifindex) - return 0; - break; - default: - /* do nothing */ - break; - } - return 1; -} - -static int -bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1, - struct bgp_nexthop_cache *bnc2) -{ - int i; - struct nexthop *next1, *next2; - - if (bnc1->nexthop_num != bnc2->nexthop_num) - return 1; - - next1 = bnc1->nexthop; - next2 = bnc2->nexthop; - - for (i = 0; i < bnc1->nexthop_num; i++) - { - if (! bgp_nexthop_same (next1, next2)) - return 1; - - next1 = next1->next; - next2 = next2->next; - } - return 0; -} - /* If nexthop exists on connected network return 1. */ int bgp_nexthop_onlink (afi_t afi, struct attr *attr) { struct bgp_node *rn; - /* If zebra is not enabled return */ - if (zlookup->sock < 0) - return 1; - /* Lookup the address is onlink or not. */ if (afi == AFI_IP) { @@ -214,325 +126,6 @@ bgp_nexthop_onlink (afi_t afi, struct attr *attr) return 0; } -/* Check specified next-hop is reachable or not. */ -static int -bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed, - int *metricchanged) -{ - struct bgp_node *rn; - struct prefix p; - struct bgp_nexthop_cache *bnc; - struct attr *attr; - - /* If lookup is not enabled, return valid. */ - if (zlookup->sock < 0) - { - if (ri->extra) - ri->extra->igpmetric = 0; - return 1; - } - - /* Only check IPv6 global address only nexthop. */ - attr = ri->attr; - - if (attr->extra->mp_nexthop_len != 16 - || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global)) - return 1; - - memset (&p, 0, sizeof (struct prefix)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = attr->extra->mp_nexthop_global; - - /* IBGP or ebgp-multihop */ - rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p); - - if (rn->info) - { - bnc = rn->info; - bgp_unlock_node (rn); - } - else - { - if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global))) - bnc = bnc_new (); - else - { - if (changed) - { - struct bgp_table *old; - struct bgp_node *oldrn; - - if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6]) - old = cache2_table[AFI_IP6]; - else - old = cache1_table[AFI_IP6]; - - oldrn = bgp_node_lookup (old, &p); - if (oldrn) - { - struct bgp_nexthop_cache *oldbnc = oldrn->info; - - bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc); - - if (bnc->metric != oldbnc->metric) - bnc->metricchanged = 1; - - bgp_unlock_node (oldrn); - } - } - } - rn->info = bnc; - } - - if (changed) - *changed = bnc->changed; - - if (metricchanged) - *metricchanged = bnc->metricchanged; - - if (bnc->valid && bnc->metric) - (bgp_info_extra_get (ri))->igpmetric = bnc->metric; - else if (ri->extra) - ri->extra->igpmetric = 0; - - return bnc->valid; -} - -/* Check specified next-hop is reachable or not. */ -int -bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri, - int *changed, int *metricchanged) -{ - struct bgp_node *rn; - struct prefix p; - struct bgp_nexthop_cache *bnc; - struct in_addr addr; - - /* If lookup is not enabled, return valid. */ - if (zlookup->sock < 0) - { - if (ri->extra) - ri->extra->igpmetric = 0; - return 1; - } - - if (afi == AFI_IP6) - return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged); - - addr = ri->attr->nexthop; - - memset (&p, 0, sizeof (struct prefix)); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = addr; - - /* IBGP or ebgp-multihop */ - rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p); - - if (rn->info) - { - bnc = rn->info; - bgp_unlock_node (rn); - } - else - { - if (NULL == (bnc = zlookup_query (addr))) - bnc = bnc_new (); - else - { - if (changed) - { - struct bgp_table *old; - struct bgp_node *oldrn; - - if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP]) - old = cache2_table[AFI_IP]; - else - old = cache1_table[AFI_IP]; - - oldrn = bgp_node_lookup (old, &p); - if (oldrn) - { - struct bgp_nexthop_cache *oldbnc = oldrn->info; - - bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc); - - if (bnc->metric != oldbnc->metric) - bnc->metricchanged = 1; - - bgp_unlock_node (oldrn); - } - } - } - rn->info = bnc; - } - - if (changed) - *changed = bnc->changed; - - if (metricchanged) - *metricchanged = bnc->metricchanged; - - if (bnc->valid && bnc->metric) - (bgp_info_extra_get(ri))->igpmetric = bnc->metric; - else if (ri->extra) - ri->extra->igpmetric = 0; - - return bnc->valid; -} - -/* Reset and free all BGP nexthop cache. */ -static void -bgp_nexthop_cache_reset (struct bgp_table *table) -{ - struct bgp_node *rn; - struct bgp_nexthop_cache *bnc; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL) - { - bnc_free (bnc); - rn->info = NULL; - bgp_unlock_node (rn); - } -} - -static void -bgp_scan (afi_t afi, safi_t safi) -{ - struct bgp_node *rn; - struct bgp *bgp; - struct bgp_info *bi; - struct bgp_info *next; - struct peer *peer; - struct listnode *node, *nnode; - int valid; - int current; - int changed; - int metricchanged; - - /* Change cache. */ - if (bgp_nexthop_cache_table[afi] == cache1_table[afi]) - bgp_nexthop_cache_table[afi] = cache2_table[afi]; - else - bgp_nexthop_cache_table[afi] = cache1_table[afi]; - - /* Get default bgp. */ - bgp = bgp_get_default (); - if (bgp == NULL) - return; - - /* Maximum prefix check */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->status != Established) - continue; - - if (peer->afc[afi][SAFI_UNICAST]) - bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1); - if (peer->afc[afi][SAFI_MULTICAST]) - bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1); - if (peer->afc[afi][SAFI_MPLS_VPN]) - bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1); - } - - for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn; - rn = bgp_route_next (rn)) - { - for (bi = rn->info; bi; bi = next) - { - next = bi->next; - - if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL) - { - changed = 0; - metricchanged = 0; - - if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1 - && !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) - valid = bgp_nexthop_onlink (afi, bi->attr); - else - valid = bgp_nexthop_lookup (afi, bi->peer, bi, - &changed, &metricchanged); - - current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0; - - if (changed) - SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED); - else - UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED); - - if (valid != current) - { - if (CHECK_FLAG (bi->flags, BGP_INFO_VALID)) - { - bgp_aggregate_decrement (bgp, &rn->p, bi, - afi, SAFI_UNICAST); - bgp_info_unset_flag (rn, bi, BGP_INFO_VALID); - } - else - { - bgp_info_set_flag (rn, bi, BGP_INFO_VALID); - bgp_aggregate_increment (bgp, &rn->p, bi, - afi, SAFI_UNICAST); - } - } - - if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST], - BGP_CONFIG_DAMPENING) - && bi->extra && bi->extra->damp_info ) - if (bgp_damp_scan (bi, afi, SAFI_UNICAST)) - bgp_aggregate_increment (bgp, &rn->p, bi, - afi, SAFI_UNICAST); - } - } - if (rn->info) - bgp_process (bgp, rn, afi, SAFI_UNICAST); - } - - /* Flash old cache. */ - if (bgp_nexthop_cache_table[afi] == cache1_table[afi]) - bgp_nexthop_cache_reset (cache2_table[afi]); - else - bgp_nexthop_cache_reset (cache1_table[afi]); - - if (BGP_DEBUG (events, EVENTS)) - { - if (afi == AFI_IP) - zlog_debug ("scanning IPv4 Unicast routing tables"); - else if (afi == AFI_IP6) - zlog_debug ("scanning IPv6 Unicast routing tables"); - } - - /* Reevaluate default-originate route-maps and announce/withdraw - * default route if neccesary. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->status == Established - && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) - && peer->default_rmap[afi][safi].name) - bgp_default_originate (peer, afi, safi, 0); - } -} - -/* BGP scan thread. This thread check nexthop reachability. */ -static int -bgp_scan_timer (struct thread *t) -{ - bgp_scan_thread = - thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval); - - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("Performing BGP general scanning"); - - bgp_scan (AFI_IP, SAFI_UNICAST); - - bgp_scan (AFI_IP6, SAFI_UNICAST); - - return 0; -} - /* BGP own address structure */ struct bgp_addr { @@ -599,6 +192,9 @@ bgp_address_add (struct prefix *p) tmp.addr = p->u.prefix4; addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc); + if (!addr) + return; + addr->refcnt++; } @@ -777,652 +373,158 @@ bgp_nexthop_self (struct attr *attr) return 0; } -static struct bgp_nexthop_cache * -zlookup_read (void) -{ - struct stream *s; - uint16_t length; - u_char marker; - u_char version; - uint16_t vrf_id; - uint16_t command; - int err; - struct in_addr raddr __attribute__((unused)); - uint32_t metric; - int i; - u_char nexthop_num; - struct nexthop *nexthop; - struct bgp_nexthop_cache *bnc; - - s = zlookup->ibuf; - stream_reset (s); - - err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, - &vrf_id, &command); - if (err < 0) - { - zlog_err("%s: zserv_read_header() failed", __func__); - return NULL; - } - - /* XXX: not doing anything with raddr */ - raddr.s_addr = stream_get_ipv4 (s); - metric = stream_getl (s); - nexthop_num = stream_getc (s); - - if (nexthop_num) - { - bnc = bnc_new (); - bnc->valid = 1; - bnc->metric = metric; - bnc->nexthop_num = nexthop_num; - - for (i = 0; i < nexthop_num; i++) - { - nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - nexthop->type = stream_getc (s); - switch (nexthop->type) - { - case ZEBRA_NEXTHOP_IPV4: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - nexthop->ifindex = stream_getl (s); - break; - case ZEBRA_NEXTHOP_IFINDEX: - case ZEBRA_NEXTHOP_IFNAME: - nexthop->ifindex = stream_getl (s); - break; - default: - /* do nothing */ - break; - } - bnc_nexthop_add (bnc, nexthop); - } - } - else - return NULL; - - return bnc; -} - -struct bgp_nexthop_cache * -zlookup_query (struct in_addr addr) -{ - int ret; - struct stream *s; - - /* Check socket. */ - if (zlookup->sock < 0) - return NULL; - - s = zlookup->obuf; - stream_reset (s); - zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, VRF_DEFAULT); - stream_put_in_addr (s, &addr); - - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = writen (zlookup->sock, s->data, stream_get_endp (s)); - if (ret < 0) - { - zlog_err ("can't write to zlookup->sock"); - close (zlookup->sock); - zlookup->sock = -1; - return NULL; - } - if (ret == 0) - { - zlog_err ("zlookup->sock connection closed"); - close (zlookup->sock); - zlookup->sock = -1; - return NULL; - } - - return zlookup_read (); -} - -static struct bgp_nexthop_cache * -zlookup_read_ipv6 (void) -{ - struct stream *s; - uint16_t length, vrf_id, cmd; - u_char version, marker; - struct in6_addr raddr; - uint32_t metric; - int i, err; - u_char nexthop_num; - struct nexthop *nexthop; - struct bgp_nexthop_cache *bnc; - - s = zlookup->ibuf; - stream_reset (s); - - err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, - &vrf_id, &cmd); - if (err < 0) - { - zlog_err("%s: zserv_read_header() failed", __func__); - return NULL; - } - - /* XXX: not actually doing anything with raddr */ - stream_get (&raddr, s, 16); - - metric = stream_getl (s); - nexthop_num = stream_getc (s); - - if (nexthop_num) - { - bnc = bnc_new (); - bnc->valid = 1; - bnc->metric = metric; - bnc->nexthop_num = nexthop_num; - - for (i = 0; i < nexthop_num; i++) - { - nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - nexthop->type = stream_getc (s); - switch (nexthop->type) - { - case ZEBRA_NEXTHOP_IPV6: - stream_get (&nexthop->gate.ipv6, s, 16); - break; - case ZEBRA_NEXTHOP_IPV6_IFINDEX: - case ZEBRA_NEXTHOP_IPV6_IFNAME: - stream_get (&nexthop->gate.ipv6, s, 16); - nexthop->ifindex = stream_getl (s); - break; - case ZEBRA_NEXTHOP_IFINDEX: - case ZEBRA_NEXTHOP_IFNAME: - nexthop->ifindex = stream_getl (s); - break; - default: - /* do nothing */ - break; - } - bnc_nexthop_add (bnc, nexthop); - } - } - else - return NULL; - - return bnc; -} - -struct bgp_nexthop_cache * -zlookup_query_ipv6 (struct in6_addr *addr) -{ - int ret; - struct stream *s; - - /* Check socket. */ - if (zlookup->sock < 0) - return NULL; - - s = zlookup->obuf; - stream_reset (s); - zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, VRF_DEFAULT); - stream_put (s, addr, 16); - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = writen (zlookup->sock, s->data, stream_get_endp (s)); - if (ret < 0) - { - zlog_err ("can't write to zlookup->sock"); - close (zlookup->sock); - zlookup->sock = -1; - return NULL; - } - if (ret == 0) - { - zlog_err ("zlookup->sock connection closed"); - close (zlookup->sock); - zlookup->sock = -1; - return NULL; - } - - return zlookup_read_ipv6 (); -} - -static int -bgp_import_check (struct prefix *p, u_int32_t *igpmetric, - struct in_addr *igpnexthop) -{ - struct stream *s; - int ret; - u_int16_t length, vrf_id, command; - u_char version, marker; - struct in_addr addr __attribute__((unused)); - struct in_addr nexthop; - u_int32_t metric = 0; - u_char nexthop_num; - u_char nexthop_type; - - /* If lookup connection is not available return valid. */ - if (zlookup->sock < 0) - { - if (igpmetric) - *igpmetric = 0; - return 1; - } - - /* Send query to the lookup connection */ - s = zlookup->obuf; - stream_reset (s); - zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP, VRF_DEFAULT); - - stream_putc (s, p->prefixlen); - stream_put_in_addr (s, &p->u.prefix4); - - stream_putw_at (s, 0, stream_get_endp (s)); - - /* Write the packet. */ - ret = writen (zlookup->sock, s->data, stream_get_endp (s)); - - if (ret < 0) - { - zlog_err ("can't write to zlookup->sock"); - close (zlookup->sock); - zlookup->sock = -1; - return 1; - } - if (ret == 0) - { - zlog_err ("zlookup->sock connection closed"); - close (zlookup->sock); - zlookup->sock = -1; - return 1; - } - - /* Get result. */ - stream_reset (s); - - ret = zclient_read_header (s, zlookup->sock, &length, &marker, &version, - &vrf_id, &command); - if (ret < 0) - { - zlog_err("%s: zserv_read_header() failed", __func__); - return 0; - } - - /* XXX: not using addr */ - addr.s_addr = stream_get_ipv4 (s); - metric = stream_getl (s); - nexthop_num = stream_getc (s); - - /* Set IGP metric value. */ - if (igpmetric) - *igpmetric = metric; - - /* If there is nexthop then this is active route. */ - if (nexthop_num) - { - nexthop.s_addr = 0; - nexthop_type = stream_getc (s); - switch (nexthop_type) - { - case ZEBRA_NEXTHOP_IPV4: - nexthop.s_addr = stream_get_ipv4 (s); - break; - case ZEBRA_NEXTHOP_IPV4_IFINDEX: - nexthop.s_addr = stream_get_ipv4 (s); - /* ifindex */ (void)stream_getl (s); - break; - default: - /* do nothing */ - break; - } - *igpnexthop = nexthop; - - return 1; - } - else - return 0; -} - -/* Scan all configured BGP route then check the route exists in IGP or - not. */ -static int -bgp_import (struct thread *t) -{ - struct bgp *bgp; - struct bgp_node *rn; - struct bgp_static *bgp_static; - struct listnode *node, *nnode; - int valid; - u_int32_t metric; - struct in_addr nexthop; - afi_t afi; - safi_t safi; - - bgp_import_thread = - thread_add_timer (bm->master, bgp_import, NULL, bgp_import_interval); - - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("Import timer expired."); - - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++) - for (rn = bgp_table_top (bgp->route[afi][safi]); rn; - rn = bgp_route_next (rn)) - if ((bgp_static = rn->info) != NULL) - { - if (bgp_static->backdoor) - continue; - - valid = bgp_static->valid; - metric = bgp_static->igpmetric; - nexthop = bgp_static->igpnexthop; - - if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) - && afi == AFI_IP && safi == SAFI_UNICAST) - bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric, - &bgp_static->igpnexthop); - else - { - bgp_static->valid = 1; - bgp_static->igpmetric = 0; - bgp_static->igpnexthop.s_addr = 0; - } - - if (bgp_static->valid != valid) - { - if (bgp_static->valid) - bgp_static_update (bgp, &rn->p, bgp_static, afi, safi); - else - bgp_static_withdraw (bgp, &rn->p, afi, safi); - } - else if (bgp_static->valid) - { - if (bgp_static->igpmetric != metric - || bgp_static->igpnexthop.s_addr != nexthop.s_addr - || bgp_static->rmap.name) - bgp_static_update (bgp, &rn->p, bgp_static, afi, safi); - } - } - } - return 0; -} - -/* Connect to zebra for nexthop lookup. */ -static int -zlookup_connect (struct thread *t) -{ - struct zclient *zlookup; - - zlookup = THREAD_ARG (t); - zlookup->t_connect = NULL; - - if (zlookup->sock != -1) - return 0; - - if (zclient_socket_connect (zlookup) < 0) - return -1; - - return 0; -} - -/* Check specified multiaccess next-hop. */ int -bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer) +bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer) { struct bgp_node *rn1; struct bgp_node *rn2; - struct prefix p1; - struct prefix p2; - struct in_addr addr; + struct prefix p; int ret; - ret = inet_aton (peer, &addr); - if (! ret) - return 0; - - memset (&p1, 0, sizeof (struct prefix)); - p1.family = AF_INET; - p1.prefixlen = IPV4_MAX_BITLEN; - p1.u.prefix4 = nexthop; - memset (&p2, 0, sizeof (struct prefix)); - p2.family = AF_INET; - p2.prefixlen = IPV4_MAX_BITLEN; - p2.u.prefix4 = addr; - - /* If bgp scan is not enabled, return invalid. */ - if (zlookup->sock < 0) - return 0; + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = nexthop; - rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1); - if (! rn1) - return 0; - bgp_unlock_node (rn1); - - rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2); - if (! rn2) + rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p); + if (!rn1) return 0; - bgp_unlock_node (rn2); - /* This is safe, even with above unlocks, since we are just - comparing pointers to the objects, not the objects themselves. */ - if (rn1 == rn2) - return 1; - - return 0; -} - -DEFUN (bgp_scan_time, - bgp_scan_time_cmd, - "bgp scan-time <5-60>", - "BGP specific commands\n" - "Configure background scanner interval\n" - "Scanner interval (seconds)\n") -{ - bgp_scan_interval = atoi (argv[0]); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = peer->su.sin.sin_addr; - if (bgp_scan_thread) + rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p); + if (!rn2) { - thread_cancel (bgp_scan_thread); - bgp_scan_thread = - thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval); + bgp_unlock_node(rn1); + return 0; } - return CMD_SUCCESS; -} + ret = (rn1 == rn2) ? 1 : 0; -DEFUN (no_bgp_scan_time, - no_bgp_scan_time_cmd, - "no bgp scan-time", - NO_STR - "BGP specific commands\n" - "Configure background scanner interval\n") -{ - bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT; + bgp_unlock_node(rn1); + bgp_unlock_node(rn2); - if (bgp_scan_thread) - { - thread_cancel (bgp_scan_thread); - bgp_scan_thread = - thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval); - } - - return CMD_SUCCESS; + return (ret); } -ALIAS (no_bgp_scan_time, - no_bgp_scan_time_val_cmd, - "no bgp scan-time <5-60>", - NO_STR - "BGP specific commands\n" - "Configure background scanner interval\n" - "Scanner interval (seconds)\n") - static int -show_ip_bgp_scan_tables (struct vty *vty, const char detail) +show_ip_bgp_nexthop_table (struct vty *vty, int detail) { struct bgp_node *rn; struct bgp_nexthop_cache *bnc; char buf[INET6_ADDRSTRLEN]; - u_char i; - - if (bgp_scan_thread) - vty_out (vty, "BGP scan is running%s", VTY_NEWLINE); - else - vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE); - vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE); + struct nexthop *nexthop; + time_t tbuf; + afi_t afi; vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE); - for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL) - { - if (bnc->valid) - { - vty_out (vty, " %s valid [IGP metric %d]%s", - inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE); - if (detail) - for (i = 0; i < bnc->nexthop_num; i++) - switch (bnc->nexthop[i].type) - { - case NEXTHOP_TYPE_IPV4: - vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " gate %s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN)); - vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE); - break; - default: - vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE); - } - } - else - vty_out (vty, " %s invalid%s", - inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); - } - - { - for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]); - rn; - rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL) + for (afi = AFI_IP ; afi < AFI_MAX ; afi++) + { + for (rn = bgp_table_top (bgp_nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn)) { - if (bnc->valid) - { - vty_out (vty, " %s valid [IGP metric %d]%s", - inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN), - bnc->metric, VTY_NEWLINE); - if (detail) - for (i = 0; i < bnc->nexthop_num; i++) - switch (bnc->nexthop[i].type) + if ((bnc = rn->info) != NULL) + { + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) { - case NEXTHOP_TYPE_IPV6: - vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE); - break; - default: - vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE); + vty_out (vty, " %s valid [IGP metric %d], #paths %d%s", + inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)), + bnc->metric, bnc->path_count, VTY_NEWLINE); + if (detail) + for (nexthop = bnc->nexthop ; nexthop; nexthop = nexthop->next) + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV6: + vty_out (vty, " gate %s%s", + inet_ntop (AF_INET6, &nexthop->gate.ipv6, + buf, INET6_ADDRSTRLEN), VTY_NEWLINE); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " gate %s, if %s%s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, + INET6_ADDRSTRLEN), + ifindex2ifname(nexthop->ifindex), + VTY_NEWLINE); + break; + case NEXTHOP_TYPE_IPV4: + vty_out (vty, " gate %s%s", + inet_ntop (AF_INET, &nexthop->gate.ipv4, buf, + INET6_ADDRSTRLEN), VTY_NEWLINE); + break; + case NEXTHOP_TYPE_IFINDEX: + vty_out (vty, " if %s%s", + ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out (vty, " gate %s, if %s%s", + inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, + INET6_ADDRSTRLEN), + ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); + break; + default: + vty_out (vty, " invalid nexthop type %u%s", + nexthop->type, VTY_NEWLINE); + } } - } - else - vty_out (vty, " %s invalid%s", - inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN), - VTY_NEWLINE); + else + vty_out (vty, " %s invalid%s", + inet_ntop (AF_INET, &rn->p.u.prefix, buf, sizeof (buf)), VTY_NEWLINE); +#ifdef HAVE_CLOCK_MONOTONIC + tbuf = time(NULL) - (bgp_clock() - bnc->last_update); + vty_out (vty, " Last update: %s", ctime(&tbuf)); +#else + vty_out (vty, " Last update: %s", ctime(&bnc->uptime)); +#endif /* HAVE_CLOCK_MONOTONIC */ + vty_out(vty, "%s", VTY_NEWLINE); + } } - } - - vty_out (vty, "BGP connected route:%s", VTY_NEWLINE); - for (rn = bgp_table_top (bgp_connected_table[AFI_IP]); - rn; - rn = bgp_route_next (rn)) - if (rn->info != NULL) - vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, - VTY_NEWLINE); - - { - for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]); - rn; - rn = bgp_route_next (rn)) - if (rn->info != NULL) - vty_out (vty, " %s/%d%s", - inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN), - rn->p.prefixlen, - VTY_NEWLINE); - } - + } return CMD_SUCCESS; } -DEFUN (show_ip_bgp_scan, - show_ip_bgp_scan_cmd, - "show ip bgp scan", +DEFUN (show_ip_bgp_nexthop, + show_ip_bgp_nexthop_cmd, + "show ip bgp nexthop", SHOW_STR IP_STR BGP_STR - "BGP scan status\n") + "BGP nexthop table\n") { - return show_ip_bgp_scan_tables (vty, 0); + return show_ip_bgp_nexthop_table (vty, 0); } -DEFUN (show_ip_bgp_scan_detail, - show_ip_bgp_scan_detail_cmd, - "show ip bgp scan detail", +DEFUN (show_ip_bgp_nexthop_detail, + show_ip_bgp_nexthop_detail_cmd, + "show ip bgp nexthop detail", SHOW_STR IP_STR BGP_STR - "BGP scan status\n" - "More detailed output\n") + "BGP nexthop table\n") { - return show_ip_bgp_scan_tables (vty, 1); -} - -int -bgp_config_write_scan_time (struct vty *vty) -{ - if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT) - vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE); - return CMD_SUCCESS; + return show_ip_bgp_nexthop_table (vty, 1); } void bgp_scan_init (void) { - zlookup = zclient_new (bm->master); - zlookup->sock = -1; - zlookup->t_connect = thread_add_event (bm->master, zlookup_connect, zlookup, 0); - - bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT; - bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT; - cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); - cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP]; bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); - cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6]; bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); - /* Make BGP scan thread. */ - bgp_scan_thread = thread_add_timer (bm->master, bgp_scan_timer, - NULL, bgp_scan_interval); - /* Make BGP import there. */ - bgp_import_thread = thread_add_timer (bm->master, bgp_import, NULL, 0); - - install_element (BGP_NODE, &bgp_scan_time_cmd); - install_element (BGP_NODE, &no_bgp_scan_time_cmd); - install_element (BGP_NODE, &no_bgp_scan_time_val_cmd); - install_element (VIEW_NODE, &show_ip_bgp_scan_cmd); - install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd); - install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd); - install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd); - install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd); +} + +void +bgp_scan_vty_init() +{ + install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd); + install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd); + install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd); } void @@ -1432,10 +534,6 @@ bgp_scan_finish (void) bgp_table_unlock (cache1_table[AFI_IP]); cache1_table[AFI_IP] = NULL; - if (cache2_table[AFI_IP]) - bgp_table_unlock (cache2_table[AFI_IP]); - cache2_table[AFI_IP] = NULL; - if (bgp_connected_table[AFI_IP]) bgp_table_unlock (bgp_connected_table[AFI_IP]); bgp_connected_table[AFI_IP] = NULL; @@ -1444,10 +542,6 @@ bgp_scan_finish (void) bgp_table_unlock (cache1_table[AFI_IP6]); cache1_table[AFI_IP6] = NULL; - if (cache2_table[AFI_IP6]) - bgp_table_unlock (cache2_table[AFI_IP6]); - cache2_table[AFI_IP6] = NULL; - if (bgp_connected_table[AFI_IP6]) bgp_table_unlock (bgp_connected_table[AFI_IP6]); bgp_connected_table[AFI_IP6] = NULL; @@ -1456,12 +550,5 @@ bgp_scan_finish (void) void bgp_scan_destroy (void) { - if (zlookup == NULL) - return; - THREAD_OFF(bgp_import_thread); - THREAD_OFF(bgp_scan_thread); - THREAD_OFF(zlookup->t_connect); bgp_scan_finish(); - zclient_free (zlookup); - zlookup = NULL; } diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index 85c5a5d0..fe4f5ad4 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -22,9 +22,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define _QUAGGA_BGP_NEXTHOP_H #include "if.h" - -#define BGP_SCAN_INTERVAL_DEFAULT 60 -#define BGP_IMPORT_INTERVAL_DEFAULT 15 +#include "queue.h" +#include "prefix.h" #define NEXTHOP_FAMILY(nexthop_len) ( \ ((nexthop_len) == 4 || \ @@ -38,35 +37,48 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA /* BGP nexthop cache value structure. */ struct bgp_nexthop_cache { - /* This nexthop exists in IGP. */ - u_char valid; - - /* Nexthop is changed. */ - u_char changed; - - /* Nexthop is changed. */ - u_char metricchanged; - /* IGP route's metric. */ u_int32_t metric; /* Nexthop number and nexthop linked list.*/ u_char nexthop_num; struct nexthop *nexthop; + time_t last_update; + u_int16_t flags; + +#define BGP_NEXTHOP_VALID (1 << 0) +#define BGP_NEXTHOP_REGISTERED (1 << 1) +#define BGP_NEXTHOP_CONNECTED (1 << 2) +#define BGP_NEXTHOP_PEER_NOTIFIED (1 << 3) + + u_int16_t change_flags; + +#define BGP_NEXTHOP_CHANGED (1 << 0) +#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1) +#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2) + + struct bgp_node *node; + void *nht_info; /* In BGP, peer session */ + LIST_HEAD(path_list, bgp_info) paths; + unsigned int path_count; }; -extern void bgp_scan_init (void); -extern void bgp_scan_finish (void); extern int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *, int *, int *); extern void bgp_connected_add (struct connected *c); extern void bgp_connected_delete (struct connected *c); -extern int bgp_multiaccess_check_v4 (struct in_addr, char *); +extern int bgp_multiaccess_check_v4 (struct in_addr, struct peer *); extern int bgp_config_write_scan_time (struct vty *); extern int bgp_nexthop_onlink (afi_t, struct attr *); extern int bgp_nexthop_self (struct attr *); extern void bgp_address_init (void); extern void bgp_address_destroy (void); extern void bgp_scan_destroy (void); +extern struct bgp_nexthop_cache *bnc_new(void); +extern void bnc_free(struct bgp_nexthop_cache *bnc); +extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc); +extern char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size); +extern void bgp_scan_init (void); +extern void bgp_scan_vty_init (void); #endif /* _QUAGGA_BGP_NEXTHOP_H */ diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c new file mode 100644 index 00000000..34b5fd1c --- /dev/null +++ b/bgpd/bgp_nht.c @@ -0,0 +1,518 @@ +/* BGP Nexthop tracking + * Copyright (C) 2013 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <zebra.h> + +#include "command.h" +#include "thread.h" +#include "prefix.h" +#include "zclient.h" +#include "stream.h" +#include "network.h" +#include "log.h" +#include "memory.h" +#include "nexthop.h" +#include "filter.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_table.h" +#include "bgpd/bgp_route.h" +#include "bgpd/bgp_attr.h" +#include "bgpd/bgp_nexthop.h" +#include "bgpd/bgp_debug.h" +#include "bgpd/bgp_nht.h" +#include "bgpd/bgp_fsm.h" + +extern struct zclient *zclient; +extern struct bgp_table *bgp_nexthop_cache_table[AFI_MAX]; + +static void register_nexthop(struct bgp_nexthop_cache *bnc); +static void unregister_nexthop (struct bgp_nexthop_cache *bnc); +static void evaluate_paths(struct bgp_nexthop_cache *bnc); +static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p); +static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc, + int keep); + +int +bgp_find_nexthop (struct bgp_info *path, int connected) +{ + struct bgp_nexthop_cache *bnc = path->nexthop; + + if (!bnc) + return 0; + + if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))) + return 0; + + return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)); +} + +void +bgp_unlink_nexthop (struct bgp_info *path) +{ + struct bgp_nexthop_cache *bnc = path->nexthop; + + if (!bnc) + return; + + path_nh_map(path, NULL, 0); + + if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) + { + if (BGP_DEBUG(nht, NHT)) + { + char buf[INET6_ADDRSTRLEN]; + zlog_debug("bgp_unlink_nexthop: freeing bnc %s", + bnc_str(bnc, buf, INET6_ADDRSTRLEN)); + } + unregister_nexthop(bnc); + bnc->node->info = NULL; + bgp_unlock_node(bnc->node); + bnc_free(bnc); + } +} + +int +bgp_find_or_add_nexthop (afi_t afi, struct bgp_info *ri, struct peer *peer, + int connected) +{ + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + struct prefix p; + + if (ri) + { + if (make_prefix(afi, ri, &p) < 0) + return 1; + } + else if (peer) + { + if (afi == AFI_IP) + { + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = peer->su.sin.sin_addr; + } + else if (afi == AFI_IP6) + { + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_BITLEN; + p.u.prefix6 = peer->su.sin6.sin6_addr; + } + } + + rn = bgp_node_get (bgp_nexthop_cache_table[afi], &p); + + if (!rn->info) + { + bnc = bnc_new(); + rn->info = bnc; + bnc->node = rn; + bgp_lock_node(rn); + if (connected) + SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED); + } + + bnc = rn->info; + bgp_unlock_node (rn); + + if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) + register_nexthop(bnc); + + if (ri) + { + path_nh_map(ri, bnc, 1); + + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) + (bgp_info_extra_get(ri))->igpmetric = bnc->metric; + else if (ri->extra) + ri->extra->igpmetric = 0; + } + else if (peer) + bnc->nht_info = (void *)peer; + + return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)); +} + +void +bgp_parse_nexthop_update (void) +{ + struct stream *s; + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + struct nexthop *nexthop; + struct nexthop *oldnh; + struct nexthop *nhlist_head = NULL; + struct nexthop *nhlist_tail = NULL; + uint32_t metric; + u_char nexthop_num; + struct prefix p; + int i; + + s = zclient->ibuf; + + memset(&p, 0, sizeof(struct prefix)); + p.family = stream_getw(s); + p.prefixlen = stream_getc(s); + switch (p.family) + { + case AF_INET: + p.u.prefix4.s_addr = stream_get_ipv4 (s); + break; + case AF_INET6: + stream_get(&p.u.prefix6, s, 16); + break; + default: + break; + } + + rn = bgp_node_lookup(bgp_nexthop_cache_table[family2afi(p.family)], &p); + if (!rn || !rn->info) + { + if (BGP_DEBUG(nht, NHT)) + { + char buf[INET6_ADDRSTRLEN]; + prefix2str(&p, buf, INET6_ADDRSTRLEN); + zlog_debug("parse nexthop update(%s): rn not found", buf); + } + if (rn) + bgp_unlock_node (rn); + return; + } + + bnc = rn->info; + bgp_unlock_node (rn); + bnc->last_update = bgp_clock(); + bnc->change_flags = 0; + metric = stream_getl (s); + nexthop_num = stream_getc (s); + + /* debug print the input */ + if (BGP_DEBUG(nht, NHT)) + { + char buf[INET6_ADDRSTRLEN]; + prefix2str(&p, buf, INET6_ADDRSTRLEN); + zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf, + metric, nexthop_num); + } + + if (metric != bnc->metric) + bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED; + + if(nexthop_num != bnc->nexthop_num) + bnc->change_flags |= BGP_NEXTHOP_CHANGED; + + if (nexthop_num) + { + bnc->flags |= BGP_NEXTHOP_VALID; + bnc->metric = metric; + bnc->nexthop_num = nexthop_num; + + for (i = 0; i < nexthop_num; i++) + { + nexthop = nexthop_new(); + nexthop->type = stream_getc (s); + switch (nexthop->type) + { + case ZEBRA_NEXTHOP_IPV4: + nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); + break; + case ZEBRA_NEXTHOP_IFINDEX: + case ZEBRA_NEXTHOP_IFNAME: + nexthop->ifindex = stream_getl (s); + break; + case ZEBRA_NEXTHOP_IPV4_IFINDEX: + case ZEBRA_NEXTHOP_IPV4_IFNAME: + nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); + nexthop->ifindex = stream_getl (s); + break; +#ifdef HAVE_IPV6 + case ZEBRA_NEXTHOP_IPV6: + stream_get (&nexthop->gate.ipv6, s, 16); + break; + case ZEBRA_NEXTHOP_IPV6_IFINDEX: + case ZEBRA_NEXTHOP_IPV6_IFNAME: + stream_get (&nexthop->gate.ipv6, s, 16); + nexthop->ifindex = stream_getl (s); + break; +#endif + default: + /* do nothing */ + break; + } + + if (nhlist_tail) + { + nhlist_tail->next = nexthop; + nhlist_tail = nexthop; + } + else + { + nhlist_tail = nexthop; + nhlist_head = nexthop; + } + + /* No need to evaluate the nexthop if we have already determined + * that there has been a change. + */ + if (bnc->change_flags & BGP_NEXTHOP_CHANGED) + continue; + + for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next) + if (nexthop_same_no_recurse(oldnh, nexthop)) + break; + + if (!oldnh) + bnc->change_flags |= BGP_NEXTHOP_CHANGED; + } + bnc_nexthop_free(bnc); + bnc->nexthop = nhlist_head; + } + else + { + bnc->flags &= ~BGP_NEXTHOP_VALID; + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); + bnc_nexthop_free(bnc); + bnc->nexthop = NULL; + } + + evaluate_paths(bnc); +} + +/** + * make_prefix - make a prefix structure from the path (essentially + * path's node. + */ +static int +make_prefix (int afi, struct bgp_info *ri, struct prefix *p) +{ + memset (p, 0, sizeof (struct prefix)); + switch (afi) + { + case AFI_IP: + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4 = ri->attr->nexthop; + break; +#ifdef HAVE_IPV6 + case AFI_IP6: + if (ri->attr->extra->mp_nexthop_len != 16 + || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global)) + return -1; + + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_BITLEN; + p->u.prefix6 = ri->attr->extra->mp_nexthop_global; + break; +#endif + default: + break; + } + return 0; +} + +/** + * sendmsg_nexthop -- Format and send a nexthop register/Unregister + * command to Zebra. + * ARGUMENTS: + * struct bgp_nexthop_cache *bnc -- the nexthop structure. + * int command -- either ZEBRA_NEXTHOP_REGISTER or ZEBRA_NEXTHOP_UNREGISTER + * RETURNS: + * void. + */ +static void +sendmsg_nexthop (struct bgp_nexthop_cache *bnc, int command) +{ + struct stream *s; + struct prefix *p; + int ret; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + { + zlog_debug("%s: Can't send NH register, Zebra client not established", + __FUNCTION__); + return; + } + + p = &(bnc->node->p); + s = zclient->obuf; + stream_reset (s); + zclient_create_header (s, command, VRF_DEFAULT); + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) + stream_putc(s, 1); + else + stream_putc(s, 0); + + stream_putw(s, PREFIX_FAMILY(p)); + stream_putc(s, p->prefixlen); + switch (PREFIX_FAMILY(p)) + { + case AF_INET: + stream_put_in_addr (s, &p->u.prefix4); + break; + case AF_INET6: + stream_put(s, &(p->u.prefix6), 16); + break; + default: + break; + } + stream_putw_at (s, 0, stream_get_endp (s)); + + ret = zclient_send_message(zclient); + /* TBD: handle the failure */ + if (ret < 0) + zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); + + if (command == ZEBRA_NEXTHOP_REGISTER) + SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + else if (command == ZEBRA_NEXTHOP_UNREGISTER) + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + return; +} + +/** + * register_nexthop - register a nexthop with Zebra for notification + * when the route to the nexthop changes. + * ARGUMENTS: + * struct bgp_nexthop_cache *bnc -- the nexthop structure. + * RETURNS: + * void. + */ +static void +register_nexthop (struct bgp_nexthop_cache *bnc) +{ + /* Check if we have already registered */ + if (bnc->flags & BGP_NEXTHOP_REGISTERED) + return; + sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_REGISTER); +} + +/** + * unregister_nexthop -- Unregister the nexthop from Zebra. + * ARGUMENTS: + * struct bgp_nexthop_cache *bnc -- the nexthop structure. + * RETURNS: + * void. + */ +static void +unregister_nexthop (struct bgp_nexthop_cache *bnc) +{ + /* Check if we have already registered */ + if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) + return; + + sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_UNREGISTER); +} + +/** + * evaluate_paths - Evaluate the paths/nets associated with a nexthop. + * ARGUMENTS: + * struct bgp_nexthop_cache *bnc -- the nexthop structure. + * RETURNS: + * void. + */ +static void +evaluate_paths (struct bgp_nexthop_cache *bnc) +{ + struct bgp_node *rn; + struct bgp_info *path; + struct bgp *bgp = bgp_get_default(); + int afi; + struct peer *peer = (struct peer *)bnc->nht_info; + + LIST_FOREACH(path, &(bnc->paths), nh_thread) + { + if (!(path->type == ZEBRA_ROUTE_BGP && + path->sub_type == BGP_ROUTE_NORMAL)) + continue; + + rn = path->net; + afi = family2afi(rn->p.family); + + /* Path becomes valid/invalid depending on whether the nexthop + * reachable/unreachable. + */ + if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) != + (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? 1 : 0)) + { + if (CHECK_FLAG (path->flags, BGP_INFO_VALID)) + { + bgp_aggregate_decrement (bgp, &rn->p, path, + afi, SAFI_UNICAST); + bgp_info_unset_flag (rn, path, BGP_INFO_VALID); + } + else + { + bgp_info_set_flag (rn, path, BGP_INFO_VALID); + bgp_aggregate_increment (bgp, &rn->p, path, + afi, SAFI_UNICAST); + } + } + + /* Copy the metric to the path. Will be used for bestpath computation */ + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) + (bgp_info_extra_get(path))->igpmetric = bnc->metric; + else if (path->extra) + path->extra->igpmetric = 0; + + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_METRIC_CHANGED) || + CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CHANGED)) + SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); + + bgp_process(bgp, rn, afi, SAFI_UNICAST); + } + + if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) + { + if (BGP_DEBUG(nht, NHT)) + zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host); + bgp_fsm_nht_update(peer, CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)); + SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); + } + + RESET_FLAG(bnc->change_flags); +} + +/** + * path_nh_map - make or break path-to-nexthop association. + * ARGUMENTS: + * path - pointer to the path structure + * bnc - pointer to the nexthop structure + * make - if set, make the association. if unset, just break the existing + * association. + */ +static void +path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make) +{ + if (path->nexthop) + { + LIST_REMOVE(path, nh_thread); + path->nexthop->path_count--; + path->nexthop = NULL; + } + if (make) + { + LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread); + path->nexthop = bnc; + path->nexthop->path_count++; + } +} diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h new file mode 100644 index 00000000..2bced7fb --- /dev/null +++ b/bgpd/bgp_nht.h @@ -0,0 +1,58 @@ +/* BGP Nexthop tracking + * Copyright (C) 2013 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _BGP_NHT_H +#define _BGP_NHT_H + +/** + * bgp_parse_nexthop_update() - parse a nexthop update message from Zebra. + */ +extern void bgp_parse_nexthop_update(void); + +/** + * bgp_find_nexthop() - lookup the nexthop cache table for the bnc object + * ARGUMENTS: + * p - path for which the nexthop object is being looked up + * connected - True if NH MUST be a connected route + */ +extern int bgp_find_nexthop(struct bgp_info *p, int connected); + +/** + * bgp_find_or_add_nexthop() - lookup the nexthop cache table for the bnc + * object. If not found, create a new object and register with ZEBRA for + * nexthop notification. + * ARGUMENTS: + * a - afi: AFI_IP or AF_IP6 + * p - path for which the nexthop object is being looked up + * peer - The BGP peer associated with this NHT + * connected - True if NH MUST be a connected route + */ +extern int bgp_find_or_add_nexthop(afi_t a, struct bgp_info *p, + struct peer *peer, int connected); + +/** + * bgp_unlink_nexthop() - Unlink the nexthop object from the path structure. + * ARGUMENTS: + * p - path structure. + */ +extern void bgp_unlink_nexthop(struct bgp_info *p); + +#endif /* _BGP_NHT_H */ diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 7b8b6577..35387f17 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -160,7 +160,7 @@ bgp_capability_mp (struct peer *peer, struct capability_header *hdr) bgp_capability_mp_data (s, &mpc); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", peer->host, mpc.afi, mpc.safi); @@ -182,7 +182,7 @@ static void bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi, u_char type, u_char mode) { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported", peer->host, afi, safi, type, mode); } @@ -221,7 +221,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) afi = entry.mpc.afi; safi = entry.mpc.safi; - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u", peer->host, entry.mpc.afi, entry.mpc.safi); @@ -298,7 +298,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) continue; } - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s OPEN has %s ORF capability" " as %s for afi/safi: %d/%d", peer->host, LOOKUP (orf_type_str, type), @@ -353,7 +353,7 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) UNSET_FLAG (restart_flag_time, 0xF000); peer->v_gr_restart = restart_flag_time; - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) { zlog_debug ("%s OPEN has Graceful Restart capability", peer->host); zlog_debug ("%s Peer has%srestarted. Restart Time : %d", @@ -371,21 +371,21 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) if (!bgp_afi_safi_valid_indices (afi, &safi)) { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." " Ignore the Graceful Restart capability", peer->host, afi, safi); } else if (!peer->afc[afi][safi]) { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." " Ignore the Graceful Restart capability", peer->host, afi, safi); } else { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Address family %s is%spreserved", peer->host, afi_safi_print (afi, safi), CHECK_FLAG (peer->af_cap[afi][safi], @@ -507,7 +507,7 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, return -1; } - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s OPEN has %s capability (%u), length %u", peer->host, LOOKUP (capcode_str, caphdr.code), @@ -750,7 +750,7 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) ret = 0; error = error_data; - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u", peer->host, length); @@ -781,7 +781,7 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) return -1; } - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u", peer->host, opt_type, opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" : @@ -851,12 +851,11 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP]) { - plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not " + zlog_err ("%s [Error] Configured AFI/SAFIs do not " "overlap with received MP capabilities", peer->host); if (error != error_data) - bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL, diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 740b0f1c..3fd584c5 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -103,8 +103,8 @@ bgp_packet_delete (struct peer *peer) } /* Check file descriptor whether connect is established. */ -static void -bgp_connect_check (struct peer *peer) +int +bgp_connect_check (struct peer *peer, int change_state) { int status; socklen_t slen; @@ -121,22 +121,25 @@ bgp_connect_check (struct peer *peer) /* If getsockopt is fail, this is fatal error. */ if (ret < 0) { - zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect"); + zlog_info ("can't get sockopt for nonblocking connect"); BGP_EVENT_ADD (peer, TCP_fatal_error); - return; + return -1; } /* When status is 0 then TCP connection is established. */ if (status == 0) { BGP_EVENT_ADD (peer, TCP_connection_open); + return 1; } else { - if (BGP_DEBUG (events, EVENTS)) - plog_debug (peer->log, "%s [Event] Connect failed (%s)", - peer->host, safe_strerror (errno)); - BGP_EVENT_ADD (peer, TCP_connection_open_failed); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [Event] Connect failed (%s)", + peer->host, safe_strerror (errno)); + if (change_state) + BGP_EVENT_ADD (peer, TCP_connection_open_failed); + return 0; } } @@ -153,8 +156,13 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi) struct bgp_info *binfo = NULL; bgp_size_t total_attr_len = 0; unsigned long attrlen_pos = 0; + int space_remaining = 0; + int space_needed = 0; size_t mpattrlen_pos = 0; size_t mpattr_pos = 0; + int num_pfx_adv = 0; + char send_attr_str[BUFSIZ]; + int send_attr_printed = 0; s = peer->work; stream_reset (s); @@ -171,9 +179,12 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi) if (adv->binfo) binfo = adv->binfo; + space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - + BGP_MAX_PACKET_SIZE_OVERFLOW; + space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p); + /* When remaining space can't include NLRI and it's length. */ - if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <= - (BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(afi,safi,&rn->p))) + if (space_remaining < space_needed) break; /* If packet is empty, set attribute. */ @@ -217,6 +228,29 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi) &rn->p : NULL), afi, safi, from, prd, tag); + space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - + BGP_MAX_PACKET_SIZE_OVERFLOW; + space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);; + + /* If the attributes alone do not leave any room for NLRI then + * return */ + if (space_remaining < space_needed) + { + zlog_err ("%s cannot send UPDATE, the attributes do not leave " + "room for NLRI", peer->host); + /* Flush the FIFO update queue */ + while (adv) + adv = bgp_advertise_clean (peer, adv->adj, afi, safi); + return NULL; + } + + if (BGP_DEBUG (update, UPDATE_OUT) || + BGP_DEBUG (update, UPDATE_PREFIX)) + { + memset (send_attr_str, 0, BUFSIZ); + send_attr_printed = 0; + bgp_dump_attr (peer, adv->baa->attr, send_attr_str, BUFSIZ); + } } if (afi == AFI_IP && safi == SAFI_UNICAST) @@ -237,14 +271,21 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi) adv->baa->attr); bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag); } - if (BGP_DEBUG (update, UPDATE_OUT)) + num_pfx_adv++; + + if (bgp_debug_update(peer, &rn->p, 0)) { + if (!send_attr_printed) + { + zlog_debug ("%s send UPDATE w/ attr: %s", peer->host, send_attr_str); + send_attr_printed = 1; + } char buf[INET6_BUFSIZ]; - zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d", - peer->host, - inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ), - rn->p.prefixlen); + zlog_debug ("%s send UPDATE %s/%d", + peer->host, + inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ), + rn->p.prefixlen); } /* Synchnorize attribute. */ @@ -274,8 +315,11 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi) else packet = stream_dup (s); bgp_packet_set_size (packet); + if (BGP_DEBUG (update, UPDATE_OUT)) + zlog_debug("%s form UPDATE (adv) total len %zd numPfx %d", + peer->host, + (stream_get_endp (s) - stream_get_getp (s)), num_pfx_adv); bgp_packet_add (peer, packet); - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); stream_reset (s); stream_reset (snlri); return packet; @@ -291,7 +335,7 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi) if (DISABLE_BGP_ANNOUNCE) return NULL; - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host); s = stream_new (BGP_MAX_PACKET_SIZE); @@ -347,6 +391,9 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi) size_t attrlen_pos = 0; size_t mplen_pos = 0; u_char first_time = 1; + int space_remaining = 0; + int space_needed = 0; + int num_pfx_wd = 0; s = peer->work; stream_reset (s); @@ -357,8 +404,12 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi) adj = adv->adj; rn = adv->rn; - if (STREAM_REMAIN (s) - < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen))) + space_remaining = STREAM_REMAIN (s) - + BGP_MAX_PACKET_SIZE_OVERFLOW; + space_needed = (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p)); + + if (space_remaining < space_needed) break; if (stream_empty (s)) @@ -390,15 +441,16 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi) bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL); } + num_pfx_wd++; - if (BGP_DEBUG (update, UPDATE_OUT)) + if (bgp_debug_update(peer, &rn->p, 0)) { char buf[INET6_BUFSIZ]; - zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable", - peer->host, - inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ), - rn->p.prefixlen); + zlog_debug ("%s send UPDATE %s/%d -- unreachable", + peer->host, + inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ), + rn->p.prefixlen); } peer->scount[afi][safi]--; @@ -426,6 +478,10 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi) stream_putw_at (s, attrlen_pos, total_attr_len); } bgp_packet_set_size (s); + if (BGP_DEBUG (update, UPDATE_OUT)) + zlog_debug("%s form UPDATE (wd) total len %zd numPfx %d", + peer->host, + (stream_get_endp (s) - stream_get_getp (s)), num_pfx_wd); packet = stream_dup (s); bgp_packet_add (peer, packet); stream_reset (s); @@ -453,16 +509,16 @@ bgp_default_update_send (struct peer *peer, struct attr *attr, str2prefix ("::/0", &p); /* Logging the attribute. */ - if (BGP_DEBUG (update, UPDATE_OUT)) + if (bgp_debug_update(peer, &p, 0)) { char attrstr[BUFSIZ]; char buf[INET6_BUFSIZ]; attrstr[0] = '\0'; bgp_dump_attr (peer, attr, attrstr, BUFSIZ); - zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s", - peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ), - p.prefixlen, attrstr); + zlog_debug ("%s send UPDATE %s/%d %s", + peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ), + p.prefixlen, attrstr); } s = stream_new (BGP_MAX_PACKET_SIZE); @@ -521,13 +577,13 @@ bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi) total_attr_len = 0; - if (BGP_DEBUG (update, UPDATE_OUT)) + if (bgp_debug_update(peer, &p, 0)) { char buf[INET6_BUFSIZ]; - zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable", - peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ), - p.prefixlen); + zlog_debug ("%s send UPDATE %s/%d -- unreachable", + peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ), + p.prefixlen); } s = stream_new (BGP_MAX_PACKET_SIZE); @@ -589,6 +645,12 @@ bgp_write_packet (struct peer *peer) if (s) return s; + /* The code beyond this part deals with update packets, check if updates + are on hold as part of the update-delay post processing stages. */ + if (peer->bgp && (peer->bgp->main_peers_update_hold || + peer->bgp->rsclient_peers_update_hold)) + return NULL; + for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { @@ -607,7 +669,7 @@ bgp_write_packet (struct peer *peer) adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update); if (adv) { - if (adv->binfo && adv->binfo->uptime < peer->synctime) + if (adv->binfo && adv->binfo->uptime <= peer->synctime) { if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV) && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV) @@ -645,28 +707,82 @@ bgp_write_packet (struct peer *peer) return NULL; } -/* Is there partially written packet or updates we can send right - now. */ -static int -bgp_write_proceed (struct peer *peer) +/* Are there prefixes queued for being withdrawn? */ +int +bgp_peer_wd_fifo_exists (struct peer *peer) { afi_t afi; safi_t safi; - struct bgp_advertise *adv; - - if (stream_fifo_head (peer->obuf)) - return 1; for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) return 1; + return 0; +} + +/* Are there prefixes queued for being advertised? + * Are they recent? + */ +int +bgp_peer_adv_fifo_exists (struct peer *peer, int chk_recent) +{ + afi_t afi; + safi_t safi; + struct bgp_advertise *adv; + for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL) - if (adv->binfo->uptime < peer->synctime) - return 1; + { + if (!chk_recent) + return 1; + if (adv->binfo->uptime < peer->synctime) + return 1; + } + + return 0; +} + +/* + * Schedule updates for the peer, if needed. + */ +void +bgp_peer_schedule_updates(struct peer *peer) +{ + /* If withdraw FIFO exists, immediately schedule write */ + if (bgp_peer_wd_fifo_exists(peer) && !peer->t_write) + { + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("%s scheduling write thread", peer->host); + BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + } + + /* If update FIFO exists, fire MRAI timer */ + if (bgp_peer_adv_fifo_exists(peer, 0) && !peer->radv_adjusted) + { + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("%s scheduling MRAI timer", peer->host); + bgp_adjust_routeadv(peer); + } +} + +/* Is there partially written packet or updates we can send right + now. */ +static int +bgp_write_proceed (struct peer *peer) +{ + /* If queued packet exists, we should try to write it */ + if (stream_fifo_head (peer->obuf)) + return 1; + + /* If there are prefixes to be withdrawn or to be advertised (and + * queued before last MRAI timer expiry), schedule write + */ + if (bgp_peer_wd_fifo_exists(peer) + || bgp_peer_adv_fifo_exists(peer, 1)) + return 1; return 0; } @@ -680,6 +796,7 @@ bgp_write (struct thread *thread) struct stream *s; int num; unsigned int count = 0; + unsigned int oc = 0; /* Yes first of all get peer pointer. */ peer = THREAD_ARG (thread); @@ -688,7 +805,7 @@ bgp_write (struct thread *thread) /* For non-blocking IO check. */ if (peer->status == Connect) { - bgp_connect_check (peer); + bgp_connect_check (peer, 1); return 0; } @@ -698,6 +815,8 @@ bgp_write (struct thread *thread) sockopt_cork (peer->fd, 1); + oc = peer->update_out; + /* Nonblocking write until TCP output buffer is full. */ do { @@ -765,13 +884,17 @@ bgp_write (struct thread *thread) /* OK we send packet so delete it. */ bgp_packet_delete (peer); } - while (++count < BGP_WRITE_PACKET_MAX && + while (++count < peer->bgp->wpkt_quanta && (s = bgp_write_packet (peer)) != NULL); - + if (bgp_write_proceed (peer)) BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); done: + /* Update the last write if some updates were written. */ + if (peer->update_out > oc) + peer->last_write = bgp_clock (); + sockopt_cork (peer->fd, 0); return 0; } @@ -826,6 +949,8 @@ bgp_write_notify (struct peer *peer) if (peer->v_start >= (60 * 2)) peer->v_start = (60 * 2); + /* Handle Graceful Restart case where the state changes to + Connect instead of Idle */ BGP_EVENT_ADD (peer, BGP_Stop); return 0; @@ -836,7 +961,6 @@ void bgp_keepalive_send (struct peer *peer) { struct stream *s; - int length; s = stream_new (BGP_MAX_PACKET_SIZE); @@ -844,16 +968,13 @@ bgp_keepalive_send (struct peer *peer) bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE); /* Set packet size. */ - length = bgp_packet_set_size (s); + (void)bgp_packet_set_size (s); /* Dump packet if debug option is set. */ /* bgp_packet_dump (s); */ - if (BGP_DEBUG (keepalive, KEEPALIVE)) + if (bgp_debug_keepalive(peer)) zlog_debug ("%s sending KEEPALIVE", peer->host); - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s send message type %d, length (incl. header) %d", - peer->host, BGP_MSG_KEEPALIVE, length); /* Add packet to the peer. */ bgp_packet_add (peer, s); @@ -866,7 +987,6 @@ void bgp_open_send (struct peer *peer) { struct stream *s; - int length; u_int16_t send_holdtime; as_t local_as; @@ -897,17 +1017,13 @@ bgp_open_send (struct peer *peer) bgp_open_capability (s, peer); /* Set BGP packet length. */ - length = bgp_packet_set_size (s); + (void)bgp_packet_set_size (s); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s", peer->host, BGP_VERSION_4, local_as, send_holdtime, inet_ntoa (peer->local_id)); - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s send message type %d, length (incl. header) %d", - peer->host, BGP_MSG_OPEN, length); - /* Dump packet if debug option is set. */ /* bgp_packet_dump (s); */ @@ -984,33 +1100,16 @@ bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code, } } - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s send message type %d, length (incl. header) %d", - peer->host, BGP_MSG_NOTIFY, length); - /* peer reset cause */ if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE) { if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET) - { peer->last_reset = PEER_DOWN_USER_RESET; - zlog_info ("Notification sent to neighbor %s: User reset", peer->host); - } else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN) - { peer->last_reset = PEER_DOWN_USER_SHUTDOWN; - zlog_info ("Notification sent to neighbor %s: shutdown", peer->host); - } else - { peer->last_reset = PEER_DOWN_NOTIFY_SEND; - zlog_info ("Notification sent to neighbor %s: type %u/%u", - peer->host, code, sub_code); - } } - else - zlog_info ("Notification sent to neighbor %s: configuration change", - peer->host); /* Call immediately. */ BGP_WRITE_OFF (peer->t_write); @@ -1031,7 +1130,6 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, u_char orf_type, u_char when_to_refresh, int remove) { struct stream *s; - int length; struct bgp_filter *filter; int orf_refresh = 0; @@ -1074,7 +1172,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, { UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND); stream_putc (s, ORF_COMMON_PART_REMOVE_ALL); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", peer->host, orf_type, (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), @@ -1086,7 +1184,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist, ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT, ORF_COMMON_PART_DENY); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", peer->host, orf_type, (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), @@ -1099,16 +1197,13 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, } /* Set packet size. */ - length = bgp_packet_set_size (s); + (void)bgp_packet_set_size (s); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) { if (! orf_refresh) zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d", peer->host, afi, safi); - zlog_debug ("%s send message type %d, length (incl. header) %d", - peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ? - BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length); } /* Add packet to the peer. */ @@ -1123,7 +1218,6 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi, int capability_code, int action) { struct stream *s; - int length; /* Adjust safi code. */ if (safi == SAFI_MPLS_VPN) @@ -1144,23 +1238,18 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi, stream_putc (s, 0); stream_putc (s, safi); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d", peer->host, action == CAPABILITY_ACTION_SET ? "Advertising" : "Removing", afi, safi); } /* Set packet size. */ - length = bgp_packet_set_size (s); - + (void)bgp_packet_set_size (s); /* Add packet to the peer. */ bgp_packet_add (peer, s); - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s send message type %d, length (incl. header) %d", - peer->host, BGP_MSG_CAPABILITY, length); - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); } @@ -1169,13 +1258,7 @@ static int bgp_collision_detect (struct peer *new, struct in_addr remote_id) { struct peer *peer; - struct listnode *node, *nnode; - struct bgp *bgp; - bgp = bgp_get_default (); - if (! bgp) - return 0; - /* Upon receipt of an OPEN message, the local system must examine all of its connections that are in the OpenConfirm state. A BGP speaker may also examine connections in an OpenSent state if it @@ -1185,31 +1268,42 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id) OPEN message, then the local system performs the following collision resolution procedure: */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + if ((peer = new->doppelganger) != NULL) { - /* Under OpenConfirm status, local peer structure already hold - remote router ID. */ - - if (peer != new - && (peer->status == OpenConfirm || peer->status == OpenSent) - && sockunion_same (&peer->su, &new->su)) + /* Do not accept the new connection in Established or Clearing states. + * Note that a peer GR is handled by closing the existing connection + * upon receipt of new one. + */ + if (peer->status == Established || peer->status == Clearing) + { + bgp_notify_send (new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return (-1); + } + else if ((peer->status == OpenConfirm) || (peer->status == OpenSent)) { /* 1. The BGP Identifier of the local system is compared to the BGP Identifier of the remote system (as specified in the OPEN message). */ if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr)) - { - /* 2. If the value of the local BGP Identifier is less - than the remote one, the local system closes BGP - connection that already exists (the one that is - already in the OpenConfirm state), and accepts BGP - connection initiated by the remote system. */ - - if (peer->fd >= 0) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return 1; - } + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) + { + /* 2. If the value of the local BGP Identifier is less + than the remote one, the local system closes BGP + connection that already exists (the one that is + already in the OpenConfirm state), and accepts BGP + connection initiated by the remote system. */ + bgp_notify_send (peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return 1; + } + else + { + bgp_notify_send (new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return -1; + } else { /* 3. Otherwise, the local system closes newly created @@ -1217,11 +1311,18 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id) received OPEN message), and continues to use the existing one (the one that is already in the OpenConfirm state). */ - - if (new->fd >= 0) - bgp_notify_send (new, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return -1; + if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) + { + bgp_notify_send (peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return 1; + } + else + { + bgp_notify_send (new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return -1; + } } } } @@ -1238,24 +1339,23 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) u_int16_t send_holdtime; as_t remote_as; as_t as4 = 0; - struct peer *realpeer; struct in_addr remote_id; int mp_capability; u_int8_t notify_data_remote_as[2]; u_int8_t notify_data_remote_id[4]; + u_int16_t *holdtime_ptr; - realpeer = NULL; - /* Parse open packet. */ version = stream_getc (peer->ibuf); memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2); remote_as = stream_getw (peer->ibuf); + holdtime_ptr = (u_int16_t *)stream_pnt (peer->ibuf); holdtime = stream_getw (peer->ibuf); memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4); remote_id.s_addr = stream_get_ipv4 (peer->ibuf); /* Receive OPEN message log */ - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u," " holdtime %d, id %s", peer->host, version, remote_as, holdtime, @@ -1294,8 +1394,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) { zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS); + bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS); return -1; } @@ -1325,154 +1425,12 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) } } - /* Lookup peer from Open packet. */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - int as = 0; - - realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as); - - if (! realpeer) - { - /* Peer's source IP address is check in bgp_accept(), so this - must be AS number mismatch or remote-id configuration - mismatch. */ - if (as) - { - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s bad OPEN, wrong router identifier %s", - peer->host, inet_ntoa (remote_id)); - bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_BGP_IDENT, - notify_data_remote_id, 4); - } - else - { - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s bad OPEN, remote AS is %u, expected %u", - peer->host, remote_as, peer->as); - bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as, 2); - } - return -1; - } - } - - /* When collision is detected and this peer is closed. Retrun - immidiately. */ - ret = bgp_collision_detect (peer, remote_id); - if (ret < 0) - return ret; - - /* Hack part. */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - if (realpeer->status == Established - && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE)) - { - realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; - SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT); - } - else if (ret == 0 && realpeer->status != Active - && realpeer->status != OpenSent - && realpeer->status != OpenConfirm - && realpeer->status != Connect) - { - /* XXX: This is an awful problem.. - * - * According to the RFC we should just let this connection (of the - * accepted 'peer') continue on to Established if the other - * connection (the 'realpeer' one) is in state Connect, and deal - * with the more larval FSM as/when it gets far enough to receive - * an Open. We don't do that though, we instead close the (more - * developed) accepted connection. - * - * This means there's a race, which if hit, can loop: - * - * FSM for A FSM for B - * realpeer accept-peer realpeer accept-peer - * - * Connect Connect - * Active - * OpenSent OpenSent - * <arrive here, - * Notify, delete> - * Idle Active - * OpenSent OpenSent - * <arrive here, - * Notify, delete> - * Idle - * <wait> <wait> - * Connect Connect - * - * - * If both sides are Quagga, they're almost certain to wait for - * the same amount of time of course (which doesn't preclude other - * implementations also waiting for same time). The race is - * exacerbated by high-latency (in bgpd and/or the network). - * - * The reason we do this is because our FSM is tied to our peer - * structure, which carries our configuration information, etc. - * I.e. we can't let the accepted-peer FSM continue on as it is, - * cause it's not associated with any actual peer configuration - - * it's just a dummy. - * - * It's possible we could hack-fix this by just bgp_stop'ing the - * realpeer and continueing on with the 'transfer FSM' below. - * Ideally, we need to seperate FSMs from struct peer. - * - * Setting one side to passive avoids the race, as a workaround. - */ - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("%s peer status is %s close connection", - realpeer->host, LOOKUP (bgp_status_msg, - realpeer->status)); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONNECT_REJECT); - - return -1; - } - - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)", - peer->host, - LOOKUP (bgp_status_msg, realpeer->status)); - - bgp_stop (realpeer); - - /* Transfer file descriptor. */ - realpeer->fd = peer->fd; - peer->fd = -1; - - /* Transfer input buffer. */ - stream_free (realpeer->ibuf); - realpeer->ibuf = peer->ibuf; - realpeer->packet_size = peer->packet_size; - peer->ibuf = NULL; - - /* Transfer status. */ - realpeer->status = peer->status; - bgp_stop (peer); - - /* peer pointer change. Open packet send to neighbor. */ - peer = realpeer; - bgp_open_send (peer); - if (peer->fd < 0) - { - zlog_err ("bgp_open_receive peer's fd is negative value %d", - peer->fd); - return -1; - } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); - } - /* remote router-id check. */ if (remote_id.s_addr == 0 || IPV4_CLASS_DE (ntohl (remote_id.s_addr)) || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr)) { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s bad OPEN, wrong router identifier %s", peer->host, inet_ntoa (remote_id)); bgp_notify_send_with_data (peer, @@ -1490,7 +1448,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) { u_int16_t maxver = htons(BGP_VERSION_4); /* XXX this reply may not be correct if version < 4 XXX */ - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s bad protocol version, remote requested %d, local request %d", peer->host, version, BGP_VERSION_4); /* Data must be in network byte order here */ @@ -1504,7 +1462,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) /* Check neighbor as number. */ if (remote_as != peer->as) { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s bad OPEN, remote AS is %u, expected %u", peer->host, remote_as, peer->as); bgp_notify_send_with_data (peer, @@ -1522,9 +1480,10 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) if (holdtime < 3 && holdtime != 0) { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNACEP_HOLDTIME); + bgp_notify_send_with_data (peer, + BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, + (u_int8_t *)holdtime_ptr, 2); return -1; } @@ -1559,7 +1518,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) } else { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0", peer->host); } @@ -1578,11 +1537,28 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST]; } + /* When collision is detected and this peer is closed. Retrun + immidiately. */ + ret = bgp_collision_detect (peer, remote_id); + if (ret < 0) + return ret; + /* Get sockname. */ - bgp_getsockname (peer); + if ((ret = bgp_getsockname (peer)) < 0) + { + zlog_err("%s: bgp_getsockname() failed for peer: %s", __FUNCTION__, + peer->host); + return (ret); + } peer->rtt = sockopt_tcp_rtt (peer->fd); - BGP_EVENT_ADD (peer, Receive_OPEN_message); + if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0) + { + zlog_err("%s: BGP event update failed for peer: %s", __FUNCTION__, + peer->host); + /* DD: bgp send notify and reset state */ + return (ret); + } peer->packet_size = 0; if (peer->ibuf) @@ -1609,6 +1585,117 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) return -1; } +/* Called when there is a change in the EOR(implicit or explicit) status of a peer. + Ends the update-delay if all expected peers are done with EORs. */ +void +bgp_check_update_delay(struct bgp *bgp) +{ + struct listnode *node, *nnode; + struct peer *peer = NULL; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("Checking update delay, T: %d R: %d I:%d E: %d", bgp->established, + bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors); + + if (bgp->established <= + bgp->restarted_peers + bgp->implicit_eors + bgp->explicit_eors) + { + /* This is an extra sanity check to make sure we wait for all the + eligible configured peers. This check is performed if establish wait + timer is on, or establish wait option is not given with the + update-delay command */ + if (bgp->t_establish_wait || + (bgp->v_establish_wait == bgp->v_update_delay)) + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) + && !CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN) + && !peer->update_delay_over) + { + if (bgp_debug_neighbor_events(peer)) + zlog_debug (" Peer %s pending, continuing read-only mode", + peer->host); + return; + } + } + + zlog_info ("Update delay ended, restarted: %d, EORs implicit: %d, explicit: %d", + bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors); + bgp_update_delay_end(bgp); + } +} + +/* Called if peer is known to have restarted. The restart-state bit in + Graceful-Restart capability is used for that */ +void +bgp_update_restarted_peers (struct peer *peer) +{ + if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */ + if (peer->update_delay_over) return; /* This peer has already been considered */ + + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("Peer %s: Checking restarted", peer->host); + + if (peer->status == Established) + { + peer->update_delay_over = 1; + peer->bgp->restarted_peers++; + bgp_check_update_delay(peer->bgp); + } +} + +/* Called as peer receives a keep-alive. Determines if this occurence can be + taken as an implicit EOR for this peer. + NOTE: The very first keep-alive after the Established state of a peer is + considered implicit EOR for the update-delay purposes */ +void +bgp_update_implicit_eors (struct peer *peer) +{ + if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */ + if (peer->update_delay_over) return; /* This peer has already been considered */ + + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("Peer %s: Checking implicit EORs", peer->host); + + if (peer->status == Established) + { + peer->update_delay_over = 1; + peer->bgp->implicit_eors++; + bgp_check_update_delay(peer->bgp); + } +} + +/* Should be called only when there is a change in the EOR_RECEIVED status + for any afi/safi on a peer */ +static void +bgp_update_explicit_eors (struct peer *peer) +{ + afi_t afi; + safi_t safi; + + if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */ + if (peer->update_delay_over) return; /* This peer has already been considered */ + + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("Peer %s: Checking explicit EORs", peer->host); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + if (peer->afc_nego[afi][safi] && + !CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) + { + if (bgp_debug_neighbor_events(peer)) + zlog_debug (" afi %d safi %d didnt receive EOR", afi, safi); + return; + } + } + + peer->update_delay_over = 1; + peer->bgp->explicit_eors++; + bgp_check_update_delay(peer->bgp); +} + /* Parse BGP Update packet and make attribute object. */ static int bgp_update_receive (struct peer *peer, bgp_size_t size) @@ -1646,6 +1733,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) memset (&extra, 0, sizeof (struct attr_extra)); memset (&nlris, 0, sizeof nlris); attr.extra = &extra; + memset (peer->rcvd_attr_str, 0, BUFSIZ); + peer->rcvd_attr_printed = 0; s = peer->ibuf; end = stream_pnt (s) + size; @@ -1686,8 +1775,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) nlris[NLRI_WITHDRAW].nlri = stream_pnt (s); nlris[NLRI_WITHDRAW].length = withdraw_len; - if (BGP_DEBUG (packet, PACKET_RECV)) - zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host); + zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host); stream_forward_getp (s, withdraw_len); } @@ -1744,24 +1832,21 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) } /* Logging the attribute. */ - if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW - || BGP_DEBUG (update, UPDATE_IN)) + if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW || + BGP_DEBUG (update, UPDATE_IN) || + BGP_DEBUG (update, UPDATE_PREFIX)) { - char attrstr[BUFSIZ]; - attrstr[0] = '\0'; - - ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ); - int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW) - ? LOG_ERR : LOG_DEBUG; + ret = bgp_dump_attr (peer, &attr, peer->rcvd_attr_str, BUFSIZ); if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW) - zlog (peer->log, LOG_ERR, - "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.", - peer->host); + zlog_err ("%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.", + peer->host); - if (ret) - zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s", - peer->host, attrstr); + if (ret && bgp_debug_update(peer, NULL, 1)) + { + zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } } /* Network Layer Reachability Information. */ @@ -1796,8 +1881,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) */ if (!bgp_afi_safi_valid_indices (nlris[i].afi, &nlris[i].safi)) { - plog_info (peer->log, - "%s [Info] UPDATE with unsupported AFI/SAFI %u/%u", + zlog_info ("%s [Info] UPDATE with unsupported AFI/SAFI %u/%u", peer->host, nlris[i].afi, nlris[i].safi); continue; } @@ -1806,8 +1890,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) Address Family and Subsequent Address Family. */ if (!peer->afc[nlris[i].afi][nlris[i].safi]) { - plog_info (peer->log, - "%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u", + zlog_info ("%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u", peer->host, nlris[i].afi, nlris[i].safi); continue; } @@ -1829,8 +1912,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) if (nlri_ret < 0) { - plog_err (peer->log, - "%s [Error] Error parsing NLRI", peer->host); + zlog_err ("%s [Error] Error parsing NLRI", peer->host); if (peer->status == Established) bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, i <= NLRI_WITHDRAW @@ -1877,14 +1959,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) /* End-of-RIB received */ SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED); + if (!CHECK_FLAG (peer->af_sflags[afi][safi], + PEER_STATUS_EOR_RECEIVED)) + { + SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST], + PEER_STATUS_EOR_RECEIVED); + bgp_update_explicit_eors(peer); + } /* NSF delete stale route */ if (peer->nsf[afi][safi]) bgp_clear_stale_route (peer, afi, safi); - if (BGP_DEBUG (normal, NORMAL)) - zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for %s from %s", - peer->host, afi_safi_print (afi, safi)); + zlog_debug ("rcvd End-of-RIB for %s from %s", + peer->host, afi_safi_print (afi, safi)); } } @@ -1991,7 +2079,7 @@ bgp_notify_receive (struct peer *peer, bgp_size_t size) static void bgp_keepalive_receive (struct peer *peer, bgp_size_t size) { - if (BGP_DEBUG (keepalive, KEEPALIVE)) + if (bgp_debug_keepalive(peer)) zlog_debug ("%s KEEPALIVE rcvd", peer->host); BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message); @@ -2008,7 +2096,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) /* If peer does not have the capability, send notification. */ if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV)) { - plog_err (peer->log, "%s [Error] BGP route refresh is not enabled", + zlog_err ("%s [Error] BGP route refresh is not enabled", peer->host); bgp_notify_send (peer, BGP_NOTIFY_HEADER_ERR, @@ -2019,8 +2107,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) /* Status must be Established. */ if (peer->status != Established) { - plog_err (peer->log, - "%s [Error] Route refresh packet received under status %s", + zlog_err ("%s [Error] Route refresh packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status)); bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0); return; @@ -2034,7 +2121,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) stream_getc (s); safi = stream_getc (s); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_update(peer, NULL, 0)) zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d", peer->host, afi, safi); @@ -2043,11 +2130,8 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_MPLS_LABELED_VPN)) { - if (BGP_DEBUG (normal, NORMAL)) - { - zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored", - peer->host, afi, safi); - } + zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored", + peer->host, afi, safi); return; } @@ -2092,7 +2176,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) char name[BUFSIZ]; int ret; - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) { zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d", peer->host, orf_type, orf_len); @@ -2119,7 +2203,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) /* after ++: p_pnt <= p_end */ if (common & ORF_COMMON_PART_REMOVE_ALL) { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host); prefix_bgp_orf_remove_all (afi, name); break; @@ -2158,7 +2242,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) memcpy (&orfp.p.u.prefix, p_pnt, psize); p_pnt += psize; - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) { char buf[INET6_BUFSIZ]; @@ -2179,9 +2263,8 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) if (!ok || (ok && ret != CMD_SUCCESS)) { - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s Received misformatted prefixlist ORF." - " Remove All pfxlist", peer->host); + zlog_info ("%s Received misformatted prefixlist ORF." + " Remove All pfxlist", peer->host); prefix_bgp_orf_remove_all (afi, name); break; } @@ -2191,7 +2274,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) } stream_forward_getp (s, orf_len); } - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcvd Refresh %s ORF request", peer->host, when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate"); if (when_to_refresh == REFRESH_DEFER) @@ -2240,7 +2323,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) return -1; } - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u", peer->host, action, hdr->code, hdr->length); @@ -2267,14 +2350,14 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) if (!bgp_afi_safi_valid_indices (afi, &safi)) { - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid " "(%u/%u)", peer->host, afi, safi); continue; } /* Address family check. */ - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u", peer->host, action == CAPABILITY_ACTION_SET @@ -2323,13 +2406,13 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size) /* Fetch pointer. */ pnt = stream_pnt (peer->ibuf); - if (BGP_DEBUG (normal, NORMAL)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcv CAPABILITY", peer->host); /* If peer does not have the capability, send notification. */ if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV)) { - plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled", + zlog_err ("%s [Error] BGP dynamic capability is not enabled", peer->host); bgp_notify_send (peer, BGP_NOTIFY_HEADER_ERR, @@ -2340,8 +2423,8 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size) /* Status must be Established. */ if (peer->status != Established) { - plog_err (peer->log, - "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status)); + zlog_err ("%s [Error] Dynamic capability packet received under status %s", + peer->host, LOOKUP (bgp_status_msg, peer->status)); bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0); return -1; } @@ -2373,8 +2456,8 @@ bgp_read_packet (struct peer *peer) if (nbytes == -2) return -1; - plog_err (peer->log, "%s [Error] bgp_read_packet error: %s", - peer->host, safe_strerror (errno)); + zlog_err ("%s [Error] bgp_read_packet error: %s", + peer->host, safe_strerror (errno)); if (peer->status == Established) { @@ -2394,9 +2477,9 @@ bgp_read_packet (struct peer *peer) /* When read byte is zero : clear bgp peer and return */ if (nbytes == 0) { - if (BGP_DEBUG (events, EVENTS)) - plog_debug (peer->log, "%s [Event] BGP connection closed fd %d", - peer->host, peer->fd); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s [Event] BGP connection closed fd %d", + peer->host, peer->fd); if (peer->status == Established) { @@ -2451,15 +2534,19 @@ bgp_read (struct thread *thread) struct peer *peer; bgp_size_t size; char notify_data_length[2]; + u_int32_t notify_out; /* Yes first of all get peer pointer. */ peer = THREAD_ARG (thread); peer->t_read = NULL; + /* Note notify_out so we can check later to see if we sent another one */ + notify_out = peer->notify_out; + /* For non-blocking IO check. */ if (peer->status == Connect) { - bgp_connect_check (peer); + bgp_connect_check (peer, 1); goto done; } else @@ -2490,10 +2577,6 @@ bgp_read (struct thread *thread) size = stream_getw (peer->ibuf); type = stream_getc (peer->ibuf); - if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0) - zlog_debug ("%s rcv message type %d, length (excl. header) %d", - peer->host, type, size - BGP_HEADER_SIZE); - /* Marker check */ if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE)) && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE)) @@ -2511,10 +2594,9 @@ bgp_read (struct thread *thread) && type != BGP_MSG_ROUTE_REFRESH_OLD && type != BGP_MSG_CAPABILITY) { - if (BGP_DEBUG (normal, NORMAL)) - plog_debug (peer->log, - "%s unknown message type 0x%02x", - peer->host, type); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s unknown message type 0x%02x", + peer->host, type); bgp_notify_send_with_data (peer, BGP_NOTIFY_HEADER_ERR, BGP_NOTIFY_HEADER_BAD_MESTYPE, @@ -2532,12 +2614,11 @@ bgp_read (struct thread *thread) || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE) || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE)) { - if (BGP_DEBUG (normal, NORMAL)) - plog_debug (peer->log, - "%s bad message length - %d for %s", - peer->host, size, - type == 128 ? "ROUTE-REFRESH" : - bgp_type_str[(int) type]); + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s bad message length - %d for %s", + peer->host, size, + type == 128 ? "ROUTE-REFRESH" : + bgp_type_str[(int) type]); bgp_notify_send_with_data (peer, BGP_NOTIFY_HEADER_ERR, BGP_NOTIFY_HEADER_BAD_MESLEN, @@ -2591,17 +2672,30 @@ bgp_read (struct thread *thread) break; } + /* If reading this packet caused us to send a NOTIFICATION then store a copy + * of the packet for troubleshooting purposes + */ + if (notify_out < peer->notify_out) + { + memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size); + peer->last_reset_cause_size = peer->packet_size; + notify_out = peer->notify_out; + } + /* Clear input buffer. */ peer->packet_size = 0; if (peer->ibuf) stream_reset (peer->ibuf); done: - if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) + /* If reading this packet caused us to send a NOTIFICATION then store a copy + * of the packet for troubleshooting purposes + */ + if (notify_out < peer->notify_out) { - if (BGP_DEBUG (events, EVENTS)) - zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host); - peer_delete (peer); + memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size); + peer->last_reset_cause_size = peer->packet_size; } + return 0; } diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h index 6b0b7f4d..0e490cf7 100644 --- a/bgpd/bgp_packet.h +++ b/bgpd/bgp_packet.h @@ -26,6 +26,12 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define BGP_UNFEASIBLE_LEN 2U #define BGP_WRITE_PACKET_MAX 10U +/* Size of FIFOs upon which write thread is triggered. Note that write + * thread is also triggered upon BGP work-queue completion. + */ +#define BGP_ADV_FIFO_QUANTA 500 +#define BGP_WD_FIFO_QUANTA 200 + /* When to refresh */ #define REFRESH_IMMEDIATE 1 #define REFRESH_DEFER 2 @@ -40,6 +46,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA /* Packet send and receive function prototypes. */ extern int bgp_read (struct thread *); extern int bgp_write (struct thread *); +extern int bgp_connect_check (struct peer *, int change_state); extern void bgp_keepalive_send (struct peer *); extern void bgp_open_send (struct peer *); @@ -56,4 +63,10 @@ extern int bgp_capability_receive (struct peer *, bgp_size_t); extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *); +extern void bgp_update_restarted_peers (struct peer *); +extern void bgp_update_implicit_eors (struct peer *); +extern void bgp_check_update_delay (struct bgp *); +extern int bgp_peer_wd_fifo_exists (struct peer *); +extern int bgp_peer_adv_fifo_exists (struct peer *, int); +extern void bgp_peer_schedule_updates(struct peer *peer); #endif /* _QUAGGA_BGP_PACKET_H */ diff --git a/bgpd/bgp_regex.c b/bgpd/bgp_regex.c index 13fa8295..d96f74ce 100644 --- a/bgpd/bgp_regex.c +++ b/bgpd/bgp_regex.c @@ -24,6 +24,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "command.h" #include "memory.h" #include "filter.h" +#include "linklist.h" +#include "prefix.h" #include "bgpd.h" #include "bgp_aspath.h" diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c364372f..4bd6b842 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -55,6 +55,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_zebra.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_mpath.h" +#include "bgpd/bgp_nht.h" /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; @@ -126,20 +127,14 @@ bgp_info_extra_get (struct bgp_info *ri) return ri->extra; } -/* Allocate new bgp info structure. */ -static struct bgp_info * -bgp_info_new (void) -{ - return XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); -} - /* Free bgp route information. */ static void bgp_info_free (struct bgp_info *binfo) { if (binfo->attr) bgp_attr_unintern (&binfo->attr); - + + bgp_unlink_nexthop(binfo); bgp_info_extra_free (&binfo->extra); bgp_info_mpath_free (&binfo->mpath); @@ -252,7 +247,7 @@ bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) || ri->peer == ri->peer->bgp->peer_self) return; - if (BGP_INFO_HOLDDOWN (ri) + if (!BGP_INFO_COUNTABLE (ri) && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) { @@ -269,7 +264,7 @@ bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) zlog_warn ("%s: Please report to Quagga bugzilla", __func__); } } - else if (!BGP_INFO_HOLDDOWN (ri) + else if (BGP_INFO_COUNTABLE (ri) && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) { SET_FLAG (ri->flags, BGP_INFO_COUNTED); @@ -286,8 +281,8 @@ 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)) + /* early bath if we know it's not a flag that changes countability state */ + if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED)) return; bgp_pcount_adjust (rn, ri); @@ -298,8 +293,8 @@ 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)) + /* early bath if we know it's not a flag that changes countability state */ + if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED)) return; bgp_pcount_adjust (rn, ri); @@ -477,6 +472,27 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, if (newm > existm) return 1; + /* 8.1. Same IGP metric. Compare the cluster list length as + representative of IGP hops metric. Rewrite the metric value + pair (newm, existm) with the cluster list length. Prefer the + path with smaller cluster list length. */ + if (newm == existm) + { + struct bgp_maxpaths_cfg *mpath_cfg = &bgp->maxpaths[afi][safi]; + if (peer_sort (new->peer) == BGP_PEER_IBGP + && peer_sort (exist->peer) == BGP_PEER_IBGP + && CHECK_FLAG (mpath_cfg->ibgp_flags, + BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN)) + { + newm = BGP_CLUSTER_LIST_LENGTH(new->attr); + existm = BGP_CLUSTER_LIST_LENGTH(exist->attr); + if (newm < existm) + ret = 1; + if (newm > existm) + ret = 0; + } + } + /* 9. Maximum path check. */ if (bgp_mpath_is_configured (bgp, afi, safi)) { @@ -535,12 +551,8 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, return 1; /* 12. Cluster length comparision. */ - new_cluster = exist_cluster = 0; - - if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) - new_cluster = newattre->cluster->length; - if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) - exist_cluster = existattre->cluster->length; + new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr); + exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr); if (new_cluster < exist_cluster) return -1; @@ -582,7 +594,7 @@ 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))) \ - plog_warn (peer->log, "%s: Could not find configured input %s-list %s!", \ + zlog_warn ("%s: Could not find configured input %s-list %s!", \ peer->host, #f, F ## _IN_NAME(filter)); if (DISTRIBUTE_IN_NAME (filter)) { @@ -621,7 +633,7 @@ 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))) \ - plog_warn (peer->log, "%s: Could not find configured output %s-list %s!", \ + zlog_warn ("%s: Could not find configured output %s-list %s!", \ peer->host, #f, F ## _OUT_NAME(filter)); if (DISTRIBUTE_OUT_NAME (filter)) { @@ -694,11 +706,12 @@ bgp_cluster_filter (struct peer *peer, struct attr *attr) static int bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, - afi_t afi, safi_t safi) + afi_t afi, safi_t safi, const char *rmap_name) { struct bgp_filter *filter; struct bgp_info info; route_map_result_t ret; + struct route_map *rmap = NULL; filter = &peer->filter[afi][safi]; @@ -706,8 +719,18 @@ bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, if (peer->weight) (bgp_attr_extra_get (attr))->weight = peer->weight; + if (rmap_name) + { + rmap = route_map_lookup_by_name(rmap_name); + } + else + { + if (ROUTE_MAP_IN_NAME(filter)) + rmap = ROUTE_MAP_IN (filter); + } + /* Route map apply. */ - if (ROUTE_MAP_IN_NAME (filter)) + if (rmap) { /* Duplicate current value to new strucutre for modification. */ info.peer = peer; @@ -716,7 +739,56 @@ bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *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); + ret = route_map_apply (rmap, p, RMAP_BGP, &info); + + 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; + } + } + return RMAP_PERMIT; +} + +static int +bgp_output_modifier (struct peer *peer, struct prefix *p, struct attr *attr, + afi_t afi, safi_t safi, const char *rmap_name) +{ + struct bgp_filter *filter; + struct bgp_info info; + route_map_result_t ret; + struct route_map *rmap = NULL; + + filter = &peer->filter[afi][safi]; + + /* Apply default weight value. */ + if (peer->weight) + (bgp_attr_extra_get (attr))->weight = peer->weight; + + if (rmap_name) + { + rmap = route_map_lookup_by_name(rmap_name); + } + else + { + if (ROUTE_MAP_OUT_NAME(filter)) + rmap = ROUTE_MAP_OUT (filter); + } + + /* Route map apply. */ + if (rmap) + { + /* Duplicate current value to new strucutre for modification. */ + info.peer = peer; + info.attr = attr; + + SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); + + /* Apply BGP route map to the attribute. */ + ret = route_map_apply (rmap, p, RMAP_BGP, &info); peer->rmap_type = 0; @@ -799,6 +871,55 @@ bgp_import_modifier (struct peer *rsclient, struct peer *peer, return RMAP_PERMIT; } + +/* If this is an EBGP peer with remove-private-AS */ +static void +bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi, + struct peer *peer, struct attr *attr) +{ + if (peer->sort == BGP_PEER_EBGP && + peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)) + { + // Take action on the entire aspath + if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) + { + if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as); + + // The entire aspath consists of private ASNs so create an empty aspath + else if (aspath_private_as_check (attr->aspath)) + attr->aspath = aspath_empty_get (); + + // There are some public and some private ASNs, remove the private ASNs + else + attr->aspath = aspath_remove_private_asns (attr->aspath); + } + + // 'all' was not specified so the entire aspath must be private ASNs + // for us to do anything + else if (aspath_private_as_check (attr->aspath)) + { + if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as); + else + attr->aspath = aspath_empty_get (); + } + } +} + +/* If this is an EBGP peer with as-override */ +static void +bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi, + struct peer *peer, struct attr *attr) +{ + if (peer->sort == BGP_PEER_EBGP && + peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) + { + if (aspath_single_asn_check (attr->aspath, peer->as)) + attr->aspath = aspath_replace_specific_asn (attr->aspath, peer->as, bgp->as); + } +} + static int bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi) @@ -859,12 +980,11 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, { if (IPV4_ADDR_SAME (&peer->remote_id, &riattr->extra->originator_id)) { - 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, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (bgp_debug_update(peer, p, 0)) + zlog_debug("%s [Update:SEND] %s/%d originator-id is same as remote router-id", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); return 0; } } @@ -882,12 +1002,11 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* Output filter check. */ if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY) { - if (BGP_DEBUG (filter, FILTER)) - zlog (peer->log, LOG_DEBUG, - "%s [Update:SEND] %s/%d is filtered", - peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (bgp_debug_update(peer, p, 0)) + zlog_debug("%s [Update:SEND] %s/%d is filtered", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); return 0; } @@ -895,10 +1014,9 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* AS path loop check. */ if (aspath_loop_check (riattr->aspath, peer->as)) { - 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); + if (bgp_debug_update(peer, p, 0)) + zlog_debug("%s [Update:SEND] suppress announcement to peer AS %u is AS path.", + peer->host, peer->as); return 0; } #endif /* BGP_SEND_ASPATH_CHECK */ @@ -908,11 +1026,10 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, { if (aspath_loop_check(riattr->aspath, bgp->confed_id)) { - 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); + if (bgp_debug_update(peer, p, 0)) + zlog_debug("%s [Update:SEND] suppress announcement to peer AS %u is AS path.", + peer->host, + bgp->confed_id); return 0; } } @@ -1003,7 +1120,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, || (NEXTHOP_IS_V6 && IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) || (peer->sort == BGP_PEER_EBGP - && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0)) + && (bgp_multiaccess_check_v4 (attr->nexthop, peer) == 0))) { /* Set IPv4 nexthop. */ if (NEXTHOP_IS_V4) @@ -1063,11 +1180,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } - /* If this is EBGP peer and remove-private-AS is set. */ - if (peer->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 (); + bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); + bgp_peer_as_override(bgp, afi, safi, peer, attr); /* Route map & unsuppress-map apply. */ if (ROUTE_MAP_OUT_NAME (filter) @@ -1084,8 +1198,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* The route reflector is not allowed to modify the attributes of the reflected IBGP routes. */ - if (from->sort == BGP_PEER_IBGP - && peer->sort == BGP_PEER_IBGP) + if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) && + !bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { bgp_attr_dup (&dummy_attr, attr); info.attr = &dummy_attr; @@ -1119,9 +1233,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, struct bgp_info info; struct peer *from; struct attr *riattr; + struct bgp *bgp; from = ri->peer; filter = &rsclient->filter[afi][safi]; + bgp = rsclient->bgp; riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr; if (DISABLE_BGP_ANNOUNCE) @@ -1153,12 +1269,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, if (IPV4_ADDR_SAME (&rsclient->remote_id, &riattr->extra->originator_id)) { - if (BGP_DEBUG (filter, FILTER)) - zlog (rsclient->log, LOG_DEBUG, - "%s [Update:SEND] %s/%d originator-id is same as remote router-id", - rsclient->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (bgp_debug_update(rsclient, p, 0)) + zlog_debug ("%s [Update:SEND] %s/%d originator-id is same as remote router-id", + rsclient->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); return 0; } } @@ -1176,12 +1291,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, /* Output filter check. */ if (bgp_output_filter (rsclient, p, riattr, afi, safi) == FILTER_DENY) { - if (BGP_DEBUG (filter, FILTER)) - zlog (rsclient->log, LOG_DEBUG, - "%s [Update:SEND] %s/%d is filtered", - rsclient->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (bgp_debug_update(rsclient, p, 0)) + zlog_debug ("%s [Update:SEND] %s/%d is filtered", + rsclient->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); return 0; } @@ -1189,10 +1303,9 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, /* AS path loop check. */ if (aspath_loop_check (riattr->aspath, rsclient->as)) { - if (BGP_DEBUG (filter, FILTER)) - zlog (rsclient->log, LOG_DEBUG, - "%s [Update:SEND] suppress announcement to peer AS %u is AS path.", - rsclient->host, rsclient->as); + if (bgp_debug_update(rsclient, p, 0)) + zlog_debug ("%s [Update:SEND] suppress announcement to peer AS %u is AS path.", + rsclient->host, rsclient->as); return 0; } #endif /* BGP_SEND_ASPATH_CHECK */ @@ -1267,11 +1380,8 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, } - /* If this is EBGP peer and remove-private-AS is set. */ - if (rsclient->sort == BGP_PEER_EBGP - && peer_af_flag_check (rsclient, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) - && aspath_private_as_check (attr->aspath)) - attr->aspath = aspath_empty_get (); + bgp_peer_remove_private_as(bgp, afi, safi, rsclient, attr); + bgp_peer_as_override(bgp, afi, safi, rsclient, attr); /* Route map & unsuppress-map apply. */ if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) ) @@ -1536,8 +1646,23 @@ bgp_process_rsclient (struct work_queue *wq, void *data) struct bgp_info *old_select; struct bgp_info_pair old_and_new; struct listnode *node, *nnode; - struct peer *rsclient = bgp_node_table (rn)->owner; - + struct peer *rsclient; + + /* Is it end of initial update? (after startup) */ + if (!rn) + { + /* This is just to keep the display sane in case all the peers are + rsclients only */ + quagga_timestamp(3, bgp->update_delay_zebra_resume_time, + sizeof(bgp->update_delay_zebra_resume_time)); + + bgp->rsclient_peers_update_hold = 0; + bgp_start_routeadv(bgp); + return WQ_SUCCESS; + } + + rsclient = bgp_node_table (rn)->owner; + /* Best path selection. */ bgp_best_selection (bgp, rn, &old_and_new, afi, safi); new_select = old_and_new.new; @@ -1600,20 +1725,38 @@ bgp_process_main (struct work_queue *wq, void *data) struct bgp_info_pair old_and_new; struct listnode *node, *nnode; struct peer *peer; - + + /* Is it end of initial update? (after startup) */ + if (!rn) + { + quagga_timestamp(3, bgp->update_delay_zebra_resume_time, + sizeof(bgp->update_delay_zebra_resume_time)); + + bgp->main_zebra_update_hold = 0; + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + bgp_zebra_announce_table(bgp, afi, safi); + } + bgp->main_peers_update_hold = 0; + + bgp_start_routeadv(bgp); + return WQ_SUCCESS; + } + /* Best path selection. */ bgp_best_selection (bgp, rn, &old_and_new, afi, safi); 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 && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)) { if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED)) { if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) || CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG)) - bgp_zebra_announce (p, old_select, bgp, safi); + bgp_zebra_announce (p, old_select, bgp, afi, safi); UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); @@ -1621,6 +1764,9 @@ bgp_process_main (struct work_queue *wq, void *data) } } + /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set */ + UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); + if (old_select) bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED); if (new_select) @@ -1644,7 +1790,7 @@ bgp_process_main (struct work_queue *wq, void *data) if (new_select && new_select->type == ZEBRA_ROUTE_BGP && new_select->sub_type == BGP_ROUTE_NORMAL) - bgp_zebra_announce (p, new_select, bgp, safi); + bgp_zebra_announce (p, new_select, bgp, afi, safi); else { /* Withdraw the route from the kernel. */ @@ -1667,15 +1813,40 @@ static void bgp_processq_del (struct work_queue *wq, void *data) { struct bgp_process_queue *pq = data; - struct bgp_table *table = bgp_node_table (pq->rn); - + struct bgp_table *table; + bgp_unlock (pq->bgp); - bgp_unlock_node (pq->rn); - bgp_table_unlock (table); + if (pq->rn) + { + table = bgp_node_table (pq->rn); + bgp_unlock_node (pq->rn); + bgp_table_unlock (table); + } XFREE (MTYPE_BGP_PROCESS_QUEUE, pq); } static void +bgp_process_queue_complete (struct work_queue *wq) +{ + struct bgp *bgp; + struct peer *peer; + struct listnode *node, *nnode; + + /* Schedule write thread either directly or through the MRAI timer + * if needed. + */ + bgp = bgp_get_default (); + if (!bgp) + return; + + if (BGP_ROUTE_ADV_HOLD(bgp)) + return; + + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + bgp_peer_schedule_updates(peer); +} + +void bgp_process_queue_init (void) { bm->process_main_queue @@ -1691,8 +1862,11 @@ bgp_process_queue_init (void) 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.completion_func = &bgp_process_queue_complete; bm->process_main_queue->spec.max_retries = 0; bm->process_main_queue->spec.hold = 50; + /* Use a higher yield value of 50ms for main queue processing */ + bm->process_main_queue->spec.yield = 50 * 1000L; bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient; bm->process_rsclient_queue->spec.del_item_data = &bgp_processq_del; @@ -1753,6 +1927,36 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) return; } +void +bgp_add_eoiu_mark (struct bgp *bgp, bgp_table_t type) +{ + struct bgp_process_queue *pqnode; + + 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) + return; + + pqnode->rn = NULL; + pqnode->bgp = bgp; + bgp_lock (bgp); + switch (type) + { + case BGP_TABLE_MAIN: + work_queue_add (bm->process_main_queue, pqnode); + break; + case BGP_TABLE_RSCLIENT: + work_queue_add (bm->process_rsclient_queue, pqnode); + break; + } + + return; +} + static int bgp_maximum_prefix_restart_timer (struct thread *thread) { @@ -1761,11 +1965,11 @@ bgp_maximum_prefix_restart_timer (struct thread *thread) peer = THREAD_ARG (thread); peer->t_pmax_restart = NULL; - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Maximum-prefix restart timer expired, restore peering", peer->host); - peer_clear (peer); + peer_clear (peer, NULL); return 0; } @@ -1783,10 +1987,9 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, && ! always) return 0; - zlog (peer->log, LOG_INFO, - "%%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]); + zlog_info ("%%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)) @@ -1816,7 +2019,7 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, { peer->v_pmax_restart = peer->pmax_restart[afi][safi] * 60; - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Maximum-prefix restart timer started for %d secs", peer->host, peer->v_pmax_restart); @@ -1835,10 +2038,9 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, && ! always) return 0; - zlog (peer->log, LOG_INFO, - "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld", - afi_safi_print (afi, safi), peer->host, peer->pcount[afi][safi], - peer->pmax[afi][safi]); + zlog_info ("%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %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_THRESHOLD); } else @@ -1882,6 +2084,23 @@ bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, bgp_rib_remove (rn, ri, peer, afi, safi); } +static struct bgp_info * +info_make (int type, int sub_type, struct peer *peer, struct attr *attr, + struct bgp_node *rn) +{ + struct bgp_info *new; + + /* Make new BGP info. */ + new = XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); + new->type = type; + new->sub_type = sub_type; + new->peer = peer; + new->attr = attr; + new->uptime = bgp_clock (); + new->net = rn; + return new; +} + 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, @@ -1974,14 +2193,12 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, && attrhash_cmp (ri->attr, attr_new)) { - bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED); + if (bgp_debug_update(peer, p, 1)) + zlog_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); - if (BGP_DEBUG (update, UPDATE_IN)) - zlog (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); bgp_unlock_node (rn); bgp_attr_unintern (&attr_new); @@ -1994,11 +2211,11 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, 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); + if (bgp_debug_update(peer, p, 1)) + zlog_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. */ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); @@ -2021,21 +2238,15 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, } /* Received Logging. */ - if (BGP_DEBUG (update, UPDATE_IN)) + if (bgp_debug_update(peer, p, 1)) { - 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_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); } - /* 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 (); + new = info_make(type, sub_type, peer, attr_new, rn); /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) @@ -2057,12 +2268,11 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, filtered: /* This BGP update is filtered. Log the reason then update BGP entry. */ - if (BGP_DEBUG (update, UPDATE_IN)) - zlog (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); + if (bgp_debug_update(peer, p, 1)) + zlog_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); if (ri) bgp_rib_remove (rn, ri, peer, afi, safi); @@ -2094,11 +2304,10 @@ bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* Withdraw specified route from routing table. */ if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) bgp_rib_withdraw (rn, ri, peer, afi, safi, prd); - else if (BGP_DEBUG (update, UPDATE_IN)) - 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); + else if (bgp_debug_update(peer, p, 1)) + zlog_debug ("%s Can't find the route %s/%d", peer->host, + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); /* Unlock bgp_node_get() lock. */ bgp_unlock_node (rn); @@ -2120,6 +2329,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, struct bgp_info *new; const char *reason; char buf[SU_ADDRSTRLEN]; + int connected = 0; memset (&new_attr, 0, sizeof(struct attr)); memset (&new_extra, 0, sizeof(struct attr_extra)); @@ -2190,7 +2400,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, * NB: new_attr may now contain newly allocated values from route-map "set" * commands, so we need bgp_attr_flush in the error paths, until we intern * the attr (which takes over the memory references) */ - if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY) + if (bgp_input_modifier (peer, p, &new_attr, afi, safi, NULL) == RMAP_DENY) { reason = "route-map;"; bgp_attr_flush (&new_attr); @@ -2200,17 +2410,6 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* IPv4 unicast next hop check. */ if (afi == AFI_IP && safi == SAFI_UNICAST) { - /* If the peer is EBGP and nexthop is not on connected route, - discard it. */ - if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 - && ! bgp_nexthop_onlink (afi, &new_attr) - && ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) - { - reason = "non-connected next-hop;"; - bgp_attr_flush (&new_attr); - goto filtered; - } - /* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop must not be my own address. */ if (new_attr.nexthop.s_addr == 0 @@ -2234,17 +2433,15 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) && attrhash_cmp (ri->attr, attr_new)) { - bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) { - 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), - p->prefixlen); + if (bgp_debug_update(peer, p, 1)) + zlog_debug ("%s rcvd %s/%d", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED) { @@ -2254,12 +2451,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, } else /* Duplicate - odd */ { - if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, - "%s rcvd %s/%d...duplicate ignored", - peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (bgp_debug_update(peer, p, 1)) + { + if (!peer->rcvd_attr_printed) + { + zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } + + zlog_debug ("%s rcvd %s/%d...duplicate ignored", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + } /* graceful restart STALE flag unset. */ if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) @@ -2279,20 +2483,20 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Withdraw/Announce before we fully processed the withdraw */ 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", - peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (bgp_debug_update(peer, p, 1)) + zlog_debug ("%s rcvd %s/%d, flapped quicker than processing", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); bgp_info_restore (rn, ri); } /* Received Logging. */ - 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), - p->prefixlen); + if (bgp_debug_update(peer, p, 1)) + zlog_debug ("%s rcvd %s/%d", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); /* graceful restart STALE flag unset. */ if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) @@ -2340,20 +2544,29 @@ 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 == BGP_PEER_IBGP - || peer->sort == BGP_PEER_CONFED - || (peer->sort == BGP_PEER_EBGP && peer->ttl != 1) - || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))) + if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) { - if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL)) + if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && + ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) + connected = 1; + else + connected = 0; + + if (bgp_find_or_add_nexthop (afi, ri, NULL, connected)) bgp_info_set_flag (rn, ri, BGP_INFO_VALID); else - bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); + { + if (BGP_DEBUG(nht, NHT)) + { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); + } + bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); + } } else - bgp_info_set_flag (rn, ri, BGP_INFO_VALID); + bgp_info_set_flag (rn, ri, BGP_INFO_VALID); bgp_attr_flush (&new_attr); @@ -2367,38 +2580,48 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, } /* Received Logging. */ - if (BGP_DEBUG (update, UPDATE_IN)) + if (bgp_debug_update(peer, p, 1)) { - zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d", - peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (!peer->rcvd_attr_printed) + { + zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } + + zlog_debug ("%s rcvd %s/%d", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); } /* 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 (); + new = info_make(type, sub_type, peer, attr_new, rn); /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) memcpy ((bgp_info_extra_get (new))->tag, tag, 3); /* Nexthop reachability check. */ - if ((afi == AFI_IP || afi == AFI_IP6) - && safi == SAFI_UNICAST - && (peer->sort == BGP_PEER_IBGP - || peer->sort == BGP_PEER_CONFED - || (peer->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)) + if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) + { + if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && + ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) + connected = 1; + else + connected = 0; + + if (bgp_find_or_add_nexthop (afi, new, NULL, connected)) bgp_info_set_flag (rn, new, BGP_INFO_VALID); else - bgp_info_unset_flag (rn, new, BGP_INFO_VALID); + { + if (BGP_DEBUG(nht, NHT)) + { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); + } + bgp_info_unset_flag (rn, new, BGP_INFO_VALID); + } } else bgp_info_set_flag (rn, new, BGP_INFO_VALID); @@ -2427,12 +2650,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* This BGP update is filtered. Log the reason then update BGP entry. */ filtered: - if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, - "%s rcvd UPDATE about %s/%d -- DENIED due to: %s", - peer->host, - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, reason); + if (bgp_debug_update(peer, p, 1)) + { + if (!peer->rcvd_attr_printed) + { + zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } + + zlog_debug ("%s rcvd UPDATE about %s/%d -- DENIED due to: %s", + peer->host, + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen, reason); + } if (ri) bgp_rib_remove (rn, ri, peer, afi, safi); @@ -2495,11 +2725,11 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, && peer != bgp->peer_self) if (!bgp_adj_in_unset (rn, peer)) { - if (BGP_DEBUG (update, UPDATE_IN)) - zlog (peer->log, LOG_DEBUG, "%s withdrawing route %s/%d " - "not in adj-in", peer->host, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); + if (bgp_debug_update (peer, p, 1)) + zlog_debug ("%s withdrawing route %s/%d " + "not in adj-in", peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); bgp_unlock_node (rn); return 0; } @@ -2512,11 +2742,11 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, } /* Logging. */ - 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), - p->prefixlen); + if (bgp_debug_update(peer, p, 1)) + zlog_debug ("%s rcvd UPDATE about %s/%d -- withdrawn", + peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); /* Lookup withdrawn route. */ for (ri = rn->info; ri; ri = ri->next) @@ -2526,11 +2756,10 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, /* Withdraw specified route from routing table. */ if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) bgp_rib_withdraw (rn, ri, peer, afi, safi, prd); - else if (BGP_DEBUG (update, UPDATE_IN)) - 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); + else if (bgp_debug_update(peer, p, 1)) + zlog_debug ("%s Can't find the route %s/%d", peer->host, + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); /* Unlock bgp_node_get() lock. */ bgp_unlock_node (rn); @@ -2701,6 +2930,12 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) bgp_announce_table (peer, afi, safi, NULL, 1); + + /* + * The write thread needs to be scheduled since it may not be done as + * part of building adj_out. + */ + bgp_peer_schedule_updates(peer); } void @@ -3261,8 +3496,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, /* Prefix length check. */ if (p.prefixlen > prefix_blen (&p) * 8) { - plog_err (peer->log, - "%s [Error] Update packet error" + zlog_err ("%s [Error] Update packet error" " (wrong prefix length %u for afi %u)", peer->host, p.prefixlen, packet->afi); return -1; @@ -3274,8 +3508,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, /* When packet overflow occur return immediately. */ if (pnt + psize > lim) { - plog_err (peer->log, - "%s [Error] Update packet error" + zlog_err ("%s [Error] Update packet error" " (prefix length %u overflows packet)", peer->host, p.prefixlen); return -1; @@ -3284,8 +3517,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, /* Defensive coding, double-check the psize fits in a struct prefix */ if (psize > (ssize_t) sizeof(p.u)) { - plog_err (peer->log, - "%s [Error] Update packet error" + zlog_err ("%s [Error] Update packet error" " (prefix length %u too large for prefix storage %zu!?!!", peer->host, p.prefixlen, sizeof(p.u)); return -1; @@ -3306,9 +3538,8 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, * (e.g., an unexpected multicast IP address), an error SHOULD * be logged locally, and the prefix SHOULD be ignored. */ - zlog (peer->log, LOG_ERR, - "%s: IPv4 unicast NLRI is multicast address %s, ignoring", - peer->host, inet_ntoa (p.u.prefix4)); + zlog_err ("IPv4 unicast NLRI is multicast address %s", + inet_ntoa (p.u.prefix4)); continue; } } @@ -3320,18 +3551,15 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, { char buf[BUFSIZ]; - zlog (peer->log, LOG_ERR, - "%s: IPv6 unicast NLRI is link-local address %s, ignoring", - peer->host, - inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); + zlog_warn ("IPv6 link-local NLRI received %s ignore this NLRI", + inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); continue; } if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6)) { char buf[BUFSIZ]; - zlog (peer->log, LOG_ERR, - "%s: IPv6 unicast NLRI is multicast address %s, ignoring", + zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring", peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); continue; @@ -3355,8 +3583,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, /* Packet length consistency check. */ if (pnt != lim) { - plog_err (peer->log, - "%s [Error] Update packet error" + zlog_err ("%s [Error] Update packet error" " (prefix length mismatch with total length)", peer->host); return -1; @@ -3480,11 +3707,10 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, == RMAP_DENY) { /* 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); + if (bgp_debug_update(rsclient, p, 1)) + zlog_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; @@ -3530,6 +3756,23 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, ri->attr = attr_new; ri->uptime = bgp_clock (); + /* Nexthop reachability check. */ + if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) + { + if (bgp_find_or_add_nexthop (afi, ri, NULL, 0)) + bgp_info_set_flag (rn, ri, BGP_INFO_VALID); + else + { + if (BGP_DEBUG(nht, NHT)) + { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, (const void *)&attr_new->nexthop, + buf1, INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); + } + bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); + } + } /* Process change. */ bgp_process (bgp, rn, afi, safi); bgp_unlock_node (rn); @@ -3538,15 +3781,29 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, 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 (); + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, + attr_new, rn); + /* Nexthop reachability check. */ + if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) + { + if (bgp_find_or_add_nexthop (afi, new, NULL, 0)) + bgp_info_set_flag (rn, new, BGP_INFO_VALID); + else + { + if (BGP_DEBUG(nht, NHT)) + { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, (const void *)&attr_new->nexthop, + buf1, INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); + } + bgp_info_unset_flag (rn, new, BGP_INFO_VALID); + } + } + else + bgp_info_set_flag (rn, new, BGP_INFO_VALID); /* Register new BGP information. */ bgp_info_add (rn, new); @@ -3564,7 +3821,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, static void bgp_static_update_main (struct bgp *bgp, struct prefix *p, - struct bgp_static *bgp_static, afi_t afi, safi_t safi) + struct bgp_static *bgp_static, afi_t afi, safi_t safi) { struct bgp_node *rn; struct bgp_info *ri; @@ -3648,6 +3905,23 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, ri->attr = attr_new; ri->uptime = bgp_clock (); + /* Nexthop reachability check. */ + if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) + { + if (bgp_find_or_add_nexthop (afi, ri, NULL, 0)) + bgp_info_set_flag (rn, ri, BGP_INFO_VALID); + else + { + if (BGP_DEBUG(nht, NHT)) + { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, (const void *)&attr_new->nexthop, + buf1, INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); + } + bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); + } + } /* Process change. */ bgp_aggregate_increment (bgp, p, ri, afi, safi); bgp_process (bgp, rn, afi, safi); @@ -3659,13 +3933,27 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, } /* 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 (); + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, attr_new, + rn); + /* Nexthop reachability check. */ + if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) + { + if (bgp_find_or_add_nexthop (afi, new, NULL, 0)) + bgp_info_set_flag (rn, new, BGP_INFO_VALID); + else + { + if (BGP_DEBUG(nht, NHT)) + { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, + INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); + } + bgp_info_unset_flag (rn, new, BGP_INFO_VALID); + } + } + else + bgp_info_set_flag (rn, new, BGP_INFO_VALID); /* Aggregate address increment. */ bgp_aggregate_increment (bgp, p, new, afi, safi); @@ -3706,8 +3994,14 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, { struct bgp_node *rn; struct bgp_info *ri; + struct bgp_info *new; - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL); + /* Make new BGP info. */ + rn = bgp_node_get (bgp->rib[afi][safi], p); + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, + bgp_attr_default_intern(BGP_ORIGIN_IGP), rn); + + SET_FLAG (new->flags, BGP_INFO_VALID); /* Check selected route and self inserted route. */ for (ri = rn->info; ri; ri = ri->next) @@ -3720,6 +4014,7 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, if (ri) { bgp_aggregate_decrement (bgp, p, ri, afi, safi); + bgp_unlink_nexthop(ri); bgp_info_delete (rn, ri); bgp_process (bgp, rn, afi, safi); } @@ -3877,13 +4172,9 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p, /* Make new BGP info. */ - new = bgp_info_new (); - new->type = ZEBRA_ROUTE_BGP; - new->sub_type = BGP_ROUTE_STATIC; - new->peer = bgp->peer_self; - new->attr = attr_new; + new = info_make (ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, + attr_new, rn); SET_FLAG (new->flags, BGP_INFO_VALID); - new->uptime = bgp_clock (); new->extra = bgp_info_extra_new(); memcpy (new->extra->tag, bgp_static->tag, 3); @@ -3982,17 +4273,12 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str, rn->info = bgp_static; } - /* If BGP scan is not enabled, we should install this route here. */ - if (! bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) - { - bgp_static->valid = 1; - - if (need_update) - bgp_static_withdraw (bgp, &p, afi, safi); + bgp_static->valid = 1; + if (need_update) + bgp_static_withdraw (bgp, &p, afi, safi); - if (! bgp_static->backdoor) - bgp_static_update (bgp, &p, bgp_static, afi, safi); - } + if (! bgp_static->backdoor) + bgp_static_update (bgp, &p, bgp_static, afi, safi); return CMD_SUCCESS; } @@ -4242,6 +4528,84 @@ bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str, return CMD_SUCCESS; } +static int +bgp_table_map_set (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, + const char *rmap_name) +{ + struct bgp_rmap *rmap; + + rmap = &bgp->table_map[afi][safi]; + if (rmap_name) + { + if (rmap->name) + free (rmap->name); + rmap->name = strdup (rmap_name); + rmap->map = route_map_lookup_by_name (rmap_name); + } + else + { + if (rmap->name) + free (rmap->name); + rmap->name = NULL; + rmap->map = NULL; + } + + bgp_zebra_announce_table(bgp, afi, safi); + + return CMD_SUCCESS; +} + +static int +bgp_table_map_unset (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, + const char *rmap_name) +{ + struct bgp_rmap *rmap; + + rmap = &bgp->table_map[afi][safi]; + if (rmap->name) + free (rmap->name); + rmap->name = NULL; + rmap->map = NULL; + + bgp_zebra_announce_table(bgp, afi, safi); + + return CMD_SUCCESS; +} + +int +bgp_config_write_table_map (struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) +{ + if (bgp->table_map[afi][safi].name) + { + bgp_config_write_family_header (vty, afi, safi, write); + vty_out (vty, " table-map %s%s", + bgp->table_map[afi][safi].name, VTY_NEWLINE); + } + + return 0; +} + + +DEFUN (bgp_table_map, + bgp_table_map_cmd, + "table-map WORD", + "BGP table to RIB route download filter\n" + "Name of the route map\n") +{ + return bgp_table_map_set (vty, vty->index, + bgp_node_afi (vty), bgp_node_safi (vty), argv[0]); +} +DEFUN (no_bgp_table_map, + no_bgp_table_map_cmd, + "no table-map WORD", + "BGP table to RIB route download filter\n" + "Name of the route map\n") +{ + return bgp_table_map_unset (vty, vty->index, + bgp_node_afi (vty), bgp_node_safi (vty), argv[0]); +} + DEFUN (bgp_network, bgp_network_cmd, "network A.B.C.D/M", @@ -4736,6 +5100,7 @@ bgp_aggregate_free (struct bgp_aggregate *aggregate) XFREE (MTYPE_BGP_AGGREGATE, aggregate); } +/* Update an aggregate as routes are added/removed from the BGP table */ 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, @@ -4753,6 +5118,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, struct bgp_info *new; int first = 1; unsigned long match = 0; + u_char atomic_aggregate = 0; /* ORIGIN attribute: If at least one route among routes that are aggregated has ORIGIN with the value INCOMPLETE, then the @@ -4797,6 +5163,9 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, } #endif /* AGGREGATE_NEXTHOP_CHECK */ + if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) + atomic_aggregate = 1; + if (ri->sub_type != BGP_ROUTE_AGGREGATE) { if (aggregate->summary_only) @@ -4808,11 +5177,11 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, aggregate->count++; + if (origin < ri->attr->origin) + origin = ri->attr->origin; + if (aggregate->as_set) { - if (origin < ri->attr->origin) - origin = ri->attr->origin; - if (aspath) { asmerge = aspath_aggregate (aspath, ri->attr->aspath); @@ -4849,11 +5218,11 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, if (aggregate->summary_only) (bgp_info_extra_get (rinew))->suppress++; + if (origin < rinew->attr->origin) + origin = rinew->attr->origin; + if (aggregate->as_set) { - if (origin < rinew->attr->origin) - origin = rinew->attr->origin; - if (aspath) { asmerge = aspath_aggregate (aspath, rinew->attr->aspath); @@ -4881,13 +5250,11 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, if (aggregate->count > 0) { rn = bgp_node_get (table, p); - new = bgp_info_new (); - new->type = ZEBRA_ROUTE_BGP; - new->sub_type = BGP_ROUTE_AGGREGATE; - new->peer = bgp->peer_self; + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, bgp->peer_self, + bgp_attr_aggregate_intern(bgp, origin, aspath, community, + aggregate->as_set, + atomic_aggregate), rn); SET_FLAG (new->flags, BGP_INFO_VALID); - new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set); - new->uptime = bgp_clock (); bgp_info_add (rn, new); bgp_unlock_node (rn); @@ -4976,6 +5343,7 @@ bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p, bgp_unlock_node (child); } +/* Called via bgp_aggregate_set when the user configures aggregate-address */ static void bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, struct bgp_aggregate *aggregate) @@ -4991,6 +5359,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, struct aspath *asmerge = NULL; struct community *community = NULL; struct community *commerge = NULL; + u_char atomic_aggregate = 0; table = bgp->rib[afi][safi]; @@ -5012,6 +5381,9 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, if (BGP_INFO_HOLDDOWN (ri)) continue; + if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) + atomic_aggregate = 1; + if (ri->sub_type != BGP_ROUTE_AGGREGATE) { /* summary-only aggregate route suppress aggregated @@ -5022,13 +5394,21 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); match++; } + + /* If at least one route among routes that are aggregated has + * ORIGIN with the value INCOMPLETE, then the aggregated route + * MUST have the ORIGIN attribute with the value INCOMPLETE. + * Otherwise, if at least one route among routes that are + * aggregated has ORIGIN with the value EGP, then the aggregated + * route MUST have the ORIGIN attribute with the value EGP. + */ + if (origin < ri->attr->origin) + origin = ri->attr->origin; + /* as-set aggregate route generate origin, as path, community aggregation. */ if (aggregate->as_set) { - if (origin < ri->attr->origin) - origin = ri->attr->origin; - if (aspath) { asmerge = aspath_aggregate (aspath, ri->attr->aspath); @@ -5065,14 +5445,11 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, if (aggregate->count) { rn = bgp_node_get (table, p); - - new = bgp_info_new (); - new->type = ZEBRA_ROUTE_BGP; - new->sub_type = BGP_ROUTE_AGGREGATE; - new->peer = bgp->peer_self; + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, bgp->peer_self, + bgp_attr_aggregate_intern(bgp, origin, aspath, community, + aggregate->as_set, + atomic_aggregate), rn); SET_FLAG (new->flags, BGP_INFO_VALID); - new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set); - new->uptime = bgp_clock (); bgp_info_add (rn, new); bgp_unlock_node (rn); @@ -5602,8 +5979,8 @@ ALIAS (no_ipv6_aggregate_address_summary_only, /* Redistribute route treatment. */ void bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, - const struct in6_addr *nexthop6, - u_int32_t metric, u_char type) + const struct in6_addr *nexthop6, unsigned int ifindex, + u_int32_t metric, u_char type, u_short tag) { struct bgp *bgp; struct listnode *node, *nnode; @@ -5620,6 +5997,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); if (nexthop) attr.nexthop = *nexthop; + attr.nh_ifindex = ifindex; if (nexthop6) { @@ -5630,6 +6008,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, attr.med = metric; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + attr.extra->tag = tag; for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) { @@ -5715,16 +6094,12 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, aspath_unintern (&attr.aspath); bgp_attr_extra_free (&attr); return; - } + } } - new = bgp_info_new (); - new->type = type; - new->sub_type = BGP_ROUTE_REDISTRIBUTE; - new->peer = bgp->peer_self; + new = info_make(type, BGP_ROUTE_REDISTRIBUTE, bgp->peer_self, + new_attr, bn); SET_FLAG (new->flags, BGP_INFO_VALID); - new->attr = new_attr; - new->uptime = bgp_clock (); bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST); bgp_info_add (bn, new); @@ -5847,7 +6222,8 @@ route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo) vty_out (vty, "S"); else if (binfo->extra && binfo->extra->suppress) vty_out (vty, "s"); - else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + else if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) && + ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) vty_out (vty, "*"); else vty_out (vty, " "); @@ -6293,7 +6669,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, VTY_NEWLINE); } - /* Line 3 display Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */ + /* Line 3 display Origin, Med, Locpref, Weight, Tag, 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)) @@ -6306,8 +6682,13 @@ 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 (attr->extra && attr->extra->tag != 0) + vty_out (vty, ", tag %d", attr->extra->tag); - if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) + if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) + vty_out (vty, ", invalid"); + else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) vty_out (vty, ", valid"); if (binfo->peer != bgp->peer_self) @@ -6756,7 +7137,7 @@ static int 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) + int prefix_check, enum bgp_path_type pathtype) { int ret; int header; @@ -6807,7 +7188,12 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, header = 0; } display++; - route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi); + + if (pathtype == BGP_PATH_ALL || + (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) || + (pathtype == BGP_PATH_MULTIPATH && + (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)))) + route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi); } bgp_unlock_node (rm); @@ -6831,7 +7217,12 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, header = 0; } display++; - route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi); + + if (pathtype == BGP_PATH_ALL || + (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) || + (pathtype == BGP_PATH_MULTIPATH && + (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)))) + route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi); } } @@ -6852,7 +7243,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, static int bgp_show_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 prefix_check, enum bgp_path_type pathtype) { struct bgp *bgp; @@ -6877,7 +7268,7 @@ bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str, } return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str, - afi, safi, prd, prefix_check); + afi, safi, prd, prefix_check, pathtype); } /* BGP route print out function. */ @@ -6916,7 +7307,47 @@ DEFUN (show_ip_bgp_route, BGP_STR "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); +} + +DEFUN (show_ip_bgp_route_pathtype, + show_ip_bgp_route_pathtype_cmd, + "show ip bgp A.B.C.D (bestpath|multipath)", + SHOW_STR + IP_STR + BGP_STR + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[1], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH); +} + +DEFUN (show_bgp_ipv4_safi_route_pathtype, + show_bgp_ipv4_safi_route_pathtype_cmd, + "show bgp ipv4 (unicast|multicast) A.B.C.D (bestpath|multipath)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_MULTIPATH); + else + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH); } DEFUN (show_ip_bgp_ipv4_route, @@ -6931,9 +7362,9 @@ DEFUN (show_ip_bgp_ipv4_route, "Network in the BGP routing table to display\n") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL); - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } DEFUN (show_ip_bgp_vpnv4_all_route, @@ -6946,9 +7377,10 @@ DEFUN (show_ip_bgp_vpnv4_all_route, "Display information about all VPNv4 NLRIs\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL); } + DEFUN (show_ip_bgp_vpnv4_rd_route, show_ip_bgp_vpnv4_rd_route_cmd, "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D", @@ -6969,7 +7401,7 @@ DEFUN (show_ip_bgp_vpnv4_rd_route, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL); } DEFUN (show_ip_bgp_prefix, @@ -6980,7 +7412,23 @@ DEFUN (show_ip_bgp_prefix, BGP_STR "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); +} + +DEFUN (show_ip_bgp_prefix_pathtype, + show_ip_bgp_prefix_pathtype_cmd, + "show ip bgp A.B.C.D/M (bestpath|multipath)", + SHOW_STR + IP_STR + BGP_STR + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[1], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH); } DEFUN (show_ip_bgp_ipv4_prefix, @@ -6995,11 +7443,48 @@ DEFUN (show_ip_bgp_ipv4_prefix, "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL); + + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); +} - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1); +DEFUN (show_ip_bgp_ipv4_prefix_pathtype, + show_ip_bgp_ipv4_prefix_pathtype_cmd, + "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M (bestpath|multipath)", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_MULTIPATH); + else + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH); } +ALIAS (show_ip_bgp_ipv4_prefix_pathtype, + show_bgp_ipv4_safi_prefix_pathtype_cmd, + "show bgp ipv4 (unicast|multicast) A.B.C.D/M (bestpath|multipath)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" + "Display only the bestpath\n" + "Display only multipaths\n") + DEFUN (show_ip_bgp_vpnv4_all_prefix, show_ip_bgp_vpnv4_all_prefix_cmd, "show ip bgp vpnv4 all A.B.C.D/M", @@ -7010,7 +7495,7 @@ DEFUN (show_ip_bgp_vpnv4_all_prefix, "Display information about all VPNv4 NLRIs\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1, BGP_PATH_ALL); } DEFUN (show_ip_bgp_vpnv4_rd_prefix, @@ -7033,7 +7518,7 @@ DEFUN (show_ip_bgp_vpnv4_rd_prefix, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 1); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 1, BGP_PATH_ALL); } DEFUN (show_ip_bgp_view, @@ -7068,7 +7553,7 @@ DEFUN (show_ip_bgp_view_route, "View name\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } DEFUN (show_ip_bgp_view_prefix, @@ -7081,7 +7566,7 @@ DEFUN (show_ip_bgp_view_prefix, "View name\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp, @@ -7120,7 +7605,7 @@ DEFUN (show_bgp_route, BGP_STR "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_safi, @@ -7150,9 +7635,58 @@ DEFUN (show_bgp_ipv4_safi_route, "Network in the BGP routing table to display\n") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL); + + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); +} + +DEFUN (show_bgp_route_pathtype, + show_bgp_route_pathtype_cmd, + "show bgp X:X::X:X (bestpath|multipath)", + SHOW_STR + BGP_STR + "Network in the BGP routing table to display\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[1], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH); +} - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0); +ALIAS (show_bgp_route_pathtype, + show_bgp_ipv6_route_pathtype_cmd, + "show bgp ipv6 X:X::X:X (bestpath|multipath)", + SHOW_STR + BGP_STR + "Address family\n" + "Network in the BGP routing table to display\n" + "Display only the bestpath\n" + "Display only multipaths\n") + +DEFUN (show_bgp_ipv6_safi_route_pathtype, + show_bgp_ipv6_safi_route_pathtype_cmd, + "show bgp ipv6 (unicast|multicast) X:X::X:X (bestpath|multipath)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Network in the BGP routing table to display\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_MULTIPATH); + else + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH); } DEFUN (show_bgp_ipv4_vpn_route, @@ -7164,7 +7698,7 @@ DEFUN (show_bgp_ipv4_vpn_route, "Display VPN NLRI specific information\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_vpn_route, @@ -7176,7 +7710,7 @@ DEFUN (show_bgp_ipv6_vpn_route, "Display VPN NLRI specific information\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_vpn_rd_route, @@ -7199,7 +7733,7 @@ DEFUN (show_bgp_ipv4_vpn_rd_route, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_vpn_rd_route, @@ -7222,7 +7756,56 @@ DEFUN (show_bgp_ipv6_vpn_rd_route, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MPLS_VPN, &prd, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL); +} + +DEFUN (show_bgp_prefix_pathtype, + show_bgp_prefix_pathtype_cmd, + "show bgp X:X::X:X/M (bestpath|multipath)", + SHOW_STR + BGP_STR + "IPv6 prefix <network>/<length>\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[1], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH); +} + +ALIAS (show_bgp_prefix_pathtype, + show_bgp_ipv6_prefix_pathtype_cmd, + "show bgp ipv6 X:X::X:X/M (bestpath|multipath)", + SHOW_STR + BGP_STR + "Address family\n" + "IPv6 prefix <network>/<length>\n" + "Display only the bestpath\n" + "Display only multipaths\n") + +DEFUN (show_bgp_ipv6_safi_prefix_pathtype, + show_bgp_ipv6_safi_prefix_pathtype_cmd, + "show bgp ipv6 (unicast|multicast) X:X::X:X/M (bestpath|multipath)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n" + "Display only the bestpath\n" + "Display only multipaths\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_MULTIPATH); + else + if (strncmp (argv[2], "b", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH); + else + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH); } DEFUN (show_bgp_ipv4_encap_route, @@ -7234,7 +7817,7 @@ DEFUN (show_bgp_ipv4_encap_route, "Display ENCAP NLRI specific information\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_encap_route, @@ -7246,7 +7829,7 @@ DEFUN (show_bgp_ipv6_encap_route, "Display ENCAP NLRI specific information\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_safi_rd_route, @@ -7275,7 +7858,7 @@ DEFUN (show_bgp_ipv4_safi_rd_route, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 0); + return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_safi_rd_route, @@ -7304,7 +7887,7 @@ DEFUN (show_bgp_ipv6_safi_rd_route, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[2], AFI_IP6, SAFI_ENCAP, &prd, 0); + return bgp_show_route (vty, NULL, argv[2], AFI_IP6, SAFI_ENCAP, &prd, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_prefix, @@ -7315,7 +7898,7 @@ DEFUN (show_bgp_ipv4_prefix, IP_STR "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_safi_prefix, @@ -7329,9 +7912,9 @@ DEFUN (show_bgp_ipv4_safi_prefix, "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL); - return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_vpn_prefix, @@ -7343,7 +7926,7 @@ DEFUN (show_bgp_ipv4_vpn_prefix, "Display VPN NLRI specific information\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_vpn_prefix, @@ -7355,7 +7938,7 @@ DEFUN (show_bgp_ipv6_vpn_prefix, "Display VPN NLRI specific information\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_encap_prefix, @@ -7368,7 +7951,7 @@ DEFUN (show_bgp_ipv4_encap_prefix, "Display information about ENCAP NLRIs\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_encap_prefix, @@ -7381,7 +7964,7 @@ DEFUN (show_bgp_ipv6_encap_prefix, "Display information about ENCAP NLRIs\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv4_safi_rd_prefix, @@ -7411,7 +7994,7 @@ DEFUN (show_bgp_ipv4_safi_rd_prefix, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 1); + return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_safi_rd_prefix, @@ -7441,7 +8024,7 @@ DEFUN (show_bgp_ipv6_safi_rd_prefix, vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, NULL, argv[2], AFI_IP6, safi, &prd, 1); + return bgp_show_route (vty, NULL, argv[2], AFI_IP6, safi, &prd, 1, BGP_PATH_ALL); } DEFUN (show_bgp_afi_safi_view, @@ -7509,7 +8092,7 @@ DEFUN (show_bgp_view_afi_safi_route, vty_out (vty, "Error: Bad SAFI: %s%s", argv[1], VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 0); + return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_view_afi_safi_prefix, @@ -7538,7 +8121,7 @@ DEFUN (show_bgp_view_afi_safi_prefix, vty_out (vty, "Error: Bad SAFI: %s%s", argv[1], VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 1); + return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 1, BGP_PATH_ALL); } /* new001 */ @@ -7584,7 +8167,7 @@ DEFUN (show_bgp_ipv6_route, "Address family\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_safi_route, @@ -7598,9 +8181,9 @@ DEFUN (show_bgp_ipv6_safi_route, "Network in the BGP routing table to display\n") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL); - return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } /* old command */ @@ -7612,7 +8195,7 @@ DEFUN (show_ipv6_bgp_route, BGP_STR "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_prefix, @@ -7622,7 +8205,7 @@ DEFUN (show_bgp_prefix, BGP_STR "IPv6 prefix <network>/<length>\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } @@ -7635,7 +8218,7 @@ DEFUN (show_bgp_ipv6_prefix, "Address family\n" "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_ipv6_safi_prefix, show_bgp_ipv6_safi_prefix_cmd, @@ -7648,9 +8231,9 @@ DEFUN (show_bgp_ipv6_safi_prefix, "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL); - return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } /* old command */ @@ -7662,7 +8245,7 @@ DEFUN (show_ipv6_bgp_prefix, BGP_STR "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_view, @@ -7717,7 +8300,7 @@ DEFUN (show_bgp_view_route, "View name\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_view_ipv6_route, @@ -7730,7 +8313,7 @@ DEFUN (show_bgp_view_ipv6_route, "Address family\n" "Network in the BGP routing table to display\n") { - return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0); + return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } /* old command */ @@ -7754,7 +8337,7 @@ DEFUN (show_ipv6_mbgp_route, MBGP_STR "Network in the MBGP routing table to display\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 0); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL); } /* old command */ @@ -7766,7 +8349,7 @@ DEFUN (show_ipv6_mbgp_prefix, MBGP_STR "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") { - return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1); + return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_view_prefix, @@ -7778,7 +8361,7 @@ DEFUN (show_bgp_view_prefix, "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, BGP_PATH_ALL); } DEFUN (show_bgp_view_ipv6_prefix, @@ -7791,7 +8374,7 @@ DEFUN (show_bgp_view_ipv6_prefix, "Address family\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, BGP_PATH_ALL); } static int @@ -11548,8 +12131,13 @@ peer_lookup_in_view (struct vty *vty, const char *view_name, ret = str2sockunion (ip_str, &su); if (ret < 0) { - vty_out (vty, "Malformed address: %s%s", ip_str, VTY_NEWLINE); - return NULL; + peer = peer_lookup_by_conf_if (bgp, ip_str); + if (!peer) + { + vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE); + return NULL; + } + return peer; } /* Peer structure lookup. */ @@ -11998,8 +12586,7 @@ bgp_peer_count_walker (struct thread *t) { pc->count[PCOUNT_COUNTED]++; if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) - plog_warn (peer->log, - "%s [pcount] %s/%d is counted but flags 0x%x", + zlog_warn ("%s [pcount] %s/%d is counted but flags 0x%x", peer->host, inet_ntop(rn->p.family, &rn->p.u.prefix, buf, SU_ADDRSTRLEN), @@ -12009,8 +12596,7 @@ bgp_peer_count_walker (struct thread *t) else { if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) - plog_warn (peer->log, - "%s [pcount] %s/%d not counted but flags 0x%x", + zlog_warn ("%s [pcount] %s/%d not counted but flags 0x%x", peer->host, inet_ntop(rn->p.family, &rn->p.u.prefix, buf, SU_ADDRSTRLEN), @@ -12068,13 +12654,14 @@ bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi) DEFUN (show_ip_bgp_neighbor_prefix_counts, show_ip_bgp_neighbor_prefix_counts_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X) prefix-counts", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display detailed prefix count information\n") { struct peer *peer; @@ -12088,13 +12675,14 @@ DEFUN (show_ip_bgp_neighbor_prefix_counts, DEFUN (show_bgp_ipv6_neighbor_prefix_counts, show_bgp_ipv6_neighbor_prefix_counts_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) prefix-counts", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display detailed prefix count information\n") { struct peer *peer; @@ -12108,7 +12696,7 @@ DEFUN (show_bgp_ipv6_neighbor_prefix_counts, DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts, show_ip_bgp_ipv4_neighbor_prefix_counts_cmd, - "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts", + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts", SHOW_STR IP_STR BGP_STR @@ -12118,6 +12706,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display detailed prefix count information\n") { struct peer *peer; @@ -12134,7 +12723,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts, DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts, show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd, - "show ip bgp vpnv4 all neighbors (A.B.C.D|X:X::X:X) prefix-counts", + "show ip bgp vpnv4 all neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts", SHOW_STR IP_STR BGP_STR @@ -12144,6 +12733,7 @@ DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display detailed prefix count information\n") { struct peer *peer; @@ -12157,7 +12747,7 @@ DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts, DEFUN (show_bgp_ipv4_safi_neighbor_prefix_counts, show_bgp_ipv4_safi_neighbor_prefix_counts_cmd, - "show bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts", + "show bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts", SHOW_STR BGP_STR "Address family\n" @@ -12168,6 +12758,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_prefix_counts, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display detailed prefix count information\n") { struct peer *peer; @@ -12187,7 +12778,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_prefix_counts, DEFUN (show_bgp_ipv6_safi_neighbor_prefix_counts, show_bgp_ipv6_safi_neighbor_prefix_counts_cmd, - "show bgp ipv6 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts", + "show bgp ipv6 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts", SHOW_STR BGP_STR "Address family\n" @@ -12198,6 +12789,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_prefix_counts, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display detailed prefix count information\n") { struct peer *peer; @@ -12217,7 +12809,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_prefix_counts, DEFUN (show_ip_bgp_encap_neighbor_prefix_counts, show_ip_bgp_encap_neighbor_prefix_counts_cmd, - "show ip bgp encap all neighbors (A.B.C.D|X:X::X:X) prefix-counts", + "show ip bgp encap all neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts", SHOW_STR IP_STR BGP_STR @@ -12227,6 +12819,7 @@ DEFUN (show_ip_bgp_encap_neighbor_prefix_counts, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display detailed prefix count information\n") { struct peer *peer; @@ -12238,19 +12831,22 @@ DEFUN (show_ip_bgp_encap_neighbor_prefix_counts, return bgp_peer_counts (vty, peer, AFI_IP, SAFI_ENCAP); } - static void show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, - int in) + int in, const char *rmap_name) { struct bgp_table *table; struct bgp_adj_in *ain; struct bgp_adj_out *adj; unsigned long output_count; + unsigned long filtered_count; struct bgp_node *rn; int header1 = 1; struct bgp *bgp; int header2 = 1; + struct attr attr; + struct attr_extra extra; + int ret; bgp = peer->bgp; @@ -12259,8 +12855,8 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, table = bgp->rib[afi][safi]; - output_count = 0; - + output_count = filtered_count = 0; + if (! in && CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE)) { @@ -12273,6 +12869,7 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, header1 = 0; } + attr.extra = &extra; for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) if (in) { @@ -12292,9 +12889,16 @@ 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++; + { + bgp_attr_dup(&attr, ain->attr); + if (bgp_input_modifier(peer, &rn->p, &attr, afi, + safi, rmap_name) != RMAP_DENY) + { + route_vty_out_tmp (vty, &rn->p, &attr, safi); + output_count++; + } + else + filtered_count++; } } } @@ -12316,9 +12920,26 @@ 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 (!CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT) + || bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) + { + + bgp_attr_dup(&attr, adj->attr); + ret = bgp_output_modifier(peer, &rn->p, &attr, afi, + safi, rmap_name); + } + else + ret = RMAP_PERMIT; + + if (ret != RMAP_DENY) + { + route_vty_out_tmp (vty, &rn->p, &attr, safi); + output_count++; + } + else + filtered_count++; } } } @@ -12329,7 +12950,8 @@ 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) +peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, + int in, const char *rmap_name) { if (! peer || ! peer->afc[afi][safi]) { @@ -12344,14 +12966,36 @@ peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, int return CMD_WARNING; } - show_adj_route (vty, peer, afi, safi, in); + if (!in && (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT) + && !bgp_flag_check(peer->bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY))) + { + vty_out (vty, "%% Cannot apply outgoing route-map on route-reflector clients%s", + VTY_NEWLINE); + vty_out (vty, "%% Enable bgp route-reflector allow-outbound-policy flag%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + show_adj_route (vty, peer, afi, safi, in, rmap_name); return CMD_SUCCESS; } +static int +peer_adj_routes_decode (struct vty *vty, const char *view, const char *ip_str, afi_t afi, safi_t safi, int in, const char *rmap) +{ + struct peer *peer; + + peer = peer_lookup_in_view (vty, view, ip_str); + if (!peer) + return CMD_WARNING; + + return peer_adj_routes (vty, peer, afi, safi, in, rmap); +} + DEFUN (show_ip_bgp_view_neighbor_advertised_route, show_ip_bgp_view_neighbor_advertised_route_cmd, - "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR IP_STR BGP_STR @@ -12362,33 +13006,63 @@ DEFUN (show_ip_bgp_view_neighbor_advertised_route, "Neighbor to display information about\n" "Display the routes advertised to a BGP neighbor\n") { - struct peer *peer; - - if (argc == 2) - peer = peer_lookup_in_view (vty, argv[0], argv[1]); - else - peer = peer_lookup_in_view (vty, NULL, argv[0]); + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, NULL); +} - if (! peer) - return CMD_WARNING; - - return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 0); +DEFUN (show_ip_bgp_view_neighbor_advertised_route_rmap, + show_ip_bgp_view_neighbor_advertised_route_rmap_cmd, + "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "BGP view\n" + "View name\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, argv[2]); } -ALIAS (show_ip_bgp_view_neighbor_advertised_route, +DEFUN (show_ip_bgp_neighbor_advertised_route, show_ip_bgp_neighbor_advertised_route_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL); +} -DEFUN (show_ip_bgp_ipv4_neighbor_advertised_route, - show_ip_bgp_ipv4_neighbor_advertised_route_cmd, - "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes", +DEFUN (show_ip_bgp_neighbor_advertised_route_rmap, + show_ip_bgp_neighbor_advertised_route_rmap_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]); +} + +DEFUN (show_ip_bgp_ipv4_safi_neighbor_advertised_route, + show_ip_bgp_ipv4_safi_neighbor_advertised_route_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR IP_STR BGP_STR @@ -12398,23 +13072,45 @@ DEFUN (show_ip_bgp_ipv4_neighbor_advertised_route, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") { - struct peer *peer; + safi_t safi = SAFI_UNICAST; - peer = peer_lookup_in_view (vty, NULL, argv[1]); - if (! peer) - return CMD_WARNING; + if (strncmp (argv[0], "m", 1) == 0) + safi = SAFI_MULTICAST; + + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, NULL); +} + +DEFUN (show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap, + show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + safi_t safi = SAFI_UNICAST; if (strncmp (argv[0], "m", 1) == 0) - return peer_adj_routes (vty, peer, AFI_IP, SAFI_MULTICAST, 0); + safi = SAFI_MULTICAST; - return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 0); + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, argv[2]); } DEFUN (show_bgp_view_neighbor_advertised_route, show_bgp_view_neighbor_advertised_route_cmd, - "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR BGP_STR "BGP view\n" @@ -12422,24 +13118,15 @@ DEFUN (show_bgp_view_neighbor_advertised_route, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") { - struct peer *peer; - - if (argc == 2) - 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; - - return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 0); + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, NULL); } -DEFUN (show_bgp_view_neighbor_received_routes, - show_bgp_view_neighbor_received_routes_cmd, - "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) received-routes", +DEFUN (show_bgp_view_neighbor_advertised_route_rmap, + show_bgp_view_neighbor_advertised_route_rmap_cmd, + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR BGP_STR "BGP view\n" @@ -12447,78 +13134,174 @@ DEFUN (show_bgp_view_neighbor_received_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" - "Display the received routes from neighbor\n") + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") { - struct peer *peer; - - if (argc == 2) - 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; - - return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 1); + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, argv[2]); } -ALIAS (show_bgp_view_neighbor_advertised_route, +DEFUN (show_bgp_neighbor_advertised_route, show_bgp_neighbor_advertised_route_cmd, - "show bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") - -ALIAS (show_bgp_view_neighbor_advertised_route, +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL); +} + +DEFUN (show_bgp_neighbor_advertised_route_rmap, + show_bgp_neighbor_advertised_route_rmap_cmd, + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]); +} + +DEFUN (show_bgp_ipv6_neighbor_advertised_route, show_bgp_ipv6_neighbor_advertised_route_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 0, NULL); +} -/* old command */ -ALIAS (show_bgp_view_neighbor_advertised_route, - ipv6_bgp_neighbor_advertised_route_cmd, - "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", +/*old command */ +ALIAS (show_bgp_ipv6_neighbor_advertised_route, + show_ipv6_bgp_neighbor_advertised_route_cmd, + "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR IPV6_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") + +DEFUN (show_bgp_ipv6_neighbor_advertised_route_rmap, + show_bgp_ipv6_neighbor_advertised_route_rmap_cmd, + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 0, argv[1]); +} + +/* old command */ +ALIAS (show_bgp_ipv6_neighbor_advertised_route_rmap, + show_ipv6_bgp_neighbor_advertised_route_rmap_cmd, + "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + IPV6_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") /* old command */ DEFUN (ipv6_mbgp_neighbor_advertised_route, ipv6_mbgp_neighbor_advertised_route_cmd, - "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR IPV6_STR MBGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") { - struct peer *peer; + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 0, NULL); +} - peer = peer_lookup_in_view (vty, NULL, argv[0]); - if (! peer) - return CMD_WARNING; +DEFUN (ipv6_mbgp_neighbor_advertised_route_rmap, + ipv6_mbgp_neighbor_advertised_route_rmap_cmd, + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + IPV6_STR + MBGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, 0, argv[1]); +} - return peer_adj_routes (vty, peer, AFI_IP6, SAFI_MULTICAST, 0); +DEFUN (show_bgp_view_neighbor_received_routes, + show_bgp_view_neighbor_received_routes_cmd, + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, NULL); +} + +DEFUN (show_bgp_view_neighbor_received_routes_rmap, + show_bgp_view_neighbor_received_routes_rmap_cmd, + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, argv[2]); } 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", + "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", SHOW_STR IP_STR BGP_STR @@ -12527,51 +13310,189 @@ DEFUN (show_ip_bgp_view_neighbor_received_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the received routes from neighbor\n") { - struct peer *peer; + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, NULL); +} - if (argc == 2) - peer = peer_lookup_in_view (vty, argv[0], argv[1]); - else - peer = peer_lookup_in_view (vty, NULL, argv[0]); +DEFUN (show_ip_bgp_view_neighbor_received_routes_rmap, + show_ip_bgp_view_neighbor_received_routes_rmap_cmd, + "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "BGP view\n" + "View name\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, argv[2]); +} - if (! peer) - return CMD_WARNING; +DEFUN (show_bgp_view_ipv6_neighbor_received_routes, + show_bgp_view_ipv6_neighbor_received_routes_cmd, + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 1, NULL); +} - return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1); +DEFUN (show_bgp_view_ipv6_neighbor_received_routes_rmap, + show_bgp_view_ipv6_neighbor_received_routes_rmap_cmd, + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 1, argv[2]); } -ALIAS (show_ip_bgp_view_neighbor_received_routes, +DEFUN (show_ip_bgp_neighbor_received_routes, show_ip_bgp_neighbor_received_routes_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X) received-routes", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the received routes from neighbor\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL); +} + +DEFUN (show_ip_bgp_neighbor_received_routes_rmap, + show_ip_bgp_neighbor_received_routes_rmap_cmd, + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 1, argv[1]); +} -ALIAS (show_bgp_view_neighbor_received_routes, +DEFUN (show_bgp_ipv6_neighbor_received_routes, show_bgp_ipv6_neighbor_received_routes_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received-routes", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the received routes from neighbor\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 1, NULL); +} + +DEFUN (show_bgp_ipv6_neighbor_received_routes_rmap, + show_bgp_ipv6_neighbor_received_routes_rmap_cmd, + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 1, argv[1]); +} + +/* old command */ +DEFUN (show_ipv6_bgp_neighbor_received_routes, + show_ipv6_bgp_neighbor_received_routes_cmd, + "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", + SHOW_STR + IPV6_STR + BGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 1, NULL); +} + +/* old command */ +DEFUN (ipv6_mbgp_neighbor_received_routes, + ipv6_mbgp_neighbor_received_routes_cmd, + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", + SHOW_STR + IPV6_STR + MBGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, 1, NULL); +} + +DEFUN (ipv6_mbgp_neighbor_received_routes_rmap, + ipv6_mbgp_neighbor_received_routes_rmap_cmd, + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + IPV6_STR + MBGP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, 1, argv[1]); +} DEFUN (show_bgp_neighbor_received_prefix_filter, show_bgp_neighbor_received_prefix_filter_cmd, - "show bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display information received from a BGP neighbor\n" "Display the prefixlist filter\n") { @@ -12602,42 +13523,11 @@ DEFUN (show_bgp_neighbor_received_prefix_filter, return CMD_SUCCESS; } -/* old command */ -ALIAS (show_bgp_view_neighbor_received_routes, - ipv6_bgp_neighbor_received_routes_cmd, - "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) received-routes", - SHOW_STR - IPV6_STR - BGP_STR - "Detailed information on TCP and BGP neighbor connections\n" - "Neighbor to display information about\n" - "Neighbor to display information about\n" - "Display the received routes from neighbor\n") -/* old command */ -DEFUN (ipv6_mbgp_neighbor_received_routes, - ipv6_mbgp_neighbor_received_routes_cmd, - "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) received-routes", - SHOW_STR - IPV6_STR - MBGP_STR - "Detailed information on TCP and BGP neighbor connections\n" - "Neighbor to display information about\n" - "Neighbor to display information about\n" - "Display the received routes from neighbor\n") -{ - struct peer *peer; - - peer = peer_lookup_in_view (vty, NULL, argv[0]); - if (! peer) - return CMD_WARNING; - - return peer_adj_routes (vty, peer, AFI_IP6, SAFI_MULTICAST, 1); -} DEFUN (show_bgp_view_neighbor_received_prefix_filter, show_bgp_view_neighbor_received_prefix_filter_cmd, - "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR BGP_STR "BGP view\n" @@ -12684,10 +13574,9 @@ DEFUN (show_bgp_view_neighbor_received_prefix_filter, return CMD_SUCCESS; } - -DEFUN (show_ip_bgp_ipv4_neighbor_received_routes, - show_ip_bgp_ipv4_neighbor_received_routes_cmd, - "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received-routes", +DEFUN (show_ip_bgp_ipv4_safi_neighbor_received_routes, + show_ip_bgp_ipv4_safi_neighbor_received_routes_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", SHOW_STR IP_STR BGP_STR @@ -12697,23 +13586,49 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the received routes from neighbor\n") { - struct peer *peer; + safi_t safi; - peer = peer_lookup_in_view (vty, NULL, argv[1]); - if (! peer) + if (bgp_parse_safi(argv[0], &safi)) { + vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; - - if (strncmp (argv[0], "m", 1) == 0) - return peer_adj_routes (vty, peer, AFI_IP, SAFI_MULTICAST, 1); + } + + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, NULL); +} + +DEFUN (show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap, + show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd, + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + IP_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Display routes matching the route-map\n" + "A route-map to match on\n") +{ + safi_t safi; - return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1); + if (bgp_parse_safi(argv[0], &safi)) { + vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, argv[1]); } DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route, show_bgp_ipv4_safi_neighbor_advertised_route_cmd, - "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR BGP_STR "Address Family modifier\n" @@ -12721,9 +13636,9 @@ DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") { - struct peer *peer; safi_t safi; if (bgp_parse_safi(argv[0], &safi)) { @@ -12731,16 +13646,37 @@ DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route, return CMD_WARNING; } - peer = peer_lookup_in_view (vty, NULL, argv[1]); - if (! peer) + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, NULL); +} + +DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route_rmap, + show_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd, + "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + BGP_STR + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + safi_t safi; + + if (bgp_parse_safi(argv[0], &safi)) { + vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; + } - return peer_adj_routes (vty, peer, AFI_IP, safi, 0); + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, argv[2]); } DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route, show_bgp_ipv6_safi_neighbor_advertised_route_cmd, - "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR BGP_STR "Address Family modifier\n" @@ -12749,9 +13685,9 @@ DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") { - struct peer *peer; safi_t safi; if (bgp_parse_safi(argv[0], &safi)) { @@ -12759,16 +13695,38 @@ DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route, return CMD_WARNING; } - peer = peer_lookup_in_view (vty, NULL, argv[1]); - if (! peer) + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 0, NULL); +} + +DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route_rmap, + show_bgp_ipv6_safi_neighbor_advertised_route_rmap_cmd, + "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", + SHOW_STR + BGP_STR + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + safi_t safi; + + if (bgp_parse_safi(argv[0], &safi)) { + vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; + } - return peer_adj_routes (vty, peer, AFI_IP6, safi, 0); + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 0, argv[2]); } DEFUN (show_bgp_view_ipv6_neighbor_advertised_route, show_bgp_view_ipv6_neighbor_advertised_route_cmd, - "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) advertised-routes", + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes", SHOW_STR BGP_STR "BGP view\n" @@ -12777,24 +13735,15 @@ DEFUN (show_bgp_view_ipv6_neighbor_advertised_route, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the routes advertised to a BGP neighbor\n") { - struct peer *peer; - - if (argc == 2) - 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; - - return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 0); + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 0, NULL); } -DEFUN (show_bgp_view_ipv6_neighbor_received_routes, - show_bgp_view_ipv6_neighbor_received_routes_cmd, - "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) received-routes", +DEFUN (show_bgp_view_ipv6_neighbor_advertised_route_rmap, + show_bgp_view_ipv6_neighbor_advertised_route_rmap_cmd, + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD", SHOW_STR BGP_STR "BGP view\n" @@ -12803,24 +13752,17 @@ DEFUN (show_bgp_view_ipv6_neighbor_received_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" - "Display the received routes from neighbor\n") + "Neighbor on bgp configured interface\n" + "Display the routes advertised to a BGP neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") { - struct peer *peer; - - if (argc == 2) - 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; - - return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 1); + return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 0, argv[2]); } DEFUN (show_bgp_ipv4_safi_neighbor_received_routes, show_bgp_ipv4_safi_neighbor_received_routes_cmd, - "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received-routes", + "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", SHOW_STR BGP_STR "Address family\n" @@ -12831,9 +13773,9 @@ DEFUN (show_bgp_ipv4_safi_neighbor_received_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the received routes from neighbor\n") { - struct peer *peer; safi_t safi; if (bgp_parse_safi(argv[0], &safi)) { @@ -12841,16 +13783,40 @@ DEFUN (show_bgp_ipv4_safi_neighbor_received_routes, return CMD_WARNING; } - peer = peer_lookup_in_view (vty, NULL, argv[1]); - if (! peer) + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, NULL); +} + +DEFUN (show_bgp_ipv4_safi_neighbor_received_routes_rmap, + show_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd, + "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + safi_t safi; + + if (bgp_parse_safi(argv[0], &safi)) { + vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; - - return peer_adj_routes (vty, peer, AFI_IP, safi, 1); + } + + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, argv[2]); } DEFUN (show_bgp_ipv6_safi_neighbor_received_routes, show_bgp_ipv6_safi_neighbor_received_routes_cmd, - "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received-routes", + "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", SHOW_STR BGP_STR "Address family\n" @@ -12861,9 +13827,9 @@ DEFUN (show_bgp_ipv6_safi_neighbor_received_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the received routes from neighbor\n") { - struct peer *peer; safi_t safi; if (bgp_parse_safi(argv[0], &safi)) { @@ -12871,16 +13837,40 @@ DEFUN (show_bgp_ipv6_safi_neighbor_received_routes, return CMD_WARNING; } - peer = peer_lookup_in_view (vty, NULL, argv[1]); - if (! peer) + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 1, NULL); +} + +DEFUN (show_bgp_ipv6_safi_neighbor_received_routes_rmap, + show_bgp_ipv6_safi_neighbor_received_routes_rmap_cmd, + "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + safi_t safi; + + if (bgp_parse_safi(argv[0], &safi)) { + vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; - - return peer_adj_routes (vty, peer, AFI_IP6, safi, 1); + } + + return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 1, argv[2]); } DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes, show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd, - "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)", + "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) (advertised-routes|received-routes)", SHOW_STR BGP_STR "BGP view\n" @@ -12892,35 +13882,63 @@ DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the advertised routes to neighbor\n" "Display the received routes from neighbor\n") { int afi; int safi; int in; - struct peer *peer; - peer = peer_lookup_in_view (vty, argv[0], argv[3]); + afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP; + safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0; + + return peer_adj_routes_decode (vty, argv[0], argv[3], afi, safi, in, NULL); +} - if (! peer) - return CMD_WARNING; +DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes_rmap, + show_bgp_view_afi_safi_neighbor_adv_recd_routes_rmap_cmd, + "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) (advertised-routes|received-routes) route-map WORD", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Address family\n" + "Address family\n" + "Address family modifier\n" + "Address family modifier\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" + "Display the advertised routes to neighbor\n" + "Display the received routes from neighbor\n" + "Route-map to control what is displayed\n" + "Route-map name\n") +{ + int afi; + int safi; + int in; afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP; safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0; - return peer_adj_routes (vty, peer, afi, safi, in); + return peer_adj_routes_decode (vty, argv[0], argv[3], afi, safi, in, argv[5]); } + DEFUN (show_ip_bgp_neighbor_received_prefix_filter, show_ip_bgp_neighbor_received_prefix_filter_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display information received from a BGP neighbor\n" "Display the prefixlist filter\n") { @@ -12932,13 +13950,19 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, ret = str2sockunion (argv[0], &su); if (ret < 0) { - vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE); - return CMD_WARNING; + peer = peer_lookup_by_conf_if (NULL, argv[0]); + if (!peer) + { + vty_out (vty, "Malformed address or name: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + peer = peer_lookup (NULL, &su); + if (! peer) + return CMD_WARNING; } - - peer = peer_lookup (NULL, &su); - if (! peer) - return CMD_WARNING; sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_UNICAST); count = prefix_bgp_show_prefix_list (NULL, AFI_IP, name); @@ -12953,7 +13977,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter, show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd, - "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR IP_STR BGP_STR @@ -12963,6 +13987,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display information received from a BGP neighbor\n" "Display the prefixlist filter\n") { @@ -12974,13 +13999,19 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter, ret = str2sockunion (argv[1], &su); if (ret < 0) { - vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE); - return CMD_WARNING; + peer = peer_lookup_by_conf_if (NULL, argv[1]); + if (!peer) + { + vty_out (vty, "Malformed address or name: %s%s", argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + peer = peer_lookup (NULL, &su); + if (! peer) + return CMD_WARNING; } - - peer = peer_lookup (NULL, &su); - if (! peer) - return CMD_WARNING; if (strncmp (argv[0], "m", 1) == 0) { @@ -13006,19 +14037,23 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter, return CMD_SUCCESS; } -ALIAS (show_bgp_view_neighbor_received_routes, +DEFUN (show_bgp_neighbor_received_routes, show_bgp_neighbor_received_routes_cmd, - "show bgp neighbors (A.B.C.D|X:X::X:X) received-routes", + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes", SHOW_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the received routes from neighbor\n") +{ + return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL); +} DEFUN (show_bgp_ipv4_safi_neighbor_received_prefix_filter, show_bgp_ipv4_safi_neighbor_received_prefix_filter_cmd, - "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR BGP_STR IP_STR @@ -13066,7 +14101,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_received_prefix_filter, DEFUN (show_bgp_ipv6_safi_neighbor_received_prefix_filter, show_bgp_ipv6_safi_neighbor_received_prefix_filter_cmd, - "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR BGP_STR IP_STR @@ -13114,13 +14149,14 @@ DEFUN (show_bgp_ipv6_safi_neighbor_received_prefix_filter, DEFUN (show_bgp_ipv6_neighbor_received_prefix_filter, show_bgp_ipv6_neighbor_received_prefix_filter_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display information received from a BGP neighbor\n" "Display the prefixlist filter\n") { @@ -13132,13 +14168,19 @@ DEFUN (show_bgp_ipv6_neighbor_received_prefix_filter, ret = str2sockunion (argv[0], &su); if (ret < 0) { - vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE); - return CMD_WARNING; + peer = peer_lookup_by_conf_if (NULL, argv[0]); + if (!peer) + { + vty_out (vty, "Malformed address or name: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + peer = peer_lookup (NULL, &su); + if (! peer) + return CMD_WARNING; } - - peer = peer_lookup (NULL, &su); - if (! peer) - return CMD_WARNING; sprintf (name, "%s.%d.%d", peer->host, AFI_IP6, SAFI_UNICAST); count = prefix_bgp_show_prefix_list (NULL, AFI_IP6, name); @@ -13153,7 +14195,7 @@ DEFUN (show_bgp_ipv6_neighbor_received_prefix_filter, DEFUN (show_bgp_view_ipv6_neighbor_received_prefix_filter, show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd, - "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) received prefix-filter", + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter", SHOW_STR BGP_STR "BGP view\n" @@ -13162,6 +14204,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_received_prefix_filter, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display information received from a BGP neighbor\n" "Display the prefixlist filter\n") { @@ -13182,13 +14225,19 @@ DEFUN (show_bgp_view_ipv6_neighbor_received_prefix_filter, ret = str2sockunion (argv[1], &su); if (ret < 0) { - vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE); - return CMD_WARNING; + peer = peer_lookup_by_conf_if (bgp, argv[1]); + if (!peer) + { + vty_out (vty, "%% Malformed address or name: %s%s", argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + peer = peer_lookup (bgp, &su); + if (! peer) + return CMD_WARNING; } - - peer = peer_lookup (bgp, &su); - if (! peer) - return CMD_WARNING; sprintf (name, "%s.%d.%d", peer->host, AFI_IP6, SAFI_UNICAST); count = prefix_bgp_show_prefix_list (NULL, AFI_IP6, name); @@ -13215,13 +14264,14 @@ bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi, } DEFUN (show_ip_bgp_neighbor_routes, show_ip_bgp_neighbor_routes_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X) routes", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display routes learned from neighbor\n") { struct peer *peer; @@ -13234,15 +14284,17 @@ DEFUN (show_ip_bgp_neighbor_routes, bgp_show_type_neighbor); } + DEFUN (show_ip_bgp_neighbor_flap, show_ip_bgp_neighbor_flap_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X) flap-statistics", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display flap statistics of the routes learned from neighbor\n") { struct peer *peer; @@ -13257,13 +14309,14 @@ DEFUN (show_ip_bgp_neighbor_flap, DEFUN (show_ip_bgp_neighbor_damp, show_ip_bgp_neighbor_damp_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X) dampened-routes", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the dampened routes received from neighbor\n") { struct peer *peer; @@ -13278,7 +14331,7 @@ DEFUN (show_ip_bgp_neighbor_damp, DEFUN (show_ip_bgp_ipv4_neighbor_routes, show_ip_bgp_ipv4_neighbor_routes_cmd, - "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) routes", + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR IP_STR BGP_STR @@ -13288,6 +14341,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display routes learned from neighbor\n") { struct peer *peer; @@ -13306,14 +14360,14 @@ DEFUN (show_ip_bgp_ipv4_neighbor_routes, DEFUN (show_ip_bgp_view_rsclient, show_ip_bgp_view_rsclient_cmd, - "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X)", + "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR IP_STR BGP_STR "BGP view\n" "View name\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR) + NEIGHBOR_ADDR_STR3) { struct bgp_table *table; struct peer *peer; @@ -13348,16 +14402,16 @@ DEFUN (show_ip_bgp_view_rsclient, ALIAS (show_ip_bgp_view_rsclient, show_ip_bgp_rsclient_cmd, - "show ip bgp rsclient (A.B.C.D|X:X::X:X)", + "show ip bgp rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR IP_STR BGP_STR "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR) + NEIGHBOR_ADDR_STR3) DEFUN (show_bgp_view_ipv4_safi_rsclient, show_bgp_view_ipv4_safi_rsclient_cmd, - "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "BGP view\n" @@ -13366,7 +14420,7 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient, "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR) + NEIGHBOR_ADDR_STR3) { struct bgp_table *table; struct peer *peer; @@ -13405,25 +14459,25 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient, ALIAS (show_bgp_view_ipv4_safi_rsclient, show_bgp_ipv4_safi_rsclient_cmd, - "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "Address family\n" "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR) + NEIGHBOR_ADDR_STR3) DEFUN (show_ip_bgp_view_rsclient_route, show_ip_bgp_view_rsclient_route_cmd, - "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D", + "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D", SHOW_STR IP_STR BGP_STR "BGP view\n" "View name\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") { struct bgp *bgp; @@ -13474,22 +14528,22 @@ DEFUN (show_ip_bgp_view_rsclient_route, 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); + AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } ALIAS (show_ip_bgp_view_rsclient_route, show_ip_bgp_rsclient_route_cmd, - "show ip bgp rsclient (A.B.C.D|X:X::X:X) A.B.C.D", + "show ip bgp rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D", SHOW_STR IP_STR BGP_STR "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") DEFUN (show_bgp_ipv4_safi_neighbor_flap, show_bgp_ipv4_safi_neighbor_flap_cmd, - "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) flap-statistics", + "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics", SHOW_STR BGP_STR "Address Family Modifier\n" @@ -13519,7 +14573,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_flap, DEFUN (show_bgp_ipv6_safi_neighbor_flap, show_bgp_ipv6_safi_neighbor_flap_cmd, - "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) flap-statistics", + "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics", SHOW_STR BGP_STR "Address Family Modifier\n" @@ -13549,7 +14603,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_flap, DEFUN (show_bgp_ipv4_safi_neighbor_damp, show_bgp_ipv4_safi_neighbor_damp_cmd, - "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) dampened-routes", + "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes", SHOW_STR BGP_STR "Address Family Modifier\n" @@ -13579,7 +14633,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_damp, DEFUN (show_bgp_ipv6_safi_neighbor_damp, show_bgp_ipv6_safi_neighbor_damp_cmd, - "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) dampened-routes", + "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes", SHOW_STR BGP_STR "Address Family Modifier\n" @@ -13609,7 +14663,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_damp, DEFUN (show_bgp_ipv4_safi_neighbor_routes, show_bgp_ipv4_safi_neighbor_routes_cmd, - "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) routes", + "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR BGP_STR "Address family\n" @@ -13638,7 +14692,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_routes, DEFUN (show_bgp_ipv6_safi_neighbor_routes, show_bgp_ipv6_safi_neighbor_routes_cmd, - "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) routes", + "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR BGP_STR "Address family\n" @@ -13667,7 +14721,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_routes, DEFUN (show_bgp_view_ipv4_safi_rsclient_route, show_bgp_view_ipv4_safi_rsclient_route_cmd, - "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D", + "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D", SHOW_STR BGP_STR "BGP view\n" @@ -13676,7 +14730,7 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient_route, "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") { struct bgp *bgp; @@ -13731,25 +14785,25 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient_route, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi], (argc == 4) ? argv[3] : argv[2], - AFI_IP, safi, NULL, 0); + AFI_IP, safi, NULL, 0, BGP_PATH_ALL); } ALIAS (show_bgp_view_ipv4_safi_rsclient_route, show_bgp_ipv4_safi_rsclient_route_cmd, - "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D", + "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D", SHOW_STR BGP_STR "Address family\n" "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix, show_bgp_view_ipv4_safi_rsclient_prefix_cmd, - "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M", + "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M", SHOW_STR BGP_STR "BGP view\n" @@ -13813,19 +14867,19 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi], (argc == 4) ? argv[3] : argv[2], - AFI_IP, safi, NULL, 1); + AFI_IP, safi, NULL, 1, BGP_PATH_ALL); } DEFUN (show_ip_bgp_view_rsclient_prefix, show_ip_bgp_view_rsclient_prefix_cmd, - "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M", + "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M", SHOW_STR IP_STR BGP_STR "BGP view\n" "View name\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { struct bgp *bgp; @@ -13876,34 +14930,34 @@ DEFUN (show_ip_bgp_view_rsclient_prefix, 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); + AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } ALIAS (show_ip_bgp_view_rsclient_prefix, show_ip_bgp_rsclient_prefix_cmd, - "show ip bgp rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M", + "show ip bgp rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M", SHOW_STR IP_STR BGP_STR "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") ALIAS (show_bgp_view_ipv4_safi_rsclient_prefix, show_bgp_ipv4_safi_rsclient_prefix_cmd, - "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M", + "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M", SHOW_STR BGP_STR "Address family\n" "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") DEFUN (show_bgp_view_ipv6_neighbor_routes, show_bgp_view_ipv6_neighbor_routes_cmd, - "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) routes", + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR BGP_STR "BGP view\n" @@ -13912,6 +14966,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_routes, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display routes learned from neighbor\n") { struct peer *peer; @@ -13930,7 +14985,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_routes, DEFUN (show_bgp_view_neighbor_damp, show_bgp_view_neighbor_damp_cmd, - "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) dampened-routes", + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes", SHOW_STR BGP_STR "BGP view\n" @@ -13938,6 +14993,7 @@ DEFUN (show_bgp_view_neighbor_damp, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the dampened routes received from neighbor\n") { struct peer *peer; @@ -13956,7 +15012,7 @@ DEFUN (show_bgp_view_neighbor_damp, DEFUN (show_bgp_view_ipv6_neighbor_damp, show_bgp_view_ipv6_neighbor_damp_cmd, - "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) dampened-routes", + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes", SHOW_STR BGP_STR "BGP view\n" @@ -13965,6 +15021,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_damp, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the dampened routes received from neighbor\n") { struct peer *peer; @@ -13983,7 +15040,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_damp, DEFUN (show_bgp_view_ipv6_neighbor_flap, show_bgp_view_ipv6_neighbor_flap_cmd, - "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) flap-statistics", + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics", SHOW_STR BGP_STR "BGP view\n" @@ -13992,6 +15049,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_flap, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the dampened routes received from neighbor\n") { struct peer *peer; @@ -14010,7 +15068,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_flap, DEFUN (show_bgp_view_neighbor_flap, show_bgp_view_neighbor_flap_cmd, - "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) flap-statistics", + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics", SHOW_STR BGP_STR "BGP view\n" @@ -14018,6 +15076,7 @@ DEFUN (show_bgp_view_neighbor_flap, "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display flap statistics of the routes learned from neighbor\n") { struct peer *peer; @@ -14036,7 +15095,7 @@ DEFUN (show_bgp_view_neighbor_flap, ALIAS (show_bgp_view_neighbor_flap, show_bgp_neighbor_flap_cmd, - "show bgp neighbors (A.B.C.D|X:X::X:X) flap-statistics", + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics", SHOW_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" @@ -14046,7 +15105,7 @@ ALIAS (show_bgp_view_neighbor_flap, ALIAS (show_bgp_view_neighbor_damp, show_bgp_neighbor_damp_cmd, - "show bgp neighbors (A.B.C.D|X:X::X:X) dampened-routes", + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes", SHOW_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" @@ -14056,7 +15115,7 @@ ALIAS (show_bgp_view_neighbor_damp, DEFUN (show_bgp_view_neighbor_routes, show_bgp_view_neighbor_routes_cmd, - "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) routes", + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR BGP_STR "BGP view\n" @@ -14082,47 +15141,51 @@ DEFUN (show_bgp_view_neighbor_routes, ALIAS (show_bgp_view_neighbor_routes, show_bgp_neighbor_routes_cmd, - "show bgp neighbors (A.B.C.D|X:X::X:X) routes", + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display routes learned from neighbor\n") ALIAS (show_bgp_view_neighbor_routes, show_bgp_ipv6_neighbor_routes_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) routes", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display routes learned from neighbor\n") /* old command */ ALIAS (show_bgp_view_neighbor_routes, ipv6_bgp_neighbor_routes_cmd, - "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) routes", + "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR IPV6_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display routes learned from neighbor\n") /* old command */ DEFUN (ipv6_mbgp_neighbor_routes, ipv6_mbgp_neighbor_routes_cmd, - "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) routes", + "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) routes", SHOW_STR IPV6_STR MBGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display routes learned from neighbor\n") { struct peer *peer; @@ -14137,29 +15200,31 @@ DEFUN (ipv6_mbgp_neighbor_routes, ALIAS (show_bgp_view_neighbor_flap, show_bgp_ipv6_neighbor_flap_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) flap-statistics", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display flap statistics of the routes learned from neighbor\n") ALIAS (show_bgp_view_neighbor_damp, show_bgp_ipv6_neighbor_damp_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) dampened-routes", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n" "Display the dampened routes received from neighbor\n") DEFUN (show_bgp_view_rsclient, show_bgp_view_rsclient_cmd, - "show bgp view WORD rsclient (A.B.C.D|X:X::X:X)", + "show bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "BGP view\n" @@ -14200,7 +15265,7 @@ DEFUN (show_bgp_view_rsclient, ALIAS (show_bgp_view_rsclient, show_bgp_rsclient_cmd, - "show bgp rsclient (A.B.C.D|X:X::X:X)", + "show bgp rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "Information about Route Server Client\n" @@ -14208,7 +15273,7 @@ ALIAS (show_bgp_view_rsclient, DEFUN (show_bgp_view_ipv4_rsclient, show_bgp_view_ipv4_rsclient_cmd, - "show bgp view WORD ipv4 rsclient (A.B.C.D|X:X::X:X)", + "show bgp view WORD ipv4 rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "BGP view\n" @@ -14249,7 +15314,7 @@ DEFUN (show_bgp_view_ipv4_rsclient, } DEFUN (show_bgp_view_ipv6_rsclient, show_bgp_view_ipv6_rsclient_cmd, - "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X)", + "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "BGP view\n" @@ -14291,25 +15356,25 @@ DEFUN (show_bgp_view_ipv6_rsclient, ALIAS (show_bgp_view_ipv4_rsclient, show_bgp_ipv4_rsclient_cmd, - "show bgp ipv4 rsclient (A.B.C.D|X:X::X:X)", + "show bgp ipv4 rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "Address Family\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR2) + NEIGHBOR_ADDR_STR3) ALIAS (show_bgp_view_ipv6_rsclient, show_bgp_ipv6_rsclient_cmd, - "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X)", + "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "Address Family\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR2) + NEIGHBOR_ADDR_STR3) DEFUN (show_bgp_view_ipv6_safi_rsclient, show_bgp_view_ipv6_safi_rsclient_cmd, - "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "BGP view\n" @@ -14318,7 +15383,7 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient, "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR) + NEIGHBOR_ADDR_STR3) { struct bgp_table *table; struct peer *peer; @@ -14357,24 +15422,24 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient, ALIAS (show_bgp_view_ipv6_safi_rsclient, show_bgp_ipv6_safi_rsclient_cmd, - "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "Address family\n" "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR) + NEIGHBOR_ADDR_STR3) DEFUN (show_bgp_view_rsclient_route, show_bgp_view_rsclient_route_cmd, - "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + "show bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X", SHOW_STR BGP_STR "BGP view\n" "View name\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") { struct bgp *bgp; @@ -14425,12 +15490,12 @@ DEFUN (show_bgp_view_rsclient_route, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST], (argc == 3) ? argv[2] : argv[1], - AFI_IP6, SAFI_UNICAST, NULL, 0); + AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } DEFUN (show_bgp_view_ipv6_rsclient_route, show_bgp_view_ipv6_rsclient_route_cmd, - "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X", SHOW_STR BGP_STR "BGP view\n" @@ -14488,21 +15553,21 @@ DEFUN (show_bgp_view_ipv6_rsclient_route, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST], (argc == 3) ? argv[2] : argv[1], - AFI_IP6, SAFI_UNICAST, NULL, 0); + AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL); } ALIAS (show_bgp_view_ipv6_rsclient_route, show_bgp_rsclient_route_cmd, - "show bgp rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + "show bgp rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X", SHOW_STR BGP_STR "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") ALIAS (show_bgp_view_ipv6_rsclient_route, show_bgp_ipv6_rsclient_route_cmd, - "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X", SHOW_STR BGP_STR IP6_STR @@ -14512,7 +15577,7 @@ ALIAS (show_bgp_view_ipv6_rsclient_route, DEFUN (show_bgp_view_ipv6_safi_rsclient_route, show_bgp_view_ipv6_safi_rsclient_route_cmd, - "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X", SHOW_STR BGP_STR "BGP view\n" @@ -14521,7 +15586,7 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_route, "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") { struct bgp *bgp; @@ -14576,31 +15641,31 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_route, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi], (argc == 4) ? argv[3] : argv[2], - AFI_IP6, safi, NULL, 0); + AFI_IP6, safi, NULL, 0, BGP_PATH_ALL); } ALIAS (show_bgp_view_ipv6_safi_rsclient_route, show_bgp_ipv6_safi_rsclient_route_cmd, - "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X", SHOW_STR BGP_STR "Address family\n" "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "Network in the BGP routing table to display\n") DEFUN (show_bgp_view_rsclient_prefix, show_bgp_view_rsclient_prefix_cmd, - "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + "show bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M", SHOW_STR BGP_STR "BGP view\n" "View name\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") { struct bgp *bgp; @@ -14651,12 +15716,12 @@ DEFUN (show_bgp_view_rsclient_prefix, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST], (argc == 3) ? argv[2] : argv[1], - AFI_IP6, SAFI_UNICAST, NULL, 1); + AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } DEFUN (show_bgp_view_ipv6_rsclient_prefix, show_bgp_view_ipv6_rsclient_prefix_cmd, - "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M", SHOW_STR BGP_STR "BGP view\n" @@ -14714,21 +15779,21 @@ DEFUN (show_bgp_view_ipv6_rsclient_prefix, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST], (argc == 3) ? argv[2] : argv[1], - AFI_IP6, SAFI_UNICAST, NULL, 1); + AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL); } ALIAS (show_bgp_view_ipv6_rsclient_prefix, show_bgp_rsclient_prefix_cmd, - "show bgp rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + "show bgp rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M", SHOW_STR BGP_STR "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") ALIAS (show_bgp_view_ipv6_rsclient_prefix, show_bgp_ipv6_rsclient_prefix_cmd, - "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M", SHOW_STR BGP_STR "Information about Route Server Client\n" @@ -14737,7 +15802,7 @@ ALIAS (show_bgp_view_ipv6_rsclient_prefix, DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix, show_bgp_view_ipv6_safi_rsclient_prefix_cmd, - "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M", SHOW_STR BGP_STR "BGP view\n" @@ -14746,7 +15811,7 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix, "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "IP prefix <network>/<length>, e.g., 3ffe::/16\n") { struct bgp *bgp; @@ -14801,19 +15866,19 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix, return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi], (argc == 4) ? argv[3] : argv[2], - AFI_IP6, safi, NULL, 1); + AFI_IP6, safi, NULL, 1, BGP_PATH_ALL); } ALIAS (show_bgp_view_ipv6_safi_rsclient_prefix, show_bgp_ipv6_safi_rsclient_prefix_cmd, - "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M", SHOW_STR BGP_STR "Address family\n" "Address Family modifier\n" "Address Family modifier\n" "Information about Route Server Client\n" - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR3 "IP prefix <network>/<length>, e.g., 3ffe::/16\n") struct bgp_table *bgp_distance_table; @@ -15697,6 +16762,7 @@ bgp_route_init (void) bgp_distance_table = bgp_table_init (AFI_IP, SAFI_UNICAST); /* IPv4 BGP commands. */ + install_element (BGP_NODE, &bgp_table_map_cmd); install_element (BGP_NODE, &bgp_network_cmd); install_element (BGP_NODE, &bgp_network_mask_cmd); install_element (BGP_NODE, &bgp_network_mask_natural_cmd); @@ -15706,6 +16772,7 @@ bgp_route_init (void) install_element (BGP_NODE, &bgp_network_backdoor_cmd); install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd); install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd); + install_element (BGP_NODE, &no_bgp_table_map_cmd); install_element (BGP_NODE, &no_bgp_network_cmd); install_element (BGP_NODE, &no_bgp_network_mask_cmd); install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd); @@ -15867,9 +16934,13 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_ipv4_safi_prefix_longer_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_longer_cmd); install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd); install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_routes_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_routes_cmd); @@ -16026,9 +17097,13 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_ipv4_safi_prefix_longer_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_longer_cmd); install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd); install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_routes_cmd); @@ -16096,8 +17171,10 @@ bgp_route_init (void) /* New config IPv6 BGP commands. */ install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd); install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); + install_element (BGP_IPV6_NODE, &bgp_table_map_cmd); install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_route_map_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd); install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_summary_only_cmd); @@ -16136,6 +17213,8 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_community_list_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_prefix_longer_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_advertised_route_rmap_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_routes_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd); @@ -16152,7 +17231,9 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_view_ipv6_route_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_prefix_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_routes_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_flap_cmd); @@ -16213,7 +17294,9 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_ipv6_safi_community_list_exact_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_longer_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_advertised_route_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_routes_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_flap_cmd); @@ -16229,7 +17312,9 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_view_ipv6_route_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_prefix_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_received_routes_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_flap_cmd); @@ -16264,6 +17349,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); + install_element (BGP_IPV4_NODE, &bgp_table_map_cmd); /* Deprecated AS-Pathlimit commands */ install_element (BGP_NODE, &bgp_network_ttl_cmd); @@ -16293,13 +17379,15 @@ bgp_route_init (void) 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_IPV4_NODE, &no_bgp_table_map_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, &bgp_table_map_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_ttl_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_ttl_cmd); @@ -16307,6 +17395,7 @@ bgp_route_init (void) install_element (BGP_IPV4M_NODE, &no_bgp_network_backdoor_ttl_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_backdoor_ttl_cmd); install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_table_map_cmd); install_element (BGP_IPV6_NODE, &ipv6_bgp_network_ttl_cmd); install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_ttl_cmd); @@ -16315,11 +17404,16 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd); install_element (VIEW_NODE, &show_ip_bgp_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_route_pathtype_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_route_pathtype_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_pathtype_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_prefix_pathtype_cmd); + install_element (VIEW_NODE, &show_ip_bgp_prefix_pathtype_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_cmd); @@ -16359,10 +17453,14 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_list_exact_cmd); install_element (VIEW_NODE, &show_ip_bgp_prefix_longer_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_advertised_route_cmd); - install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_advertised_route_rmap_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_cmd); - install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); @@ -16392,15 +17490,22 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_rsclient_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_rsclient_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd); + install_element (RESTRICTED_NODE, &show_ip_bgp_route_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_route_pathtype_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_prefix_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_pathtype_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_view_route_cmd); @@ -16428,11 +17533,16 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd); install_element (ENABLE_NODE, &show_ip_bgp_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_route_pathtype_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_route_pathtype_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_pathtype_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_prefix_pathtype_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_prefix_pathtype_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_cmd); @@ -16473,10 +17583,13 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_prefix_longer_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_advertised_route_cmd); - install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_advertised_route_rmap_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_cmd); - install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd); - install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_rmap_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd); @@ -16506,17 +17619,26 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_rsclient_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_rsclient_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_rmap_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_rmap_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_prefix_counts_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_prefix_counts_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd); + install_element (VIEW_NODE, &show_bgp_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_cmd); install_element (VIEW_NODE, &show_bgp_route_cmd); install_element (VIEW_NODE, &show_bgp_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_route_pathtype_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_route_pathtype_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_route_pathtype_cmd); + install_element (VIEW_NODE, &show_bgp_prefix_pathtype_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_prefix_pathtype_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_pathtype_cmd); install_element (VIEW_NODE, &show_bgp_regexp_cmd); install_element (VIEW_NODE, &show_bgp_prefix_list_cmd); install_element (VIEW_NODE, &show_bgp_filter_list_cmd); @@ -16536,6 +17658,7 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_ipv6_safi_community_list_exact_cmd); install_element (VIEW_NODE, &show_bgp_prefix_longer_cmd); install_element (VIEW_NODE, &show_bgp_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &show_bgp_neighbor_received_routes_cmd); install_element (VIEW_NODE, &show_bgp_neighbor_routes_cmd); install_element (VIEW_NODE, &show_bgp_neighbor_received_prefix_filter_cmd); @@ -16546,7 +17669,9 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_view_route_cmd); install_element (VIEW_NODE, &show_bgp_view_prefix_cmd); install_element (VIEW_NODE, &show_bgp_view_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_bgp_view_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &show_bgp_view_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_bgp_view_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &show_bgp_view_neighbor_routes_cmd); install_element (VIEW_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd); install_element (VIEW_NODE, &show_bgp_view_neighbor_flap_cmd); @@ -16554,6 +17679,12 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd); install_element (RESTRICTED_NODE, &show_bgp_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_prefix_cmd); + install_element (RESTRICTED_NODE, &show_bgp_route_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_route_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_bgp_prefix_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_prefix_pathtype_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_prefix_pathtype_cmd); install_element (RESTRICTED_NODE, &show_bgp_community_cmd); install_element (RESTRICTED_NODE, &show_bgp_community2_cmd); install_element (RESTRICTED_NODE, &show_bgp_community3_cmd); @@ -16569,6 +17700,12 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_ipv6_cmd); install_element (ENABLE_NODE, &show_bgp_route_cmd); install_element (ENABLE_NODE, &show_bgp_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_route_pathtype_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_route_pathtype_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_route_pathtype_cmd); + install_element (ENABLE_NODE, &show_bgp_prefix_pathtype_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_pathtype_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_pathtype_cmd); install_element (ENABLE_NODE, &show_bgp_regexp_cmd); install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd); install_element (ENABLE_NODE, &show_bgp_filter_list_cmd); @@ -16587,6 +17724,7 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_community_list_exact_cmd); install_element (ENABLE_NODE, &show_bgp_prefix_longer_cmd); install_element (ENABLE_NODE, &show_bgp_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_neighbor_advertised_route_rmap_cmd); install_element (ENABLE_NODE, &show_bgp_neighbor_received_routes_cmd); install_element (ENABLE_NODE, &show_bgp_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_bgp_neighbor_received_prefix_filter_cmd); @@ -16597,6 +17735,8 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_view_route_cmd); install_element (ENABLE_NODE, &show_bgp_view_prefix_cmd); install_element (ENABLE_NODE, &show_bgp_view_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_bgp_view_neighbor_advertised_route_rmap_cmd); + install_element (ENABLE_NODE, &show_bgp_view_neighbor_received_routes_cmd); install_element (ENABLE_NODE, &show_bgp_view_neighbor_received_routes_cmd); install_element (ENABLE_NODE, &show_bgp_view_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd); @@ -16677,14 +17817,20 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_cmd); install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_exact_cmd); install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_longer_cmd); - install_element (VIEW_NODE, &ipv6_bgp_neighbor_advertised_route_cmd); - install_element (ENABLE_NODE, &ipv6_bgp_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_neighbor_advertised_route_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_neighbor_advertised_route_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_neighbor_advertised_route_rmap_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_neighbor_advertised_route_rmap_cmd); install_element (VIEW_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd); install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd); - install_element (VIEW_NODE, &ipv6_bgp_neighbor_received_routes_cmd); - install_element (ENABLE_NODE, &ipv6_bgp_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &ipv6_mbgp_neighbor_advertised_route_rmap_cmd); + install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_advertised_route_rmap_cmd); + install_element (VIEW_NODE, &show_ipv6_bgp_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_ipv6_bgp_neighbor_received_routes_cmd); install_element (VIEW_NODE, &ipv6_mbgp_neighbor_received_routes_cmd); install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &ipv6_mbgp_neighbor_received_routes_rmap_cmd); + install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_received_routes_rmap_cmd); install_element (VIEW_NODE, &ipv6_bgp_neighbor_routes_cmd); install_element (ENABLE_NODE, &ipv6_bgp_neighbor_routes_cmd); install_element (VIEW_NODE, &ipv6_mbgp_neighbor_routes_cmd); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index c8037592..b54a7941 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -21,8 +21,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #ifndef _QUAGGA_BGP_ROUTE_H #define _QUAGGA_BGP_ROUTE_H +#include "queue.h" #include "bgp_table.h" +struct bgp_nexthop_cache; + /* Ancillary information to struct bgp_info, * used for uncommonly used data (aggregation, MPLS, etc.) * and lazily allocated to save memory. @@ -47,7 +50,16 @@ struct bgp_info /* For linked list. */ struct bgp_info *next; struct bgp_info *prev; - + + /* For nexthop linked list */ + LIST_ENTRY(bgp_info) nh_thread; + + /* Back pointer to the prefix node */ + struct bgp_node *net; + + /* Back pointer to the nexthop structure */ + struct bgp_nexthop_cache *nexthop; + /* Peer structure. */ struct peer *peer; @@ -127,6 +139,10 @@ struct bgp_static u_char tag[3]; }; +#define BGP_INFO_COUNTABLE(BI) \ + (! CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY) \ + && ! CHECK_FLAG ((BI)->flags, BGP_INFO_REMOVED)) + /* Flags which indicate a route is unuseable in some form */ #define BGP_INFO_UNUSEABLE \ (BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED) @@ -172,7 +188,15 @@ enum bgp_clear_route_type BGP_CLEAR_ROUTE_MY_RSCLIENT }; +enum bgp_path_type +{ + BGP_PATH_ALL, + BGP_PATH_BESTPATH, + BGP_PATH_MULTIPATH +}; + /* Prototypes. */ +extern void bgp_process_queue_init (void); extern void bgp_route_init (void); extern void bgp_route_finish (void); extern void bgp_cleanup_routes (void); @@ -201,8 +225,8 @@ extern int bgp_nlri_parse_ip (struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int); extern void bgp_redistribute_add (struct prefix *, const struct in_addr *, - const struct in6_addr *, - u_int32_t, u_char); + const struct in6_addr *, unsigned int ifindex, + u_int32_t, u_char, u_short); extern void bgp_redistribute_delete (struct prefix *, u_char); extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int); @@ -226,6 +250,14 @@ extern int bgp_withdraw (struct peer *, struct prefix *, struct attr *, /* for bgp_nexthop and bgp_damp */ extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t); + +/* + * Add an end-of-initial-update marker to the process queue. This is just a + * queue element with NULL bgp node. + */ +extern void bgp_add_eoiu_mark (struct bgp *, bgp_table_t); +extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t, + int *); extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *); extern int bgp_config_write_distance (struct vty *, struct bgp *); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 39fa08c8..18ecc6c8 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -39,12 +39,15 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #endif /* HAVE_LIBPCREPOSIX */ #include "buffer.h" #include "sockunion.h" +#include "hash.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_aspath.h" +#include "bgpd/bgp_packet.h" #include "bgpd/bgp_route.h" +#include "bgpd/bgp_zebra.h" #include "bgpd/bgp_regex.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_clist.h" @@ -52,6 +55,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_vty.h" +#include "bgpd/bgp_debug.h" + /* Memo of route-map commands. @@ -59,7 +64,7 @@ o Cisco route-map match as-path : Done community : Done - interface : Not yet + interface : Done ip address : Done ip next-hop : Done ip route-source : Done @@ -71,7 +76,8 @@ o Cisco route-map length : (This will not be implemented by bgpd) metric : Done route-type : (This will not be implemented by bgpd) - tag : (This will not be implemented by bgpd) + tag : Done + local-preference : Done set as-path prepend : Done as-path tag : Not yet @@ -90,7 +96,7 @@ o Cisco route-map metric : Done metric-type : Not yet origin : Done - tag : (This will not be implemented by bgpd) + tag : Done weight : Done o Local extensions @@ -613,6 +619,72 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = route_match_ip_route_source_prefix_list_free }; +/* `match local-preference LOCAL-PREF' */ + +/* Match function return 1 if match is success else return zero. */ +static route_map_result_t +route_match_local_pref (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_int32_t *local_pref; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) + { + local_pref = rule; + bgp_info = object; + + if (bgp_info->attr->local_pref == *local_pref) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } + return RMAP_NOMATCH; +} + +/* Route map `match local-preference' match statement. + `arg' is local-pref value */ +static void * +route_match_local_pref_compile (const char *arg) +{ + u_int32_t *local_pref; + char *endptr = NULL; + unsigned long tmpval; + + /* Locpref value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + errno = 0; + tmpval = strtoul (arg, &endptr, 10); + if (*endptr != '\0' || errno || tmpval > UINT32_MAX) + return NULL; + + local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + + if (!local_pref) + return local_pref; + + *local_pref = tmpval; + return local_pref; +} + +/* Free route map's compiled `match local-preference' value. */ +static void +route_match_local_pref_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for metric matching. */ +struct route_map_rule_cmd route_match_local_pref_cmd = +{ + "local-preference", + route_match_local_pref, + route_match_local_pref_compile, + route_match_local_pref_free +}; + /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ @@ -657,9 +729,9 @@ route_match_aspath (void *rule, struct prefix *prefix, as_list = as_list_lookup ((char *) rule); if (as_list == NULL) return RMAP_NOMATCH; - + bgp_info = object; - + /* Perform match. */ return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH); } @@ -933,10 +1005,127 @@ struct route_map_rule_cmd route_match_probability_cmd = route_match_probability_free }; +/* `match interface IFNAME' */ +/* Match function should return 1 if match is success else return + zero. */ +static route_map_result_t +route_match_interface (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct interface *ifp; + struct bgp_info *info; + + if (type == RMAP_BGP) + { + info = object; + + if (!info || !info->attr) + return RMAP_NOMATCH; + + ifp = if_lookup_by_name ((char *)rule); + + if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex) + return RMAP_NOMATCH; + + return RMAP_MATCH; + } + return RMAP_NOMATCH; +} + +/* Route map `interface' match statement. `arg' should be + interface name. */ +static void * +route_match_interface_compile (const char *arg) +{ + return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); +} + +/* Free route map's compiled `interface' value. */ +static void +route_match_interface_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for ip address matching. */ +struct route_map_rule_cmd route_match_interface_cmd = +{ + "interface", + route_match_interface, + route_match_interface_compile, + route_match_interface_free +}; + /* } */ /* `set ip next-hop IP_ADDRESS' */ +/* Match function return 1 if match is success else return zero. */ +static route_map_result_t +route_match_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) + { + tag = rule; + bgp_info = object; + + if (!bgp_info->attr->extra) + return RMAP_NOMATCH; + + return ((bgp_info->attr->extra->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH); + } + + return RMAP_NOMATCH; +} + + +/* Route map `match tag' match statement. `arg' is TAG value */ +static void * +route_match_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + + +/* Free route map's compiled 'match tag' value. */ +static void +route_match_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag matching. */ +struct route_map_rule_cmd route_match_tag_cmd = +{ + "tag", + route_match_tag, + route_match_tag_compile, + route_match_tag_free, +}; + + /* Set nexthop to object. ojbect must be pointer to struct attr. */ struct rmap_ip_nexthop_set { @@ -1710,6 +1899,73 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = route_set_aggregator_as_free, }; +/* Set tag to object. object must be pointer to struct bgp_info */ +static route_map_result_t +route_set_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct bgp_info *bgp_info; + struct attr_extra *ae; + + if (type == RMAP_BGP) + { + tag = rule; + bgp_info = object; + ae = bgp_attr_extra_get (bgp_info->attr); + + /* Set tag value */ + ae->tag=*tag; + + } + + return RMAP_OKAY; +} + +/* Route map `tag' compile function. Given string is converted to u_short. */ +static void * +route_set_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + +/* Free route map's tag value. */ +static void +route_set_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + + +/* Route map commands for tag set. */ +struct route_map_rule_cmd route_set_tag_cmd = +{ + "tag", + route_set_tag, + route_set_tag_compile, + route_set_tag_free, +}; + + /* `match ipv6 address IP_ACCESS_LIST' */ static route_map_result_t @@ -2187,7 +2443,8 @@ struct route_map_rule_cmd route_set_originator_id_cmd = /* Add bgp route map rule. */ static int bgp_route_match_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) + const char *command, const char *arg, + route_map_event_t type) { int ret; @@ -2197,36 +2454,71 @@ bgp_route_match_add (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } + + if (type != RMAP_EVENT_MATCH_ADDED) + { + route_map_upd8_dependency (type, arg, index->map->name); + } + return CMD_SUCCESS; } /* Delete bgp route map rule. */ static int bgp_route_match_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) + const char *command, const char *arg, + route_map_event_t type) { int ret; + char *dep_name = (char *)arg; + const char *tmpstr; + char *rmap_name = NULL; + + if (type != RMAP_EVENT_MATCH_DELETED) + { + /* ignore the mundane, the types without any dependency */ + if (arg == NULL) + { + if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) + dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); + } + rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); + } - ret = route_map_delete_match (index, command, arg); + ret = route_map_delete_match (index, command, dep_name); if (ret) { switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); - return CMD_WARNING; + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); + break; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); - return CMD_WARNING; + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); + break; } + if (arg == NULL && dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + return CMD_WARNING; } + + if (type != RMAP_EVENT_MATCH_DELETED && dep_name) + route_map_upd8_dependency(type, dep_name, rmap_name); + + if (arg == NULL && dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + return CMD_SUCCESS; } @@ -2243,10 +2535,10 @@ bgp_route_set_add (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } @@ -2266,134 +2558,363 @@ bgp_route_set_delete (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } return CMD_SUCCESS; } -/* Hook function for updating route_map assignment. */ +/* + * This is the workhorse routine for processing in/out/import/export routemap + * modifications. + */ static void -bgp_route_map_update (const char *unused) +bgp_route_map_process_peer (const char *rmap_name, struct peer *peer, + int afi, int safi, int route_update) { - int i; - afi_t afi; - safi_t safi; - int direct; - struct listnode *node, *nnode; - struct listnode *mnode, *mnnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; + + int update; struct bgp_filter *filter; - struct bgp_node *bn; - struct bgp_static *bgp_static; if (bm->bgp == NULL) /* may be called during cleanup */ return; - /* For neighbor route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) + if (!peer || !rmap_name) + return; + + filter = &peer->filter[afi][safi]; + /* + * in is for non-route-server clients, + * import/export is for route-server clients, + * out is for all peers + */ + if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + if (filter->map[RMAP_IN].name && + (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &peer->filter[afi][safi]; - - for (direct = RMAP_IN; direct < RMAP_MAX; direct++) - { - if (filter->map[direct].name) - filter->map[direct].map = - route_map_lookup_by_name (filter->map[direct].name); - else - filter->map[direct].map = NULL; - } - - if (filter->usmap.name) - filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); - else - filter->usmap.map = NULL; - } + filter->map[RMAP_IN].map = + route_map_lookup_by_name (filter->map[RMAP_IN].name); + + if (route_update && peer->status == Established) + { + if (CHECK_FLAG (peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + { + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (inbound, soft-reconfig)", + rmap_name, peer->host); + + bgp_soft_reconfig_in (peer, afi, safi); + } + else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + { + + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (inbound, route-refresh)", + rmap_name, peer->host); + bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); + } + } + } + } + + if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) + { + update = 0; + + if (filter->map[RMAP_IMPORT].name && + (strcmp(rmap_name, filter->map[RMAP_IMPORT].name) == 0)) + { + filter->map[RMAP_IMPORT].map = + route_map_lookup_by_name (filter->map[RMAP_IMPORT].name); + update = 1; } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) + + if (filter->map[RMAP_EXPORT].name && + (strcmp(rmap_name, filter->map[RMAP_EXPORT].name) == 0)) { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; - - for (direct = RMAP_IN; direct < RMAP_MAX; direct++) - { - if (filter->map[direct].name) - filter->map[direct].map = - route_map_lookup_by_name (filter->map[direct].name); - else - filter->map[direct].map = NULL; - } - - if (filter->usmap.name) - filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); - else - filter->usmap.map = NULL; - } + filter->map[RMAP_EXPORT].map = + route_map_lookup_by_name (filter->map[RMAP_EXPORT].name); + + update = 1; + } + + if (update && route_update && peer->status == Established) + { + if (CHECK_FLAG (peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + { + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (import, soft-reconfig)", + rmap_name, peer->host); + + bgp_soft_reconfig_in (peer, afi, safi); + } + else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + { + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug("Processing route_map %s update on " + "peer %s (import, route-refresh)", + rmap_name, peer->host); + bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); + } + /* DD: Else, what else do we do ? Reset peer ? */ } } - /* For default-originate route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + if (filter->map[RMAP_OUT].name && + (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0)) { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (peer->default_rmap[afi][safi].name) - peer->default_rmap[afi][safi].map = - route_map_lookup_by_name (peer->default_rmap[afi][safi].name); - else - peer->default_rmap[afi][safi].map = NULL; - } + filter->map[RMAP_OUT].map = + route_map_lookup_by_name (filter->map[RMAP_OUT].name); + + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("Processing route_map %s update on peer %s (outbound)", + rmap_name, peer->host); + + if (route_update) + bgp_announce_route_all(peer); } + + if (filter->usmap.name && + (strcmp(rmap_name, filter->usmap.name) == 0)) + { + filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); + if (route_update) + bgp_announce_route_all(peer); } +} - /* For network route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) +static void +bgp_route_map_update_peer_group(const char *rmap_name, struct bgp *bgp) +{ + struct peer_group *group; + struct listnode *node, *nnode; + struct bgp_filter *filter; + int afi, safi; + int direct; + + if (!bgp) + return; + + /* All the peers have been updated correctly already. This is + * just updating the placeholder data. No real update required. + */ + for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + filter = &group->conf->filter[afi][safi]; + + for (direct = RMAP_IN; direct < RMAP_MAX; direct++) + { + if ((filter->map[direct].name) && + (strcmp(rmap_name, filter->map[direct].name) == 0)) + filter->map[direct].map = + route_map_lookup_by_name (filter->map[direct].name); + } + + if (filter->usmap.name && + (strcmp(rmap_name, filter->usmap.name) == 0)) + filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); + } +} + +static int +bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update) +{ + int i; + afi_t afi; + safi_t safi; + struct peer *peer; + struct bgp_node *bn; + struct bgp_static *bgp_static; + struct bgp *bgp = (struct bgp *)arg; + struct listnode *node, *nnode; + char buf[INET6_ADDRSTRLEN]; + + if (!bgp) + return -1; + + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { + + /* Ignore dummy peer-group structure */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + continue; + for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - for (bn = bgp_table_top (bgp->route[afi][safi]); bn; - bn = bgp_route_next (bn)) - if ((bgp_static = bn->info) != NULL) + { + /* Ignore inactive AFI/SAFI */ + if (! peer->afc[afi][safi]) + continue; + + /* process in/out/import/export route-maps */ + bgp_route_map_process_peer(rmap_name, peer, afi, safi, route_update); + + /* process default-originate route-map */ + if (peer->default_rmap[afi][safi].name && + (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0)) { - if (bgp_static->rmap.name) - bgp_static->rmap.map = - route_map_lookup_by_name (bgp_static->rmap.name); - else - bgp_static->rmap.map = NULL; + peer->default_rmap[afi][safi].map = + route_map_lookup_by_name (peer->default_rmap[afi][safi].name); + + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("Processing route_map %s update on " + "default-originate", rmap_name); + + if (route_update) + bgp_default_originate (peer, afi, safi, 0); } + } } + bgp_route_map_update_peer_group(rmap_name, bgp); + + /* For table route-map updates. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + if (bgp->table_map[afi][safi].name && + (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0)) + { + bgp->table_map[afi][safi].map = + route_map_lookup_by_name (bgp->table_map[afi][safi].name); + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Processing route_map %s update on " + "table map", rmap_name); + if (route_update) + bgp_zebra_announce_table(bgp, afi, safi); + } + } + + /* For network route-map updates. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + for (bn = bgp_table_top (bgp->route[afi][safi]); bn; + bn = bgp_route_next (bn)) + if ((bgp_static = bn->info) != NULL) + { + if (bgp_static->rmap.name && + (strcmp(rmap_name, bgp_static->rmap.name) == 0)) + { + bgp_static->rmap.map = + route_map_lookup_by_name (bgp_static->rmap.name); + if (route_update) + if (!bgp_static->backdoor) + { + if (bgp_debug_zebra(&bn->p)) + zlog_debug("Processing route_map %s update on " + "static route %s", rmap_name, + inet_ntop (bn->p.family, &bn->p.u.prefix, + buf, INET6_ADDRSTRLEN)); + bgp_static_update (bgp, &bn->p, bgp_static, afi, safi); + } + } + } + /* For redistribute route-map updates. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + { + if (bgp->rmap[afi][i].name && + (strcmp(rmap_name, bgp->rmap[afi][i].name) == 0)) + { + bgp->rmap[afi][i].map = + route_map_lookup_by_name (bgp->rmap[afi][i].name); + + if (bgp->redist[afi][i] && route_update) + { + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Processing route_map %s update on " + "redistributed routes", rmap_name); + + bgp_redistribute_resend (bgp, afi, i); + } + } + } + + return 0; +} + +static int +bgp_route_map_process_update_cb (void *arg, char *rmap_name) +{ + return bgp_route_map_process_update (arg, rmap_name, 1); +} + +int +bgp_route_map_update_timer(struct thread *thread) +{ + struct bgp *bgp = THREAD_ARG(thread); + + bgp->t_rmap_update = NULL; + + route_map_walk_update_list((void *)bgp, bgp_route_map_process_update_cb); + + return (0); +} + +static void +bgp_route_map_mark_update (const char *rmap_name) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (bgp->t_rmap_update == NULL) { - if (bgp->rmap[AFI_IP][i].name) - bgp->rmap[AFI_IP][i].map = - route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name); - if (bgp->rmap[AFI_IP6][i].name) - bgp->rmap[AFI_IP6][i].map = - route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name); + /* rmap_update_timer of 0 means don't do route updates */ + if (bgp->rmap_update_timer) + bgp->t_rmap_update = + thread_add_timer(bm->master, bgp_route_map_update_timer, bgp, + bgp->rmap_update_timer); + else + bgp_route_map_process_update((void *)bgp, rmap_name, 0); } } } +static void +bgp_route_map_add (const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 0) == 0) + bgp_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +} + +static void +bgp_route_map_delete (const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 1) == 0) + bgp_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); +} + +static void +bgp_route_map_event (route_map_event_t event, const char *rmap_name) +{ + if (route_map_mark_updated(rmap_name, 0) == 0) + bgp_route_map_mark_update(rmap_name); + + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); +} + + DEFUN (match_peer, match_peer_cmd, "match peer (A.B.C.D|X:X::X:X)", @@ -2402,7 +2923,8 @@ DEFUN (match_peer, "IPv6 address of peer\n" "IP address of peer\n") { - return bgp_route_match_add (vty, vty->index, "peer", argv[0]); + return bgp_route_match_add (vty, vty->index, "peer", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (match_peer_local, @@ -2412,7 +2934,8 @@ DEFUN (match_peer_local, "Match peer address\n" "Static or Redistributed routes\n") { - return bgp_route_match_add (vty, vty->index, "peer", "local"); + return bgp_route_match_add (vty, vty->index, "peer", "local", + RMAP_EVENT_MATCH_DELETED); } DEFUN (no_match_peer, @@ -2423,9 +2946,11 @@ DEFUN (no_match_peer, "Match peer address\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "peer", NULL); + return bgp_route_match_delete (vty, vty->index, "peer", NULL, + RMAP_EVENT_MATCH_DELETED); - return bgp_route_match_delete (vty, vty->index, "peer", argv[0]); + return bgp_route_match_delete (vty, vty->index, "peer", argv[0], + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_peer, @@ -2455,7 +2980,8 @@ DEFUN (match_ip_address, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip address", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip address", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ip_address, @@ -2467,9 +2993,11 @@ DEFUN (no_match_ip_address, "Match address of route\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip address", NULL); + return bgp_route_match_delete (vty, vty->index, "ip address", NULL, + RMAP_EVENT_FILTER_DELETED); - return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip address", argv[0], + RMAP_EVENT_FILTER_DELETED); } ALIAS (no_match_ip_address, @@ -2493,7 +3021,8 @@ DEFUN (match_ip_next_hop, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ip_next_hop, @@ -2505,9 +3034,11 @@ DEFUN (no_match_ip_next_hop, "Match next-hop address of route\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL); + return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL, + RMAP_EVENT_FILTER_DELETED); - return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0], + RMAP_EVENT_FILTER_DELETED); } ALIAS (no_match_ip_next_hop, @@ -2530,7 +3061,8 @@ DEFUN (match_probability, "Match portion of routes defined by percentage value\n" "Percentage of routes\n") { - return bgp_route_match_add (vty, vty->index, "probability", argv[0]); + return bgp_route_match_add (vty, vty->index, "probability", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_probability, @@ -2540,7 +3072,8 @@ DEFUN (no_match_probability, MATCH_STR "Match portion of routes defined by percentage value\n") { - return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL); + return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL, + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_probability, @@ -2563,7 +3096,8 @@ DEFUN (match_ip_route_source, "IP access-list number (expanded range)\n" "IP standard access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ip_route_source, @@ -2575,9 +3109,11 @@ DEFUN (no_match_ip_route_source, "Match advertising source address of route\n") { if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL); + return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL, + RMAP_EVENT_FILTER_DELETED); - return bgp_route_match_delete (vty, vty->index, "ip route-source", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip route-source", + argv[0], RMAP_EVENT_FILTER_DELETED); } ALIAS (no_match_ip_route_source, @@ -2600,7 +3136,8 @@ DEFUN (match_ip_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip address prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ip_address_prefix_list, @@ -2612,10 +3149,9 @@ DEFUN (no_match_ip_address_prefix_list, "Match address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL); - - return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_PLIST_DELETED); } ALIAS (no_match_ip_address_prefix_list, @@ -2637,7 +3173,8 @@ DEFUN (match_ip_next_hop_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ip_next_hop_prefix_list, @@ -2649,10 +3186,9 @@ DEFUN (no_match_ip_next_hop_prefix_list, "Match next-hop address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL); - - return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_PLIST_DELETED); } ALIAS (no_match_ip_next_hop_prefix_list, @@ -2674,7 +3210,8 @@ DEFUN (match_ip_route_source_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ip_route_source_prefix_list, @@ -2686,10 +3223,9 @@ DEFUN (no_match_ip_route_source_prefix_list, "Match advertising source address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", NULL); - - return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_PLIST_DELETED); } ALIAS (no_match_ip_route_source_prefix_list, @@ -2709,7 +3245,8 @@ DEFUN (match_metric, "Match metric of route\n" "Metric value\n") { - return bgp_route_match_add (vty, vty->index, "metric", argv[0]); + return bgp_route_match_add (vty, vty->index, "metric", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_metric, @@ -2719,10 +3256,9 @@ DEFUN (no_match_metric, MATCH_STR "Match metric of route\n") { - if (argc == 0) - return bgp_route_match_delete (vty, vty->index, "metric", NULL); - - return bgp_route_match_delete (vty, vty->index, "metric", argv[0]); + return bgp_route_match_delete (vty, vty->index, "metric", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_metric, @@ -2733,6 +3269,40 @@ ALIAS (no_match_metric, "Match metric of route\n" "Metric value\n") +DEFUN (match_local_pref, + match_local_pref_cmd, + "match local-preference <0-4294967295>", + MATCH_STR + "Match local-preference of route\n" + "Metric value\n") +{ + return bgp_route_match_add (vty, vty->index, "local-preference", argv[0], + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_local_pref, + no_match_local_pref_cmd, + "no match local-preference", + NO_STR + MATCH_STR + "Match local preference of route\n") +{ + return bgp_route_match_delete (vty, vty->index, "local-preference", + argc == 0 ? NULL : argv[0], + RMAP_EVENT_MATCH_DELETED); + + return bgp_route_match_delete (vty, vty->index, "local-preference", argv[0], + RMAP_EVENT_MATCH_DELETED); +} + +ALIAS (no_match_local_pref, + no_match_local_pref_val_cmd, + "no match local-preference <0-4294967295>", + NO_STR + MATCH_STR + "Match local preference of route\n" + "Local preference value\n") + DEFUN (match_community, match_community_cmd, "match community (<1-99>|<100-500>|WORD)", @@ -2742,7 +3312,8 @@ DEFUN (match_community, "Community-list number (expanded)\n" "Community-list name\n") { - return bgp_route_match_add (vty, vty->index, "community", argv[0]); + return bgp_route_match_add (vty, vty->index, "community", argv[0], + RMAP_EVENT_CLIST_ADDED); } DEFUN (match_community_exact, @@ -2763,7 +3334,8 @@ DEFUN (match_community_exact, sprintf (argstr, "%s exact-match", argv[0]); - ret = bgp_route_match_add (vty, vty->index, "community", argstr); + ret = bgp_route_match_add (vty, vty->index, "community", argstr, + RMAP_EVENT_CLIST_ADDED); XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr); @@ -2777,7 +3349,8 @@ DEFUN (no_match_community, MATCH_STR "Match BGP community list\n") { - return bgp_route_match_delete (vty, vty->index, "community", NULL); + return bgp_route_match_delete (vty, vty->index, "community", NULL, + RMAP_EVENT_CLIST_DELETED); } ALIAS (no_match_community, @@ -2810,7 +3383,8 @@ DEFUN (match_ecommunity, "Extended community-list number (expanded)\n" "Extended community-list name\n") { - return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0]); + return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0], + RMAP_EVENT_ECLIST_ADDED); } DEFUN (no_match_ecommunity, @@ -2820,7 +3394,8 @@ DEFUN (no_match_ecommunity, MATCH_STR "Match BGP/VPN extended community list\n") { - return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL); + return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL, + RMAP_EVENT_ECLIST_DELETED); } ALIAS (no_match_ecommunity, @@ -2840,7 +3415,8 @@ DEFUN (match_aspath, "Match BGP AS path list\n" "AS path access-list name\n") { - return bgp_route_match_add (vty, vty->index, "as-path", argv[0]); + return bgp_route_match_add (vty, vty->index, "as-path", argv[0], + RMAP_EVENT_ASLIST_ADDED); } DEFUN (no_match_aspath, @@ -2850,7 +3426,8 @@ DEFUN (no_match_aspath, MATCH_STR "Match BGP AS path list\n") { - return bgp_route_match_delete (vty, vty->index, "as-path", NULL); + return bgp_route_match_delete (vty, vty->index, "as-path", NULL, + RMAP_EVENT_ASLIST_DELETED); } ALIAS (no_match_aspath, @@ -2871,11 +3448,14 @@ DEFUN (match_origin, "unknown heritage\n") { if (strncmp (argv[0], "igp", 2) == 0) - return bgp_route_match_add (vty, vty->index, "origin", "igp"); + return bgp_route_match_add (vty, vty->index, "origin", "igp", + RMAP_EVENT_MATCH_ADDED); if (strncmp (argv[0], "egp", 1) == 0) - return bgp_route_match_add (vty, vty->index, "origin", "egp"); + return bgp_route_match_add (vty, vty->index, "origin", "egp", + RMAP_EVENT_MATCH_ADDED); if (strncmp (argv[0], "incomplete", 2) == 0) - return bgp_route_match_add (vty, vty->index, "origin", "incomplete"); + return bgp_route_match_add (vty, vty->index, "origin", "incomplete", + RMAP_EVENT_MATCH_ADDED); return CMD_WARNING; } @@ -2887,7 +3467,8 @@ DEFUN (no_match_origin, MATCH_STR "BGP origin code\n") { - return bgp_route_match_delete (vty, vty->index, "origin", NULL); + return bgp_route_match_delete (vty, vty->index, "origin", NULL, + RMAP_EVENT_MATCH_DELETED); } ALIAS (no_match_origin, @@ -2900,6 +3481,75 @@ ALIAS (no_match_origin, "local IGP\n" "unknown heritage\n") +DEFUN (match_interface, + match_interface_cmd, + "match interface WORD", + MATCH_STR + "Match first hop interface of route\n" + "Interface name\n") +{ + return bgp_route_match_add (vty, vty->index, "interface", argv[0], + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_interface, + no_match_interface_cmd, + "no match interface", + NO_STR + MATCH_STR + "Match first hop interface of route\n") +{ + if (argc == 0) + return bgp_route_match_delete (vty, vty->index, "interface", NULL, + RMAP_EVENT_MATCH_DELETED); + + return bgp_route_match_delete (vty, vty->index, "interface", argv[0], + RMAP_EVENT_MATCH_DELETED); +} + +ALIAS (no_match_interface, + no_match_interface_val_cmd, + "no match interface WORD", + NO_STR + MATCH_STR + "Match first hop interface of route\n" + "Interface name\n") + +DEFUN (match_tag, + match_tag_cmd, + "match tag <1-65535>", + MATCH_STR + "Match tag of route\n" + "Tag value\n") +{ + return bgp_route_match_add (vty, vty->index, "tag", argv[0], + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_tag, + no_match_tag_cmd, + "no match tag", + NO_STR + MATCH_STR + "Match tag of route\n") +{ + if (argc == 0) + return bgp_route_match_delete (vty, vty->index, "tag", NULL, + RMAP_EVENT_MATCH_DELETED); + + return bgp_route_match_delete (vty, vty->index, "tag", argv[0], + RMAP_EVENT_MATCH_DELETED); +} + +ALIAS (no_match_tag, + no_match_tag_val_cmd, + "no match tag <1-65535>", + NO_STR + MATCH_STR + "Match tag of route\n" + "Tag value\n") + + DEFUN (set_ip_nexthop, set_ip_nexthop_cmd, "set ip next-hop A.B.C.D", @@ -3313,7 +3963,7 @@ DEFUN (set_community_delete, SET_STR "set BGP community list (for deletion)\n" "Community-list number (standard)\n" - "Communitly-list number (expanded)\n" + "Community-list number (expanded)\n" "Community-list name\n" "Delete matching communities\n") { @@ -3346,7 +3996,7 @@ ALIAS (no_set_community_delete, SET_STR "set BGP community list (for deletion)\n" "Community-list number (standard)\n" - "Communitly-list number (expanded)\n" + "Community-list number (expanded)\n" "Community-list name\n" "Delete matching communities\n") @@ -3565,6 +4215,38 @@ ALIAS (no_set_aggregator_as, "AS number\n" "IP address of aggregator\n") +DEFUN (set_tag, + set_tag_cmd, + "set tag <1-65535>", + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") +{ + return bgp_route_set_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_set_tag, + no_set_tag_cmd, + "no set tag", + NO_STR + SET_STR + "Tag value for routing protocol\n") +{ + if (argc == 0) + bgp_route_set_delete(vty, vty->index, "tag", NULL); + + return bgp_route_set_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_set_tag, + no_set_tag_val_cmd, + "no set tag <1-65535>", + NO_STR + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") + + DEFUN (match_ipv6_address, match_ipv6_address_cmd, "match ipv6 address WORD", @@ -3573,7 +4255,8 @@ DEFUN (match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]); + return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0], + RMAP_EVENT_FILTER_ADDED); } DEFUN (no_match_ipv6_address, @@ -3585,7 +4268,8 @@ DEFUN (no_match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0], + RMAP_EVENT_FILTER_DELETED); } DEFUN (match_ipv6_next_hop, @@ -3596,7 +4280,8 @@ DEFUN (match_ipv6_next_hop, "Match IPv6 next-hop address of route\n" "IPv6 address of next hop\n") { - return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]); + return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0], + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_ipv6_next_hop, @@ -3608,7 +4293,8 @@ DEFUN (no_match_ipv6_next_hop, "Match IPv6 next-hop address of route\n" "IPv6 address of next hop\n") { - return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0], + RMAP_EVENT_MATCH_DELETED); } DEFUN (match_ipv6_address_prefix_list, @@ -3620,7 +4306,8 @@ DEFUN (match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]); + return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", + argv[0], RMAP_EVENT_PLIST_ADDED); } DEFUN (no_match_ipv6_address_prefix_list, @@ -3633,7 +4320,8 @@ DEFUN (no_match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]); + return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", + argv[0], RMAP_EVENT_PLIST_DELETED); } DEFUN (set_ipv6_nexthop_peer, @@ -3863,10 +4551,12 @@ bgp_route_map_init (void) { route_map_init (); route_map_init_vty (); - route_map_add_hook (bgp_route_map_update); - route_map_delete_hook (bgp_route_map_update); + route_map_add_hook (bgp_route_map_add); + route_map_delete_hook (bgp_route_map_delete); + route_map_event_hook (bgp_route_map_event); route_map_install_match (&route_match_peer_cmd); + route_map_install_match (&route_match_local_pref_cmd); route_map_install_match (&route_match_ip_address_cmd); route_map_install_match (&route_match_ip_next_hop_cmd); route_map_install_match (&route_match_ip_route_source_cmd); @@ -3876,9 +4566,12 @@ bgp_route_map_init (void) route_map_install_match (&route_match_aspath_cmd); route_map_install_match (&route_match_community_cmd); route_map_install_match (&route_match_ecommunity_cmd); + route_map_install_match (&route_match_local_pref_cmd); route_map_install_match (&route_match_metric_cmd); route_map_install_match (&route_match_origin_cmd); route_map_install_match (&route_match_probability_cmd); + route_map_install_match (&route_match_interface_cmd); + route_map_install_match (&route_match_tag_cmd); route_map_install_set (&route_set_ip_nexthop_cmd); route_map_install_set (&route_set_local_pref_cmd); @@ -3895,6 +4588,7 @@ bgp_route_map_init (void) route_map_install_set (&route_set_originator_id_cmd); route_map_install_set (&route_set_ecommunity_rt_cmd); route_map_install_set (&route_set_ecommunity_soo_cmd); + route_map_install_set (&route_set_tag_cmd); install_element (RMAP_NODE, &match_peer_cmd); install_element (RMAP_NODE, &match_peer_local_cmd); @@ -3926,6 +4620,9 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &match_metric_cmd); install_element (RMAP_NODE, &no_match_metric_cmd); install_element (RMAP_NODE, &no_match_metric_val_cmd); + install_element (RMAP_NODE, &match_local_pref_cmd); + install_element (RMAP_NODE, &no_match_local_pref_cmd); + install_element (RMAP_NODE, &no_match_local_pref_val_cmd); install_element (RMAP_NODE, &match_community_cmd); install_element (RMAP_NODE, &match_community_exact_cmd); install_element (RMAP_NODE, &no_match_community_cmd); @@ -3940,6 +4637,12 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &match_probability_cmd); install_element (RMAP_NODE, &no_match_probability_cmd); install_element (RMAP_NODE, &no_match_probability_val_cmd); + install_element (RMAP_NODE, &match_interface_cmd); + install_element (RMAP_NODE, &no_match_interface_cmd); + install_element (RMAP_NODE, &no_match_interface_val_cmd); + install_element (RMAP_NODE, &match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_val_cmd); install_element (RMAP_NODE, &set_ip_nexthop_cmd); install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd); @@ -3991,6 +4694,9 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &set_originator_id_cmd); install_element (RMAP_NODE, &no_set_originator_id_cmd); install_element (RMAP_NODE, &no_set_originator_id_val_cmd); + install_element (RMAP_NODE, &set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_val_cmd); route_map_install_match (&route_match_ipv6_address_cmd); route_map_install_match (&route_match_ipv6_next_hop_cmd); @@ -4024,3 +4730,15 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &no_match_pathlimit_as_cmd); install_element (RMAP_NODE, &no_match_pathlimit_as_val_cmd); } + +void +bgp_route_map_terminate (void) +{ + /* ToDo: Cleanup all the used memory */ + + route_map_add_hook (NULL); + route_map_delete_hook (NULL); + route_map_event_hook (NULL); + route_map_finish(); + +} diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 92bb9575..e66e0451 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "vty.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index bee12963..9531b69a 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -65,6 +65,7 @@ struct bgp_node u_char flags; #define BGP_NODE_PROCESS_SCHEDULED (1 << 0) +#define BGP_NODE_USER_CLEAR (1 << 1) }; /* diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6db3dcb1..5476a669 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -50,6 +50,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_table.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_mpath.h" +#include "bgpd/bgp_packet.h" extern struct in_addr router_id_zebra; @@ -166,15 +167,22 @@ peer_lookup_vty (struct vty *vty, const char *ip_str) ret = str2sockunion (ip_str, &su); if (ret < 0) { - vty_out (vty, "%% Malformed address: %s%s", ip_str, VTY_NEWLINE); - return NULL; + peer = peer_lookup_by_conf_if (bgp, ip_str); + if (!peer) + { + vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE); + return NULL; + } } - - peer = peer_lookup (bgp, &su); - if (! peer) + else { - vty_out (vty, "%% Specify remote-as or peer-group commands first%s", VTY_NEWLINE); - return NULL; + peer = peer_lookup (bgp, &su); + if (! peer) + { + vty_out (vty, "%% Specify remote-as or peer-group commands first%s", + VTY_NEWLINE); + return NULL; + } } return peer; } @@ -200,6 +208,10 @@ peer_and_group_lookup_vty (struct vty *vty, const char *peer_str) } else { + peer = peer_lookup_by_conf_if (bgp, peer_str); + if (peer) + return peer; + group = peer_group_lookup (bgp, peer_str); if (group) return group->conf; @@ -264,7 +276,7 @@ bgp_vty_return (struct vty *vty, int ret) str = "Invalid command. Not an internal neighbor"; break; case BGP_ERR_REMOVE_PRIVATE_AS: - str = "Private AS cannot be removed for IBGP peers"; + str = "remove-private-AS cannot be configured for IBGP peers"; break; case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP: str = "Local-AS allowed only for EBGP peers"; @@ -281,6 +293,9 @@ bgp_vty_return (struct vty *vty, int ret) case BGP_ERR_NO_IBGP_WITH_TTLHACK: str = "ttl-security only allowed for EBGP peers"; break; + case BGP_ERR_AS_OVERRIDE: + str = "as-override cannot be configured for IBGP peers"; + break; } if (str) { @@ -712,87 +727,408 @@ DEFUN (no_bgp_confederation_peers, return CMD_SUCCESS; } -/* Maximum-paths configuration */ -DEFUN (bgp_maxpaths, - bgp_maxpaths_cmd, - "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM), - "Forward packets over multiple paths\n" - "Number of paths\n") +/** + * Central routine for maximum-paths configuration. + * @peer_type: BGP_PEER_EBGP or BGP_PEER_IBGP + * @set: 1 for setting values, 0 for removing the max-paths config. + */ +static int +bgp_maxpaths_config_vty (struct vty *vty, int peer_type, const char *mpaths, + u_int16_t options, int set) { struct bgp *bgp; - u_int16_t maxpaths; + u_int16_t maxpaths = 0; int ret; + afi_t afi; + safi_t safi; bgp = vty->index; + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); - VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, argv[0], 1, 255); + if (set) + { + VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, mpaths, 1, + BGP_MAXIMUM_MAXPATHS); + ret = bgp_maximum_paths_set (bgp, afi, safi, peer_type, maxpaths, + options); + } + else + ret = bgp_maximum_paths_unset (bgp, afi, safi, peer_type); - ret = bgp_maximum_paths_set (bgp, bgp_node_afi (vty), bgp_node_safi(vty), - BGP_PEER_EBGP, maxpaths); if (ret < 0) { vty_out (vty, - "%% Failed to set maximum-paths %u for afi %u, safi %u%s", - maxpaths, bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE); + "%% Failed to %sset maximum-paths %s %u for afi %u, safi %u%s", + (set == 1) ? "" : "un", + (peer_type == BGP_PEER_EBGP) ? "ebgp" : "ibgp", + maxpaths, afi, safi, VTY_NEWLINE); return CMD_WARNING; } return CMD_SUCCESS; } -DEFUN (bgp_maxpaths_ibgp, - bgp_maxpaths_ibgp_cmd, - "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM), - "Forward packets over multiple paths\n" - "iBGP-multipath\n" - "Number of paths\n") +DEFUN (bgp_maxmed_admin, + bgp_maxmed_admin_cmd, + "bgp max-med administrative ", + BGP_STR + "Advertise routes with max-med\n" + "Administratively applied, for an indefinite period\n") { struct bgp *bgp; - u_int16_t maxpaths; - int ret; bgp = vty->index; - VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, argv[0], 1, 255); + bgp->v_maxmed_admin = 1; + bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; - ret = bgp_maximum_paths_set (bgp, bgp_node_afi (vty), bgp_node_safi(vty), - BGP_PEER_IBGP, maxpaths); - if (ret < 0) + bgp_maxmed_update(bgp); + + return CMD_SUCCESS; +} + +DEFUN (bgp_maxmed_admin_medv, + bgp_maxmed_admin_medv_cmd, + "bgp max-med administrative <0-4294967294>", + BGP_STR + "Advertise routes with max-med\n" + "Administratively applied, for an indefinite period\n" + "Max MED value to be used\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + bgp->v_maxmed_admin = 1; + VTY_GET_INTEGER ("max-med admin med-value", bgp->maxmed_admin_value, argv[0]); + + bgp_maxmed_update(bgp); + + return CMD_SUCCESS; +} + +DEFUN (no_bgp_maxmed_admin, + no_bgp_maxmed_admin_cmd, + "no bgp max-med administrative", + NO_STR + BGP_STR + "Advertise routes with max-med\n" + "Administratively applied, for an indefinite period\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + bgp->v_maxmed_admin = BGP_MAXMED_ADMIN_UNCONFIGURED; + bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; + + bgp_maxmed_update(bgp); + + return CMD_SUCCESS; +} + +ALIAS (no_bgp_maxmed_admin, + no_bgp_maxmed_admin_medv_cmd, + "no bgp max-med administrative <0-4294967294>", + NO_STR + BGP_STR + "Advertise routes with max-med\n" + "Administratively applied, for an indefinite period\n" + "Max MED value to be used\n") + + +DEFUN (bgp_maxmed_onstartup, + bgp_maxmed_onstartup_cmd, + "bgp max-med on-startup <5-86400>", + BGP_STR + "Advertise routes with max-med\n" + "Effective on a startup\n" + "Time (seconds) period for max-med\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + if (argc != 1) { - vty_out (vty, - "%% Failed to set maximum-paths ibgp %u for afi %u, safi %u%s", - maxpaths, bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE); + vty_out (vty, "%% Must supply max-med on-startup period"); return CMD_WARNING; } + VTY_GET_INTEGER ("max-med on-startup period", bgp->v_maxmed_onstartup, argv[0]); + bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; + + bgp_maxmed_update(bgp); + return CMD_SUCCESS; } -DEFUN (no_bgp_maxpaths, - no_bgp_maxpaths_cmd, - "no maximum-paths", +DEFUN (bgp_maxmed_onstartup_medv, + bgp_maxmed_onstartup_medv_cmd, + "bgp max-med on-startup <5-86400> <0-4294967294>", + BGP_STR + "Advertise routes with max-med\n" + "Effective on a startup\n" + "Time (seconds) period for max-med\n" + "Max MED value to be used\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + if (argc != 2) + { + vty_out (vty, "%% Must supply max-med on-startup period and med value"); + return CMD_WARNING; + } + + VTY_GET_INTEGER ("max-med on-startup period", bgp->v_maxmed_onstartup, argv[0]); + VTY_GET_INTEGER ("max-med on-startup med-value", bgp->maxmed_onstartup_value, argv[1]); + + bgp_maxmed_update(bgp); + + return CMD_SUCCESS; +} + +DEFUN (no_bgp_maxmed_onstartup, + no_bgp_maxmed_onstartup_cmd, + "no bgp max-med on-startup", NO_STR - "Forward packets over multiple paths\n" - "Number of paths\n") + BGP_STR + "Advertise routes with max-med\n" + "Effective on a startup\n") { struct bgp *bgp; - int ret; bgp = vty->index; - ret = bgp_maximum_paths_unset (bgp, bgp_node_afi (vty), bgp_node_safi(vty), - BGP_PEER_EBGP); - if (ret < 0) + /* Cancel max-med onstartup if its on */ + if (bgp->t_maxmed_onstartup) { - vty_out (vty, - "%% Failed to unset maximum-paths for afi %u, safi %u%s", - bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE); + THREAD_TIMER_OFF (bgp->t_maxmed_onstartup); + bgp->maxmed_onstartup_over = 1; + } + + bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED; + bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; + + bgp_maxmed_update(bgp); + + return CMD_SUCCESS; +} + +ALIAS (no_bgp_maxmed_onstartup, + no_bgp_maxmed_onstartup_period_cmd, + "no bgp max-med on-startup <5-86400>", + NO_STR + BGP_STR + "Advertise routes with max-med\n" + "Effective on a startup\n" + "Time (seconds) period for max-med\n") + +ALIAS (no_bgp_maxmed_onstartup, + no_bgp_maxmed_onstartup_period_medv_cmd, + "no bgp max-med on-startup <5-86400> <0-4294967294>", + NO_STR + BGP_STR + "Advertise routes with max-med\n" + "Effective on a startup\n" + "Time (seconds) period for max-med\n" + "Max MED value to be used\n") + +static int +bgp_update_delay_config_vty (struct vty *vty, const char *delay, + const char *wait) +{ + struct bgp *bgp; + u_int16_t update_delay; + u_int16_t establish_wait; + + + bgp = vty->index; + + VTY_GET_INTEGER_RANGE ("update-delay", update_delay, delay, + BGP_UPDATE_DELAY_MIN, BGP_UPDATE_DELAY_MAX); + + if (!wait) /* update-delay <delay> */ + { + bgp->v_update_delay = update_delay; + bgp->v_establish_wait = bgp->v_update_delay; + return CMD_SUCCESS; + } + + /* update-delay <delay> <establish-wait> */ + establish_wait = atoi (wait); + if (update_delay < establish_wait) + { + vty_out (vty, "%%Failed: update-delay less than the establish-wait!%s", + VTY_NEWLINE); return CMD_WARNING; } + bgp->v_update_delay = update_delay; + bgp->v_establish_wait = establish_wait; + + return CMD_SUCCESS; +} + +static int +bgp_update_delay_deconfig_vty (struct vty *vty) +{ + struct bgp *bgp; + + bgp = vty->index; + + bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; + bgp->v_establish_wait = bgp->v_update_delay; + + return CMD_SUCCESS; +} + +int +bgp_config_write_update_delay (struct vty *vty, struct bgp *bgp) +{ + if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) + { + vty_out (vty, " update-delay %d", bgp->v_update_delay); + if (bgp->v_update_delay != bgp->v_establish_wait) + vty_out (vty, " %d", bgp->v_establish_wait); + vty_out (vty, "%s", VTY_NEWLINE); + } + + return 0; +} + + +/* Update-delay configuration */ +DEFUN (bgp_update_delay, + bgp_update_delay_cmd, + "update-delay <0-3600>", + "Force initial delay for best-path and updates\n" + "Seconds\n") +{ + return bgp_update_delay_config_vty(vty, argv[0], NULL); +} + +DEFUN (bgp_update_delay_establish_wait, + bgp_update_delay_establish_wait_cmd, + "update-delay <0-3600> <1-3600>", + "Force initial delay for best-path and updates\n" + "Seconds\n" + "Wait for peers to be established\n" + "Seconds\n") +{ + return bgp_update_delay_config_vty(vty, argv[0], argv[1]); +} + +/* Update-delay deconfiguration */ +DEFUN (no_bgp_update_delay, + no_bgp_update_delay_cmd, + "no update-delay <0-3600>", + "Force initial delay for best-path and updates\n" + "Seconds\n") +{ + return bgp_update_delay_deconfig_vty(vty); +} + +ALIAS (no_bgp_update_delay, + no_bgp_update_delay_establish_wait_cmd, + "no update-delay <0-3600> <1-3600>", + "Force initial delay for best-path and updates\n" + "Seconds\n" + "Wait for peers to be established\n" + "Seconds\n") + +static int +bgp_wpkt_quanta_config_vty (struct vty *vty, const char *num, char set) +{ + struct bgp *bgp; + + bgp = vty->index; + + if (set) + VTY_GET_INTEGER_RANGE ("write-quanta", bgp->wpkt_quanta, num, + 1, 10000); + else + bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; + return CMD_SUCCESS; } +int +bgp_config_write_wpkt_quanta (struct vty *vty, struct bgp *bgp) +{ + if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX) + vty_out (vty, " write-quanta %d%s", + bgp->wpkt_quanta, VTY_NEWLINE); + + return 0; +} + + +/* Update-delay configuration */ +DEFUN (bgp_wpkt_quanta, + bgp_wpkt_quanta_cmd, + "write-quanta <1-10000>", + "How many packets to write to peer socket per run\n" + "Number of packets\n") +{ + return bgp_wpkt_quanta_config_vty(vty, argv[0], 1); +} + +/* Update-delay deconfiguration */ +DEFUN (no_bgp_wpkt_quanta, + no_bgp_wpkt_quanta_cmd, + "no write-quanta <1-10000>", + "How many packets to write to peer socket per run\n" + "Number of packets\n") +{ + return bgp_wpkt_quanta_config_vty(vty, argv[0], 0); +} + +/* Maximum-paths configuration */ +DEFUN (bgp_maxpaths, + bgp_maxpaths_cmd, + "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM), + "Forward packets over multiple paths\n" + "Number of paths\n") +{ + return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, argv[0], 0, 1); +} + +DEFUN (bgp_maxpaths_ibgp, + bgp_maxpaths_ibgp_cmd, + "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM), + "Forward packets over multiple paths\n" + "iBGP-multipath\n" + "Number of paths\n") +{ + return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[0], 0, 1); +} + +DEFUN (bgp_maxpaths_ibgp_cluster, + bgp_maxpaths_ibgp_cluster_cmd, + "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM) " equal-cluster-length", + "Forward packets over multiple paths\n" + "iBGP-multipath\n" + "Number of paths\n" + "Match the cluster length\n") +{ + return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[0], + BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN, 1); +} + +DEFUN (no_bgp_maxpaths, + no_bgp_maxpaths_cmd, + "no maximum-paths", + NO_STR + "Forward packets over multiple paths\n" + "Number of paths\n") +{ + return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, NULL, 0, 0); +} + ALIAS (no_bgp_maxpaths, no_bgp_maxpaths_arg_cmd, "no maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM), @@ -808,22 +1144,7 @@ DEFUN (no_bgp_maxpaths_ibgp, "iBGP-multipath\n" "Number of paths\n") { - struct bgp *bgp; - int ret; - - bgp = vty->index; - - ret = bgp_maximum_paths_unset (bgp, bgp_node_afi (vty), bgp_node_safi(vty), - BGP_PEER_IBGP); - if (ret < 0) - { - vty_out (vty, - "%% Failed to unset maximum-paths ibgp for afi %u, safi %u%s", - bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; + return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, NULL, 0, 0); } ALIAS (no_bgp_maxpaths_ibgp, @@ -834,6 +1155,15 @@ ALIAS (no_bgp_maxpaths_ibgp, "iBGP-multipath\n" "Number of paths\n") +ALIAS (no_bgp_maxpaths_ibgp, + no_bgp_maxpaths_ibgp_cluster_cmd, + "no maximum-paths ibgp <1-255> equal-cluster-length", + NO_STR + "Forward packets over multiple paths\n" + "iBGP-multipath\n" + "Number of paths\n" + "Match the cluster length\n") + int bgp_config_write_maxpaths (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, int *write) @@ -848,8 +1178,12 @@ bgp_config_write_maxpaths (struct vty *vty, struct bgp *bgp, afi_t afi, if (bgp->maxpaths[afi][safi].maxpaths_ibgp != BGP_DEFAULT_MAXPATHS) { bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " maximum-paths ibgp %d%s", - bgp->maxpaths[afi][safi].maxpaths_ibgp, VTY_NEWLINE); + vty_out (vty, " maximum-paths ibgp %d", + bgp->maxpaths[afi][safi].maxpaths_ibgp); + if (CHECK_FLAG (bgp->maxpaths[afi][safi].ibgp_flags, + BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN)) + vty_out (vty, " equal-cluster-length"); + vty_out (vty, "%s", VTY_NEWLINE); } return 0; @@ -1483,6 +1817,80 @@ ALIAS (no_bgp_default_local_preference, "local preference (higher=more preferred)\n" "Configure default local preference value\n") +static void +peer_announce_routes_if_rmap_out (struct bgp *bgp) +{ + struct peer *peer; + struct listnode *node, *nnode; + struct bgp_filter *filter; + afi_t afi; + safi_t safi; + + /* Reannounce all routes to appropriate neighbors */ + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) + { + /* check if there's an out route-map on this client */ + filter = &peer->filter[afi][safi]; + if (ROUTE_MAP_OUT_NAME(filter)) + { + if (bgp_debug_update(peer, NULL, 0)) + zlog_debug("%s: Announcing routes again for peer %s" + "(afi=%d, safi=%d", __func__, peer->host, afi, + safi); + + bgp_announce_route_all(peer); + } + } + } + } +} + +DEFUN (bgp_rr_allow_outbound_policy, + bgp_rr_allow_outbound_policy_cmd, + "bgp route-reflector allow-outbound-policy", + "BGP specific commands\n" + "Allow modifications made by out route-map\n" + "on ibgp neighbors\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + if (!bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) + { + bgp_flag_set(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); + peer_announce_routes_if_rmap_out(bgp); + } + + return CMD_SUCCESS; +} + +DEFUN (no_bgp_rr_allow_outbound_policy, + no_bgp_rr_allow_outbound_policy_cmd, + "no bgp route-reflector allow-outbound-policy", + NO_STR + "BGP specific commands\n" + "Allow modifications made by out route-map\n" + "on ibgp neighbors\n") +{ + struct bgp *bgp; + + bgp = vty->index; + + if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) + { + bgp_flag_unset(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); + peer_announce_routes_if_rmap_out(bgp); + } + + return CMD_SUCCESS; +} + static int peer_remote_as_vty (struct vty *vty, const char *peer_str, const char *as_str, afi_t afi, safi_t safi) @@ -1501,24 +1909,31 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str, ret = str2sockunion (peer_str, &su); if (ret < 0) { - ret = peer_group_remote_as (bgp, peer_str, &as); + /* Check for peer by interface */ + ret = peer_remote_as (bgp, NULL, peer_str, &as, afi, safi); if (ret < 0) - { - vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; + { + ret = peer_group_remote_as (bgp, peer_str, &as); + if (ret < 0) + { + vty_out (vty, "%% Create the peer-group or interface first%s", + VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; + } } - - if (peer_address_self_check (&su)) + else { - vty_out (vty, "%% Can not configure the local system as neighbor%s", - VTY_NEWLINE); - return CMD_WARNING; + if (peer_address_self_check (&su)) + { + vty_out (vty, "%% Can not configure the local system as neighbor%s", + VTY_NEWLINE); + return CMD_WARNING; + } + ret = peer_remote_as (bgp, &su, NULL, &as, afi, safi); } - ret = peer_remote_as (bgp, &su, &as, afi, safi); - /* This peer belongs to peer group. */ switch (ret) { @@ -1543,17 +1958,51 @@ DEFUN (neighbor_remote_as, return peer_remote_as_vty (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST); } +DEFUN (neighbor_interface_config, + neighbor_interface_config_cmd, + "neighbor WORD interface", + NEIGHBOR_STR + "Interface name or neighbor tag\n" + "Enable BGP on interface\n") +{ + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + + bgp = vty->index; + group = peer_group_lookup (bgp, argv[0]); + if (group) + { + vty_out (vty, "%% Name conflict with peer-group %s", VTY_NEWLINE); + return CMD_WARNING; + } + + peer = peer_conf_interface_get (bgp, argv[0], AFI_IP, SAFI_UNICAST); + if (!peer) + return CMD_WARNING; + + return CMD_SUCCESS; +} + + DEFUN (neighbor_peer_group, neighbor_peer_group_cmd, "neighbor WORD peer-group", NEIGHBOR_STR - "Neighbor tag\n" + "Interface name or neighbor tag\n" "Configure peer-group\n") { struct bgp *bgp; + struct peer *peer; struct peer_group *group; bgp = vty->index; + peer = peer_lookup_by_conf_if (bgp, argv[0]); + if (peer) + { + vty_out (vty, "%% Name conflict with interface: %s", VTY_NEWLINE); + return CMD_WARNING; + } group = peer_group_get (bgp, argv[0]); if (! group) @@ -1573,10 +2022,19 @@ DEFUN (no_neighbor, union sockunion su; struct peer_group *group; struct peer *peer; + struct peer *other; ret = str2sockunion (argv[0], &su); if (ret < 0) { + /* look up for neighbor by interface name config. */ + peer = peer_lookup_by_conf_if (vty->index, argv[0]); + if (peer) + { + peer_delete (peer); + return CMD_SUCCESS; + } + group = peer_group_lookup (vty->index, argv[0]); if (group) peer_group_delete (group); @@ -1590,7 +2048,12 @@ DEFUN (no_neighbor, { peer = peer_lookup (vty->index, &su); if (peer) - peer_delete (peer); + { + other = peer->doppelganger; + peer_delete (peer); + if (other && other->status != Deleted) + peer_delete(other); + } } return CMD_SUCCESS; @@ -1605,6 +2068,30 @@ ALIAS (no_neighbor, "Specify a BGP neighbor\n" AS_STR) +DEFUN (no_neighbor_interface_config, + no_neighbor_interface_config_cmd, + "no neighbor WORD interface", + NO_STR + NEIGHBOR_STR + "Interface name\n" + "Configure BGP on interface\n") +{ + struct peer *peer; + + /* look up for neighbor by interface name config. */ + peer = peer_lookup_by_conf_if (vty->index, argv[0]); + if (peer) + { + peer_delete (peer); + } + else + { + vty_out (vty, "%% Create the bgp interface first%s", VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + DEFUN (no_neighbor_peer_group, no_neighbor_peer_group_cmd, "no neighbor WORD peer-group", @@ -1626,23 +2113,32 @@ DEFUN (no_neighbor_peer_group, return CMD_SUCCESS; } -DEFUN (no_neighbor_peer_group_remote_as, - no_neighbor_peer_group_remote_as_cmd, +DEFUN (no_neighbor_interface_peer_group_remote_as, + no_neighbor_interface_peer_group_remote_as_cmd, "no neighbor WORD remote-as " CMD_AS_RANGE, NO_STR NEIGHBOR_STR - "Neighbor tag\n" + "Interface name or neighbor tag\n" "Specify a BGP neighbor\n" AS_STR) { struct peer_group *group; + struct peer *peer; + + /* look up for neighbor by interface name config. */ + peer = peer_lookup_by_conf_if (vty->index, argv[0]); + if (peer) + { + peer_as_change (peer, 0); + return CMD_SUCCESS; + } group = peer_group_lookup (vty->index, argv[0]); if (group) peer_group_remote_as_delete (group); else { - vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE); + vty_out (vty, "%% Create the peer-group or interface first%s", VTY_NEWLINE); return CMD_WARNING; } return CMD_SUCCESS; @@ -1837,9 +2333,9 @@ DEFUN (no_neighbor_activate, DEFUN (neighbor_set_peer_group, neighbor_set_peer_group_cmd, - NEIGHBOR_CMD "peer-group WORD", + NEIGHBOR_CMD2 "peer-group WORD", NEIGHBOR_STR - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR2 "Member of the peer-group\n" "peer-group name\n") { @@ -1847,15 +2343,30 @@ DEFUN (neighbor_set_peer_group, as_t as; union sockunion su; struct bgp *bgp; + struct peer *peer; struct peer_group *group; bgp = vty->index; + peer = NULL; ret = str2sockunion (argv[0], &su); if (ret < 0) { - vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE); - return CMD_WARNING; + peer = peer_lookup_by_conf_if (bgp, argv[0]); + if (!peer) + { + vty_out (vty, "%% Malformed address or name: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + if (peer_address_self_check (&su)) + { + vty_out (vty, "%% Can not configure the local system as neighbor%s", + VTY_NEWLINE); + return CMD_WARNING; + } } group = peer_group_lookup (bgp, argv[1]); @@ -1865,14 +2376,7 @@ DEFUN (neighbor_set_peer_group, return CMD_WARNING; } - if (peer_address_self_check (&su)) - { - vty_out (vty, "%% Can not configure the local system as neighbor%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - ret = peer_group_bind (bgp, &su, group, bgp_node_afi (vty), + ret = peer_group_bind (bgp, &su, peer, group, bgp_node_afi (vty), bgp_node_safi (vty), &as); if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT) @@ -1886,10 +2390,10 @@ DEFUN (neighbor_set_peer_group, DEFUN (no_neighbor_set_peer_group, no_neighbor_set_peer_group_cmd, - NO_NEIGHBOR_CMD "peer-group WORD", + NO_NEIGHBOR_CMD2 "peer-group WORD", NO_STR NEIGHBOR_STR - NEIGHBOR_ADDR_STR + NEIGHBOR_ADDR_STR2 "Member of the peer-group\n" "peer-group name\n") { @@ -2191,32 +2695,143 @@ DEFUN (no_neighbor_nexthop_self, PEER_FLAG_NEXTHOP_SELF|PEER_FLAG_NEXTHOP_SELF_ALL); } +/* neighbor as-override */ +DEFUN (neighbor_as_override, + neighbor_as_override_cmd, + NEIGHBOR_CMD2 "as-override", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Override ASNs in outbound updates if aspath equals remote-as\n") +{ + return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_AS_OVERRIDE); +} + +DEFUN (no_neighbor_as_override, + no_neighbor_as_override_cmd, + NO_NEIGHBOR_CMD2 "as-override", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Override ASNs in outbound updates if aspath equals remote-as\n") +{ + return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_AS_OVERRIDE); +} + /* neighbor remove-private-AS. */ DEFUN (neighbor_remove_private_as, neighbor_remove_private_as_cmd, NEIGHBOR_CMD2 "remove-private-AS", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 - "Remove private AS number from outbound updates\n") + "Remove private ASNs in outbound updates\n") { + peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_REMOVE_PRIVATE_AS_ALL| + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty), PEER_FLAG_REMOVE_PRIVATE_AS); } +DEFUN (neighbor_remove_private_as_all, + neighbor_remove_private_as_all_cmd, + NEIGHBOR_CMD2 "remove-private-AS all", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers") +{ + peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); + return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_REMOVE_PRIVATE_AS| + PEER_FLAG_REMOVE_PRIVATE_AS_ALL); +} + +DEFUN (neighbor_remove_private_as_replace_as, + neighbor_remove_private_as_replace_as_cmd, + NEIGHBOR_CMD2 "remove-private-AS replace-AS", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Replace private ASNs with our ASN in outbound updates\n") +{ + peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_REMOVE_PRIVATE_AS_ALL); + return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_REMOVE_PRIVATE_AS| + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); +} + +DEFUN (neighbor_remove_private_as_all_replace_as, + neighbor_remove_private_as_all_replace_as_cmd, + NEIGHBOR_CMD2 "remove-private-AS all replace-AS", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers" + "Replace private ASNs with our ASN in outbound updates\n") +{ + return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_REMOVE_PRIVATE_AS| + PEER_FLAG_REMOVE_PRIVATE_AS_ALL| + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); +} + DEFUN (no_neighbor_remove_private_as, no_neighbor_remove_private_as_cmd, NO_NEIGHBOR_CMD2 "remove-private-AS", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 - "Remove private AS number from outbound updates\n") + "Remove private ASNs in outbound updates\n") { return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS); + PEER_FLAG_REMOVE_PRIVATE_AS| + PEER_FLAG_REMOVE_PRIVATE_AS_ALL| + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); } +ALIAS (no_neighbor_remove_private_as, + no_neighbor_remove_private_as_all_cmd, + NO_NEIGHBOR_CMD2 "remove-private-AS all", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers") + +ALIAS (no_neighbor_remove_private_as, + no_neighbor_remove_private_as_replace_as_cmd, + NO_NEIGHBOR_CMD2 "remove-private-AS replace-AS", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Replace private ASNs with our ASN in outbound updates\n") + +ALIAS (no_neighbor_remove_private_as, + no_neighbor_remove_private_as_all_replace_as_cmd, + NO_NEIGHBOR_CMD2 "remove-private-AS all replace-AS", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers" + "Replace private ASNs with our ASN in outbound updates\n") + + /* neighbor send-community. */ DEFUN (neighbor_send_community, neighbor_send_community_cmd, @@ -3090,6 +3705,9 @@ peer_update_source_vty (struct vty *vty, const char *peer_str, if (! peer) return CMD_WARNING; + if (peer->conf_if) + return CMD_WARNING; + if (source_str) { union sockunion su; @@ -3539,6 +4157,54 @@ ALIAS (no_neighbor_advertise_interval, "Minimum interval between sending BGP routing updates\n" "time in seconds\n") +/* Time to wait before processing route-map updates */ +DEFUN (bgp_set_route_map_delay_timer, + bgp_set_route_map_delay_timer_cmd, + "bgp route-map delay-timer <0-600>", + SET_STR + "BGP route-map delay timer\n" + "Time in secs to wait before processing route-map changes\n" + "0 disables the timer and no route updates happen when\n" + "route-maps change") +{ + u_int32_t rmap_delay_timer; + struct bgp *bgp; + + bgp = vty->index; + if (argv[0]) + { + VTY_GET_INTEGER_RANGE ("delay-timer", rmap_delay_timer, argv[0], 0, 600); + bgp->rmap_update_timer = rmap_delay_timer; + + /* if the dynamic update handling is being disabled, and a timer is + * running, stop the timer and act as if the timer has already fired. + */ + if (!rmap_delay_timer && bgp->t_rmap_update ) + { + BGP_TIMER_OFF(bgp->t_rmap_update); + thread_execute (bm->master, bgp_route_map_update_timer, &bgp, 0); + } + return CMD_SUCCESS; + } + else + return CMD_WARNING; +} + +DEFUN (no_bgp_set_route_map_delay_timer, + no_bgp_set_route_map_delay_timer_cmd, + "no bgp route-map delay-timer", + NO_STR + "Default BGP route-map delay timer\n" + "Reset to default time to wait for processing route-map changes") +{ + struct bgp *bgp; + + bgp = vty->index; + bgp->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; + + return CMD_SUCCESS; +} + /* neighbor interface */ static int peer_interface_vty (struct vty *vty, const char *ip_str, const char *str) @@ -3547,7 +4213,7 @@ peer_interface_vty (struct vty *vty, const char *ip_str, const char *str) struct peer *peer; peer = peer_lookup_vty (vty, ip_str); - if (! peer) + if (! peer || peer->conf_if) return CMD_WARNING; if (str) @@ -4437,18 +5103,27 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, struct listnode *node, *nnode; /* Clear all neighbors. */ + /* + * Pass along pointer to next node to peer_clear() when walking all nodes + * on the BGP instance as that may get freed if it is a doppelganger + */ if (sort == clear_all) { for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer); + ret = peer_clear (peer, &nnode); else ret = peer_clear_soft (peer, afi, safi, stype); if (ret < 0) bgp_clear_vty_error (vty, peer, afi, safi, ret); } + + /* This is to apply read-only mode on this clear. */ + if (stype == BGP_CLEAR_SOFT_NONE) + bgp->update_delay_over = 0; + return CMD_SUCCESS; } @@ -4461,19 +5136,26 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, /* Make sockunion for lookup. */ ret = str2sockunion (arg, &su); if (ret < 0) - { - vty_out (vty, "Malformed address: %s%s", arg, VTY_NEWLINE); - return CMD_WARNING; - } - peer = peer_lookup (bgp, &su); - if (! peer) - { - vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"%s", arg, VTY_NEWLINE); - return CMD_WARNING; - } + { + peer = peer_lookup_by_conf_if (bgp, arg); + if (!peer) + { + vty_out (vty, "Malformed address or name: %s%s", arg, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + peer = peer_lookup (bgp, &su); + if (! peer) + { + vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"%s", arg, VTY_NEWLINE); + return CMD_WARNING; + } + } if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer); + ret = peer_clear (peer, NULL); else ret = peer_clear_soft (peer, afi, safi, stype); @@ -4499,7 +5181,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, { if (stype == BGP_CLEAR_SOFT_NONE) { - ret = peer_clear (peer); + ret = peer_clear (peer, NULL); continue; } @@ -4522,7 +5204,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, continue; if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer); + ret = peer_clear (peer, &nnode); else ret = peer_clear_soft (peer, afi, safi, stype); @@ -4546,7 +5228,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, find = 1; if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer); + ret = peer_clear (peer, &nnode); else ret = peer_clear_soft (peer, afi, safi, stype); @@ -4562,6 +5244,87 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, return CMD_SUCCESS; } +/* Recalculate bestpath and re-advertise a prefix */ +static int +bgp_clear_prefix (struct vty *vty, char *view_name, const char *ip_str, + afi_t afi, safi_t safi, struct prefix_rd *prd) +{ + int ret; + struct prefix match; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp *bgp; + struct bgp_table *table; + struct bgp_table *rib; + + /* BGP structure lookup. */ + if (view_name) + { + 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; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + /* Check IP address argument. */ + ret = str2prefix (ip_str, &match); + if (! ret) + { + vty_out (vty, "%% address is malformed%s", VTY_NEWLINE); + return CMD_WARNING; + } + + match.family = afi2family (afi); + rib = bgp->rib[afi][safi]; + + if (safi == SAFI_MPLS_VPN) + { + for (rn = bgp_table_top (rib); 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 (rm->p.prefixlen == match.prefixlen) + { + SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR); + bgp_process (bgp, rm, afi, safi); + } + bgp_unlock_node (rm); + } + } + } + } + else + { + if ((rn = bgp_node_match (rib, &match)) != NULL) + { + if (rn->p.prefixlen == match.prefixlen) + { + SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR); + bgp_process (bgp, rn, afi, safi); + } + bgp_unlock_node (rn); + } + } + + return CMD_SUCCESS; +} + static int bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi, enum clear_sort sort, enum bgp_clear_type stype, @@ -4642,32 +5405,35 @@ ALIAS (clear_ip_bgp_all, DEFUN (clear_ip_bgp_peer, clear_ip_bgp_peer_cmd, - "clear ip bgp (A.B.C.D|X:X::X:X)", + "clear ip bgp (A.B.C.D|X:X::X:X|WORD)", CLEAR_STR IP_STR BGP_STR "BGP neighbor IP address to clear\n" - "BGP IPv6 neighbor to clear\n") + "BGP IPv6 neighbor to clear\n" + "BGP neighbor on interface to clear\n") { return bgp_clear_vty (vty, NULL, 0, 0, clear_peer, BGP_CLEAR_SOFT_NONE, argv[0]); } ALIAS (clear_ip_bgp_peer, clear_bgp_peer_cmd, - "clear bgp (A.B.C.D|X:X::X:X)", + "clear bgp (A.B.C.D|X:X::X:X|WORD)", CLEAR_STR BGP_STR "BGP neighbor address to clear\n" - "BGP IPv6 neighbor to clear\n") + "BGP IPv6 neighbor to clear\n" + "BGP neighbor on interface to clear\n") ALIAS (clear_ip_bgp_peer, clear_bgp_ipv6_peer_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X)", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD)", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor address to clear\n" - "BGP IPv6 neighbor to clear\n") + "BGP IPv6 neighbor to clear\n" + "BGP neighbor on interface to clear\n") DEFUN (clear_ip_bgp_peer_group, clear_ip_bgp_peer_group_cmd, @@ -4724,6 +5490,27 @@ ALIAS (clear_ip_bgp_external, "Address family\n" "Clear all external peers\n") +DEFUN (clear_ip_bgp_prefix, + clear_ip_bgp_prefix_cmd, + "clear ip bgp prefix A.B.C.D/M", + CLEAR_STR + IP_STR + BGP_STR + "Clear bestpath and re-advertise\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") +{ + return bgp_clear_prefix (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL); +} + +ALIAS (clear_ip_bgp_prefix, + clear_bgp_prefix_cmd, + "clear bgp prefix A.B.C.D/M", + CLEAR_STR + BGP_STR + "Clear bestpath and re-advertise\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") + + DEFUN (clear_ip_bgp_as, clear_ip_bgp_as_cmd, "clear ip bgp " CMD_AS_RANGE, @@ -4758,8 +5545,8 @@ DEFUN (clear_ip_bgp_all_soft_out, IP_STR BGP_STR "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all, @@ -4776,7 +5563,7 @@ ALIAS (clear_ip_bgp_all_soft_out, IP_STR BGP_STR "Clear all peers\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) ALIAS (clear_ip_bgp_all_soft_out, clear_ip_bgp_instance_all_soft_out_cmd, @@ -4787,8 +5574,8 @@ ALIAS (clear_ip_bgp_all_soft_out, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_all_ipv4_soft_out, clear_ip_bgp_all_ipv4_soft_out_cmd, @@ -4800,8 +5587,8 @@ DEFUN (clear_ip_bgp_all_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { if (strncmp (argv[0], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all, @@ -4821,7 +5608,7 @@ ALIAS (clear_ip_bgp_all_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_instance_all_ipv4_soft_out, clear_ip_bgp_instance_all_ipv4_soft_out_cmd, @@ -4835,7 +5622,7 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST, clear_all, @@ -4854,8 +5641,8 @@ DEFUN (clear_ip_bgp_all_vpnv4_soft_out, "Clear all peers\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all, BGP_CLEAR_SOFT_OUT, NULL); @@ -4870,7 +5657,7 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_out, "Clear all peers\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_all_encap_soft_out, clear_ip_bgp_all_encap_soft_out_cmd, @@ -4905,8 +5692,8 @@ DEFUN (clear_bgp_all_soft_out, CLEAR_STR BGP_STR "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all, @@ -4924,8 +5711,8 @@ ALIAS (clear_bgp_all_soft_out, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_all_soft_out, clear_bgp_all_out_cmd, @@ -4933,7 +5720,7 @@ ALIAS (clear_bgp_all_soft_out, CLEAR_STR BGP_STR "Clear all peers\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_all_soft_out, clear_bgp_ipv6_all_soft_out_cmd, @@ -4942,8 +5729,8 @@ ALIAS (clear_bgp_all_soft_out, BGP_STR "Address family\n" "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_all_soft_out, clear_bgp_ipv6_all_out_cmd, @@ -4952,7 +5739,23 @@ ALIAS (clear_bgp_all_soft_out, BGP_STR "Address family\n" "Clear all peers\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) + +DEFUN (clear_bgp_ipv6_safi_prefix, + clear_bgp_ipv6_safi_prefix_cmd, + "clear bgp ipv6 (unicast|multicast) prefix X:X::X:X/M", + CLEAR_STR + BGP_STR + "Address family\n" + "Address Family Modifier\n" + "Clear bestpath and re-advertise\n" + "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_clear_prefix (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL); + else + return bgp_clear_prefix (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL); +} DEFUN (clear_ip_bgp_peer_soft_out, clear_ip_bgp_peer_soft_out_cmd, @@ -4961,8 +5764,8 @@ DEFUN (clear_ip_bgp_peer_soft_out, IP_STR BGP_STR "BGP neighbor address to clear\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -4975,7 +5778,7 @@ ALIAS (clear_ip_bgp_peer_soft_out, IP_STR BGP_STR "BGP neighbor address to clear\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_peer_ipv4_soft_out, clear_ip_bgp_peer_ipv4_soft_out_cmd, @@ -4987,8 +5790,8 @@ DEFUN (clear_ip_bgp_peer_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer, @@ -5008,7 +5811,7 @@ ALIAS (clear_ip_bgp_peer_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_peer_vpnv4_soft_out, clear_ip_bgp_peer_vpnv4_soft_out_cmd, @@ -5019,8 +5822,8 @@ DEFUN (clear_ip_bgp_peer_vpnv4_soft_out, "BGP neighbor address to clear\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -5035,7 +5838,7 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_out, "BGP neighbor address to clear\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_peer_encap_soft_out, clear_ip_bgp_peer_encap_soft_out_cmd, @@ -5066,13 +5869,14 @@ ALIAS (clear_ip_bgp_peer_encap_soft_out, DEFUN (clear_bgp_peer_soft_out, clear_bgp_peer_soft_out_cmd, - "clear bgp (A.B.C.D|X:X::X:X) soft out", + "clear bgp (A.B.C.D|X:X::X:X|WORD) soft out", CLEAR_STR BGP_STR "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -5080,33 +5884,36 @@ DEFUN (clear_bgp_peer_soft_out, ALIAS (clear_bgp_peer_soft_out, clear_bgp_ipv6_peer_soft_out_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft out", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) soft out", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_STR + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_peer_soft_out, clear_bgp_peer_out_cmd, - "clear bgp (A.B.C.D|X:X::X:X) out", + "clear bgp (A.B.C.D|X:X::X:X|WORD) out", CLEAR_STR BGP_STR "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig outbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_peer_soft_out, clear_bgp_ipv6_peer_out_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X) out", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) out", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig outbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_peer_group_soft_out, clear_ip_bgp_peer_group_soft_out_cmd, @@ -5116,8 +5923,8 @@ DEFUN (clear_ip_bgp_peer_group_soft_out, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -5131,7 +5938,7 @@ ALIAS (clear_ip_bgp_peer_group_soft_out, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_peer_group_ipv4_soft_out, clear_ip_bgp_peer_group_ipv4_soft_out_cmd, @@ -5144,8 +5951,8 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group, @@ -5166,7 +5973,7 @@ ALIAS (clear_ip_bgp_peer_group_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_bgp_peer_group_soft_out, clear_bgp_peer_group_soft_out_cmd, @@ -5175,8 +5982,8 @@ DEFUN (clear_bgp_peer_group_soft_out, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -5190,8 +5997,8 @@ ALIAS (clear_bgp_peer_group_soft_out, "Address family\n" "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_peer_group_soft_out, clear_bgp_peer_group_out_cmd, @@ -5200,7 +6007,7 @@ ALIAS (clear_bgp_peer_group_soft_out, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_peer_group_soft_out, clear_bgp_ipv6_peer_group_out_cmd, @@ -5210,7 +6017,7 @@ ALIAS (clear_bgp_peer_group_soft_out, "Address family\n" "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_external_soft_out, clear_ip_bgp_external_soft_out_cmd, @@ -5219,8 +6026,8 @@ DEFUN (clear_ip_bgp_external_soft_out, IP_STR BGP_STR "Clear all external peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external, BGP_CLEAR_SOFT_OUT, NULL); @@ -5233,7 +6040,7 @@ ALIAS (clear_ip_bgp_external_soft_out, IP_STR BGP_STR "Clear all external peers\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_external_ipv4_soft_out, clear_ip_bgp_external_ipv4_soft_out_cmd, @@ -5245,8 +6052,8 @@ DEFUN (clear_ip_bgp_external_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { if (strncmp (argv[0], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external, @@ -5266,7 +6073,7 @@ ALIAS (clear_ip_bgp_external_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_bgp_external_soft_out, clear_bgp_external_soft_out_cmd, @@ -5274,8 +6081,8 @@ DEFUN (clear_bgp_external_soft_out, CLEAR_STR BGP_STR "Clear all external peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external, BGP_CLEAR_SOFT_OUT, NULL); @@ -5288,8 +6095,8 @@ ALIAS (clear_bgp_external_soft_out, BGP_STR "Address family\n" "Clear all external peers\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_external_soft_out, clear_bgp_external_out_cmd, @@ -5297,7 +6104,7 @@ ALIAS (clear_bgp_external_soft_out, CLEAR_STR BGP_STR "Clear all external peers\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_external_soft_out, clear_bgp_ipv6_external_out_cmd, @@ -5306,7 +6113,7 @@ ALIAS (clear_bgp_external_soft_out, BGP_STR "Address family\n" "Clear all external peers\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_as_soft_out, clear_ip_bgp_as_soft_out_cmd, @@ -5315,8 +6122,8 @@ DEFUN (clear_ip_bgp_as_soft_out, IP_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -5329,7 +6136,7 @@ ALIAS (clear_ip_bgp_as_soft_out, IP_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_as_ipv4_soft_out, clear_ip_bgp_as_ipv4_soft_out_cmd, @@ -5341,8 +6148,8 @@ DEFUN (clear_ip_bgp_as_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as, @@ -5362,7 +6169,7 @@ ALIAS (clear_ip_bgp_as_ipv4_soft_out, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_as_vpnv4_soft_out, clear_ip_bgp_as_vpnv4_soft_out_cmd, @@ -5373,8 +6180,8 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft_out, "Clear peers with the AS number\n" "Address family\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -5389,7 +6196,7 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_out, "Clear peers with the AS number\n" "Address family\n" "Address Family modifier\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) DEFUN (clear_ip_bgp_as_encap_soft_out, clear_ip_bgp_as_encap_soft_out_cmd, @@ -5424,8 +6231,8 @@ DEFUN (clear_bgp_as_soft_out, CLEAR_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as, BGP_CLEAR_SOFT_OUT, argv[0]); @@ -5438,8 +6245,8 @@ ALIAS (clear_bgp_as_soft_out, BGP_STR "Address family\n" "Clear peers with the AS number\n" - "Soft reconfig\n" - "Soft reconfig outbound update\n") + BGP_SOFT_STR + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_as_soft_out, clear_bgp_as_out_cmd, @@ -5447,7 +6254,7 @@ ALIAS (clear_bgp_as_soft_out, CLEAR_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) ALIAS (clear_bgp_as_soft_out, clear_bgp_ipv6_as_out_cmd, @@ -5456,7 +6263,7 @@ ALIAS (clear_bgp_as_soft_out, BGP_STR "Address family\n" "Clear peers with the AS number\n" - "Soft reconfig outbound update\n") + BGP_SOFT_OUT_STR) /* Inbound soft-reconfiguration */ DEFUN (clear_ip_bgp_all_soft_in, @@ -5466,8 +6273,8 @@ DEFUN (clear_ip_bgp_all_soft_in, IP_STR BGP_STR "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all, @@ -5486,8 +6293,8 @@ ALIAS (clear_ip_bgp_all_soft_in, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) ALIAS (clear_ip_bgp_all_soft_in, clear_ip_bgp_all_in_cmd, @@ -5496,7 +6303,7 @@ ALIAS (clear_ip_bgp_all_soft_in, IP_STR BGP_STR "Clear all peers\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_all_in_prefix_filter, clear_ip_bgp_all_in_prefix_filter_cmd, @@ -5505,7 +6312,7 @@ DEFUN (clear_ip_bgp_all_in_prefix_filter, IP_STR BGP_STR "Clear all peers\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { if (argc== 1) @@ -5525,7 +6332,7 @@ ALIAS (clear_ip_bgp_all_in_prefix_filter, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") @@ -5539,8 +6346,8 @@ DEFUN (clear_ip_bgp_all_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (strncmp (argv[0], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all, @@ -5560,7 +6367,7 @@ ALIAS (clear_ip_bgp_all_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_instance_all_ipv4_soft_in, clear_ip_bgp_instance_all_ipv4_soft_in_cmd, @@ -5574,8 +6381,8 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST, clear_all, @@ -5595,7 +6402,7 @@ DEFUN (clear_ip_bgp_all_ipv4_in_prefix_filter, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { if (strncmp (argv[0], "m", 1) == 0) @@ -5616,7 +6423,7 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_in_prefix_filter, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { if (strncmp (argv[1], "m", 1) == 0) @@ -5636,8 +6443,8 @@ DEFUN (clear_ip_bgp_all_vpnv4_soft_in, "Clear all peers\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all, BGP_CLEAR_SOFT_IN, NULL); @@ -5652,7 +6459,7 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_in, "Clear all peers\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_all_encap_soft_in, clear_ip_bgp_all_encap_soft_in_cmd, @@ -5687,8 +6494,8 @@ DEFUN (clear_bgp_all_soft_in, CLEAR_STR BGP_STR "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all, @@ -5706,8 +6513,8 @@ ALIAS (clear_bgp_all_soft_in, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) ALIAS (clear_bgp_all_soft_in, clear_bgp_ipv6_all_soft_in_cmd, @@ -5716,8 +6523,8 @@ ALIAS (clear_bgp_all_soft_in, BGP_STR "Address family\n" "Clear all peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) ALIAS (clear_bgp_all_soft_in, clear_bgp_all_in_cmd, @@ -5725,7 +6532,7 @@ ALIAS (clear_bgp_all_soft_in, CLEAR_STR BGP_STR "Clear all peers\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) ALIAS (clear_bgp_all_soft_in, clear_bgp_ipv6_all_in_cmd, @@ -5734,7 +6541,7 @@ ALIAS (clear_bgp_all_soft_in, BGP_STR "Address family\n" "Clear all peers\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_bgp_all_in_prefix_filter, clear_bgp_all_in_prefix_filter_cmd, @@ -5742,7 +6549,7 @@ DEFUN (clear_bgp_all_in_prefix_filter, CLEAR_STR BGP_STR "Clear all peers\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all, @@ -5756,7 +6563,7 @@ ALIAS (clear_bgp_all_in_prefix_filter, BGP_STR "Address family\n" "Clear all peers\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") DEFUN (clear_ip_bgp_peer_soft_in, @@ -5766,8 +6573,8 @@ DEFUN (clear_ip_bgp_peer_soft_in, IP_STR BGP_STR "BGP neighbor address to clear\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer, BGP_CLEAR_SOFT_IN, argv[0]); @@ -5780,7 +6587,7 @@ ALIAS (clear_ip_bgp_peer_soft_in, IP_STR BGP_STR "BGP neighbor address to clear\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_peer_in_prefix_filter, clear_ip_bgp_peer_in_prefix_filter_cmd, @@ -5789,7 +6596,7 @@ DEFUN (clear_ip_bgp_peer_in_prefix_filter, IP_STR BGP_STR "BGP neighbor address to clear\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out the existing ORF prefix-list\n") { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer, @@ -5806,8 +6613,8 @@ DEFUN (clear_ip_bgp_peer_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer, @@ -5827,7 +6634,7 @@ ALIAS (clear_ip_bgp_peer_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_peer_ipv4_in_prefix_filter, clear_ip_bgp_peer_ipv4_in_prefix_filter_cmd, @@ -5839,7 +6646,7 @@ DEFUN (clear_ip_bgp_peer_ipv4_in_prefix_filter, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out the existing ORF prefix-list\n") { if (strncmp (argv[1], "m", 1) == 0) @@ -5859,8 +6666,8 @@ DEFUN (clear_ip_bgp_peer_vpnv4_soft_in, "BGP neighbor address to clear\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer, BGP_CLEAR_SOFT_IN, argv[0]); @@ -5875,7 +6682,7 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_in, "BGP neighbor address to clear\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_peer_encap_soft_in, clear_ip_bgp_peer_encap_soft_in_cmd, @@ -5906,13 +6713,14 @@ ALIAS (clear_ip_bgp_peer_encap_soft_in, DEFUN (clear_bgp_peer_soft_in, clear_bgp_peer_soft_in_cmd, - "clear bgp (A.B.C.D|X:X::X:X) soft in", + "clear bgp (A.B.C.D|X:X::X:X|WORD) soft in", CLEAR_STR BGP_STR "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer, BGP_CLEAR_SOFT_IN, argv[0]); @@ -5920,42 +6728,46 @@ DEFUN (clear_bgp_peer_soft_in, ALIAS (clear_bgp_peer_soft_in, clear_bgp_ipv6_peer_soft_in_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft in", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) soft in", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_STR + BGP_SOFT_IN_STR) ALIAS (clear_bgp_peer_soft_in, clear_bgp_peer_in_cmd, - "clear bgp (A.B.C.D|X:X::X:X) in", + "clear bgp (A.B.C.D|X:X::X:X|WORD) in", CLEAR_STR BGP_STR "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig inbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_IN_STR) ALIAS (clear_bgp_peer_soft_in, clear_bgp_ipv6_peer_in_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X) in", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) in", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig inbound update\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_IN_STR) DEFUN (clear_bgp_peer_in_prefix_filter, clear_bgp_peer_in_prefix_filter_cmd, - "clear bgp (A.B.C.D|X:X::X:X) in prefix-filter", + "clear bgp (A.B.C.D|X:X::X:X|WORD) in prefix-filter", CLEAR_STR BGP_STR "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig inbound update\n" + "BGP neighbor on interface to clear\n" + BGP_SOFT_IN_STR "Push out the existing ORF prefix-list\n") { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer, @@ -5964,13 +6776,14 @@ DEFUN (clear_bgp_peer_in_prefix_filter, ALIAS (clear_bgp_peer_in_prefix_filter, clear_bgp_ipv6_peer_in_prefix_filter_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X) in prefix-filter", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) in prefix-filter", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig inbound update\n" + "BGP neighbor on interface to clear\n" + BGP_SOFT_IN_STR "Push out the existing ORF prefix-list\n") DEFUN (clear_ip_bgp_peer_group_soft_in, @@ -5981,8 +6794,8 @@ DEFUN (clear_ip_bgp_peer_group_soft_in, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group, BGP_CLEAR_SOFT_IN, argv[0]); @@ -5996,7 +6809,7 @@ ALIAS (clear_ip_bgp_peer_group_soft_in, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_peer_group_in_prefix_filter, clear_ip_bgp_peer_group_in_prefix_filter_cmd, @@ -6006,7 +6819,7 @@ DEFUN (clear_ip_bgp_peer_group_in_prefix_filter, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group, @@ -6024,8 +6837,8 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group, @@ -6046,7 +6859,7 @@ ALIAS (clear_ip_bgp_peer_group_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_peer_group_ipv4_in_prefix_filter, clear_ip_bgp_peer_group_ipv4_in_prefix_filter_cmd, @@ -6059,7 +6872,7 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_in_prefix_filter, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { if (strncmp (argv[1], "m", 1) == 0) @@ -6077,8 +6890,8 @@ DEFUN (clear_bgp_peer_group_soft_in, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group, BGP_CLEAR_SOFT_IN, argv[0]); @@ -6092,8 +6905,8 @@ ALIAS (clear_bgp_peer_group_soft_in, "Address family\n" "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) ALIAS (clear_bgp_peer_group_soft_in, clear_bgp_peer_group_in_cmd, @@ -6102,7 +6915,7 @@ ALIAS (clear_bgp_peer_group_soft_in, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) ALIAS (clear_bgp_peer_group_soft_in, clear_bgp_ipv6_peer_group_in_cmd, @@ -6112,7 +6925,7 @@ ALIAS (clear_bgp_peer_group_soft_in, "Address family\n" "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_bgp_peer_group_in_prefix_filter, clear_bgp_peer_group_in_prefix_filter_cmd, @@ -6121,7 +6934,7 @@ DEFUN (clear_bgp_peer_group_in_prefix_filter, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group, @@ -6136,7 +6949,7 @@ ALIAS (clear_bgp_peer_group_in_prefix_filter, "Address family\n" "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") DEFUN (clear_ip_bgp_external_soft_in, @@ -6146,8 +6959,8 @@ DEFUN (clear_ip_bgp_external_soft_in, IP_STR BGP_STR "Clear all external peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external, BGP_CLEAR_SOFT_IN, NULL); @@ -6160,7 +6973,7 @@ ALIAS (clear_ip_bgp_external_soft_in, IP_STR BGP_STR "Clear all external peers\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_external_in_prefix_filter, clear_ip_bgp_external_in_prefix_filter_cmd, @@ -6169,7 +6982,7 @@ DEFUN (clear_ip_bgp_external_in_prefix_filter, IP_STR BGP_STR "Clear all external peers\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external, @@ -6186,8 +6999,8 @@ DEFUN (clear_ip_bgp_external_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (strncmp (argv[0], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external, @@ -6207,7 +7020,7 @@ ALIAS (clear_ip_bgp_external_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_external_ipv4_in_prefix_filter, clear_ip_bgp_external_ipv4_in_prefix_filter_cmd, @@ -6219,7 +7032,7 @@ DEFUN (clear_ip_bgp_external_ipv4_in_prefix_filter, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { if (strncmp (argv[0], "m", 1) == 0) @@ -6236,8 +7049,8 @@ DEFUN (clear_bgp_external_soft_in, CLEAR_STR BGP_STR "Clear all external peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external, BGP_CLEAR_SOFT_IN, NULL); @@ -6250,8 +7063,8 @@ ALIAS (clear_bgp_external_soft_in, BGP_STR "Address family\n" "Clear all external peers\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) ALIAS (clear_bgp_external_soft_in, clear_bgp_external_in_cmd, @@ -6259,7 +7072,7 @@ ALIAS (clear_bgp_external_soft_in, CLEAR_STR BGP_STR "Clear all external peers\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) ALIAS (clear_bgp_external_soft_in, clear_bgp_ipv6_external_in_cmd, @@ -6268,7 +7081,7 @@ ALIAS (clear_bgp_external_soft_in, BGP_STR "Address family\n" "Clear all external peers\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_bgp_external_in_prefix_filter, clear_bgp_external_in_prefix_filter_cmd, @@ -6276,7 +7089,7 @@ DEFUN (clear_bgp_external_in_prefix_filter, CLEAR_STR BGP_STR "Clear all external peers\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external, @@ -6290,7 +7103,7 @@ ALIAS (clear_bgp_external_in_prefix_filter, BGP_STR "Address family\n" "Clear all external peers\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") DEFUN (clear_ip_bgp_as_soft_in, @@ -6300,8 +7113,8 @@ DEFUN (clear_ip_bgp_as_soft_in, IP_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as, BGP_CLEAR_SOFT_IN, argv[0]); @@ -6314,7 +7127,7 @@ ALIAS (clear_ip_bgp_as_soft_in, IP_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_as_in_prefix_filter, clear_ip_bgp_as_in_prefix_filter_cmd, @@ -6323,7 +7136,7 @@ DEFUN (clear_ip_bgp_as_in_prefix_filter, IP_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as, @@ -6340,8 +7153,8 @@ DEFUN (clear_ip_bgp_as_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as, @@ -6361,7 +7174,7 @@ ALIAS (clear_ip_bgp_as_ipv4_soft_in, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter, clear_ip_bgp_as_ipv4_in_prefix_filter_cmd, @@ -6373,7 +7186,7 @@ DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { if (strncmp (argv[1], "m", 1) == 0) @@ -6393,8 +7206,8 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft_in, "Clear peers with the AS number\n" "Address family\n" "Address Family modifier\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as, BGP_CLEAR_SOFT_IN, argv[0]); @@ -6409,7 +7222,7 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_in, "Clear peers with the AS number\n" "Address family\n" "Address Family modifier\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_ip_bgp_as_encap_soft_in, clear_ip_bgp_as_encap_soft_in_cmd, @@ -6444,8 +7257,8 @@ DEFUN (clear_bgp_as_soft_in, CLEAR_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as, BGP_CLEAR_SOFT_IN, argv[0]); @@ -6458,8 +7271,8 @@ ALIAS (clear_bgp_as_soft_in, BGP_STR "Address family\n" "Clear peers with the AS number\n" - "Soft reconfig\n" - "Soft reconfig inbound update\n") + BGP_SOFT_STR + BGP_SOFT_IN_STR) ALIAS (clear_bgp_as_soft_in, clear_bgp_as_in_cmd, @@ -6467,7 +7280,7 @@ ALIAS (clear_bgp_as_soft_in, CLEAR_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) ALIAS (clear_bgp_as_soft_in, clear_bgp_ipv6_as_in_cmd, @@ -6476,7 +7289,7 @@ ALIAS (clear_bgp_as_soft_in, BGP_STR "Address family\n" "Clear peers with the AS number\n" - "Soft reconfig inbound update\n") + BGP_SOFT_IN_STR) DEFUN (clear_bgp_as_in_prefix_filter, clear_bgp_as_in_prefix_filter_cmd, @@ -6484,7 +7297,7 @@ DEFUN (clear_bgp_as_in_prefix_filter, CLEAR_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as, @@ -6498,7 +7311,7 @@ ALIAS (clear_bgp_as_in_prefix_filter, BGP_STR "Address family\n" "Clear peers with the AS number\n" - "Soft reconfig inbound update\n" + BGP_SOFT_IN_STR "Push out prefix-list ORF and do inbound soft reconfig\n") /* Both soft-reconfiguration */ @@ -6509,7 +7322,7 @@ DEFUN (clear_ip_bgp_all_soft, IP_STR BGP_STR "Clear all peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all, @@ -6528,7 +7341,7 @@ ALIAS (clear_ip_bgp_all_soft, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) DEFUN (clear_ip_bgp_all_ipv4_soft, @@ -6541,7 +7354,7 @@ DEFUN (clear_ip_bgp_all_ipv4_soft, "Address family\n" "Address Family Modifier\n" "Address Family Modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (strncmp (argv[0], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all, @@ -6563,7 +7376,7 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_soft, "Address family\n" "Address Family Modifier\n" "Address Family Modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all, @@ -6582,7 +7395,7 @@ DEFUN (clear_ip_bgp_all_vpnv4_soft, "Clear all peers\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6609,7 +7422,7 @@ DEFUN (clear_bgp_all_soft, CLEAR_STR BGP_STR "Clear all peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all, @@ -6627,7 +7440,7 @@ ALIAS (clear_bgp_all_soft, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) ALIAS (clear_bgp_all_soft, clear_bgp_ipv6_all_soft_cmd, @@ -6636,7 +7449,7 @@ ALIAS (clear_bgp_all_soft, BGP_STR "Address family\n" "Clear all peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) DEFUN (clear_ip_bgp_peer_soft, clear_ip_bgp_peer_soft_cmd, @@ -6645,7 +7458,7 @@ DEFUN (clear_ip_bgp_peer_soft, IP_STR BGP_STR "BGP neighbor address to clear\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6661,7 +7474,7 @@ DEFUN (clear_ip_bgp_peer_ipv4_soft, "Address family\n" "Address Family Modifier\n" "Address Family Modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer, @@ -6680,7 +7493,7 @@ DEFUN (clear_ip_bgp_peer_vpnv4_soft, "BGP neighbor address to clear\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6703,12 +7516,13 @@ DEFUN (clear_ip_bgp_peer_encap_soft, DEFUN (clear_bgp_peer_soft, clear_bgp_peer_soft_cmd, - "clear bgp (A.B.C.D|X:X::X:X) soft", + "clear bgp (A.B.C.D|X:X::X:X|WORD) soft", CLEAR_STR BGP_STR "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6716,13 +7530,14 @@ DEFUN (clear_bgp_peer_soft, ALIAS (clear_bgp_peer_soft, clear_bgp_ipv6_peer_soft_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) soft", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_STR) DEFUN (clear_ip_bgp_peer_group_soft, clear_ip_bgp_peer_group_soft_cmd, @@ -6732,7 +7547,7 @@ DEFUN (clear_ip_bgp_peer_group_soft, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6749,7 +7564,7 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_soft, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group, @@ -6766,7 +7581,7 @@ DEFUN (clear_bgp_peer_group_soft, BGP_STR "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6780,7 +7595,7 @@ ALIAS (clear_bgp_peer_group_soft, "Address family\n" "Clear all members of peer-group\n" "BGP peer-group name\n" - "Soft reconfig\n") + BGP_SOFT_STR) DEFUN (clear_ip_bgp_external_soft, clear_ip_bgp_external_soft_cmd, @@ -6789,7 +7604,7 @@ DEFUN (clear_ip_bgp_external_soft, IP_STR BGP_STR "Clear all external peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external, BGP_CLEAR_SOFT_BOTH, NULL); @@ -6805,7 +7620,7 @@ DEFUN (clear_ip_bgp_external_ipv4_soft, "Address family\n" "Address Family modifier\n" "Address Family modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (strncmp (argv[0], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external, @@ -6821,7 +7636,7 @@ DEFUN (clear_bgp_external_soft, CLEAR_STR BGP_STR "Clear all external peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external, BGP_CLEAR_SOFT_BOTH, NULL); @@ -6834,7 +7649,7 @@ ALIAS (clear_bgp_external_soft, BGP_STR "Address family\n" "Clear all external peers\n" - "Soft reconfig\n") + BGP_SOFT_STR) DEFUN (clear_ip_bgp_as_soft, clear_ip_bgp_as_soft_cmd, @@ -6843,7 +7658,7 @@ DEFUN (clear_ip_bgp_as_soft, IP_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6859,7 +7674,7 @@ DEFUN (clear_ip_bgp_as_ipv4_soft, "Address family\n" "Address Family Modifier\n" "Address Family Modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { if (strncmp (argv[1], "m", 1) == 0) return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as, @@ -6878,7 +7693,7 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft, "Clear peers with the AS number\n" "Address family\n" "Address Family Modifier\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6905,7 +7720,7 @@ DEFUN (clear_bgp_as_soft, CLEAR_STR BGP_STR "Clear peers with the AS number\n" - "Soft reconfig\n") + BGP_SOFT_STR) { return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as, BGP_CLEAR_SOFT_BOTH, argv[0]); @@ -6918,7 +7733,7 @@ ALIAS (clear_bgp_as_soft, BGP_STR "Address family\n" "Clear peers with the AS number\n" - "Soft reconfig\n") + BGP_SOFT_STR) /* RS-client soft reconfiguration. */ DEFUN (clear_bgp_all_rsclient, @@ -6927,7 +7742,7 @@ DEFUN (clear_bgp_all_rsclient, CLEAR_STR BGP_STR "Clear all peers\n" - "Soft reconfig for rsclient RIB\n") + BGP_SOFT_RSCLIENT_RIB_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all, @@ -6944,7 +7759,7 @@ ALIAS (clear_bgp_all_rsclient, BGP_STR "Address family\n" "Clear all peers\n" - "Soft reconfig for rsclient RIB\n") + BGP_SOFT_RSCLIENT_RIB_STR) ALIAS (clear_bgp_all_rsclient, clear_bgp_instance_all_rsclient_cmd, @@ -6954,7 +7769,7 @@ ALIAS (clear_bgp_all_rsclient, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig for rsclient RIB\n") + BGP_SOFT_RSCLIENT_RIB_STR) ALIAS (clear_bgp_all_rsclient, clear_bgp_ipv6_instance_all_rsclient_cmd, @@ -6965,7 +7780,7 @@ ALIAS (clear_bgp_all_rsclient, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig for rsclient RIB\n") + BGP_SOFT_RSCLIENT_RIB_STR) DEFUN (clear_ip_bgp_all_rsclient, clear_ip_bgp_all_rsclient_cmd, @@ -6974,7 +7789,7 @@ DEFUN (clear_ip_bgp_all_rsclient, IP_STR BGP_STR "Clear all peers\n" - "Soft reconfig for rsclient RIB\n") + BGP_SOFT_RSCLIENT_RIB_STR) { if (argc == 1) return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all, @@ -6993,16 +7808,17 @@ ALIAS (clear_ip_bgp_all_rsclient, "BGP view\n" "view name\n" "Clear all peers\n" - "Soft reconfig for rsclient RIB\n") + BGP_SOFT_RSCLIENT_RIB_STR) DEFUN (clear_bgp_peer_rsclient, clear_bgp_peer_rsclient_cmd, - "clear bgp (A.B.C.D|X:X::X:X) rsclient", + "clear bgp (A.B.C.D|X:X::X:X|WORD) rsclient", CLEAR_STR BGP_STR "BGP neighbor IP address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig for rsclient RIB\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_RSCLIENT_RIB_STR) { if (argc == 2) return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_peer, @@ -7014,28 +7830,30 @@ DEFUN (clear_bgp_peer_rsclient, ALIAS (clear_bgp_peer_rsclient, clear_bgp_ipv6_peer_rsclient_cmd, - "clear bgp ipv6 (A.B.C.D|X:X::X:X) rsclient", + "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) rsclient", CLEAR_STR BGP_STR "Address family\n" "BGP neighbor IP address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig for rsclient RIB\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_RSCLIENT_RIB_STR) ALIAS (clear_bgp_peer_rsclient, clear_bgp_instance_peer_rsclient_cmd, - "clear bgp view WORD (A.B.C.D|X:X::X:X) rsclient", + "clear bgp view WORD (A.B.C.D|X:X::X:X|WORD) rsclient", CLEAR_STR BGP_STR "BGP view\n" "view name\n" "BGP neighbor IP address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig for rsclient RIB\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_RSCLIENT_RIB_STR) ALIAS (clear_bgp_peer_rsclient, clear_bgp_ipv6_instance_peer_rsclient_cmd, - "clear bgp ipv6 view WORD (A.B.C.D|X:X::X:X) rsclient", + "clear bgp ipv6 view WORD (A.B.C.D|X:X::X:X|WORD) rsclient", CLEAR_STR BGP_STR "Address family\n" @@ -7043,17 +7861,19 @@ ALIAS (clear_bgp_peer_rsclient, "view name\n" "BGP neighbor IP address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig for rsclient RIB\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_RSCLIENT_RIB_STR) DEFUN (clear_ip_bgp_peer_rsclient, clear_ip_bgp_peer_rsclient_cmd, - "clear ip bgp (A.B.C.D|X:X::X:X) rsclient", + "clear ip bgp (A.B.C.D|X:X::X:X|WORD) rsclient", CLEAR_STR IP_STR BGP_STR "BGP neighbor IP address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig for rsclient RIB\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_RSCLIENT_RIB_STR) { if (argc == 2) return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_peer, @@ -7065,7 +7885,7 @@ DEFUN (clear_ip_bgp_peer_rsclient, ALIAS (clear_ip_bgp_peer_rsclient, clear_ip_bgp_instance_peer_rsclient_cmd, - "clear ip bgp view WORD (A.B.C.D|X:X::X:X) rsclient", + "clear ip bgp view WORD (A.B.C.D|X:X::X:X|WORD) rsclient", CLEAR_STR IP_STR BGP_STR @@ -7073,7 +7893,8 @@ ALIAS (clear_ip_bgp_peer_rsclient, "view name\n" "BGP neighbor IP address to clear\n" "BGP IPv6 neighbor to clear\n" - "Soft reconfig for rsclient RIB\n") + "BGP neighbor on interface to clear\n" + BGP_SOFT_RSCLIENT_RIB_STR) DEFUN (show_bgp_views, show_bgp_views_cmd, @@ -7252,6 +8073,9 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + if (peer->afc[afi][safi]) { if (!count) @@ -7263,6 +8087,39 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi) vty_out (vty, "BGP router identifier %s, local AS number %u%s", inet_ntoa (bgp->router_id), bgp->as, VTY_NEWLINE); + if (bgp_update_delay_configured(bgp)) + { + vty_out (vty, "Read-only mode update-delay limit: %d seconds%s", + bgp->v_update_delay, VTY_NEWLINE); + if (bgp->v_update_delay != bgp->v_establish_wait) + vty_out (vty, " Establish wait: %d seconds%s", + bgp->v_establish_wait, VTY_NEWLINE); + if (bgp_update_delay_active(bgp)) + { + vty_out (vty, " First neighbor established: %s%s", + bgp->update_delay_begin_time, VTY_NEWLINE); + vty_out (vty, " Delay in progress%s", VTY_NEWLINE); + } + else + { + if (bgp->update_delay_over) + { + vty_out (vty, " First neighbor established: %s%s", + bgp->update_delay_begin_time, VTY_NEWLINE); + vty_out (vty, " Best-paths resumed: %s%s", + bgp->update_delay_end_time, VTY_NEWLINE); + vty_out (vty, " zebra update resumed: %s%s", + bgp->update_delay_zebra_resume_time, VTY_NEWLINE); + vty_out (vty, " peers update resumed: %s%s", + bgp->update_delay_peers_resume_time, VTY_NEWLINE); + } + } + } + + if (bgp_maxmed_onstartup_configured(bgp) && bgp->maxmed_active) + vty_out (vty, "Max-med on-startup active%s", VTY_NEWLINE); + if (bgp->v_maxmed_admin) + vty_out (vty, "Max-med administrative active%s", VTY_NEWLINE); ents = bgp_table_count (bgp->rib[afi][safi]); vty_out (vty, "RIB entries %ld, using %s of memory%s", ents, @@ -7308,14 +8165,16 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi) vty_out (vty, "4 "); - vty_out (vty, "%5u %7d %7d %8d %4d %4lu ", + vty_out (vty, "%5u %7d %7d %8d %4d %4d ", peer->as, peer->open_in + peer->update_in + peer->keepalive_in + peer->notify_in + peer->refresh_in + peer->dynamic_cap_in, peer->open_out + peer->update_out + peer->keepalive_out + peer->notify_out + peer->refresh_out + peer->dynamic_cap_out, - 0, 0, (unsigned long) peer->obuf->count); + 0, 0, + peer->sync[afi][safi]->update.count + + peer->sync[afi][safi]->withdraw.count); vty_out (vty, "%8s", peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN)); @@ -7344,6 +8203,7 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi) else vty_out (vty, "No %s neighbor is configured%s", afi == AFI_IP ? "IPv4" : "IPv6", VTY_NEWLINE); + return CMD_SUCCESS; } @@ -7983,9 +8843,16 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi) vty_out (vty, " Route-Server Client%s", VTY_NEWLINE); if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) vty_out (vty, " Inbound soft reconfiguration allowed%s", VTY_NEWLINE); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS)) - vty_out (vty, " Private AS number removed from updates to this neighbor%s", VTY_NEWLINE); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF)) + if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + vty_out (vty, " Private AS numbers replaced in updates to this neighbor%s", VTY_NEWLINE); + else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS)) + vty_out (vty, " Private AS numbers removed in updates to this neighbor%s", VTY_NEWLINE); + + if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE)) + vty_out (vty, " Override ASNs in outbound updates if aspath equals remote-as%s", VTY_NEWLINE); + + if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) || + CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF_ALL)) vty_out (vty, " NEXT_HOP is always this router%s", VTY_NEWLINE); if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) vty_out (vty, " AS_PATH is propagated unchanged to this neighbor%s", VTY_NEWLINE); @@ -8122,15 +8989,21 @@ static void bgp_show_peer (struct vty *vty, struct peer *p) { struct bgp *bgp; - char buf1[BUFSIZ]; + char buf1[BUFSIZ], buf[SU_ADDRSTRLEN]; char timebuf[BGP_UPTIME_LEN]; afi_t afi; safi_t safi; + u_int16_t i; + u_char *msg; bgp = p->bgp; - /* Configured IP address. */ - vty_out (vty, "BGP neighbor is %s, ", p->host); + if (p->conf_if) /* Configured interface name. */ + vty_out (vty, "BGP neighbor on %s: %s, ", p->conf_if, + BGP_PEER_SU_UNSPEC(p) ? "None" : + sockunion2str (&p->su, buf, SU_ADDRSTRLEN)); + else /* Configured IP address. */ + vty_out (vty, "BGP neighbor is %s, ", p->host); vty_out (vty, "remote AS %u, ", p->as); vty_out (vty, "local AS %u%s%s, ", p->change_local_as ? p->change_local_as : p->local_as, @@ -8183,9 +9056,11 @@ bgp_show_peer (struct vty *vty, struct peer *p) /* read timer */ vty_out (vty, " Last read %s", peer_uptime (p->readtime, timebuf, BGP_UPTIME_LEN)); + vty_out (vty, ", Last write %s%s", + peer_uptime (p->last_write, timebuf, BGP_UPTIME_LEN), VTY_NEWLINE); /* Configured timer values. */ - vty_out (vty, ", hold time is %d, keepalive interval is %d seconds%s", + vty_out (vty, " Hold time is %d, keepalive interval is %d seconds%s", p->v_holdtime, p->v_keepalive, VTY_NEWLINE); if (CHECK_FLAG (p->config, PEER_CONFIG_TIMER)) { @@ -8404,12 +9279,33 @@ bgp_show_peer (struct vty *vty, struct peer *p) p->established, p->dropped, VTY_NEWLINE); - if (! p->dropped) + if (! p->last_reset) vty_out (vty, " Last reset never%s", VTY_NEWLINE); else - vty_out (vty, " Last reset %s, due to %s%s", - peer_uptime (p->resettime, timebuf, BGP_UPTIME_LEN), - peer_down_str[(int) p->last_reset], VTY_NEWLINE); + { + vty_out (vty, " Last reset %s, due to %s%s", + peer_uptime (p->resettime, timebuf, BGP_UPTIME_LEN), + peer_down_str[(int) p->last_reset], VTY_NEWLINE); + + if (p->last_reset_cause_size) + { + msg = p->last_reset_cause; + vty_out(vty, " Message received that caused BGP to send a NOTIFICATION:%s ", VTY_NEWLINE); + for (i = 1; i <= p->last_reset_cause_size; i++) + { + vty_out(vty, "%02X", *msg++); + + if (i != p->last_reset_cause_size) + { + if (i % 16 == 0) + vty_out(vty, "%s ", VTY_NEWLINE); + else if (i % 4 == 0) + vty_out(vty, " "); + } + } + vty_out(vty, "%s", VTY_NEWLINE); + } + } if (CHECK_FLAG (p->sflags, PEER_STATUS_PREFIX_OVERFLOW)) { @@ -8488,8 +9384,12 @@ bgp_show_peer (struct vty *vty, struct peer *p) if (p->t_connect) vty_out (vty, "Next connect timer due in %ld seconds%s", thread_timer_remain_second (p->t_connect), VTY_NEWLINE); - - vty_out (vty, "Read thread: %s Write thread: %s%s", + if (p->t_routeadv) + vty_out (vty, "MRAI (interval %d) timer expires in %ld seconds%s", + p->v_routeadv, thread_timer_remain_second (p->t_routeadv), + VTY_NEWLINE); + + vty_out (vty, "Read thread: %s Write thread: %s%s", p->t_read ? "on" : "off", p->t_write ? "on" : "off", VTY_NEWLINE); @@ -8503,7 +9403,7 @@ bgp_show_peer (struct vty *vty, struct peer *p) static int bgp_show_neighbor (struct vty *vty, struct bgp *bgp, - enum show_type type, union sockunion *su) + enum show_type type, union sockunion *su, const char *conf_if) { struct listnode *node, *nnode; struct peer *peer; @@ -8511,17 +9411,31 @@ bgp_show_neighbor (struct vty *vty, struct bgp *bgp, for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + switch (type) { case show_all: bgp_show_peer (vty, peer); break; case show_peer: - if (sockunion_same (&peer->su, su)) - { - find = 1; - bgp_show_peer (vty, peer); - } + if (conf_if) + { + if (peer->conf_if && !strcmp(peer->conf_if, conf_if)) + { + find = 1; + bgp_show_peer (vty, peer); + } + } + else + { + if (sockunion_same (&peer->su, su)) + { + find = 1; + bgp_show_peer (vty, peer); + } + } break; } } @@ -8540,35 +9454,35 @@ bgp_show_neighbor_vty (struct vty *vty, const char *name, struct bgp *bgp; union sockunion su; - if (ip_str) - { - ret = str2sockunion (ip_str, &su); - if (ret < 0) - { - vty_out (vty, "%% Malformed address: %s%s", ip_str, VTY_NEWLINE); - return CMD_WARNING; - } - } - if (name) { bgp = bgp_lookup_by_name (name); - if (! bgp) { vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE); return CMD_WARNING; } - - bgp_show_neighbor (vty, bgp, type, &su); - - return CMD_SUCCESS; } - - bgp = bgp_get_default (); + else + { + bgp = bgp_get_default (); + } if (bgp) - bgp_show_neighbor (vty, bgp, type, &su); + { + if (ip_str) + { + ret = str2sockunion (ip_str, &su); + if (ret < 0) + bgp_show_neighbor (vty, bgp, type, NULL, ip_str); + else + bgp_show_neighbor (vty, bgp, type, &su, NULL); + } + else + { + bgp_show_neighbor (vty, bgp, type, NULL, NULL); + } + } return CMD_SUCCESS; } @@ -8626,20 +9540,21 @@ ALIAS (show_ip_bgp_neighbors, DEFUN (show_ip_bgp_neighbors_peer, show_ip_bgp_neighbors_peer_cmd, - "show ip bgp neighbors (A.B.C.D|X:X::X:X)", + "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD)", SHOW_STR IP_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" - "Neighbor to display information about\n") + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n") { return bgp_show_neighbor_vty (vty, NULL, show_peer, argv[argc - 1]); } ALIAS (show_ip_bgp_neighbors_peer, show_ip_bgp_ipv4_neighbors_peer_cmd, - "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X)", + "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD)", SHOW_STR IP_STR BGP_STR @@ -8648,7 +9563,8 @@ ALIAS (show_ip_bgp_neighbors_peer, "Address Family modifier\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" - "Neighbor to display information about\n") + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n") ALIAS (show_ip_bgp_neighbors_peer, show_ip_bgp_vpnv4_all_neighbors_peer_cmd, @@ -8674,13 +9590,14 @@ ALIAS (show_ip_bgp_neighbors_peer, ALIAS (show_ip_bgp_neighbors_peer, show_bgp_ipv6_neighbors_peer_cmd, - "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X)", + "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" - "Neighbor to display information about\n") + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n") DEFUN (show_ip_bgp_instance_neighbors, show_ip_bgp_instance_neighbors_cmd, @@ -8707,7 +9624,7 @@ ALIAS (show_ip_bgp_instance_neighbors, DEFUN (show_ip_bgp_instance_neighbors_peer, show_ip_bgp_instance_neighbors_peer_cmd, - "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X)", + "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD)", SHOW_STR IP_STR BGP_STR @@ -8715,7 +9632,8 @@ DEFUN (show_ip_bgp_instance_neighbors_peer, "View name\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" - "Neighbor to display information about\n") + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n") { return bgp_show_neighbor_vty (vty, argv[0], show_peer, argv[1]); } @@ -8765,12 +9683,13 @@ DEFUN (show_bgp_neighbors, DEFUN (show_bgp_neighbors_peer, show_bgp_neighbors_peer_cmd, - "show bgp neighbors (A.B.C.D|X:X::X:X)", + "show bgp neighbors (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" - "Neighbor to display information about\n") + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n") { return bgp_show_neighbor_vty (vty, NULL, show_peer, argv[argc - 1]); } @@ -8789,21 +9708,22 @@ DEFUN (show_bgp_instance_neighbors, DEFUN (show_bgp_instance_neighbors_peer, show_bgp_instance_neighbors_peer_cmd, - "show bgp view WORD neighbors (A.B.C.D|X:X::X:X)", + "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "BGP view\n" "View name\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" - "Neighbor to display information about\n") + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n") { return bgp_show_neighbor_vty (vty, argv[0], show_peer, argv[1]); } ALIAS (show_bgp_instance_neighbors_peer, show_bgp_instance_ipv6_neighbors_peer_cmd, - "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X)", + "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD)", SHOW_STR BGP_STR "BGP view\n" @@ -8811,7 +9731,8 @@ ALIAS (show_bgp_instance_neighbors_peer, "Address family\n" "Detailed information on TCP and BGP neighbor connections\n" "Neighbor to display information about\n" - "Neighbor to display information about\n") + "Neighbor to display information about\n" + "Neighbor on bgp configured interface\n") /* Show BGP's AS paths internal data. There are both `show ip bgp paths' and `show ip mbgp paths'. Those functions results are the @@ -9407,7 +10328,7 @@ DEFUN (no_bgp_redistribute_ipv4, return bgp_redistribute_unset (vty->index, AFI_IP, type); } -DEFUN (no_bgp_redistribute_ipv4_rmap, +ALIAS (no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_rmap_cmd, "no redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD", NO_STR @@ -9415,21 +10336,8 @@ DEFUN (no_bgp_redistribute_ipv4_rmap, QUAGGA_IP_REDIST_HELP_STR_BGPD "Route map reference\n" "Pointer to route-map entries\n") -{ - int type; - - type = proto_redistnum (AFI_IP, argv[0]); - if (type < 0 || type == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - - bgp_redistribute_routemap_unset (vty->index, AFI_IP, type); - return CMD_SUCCESS; -} -DEFUN (no_bgp_redistribute_ipv4_metric, +ALIAS (no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_metric_cmd, "no redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295>", NO_STR @@ -9437,21 +10345,8 @@ DEFUN (no_bgp_redistribute_ipv4_metric, QUAGGA_IP_REDIST_HELP_STR_BGPD "Metric for redistributed routes\n" "Default metric\n") -{ - int type; - type = proto_redistnum (AFI_IP, argv[0]); - if (type < 0 || type == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - - bgp_redistribute_metric_unset (vty->index, AFI_IP, type); - return CMD_SUCCESS; -} - -DEFUN (no_bgp_redistribute_ipv4_rmap_metric, +ALIAS (no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_rmap_metric_cmd, "no redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>", NO_STR @@ -9461,22 +10356,8 @@ DEFUN (no_bgp_redistribute_ipv4_rmap_metric, "Pointer to route-map entries\n" "Metric for redistributed routes\n" "Default metric\n") -{ - int type; - type = proto_redistnum (AFI_IP, argv[0]); - if (type < 0 || type == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - - bgp_redistribute_metric_unset (vty->index, AFI_IP, type); - bgp_redistribute_routemap_unset (vty->index, AFI_IP, type); - return CMD_SUCCESS; -} - -ALIAS (no_bgp_redistribute_ipv4_rmap_metric, +ALIAS (no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_metric_rmap_cmd, "no redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD", NO_STR @@ -9620,7 +10501,7 @@ DEFUN (no_bgp_redistribute_ipv6, return bgp_redistribute_unset (vty->index, AFI_IP6, type); } -DEFUN (no_bgp_redistribute_ipv6_rmap, +ALIAS (no_bgp_redistribute_ipv6, no_bgp_redistribute_ipv6_rmap_cmd, "no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD", NO_STR @@ -9628,21 +10509,8 @@ DEFUN (no_bgp_redistribute_ipv6_rmap, QUAGGA_IP6_REDIST_HELP_STR_BGPD "Route map reference\n" "Pointer to route-map entries\n") -{ - int type; - type = proto_redistnum (AFI_IP6, argv[0]); - if (type < 0 || type == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - - bgp_redistribute_routemap_unset (vty->index, AFI_IP6, type); - return CMD_SUCCESS; -} - -DEFUN (no_bgp_redistribute_ipv6_metric, +ALIAS (no_bgp_redistribute_ipv6, no_bgp_redistribute_ipv6_metric_cmd, "no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295>", NO_STR @@ -9650,21 +10518,8 @@ DEFUN (no_bgp_redistribute_ipv6_metric, QUAGGA_IP6_REDIST_HELP_STR_BGPD "Metric for redistributed routes\n" "Default metric\n") -{ - int type; - - type = proto_redistnum (AFI_IP6, argv[0]); - if (type < 0 || type == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - bgp_redistribute_metric_unset (vty->index, AFI_IP6, type); - return CMD_SUCCESS; -} - -DEFUN (no_bgp_redistribute_ipv6_rmap_metric, +ALIAS (no_bgp_redistribute_ipv6, no_bgp_redistribute_ipv6_rmap_metric_cmd, "no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>", NO_STR @@ -9674,22 +10529,8 @@ DEFUN (no_bgp_redistribute_ipv6_rmap_metric, "Pointer to route-map entries\n" "Metric for redistributed routes\n" "Default metric\n") -{ - int type; - - type = proto_redistnum (AFI_IP6, argv[0]); - if (type < 0 || type == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - bgp_redistribute_metric_unset (vty->index, AFI_IP6, type); - bgp_redistribute_routemap_unset (vty->index, AFI_IP6, type); - return CMD_SUCCESS; -} - -ALIAS (no_bgp_redistribute_ipv6_rmap_metric, +ALIAS (no_bgp_redistribute_ipv6, no_bgp_redistribute_ipv6_metric_rmap_cmd, "no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD", NO_STR @@ -9864,6 +10705,26 @@ bgp_vty_init (void) install_element (BGP_NODE, &bgp_confederation_peers_cmd); install_element (BGP_NODE, &no_bgp_confederation_peers_cmd); + /* bgp max-med command */ + install_element (BGP_NODE, &bgp_maxmed_admin_cmd); + install_element (BGP_NODE, &no_bgp_maxmed_admin_cmd); + install_element (BGP_NODE, &bgp_maxmed_admin_medv_cmd); + install_element (BGP_NODE, &no_bgp_maxmed_admin_medv_cmd); + install_element (BGP_NODE, &bgp_maxmed_onstartup_cmd); + install_element (BGP_NODE, &no_bgp_maxmed_onstartup_cmd); + install_element (BGP_NODE, &no_bgp_maxmed_onstartup_period_cmd); + install_element (BGP_NODE, &bgp_maxmed_onstartup_medv_cmd); + install_element (BGP_NODE, &no_bgp_maxmed_onstartup_period_medv_cmd); + + /* bgp update-delay command */ + install_element (BGP_NODE, &bgp_update_delay_cmd); + install_element (BGP_NODE, &no_bgp_update_delay_cmd); + install_element (BGP_NODE, &bgp_update_delay_establish_wait_cmd); + install_element (BGP_NODE, &no_bgp_update_delay_establish_wait_cmd); + + install_element (BGP_NODE, &bgp_wpkt_quanta_cmd); + install_element (BGP_NODE, &no_bgp_wpkt_quanta_cmd); + /* "maximum-paths" commands. */ install_element (BGP_NODE, &bgp_maxpaths_cmd); install_element (BGP_NODE, &no_bgp_maxpaths_cmd); @@ -9871,18 +10732,34 @@ bgp_vty_init (void) install_element (BGP_IPV4_NODE, &bgp_maxpaths_cmd); install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_cmd); install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_arg_cmd); + install_element (BGP_IPV6_NODE, &bgp_maxpaths_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_arg_cmd); install_element (BGP_NODE, &bgp_maxpaths_ibgp_cmd); + install_element(BGP_NODE, &bgp_maxpaths_ibgp_cluster_cmd); install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cmd); install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_arg_cmd); + install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd); install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd); + install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd); install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd); install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_arg_cmd); + install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd); + install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_arg_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd); /* "timers bgp" commands. */ install_element (BGP_NODE, &bgp_timers_cmd); install_element (BGP_NODE, &no_bgp_timers_cmd); install_element (BGP_NODE, &no_bgp_timers_arg_cmd); + /* route-map delay-timer commands */ + install_element (BGP_NODE, &bgp_set_route_map_delay_timer_cmd); + install_element (BGP_NODE, &no_bgp_set_route_map_delay_timer_cmd); + /* "bgp client-to-client reflection" commands */ install_element (BGP_NODE, &no_bgp_client_to_client_reflection_cmd); install_element (BGP_NODE, &bgp_client_to_client_reflection_cmd); @@ -9951,15 +10828,21 @@ bgp_vty_init (void) install_element (BGP_NODE, &no_bgp_default_local_preference_cmd); install_element (BGP_NODE, &no_bgp_default_local_preference_val_cmd); + /* bgp ibgp-allow-policy-mods command */ + install_element (BGP_NODE, &bgp_rr_allow_outbound_policy_cmd); + install_element (BGP_NODE, &no_bgp_rr_allow_outbound_policy_cmd); + /* "neighbor remote-as" commands. */ install_element (BGP_NODE, &neighbor_remote_as_cmd); + install_element (BGP_NODE, &neighbor_interface_config_cmd); install_element (BGP_NODE, &no_neighbor_cmd); install_element (BGP_NODE, &no_neighbor_remote_as_cmd); + install_element (BGP_NODE, &no_neighbor_interface_config_cmd); /* "neighbor peer-group" commands. */ install_element (BGP_NODE, &neighbor_peer_group_cmd); install_element (BGP_NODE, &no_neighbor_peer_group_cmd); - install_element (BGP_NODE, &no_neighbor_peer_group_remote_as_cmd); + install_element (BGP_NODE, &no_neighbor_interface_peer_group_remote_as_cmd); /* "neighbor local-as" commands. */ install_element (BGP_NODE, &neighbor_local_as_cmd); @@ -10270,17 +11153,61 @@ bgp_vty_init (void) install_element (BGP_ENCAPV6_NODE, &neighbor_nexthop_self_cmd); install_element (BGP_ENCAPV6_NODE, &no_neighbor_nexthop_self_cmd); + /* "neighbor as-override" commands. */ + install_element (BGP_NODE, &neighbor_as_override_cmd); + install_element (BGP_NODE, &no_neighbor_as_override_cmd); + install_element (BGP_IPV4_NODE, &neighbor_as_override_cmd); + install_element (BGP_IPV4_NODE, &no_neighbor_as_override_cmd); + install_element (BGP_IPV4M_NODE, &neighbor_as_override_cmd); + install_element (BGP_IPV4M_NODE, &no_neighbor_as_override_cmd); + install_element (BGP_IPV6_NODE, &neighbor_as_override_cmd); + install_element (BGP_IPV6_NODE, &no_neighbor_as_override_cmd); + install_element (BGP_IPV6M_NODE, &neighbor_as_override_cmd); + install_element (BGP_IPV6M_NODE, &no_neighbor_as_override_cmd); + install_element (BGP_VPNV4_NODE, &neighbor_as_override_cmd); + install_element (BGP_VPNV4_NODE, &no_neighbor_as_override_cmd); + /* "neighbor remove-private-AS" commands. */ install_element (BGP_NODE, &neighbor_remove_private_as_cmd); install_element (BGP_NODE, &no_neighbor_remove_private_as_cmd); + install_element (BGP_NODE, &neighbor_remove_private_as_all_cmd); + install_element (BGP_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element (BGP_NODE, &neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_NODE, &no_neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_NODE, &neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_cmd); install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_cmd); + install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_cmd); install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_cmd); + install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_cmd); install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd); + install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_cmd); install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_cmd); + install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd); install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_cmd); @@ -10289,6 +11216,12 @@ bgp_vty_init (void) install_element (BGP_ENCAP_NODE, &no_neighbor_remove_private_as_cmd); install_element (BGP_ENCAPV6_NODE, &neighbor_remove_private_as_cmd); install_element (BGP_ENCAPV6_NODE, &no_neighbor_remove_private_as_cmd); + install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_cmd); + install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); /* "neighbor send-community" commands.*/ install_element (BGP_NODE, &neighbor_send_community_cmd); @@ -10856,6 +11789,10 @@ bgp_vty_init (void) install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_cmd); install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_prefix_filter_cmd); + /* clear ip bgp prefix */ + install_element (ENABLE_NODE, &clear_ip_bgp_prefix_cmd); + install_element (ENABLE_NODE, &clear_bgp_ipv6_safi_prefix_cmd); + /* "clear ip bgp neighbor soft out" */ install_element (ENABLE_NODE, &clear_ip_bgp_all_soft_out_cmd); install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_soft_out_cmd); diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 7329c5fd..fdbbb782 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -21,10 +21,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #ifndef _QUAGGA_BGP_VTY_H #define _QUAGGA_BGP_VTY_H +#include "bgpd/bgpd.h" + #define CMD_AS_RANGE "<1-4294967295>" extern void bgp_vty_init (void); extern const char *afi_safi_print (afi_t, safi_t); +extern int bgp_config_write_update_delay (struct vty *, struct bgp *); +extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp); extern int bgp_parse_afi(const char *str, afi_t *afi); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index d0b9216a..92883d5d 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -39,6 +39,8 @@ Boston, MA 02111-1307, USA. */ #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_mpath.h" +#include "bgpd/bgp_nexthop.h" +#include "bgpd/bgp_nht.h" /* All information about zebra. */ struct zclient *zclient = NULL; @@ -46,6 +48,44 @@ struct in_addr router_id_zebra; /* Growable buffer for nexthops sent to zebra */ struct stream *bgp_nexthop_buf = NULL; +struct stream *bgp_ifindices_buf = NULL; + +/* These array buffers are used in making a copy of the attributes for + route-map apply. Arrays are being used here to minimize mallocs and + frees for the temporary copy of the attributes. + Given the zapi api expects the nexthop buffer to contain pointer to + pointers for nexthops, we couldnt have used a single nexthop variable + on the stack, hence we had two options: + 1. maintain a linked-list and free it after zapi_*_route call + 2. use an array to avoid number of mallocs. + Number of supported next-hops are finite, use of arrays should be ok. */ +struct attr attr_cp[BGP_MAXIMUM_MAXPATHS]; +struct attr_extra attr_extra_cp[BGP_MAXIMUM_MAXPATHS]; +int attr_index = 0; + +/* Once per address-family initialization of the attribute array */ +#define BGP_INFO_ATTR_BUF_INIT()\ +do {\ + memset(attr_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr));\ + memset(attr_extra_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr_extra));\ + attr_index = 0;\ +} while (0) + +#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\ +do { \ + *info_dst = *info_src; \ + assert(attr_index != BGP_MAXIMUM_MAXPATHS);\ + attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \ + bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \ + bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \ + info_dst->attr = &attr_cp[attr_index]; \ + attr_index++;\ +} while (0) + +#define BGP_INFO_ATTR_BUF_FREE(info) \ +do { \ + bgp_attr_deep_free(info->attr); \ +} while (0) /* Router-id update message from zebra. */ static int @@ -58,7 +98,7 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, zebra_router_id_update_read(zclient->ibuf,&router_id); - if (BGP_DEBUG(zebra, ZEBRA)) + if (BGP_DEBUG (zebra, ZEBRA)) { char buf[128]; prefix2str(&router_id, buf, sizeof(buf)); @@ -76,6 +116,55 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, return 0; } +/* Nexthop update message from zebra. */ +static int +bgp_read_nexthop_update (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + bgp_parse_nexthop_update(); + return 0; +} + +static void +bgp_nbr_connected_add (struct nbr_connected *ifc) +{ + struct listnode *node, *nnode, *mnode; + struct bgp *bgp; + struct peer *peer; + + for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) + { + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { + if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0)) + { + if (peer_active(peer)) + BGP_EVENT_ADD (peer, BGP_Stop); + BGP_EVENT_ADD (peer, BGP_Start); + } + } + } +} + +static void +bgp_nbr_connected_delete (struct nbr_connected *ifc) +{ + struct listnode *node, *nnode, *mnode; + struct bgp *bgp; + struct peer *peer; + + for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) + { + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { + if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0)) + { + BGP_EVENT_ADD (peer, BGP_Stop); + } + } + } +} + /* Inteface addition message from zebra. */ static int bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length, @@ -85,7 +174,7 @@ bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length, ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); - if (BGP_DEBUG(zebra, ZEBRA) && ifp) + if (BGP_DEBUG (zebra, ZEBRA) && ifp) zlog_debug("Zebra rcvd: interface add %s", ifp->name); return 0; @@ -102,7 +191,7 @@ bgp_interface_delete (int command, struct zclient *zclient, ifp = zebra_interface_state_read (s, vrf_id); ifp->ifindex = IFINDEX_INTERNAL; - if (BGP_DEBUG(zebra, ZEBRA)) + if (BGP_DEBUG (zebra, ZEBRA)) zlog_debug("Zebra rcvd: interface delete %s", ifp->name); return 0; @@ -115,6 +204,7 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length, struct stream *s; struct interface *ifp; struct connected *c; + struct nbr_connected *nc; struct listnode *node, *nnode; s = zclient->ibuf; @@ -123,12 +213,15 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length, if (! ifp) return 0; - if (BGP_DEBUG(zebra, ZEBRA)) + if (BGP_DEBUG (zebra, ZEBRA)) zlog_debug("Zebra rcvd: interface %s up", ifp->name); for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) bgp_connected_add (c); + for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_add (nc); + return 0; } @@ -139,6 +232,7 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, struct stream *s; struct interface *ifp; struct connected *c; + struct nbr_connected *nc; struct listnode *node, *nnode; s = zclient->ibuf; @@ -146,12 +240,15 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, if (! ifp) return 0; - if (BGP_DEBUG(zebra, ZEBRA)) + if (BGP_DEBUG (zebra, ZEBRA)) zlog_debug("Zebra rcvd: interface %s down", ifp->name); for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) bgp_connected_delete (c); + for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_delete (nc); + /* Fast external-failover */ { struct listnode *mnode; @@ -188,7 +285,7 @@ bgp_interface_address_add (int command, struct zclient *zclient, if (ifc == NULL) return 0; - if (BGP_DEBUG(zebra, ZEBRA)) + if (bgp_debug_zebra(ifc->address)) { char buf[128]; prefix2str(ifc->address, buf, sizeof(buf)); @@ -213,7 +310,7 @@ bgp_interface_address_delete (int command, struct zclient *zclient, if (ifc == NULL) return 0; - if (BGP_DEBUG(zebra, ZEBRA)) + if (bgp_debug_zebra(ifc->address)) { char buf[128]; prefix2str(ifc->address, buf, sizeof(buf)); @@ -229,6 +326,58 @@ bgp_interface_address_delete (int command, struct zclient *zclient, return 0; } +static int +bgp_interface_nbr_address_add (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct nbr_connected *ifc = NULL; + + ifc = zebra_interface_nbr_address_read (command, zclient->ibuf); + + if (ifc == NULL) + return 0; + + if (bgp_debug_zebra(ifc->address)) + { + char buf[128]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Zebra rcvd: interface %s nbr address add %s", + ifc->ifp->name, buf); + } + + if (if_is_operative (ifc->ifp)) + bgp_nbr_connected_add (ifc); + + return 0; +} + +static int +bgp_interface_nbr_address_delete (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct nbr_connected *ifc = NULL; + + ifc = zebra_interface_nbr_address_read (command, zclient->ibuf); + + if (ifc == NULL) + return 0; + + if (bgp_debug_zebra(ifc->address)) + { + char buf[128]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Zebra rcvd: interface %s nbr address delete %s", + ifc->ifp->name, buf); + } + + if (if_is_operative (ifc->ifp)) + bgp_nbr_connected_delete (ifc); + + nbr_connected_free (ifc); + + return 0; +} + /* Zebra route add and delete treatment. */ static int zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, @@ -239,6 +388,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, struct in_addr nexthop; struct prefix_ipv4 p; unsigned char plength = 0; + ifindex_t ifindex; s = zclient->ibuf; nexthop.s_addr = 0; @@ -264,7 +414,11 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); - stream_getl (s); /* ifindex, unused */ + ifindex = stream_getl (s); /* ifindex, unused */ + } + else + { + ifindex = 0; } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); @@ -273,33 +427,40 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, else api.metric = 0; + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; + if (command == ZEBRA_IPV4_ROUTE_ADD) { - if (BGP_DEBUG(zebra, ZEBRA)) + if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u", + zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } - bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, - api.metric, api.type); + bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex, + api.metric, api.type, api.tag); } else { - if (BGP_DEBUG(zebra, ZEBRA)) + if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d " - "nexthop %s metric %u", + "nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } bgp_redistribute_delete((struct prefix *)&p, api.type); } @@ -317,6 +478,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length, struct in6_addr nexthop; struct prefix_ipv6 p; unsigned char plength = 0; + ifindex_t ifindex; s = zclient->ibuf; memset (&nexthop, 0, sizeof (struct in6_addr)); @@ -342,7 +504,11 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length, if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); - stream_getl (s); /* ifindex, unused */ + ifindex = stream_getl (s); /* ifindex, unused */ + } + else + { + ifindex = 0; } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); @@ -353,37 +519,44 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length, else api.metric = 0; + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; + /* Simply ignore link-local address. */ if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) return 0; if (command == ZEBRA_IPV6_ROUTE_ADD) { - if (BGP_DEBUG(zebra, ZEBRA)) + if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u", + zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } - bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, - api.metric, api.type); + bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex, + api.metric, api.type, api.tag); } else { - if (BGP_DEBUG(zebra, ZEBRA)) + if (bgp_debug_zebra((struct prefix *)&p)) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d " - "nexthop %s metric %u", + "nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } bgp_redistribute_delete ((struct prefix *) &p, api.type); } @@ -571,17 +744,22 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote, if (local->sa.sa_family == AF_INET) { nexthop->v4 = local->sin.sin_addr; - ifp = if_lookup_by_ipv4 (&local->sin.sin_addr); + if (peer->update_if) + ifp = if_lookup_by_name (peer->update_if); + else + ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr); } if (local->sa.sa_family == AF_INET6) { if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) { - if (peer->ifname) - ifp = if_lookup_by_name (peer->ifname); + if (peer->conf_if || peer->ifname) + ifp = if_lookup_by_index (if_nametoindex (peer->conf_if ? peer->conf_if : peer->ifname)); } + else if (peer->update_if) + ifp = if_lookup_by_name (peer->update_if); else - ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr); + ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr); } if (!ifp) @@ -661,14 +839,73 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote, return ret; } +static struct in6_addr * +bgp_info_to_ipv6_nexthop (struct bgp_info *info) +{ + struct in6_addr *nexthop = NULL; + + /* Only global address nexthop exists. */ + if (info->attr->extra->mp_nexthop_len == 16) + nexthop = &info->attr->extra->mp_nexthop_global; + + /* If both global and link-local address present. */ + if (info->attr->extra->mp_nexthop_len == 32) + { + /* Workaround for Cisco's nexthop bug. */ + if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) + && info->peer->su_remote->sa.sa_family == AF_INET6) + nexthop = &info->peer->su_remote->sin6.sin6_addr; + else + nexthop = &info->attr->extra->mp_nexthop_local; + } + + return nexthop; +} + +static int +bgp_table_map_apply (struct route_map *map, struct prefix *p, + struct bgp_info *info) +{ + if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH) + return 1; + + if (bgp_debug_zebra(p)) + { + if (p->family == AF_INET) + { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug("Zebra rmap deny: IPv4 route %s/%d nexthop %s", + inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, &info->attr->nexthop, buf[1], + sizeof(buf[1]))); + } + if (p->family == AF_INET6) + { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug("Zebra rmap deny: IPv6 route %s/%d nexthop %s", + inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET6, bgp_info_to_ipv6_nexthop(info), buf[1], + sizeof(buf[1]))); + } + } + return 0; +} + void -bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi) +bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, + afi_t afi, safi_t safi) { int flags; u_char distance; struct peer *peer; struct bgp_info *mpinfo; size_t oldsize, newsize; + u_int32_t nhcount, metric; + struct bgp_info local_info; + struct bgp_info *info_cp = &local_info; + u_short tag = 0; if (zclient->sock < 0) return; @@ -676,9 +913,15 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT)) return; + if (bgp->main_zebra_update_hold) + return; + flags = 0; peer = info->peer; + if ((info->attr->extra) && (info->attr->extra->tag != 0)) + tag = info->attr->extra->tag; + if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) { SET_FLAG (flags, ZEBRA_FLAG_IBGP); @@ -689,46 +932,108 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - /* resize nexthop buffer size if necessary */ - if ((oldsize = stream_get_size (bgp_nexthop_buf)) < - (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1))) - { - newsize = (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1)); - newsize = stream_resize (bgp_nexthop_buf, newsize); - if (newsize == oldsize) - { - zlog_err ("can't resize nexthop buffer"); - return; - } - } - - stream_reset (bgp_nexthop_buf); + nhcount = 1 + bgp_info_mpath_count (info); if (p->family == AF_INET) { struct zapi_ipv4 api; struct in_addr *nexthop; + char buf[2][INET_ADDRSTRLEN]; + int valid_nh_count = 0; + + /* resize nexthop buffer size if necessary */ + if ((oldsize = stream_get_size (bgp_nexthop_buf)) < + (sizeof (struct in_addr *) * nhcount)) + { + newsize = (sizeof (struct in_addr *) * nhcount); + newsize = stream_resize (bgp_nexthop_buf, newsize); + if (newsize == oldsize) + { + zlog_err ("can't resize nexthop buffer"); + return; + } + } + stream_reset (bgp_nexthop_buf); + nexthop = NULL; + + /* Metric is currently based on the best-path only. */ + metric = info->attr->med; + + if (bgp->table_map[afi][safi].name) + { + BGP_INFO_ATTR_BUF_INIT(); + + /* Copy info and attributes, so the route-map apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(info, info_cp); + if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) + { + metric = info_cp->attr->med; + nexthop = &info_cp->attr->nexthop; + + if (info_cp->attr->extra) + tag = info_cp->attr->extra->tag; + } + BGP_INFO_ATTR_BUF_FREE(info_cp); + } + else + { + nexthop = &info->attr->nexthop; + } + + if (nexthop) + { + stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); + valid_nh_count++; + } api.vrf_id = VRF_DEFAULT; api.flags = flags; nexthop = &info->attr->nexthop; stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); + for (mpinfo = bgp_info_mpath_first (info); mpinfo; - mpinfo = bgp_info_mpath_next (mpinfo)) - { - nexthop = &mpinfo->attr->nexthop; - stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); - } + mpinfo = bgp_info_mpath_next (mpinfo)) + { + nexthop = NULL; + + if (bgp->table_map[afi][safi].name) + { + /* Copy info and attributes, so the route-map apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); + if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) + nexthop = &info_cp->attr->nexthop; + BGP_INFO_ATTR_BUF_FREE(info_cp); + } + else + { + nexthop = &mpinfo->attr->nexthop; + } + + if (nexthop == NULL) + continue; + + stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); + valid_nh_count++; + } + api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1 + bgp_info_mpath_count (info); + api.nexthop_num = valid_nh_count; api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf); api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; + api.metric = metric; + + if (tag) + { + SET_FLAG (api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } distance = bgp_distance_apply (p, info, bgp); @@ -738,24 +1043,20 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa api.distance = distance; } - if (BGP_DEBUG(zebra, ZEBRA)) - { - int i; - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u" - " count %d", - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])), - api.metric, api.nexthop_num); - for (i = 1; i < api.nexthop_num; i++) - zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s", - i, inet_ntop(AF_INET, api.nexthop[i], buf[1], - sizeof(buf[1]))); - } - - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, - (struct prefix_ipv4 *) p, &api); + if (bgp_debug_zebra(p)) + { + int i; + zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u tag %d" + " count %d", (valid_nh_count ? "add":"delete"), + inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag, api.nexthop_num); + for (i = 0; i < api.nexthop_num; i++) + zlog_debug(" IPv4 [nexthop %d] %s", i+1, + inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1]))); + } + + zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE, + zclient, (struct prefix_ipv4 *) p, &api); } /* We have to think about a IPv6 link-local address curse. */ @@ -764,40 +1065,131 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa ifindex_t ifindex; struct in6_addr *nexthop; struct zapi_ipv6 api; + int valid_nh_count = 0; + char buf[2][INET6_ADDRSTRLEN]; + + /* resize nexthop buffer size if necessary */ + if ((oldsize = stream_get_size (bgp_nexthop_buf)) < + (sizeof (struct in6_addr *) * nhcount)) + { + newsize = (sizeof (struct in6_addr *) * nhcount); + newsize = stream_resize (bgp_nexthop_buf, newsize); + if (newsize == oldsize) + { + zlog_err ("can't resize nexthop buffer"); + return; + } + } + stream_reset (bgp_nexthop_buf); + + /* resize ifindices buffer size if necessary */ + if ((oldsize = stream_get_size (bgp_ifindices_buf)) < + (sizeof (unsigned int) * nhcount)) + { + newsize = (sizeof (unsigned int) * nhcount); + newsize = stream_resize (bgp_ifindices_buf, newsize); + if (newsize == oldsize) + { + zlog_err ("can't resize nexthop buffer"); + return; + } + } + stream_reset (bgp_ifindices_buf); ifindex = 0; nexthop = NULL; - - assert (info->attr->extra); - - /* Only global address nexthop exists. */ - if (info->attr->extra->mp_nexthop_len == 16) - nexthop = &info->attr->extra->mp_nexthop_global; - - /* If both global and link-local address present. */ - if (info->attr->extra->mp_nexthop_len == 32) - { - /* Workaround for Cisco's nexthop bug. */ - if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) - && peer->su_remote->sa.sa_family == AF_INET6) - nexthop = &peer->su_remote->sin6.sin6_addr; - else - nexthop = &info->attr->extra->mp_nexthop_local; - if (info->peer->nexthop.ifp) - ifindex = info->peer->nexthop.ifp->ifindex; - } + assert (info->attr->extra); - if (nexthop == NULL) - return; + /* Metric is currently based on the best-path only. */ + metric = info->attr->med; + + if (bgp->table_map[afi][safi].name) + { + BGP_INFO_ATTR_BUF_INIT(); + + /* Copy info and attributes, so the route-map apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(info, info_cp); + if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) + { + metric = info_cp->attr->med; + nexthop = bgp_info_to_ipv6_nexthop(info_cp); + + if (info_cp->attr->extra) + tag = info_cp->attr->extra->tag; + } + BGP_INFO_ATTR_BUF_FREE(info_cp); + } + else + { + nexthop = bgp_info_to_ipv6_nexthop(info); + } + + if (nexthop) + { + if (IN6_IS_ADDR_LINKLOCAL (nexthop)) + { + if (info->attr->extra->mp_nexthop_len == 32) + if (info->peer->nexthop.ifp) + ifindex = info->peer->nexthop.ifp->ifindex; + + if (!ifindex) + { + if (info->peer->conf_if || info->peer->ifname) + ifindex = if_nametoindex (info->peer->conf_if ? info->peer->conf_if : info->peer->ifname); + else if (info->peer->nexthop.ifp) + ifindex = info->peer->nexthop.ifp->ifindex; + } + } + + stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *)); + stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int)); + valid_nh_count++; + } - if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex) - { - if (info->peer->ifname) - ifindex = ifname2ifindex (info->peer->ifname); - else if (info->peer->nexthop.ifp) - ifindex = info->peer->nexthop.ifp->ifindex; - } + for (mpinfo = bgp_info_mpath_first (info); mpinfo; + mpinfo = bgp_info_mpath_next (mpinfo)) + { + ifindex = 0; + nexthop = NULL; + + if (bgp->table_map[afi][safi].name) + { + /* Copy info and attributes, so the route-map apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); + if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) + nexthop = bgp_info_to_ipv6_nexthop(info_cp); + BGP_INFO_ATTR_BUF_FREE(info_cp); + } + else + { + nexthop = bgp_info_to_ipv6_nexthop(mpinfo); + } + + if (nexthop == NULL) + continue; + + if (mpinfo->attr->extra->mp_nexthop_len == 32) + if (mpinfo->peer->nexthop.ifp) + ifindex = mpinfo->peer->nexthop.ifp->ifindex; + + if (!ifindex) + { + if (mpinfo->peer->conf_if || mpinfo->peer->ifname) + ifindex = if_nametoindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname); + else if (mpinfo->peer->nexthop.ifp) + ifindex = mpinfo->peer->nexthop.ifp->ifindex; + } + + if (ifindex == 0) + continue; + + stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *)); + stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int)); + valid_nh_count++; + } /* Make Zebra API structure. */ api.vrf_id = VRF_DEFAULT; @@ -806,29 +1198,57 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop; + api.nexthop_num = valid_nh_count; + api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; + api.ifindex_num = valid_nh_count; + api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; + api.metric = metric; - if (BGP_DEBUG(zebra, ZEBRA)) + if (tag) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u", - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])), - api.metric); + SET_FLAG (api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; } - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, - (struct prefix_ipv6 *) p, &api); + if (bgp_debug_zebra(p)) + { + int i; + zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u tag %d", + valid_nh_count ? "add" : "delete", + inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + for (i = 0; i < api.nexthop_num; i++) + zlog_debug(" IPv6 [nexthop %d] %s (%d)", i+1, + inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])), + api.ifindex[i]); + } + + zapi_ipv6_route (valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE, + zclient, (struct prefix_ipv6 *) p, &api); } } +/* Announce all routes of a table to zebra */ +void +bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_info *ri; + + table = bgp->rib[afi][safi]; + if (!table) return; + + for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) + for (ri = rn->info; ri; ri = ri->next) + if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_announce (&rn->p, ri, bgp, afi, safi); +} + void bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) { @@ -842,6 +1262,10 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) return; peer = info->peer; + + if (peer->bgp && peer->bgp->main_zebra_update_hold) + return; + flags = 0; if (peer->sort == BGP_PEER_IBGP) @@ -869,13 +1293,20 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; - if (BGP_DEBUG(zebra, ZEBRA)) + if ((info->attr->extra) && (info->attr->extra->tag != 0)) + { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->extra->tag; + } + + if (bgp_debug_zebra(p)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u", + zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u tag %d", inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, - api.metric); + api.metric, + api.tag); } zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, @@ -886,7 +1317,6 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) if (p->family == AF_INET6) { struct zapi_ipv6 api; - api.vrf_id = VRF_DEFAULT; api.flags = flags; api.type = ZEBRA_ROUTE_BGP; @@ -897,13 +1327,20 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; - if (BGP_DEBUG(zebra, ZEBRA)) + if ((info->attr->extra) && (info->attr->extra->tag != 0)) + { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->extra->tag; + } + + if (bgp_debug_zebra(p)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u", + zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u tag %d", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, - api.metric); + api.metric, + api.tag); } zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, @@ -928,15 +1365,32 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type) if (zclient->sock < 0) return CMD_WARNING; - if (BGP_DEBUG(zebra, ZEBRA)) + if (BGP_DEBUG (zebra, ZEBRA)) zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type)); - + /* Send distribute add message to zebra. */ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT); return CMD_SUCCESS; } +int +bgp_redistribute_resend (struct bgp *bgp, afi_t afi, int type) +{ + /* Return if zebra connection is not established. */ + if (zclient->sock < 0) + return -1; + + if (BGP_DEBUG (zebra, ZEBRA)) + zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type)); + + /* Send distribute add message to zebra. */ + zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, VRF_DEFAULT); + zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT); + + return 0; +} + /* Redistribute with route-map specification. */ int bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type, @@ -996,7 +1450,7 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type) && zclient->sock >= 0) { /* Send distribute delete message to zebra. */ - if (BGP_DEBUG(zebra, ZEBRA)) + if (BGP_DEBUG (zebra, ZEBRA)) zlog_debug("Zebra send: redistribute delete %s", zebra_route_string(type)); zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, @@ -1009,35 +1463,6 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type) return CMD_SUCCESS; } -/* Unset redistribution route-map configuration. */ -int -bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type) -{ - if (! bgp->rmap[afi][type].name) - return 0; - - /* Unset route-map. */ - free (bgp->rmap[afi][type].name); - bgp->rmap[afi][type].name = NULL; - bgp->rmap[afi][type].map = NULL; - - return 1; -} - -/* Unset redistribution metric configuration. */ -int -bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type) -{ - if (! bgp->redist_metric_flag[afi][type]) - return 0; - - /* Unset metric. */ - bgp->redist_metric_flag[afi][type] = 0; - bgp->redist_metric[afi][type] = 0; - - return 1; -} - void bgp_zclient_reset (void) { @@ -1062,14 +1487,18 @@ bgp_zebra_init (struct thread_master *master) zclient->interface_delete = bgp_interface_delete; zclient->interface_address_add = bgp_interface_address_add; zclient->interface_address_delete = bgp_interface_address_delete; + zclient->interface_nbr_address_add = bgp_interface_nbr_address_add; + zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete; zclient->ipv4_route_add = zebra_read_ipv4; zclient->ipv4_route_delete = zebra_read_ipv4; zclient->interface_up = bgp_interface_up; zclient->interface_down = bgp_interface_down; zclient->ipv6_route_add = zebra_read_ipv6; zclient->ipv6_route_delete = zebra_read_ipv6; + zclient->nexthop_update = bgp_read_nexthop_update; bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE); + bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE); } void diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index e69a0bc5..0b76263c 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -22,8 +22,10 @@ Boston, MA 02111-1307, USA. */ #define _QUAGGA_BGP_ZEBRA_H #define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *)) +#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int)) extern struct stream *bgp_nexthop_buf; +extern struct stream *bgp_ifindices_buf; extern void bgp_zebra_init (struct thread_master *master); extern void bgp_zebra_destroy (void); @@ -32,15 +34,16 @@ extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t, safi_t, int *); extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t, int *); -extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *, safi_t); +extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *, + afi_t, safi_t); +extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t); extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t); extern int bgp_redistribute_set (struct bgp *, afi_t, int); +extern int bgp_redistribute_resend (struct bgp *, afi_t, int); extern int bgp_redistribute_rmap_set (struct bgp *, afi_t, int, const char *); extern int bgp_redistribute_metric_set (struct bgp *, afi_t, int, u_int32_t); extern int bgp_redistribute_unset (struct bgp *, afi_t, int); -extern int bgp_redistribute_routemap_unset (struct bgp *, afi_t, int); -extern int bgp_redistribute_metric_unset (struct bgp *, afi_t, int); extern struct interface *if_lookup_by_ipv4 (struct in_addr *); extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 249d20f3..72ad1c19 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -61,6 +61,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_network.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_mpath.h" +#include "bgpd/bgp_nht.h" #ifdef HAVE_SNMP #include "bgpd/bgp_snmp.h" #endif /* HAVE_SNMP */ @@ -76,6 +77,44 @@ struct bgp_master *bm; /* BGP community-list. */ struct community_list_handler *bgp_clist; + +static inline void +bgp_session_reset(struct peer *peer) +{ + if (peer->doppelganger && (peer->doppelganger->status != Deleted) + && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); + + BGP_EVENT_ADD (peer, BGP_Stop); +} + +/* + * During session reset, we may delete the doppelganger peer, which would + * be the next node to the current node. If the session reset was invoked + * during walk of peer list, we would end up accessing the freed next + * node. This function moves the next node along. + */ +static inline void +bgp_session_reset_safe(struct peer *peer, struct listnode **nnode) +{ + struct listnode *n; + struct peer *npeer; + + n = (nnode) ? *nnode : NULL; + npeer = (n) ? listgetdata(n) : NULL; + + if (peer->doppelganger && (peer->doppelganger->status != Deleted) + && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) + { + if (peer->doppelganger == npeer) + /* nnode and *nnode are confirmed to be non-NULL here */ + *nnode = (*nnode)->next; + peer_delete(peer->doppelganger); + } + + BGP_EVENT_ADD (peer, BGP_Stop); +} + /* BGP global flag manipulation. */ int bgp_option_set (int flag) @@ -311,9 +350,8 @@ bgp_confederation_id_set (struct bgp *bgp, as_t as) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); } - else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset_safe(peer, &nnode); } } else @@ -332,7 +370,7 @@ bgp_confederation_id_set (struct bgp *bgp, as_t as) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset_safe(peer, &nnode); } } } @@ -362,7 +400,7 @@ bgp_confederation_id_unset (struct bgp *bgp) } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset_safe(peer, &nnode); } } return 0; @@ -425,7 +463,7 @@ bgp_confederation_peers_add (struct bgp *bgp, as_t as) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset_safe(peer, &nnode); } } } @@ -481,7 +519,7 @@ bgp_confederation_peers_remove (struct bgp *bgp, as_t as) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset_safe(peer, &nnode); } } } @@ -530,7 +568,7 @@ peer_rsclient_active (struct peer *peer) } /* Peer comparison function for sorting. */ -static int +int peer_cmp (struct peer *p1, struct peer *p2) { return sockunion_cmp (&p1->su, &p2->su); @@ -759,6 +797,10 @@ peer_free (struct peer *peer) XFREE(MTYPE_TMP, peer->notify.data); bgp_sync_delete (peer); + + if (peer->conf_if) + XFREE (MTYPE_PEER_CONF_IF, peer->conf_if); + memset (peer, 0, sizeof (struct peer)); XFREE (MTYPE_BGP_PEER, peer); @@ -801,7 +843,7 @@ peer_unlock_with_caller (const char *name, struct peer *peer) return peer; } - + /* Allocate new peer object, implicitely locked. */ static struct peer * peer_new (struct bgp *bgp) @@ -825,11 +867,11 @@ peer_new (struct bgp *bgp) peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; peer->status = Idle; peer->ostatus = Idle; - peer->weight = 0; - peer->password = NULL; peer->bgp = bgp; peer = peer_lock (peer); /* initial reference */ bgp_lock (bgp); + peer->weight = 0; + peer->password = NULL; /* Set default flags. */ for (afi = AFI_IP; afi < AFI_MAX; afi++) @@ -847,9 +889,22 @@ peer_new (struct bgp *bgp) /* Create buffers. */ peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE); peer->obuf = stream_fifo_new (); - peer->work = stream_new (BGP_MAX_PACKET_SIZE); + + /* We use a larger buffer for peer->work in the event that: + * - We RX a BGP_UPDATE where the attributes alone are just + * under BGP_MAX_PACKET_SIZE + * - The user configures an outbound route-map that does many as-path + * prepends or adds many communities. At most they can have CMD_ARGC_MAX + * args in a route-map so there is a finite limit on how large they can + * make the attributes. + * + * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds + * checking for every single attribute as we construct an UPDATE. + */ + peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); peer->scratch = stream_new (BGP_MAX_PACKET_SIZE); + bgp_sync_init (peer); /* Get service port number. */ @@ -859,17 +914,149 @@ peer_new (struct bgp *bgp) return peer; } +/* + * This function is invoked when a duplicate peer structure associated with + * a neighbor is being deleted. If this about-to-be-deleted structure is + * the one with all the config, then we have to copy over the info. + */ +void +peer_xfer_config (struct peer *peer_dst, struct peer *peer_src) +{ + afi_t afi; + safi_t safi; + + assert(peer_src); + assert(peer_dst); + + /* The following function is used by both peer group config copy to + * individual peer and when we transfer config + */ + if (peer_src->change_local_as) + peer_dst->change_local_as = peer_src->change_local_as; + + /* peer flags apply */ + peer_dst->flags = peer_src->flags; + peer_dst->cap = peer_src->cap; + peer_dst->config = peer_src->config; + + peer_dst->local_as = peer_src->local_as; + peer_dst->ifindex = peer_src->ifindex; + peer_dst->port = peer_src->port; + peer_sort(peer_dst); + peer_dst->rmap_type = peer_src->rmap_type; + + /* Timers */ + peer_dst->holdtime = peer_src->holdtime; + peer_dst->keepalive = peer_src->keepalive; + peer_dst->connect = peer_src->connect; + peer_dst->v_holdtime = peer_src->v_holdtime; + peer_dst->v_keepalive = peer_src->v_keepalive; + peer_dst->routeadv = peer_src->routeadv; + peer_dst->v_routeadv = peer_src->v_routeadv; + + /* password apply */ + if (peer_src->password && !peer_dst->password) + peer_dst->password = XSTRDUP (MTYPE_PEER_PASSWORD, peer_src->password); + + bgp_md5_set (peer_dst); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + peer_dst->afc[afi][safi] = peer_src->afc[afi][safi]; + peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi]; + peer_dst->allowas_in[afi][safi] = peer_src->allowas_in[afi][safi]; + } + + /* update-source apply */ + if (peer_src->update_source) + { + if (peer_dst->update_source) + sockunion_free (peer_dst->update_source); + if (peer_dst->update_if) + { + XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); + peer_dst->update_if = NULL; + } + peer_dst->update_source = sockunion_dup (peer_src->update_source); + } + else if (peer_src->update_if) + { + if (peer_dst->update_if) + XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); + if (peer_dst->update_source) + { + sockunion_free (peer_dst->update_source); + peer_dst->update_source = NULL; + } + peer_dst->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if); + } + + if (peer_src->ifname) + { + if (peer_dst->ifname) + free(peer_dst->ifname); + + peer_dst->ifname = strdup(peer_src->ifname); + } +} + +/* + * Set or reset the peer address socketunion structure based on the + * learnt peer address. Currently via the source address of the + * ipv6 ND router-advertisement. + */ +void +bgp_peer_conf_if_to_su_update (struct peer *peer) +{ + struct interface *ifp; + struct nbr_connected *ifc; + + if (!peer->conf_if) + return; + + if ((ifp = if_lookup_by_name(peer->conf_if)) && + ifp->nbr_connected && + (ifc = listnode_head(ifp->nbr_connected))) + { + peer->su.sa.sa_family = AF_INET6; + memcpy(&peer->su.sin6.sin6_addr, &ifc->address->u.prefix, + sizeof (struct in6_addr)); +#ifdef SIN6_LEN + peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6); +#endif + } + else + { + /* This works as an indication of unresolved peer address + on a BGP interface*/ + peer->su.sa.sa_family = AF_UNSPEC; + memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr)); + } +} + /* Create new BGP peer. */ -static struct peer * -peer_create (union sockunion *su, struct bgp *bgp, as_t local_as, - as_t remote_as, afi_t afi, safi_t safi) +struct peer * +peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp, + as_t local_as, as_t remote_as, afi_t afi, safi_t safi) { int active; struct peer *peer; char buf[SU_ADDRSTRLEN]; peer = peer_new (bgp); - peer->su = *su; + if (conf_if) + { + peer->conf_if = XSTRDUP (MTYPE_PEER_CONF_IF, conf_if); + bgp_peer_conf_if_to_su_update(peer); + peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, conf_if); + } + else if (su) + { + peer->su = *su; + sockunion2str (su, buf, SU_ADDRSTRLEN); + peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); + } peer->local_as = local_as; peer->as = remote_as; peer->local_id = bgp->router_id; @@ -894,9 +1081,7 @@ peer_create (union sockunion *su, struct bgp *bgp, as_t local_as, /* Default TTL set. */ peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1; - /* Make peer's address string. */ - sockunion2str (su, buf, SU_ADDRSTRLEN); - peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); + SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); /* Set up peer's events and timers. */ if (! active && peer_active (peer)) @@ -905,6 +1090,26 @@ peer_create (union sockunion *su, struct bgp *bgp, as_t local_as, return peer; } +struct peer * +peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi, + safi_t safi) +{ + struct peer *peer; + + peer = peer_lookup_by_conf_if (bgp, conf_if); + if (!peer) + { + if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) + && afi == AFI_IP && safi == SAFI_UNICAST) + peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, 0, 0); + else + peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, afi, safi); + + } + + return peer; +} + /* Make accept BGP peer. Called from bgp_accept (). */ struct peer * peer_create_accept (struct bgp *bgp) @@ -912,7 +1117,7 @@ peer_create_accept (struct bgp *bgp) struct peer *peer; peer = peer_new (bgp); - + peer = peer_lock (peer); /* bgp peer list reference */ listnode_add_sort (bgp->peer, peer); @@ -920,7 +1125,7 @@ peer_create_accept (struct bgp *bgp) } /* Change peer's AS number. */ -static void +void peer_as_change (struct peer *peer, as_t as) { bgp_peer_sort_t type; @@ -936,7 +1141,7 @@ peer_as_change (struct peer *peer, as_t as) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } type = peer_sort (peer); peer->as = as; @@ -1000,13 +1205,16 @@ peer_as_change (struct peer *peer, as_t as) /* If peer does not exist, create new one. If peer already exists, set AS number to the peer. */ int -peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as, - afi_t afi, safi_t safi) +peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t *as, + afi_t afi, safi_t safi) { struct peer *peer; as_t local_as; - peer = peer_lookup (bgp, su); + if (conf_if) + peer = peer_lookup_by_conf_if (bgp, conf_if); + else + peer = peer_lookup (bgp, su); if (peer) { @@ -1043,6 +1251,8 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as, } else { + if (conf_if) + return BGP_ERR_NO_INTERFACE_CONFIG; /* If the peer is not part of our confederation, and its not an iBGP peer then spoof the source AS */ @@ -1058,9 +1268,9 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as, if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) && afi == AFI_IP && safi == SAFI_UNICAST) - peer_create (su, bgp, local_as, *as, 0, 0); + peer = peer_create (su, conf_if, bgp, local_as, *as, 0, 0); else - peer_create (su, bgp, local_as, *as, afi, safi); + peer = peer_create (su, conf_if, bgp, local_as, *as, afi, safi); } return 0; @@ -1195,13 +1405,13 @@ peer_nsf_stop (struct peer *peer) if (peer->t_gr_restart) { BGP_TIMER_OFF (peer->t_gr_restart); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s graceful restart timer stopped", peer->host); } if (peer->t_gr_stale) { BGP_TIMER_OFF (peer->t_gr_stale); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); } bgp_clear_route_all (peer); @@ -1229,12 +1439,14 @@ peer_delete (struct peer *peer) struct listnode *pn; assert (peer->status != Deleted); - + bgp = peer->bgp; if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) peer_nsf_stop (peer); + SET_FLAG(peer->flags, PEER_FLAG_DELETE); + /* If this peer belongs to peer group, clear up the relationship. */ if (peer->group) @@ -1253,6 +1465,13 @@ peer_delete (struct peer *peer) */ peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; bgp_stop (peer); + UNSET_FLAG(peer->flags, PEER_FLAG_DELETE); + + if (peer->doppelganger) + peer->doppelganger->doppelganger = NULL; + peer->doppelganger = NULL; + + UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); bgp_fsm_change_status (peer, Deleted); /* Password configuration */ @@ -1266,7 +1485,7 @@ peer_delete (struct peer *peer) } bgp_timer_set (peer); /* stops all timers for Deleted */ - + /* Delete from all peer list. */ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) && (pn = listnode_lookup (bgp->peer, peer))) @@ -1281,12 +1500,15 @@ peer_delete (struct peer *peer) peer_unlock (peer); /* rsclient list reference */ list_delete_node (bgp->rsclient, pn); - /* Clear our own rsclient ribs. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - if (CHECK_FLAG(peer->af_flags[afi][safi], - PEER_FLAG_RSERVER_CLIENT)) - bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT); + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + { + /* Clear our own rsclient ribs. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_RSERVER_CLIENT)) + bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT); + } } /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not @@ -1765,13 +1987,21 @@ peer_group_delete (struct peer_group *group) { struct bgp *bgp; struct peer *peer; + struct peer *other; struct listnode *node, *nnode; bgp = group->bgp; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) { + other = peer->doppelganger; + peer->group = NULL; peer_delete (peer); + if (other && other->status != Deleted) + { + other->group = NULL; + peer_delete(other); + } } list_delete (group->peer); @@ -1792,7 +2022,7 @@ peer_group_delete (struct peer_group *group) int peer_group_remote_as_delete (struct peer_group *group) { - struct peer *peer; + struct peer *peer, *other; struct listnode *node, *nnode; if (! group->conf->as) @@ -1800,7 +2030,16 @@ peer_group_remote_as_delete (struct peer_group *group) for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) { + other = peer->doppelganger; + + peer->group = NULL; peer_delete (peer); + + if (other && other->status != Deleted) + { + other->group = NULL; + peer_delete(other); + } } list_delete_all_node (group->peer); @@ -1811,10 +2050,9 @@ peer_group_remote_as_delete (struct peer_group *group) /* Bind specified peer to peer group. */ int -peer_group_bind (struct bgp *bgp, union sockunion *su, +peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, struct peer_group *group, afi_t afi, safi_t safi, as_t *as) { - struct peer *peer; int first_member = 0; /* Check peer group's address family. */ @@ -1822,7 +2060,8 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED; /* Lookup the peer. */ - peer = peer_lookup (bgp, su); + if (!peer) + peer = peer_lookup (bgp, su); /* Create a new peer. */ if (! peer) @@ -1830,13 +2069,14 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, if (! group->conf->as) return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; - peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi); + peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, afi, safi); peer->group = group; peer->af_group[afi][safi] = 1; peer = peer_lock (peer); /* group->peer list reference */ listnode_add (group->peer, peer); peer_group2peer_config_copy (group, peer, afi, safi); + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); return 0; } @@ -1943,6 +2183,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, } peer_group2peer_config_copy (group, peer, afi, safi); + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { @@ -1951,7 +2192,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); return 0; } @@ -1960,6 +2201,8 @@ int peer_group_unbind (struct bgp *bgp, struct peer *peer, struct peer_group *group, afi_t afi, safi_t safi) { + struct peer *other; + if (! peer->af_group[afi][safi]) return 0; @@ -1979,9 +2222,20 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer, peer_unlock (peer); /* peer group list reference */ listnode_delete (group->peer, peer); peer->group = NULL; + other = peer->doppelganger; if (group->conf->as) { peer_delete (peer); + if (other && other->status != Deleted) + { + if (other->group) + { + peer_unlock(other); + listnode_delete(group->peer, other); + } + other->group = NULL; + peer_delete(other); + } return 0; } peer_global_config_reset (peer); @@ -1994,7 +2248,7 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer, BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); return 0; } @@ -2045,6 +2299,7 @@ bgp_create (as_t *as, const char *name) bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS; } + bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; @@ -2057,6 +2312,10 @@ bgp_create (as_t *as, const char *name) if (name) bgp->name = strdup (name); + bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; + bgp->adv_quanta = BGP_ADV_FIFO_QUANTA; + bgp->wd_quanta = BGP_WD_FIFO_QUANTA; + THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire, bgp, bgp->restart_time); @@ -2152,6 +2411,9 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name) bgp_router_id_set(bgp, &router_id_zebra); *bgp_val = bgp; + bgp->t_rmap_update = NULL; + bgp->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; + /* Create BGP server socket, if first instance. */ if (list_isempty(bm->bgp) && !bgp_option_check (BGP_OPT_NO_LISTEN)) @@ -2180,6 +2442,20 @@ bgp_delete (struct bgp *bgp) THREAD_OFF (bgp->t_startup); + for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) + { + if (peer->status == Established || + peer->status == OpenSent || + peer->status == OpenConfirm) + { + bgp_notify_send (peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_PEER_UNCONFIG); + } + } + + if (bgp->t_rmap_update) + BGP_TIMER_OFF(bgp->t_rmap_update); + /* Delete static route. */ bgp_static_delete (bgp); @@ -2189,17 +2465,6 @@ bgp_delete (struct bgp *bgp) if (i != ZEBRA_ROUTE_BGP) bgp_redistribute_unset (bgp, afi, i); - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - /* Send notify to remote peer. */ - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - } - - peer_delete (peer); - } - for (ALL_LIST_ELEMENTS (bgp->group, node, next, group)) { for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer)) @@ -2213,6 +2478,17 @@ bgp_delete (struct bgp *bgp) peer_group_delete (group); } + for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) + { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + { + /* Send notify to remote peer. */ + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + } + + peer_delete (peer); + } + assert (listcount (bgp->rsclient) == 0); if (bgp->peer_self) { @@ -2284,25 +2560,28 @@ bgp_free (struct bgp *bgp) } struct peer * -peer_lookup (struct bgp *bgp, union sockunion *su) +peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if) { struct peer *peer; struct listnode *node, *nnode; + if (!conf_if) + return NULL; + if (bgp != NULL) { for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (sockunion_same (&peer->su, su) + if (peer->conf_if && !strcmp(peer->conf_if, conf_if) && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) return peer; } else if (bm->bgp != NULL) { struct listnode *bgpnode, *nbgpnode; - + for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (sockunion_same (&peer->su, su) + if (peer->conf_if && !strcmp(peer->conf_if, conf_if) && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) return peer; } @@ -2310,44 +2589,27 @@ peer_lookup (struct bgp *bgp, union sockunion *su) } struct peer * -peer_lookup_with_open (union sockunion *su, as_t remote_as, - struct in_addr *remote_id, int *as) +peer_lookup (struct bgp *bgp, union sockunion *su) { struct peer *peer; - struct listnode *node; - struct listnode *bgpnode; - struct bgp *bgp; - - if (! bm->bgp) - return NULL; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp)) + if (bgp != NULL) { - for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) - { - if (sockunion_same (&peer->su, su) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - if (peer->as == remote_as - && peer->remote_id.s_addr == remote_id->s_addr) - return peer; - if (peer->as == remote_as) - *as = 1; - } - } - - for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) - { + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + if (sockunion_same (&peer->su, su) + && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))) + return peer; + } + else if (bm->bgp != NULL) + { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) if (sockunion_same (&peer->su, su) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - if (peer->as == remote_as - && peer->remote_id.s_addr == 0) - return peer; - if (peer->as == remote_as) - *as = 1; - } - } + && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))) + return peer; } return NULL; } @@ -2356,6 +2618,8 @@ peer_lookup_with_open (union sockunion *su, as_t remote_as, int peer_active (struct peer *peer) { + if (BGP_PEER_SU_UNSPEC(peer)) + return 0; if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_MPLS_VPN] @@ -2404,16 +2668,31 @@ peer_change_action (struct peer *peer, afi_t afi, safi_t safi, return; if (type == peer_change_reset) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + { + /* If we're resetting session, we've to delete both peer struct */ + if ((peer->doppelganger) && (peer->doppelganger->status != Deleted) + && (!CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); + + bgp_notify_send (peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else if (type == peer_change_reset_in) { if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); else - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + { + if ((peer->doppelganger) && (peer->doppelganger->status != Deleted) + && (!CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); + + bgp_notify_send (peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } } else if (type == peer_change_reset_out) bgp_announce_route (peer, afi, safi); @@ -2458,11 +2737,14 @@ static const struct peer_flag_action peer_af_flag_action_list[] = { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out }, { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out }, { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out }, + { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out }, + { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out }, { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in }, { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset }, { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset }, { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out }, { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out }, + { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out }, { 0, 0, 0 } }; @@ -2530,19 +2812,19 @@ peer_flag_modify_action (struct peer *peer, u_int32_t flag) if (peer->t_pmax_restart) { BGP_TIMER_OFF (peer->t_pmax_restart); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Maximum-prefix restart timer canceled", peer->host); } - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - peer_nsf_stop (peer); + if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) + peer_nsf_stop (peer); if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } else { @@ -2563,7 +2845,7 @@ peer_flag_modify_action (struct peer *peer, u_int32_t flag) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } /* Change specified peer flag. */ @@ -2706,6 +2988,11 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, && peer_sort (peer) == BGP_PEER_IBGP) return BGP_ERR_REMOVE_PRIVATE_AS; + /* as-override is not allowed for IBGP peers */ + if (flag & PEER_FLAG_AS_OVERRIDE + && peer_sort (peer) == BGP_PEER_IBGP) + return BGP_ERR_AS_OVERRIDE; + /* When unset the peer-group member's flag we have to check peer-group configuration. */ if (! set && peer->af_group[afi][safi]) @@ -2812,7 +3099,7 @@ peer_ebgp_multihop_set (struct peer *peer, int ttl) struct listnode *node, *nnode; struct peer *peer1; - if (peer->sort == BGP_PEER_IBGP) + if (peer->sort == BGP_PEER_IBGP || peer->conf_if) return 0; /* see comment in peer_ttl_security_hops_set() */ @@ -2960,7 +3247,7 @@ peer_update_source_if_set (struct peer *peer, const char *ifname) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); return 0; } @@ -2992,7 +3279,7 @@ peer_update_source_if_set (struct peer *peer, const char *ifname) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } return 0; } @@ -3016,6 +3303,7 @@ peer_update_source_addr_set (struct peer *peer, union sockunion *su) { XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); peer->update_if = NULL; + } peer->update_source = sockunion_dup (su); @@ -3029,7 +3317,7 @@ peer_update_source_addr_set (struct peer *peer, union sockunion *su) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); return 0; } @@ -3060,7 +3348,7 @@ peer_update_source_addr_set (struct peer *peer, union sockunion *su) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } return 0; } @@ -3111,7 +3399,7 @@ peer_update_source_unset (struct peer *peer) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); return 0; } @@ -3141,7 +3429,7 @@ peer_update_source_unset (struct peer *peer) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } return 0; } @@ -3642,8 +3930,7 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); - + bgp_session_reset(peer); return 0; } @@ -3718,7 +4005,7 @@ peer_local_as_unset (struct peer *peer) BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } return 0; } @@ -3748,7 +4035,7 @@ peer_password_set (struct peer *peer, const char *password) if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED; } @@ -3766,7 +4053,7 @@ peer_password_set (struct peer *peer, const char *password) if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); if (bgp_md5_set (peer) < 0) ret = BGP_ERR_TCPSIG_FAILED; @@ -3794,7 +4081,7 @@ peer_password_unset (struct peer *peer) if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); if (peer->password) XFREE (MTYPE_PEER_PASSWORD, peer->password); @@ -3817,7 +4104,7 @@ peer_password_unset (struct peer *peer) if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); XFREE (MTYPE_PEER_PASSWORD, peer->password); peer->password = NULL; @@ -4250,7 +4537,7 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct) } static void -peer_aslist_update (void) +peer_aslist_update (const char *aslist_name) { afi_t afi; safi_t safi; @@ -4300,8 +4587,42 @@ peer_aslist_update (void) } } } +static void +peer_aslist_add (char *aslist_name) +{ + peer_aslist_update (aslist_name); + route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED); +} + +static void +peer_aslist_del (const char *aslist_name) +{ + peer_aslist_update (aslist_name); + route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_DELETED); +} + /* Set route-map to the peer. */ +static void +peer_reprocess_routes (struct peer *peer, int direct, + afi_t afi, safi_t safi) +{ + if (peer->status != Established) + return; + + if (direct != RMAP_OUT) + { + if (CHECK_FLAG (peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + bgp_soft_reconfig_in (peer, afi, safi); + else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); + } + else + bgp_announce_route(peer, afi, safi); +} + int peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, const char *name) @@ -4325,12 +4646,15 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, if (filter->map[direct].name) free (filter->map[direct].name); - + filter->map[direct].name = strdup (name); filter->map[direct].map = route_map_lookup_by_name (name); if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; + { + peer_reprocess_routes(peer, direct, afi, safi); + return 0; + } group = peer->group; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) @@ -4344,6 +4668,7 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, free (filter->map[direct].name); filter->map[direct].name = strdup (name); filter->map[direct].map = route_map_lookup_by_name (name); + peer_reprocess_routes (peer, direct, afi, safi); } return 0; } @@ -4391,7 +4716,10 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) filter->map[direct].map = NULL; if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; + { + peer_reprocess_routes(peer, direct, afi, safi); + return 0; + } group = peer->group; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) @@ -4405,6 +4733,7 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) free (filter->map[direct].name); filter->map[direct].name = NULL; filter->map[direct].map = NULL; + peer_reprocess_routes(peer, direct, afi, safi); } return 0; } @@ -4433,7 +4762,10 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, filter->usmap.map = route_map_lookup_by_name (name); if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; + { + bgp_announce_route (peer, afi, safi); + return 0; + } group = peer->group; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) @@ -4447,6 +4779,7 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, free (filter->usmap.name); filter->usmap.name = strdup (name); filter->usmap.map = route_map_lookup_by_name (name); + bgp_announce_route (peer, afi, safi); } return 0; } @@ -4473,7 +4806,10 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi) filter->usmap.map = NULL; if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; + { + bgp_announce_route(peer, afi, safi); + return 0; + } group = peer->group; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) @@ -4487,6 +4823,7 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi) free (filter->usmap.name); filter->usmap.name = NULL; filter->usmap.map = NULL; + bgp_announce_route(peer, afi, safi); } return 0; } @@ -4511,24 +4848,33 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi, else UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) + if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { - if (! peer->af_group[afi][safi]) - continue; + group = peer->group; + for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) + { + if (! peer->af_group[afi][safi]) + continue; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - peer->pmax[afi][safi] = max; - peer->pmax_threshold[afi][safi] = threshold; - peer->pmax_restart[afi][safi] = restart; - if (warning) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); + SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); + peer->pmax[afi][safi] = max; + peer->pmax_threshold[afi][safi] = threshold; + peer->pmax_restart[afi][safi] = restart; + if (warning) + SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); + else + UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); + + if ((peer->status == Established) && (peer->afc[afi][safi])) + bgp_maximum_prefix_overflow (peer, afi, safi, 1); + } + } + else + { + if ((peer->status == Established) && (peer->afc[afi][safi])) + bgp_maximum_prefix_overflow (peer, afi, safi, 1); } + return 0; } @@ -4650,7 +4996,11 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops) if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { if (peer->fd >= 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops); + sockopt_minttl (peer->su.sa.sa_family, peer->fd, + MAXTTL + 1 - gtsm_hops); + if (peer->status != Established && peer->doppelganger) + sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, + MAXTTL + 1 - gtsm_hops); } else { @@ -4672,9 +5022,9 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops) } else if (peer->status < Established) { - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Min-ttl changed", peer->host); - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset(peer); } } } @@ -4702,6 +5052,9 @@ peer_ttl_security_hops_unset (struct peer *peer) { if (peer->fd >= 0) sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0); + + if (peer->status != Established && peer->doppelganger) + sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, 0); } else { @@ -4712,14 +5065,24 @@ peer_ttl_security_hops_unset (struct peer *peer) if (peer->fd >= 0) sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0); + + if (peer->status != Established && peer->doppelganger) + sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, 0); } } return peer_ebgp_multihop_unset (opeer); } +/* + * If peer clear is invoked in a loop for all peers on the BGP instance, + * it may end up freeing the doppelganger, and if this was the next node + * to the current node, we would end up accessing the freed next node. + * Pass along additional parameter which can be updated if next node + * is freed; only required when walking the peer list on BGP instance. + */ int -peer_clear (struct peer *peer) +peer_clear (struct peer *peer, struct listnode **nnode) { if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) { @@ -4729,7 +5092,7 @@ peer_clear (struct peer *peer) if (peer->t_pmax_restart) { BGP_TIMER_OFF (peer->t_pmax_restart); - if (BGP_DEBUG (events, EVENTS)) + if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Maximum-prefix restart timer canceled", peer->host); } @@ -4742,7 +5105,7 @@ peer_clear (struct peer *peer) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_RESET); else - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_session_reset_safe(peer, nnode); } return 0; } @@ -4954,7 +5317,11 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp, char buf[SU_ADDRSTRLEN]; char *addr; - addr = peer->host; + if (peer->conf_if) + addr = peer->conf_if; + else + addr = peer->host; + if (peer_group_active (peer)) g_peer = peer->group->conf; @@ -4963,6 +5330,9 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp, ************************************/ if (afi == AFI_IP && safi == SAFI_UNICAST) { + if (peer->conf_if) + vty_out (vty, " neighbor %s interface%s", addr, VTY_NEWLINE); + /* remote-as. */ if (! peer_group_active (peer)) { @@ -5173,11 +5543,27 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp, peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ? " all" : "", VTY_NEWLINE); - /* Remove private AS. */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) - && ! peer->af_group[afi][safi]) - vty_out (vty, " neighbor %s remove-private-AS%s", - addr, VTY_NEWLINE); + /* remove-private-AS */ + if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && !peer->af_group[afi][safi]) + { + if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) && + peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE); + + else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + vty_out (vty, " neighbor %s remove-private-AS replace-AS%s", addr, VTY_NEWLINE); + + else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) + vty_out (vty, " neighbor %s remove-private-AS all%s", addr, VTY_NEWLINE); + + else + vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE); + } + + /* as-override */ + if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE) && + !peer->af_group[afi][safi]) + vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE); /* send-community print. */ if (! peer->af_group[afi][safi]) @@ -5357,7 +5743,7 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi, { if (peer->afc[afi][safi]) { - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) + if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) { bgp_config_write_family_header (vty, afi, safi, &write); bgp_config_write_peer (vty, bgp, peer, afi, safi); @@ -5366,6 +5752,7 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi, } bgp_config_write_maxpaths (vty, bgp, afi, safi, &write); + bgp_config_write_table_map (vty, bgp, afi, safi, &write); if (write) vty_out (vty, " exit-address-family%s", VTY_NEWLINE); @@ -5478,6 +5865,27 @@ bgp_config_write (struct vty *vty) if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE); + /* BGP update-delay. */ + bgp_config_write_update_delay (vty, bgp); + + if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) + { + vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup); + if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT) + vty_out (vty, " %d", bgp->maxmed_onstartup_value); + vty_out (vty, "%s", VTY_NEWLINE); + } + if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) + { + vty_out (vty, " bgp max-med administrative"); + if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT) + vty_out (vty, " %d", bgp->maxmed_admin_value); + vty_out (vty, "%s", VTY_NEWLINE); + } + + /* write quanta */ + bgp_config_write_wpkt_quanta (vty, bgp); + /* BGP graceful-restart. */ if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME) vty_out (vty, " bgp graceful-restart stalepath-time %d%s", @@ -5493,6 +5901,10 @@ bgp_config_write (struct vty *vty) if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) { vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE); } + if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { + vty_out (vty, " bgp route-reflector allow-outbound-policy%s", + VTY_NEWLINE); + } if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)) vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE); if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) @@ -5510,9 +5922,6 @@ bgp_config_write (struct vty *vty) if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) vty_out (vty, " bgp network import-check%s", VTY_NEWLINE); - /* BGP scan interval. */ - bgp_config_write_scan_time (vty); - /* BGP flag dampening. */ if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST], BGP_CONFIG_DAMPENING)) @@ -5530,6 +5939,10 @@ bgp_config_write (struct vty *vty) vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive, bgp->default_holdtime, VTY_NEWLINE); + if (bgp->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER) + vty_out (vty, " bgp route-map delay-timer %d%s", bgp->rmap_update_timer, + VTY_NEWLINE); + /* peer-group */ for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) { @@ -5539,12 +5952,13 @@ bgp_config_write (struct vty *vty) /* Normal neighbor configuration. */ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) + if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST); } /* maximum-paths */ bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write); + bgp_config_write_table_map (vty, bgp, AFI_IP, SAFI_UNICAST, &write); /* Distance configuration. */ bgp_config_write_distance (vty, bgp); @@ -5598,12 +6012,16 @@ bgp_master_init (void) void bgp_init (void) { - /* BGP VTY commands installation. */ - bgp_vty_init (); + + /* allocates some vital data structures used by peer commands in vty_init */ + bgp_scan_init (); /* Init zebra. */ bgp_zebra_init (bm->master); + /* BGP VTY commands installation. */ + bgp_vty_init (); + /* BGP inits. */ bgp_attr_init (); bgp_debug_init (); @@ -5611,7 +6029,7 @@ bgp_init (void) bgp_route_init (); bgp_route_map_init (); bgp_address_init (); - bgp_scan_init (); + bgp_scan_vty_init(); bgp_mplsvpn_init (); bgp_encap_init (); @@ -5622,8 +6040,8 @@ bgp_init (void) /* Filter list initialize. */ bgp_filter_init (); - as_list_add_hook (peer_aslist_update); - as_list_delete_hook (peer_aslist_update); + as_list_add_hook (peer_aslist_add); + as_list_delete_hook (peer_aslist_del); /* Prefix list initialize.*/ prefix_list_init (); @@ -5646,12 +6064,25 @@ bgp_terminate (void) struct listnode *node, *nnode; struct listnode *mnode, *mnnode; + /* Close the listener sockets first as this prevents peers from attempting + * to reconnect on receiving the peer unconfig message. In the presence + * of a large number of peers this will ensure that no peer is left with + * a dangling connection + */ + /* reverse bgp_master_init */ + bgp_close(); + if (bm->listen_sockets) + list_free(bm->listen_sockets); + bm->listen_sockets = NULL; + for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->status == Established) + if (peer->status == Established || + peer->status == OpenSent || + peer->status == OpenConfirm) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_PEER_UNCONFIG); - + bgp_cleanup_routes (); if (bm->process_main_queue) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 7665d9d0..25838edb 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -23,6 +23,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA /* For union sockunion. */ #include "sockunion.h" +#include "routemap.h" /* Typedef BGP specific types. */ typedef u_int32_t as_t; @@ -62,6 +63,13 @@ struct bgp_master #define BGP_OPT_NO_LISTEN (1 << 3) }; +/* BGP route-map structure. */ +struct bgp_rmap +{ + char *name; + struct route_map *map; +}; + /* BGP instance structure. */ struct bgp { @@ -104,10 +112,45 @@ struct bgp as_t *confed_peers; int confed_peers_cnt; - struct thread *t_startup; + struct thread *t_startup; /* start-up timer on only once at the beginning */ + + u_int32_t v_maxmed_onstartup; /* Duration of max-med on start-up */ +#define BGP_MAXMED_ONSTARTUP_UNCONFIGURED 0 /* 0 means off, its the default */ + u_int32_t maxmed_onstartup_value; /* Max-med value when active on start-up */ + struct thread *t_maxmed_onstartup; /* non-null when max-med onstartup is on */ + u_char maxmed_onstartup_over; /* Flag to make it effective only once */ + + u_char v_maxmed_admin; /* 1/0 if max-med administrative is on/off */ +#define BGP_MAXMED_ADMIN_UNCONFIGURED 0 /* Off by default */ + u_int32_t maxmed_admin_value; /* Max-med value when administrative in on */ +#define BGP_MAXMED_VALUE_DEFAULT 4294967294 /* Maximum by default */ + + u_char maxmed_active; /* 1/0 if max-med is active or not */ + u_int32_t maxmed_value; /* Max-med value when its active */ + + /* BGP update delay on startup */ + struct thread *t_update_delay; + struct thread *t_establish_wait; + u_char update_delay_over; + u_char main_zebra_update_hold; + u_char main_peers_update_hold; + u_char rsclient_peers_update_hold; + u_int16_t v_update_delay; + u_int16_t v_establish_wait; + char update_delay_begin_time[64]; + char update_delay_end_time[64]; + char update_delay_zebra_resume_time[64]; + char update_delay_peers_resume_time[64]; + u_int32_t established; + u_int32_t restarted_peers; + u_int32_t implicit_eors; + u_int32_t explicit_eors; +#define BGP_UPDATE_DELAY_DEF 0 +#define BGP_UPDATE_DELAY_MIN 0 +#define BGP_UPDATE_DELAY_MAX 3600 /* BGP flags. */ - u_int16_t flags; + u_int32_t flags; #define BGP_FLAG_ALWAYS_COMPARE_MED (1 << 0) #define BGP_FLAG_DETERMINISTIC_MED (1 << 1) #define BGP_FLAG_MED_MISSING_AS_WORST (1 << 2) @@ -124,6 +167,7 @@ struct bgp #define BGP_FLAG_ASPATH_CONFED (1 << 13) #define BGP_FLAG_ASPATH_MULTIPATH_RELAX (1 << 14) #define BGP_FLAG_DELETING (1 << 15) +#define BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY (1 << 16) /* BGP Per AF flags */ u_int16_t af_flags[AFI_MAX][SAFI_MAX]; @@ -138,6 +182,9 @@ struct bgp /* BGP routing information base. */ struct bgp_table *rib[AFI_MAX][SAFI_MAX]; + /* BGP table route-map. */ + struct bgp_rmap table_map[AFI_MAX][SAFI_MAX]; + /* BGP redistribute configuration. */ u_char redist[AFI_MAX][ZEBRA_ROUTE_MAX]; @@ -146,11 +193,12 @@ struct bgp u_int32_t redist_metric[AFI_MAX][ZEBRA_ROUTE_MAX]; /* BGP redistribute route-map. */ - struct - { - char *name; - struct route_map *map; - } rmap[AFI_MAX][ZEBRA_ROUTE_MAX]; + struct bgp_rmap rmap[AFI_MAX][ZEBRA_ROUTE_MAX]; + + /* timer to dampen route map changes */ + struct thread *t_rmap_update; /* Handle route map updates */ + u_int32_t rmap_update_timer; /* Route map update timer */ +#define RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */ /* BGP distance configuration. */ u_char distance_ebgp; @@ -172,9 +220,18 @@ struct bgp struct bgp_maxpaths_cfg { u_int16_t maxpaths_ebgp; u_int16_t maxpaths_ibgp; + u_int16_t ibgp_flags; +#define BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN (1 << 0) } maxpaths[AFI_MAX][SAFI_MAX]; + + u_int32_t wpkt_quanta; /* per peer packet quanta to write */ + u_int32_t adv_quanta; /* adv FIFO size that triggers write */ + u_int32_t wd_quanta; /* withdraw FIFO size that triggers write */ }; +#define BGP_ROUTE_ADV_HOLD(bgp) \ + (bgp->main_peers_update_hold || bgp->rsclient_peers_update_hold) + /* BGP peer-group support. */ struct peer_group { @@ -272,6 +329,12 @@ typedef enum BGP_PEER_CONFED, } bgp_peer_sort_t; +/* BGP message header and packet size. */ +#define BGP_MARKER_SIZE 16 +#define BGP_HEADER_SIZE 19 +#define BGP_MAX_PACKET_SIZE 4096 +#define BGP_MAX_PACKET_SIZE_OVERFLOW 1024 + /* BGP neighbor structure. */ struct peer { @@ -320,6 +383,9 @@ struct peer */ struct stream *scratch; + /* the doppelganger peer structure, due to dual TCP conn setup */ + struct peer *doppelganger; + /* Status of the peer. */ int status; int ostatus; @@ -336,15 +402,16 @@ struct peer unsigned short port; /* Destination port for peer */ char *host; /* Printable address of the peer. */ union sockunion su; /* Sockunion address of the peer. */ +#define BGP_PEER_SU_UNSPEC(peer) (peer->su.sa.sa_family == AF_UNSPEC) time_t uptime; /* Last Up/Down time */ time_t readtime; /* Last read time */ time_t resettime; /* Last reset time */ ifindex_t ifindex; /* ifindex of the BGP connection. */ + char *conf_if; /* neighbor interface config name. */ char *ifname; /* bind interface name. */ char *update_if; union sockunion *update_source; - struct zlog *log; union sockunion *su_local; /* Sockunion of local address. */ union sockunion *su_remote; /* Sockunion of remote address. */ @@ -393,6 +460,8 @@ struct peer #define PEER_FLAG_DISABLE_CONNECTED_CHECK (1 << 6) /* disable-connected-check */ #define PEER_FLAG_LOCAL_AS_NO_PREPEND (1 << 7) /* local-as no-prepend */ #define PEER_FLAG_LOCAL_AS_REPLACE_AS (1 << 8) /* local-as no-prepend replace-as */ +#define PEER_FLAG_DELETE (1 << 9) /* mark the peer for deleting */ +#define PEER_FLAG_CONFIG_NODE (1 << 10) /* the node to update configs on */ /* NSF mode (graceful restart) */ u_char nsf[AFI_MAX][SAFI_MAX]; @@ -417,6 +486,9 @@ struct peer #define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */ #define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1 << 16) /* leave link-local nexthop unchanged */ #define PEER_FLAG_NEXTHOP_SELF_ALL (1 << 17) /* next-hop-self all */ +#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL (1 << 18) /* remove-private-as all */ +#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1 << 19) /* remove-private-as replace-as */ +#define PEER_FLAG_AS_OVERRIDE (1 << 20) /* as-override */ /* MD5 password */ char *password; @@ -481,6 +553,8 @@ struct peer struct thread *t_gr_restart; struct thread *t_gr_stale; + int radv_adjusted; /* flag if MRAI has been adjusted or not */ + /* workqueues */ struct work_queue *clear_node_queue; @@ -503,9 +577,13 @@ struct peer u_int32_t established; /* Established */ u_int32_t dropped; /* Dropped */ + /* Update delay related fields */ + u_char update_delay_over; /* When this is set, BGP is no more waiting for EOR */ + /* Syncronization list and time. */ struct bgp_synchronize *sync[AFI_MAX][SAFI_MAX]; time_t synctime; + time_t last_write; /* timestamp when the last UPDATE msg was written */ /* Send prefix count. */ unsigned long scount[AFI_MAX][SAFI_MAX]; @@ -525,6 +603,12 @@ struct peer /* ORF Prefix-list */ struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX]; + /* Text description of last attribute rcvd */ + char rcvd_attr_str[BUFSIZ]; + + /* Track if we printed the attribute in debugs */ + int rcvd_attr_printed; + /* Prefix count. */ unsigned long pcount[AFI_MAX][SAFI_MAX]; @@ -561,6 +645,8 @@ struct peer #define PEER_DOWN_PASSIVE_CHANGE 20 /* neighbor passive command */ #define PEER_DOWN_MULTIHOP_CHANGE 21 /* neighbor multihop command */ #define PEER_DOWN_NSF_CLOSE_SESSION 22 /* NSF tcp session close */ +unsigned long last_reset_cause_size; +u_char last_reset_cause[BGP_MAX_PACKET_SIZE]; /* The kind of route-map Flags.*/ u_char rmap_type; @@ -600,11 +686,6 @@ struct bgp_nlri /* Default BGP port number. */ #define BGP_PORT_DEFAULT 179 -/* BGP message header and packet size. */ -#define BGP_MARKER_SIZE 16 -#define BGP_HEADER_SIZE 19 -#define BGP_MAX_PACKET_SIZE 4096 - /* BGP minimum message size. */ #define BGP_MSG_OPEN_MIN_SIZE (BGP_HEADER_SIZE + 10) #define BGP_MSG_UPDATE_MIN_SIZE (BGP_HEADER_SIZE + 4) @@ -742,7 +823,7 @@ struct bgp_nlri #define BGP_EVENTS_MAX 15 /* BGP timers default value. */ -#define BGP_INIT_START_TIMER 5 +#define BGP_INIT_START_TIMER 1 #define BGP_DEFAULT_HOLDTIME 180 #define BGP_DEFAULT_KEEPALIVE 60 #define BGP_DEFAULT_EBGP_ROUTEADV 30 @@ -826,8 +907,10 @@ enum bgp_clear_type #define BGP_ERR_TCPSIG_FAILED -29 #define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -30 #define BGP_ERR_NO_IBGP_WITH_TTLHACK -31 -#define BGP_ERR_MAX -32 +#define BGP_ERR_NO_INTERFACE_CONFIG -32 #define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -33 +#define BGP_ERR_AS_OVERRIDE -34 +#define BGP_ERR_MAX -35 extern struct bgp_master *bm; @@ -842,6 +925,10 @@ extern struct bgp *bgp_get_default (void); extern struct bgp *bgp_lookup (as_t, const char *); extern struct bgp *bgp_lookup_by_name (const char *); extern struct peer *peer_lookup (struct bgp *, union sockunion *); +extern struct peer *peer_lookup_by_conf_if (struct bgp *, const char *); +extern struct peer *peer_conf_interface_get(struct bgp *, const char *, afi_t, + safi_t); +extern void bgp_peer_conf_if_to_su_update (struct peer *); extern struct peer_group *peer_group_lookup (struct bgp *, const char *); extern struct peer_group *peer_group_get (struct bgp *, const char *); extern struct peer *peer_lookup_with_open (union sockunion *, as_t, struct in_addr *, @@ -860,7 +947,10 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *); extern bgp_peer_sort_t peer_sort (struct peer *peer); extern int peer_active (struct peer *); extern int peer_active_nego (struct peer *); +extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, + as_t, as_t, afi_t, safi_t); extern struct peer *peer_create_accept (struct bgp *); +extern void peer_xfer_config (struct peer *dst, struct peer *src); extern char *peer_uptime (time_t, char *, size_t); extern int bgp_config_write (struct vty *); extern void bgp_config_write_family_header (struct vty *, afi_t, safi_t, int *); @@ -902,9 +992,12 @@ extern int bgp_timers_unset (struct bgp *); extern int bgp_default_local_preference_set (struct bgp *, u_int32_t); extern int bgp_default_local_preference_unset (struct bgp *); +extern int bgp_update_delay_active (struct bgp *); +extern int bgp_update_delay_configured (struct bgp *); extern int peer_rsclient_active (struct peer *); - -extern int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t); +extern void peer_as_change (struct peer *, as_t); +extern int peer_remote_as (struct bgp *, union sockunion *,const char *, as_t *, + afi_t, safi_t); extern int peer_group_remote_as (struct bgp *, const char *, as_t *); extern int peer_delete (struct peer *peer); extern int peer_group_delete (struct peer_group *); @@ -913,8 +1006,8 @@ extern int peer_group_remote_as_delete (struct peer_group *); extern int peer_activate (struct peer *, afi_t, safi_t); extern int peer_deactivate (struct peer *, afi_t, safi_t); -extern int peer_group_bind (struct bgp *, union sockunion *, struct peer_group *, - afi_t, safi_t, as_t *); +extern int peer_group_bind (struct bgp *, union sockunion *, struct peer *, + struct peer_group *, afi_t, safi_t, as_t *); extern int peer_group_unbind (struct bgp *, struct peer *, struct peer_group *, afi_t, safi_t); @@ -984,10 +1077,16 @@ extern int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t); extern int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int, u_int16_t); extern int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t); -extern int peer_clear (struct peer *); +extern int peer_clear (struct peer *, struct listnode **); extern int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type); extern int peer_ttl_security_hops_set (struct peer *, int); extern int peer_ttl_security_hops_unset (struct peer *); +extern int bgp_route_map_update_timer (struct thread *thread); +extern void bgp_route_map_terminate(void); + +extern void bgp_scan_finish (void); + +extern int peer_cmp (struct peer *p1, struct peer *p2); #endif /* _QUAGGA_BGPD_H */ |