bgpd: Activate ipv6-unicast for peer automatically if globally defined

When you use a single BGP session for both IPv4 and IPv6 it's a bit
annoying going into ipv6 address-family and explicitly activating it.

Let's get this automatically if enabled with `bgp default ipv6-unicast`.

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
Donatas Abraitis 2021-02-20 19:25:15 +02:00
parent 8cf565010c
commit e84c59af5b
6 changed files with 111 additions and 60 deletions

View File

@ -3146,8 +3146,7 @@ int bgp_neighbors_neighbor_neighbor_remote_as_remote_as_type_modify(
return NB_OK;
str2sockunion(peer_str, &su);
ret = peer_remote_as(bgp, &su, NULL, &as, as_type, AFI_IP,
SAFI_UNICAST);
ret = peer_remote_as(bgp, &su, NULL, &as, as_type);
if (bgp_nb_errmsg_return(args->errmsg, args->errmsg_len, ret)
< 0)
return NB_ERR_INCONSISTENCY;
@ -3202,8 +3201,7 @@ int bgp_neighbors_neighbor_neighbor_remote_as_remote_as_modify(
as = yang_dnode_get_uint32(args->dnode, NULL);
str2sockunion(peer_str, &su);
ret = peer_remote_as(bgp, &su, NULL, &as, as_type, AFI_IP,
SAFI_UNICAST);
ret = peer_remote_as(bgp, &su, NULL, &as, as_type);
if (bgp_nb_errmsg_return(args->errmsg, args->errmsg_len, ret)
< 0)
return NB_ERR_INCONSISTENCY;
@ -4370,8 +4368,7 @@ int bgp_neighbors_unnumbered_neighbor_create(struct nb_cb_create_args *args)
"./neighbor-remote-as/remote-as");
}
if (peer_conf_interface_create(bgp, peer_str, AFI_IP,
SAFI_UNICAST, v6_only,
if (peer_conf_interface_create(bgp, peer_str, v6_only,
peer_grp_str, as_type, as,
args->errmsg, args->errmsg_len))
return NB_ERR_INCONSISTENCY;
@ -4440,9 +4437,9 @@ int bgp_neighbors_unnumbered_neighbor_v6only_modify(
v6_only = yang_dnode_get_bool(args->dnode, NULL);
if (peer_conf_interface_create(
bgp, peer_str, AFI_IP, SAFI_UNICAST, v6_only, NULL,
AS_UNSPECIFIED, 0, args->errmsg, args->errmsg_len))
if (peer_conf_interface_create(bgp, peer_str, v6_only, NULL,
AS_UNSPECIFIED, 0, args->errmsg,
args->errmsg_len))
return NB_ERR_INCONSISTENCY;
break;
@ -5174,8 +5171,6 @@ void bgp_neighbors_unnumbered_neighbor_neighbor_remote_as_apply_finish(
int ret;
as_t as = 0;
struct peer *peer = NULL;
afi_t afi = AFI_IP;
safi_t safi = SAFI_UNICAST;
bgp = nb_running_get_entry(args->dnode, NULL, true);
peer_str = yang_dnode_get_string(args->dnode, "../interface");
@ -5185,7 +5180,7 @@ void bgp_neighbors_unnumbered_neighbor_neighbor_remote_as_apply_finish(
peer = peer_lookup_by_conf_if(bgp, peer_str);
ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, afi, safi);
ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type);
if (ret < 0 && !peer) {
snprintf(args->errmsg, args->errmsg_len,

View File

@ -554,7 +554,7 @@ static int bgp_accept(struct thread *thread)
peer1->host);
peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as,
peer1->as, peer1->as_type, 0, 0, NULL);
peer1->as, peer1->as_type, NULL);
hash_release(peer->bgp->peerhash, peer);
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);

View File

@ -3726,6 +3726,29 @@ DEFPY (no_bgp_bestpath_bw,
return CMD_SUCCESS;
}
/* "no bgp default ipv6-unicast". */
DEFUN(no_bgp_default_ipv6_unicast, no_bgp_default_ipv6_unicast_cmd,
"no bgp default ipv6-unicast", NO_STR
"BGP specific commands\n"
"Configure BGP defaults\n"
"Activate ipv6-unicast for a peer by default\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
UNSET_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6);
return CMD_SUCCESS;
}
DEFUN(bgp_default_ipv6_unicast, bgp_default_ipv6_unicast_cmd,
"bgp default ipv6-unicast",
"BGP specific commands\n"
"Configure BGP defaults\n"
"Activate ipv6-unicast for a peer by default\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
SET_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6);
return CMD_SUCCESS;
}
/* "no bgp default ipv4-unicast". */
DEFUN (no_bgp_default_ipv4_unicast,
no_bgp_default_ipv4_unicast_cmd,
@ -4367,10 +4390,10 @@ DEFUN_YANG(neighbor_remote_as,
return nb_cli_apply_changes(vty, base_xpath);
}
int peer_conf_interface_create(struct bgp *bgp, const char *conf_if, afi_t afi,
safi_t safi, bool v6only,
const char *peer_group_name, int as_type,
as_t as, char *errmsg, size_t errmsg_len)
int peer_conf_interface_create(struct bgp *bgp, const char *conf_if,
bool v6only, const char *peer_group_name,
int as_type, as_t as, char *errmsg,
size_t errmsg_len)
{
struct peer *peer;
struct peer_group *group;
@ -4387,16 +4410,10 @@ int peer_conf_interface_create(struct bgp *bgp, const char *conf_if, afi_t afi,
peer = peer_lookup_by_conf_if(bgp, conf_if);
if (peer) {
if (as_type != AS_UNSPECIFIED)
ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type,
afi, safi);
ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type);
} else {
if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4)
&& afi == AFI_IP && safi == SAFI_UNICAST)
peer = peer_create(NULL, conf_if, bgp, bgp->as, as,
as_type, 0, 0, NULL);
else
peer = peer_create(NULL, conf_if, bgp, bgp->as, as,
as_type, afi, safi, NULL);
peer = peer_create(NULL, conf_if, bgp, bgp->as, as, as_type,
NULL);
if (!peer) {
snprintf(errmsg, errmsg_len,
@ -16799,18 +16816,36 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
}
} else {
if (peer->afc[afi][safi]) {
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
if (CHECK_FLAG(bgp->flags,
BGP_FLAG_NO_DEFAULT_IPV4)) {
if ((afi == AFI_IP || afi == AFI_IP6)
&& safi == SAFI_UNICAST) {
if (afi == AFI_IP
&& CHECK_FLAG(bgp->flags,
BGP_FLAG_NO_DEFAULT_IPV4)) {
vty_out(vty, " neighbor %s activate\n",
addr);
} else if (afi == AFI_IP6
&& !CHECK_FLAG(
bgp->flags,
BGP_FLAG_DEFAULT_IPV6)) {
vty_out(vty, " neighbor %s activate\n",
addr);
}
} else
} else {
vty_out(vty, " neighbor %s activate\n", addr);
}
} else {
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
if (!CHECK_FLAG(bgp->flags,
BGP_FLAG_NO_DEFAULT_IPV4)) {
if ((afi == AFI_IP || afi == AFI_IP6)
&& safi == SAFI_UNICAST) {
if (afi == AFI_IP
&& !CHECK_FLAG(bgp->flags,
BGP_FLAG_NO_DEFAULT_IPV4)) {
vty_out(vty,
" no neighbor %s activate\n",
addr);
} else if (afi == AFI_IP6
&& CHECK_FLAG(
bgp->flags,
BGP_FLAG_DEFAULT_IPV6)) {
vty_out(vty,
" no neighbor %s activate\n",
addr);
@ -17244,6 +17279,10 @@ int bgp_config_write(struct vty *vty)
if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4))
vty_out(vty, " no bgp default ipv4-unicast\n");
/* BGP default ipv6-unicast. */
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6))
vty_out(vty, " bgp default ipv6-unicast\n");
/* BGP default local-preference. */
if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
vty_out(vty, " bgp default local-preference %u\n",
@ -17914,6 +17953,10 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &no_bgp_default_ipv4_unicast_cmd);
install_element(BGP_NODE, &bgp_default_ipv4_unicast_cmd);
/* "no bgp default ipv6-unicast" commands. */
install_element(BGP_NODE, &no_bgp_default_ipv6_unicast_cmd);
install_element(BGP_NODE, &bgp_default_ipv6_unicast_cmd);
/* "bgp network import-check" commands. */
install_element(BGP_NODE, &bgp_network_import_check_cmd);
install_element(BGP_NODE, &bgp_network_import_check_exact_cmd);

View File

@ -205,9 +205,9 @@ extern int peer_local_interface_cfg(struct bgp *bgp, const char *ip_str,
const char *str, char *errmsg,
size_t errmsg_len);
extern int peer_conf_interface_create(struct bgp *bgp, const char *conf_if,
afi_t afi, safi_t safi, bool v6only,
const char *peer_group_name, int as_type,
as_t as, char *errmsg, size_t errmsg_len);
bool v6only, const char *peer_group_name,
int as_type, as_t as, char *errmsg,
size_t errmsg_len);
extern int peer_flag_modify_nb(struct bgp *bgp, const char *ip_str,
struct peer *peer, uint32_t flag, bool set,
char *errmsg, size_t errmsg_len);

