bgpd: Implement group-overrides for peer attrs

This commit introduces BGP peer-group overrides for the last set of
peer-level attrs which did not offer that feature yet. The following
attributes have been implemented: description, local-as, password and
update-source.

Each attribute, with the exception of description because it does not
offer any inheritance between peer-groups and peers, is now also setting
a peer-flag instead of just modifying the internal data structures. This
made it possible to also re-use the same implementation for attribute
overrides as already done for peer flags, AF flags and AF attrs.

The `no neighbor <neigh> description` command has been slightly changed
to support negation for no parameters, one parameter or * parameters
(LINE...). This was needed for the test suite to pass and is a small
change without any bigger impact on the CLI.

Signed-off-by: Pascal Mathis <mail@pascalmathis.com>
This commit is contained in:
Pascal Mathis 2018-06-13 19:34:17 +02:00
parent b90a8e13ee
commit a14810f43f
No known key found for this signature in database
GPG Key ID: E208DBA7BFC9B28C
5 changed files with 379 additions and 252 deletions

View File

@ -4655,12 +4655,11 @@ DEFUN (neighbor_description,
DEFUN (no_neighbor_description, DEFUN (no_neighbor_description,
no_neighbor_description_cmd, no_neighbor_description_cmd,
"no neighbor <A.B.C.D|X:X::X:X|WORD> description [LINE]", "no neighbor <A.B.C.D|X:X::X:X|WORD> description",
NO_STR NO_STR
NEIGHBOR_STR NEIGHBOR_STR
NEIGHBOR_ADDR_STR2 NEIGHBOR_ADDR_STR2
"Neighbor specific description\n" "Neighbor specific description\n")
"Up to 80 characters describing this neighbor\n")
{ {
int idx_peer = 2; int idx_peer = 2;
struct peer *peer; struct peer *peer;
@ -4674,6 +4673,11 @@ DEFUN (no_neighbor_description,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS(no_neighbor_description, no_neighbor_description_comment_cmd,
"no neighbor <A.B.C.D|X:X::X:X|WORD> description LINE...",
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
"Neighbor specific description\n"
"Up to 80 characters describing this neighbor\n")
/* Neighbor update-source. */ /* Neighbor update-source. */
static int peer_update_source_vty(struct vty *vty, const char *peer_str, static int peer_update_source_vty(struct vty *vty, const char *peer_str,
@ -4681,6 +4685,7 @@ static int peer_update_source_vty(struct vty *vty, const char *peer_str,
{ {
struct peer *peer; struct peer *peer;
struct prefix p; struct prefix p;
union sockunion su;
peer = peer_and_group_lookup_vty(vty, peer_str); peer = peer_and_group_lookup_vty(vty, peer_str);
if (!peer) if (!peer)
@ -4690,10 +4695,7 @@ static int peer_update_source_vty(struct vty *vty, const char *peer_str,
return CMD_WARNING; return CMD_WARNING;
if (source_str) { if (source_str) {
union sockunion su; if (str2sockunion(source_str, &su) == 0)
int ret = str2sockunion(source_str, &su);
if (ret == 0)
peer_update_source_addr_set(peer, &su); peer_update_source_addr_set(peer, &su);
else { else {
if (str2prefix(source_str, &p)) { if (str2prefix(source_str, &p)) {
@ -13030,6 +13032,7 @@ void bgp_vty_init(void)
/* "neighbor description" commands. */ /* "neighbor description" commands. */
install_element(BGP_NODE, &neighbor_description_cmd); install_element(BGP_NODE, &neighbor_description_cmd);
install_element(BGP_NODE, &no_neighbor_description_cmd); install_element(BGP_NODE, &no_neighbor_description_cmd);
install_element(BGP_NODE, &no_neighbor_description_comment_cmd);
/* "neighbor update-source" commands. "*/ /* "neighbor update-source" commands. "*/
install_element(BGP_NODE, &neighbor_update_source_cmd); install_element(BGP_NODE, &neighbor_update_source_cmd);

View File

@ -1494,10 +1494,12 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer)
* needed. * needed.
*/ */
if (peer_addr_updated) { if (peer_addr_updated) {
if (peer->password && prev_family == AF_UNSPEC) if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)
&& prev_family == AF_UNSPEC)
bgp_md5_set(peer); bgp_md5_set(peer);
} else { } else {
if (peer->password && prev_family != AF_UNSPEC) if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)
&& prev_family != AF_UNSPEC)
bgp_md5_unset(peer); bgp_md5_unset(peer);
peer->su.sa.sa_family = AF_UNSPEC; peer->su.sa.sa_family = AF_UNSPEC;
memset(&peer->su.sin6.sin6_addr, 0, sizeof(struct in6_addr)); memset(&peer->su.sin6.sin6_addr, 0, sizeof(struct in6_addr));
@ -1719,8 +1721,9 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
/* local-as reset */ /* local-as reset */
if (peer_sort(peer) != BGP_PEER_EBGP) { if (peer_sort(peer) != BGP_PEER_EBGP) {
peer->change_local_as = 0; peer->change_local_as = 0;
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
} }
} }
@ -2230,9 +2233,8 @@ int peer_delete(struct peer *peer)
bgp_unlink_nexthop_by_peer(peer); bgp_unlink_nexthop_by_peer(peer);
/* Password configuration */ /* Password configuration */
if (peer->password) { if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)) {
XFREE(MTYPE_PEER_PASSWORD, peer->password); XFREE(MTYPE_PEER_PASSWORD, peer->password);
peer->password = NULL;
if (!accept_peer && !BGP_PEER_SU_UNSPEC(peer) if (!accept_peer && !BGP_PEER_SU_UNSPEC(peer)
&& !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
@ -2422,8 +2424,8 @@ static void peer_group2peer_config_copy(struct peer_group *group,
if (conf->as) if (conf->as)
peer->as = conf->as; peer->as = conf->as;
/* remote-as */ /* local-as */
if (conf->change_local_as) if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_LOCAL_AS))
peer->change_local_as = conf->change_local_as; peer->change_local_as = conf->change_local_as;
/* TTL */ /* TTL */
@ -2462,30 +2464,23 @@ static void peer_group2peer_config_copy(struct peer_group *group,
} }
/* password apply */ /* password apply */
if (conf->password && !peer->password) if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, conf->password); PEER_STR_ATTR_INHERIT(peer, group, password,
MTYPE_PEER_PASSWORD);
if (!BGP_PEER_SU_UNSPEC(peer)) if (!BGP_PEER_SU_UNSPEC(peer))
bgp_md5_set(peer); bgp_md5_set(peer);
/* update-source apply */ /* update-source apply */
if (conf->update_source) { if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_UPDATE_SOURCE)) {
if (peer->update_source) if (conf->update_source) {
sockunion_free(peer->update_source);
if (peer->update_if) {
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
peer->update_if = NULL; PEER_SU_ATTR_INHERIT(peer, group, update_source);
} } else if (conf->update_if) {
peer->update_source = sockunion_dup(conf->update_source);
} else if (conf->update_if) {
if (peer->update_if)
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
if (peer->update_source) {
sockunion_free(peer->update_source); sockunion_free(peer->update_source);
peer->update_source = NULL; PEER_STR_ATTR_INHERIT(peer, group, update_if,
MTYPE_PEER_UPDATE_SOURCE);
} }
peer->update_if =
XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
} }
bgp_bfd_peer_group2peer_copy(conf, peer); bgp_bfd_peer_group2peer_copy(conf, peer);
@ -2764,10 +2759,12 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
/* local-as reset */ /* local-as reset */
if (peer_sort(group->conf) != BGP_PEER_EBGP) { if (peer_sort(group->conf) != BGP_PEER_EBGP) {
group->conf->change_local_as = 0; group->conf->change_local_as = 0;
UNSET_FLAG(peer->flags, peer_flag_unset(group->conf,
PEER_FLAG_LOCAL_AS_NO_PREPEND); PEER_FLAG_LOCAL_AS);
UNSET_FLAG(peer->flags, peer_flag_unset(group->conf,
PEER_FLAG_LOCAL_AS_REPLACE_AS); PEER_FLAG_LOCAL_AS_NO_PREPEND);
peer_flag_unset(group->conf,
PEER_FLAG_LOCAL_AS_REPLACE_AS);
} }
} }
@ -3841,6 +3838,11 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_ROUTEADV, 0, peer_change_none}, {PEER_FLAG_ROUTEADV, 0, peer_change_none},
{PEER_FLAG_TIMER, 0, peer_change_none}, {PEER_FLAG_TIMER, 0, peer_change_none},
{PEER_FLAG_TIMER_CONNECT, 0, peer_change_none}, {PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
{PEER_FLAG_PASSWORD, 0, peer_change_none},
{PEER_FLAG_LOCAL_AS, 0, peer_change_none},
{PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_none},
{PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
{PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
{0, 0, 0}}; {0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = { static const struct peer_flag_action peer_af_flag_action_list[] = {
@ -4447,183 +4449,195 @@ int peer_description_unset(struct peer *peer)
/* Neighbor update-source. */ /* Neighbor update-source. */
int peer_update_source_if_set(struct peer *peer, const char *ifname) int peer_update_source_if_set(struct peer *peer, const char *ifname)
{ {
struct peer_group *group; struct peer *member;
struct listnode *node, *nnode; struct listnode *node, *nnode;
/* Set flag and configuration on peer. */
peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
if (peer->update_if) { if (peer->update_if) {
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) if (strcmp(peer->update_if, ifname) == 0)
&& strcmp(peer->update_if, ifname) == 0)
return 0; return 0;
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
peer->update_if = NULL;
} }
if (peer->update_source) {
sockunion_free(peer->update_source);
peer->update_source = NULL;
}
peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname); peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
sockunion_free(peer->update_source);
peer->update_source = NULL;
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(peer);
/* Skip peer-group mechanics for regular peers. */
return 0; return 0;
} }
/* peer-group member updates. */ /*
group = peer->group; * Set flag and configuration on all peer-group members, unless they are
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { * explicitely overriding peer-group configuration.
if (peer->update_if) { */
if (strcmp(peer->update_if, ifname) == 0) for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
continue;
/* Skip peers with the same configuration. */
if (member->update_if) {
if (strcmp(member->update_if, ifname) == 0)
continue; continue;
XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
peer->update_if = NULL;
} }
if (peer->update_source) { /* Set flag and configuration on peer-group member. */
sockunion_free(peer->update_source); SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
peer->update_source = NULL; member->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
} sockunion_free(member->update_source);
member->update_source = NULL;
peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname); /* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; bgp_notify_send(member, BGP_NOTIFY_CEASE,
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(member);
} }
return 0; return 0;
} }
int peer_update_source_addr_set(struct peer *peer, const union sockunion *su) int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
{ {
struct peer_group *group; struct peer *member;
struct listnode *node, *nnode; struct listnode *node, *nnode;
/* Set flag and configuration on peer. */
peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
if (peer->update_source) { if (peer->update_source) {
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) if (sockunion_cmp(peer->update_source, su) == 0)
&& sockunion_cmp(peer->update_source, su) == 0)
return 0; return 0;
sockunion_free(peer->update_source); sockunion_free(peer->update_source);
peer->update_source = NULL;
} }
if (peer->update_if) {
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
peer->update_if = NULL;
}
peer->update_source = sockunion_dup(su); peer->update_source = sockunion_dup(su);
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(peer);
/* Skip peer-group mechanics for regular peers. */
return 0; return 0;
} }
/* peer-group member updates. */ /*
group = peer->group; * Set flag and configuration on all peer-group members, unless they are
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { * explicitely overriding peer-group configuration.
if (peer->update_source) { */
if (sockunion_cmp(peer->update_source, su) == 0) for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
continue;
/* Skip peers with the same configuration. */
if (member->update_source) {
if (sockunion_cmp(member->update_source, su) == 0)
continue; continue;
sockunion_free(peer->update_source); sockunion_free(member->update_source);
peer->update_source = NULL;
} }
if (peer->update_if) { /* Set flag and configuration on peer-group member. */
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
peer->update_if = NULL; member->update_source = sockunion_dup(su);
} XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
peer->update_source = sockunion_dup(su); /* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; bgp_notify_send(member, BGP_NOTIFY_CEASE,
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(member);
} }
return 0; return 0;
} }
int peer_update_source_unset(struct peer *peer) int peer_update_source_unset(struct peer *peer)
{ {
union sockunion *su; struct peer *member;
struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && !peer->update_source if (!CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE))
&& !peer->update_if)
return 0; return 0;
if (peer->update_source) { /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
peer_flag_inherit(peer, PEER_FLAG_UPDATE_SOURCE);
PEER_SU_ATTR_INHERIT(peer, peer->group, update_source);
PEER_STR_ATTR_INHERIT(peer, peer->group, update_if,
MTYPE_PEER_UPDATE_SOURCE);
} else {
/* Otherwise remove flag and configuration from peer. */
peer_flag_unset(peer, PEER_FLAG_UPDATE_SOURCE);
sockunion_free(peer->update_source); sockunion_free(peer->update_source);
peer->update_source = NULL; peer->update_source = NULL;
}
if (peer->update_if) {
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
peer->update_if = NULL;
}
if (peer_group_active(peer)) {
group = peer->group;
if (group->conf->update_source) {
su = sockunion_dup(group->conf->update_source);
peer->update_source = su;
} else if (group->conf->update_if)
peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE,
group->conf->update_if);
} }
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(peer);
/* Skip peer-group mechanics for regular peers. */
return 0; return 0;
} }
/* peer-group member updates. */ /*
group = peer->group; * Set flag and configuration on all peer-group members, unless they are
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { * explicitely overriding peer-group configuration.
if (!peer->update_source && !peer->update_if) */
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
continue; continue;
if (peer->update_source) { /* Skip peers with the same configuration. */
sockunion_free(peer->update_source); if (!CHECK_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE)
peer->update_source = NULL; && !member->update_source && !member->update_if)
} continue;
if (peer->update_if) { /* Remove flag and configuration on peer-group member. */
XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); UNSET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
peer->update_if = NULL; sockunion_free(member->update_source);
} member->update_source = NULL;
XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { /* Send notification or reset peer depending on state. */
peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
bgp_notify_send(peer, BGP_NOTIFY_CEASE, member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(member);
} }
return 0; return 0;
} }
@ -5310,8 +5324,9 @@ int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
int peer_local_as_set(struct peer *peer, as_t as, int no_prepend, int peer_local_as_set(struct peer *peer, as_t as, int no_prepend,
int replace_as) int replace_as)
{ {
bool old_no_prepend, old_replace_as;
struct bgp *bgp = peer->bgp; struct bgp *bgp = peer->bgp;
struct peer_group *group; struct peer *member;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_sort(peer) != BGP_PEER_EBGP if (peer_sort(peer) != BGP_PEER_EBGP
@ -5324,57 +5339,71 @@ int peer_local_as_set(struct peer *peer, as_t as, int no_prepend,
if (peer->as == as) if (peer->as == as)
return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
if (peer->change_local_as == as /* Save previous flag states. */
&& ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) old_no_prepend =
&& no_prepend) !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
|| (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) old_replace_as =
&& !no_prepend)) !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
&& ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
&& replace_as) /* Set flag and configuration on peer. */
|| (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) peer_flag_set(peer, PEER_FLAG_LOCAL_AS);
&& !replace_as))) peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND, no_prepend);
peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS, replace_as);
if (peer->change_local_as == as && old_no_prepend == no_prepend
&& old_replace_as == replace_as)
return 0; return 0;
peer->change_local_as = as; peer->change_local_as = as;
if (no_prepend)
SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
else
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
if (replace_as)
SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
else
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(peer);
/* Skip peer-group mechanics for regular peers. */
return 0; return 0;
} }
group = peer->group; /*
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { * Set flag and configuration on all peer-group members, unless they are
peer->change_local_as = as; * explicitely overriding peer-group configuration.
if (no_prepend) */
SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
else /* Skip peers with overridden configuration. */
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
continue;
if (replace_as) /* Skip peers with the same configuration. */
SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); old_no_prepend = CHECK_FLAG(member->flags,
else PEER_FLAG_LOCAL_AS_NO_PREPEND);
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); old_replace_as = CHECK_FLAG(member->flags,
PEER_FLAG_LOCAL_AS_REPLACE_AS);
if (member->change_local_as == as
&& CHECK_FLAG(member->flags, PEER_FLAG_LOCAL_AS)
&& old_no_prepend == no_prepend
&& old_replace_as == replace_as)
continue;
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { /* Set flag and configuration on peer-group member. */
peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; SET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
bgp_notify_send(peer, BGP_NOTIFY_CEASE, COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND,
no_prepend);
COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,
replace_as);
member->change_local_as = as;
/* Send notification or stop peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
BGP_EVENT_ADD(peer, BGP_Stop); BGP_EVENT_ADD(member, BGP_Stop);
} }
return 0; return 0;
@ -5382,17 +5411,29 @@ int peer_local_as_set(struct peer *peer, as_t as, int no_prepend,
int peer_local_as_unset(struct peer *peer) int peer_local_as_unset(struct peer *peer)
{ {
struct peer_group *group; struct peer *member;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (!peer->change_local_as) if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS))
return 0; return 0;
peer->change_local_as = 0; /* Inherit configuration from peer-group if peer is member. */
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); if (peer_group_active(peer)) {
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS);
peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
PEER_ATTR_INHERIT(peer, peer->group, change_local_as);
} else {
/* Otherwise remove flag and configuration from peer. */
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
peer->change_local_as = 0;
}
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or stop peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
@ -5400,77 +5441,103 @@ int peer_local_as_unset(struct peer *peer)
} else } else
BGP_EVENT_ADD(peer, BGP_Stop); BGP_EVENT_ADD(peer, BGP_Stop);
/* Skip peer-group mechanics for regular peers. */
return 0; return 0;
} }
group = peer->group; /*
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { * Remove flag and configuration from all peer-group members, unless
peer->change_local_as = 0; * they are explicitely overriding peer-group configuration.
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); */
UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
continue;
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { /* Remove flag and configuration on peer-group member. */
peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
bgp_notify_send(peer, BGP_NOTIFY_CEASE, UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
member->change_local_as = 0;
/* Send notification or stop peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
} else } else
bgp_session_reset(peer); bgp_session_reset(member);
} }
return 0; return 0;
} }
/* Set password for authenticating with the peer. */ /* Set password for authenticating with the peer. */
int peer_password_set(struct peer *peer, const char *password) int peer_password_set(struct peer *peer, const char *password)
{ {
struct listnode *nn, *nnode; struct peer *member;
struct listnode *node, *nnode;
int len = password ? strlen(password) : 0; int len = password ? strlen(password) : 0;
int ret = BGP_SUCCESS; int ret = BGP_SUCCESS;
if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN)) if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if (peer->password && strcmp(peer->password, password) == 0 /* Set flag and configuration on peer. */
&& !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) peer_flag_set(peer, PEER_FLAG_PASSWORD);
if (peer->password && strcmp(peer->password, password) == 0)
return 0; return 0;
XFREE(MTYPE_PEER_PASSWORD, peer->password);
if (peer->password)
XFREE(MTYPE_PEER_PASSWORD, peer->password);
peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else else
bgp_session_reset(peer); bgp_session_reset(peer);
/*
* Attempt to install password on socket and skip peer-group
* mechanics.
*/
if (BGP_PEER_SU_UNSPEC(peer)) if (BGP_PEER_SU_UNSPEC(peer))
return BGP_SUCCESS; return BGP_SUCCESS;
return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS
: BGP_ERR_TCPSIG_FAILED; : BGP_ERR_TCPSIG_FAILED;
} }
for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) { /*
if (peer->password && strcmp(peer->password, password) == 0) * Set flag and configuration on all peer-group members, unless they are
* explicitely overriding peer-group configuration.
*/
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
continue; continue;
if (peer->password) /* Skip peers with the same password. */
XFREE(MTYPE_PEER_PASSWORD, peer->password); if (member->password && strcmp(member->password, password) == 0)
continue;
peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); /* Set flag and configuration on peer-group member. */
SET_FLAG(member->flags, PEER_FLAG_PASSWORD);
if (member->password)
XFREE(MTYPE_PEER_PASSWORD, member->password);
member->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) /* Send notification or reset peer depending on state. */
bgp_notify_send(peer, BGP_NOTIFY_CEASE, if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else else
bgp_session_reset(peer); bgp_session_reset(member);
if (!BGP_PEER_SU_UNSPEC(peer)) { /* Attempt to install password on socket. */
if (bgp_md5_set(peer) < 0) if (!BGP_PEER_SU_UNSPEC(member) && bgp_md5_set(member) < 0)
ret = BGP_ERR_TCPSIG_FAILED; ret = BGP_ERR_TCPSIG_FAILED;
}
} }
return ret; return ret;
@ -5478,47 +5545,63 @@ int peer_password_set(struct peer *peer, const char *password)
int peer_password_unset(struct peer *peer) int peer_password_unset(struct peer *peer)
{ {
struct listnode *nn, *nnode; struct peer *member;
struct listnode *node, *nnode;
if (!peer->password && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) if (!CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD))
return 0; return 0;
/* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
peer_flag_inherit(peer, PEER_FLAG_PASSWORD);
PEER_STR_ATTR_INHERIT(peer, peer->group, password,
MTYPE_PEER_PASSWORD);
} else {
/* Otherwise remove flag and configuration from peer. */
peer_flag_unset(peer, PEER_FLAG_PASSWORD);
XFREE(MTYPE_PEER_PASSWORD, peer->password);
}
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE, bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else else
bgp_session_reset(peer); bgp_session_reset(peer);
if (peer->password) /* Attempt to uninstall password on socket. */
XFREE(MTYPE_PEER_PASSWORD, peer->password);
peer->password = NULL;
if (!BGP_PEER_SU_UNSPEC(peer)) if (!BGP_PEER_SU_UNSPEC(peer))
bgp_md5_unset(peer); bgp_md5_unset(peer);
/* Skip peer-group mechanics for regular peers. */
return 0; return 0;
} }
XFREE(MTYPE_PEER_PASSWORD, peer->password); /*
peer->password = NULL; * Remove flag and configuration from all peer-group members, unless
* they are explicitely overriding peer-group configuration.
for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) { */
if (!peer->password) for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
/* Skip peers with overridden configuration. */
if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
continue; continue;
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) /* Remove flag and configuration on peer-group member. */
bgp_notify_send(peer, BGP_NOTIFY_CEASE, UNSET_FLAG(member->flags, PEER_FLAG_PASSWORD);
XFREE(MTYPE_PEER_PASSWORD, member->password);
/* Send notification or reset peer depending on state. */
if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
bgp_notify_send(member, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE); BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else else
bgp_session_reset(peer); bgp_session_reset(member);
XFREE(MTYPE_PEER_PASSWORD, peer->password); /* Attempt to uninstall password on socket. */
peer->password = NULL; if (!BGP_PEER_SU_UNSPEC(member))
bgp_md5_unset(member);
if (!BGP_PEER_SU_UNSPEC(peer))
bgp_md5_unset(peer);
} }
return 0; return 0;
@ -6929,24 +7012,14 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
} }
/* local-as */ /* local-as */
if (peer->change_local_as) { if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS)) {
if (!peer_group_active(peer) vty_out(vty, " neighbor %s local-as %u", addr,
|| peer->change_local_as != g_peer->change_local_as peer->change_local_as);
|| peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND) if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND))
|| peergroup_flag_check(peer, vty_out(vty, " no-prepend");
PEER_FLAG_LOCAL_AS_REPLACE_AS)) { if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS))
vty_out(vty, " neighbor %s local-as %u", addr, vty_out(vty, " replace-as");
peer->change_local_as); vty_out(vty, "\n");
if (peergroup_flag_check(peer,
PEER_FLAG_LOCAL_AS_NO_PREPEND))
vty_out(vty, " no-prepend");
if (peergroup_flag_check(peer,
PEER_FLAG_LOCAL_AS_REPLACE_AS))
vty_out(vty, " replace-as");
vty_out(vty, "\n");
}
} }
/* description */ /* description */
@ -6971,13 +7044,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
} }
/* password */ /* password */
if (peer->password) { if (peergroup_flag_check(peer, PEER_FLAG_PASSWORD))
if (!peer_group_active(peer) || !g_peer->password vty_out(vty, " neighbor %s password %s\n", addr,
|| strcmp(peer->password, g_peer->password) != 0) { peer->password);
vty_out(vty, " neighbor %s password %s\n", addr,
peer->password);
}
}
/* neighbor solo */ /* neighbor solo */
if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) { if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
@ -7027,21 +7096,14 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " neighbor %s enforce-first-as\n", addr); vty_out(vty, " neighbor %s enforce-first-as\n", addr);
/* update-source */ /* update-source */
if (peer->update_if) { if (peergroup_flag_check(peer, PEER_FLAG_UPDATE_SOURCE)) {
if (!peer_group_active(peer) || !g_peer->update_if if (peer->update_source)
|| strcmp(g_peer->update_if, peer->update_if) != 0) {
vty_out(vty, " neighbor %s update-source %s\n", addr,
peer->update_if);
}
}
if (peer->update_source) {
if (!peer_group_active(peer) || !g_peer->update_source
|| sockunion_cmp(g_peer->update_source, peer->update_source)
!= 0) {
vty_out(vty, " neighbor %s update-source %s\n", addr, vty_out(vty, " neighbor %s update-source %s\n", addr,
sockunion2str(peer->update_source, buf, sockunion2str(peer->update_source, buf,
SU_ADDRSTRLEN)); SU_ADDRSTRLEN));
} else if (peer->update_if)
vty_out(vty, " neighbor %s update-source %s\n", addr,
peer->update_if);
} }
/* advertisement-interval */ /* advertisement-interval */

