From b2b83ff67a91d24e7cd9871663f341b14c0834a2 Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 29 Oct 2015 09:34:47 -0700 Subject: [PATCH 1/5] BGP: Display the interface name used to resolve a nexthop. Display the interface name used to resolve a nexthop instead of just the ifIdx. This is already done for many cases, but was missing for one scenario. Signed-off-by: Vivek Venkataraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-6888 Reviewed By: CCR-3705 Testing Done: Manual verification This is an import of patch bgpd-show-ifname-for-nht.patch from 2.5-br. --- bgpd/bgp_nexthop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index ed7512cad2..4b3d14af58 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -477,7 +477,8 @@ show_ip_bgp_nexthop_table (struct vty *vty, int detail) VTY_NEWLINE); break; case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " ifidx %u%s", nexthop->ifindex, + vty_out (vty, " if %s%s", + ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); break; default: From 20eb8864bbaf19771502b6c1ed3f1e43186f97eb Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 29 Oct 2015 09:41:23 -0700 Subject: [PATCH 2/5] BGP: Check for duplicate and overlapping listen ranges When configuring listen ranges for allowing dynamic BGP neighbors, ensure that there are no duplicate or overlapping ones. This is necessary because at the time of handling an incoming connection, the first range that matches the source of the connection (and hence, its peer-group parameters) will be used. Signed-off-by: Vivek Venkataraman Reviewed-by: Donald Sharp Reviewed-by: Atul Patel Ticket: CM-5153 Reviewed By: CCR-3714 Testing Done: Manual verification --- bgpd/bgp_vty.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 38f3eb971e..bbacc22492 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -57,6 +57,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA extern struct in_addr router_id_zebra; +static struct peer_group * +listen_range_exists (struct bgp *bgp, struct prefix *range, int exact); + /* Utility function to get address family from current node. */ afi_t bgp_node_afi (struct vty *vty) @@ -2347,6 +2350,38 @@ DEFUN (no_bgp_listen_limit, } +/* + * Check if this listen range is already configured. Check for exact + * match or overlap based on input. + */ +static struct peer_group * +listen_range_exists (struct bgp *bgp, struct prefix *range, int exact) +{ + struct listnode *node, *nnode; + struct listnode *node1, *nnode1; + struct peer_group *group; + struct prefix *lr; + afi_t afi; + int match; + + afi = family2afi(range->family); + for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) + { + for (ALL_LIST_ELEMENTS (group->listen_range[afi], node1, + nnode1, lr)) + { + if (exact) + match = prefix_same (range, lr); + else + match = (prefix_match (range, lr) || prefix_match (lr, range)); + if (match) + return group; + } + } + + return NULL; +} + DEFUN (bgp_listen_range, bgp_listen_range_cmd, LISTEN_RANGE_CMD "peer-group WORD" , @@ -2357,7 +2392,7 @@ DEFUN (bgp_listen_range, { struct bgp *bgp; struct prefix range; - struct peer_group *group; + struct peer_group *group, *existing_group; afi_t afi; int ret; @@ -2386,6 +2421,27 @@ DEFUN (bgp_listen_range, apply_mask (&range); + /* Check if same listen range is already configured. */ + existing_group = listen_range_exists (bgp, &range, 1); + if (existing_group) + { + if (strcmp (existing_group->name, argv[1]) == 0) + return CMD_SUCCESS; + else + { + vty_out (vty, "%% Same listen range is attached to peer-group %s%s", + existing_group->name, VTY_NEWLINE); + return CMD_WARNING; + } + } + + /* Check if an overlapping listen range exists. */ + if (listen_range_exists (bgp, &range, 0)) + { + vty_out (vty, "%% Listen range overlaps with existing listen range%s", + VTY_NEWLINE); + return CMD_WARNING; + } group = peer_group_lookup (bgp, argv[1]); if (! group) From d289687f8b341363597c2f20276181341b4872c4 Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 29 Oct 2015 10:30:45 -0700 Subject: [PATCH 3/5] BGP: Do appropriate cleanup on receipt of redistribute update When there is a change to a redistributed route, either an attribute such as the metric or the route type itself has changed, protocol clients receive an update of the route instead of a delete and add as a result of an earlier optimization. The update needs to be handled as an implicit delete for any existing redistributed route, especially to handle change in route type. Signed-off-by: Vivek Venkataraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-7578 Reviewed By: CCR-3718 Testing Done: Manual verification Related-to: CM-6768 --- bgpd/bgp_zebra.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index c7b0b4364e..052c2efacb 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -438,6 +438,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) struct in_addr nexthop; struct prefix_ipv4 p; unsigned int ifindex; + int i; s = zclient->ibuf; nexthop.s_addr = 0; @@ -497,6 +498,20 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) api.metric, api.tag); } + + /* + * The ADD message is actually an UPDATE and there is no explicit DEL + * for a prior redistributed route, if any. So, perform an implicit + * DEL processing for the same redistributed route from any other + * source type. + */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + { + if (i != api.type) + bgp_redistribute_delete((struct prefix *)&p, i, api.instance); + } + + /* Now perform the add/update. */ bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex, api.metric, api.type, api.instance, api.tag); } @@ -530,6 +545,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) struct in6_addr nexthop; struct prefix_ipv6 p; unsigned int ifindex; + int i; s = zclient->ibuf; memset (&nexthop, 0, sizeof (struct in6_addr)); @@ -595,6 +611,19 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) api.metric, api.tag); } + + /* + * The ADD message is actually an UPDATE and there is no explicit DEL + * for a prior redistributed route, if any. So, perform an implicit + * DEL processing for the same redistributed route from any other + * source type. + */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + { + if (i != api.type) + bgp_redistribute_delete((struct prefix *)&p, i, api.instance); + } + bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex, api.metric, api.type, api.instance, api.tag); } From 70737f3064ffee4ec4cf4b7d7813b9793ebbf973 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 21 Oct 2015 17:40:39 -0700 Subject: [PATCH 4/5] Debian: Track dependencies so that rebuilds can work right Not the debian way, I know. But cause the debian build to create and follow dependencies. Signed-off-by: Donald Sharp --- debian/rules | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 6360a6c2ce..4642dbfeb3 100755 --- a/debian/rules +++ b/debian/rules @@ -65,7 +65,8 @@ override_dh_auto_configure: --enable-rtadv \ --enable-werror \ --enable-gcc-rdynamic \ - --with-libpam; \ + --with-libpam \ + --enable-dependency-tracking; \ fi if ! diff -b -IHAVE_SNMP -IHAVE_NETSNMP -IUCD_COMPAT -IGETIFADDR debian/my/config.h.reference config.h; then \ echo; \ From 400b1fad1d79b59c3f2866caaee42a80d4fa39e6 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 29 Oct 2015 20:33:30 +0000 Subject: [PATCH 5/5] Deactivate BGP peer via "no neighbor x.x.x.x activate" removes other config Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-6281 --- bgpd/bgp_vty.c | 3 - bgpd/bgpd.c | 362 +++++++++++++++++++++++++++++++------------------ bgpd/bgpd.h | 43 +++--- 3 files changed, 252 insertions(+), 156 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bbacc22492..17b3b2fdbc 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -210,9 +210,6 @@ bgp_vty_return (struct vty *vty, int ret) case BGP_ERR_INVALID_FLAG: str = "Invalid flag"; break; - case BGP_ERR_PEER_INACTIVE: - str = "Activate the neighbor for the address family first"; - break; case BGP_ERR_PEER_GROUP_SHUTDOWN: str = "Peer-group has been shutdown. Activate the peer-group first"; break; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index bb6e4bddc0..2d831acdd2 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1723,7 +1723,7 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi) /* De-activate the address family configuration. */ peer->afc[afi][safi] = 0; - peer_af_flag_reset (peer, afi, safi); + if (peer_af_delete(peer, afi, safi) != 0) { zlog_err("couldn't delete af structure for peer %s", peer->host); @@ -3689,16 +3689,12 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, if (! found) return BGP_ERR_INVALID_FLAG; - /* Adress family must be activated. */ - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - - /* Spcecial check for reflector client. */ + /* Special check for reflector client. */ if (flag & PEER_FLAG_REFLECTOR_CLIENT && peer_sort (peer) != BGP_PEER_IBGP) return BGP_ERR_NOT_INTERNAL_PEER; - /* Spcecial check for remove-private-AS. */ + /* Special check for remove-private-AS. */ if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && peer_sort (peer) == BGP_PEER_IBGP) return BGP_ERR_REMOVE_PRIVATE_AS; @@ -4168,10 +4164,6 @@ peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi, struct peer_group *group; struct listnode *node, *nnode; - /* Adress family must be activated. */ - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) || (rmap && ! peer->default_rmap[afi][safi].name) || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0)) @@ -4226,10 +4218,6 @@ peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; - /* Adress family must be activated. */ - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) { UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); @@ -4871,9 +4859,6 @@ peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -4921,9 +4906,6 @@ peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5042,9 +5024,6 @@ peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5091,9 +5070,6 @@ peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5215,9 +5191,6 @@ peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5261,9 +5234,6 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5395,9 +5365,6 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != RMAP_IN && direct != RMAP_OUT && direct != RMAP_IMPORT && direct != RMAP_EXPORT) return BGP_ERR_INVALID_VALUE; @@ -5444,9 +5411,6 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != RMAP_IN && direct != RMAP_OUT && direct != RMAP_IMPORT && direct != RMAP_EXPORT) return BGP_ERR_INVALID_VALUE; @@ -5509,9 +5473,6 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - filter = &peer->filter[afi][safi]; if (filter->usmap.name) @@ -5551,9 +5512,6 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - filter = &peer->filter[afi][safi]; if (filter->usmap.name) @@ -5592,9 +5550,6 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); peer->pmax[afi][safi] = max; peer->pmax_threshold[afi][safi] = threshold; @@ -5640,9 +5595,6 @@ peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - /* apply peer-group config */ if (peer->af_group[afi][safi]) { @@ -6077,9 +6029,35 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object return buf; } +static void +afi_header_vty_out (struct vty *vty, afi_t afi, safi_t safi, + int *write, const char *format, ...) +{ + va_list args; + int len = 0; + char buf[1024]; + + bgp_config_write_family_header (vty, afi, safi, write); + + if (vty_shell (vty)) + { + va_start (args, format); + vprintf (format, args); + va_end (args); + } + else + { + va_start (args, format); + len = vsnprintf (buf, sizeof(buf), format, args); + va_end (args); + + buffer_put (vty->obuf, (u_char *) buf, len); + } +} + static void bgp_config_write_filter (struct vty *vty, struct peer *peer, - afi_t afi, safi_t safi) + afi_t afi, safi_t safi, int *write) { struct bgp_filter *filter; struct bgp_filter *gfilter = NULL; @@ -6096,55 +6074,93 @@ bgp_config_write_filter (struct vty *vty, struct peer *peer, if (filter->dlist[in].name) if (! gfilter || ! gfilter->dlist[in].name || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0) - vty_out (vty, " neighbor %s distribute-list %s in%s", addr, - filter->dlist[in].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s distribute-list %s in%s", + addr, filter->dlist[in].name, VTY_NEWLINE); + } + if (filter->dlist[out].name && ! gfilter) - vty_out (vty, " neighbor %s distribute-list %s out%s", addr, - filter->dlist[out].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s distribute-list %s out%s", + addr, filter->dlist[out].name, VTY_NEWLINE); + } /* prefix-list. */ if (filter->plist[in].name) if (! gfilter || ! gfilter->plist[in].name || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0) - vty_out (vty, " neighbor %s prefix-list %s in%s", addr, - filter->plist[in].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s prefix-list %s in%s", + addr, filter->plist[in].name, VTY_NEWLINE); + } + if (filter->plist[out].name && ! gfilter) - vty_out (vty, " neighbor %s prefix-list %s out%s", addr, - filter->plist[out].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s prefix-list %s out%s", + addr, filter->plist[out].name, VTY_NEWLINE); + } /* route-map. */ if (filter->map[RMAP_IN].name) if (! gfilter || ! gfilter->map[RMAP_IN].name || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0) - vty_out (vty, " neighbor %s route-map %s in%s", addr, - filter->map[RMAP_IN].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-map %s in%s", + addr, filter->map[RMAP_IN].name, VTY_NEWLINE); + } + if (filter->map[RMAP_OUT].name && ! gfilter) - vty_out (vty, " neighbor %s route-map %s out%s", addr, - filter->map[RMAP_OUT].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-map %s out%s", + addr, filter->map[RMAP_OUT].name, VTY_NEWLINE); + } + if (filter->map[RMAP_IMPORT].name && ! gfilter) - vty_out (vty, " neighbor %s route-map %s import%s", addr, - filter->map[RMAP_IMPORT].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-map %s import%s", + addr, filter->map[RMAP_IMPORT].name, VTY_NEWLINE); + } + if (filter->map[RMAP_EXPORT].name) if (! gfilter || ! gfilter->map[RMAP_EXPORT].name - || strcmp (filter->map[RMAP_EXPORT].name, - gfilter->map[RMAP_EXPORT].name) != 0) - vty_out (vty, " neighbor %s route-map %s export%s", addr, - filter->map[RMAP_EXPORT].name, VTY_NEWLINE); + || strcmp (filter->map[RMAP_EXPORT].name, gfilter->map[RMAP_EXPORT].name) != 0) + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-map %s export%s", + addr, filter->map[RMAP_EXPORT].name, VTY_NEWLINE); + } /* unsuppress-map */ if (filter->usmap.name && ! gfilter) - vty_out (vty, " neighbor %s unsuppress-map %s%s", addr, - filter->usmap.name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s unsuppress-map %s%s", + addr, filter->usmap.name, VTY_NEWLINE); + } /* filter-list. */ if (filter->aslist[in].name) if (! gfilter || ! gfilter->aslist[in].name || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0) - vty_out (vty, " neighbor %s filter-list %s in%s", addr, - filter->aslist[in].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s filter-list %s in%s", + addr, filter->aslist[in].name, VTY_NEWLINE); + } + if (filter->aslist[out].name && ! gfilter) - vty_out (vty, " neighbor %s filter-list %s out%s", addr, - filter->aslist[out].name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s filter-list %s out%s", + addr, filter->aslist[out].name, VTY_NEWLINE); + } } /* BGP peer configuration display function. */ @@ -6382,6 +6398,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, } if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) && + peer->connect != BGP_DEFAULT_CONNECT_RETRY && ! peer_group_active (peer)) { vty_out (vty, " neighbor %s timers connect %d%s", addr, @@ -6454,11 +6471,11 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, } } - /* BGP peer configuration display function. */ static void bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, - struct peer *peer, afi_t afi, safi_t safi) + struct peer *peer, afi_t afi, safi_t safi, + int *write) { struct peer *g_peer = NULL; char *addr; @@ -6479,16 +6496,26 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, ****** Per AF to the neighbor ****** ************************************/ if (peer->af_group[afi][safi]) - vty_out (vty, " neighbor %s peer-group %s%s", addr, - peer->group->name, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s peer-group %s%s", addr, + peer->group->name, VTY_NEWLINE); + } else - vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE); + if (peer->afc[afi][safi]) + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s activate%s", + addr, VTY_NEWLINE); + } /* ORF capability. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) || peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) { - vty_out (vty, " neighbor %s capability orf prefix-list", addr); + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s capability orf prefix-list", + addr); if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) @@ -6502,44 +6529,87 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, /* Route reflector client. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) - vty_out (vty, " neighbor %s route-reflector-client%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-reflector-client%s", + addr, VTY_NEWLINE); + } /* next-hop-self force */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF)) - vty_out (vty, " neighbor %s next-hop-self force%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s next-hop-self force%s", + addr, VTY_NEWLINE); + } /* next-hop-self */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) - vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s next-hop-self%s", + addr, VTY_NEWLINE); + } /* remove-private-AS */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) - vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s remove-private-AS all replace-AS%s", + addr, VTY_NEWLINE); + } else if (peergroup_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); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s remove-private-AS replace-AS%s", + addr, VTY_NEWLINE); + } else if (peergroup_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); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s remove-private-AS all%s", + addr, VTY_NEWLINE); + } else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)) - vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s remove-private-AS%s", + addr, VTY_NEWLINE); + } /* as-override */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) - vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s as-override%s", + addr, VTY_NEWLINE); + } /* send-community print. */ if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) { if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s send-community both%s", + addr, VTY_NEWLINE); + } else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, " neighbor %s send-community extended%s", - addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s send-community extended%s", + addr, VTY_NEWLINE); + } else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) - vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s send-community%s", + addr, VTY_NEWLINE); + } } else { @@ -6547,13 +6617,25 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, " no neighbor %s send-community both%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " no neighbor %s send-community both%s", + addr, VTY_NEWLINE); + } else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, " no neighbor %s send-community extended%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " no neighbor %s send-community extended%s", + addr, VTY_NEWLINE); + } else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) - vty_out (vty, " no neighbor %s send-community%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " no neighbor %s send-community%s", + addr, VTY_NEWLINE); + } } /* Default information */ @@ -6564,7 +6646,8 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, (peer->default_rmap[afi][safi].name && strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name))))) { - vty_out (vty, " neighbor %s default-originate", addr); + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s default-originate", addr); if (peer->default_rmap[afi][safi].name) vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name); vty_out (vty, "%s", VTY_NEWLINE); @@ -6572,8 +6655,11 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, /* Soft reconfiguration inbound. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) - vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr, - VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s soft-reconfiguration inbound%s", + addr, VTY_NEWLINE); + } /* maximum-prefix. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) @@ -6583,7 +6669,9 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING) != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) { - vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]); + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s maximum-prefix %ld", + addr, peer->pmax[afi][safi]); if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT) vty_out (vty, " %d", peer->pmax_threshold[afi][safi]); if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) @@ -6595,11 +6683,19 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, /* Route server client. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT)) - vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-server-client%s", + addr, VTY_NEWLINE); + } /* Nexthop-local unchanged. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) - vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s nexthop-local unchanged%s", + addr, VTY_NEWLINE); + } /* Allow AS in. */ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) @@ -6608,14 +6704,21 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) { if (peer->allowas_in[afi][safi] == 3) - vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE); - else - vty_out (vty, " neighbor %s allowas-in %d%s", addr, - peer->allowas_in[afi][safi], VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s allowas-in%s", + addr, VTY_NEWLINE); + } + else + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s allowas-in %d%s", + addr, peer->allowas_in[afi][safi], VTY_NEWLINE); + } } /* Filter. */ - bgp_config_write_filter (vty, peer, afi, safi); + bgp_config_write_filter (vty, peer, afi, safi, write); /* atribute-unchanged. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) @@ -6625,15 +6728,22 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) - vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s attribute-unchanged%s", + addr, VTY_NEWLINE); + } else - vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr, - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ? - " as-path" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ? - " next-hop" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ? - " med" : "", VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s attribute-unchanged%s%s%s%s", addr, + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ? + " as-path" : "", + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ? + " next-hop" : "", + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ? + " med" : "", VTY_NEWLINE); + } } } @@ -6684,27 +6794,17 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi, bgp_config_write_redistribute (vty, bgp, afi, safi, &write); for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - if (group->conf->afc[afi][safi]) - { - bgp_config_write_family_header (vty, afi, safi, &write); - bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi); - } - } + bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write); + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { /* Skip dynamic neighbors. */ if (peer_dynamic_neighbor (peer)) continue; - if (peer->afc[afi][safi]) - { - if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - { - bgp_config_write_family_header (vty, afi, safi, &write); - bgp_config_write_peer_af (vty, bgp, peer, afi, safi); - } - } + /* Do not display doppelganger peers */ + if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write); } bgp_config_write_maxpaths (vty, bgp, afi, safi, &write); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index fc58f4fcc3..41bc5ea81c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1069,28 +1069,27 @@ enum bgp_clear_type #define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT -13 #define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET -14 #define BGP_ERR_AS_MISMATCH -15 -#define BGP_ERR_PEER_INACTIVE -16 -#define BGP_ERR_PEER_FLAG_CONFLICT -17 -#define BGP_ERR_PEER_GROUP_SHUTDOWN -18 -#define BGP_ERR_PEER_FILTER_CONFLICT -19 -#define BGP_ERR_NOT_INTERNAL_PEER -20 -#define BGP_ERR_REMOVE_PRIVATE_AS -21 -#define BGP_ERR_AF_UNCONFIGURED -22 -#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -23 -#define BGP_ERR_INSTANCE_MISMATCH -24 -#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -25 -#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -26 -#define BGP_ERR_TCPSIG_FAILED -27 -#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -28 -#define BGP_ERR_NO_IBGP_WITH_TTLHACK -29 -#define BGP_ERR_NO_INTERFACE_CONFIG -30 -#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -31 -#define BGP_ERR_AS_OVERRIDE -32 -#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -33 -#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -34 -#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -35 -#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -36 -#define BGP_ERR_MAX -37 +#define BGP_ERR_PEER_FLAG_CONFLICT -16 +#define BGP_ERR_PEER_GROUP_SHUTDOWN -17 +#define BGP_ERR_PEER_FILTER_CONFLICT -18 +#define BGP_ERR_NOT_INTERNAL_PEER -19 +#define BGP_ERR_REMOVE_PRIVATE_AS -20 +#define BGP_ERR_AF_UNCONFIGURED -21 +#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -22 +#define BGP_ERR_INSTANCE_MISMATCH -23 +#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -24 +#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -25 +#define BGP_ERR_TCPSIG_FAILED -26 +#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -27 +#define BGP_ERR_NO_IBGP_WITH_TTLHACK -28 +#define BGP_ERR_NO_INTERFACE_CONFIG -29 +#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -30 +#define BGP_ERR_AS_OVERRIDE -31 +#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -32 +#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -33 +#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -34 +#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -35 +#define BGP_ERR_MAX -36 /* * Enumeration of different policy kinds a peer can be configured with.