View File

@ -1467,8 +1467,10 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
paf = peer_src->peer_af_array[afidx];
if (paf != NULL)
peer_af_create(peer_dst, paf->afi, paf->safi);
if (paf != NULL) {
if (!peer_af_find(peer_dst, paf->afi, paf->safi))
peer_af_create(peer_dst, paf->afi, paf->safi);
}
}
/* update-source apply */
@ -1682,12 +1684,13 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)
*/
struct peer *peer_create(union sockunion *su, const char *conf_if,
struct bgp *bgp, as_t local_as, as_t remote_as,
int as_type, afi_t afi, safi_t safi,
struct peer_group *group)
int as_type, struct peer_group *group)
{
int active;
struct peer *peer;
char buf[SU_ADDRSTRLEN];
afi_t afi;
safi_t safi;
peer = peer_new(bgp);
if (conf_if) {
@ -1746,9 +1749,23 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
if (afi && safi) {
peer->afc[afi][safi] = 1;
peer_af_create(peer, afi, safi);
/* If address family is IPv4 and `bgp default ipv4-unicast` (default),
* then activate the neighbor for this AF.
* If address family is IPv6 and `bgp default ipv6-unicast`
* (non-default), then activate the neighbor for this AF.
*/
FOREACH_AFI_SAFI (afi, safi) {
if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) {
if ((afi == AFI_IP
&& !CHECK_FLAG(bgp->flags,
BGP_FLAG_NO_DEFAULT_IPV4))
|| (afi == AFI_IP6
&& CHECK_FLAG(bgp->flags,
BGP_FLAG_DEFAULT_IPV6))) {
peer->afc[afi][safi] = 1;
peer_af_create(peer, afi, safi);
}
}
}
/* auto shutdown if configured */
@ -1877,7 +1894,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
/* 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, const char *conf_if,
as_t *as, int as_type, afi_t afi, safi_t safi)
as_t *as, int as_type)
{
struct peer *peer;
as_t local_as;
@ -1945,16 +1962,7 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
else
local_as = bgp->as;
/* If this is IPv4 unicast configuration and "no bgp default
ipv4-unicast" is specified. */
if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4)
&& afi == AFI_IP && safi == SAFI_UNICAST)
peer_create(su, conf_if, bgp, local_as, *as, as_type, 0,
0, NULL);
else
peer_create(su, conf_if, bgp, local_as, *as, as_type,
afi, safi, NULL);
peer_create(su, conf_if, bgp, local_as, *as, as_type, NULL);
}
return 0;
@ -2561,6 +2569,8 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
group->conf = peer_new(bgp);
if (!CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4))
group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6))
group->conf->afc[AFI_IP6][SAFI_UNICAST] = 1;
XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name);
group->conf->group = group;
@ -2995,7 +3005,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
}
peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
group->conf->as_type, 0, 0, group);
group->conf->as_type, group);
peer = peer_lock(peer); /* group->peer list reference */
listnode_add(group->peer, peer);
@ -3007,7 +3017,10 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
FOREACH_AFI_SAFI (afi, safi) {
if (group->conf->afc[afi][safi]) {
peer->afc[afi][safi] = 1;
peer_af_create(peer, afi, safi);
if (!peer_af_find(peer, afi, safi))
peer_af_create(peer, afi, safi);
peer_group2peer_config_copy_af(group, peer, afi,
safi);
} else if (peer->afc[afi][safi])
@ -3806,7 +3819,7 @@ struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp,
/* Create peer first; we've already checked group config is valid. */
peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
group->conf->as_type, 0, 0, group);
group->conf->as_type, group);
if (!peer)
return NULL;