View File

@ -898,6 +898,9 @@ struct peer {
#define PEER_FLAG_ROUTEADV (1 << 17) /* route advertise */ #define PEER_FLAG_ROUTEADV (1 << 17) /* route advertise */
#define PEER_FLAG_TIMER (1 << 18) /* keepalive & holdtime */ #define PEER_FLAG_TIMER (1 << 18) /* keepalive & holdtime */
#define PEER_FLAG_TIMER_CONNECT (1 << 19) /* connect timer */ #define PEER_FLAG_TIMER_CONNECT (1 << 19) /* connect timer */
#define PEER_FLAG_PASSWORD (1 << 20) /* password */
#define PEER_FLAG_LOCAL_AS (1 << 21) /* local-as */
#define PEER_FLAG_UPDATE_SOURCE (1 << 22) /* update-source */
/* outgoing message sent in CEASE_ADMIN_SHUTDOWN notify */ /* outgoing message sent in CEASE_ADMIN_SHUTDOWN notify */
char *tx_shutdown_message; char *tx_shutdown_message;
@ -1188,6 +1191,15 @@ DECLARE_QOBJ_TYPE(peer)
else \ else \
(peer)->attr = NULL; \ (peer)->attr = NULL; \
} while (0) } while (0)
#define PEER_SU_ATTR_INHERIT(peer, group, attr) \
do { \
if ((peer)->attr) \
sockunion_free((peer)->attr); \
if ((group)->conf->attr) \
(peer)->attr = sockunion_dup((group)->conf->attr); \
else \
(peer)->attr = NULL; \
} while (0)
/* Check if suppress start/restart of sessions to peer. */ /* Check if suppress start/restart of sessions to peer. */
#define BGP_PEER_START_SUPPRESSED(P) \ #define BGP_PEER_START_SUPPRESSED(P) \

