mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 02:43:41 +00:00
bgpd: improve peer-group remote-as definitions
Problem reported that with certain sequences of defining the remote-as on the peer-group and the members, the configuration would become wrong, with configured remote-as settings not reflected in the config but peers unable to come up. This fix resolves these inconsistencies. Ticket: CM-19560 Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
parent
313731ac92
commit
faa16034cb
@ -2846,13 +2846,11 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
|
|||||||
switch (ret) {
|
switch (ret) {
|
||||||
case BGP_ERR_PEER_GROUP_MEMBER:
|
case BGP_ERR_PEER_GROUP_MEMBER:
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%% Peer-group AS %u. Cannot configure remote-as for member\n",
|
"%% Peer-group member cannot override remote-as of peer-group\n");
|
||||||
as);
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
|
case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%% The AS# can not be changed from %u to %s, peer-group members must be all internal or all external\n",
|
"%% Peer-group members must be all internal or all external\n");
|
||||||
as, as_str);
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
return bgp_vty_return(vty, ret);
|
return bgp_vty_return(vty, ret);
|
||||||
@ -9212,8 +9210,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
|
|||||||
? " replace-as"
|
? " replace-as"
|
||||||
: "");
|
: "");
|
||||||
}
|
}
|
||||||
/* peer type internal, external, confed-internal or confed-external */
|
/* peer type internal or confed-internal */
|
||||||
if (p->as == p->local_as) {
|
if ((p->as == p->local_as) || (p->as_type == AS_INTERNAL)) {
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
|
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
|
||||||
json_object_boolean_true_add(
|
json_object_boolean_true_add(
|
||||||
@ -9227,7 +9225,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
|
|||||||
else
|
else
|
||||||
vty_out(vty, "internal link\n");
|
vty_out(vty, "internal link\n");
|
||||||
}
|
}
|
||||||
} else {
|
/* peer type external or confed-external */
|
||||||
|
} else if (p->as || (p->as_type == AS_EXTERNAL)) {
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
|
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
|
||||||
json_object_boolean_true_add(
|
json_object_boolean_true_add(
|
||||||
@ -9241,6 +9240,12 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
|
|||||||
else
|
else
|
||||||
vty_out(vty, "external link\n");
|
vty_out(vty, "external link\n");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (use_json)
|
||||||
|
json_object_boolean_true_add(json_neigh,
|
||||||
|
"nbrUnspecifiedLink");
|
||||||
|
else
|
||||||
|
vty_out(vty, "unspecified link\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Description. */
|
/* Description. */
|
||||||
|
46
bgpd/bgpd.c
46
bgpd/bgpd.c
@ -1001,7 +1001,26 @@ static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer)
|
|||||||
|
|
||||||
return BGP_PEER_EBGP;
|
return BGP_PEER_EBGP;
|
||||||
} else {
|
} else {
|
||||||
if (peer->as_type != AS_SPECIFIED)
|
if (peer->as_type == AS_UNSPECIFIED) {
|
||||||
|
/* check if in peer-group with AS information */
|
||||||
|
if (peer->group
|
||||||
|
&& (peer->group->conf->as_type != AS_UNSPECIFIED)) {
|
||||||
|
if (peer->group->conf->as_type
|
||||||
|
== AS_SPECIFIED) {
|
||||||
|
if (peer->local_as
|
||||||
|
== peer->group->conf->as)
|
||||||
|
return BGP_PEER_IBGP;
|
||||||
|
else
|
||||||
|
return BGP_PEER_EBGP;
|
||||||
|
} else if (peer->group->conf->as_type
|
||||||
|
== AS_INTERNAL)
|
||||||
|
return BGP_PEER_IBGP;
|
||||||
|
else
|
||||||
|
return BGP_PEER_EBGP;
|
||||||
|
}
|
||||||
|
/* no AS information anywhere, let caller know */
|
||||||
|
return BGP_PEER_UNSPECIFIED;
|
||||||
|
} else if (peer->as_type != AS_SPECIFIED)
|
||||||
return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
|
return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
|
||||||
: BGP_PEER_EBGP);
|
: BGP_PEER_EBGP);
|
||||||
|
|
||||||
@ -1711,20 +1730,32 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
|
|||||||
|
|
||||||
/* When this peer is a member of peer-group. */
|
/* When this peer is a member of peer-group. */
|
||||||
if (peer->group) {
|
if (peer->group) {
|
||||||
if (peer->group->conf->as) {
|
/* peer-group already has AS number/internal/external */
|
||||||
|
if (peer->group->conf->as
|
||||||
|
|| peer->group->conf->as_type) {
|
||||||
/* Return peer group's AS number. */
|
/* Return peer group's AS number. */
|
||||||
*as = peer->group->conf->as;
|
*as = peer->group->conf->as;
|
||||||
return BGP_ERR_PEER_GROUP_MEMBER;
|
return BGP_ERR_PEER_GROUP_MEMBER;
|
||||||
}
|
}
|
||||||
if (peer_sort(peer->group->conf) == BGP_PEER_IBGP) {
|
|
||||||
if ((as_type != AS_INTERNAL)
|
bgp_peer_sort_t peer_sort_type =
|
||||||
&& (bgp->as != *as)) {
|
peer_sort(peer->group->conf);
|
||||||
|
|
||||||
|
/* Explicit AS numbers used, compare AS numbers */
|
||||||
|
if (as_type == AS_SPECIFIED) {
|
||||||
|
if (((peer_sort_type == BGP_PEER_IBGP)
|
||||||
|
&& (bgp->as != *as))
|
||||||
|
|| ((peer_sort_type == BGP_PEER_EBGP)
|
||||||
|
&& (bgp->as == *as))) {
|
||||||
*as = peer->as;
|
*as = peer->as;
|
||||||
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
|
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((as_type != AS_EXTERNAL)
|
/* internal/external used, compare as-types */
|
||||||
&& (bgp->as == *as)) {
|
if (((peer_sort_type == BGP_PEER_IBGP)
|
||||||
|
&& (as_type != AS_INTERNAL))
|
||||||
|
|| ((peer_sort_type == BGP_PEER_EBGP)
|
||||||
|
&& (as_type != AS_EXTERNAL))) {
|
||||||
*as = peer->as;
|
*as = peer->as;
|
||||||
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
|
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
|
||||||
}
|
}
|
||||||
@ -2688,6 +2719,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
|
|||||||
if (peer->as_type == AS_UNSPECIFIED) {
|
if (peer->as_type == AS_UNSPECIFIED) {
|
||||||
peer->as_type = group->conf->as_type;
|
peer->as_type = group->conf->as_type;
|
||||||
peer->as = group->conf->as;
|
peer->as = group->conf->as;
|
||||||
|
peer->sort = group->conf->sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!group->conf->as) {
|
if (!group->conf->as) {
|
||||||
|
@ -646,7 +646,8 @@ struct bgp_filter {
|
|||||||
/* IBGP/EBGP identifier. We also have a CONFED peer, which is to say,
|
/* IBGP/EBGP identifier. We also have a CONFED peer, which is to say,
|
||||||
a peer who's AS is part of our Confederation. */
|
a peer who's AS is part of our Confederation. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BGP_PEER_IBGP = 1,
|
BGP_PEER_UNSPECIFIED,
|
||||||
|
BGP_PEER_IBGP,
|
||||||
BGP_PEER_EBGP,
|
BGP_PEER_EBGP,
|
||||||
BGP_PEER_INTERNAL,
|
BGP_PEER_INTERNAL,
|
||||||
BGP_PEER_CONFED,
|
BGP_PEER_CONFED,
|
||||||
|
Loading…
Reference in New Issue
Block a user