View File

@ -477,6 +477,7 @@ struct bgp {
#define BGP_FLAG_SHUTDOWN (1 << 27)
#define BGP_FLAG_SUPPRESS_FIB_PENDING (1 << 28)
#define BGP_FLAG_SUPPRESS_DUPLICATES (1 << 29)
#define BGP_FLAG_DEFAULT_IPV6 (1 << 30)
enum global_mode GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE]
[BGP_GLOBAL_GR_EVENT_CMD];
@ -1916,8 +1917,7 @@ extern bool peer_active(struct peer *);
extern bool peer_active_nego(struct peer *);
extern void bgp_recalculate_all_bestpaths(struct bgp *bgp);
extern struct peer *peer_create(union sockunion *, const char *, struct bgp *,
as_t, as_t, int, afi_t, safi_t,
struct peer_group *);
as_t, as_t, int, struct peer_group *);
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 uptime2, char *buf, size_t len, bool use_json,
@ -1985,7 +1985,7 @@ extern bool bgp_update_delay_configured(struct bgp *);
extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi);
extern void peer_as_change(struct peer *, as_t, int);
extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *,
int, afi_t, safi_t);
int);
extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int);
extern int peer_delete(struct peer *peer);
extern void peer_notify_unconfig(struct peer *peer);