View File

@ -210,6 +210,12 @@ static struct test_peer_attr test_peer_attrs[] = {
.o.invert_peer = true, .o.invert_peer = true,
.o.use_iface_peer = true, .o.use_iface_peer = true,
}, },
{
.cmd = "description",
.peer_cmd = "description FRR Peer",
.group_cmd = "description FRR Group",
.type = PEER_AT_GLOBAL_CUSTOM,
},
{ {
.cmd = "disable-connected-check", .cmd = "disable-connected-check",
.u.flag = PEER_FLAG_DISABLE_CONNECTED_CHECK, .u.flag = PEER_FLAG_DISABLE_CONNECTED_CHECK,
@ -225,6 +231,22 @@ static struct test_peer_attr test_peer_attrs[] = {
.u.flag = PEER_FLAG_ENFORCE_FIRST_AS, .u.flag = PEER_FLAG_ENFORCE_FIRST_AS,
.type = PEER_AT_GLOBAL_FLAG, .type = PEER_AT_GLOBAL_FLAG,
}, },
{
.cmd = "local-as",
.peer_cmd = "local-as 1",
.group_cmd = "local-as 2",
.type = PEER_AT_GLOBAL_CUSTOM,
},
{
.cmd = "local-as 1 no-prepend",
.u.flag = PEER_FLAG_LOCAL_AS_NO_PREPEND,
.type = PEER_AT_GLOBAL_FLAG,
},
{
.cmd = "local-as 1 no-prepend replace-as",
.u.flag = PEER_FLAG_LOCAL_AS_REPLACE_AS,
.type = PEER_AT_GLOBAL_FLAG,
},
{ {
.cmd = "override-capability", .cmd = "override-capability",
.u.flag = PEER_FLAG_OVERRIDE_CAPABILITY, .u.flag = PEER_FLAG_OVERRIDE_CAPABILITY,
@ -235,6 +257,12 @@ static struct test_peer_attr test_peer_attrs[] = {
.u.flag = PEER_FLAG_PASSIVE, .u.flag = PEER_FLAG_PASSIVE,
.type = PEER_AT_GLOBAL_FLAG, .type = PEER_AT_GLOBAL_FLAG,
}, },
{
.cmd = "password",
.peer_cmd = "password FRR-Peer",
.group_cmd = "password FRR-Group",
.type = PEER_AT_GLOBAL_CUSTOM,
},
{ {
.cmd = "shutdown", .cmd = "shutdown",
.u.flag = PEER_FLAG_SHUTDOWN, .u.flag = PEER_FLAG_SHUTDOWN,
@ -259,6 +287,18 @@ static struct test_peer_attr test_peer_attrs[] = {
.u.flag = PEER_FLAG_TIMER_CONNECT, .u.flag = PEER_FLAG_TIMER_CONNECT,
.type = PEER_AT_GLOBAL_FLAG, .type = PEER_AT_GLOBAL_FLAG,
}, },
{
.cmd = "update-source",
.peer_cmd = "update-source 255.255.255.1",
.group_cmd = "update-source 255.255.255.2",
.type = PEER_AT_GLOBAL_CUSTOM,
},
{
.cmd = "update-source",
.peer_cmd = "update-source IFACE-PEER",
.group_cmd = "update-source IFACE-GROUP",
.type = PEER_AT_GLOBAL_CUSTOM,
},
/* Address Family Attributes */ /* Address Family Attributes */
{ {

View File

@ -6,16 +6,26 @@ class TestFlag(frrtest.TestMultiOut):
# List of tests can be generated by executing: # List of tests can be generated by executing:
# $> ./test_peer_attr 2>&1 | sed -n 's/\\/\\\\/g; s/\S\+ \[test\] \(.\+\)/TestFlag.okfail(\x27\1\x27)/pg' # $> ./test_peer_attr 2>&1 | sed -n 's/\\/\\\\/g; s/\S\+ \[test\] \(.\+\)/TestFlag.okfail(\x27\1\x27)/pg'
# #
TestFlag.okfail('peer\\advertisement-interval')
TestFlag.okfail('peer\\capability dynamic') TestFlag.okfail('peer\\capability dynamic')
TestFlag.okfail('peer\\capability extended-nexthop') TestFlag.okfail('peer\\capability extended-nexthop')
TestFlag.okfail('peer\\capability extended-nexthop') TestFlag.okfail('peer\\capability extended-nexthop')
TestFlag.okfail('peer\\description')
TestFlag.okfail('peer\\disable-connected-check') TestFlag.okfail('peer\\disable-connected-check')
TestFlag.okfail('peer\\dont-capability-negotiate') TestFlag.okfail('peer\\dont-capability-negotiate')
TestFlag.okfail('peer\\enforce-first-as') TestFlag.okfail('peer\\enforce-first-as')
TestFlag.okfail('peer\\local-as')
TestFlag.okfail('peer\\local-as 1 no-prepend')
TestFlag.okfail('peer\\local-as 1 no-prepend replace-as')
TestFlag.okfail('peer\\override-capability') TestFlag.okfail('peer\\override-capability')
TestFlag.okfail('peer\\passive') TestFlag.okfail('peer\\passive')
TestFlag.okfail('peer\\password')
TestFlag.okfail('peer\\shutdown') TestFlag.okfail('peer\\shutdown')
TestFlag.okfail('peer\\strict-capability-match') TestFlag.okfail('peer\\strict-capability-match')
TestFlag.okfail('peer\\timers')
TestFlag.okfail('peer\\timers connect')
TestFlag.okfail('peer\\update-source')
TestFlag.okfail('peer\\update-source')
TestFlag.okfail('peer\\ipv4-unicast\\addpath-tx-all-paths') TestFlag.okfail('peer\\ipv4-unicast\\addpath-tx-all-paths')
TestFlag.okfail('peer\\ipv4-multicast\\addpath-tx-all-paths') TestFlag.okfail('peer\\ipv4-multicast\\addpath-tx-all-paths')
TestFlag.okfail('peer\\ipv6-unicast\\addpath-tx-all-paths') TestFlag.okfail('peer\\ipv6-unicast\\addpath-tx-all-paths')