mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-11 16:39:33 +00:00
Merge pull request #1047 from dwalton76/bgpd-draft-ietf-grow-bgp-gshut-10
bgpd: implement draft-ietf-grow-bgp-gshut-10
This commit is contained in:
commit
5ba345ccb2
@ -848,10 +848,24 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, u_char origin,
|
|||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
||||||
|
|
||||||
if (community) {
|
if (community) {
|
||||||
|
u_int32_t gshut = COMMUNITY_GSHUT;
|
||||||
|
|
||||||
|
/* If we are not shutting down ourselves and we are
|
||||||
|
* aggregating a route that contains the GSHUT community we
|
||||||
|
* need to remove that community when creating the aggregate */
|
||||||
|
if (!bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN) &&
|
||||||
|
community_include(community, gshut)) {
|
||||||
|
community_del_val(community, &gshut);
|
||||||
|
}
|
||||||
|
|
||||||
attr.community = community;
|
attr.community = community;
|
||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
|
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||||
|
bgp_attr_add_gshut_community(&attr);
|
||||||
|
}
|
||||||
|
|
||||||
attr.label_index = BGP_INVALID_LABEL_INDEX;
|
attr.label_index = BGP_INVALID_LABEL_INDEX;
|
||||||
attr.label = MPLS_INVALID_LABEL;
|
attr.label = MPLS_INVALID_LABEL;
|
||||||
attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
|
attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
|
||||||
@ -1400,7 +1414,7 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
|
|||||||
|
|
||||||
attr->local_pref = stream_getl(peer->ibuf);
|
attr->local_pref = stream_getl(peer->ibuf);
|
||||||
|
|
||||||
/* Set atomic aggregate flag. */
|
/* Set the local-pref flag. */
|
||||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
||||||
|
|
||||||
return BGP_ATTR_PARSE_PROCEED;
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
|
@ -355,6 +355,9 @@ static char *community_str_get(struct community *com, int i)
|
|||||||
case COMMUNITY_LOCAL_AS:
|
case COMMUNITY_LOCAL_AS:
|
||||||
len = strlen(" local-AS");
|
len = strlen(" local-AS");
|
||||||
break;
|
break;
|
||||||
|
case COMMUNITY_GSHUT:
|
||||||
|
len = strlen(" graceful-shutdown");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
len = strlen(" 65536:65535");
|
len = strlen(" 65536:65535");
|
||||||
break;
|
break;
|
||||||
@ -380,6 +383,10 @@ static char *community_str_get(struct community *com, int i)
|
|||||||
strcpy(pnt, "local-AS");
|
strcpy(pnt, "local-AS");
|
||||||
pnt += strlen("local-AS");
|
pnt += strlen("local-AS");
|
||||||
break;
|
break;
|
||||||
|
case COMMUNITY_GSHUT:
|
||||||
|
strcpy(pnt, "graceful-shutdown");
|
||||||
|
pnt += strlen("graceful-shutdown");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
as = (comval >> 16) & 0xFFFF;
|
as = (comval >> 16) & 0xFFFF;
|
||||||
val = comval & 0xFFFF;
|
val = comval & 0xFFFF;
|
||||||
|
@ -191,6 +191,7 @@ struct community *community_uniq_sort(struct community *com)
|
|||||||
0xFFFFFF01 "no-export"
|
0xFFFFFF01 "no-export"
|
||||||
0xFFFFFF02 "no-advertise"
|
0xFFFFFF02 "no-advertise"
|
||||||
0xFFFFFF03 "local-AS"
|
0xFFFFFF03 "local-AS"
|
||||||
|
0xFFFF0000 "graceful-shutdown"
|
||||||
|
|
||||||
For other values, "AS:VAL" format is used. */
|
For other values, "AS:VAL" format is used. */
|
||||||
static void set_community_string(struct community *com)
|
static void set_community_string(struct community *com)
|
||||||
@ -244,6 +245,9 @@ static void set_community_string(struct community *com)
|
|||||||
case COMMUNITY_LOCAL_AS:
|
case COMMUNITY_LOCAL_AS:
|
||||||
len += strlen(" local-AS");
|
len += strlen(" local-AS");
|
||||||
break;
|
break;
|
||||||
|
case COMMUNITY_GSHUT:
|
||||||
|
len += strlen(" graceful-shutdown");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
len += strlen(" 65536:65535");
|
len += strlen(" 65536:65535");
|
||||||
break;
|
break;
|
||||||
@ -289,6 +293,12 @@ static void set_community_string(struct community *com)
|
|||||||
json_string = json_object_new_string("localAs");
|
json_string = json_object_new_string("localAs");
|
||||||
json_object_array_add(json_community_list, json_string);
|
json_object_array_add(json_community_list, json_string);
|
||||||
break;
|
break;
|
||||||
|
case COMMUNITY_GSHUT:
|
||||||
|
strcpy(pnt, "graceful-shutdown");
|
||||||
|
pnt += strlen("graceful-shutdown");
|
||||||
|
json_string = json_object_new_string("gracefulShutdown");
|
||||||
|
json_object_array_add(json_community_list, json_string);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
as = (comval >> 16) & 0xFFFF;
|
as = (comval >> 16) & 0xFFFF;
|
||||||
val = comval & 0xFFFF;
|
val = comval & 0xFFFF;
|
||||||
@ -480,6 +490,7 @@ enum community_token {
|
|||||||
community_token_no_export,
|
community_token_no_export,
|
||||||
community_token_no_advertise,
|
community_token_no_advertise,
|
||||||
community_token_local_as,
|
community_token_local_as,
|
||||||
|
community_token_gshut,
|
||||||
community_token_unknown
|
community_token_unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -523,6 +534,12 @@ community_gettoken(const char *buf, enum community_token *token, u_int32_t *val)
|
|||||||
p += strlen("local-AS");
|
p += strlen("local-AS");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
if (strncmp(p, "graceful-shutdown", strlen("graceful-shutdown")) == 0) {
|
||||||
|
*val = COMMUNITY_GSHUT;
|
||||||
|
*token = community_token_gshut;
|
||||||
|
p += strlen("graceful-shutdown");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/* Unknown string. */
|
/* Unknown string. */
|
||||||
*token = community_token_unknown;
|
*token = community_token_unknown;
|
||||||
@ -595,6 +612,7 @@ struct community *community_str2com(const char *str)
|
|||||||
case community_token_no_export:
|
case community_token_no_export:
|
||||||
case community_token_no_advertise:
|
case community_token_no_advertise:
|
||||||
case community_token_local_as:
|
case community_token_local_as:
|
||||||
|
case community_token_gshut:
|
||||||
if (com == NULL) {
|
if (com == NULL) {
|
||||||
com = community_new();
|
com = community_new();
|
||||||
com->json = NULL;
|
com->json = NULL;
|
||||||
|
@ -48,6 +48,7 @@ struct community {
|
|||||||
#define COMMUNITY_NO_ADVERTISE 0xFFFFFF02
|
#define COMMUNITY_NO_ADVERTISE 0xFFFFFF02
|
||||||
#define COMMUNITY_NO_EXPORT_SUBCONFED 0xFFFFFF03
|
#define COMMUNITY_NO_EXPORT_SUBCONFED 0xFFFFFF03
|
||||||
#define COMMUNITY_LOCAL_AS 0xFFFFFF03
|
#define COMMUNITY_LOCAL_AS 0xFFFFFF03
|
||||||
|
#define COMMUNITY_GSHUT 0xFFFF0000
|
||||||
|
|
||||||
/* Macros of community attribute. */
|
/* Macros of community attribute. */
|
||||||
#define com_length(X) ((X)->size * 4)
|
#define com_length(X) ((X)->size * 4)
|
||||||
|
124
bgpd/bgp_route.c
124
bgpd/bgp_route.c
@ -1268,6 +1268,39 @@ static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bgp_attr_add_gshut_community(struct attr *attr)
|
||||||
|
{
|
||||||
|
struct community *old;
|
||||||
|
struct community *new;
|
||||||
|
struct community *merge;
|
||||||
|
struct community *gshut;
|
||||||
|
|
||||||
|
old = attr->community;
|
||||||
|
gshut = community_str2com("graceful-shutdown");
|
||||||
|
|
||||||
|
if (old) {
|
||||||
|
merge = community_merge(community_dup(old), gshut);
|
||||||
|
|
||||||
|
if (old->refcnt== 0)
|
||||||
|
community_free(old);
|
||||||
|
|
||||||
|
new = community_uniq_sort(merge);
|
||||||
|
community_free(merge);
|
||||||
|
} else {
|
||||||
|
new = community_dup(gshut);
|
||||||
|
}
|
||||||
|
|
||||||
|
community_free(gshut);
|
||||||
|
attr->community = new;
|
||||||
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
|
||||||
|
|
||||||
|
/* When we add the graceful-shutdown community we must also
|
||||||
|
* lower the local-preference */
|
||||||
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
||||||
|
attr->local_pref = BGP_GSHUT_LOCAL_PREF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void subgroup_announce_reset_nhop(u_char family, struct attr *attr)
|
static void subgroup_announce_reset_nhop(u_char family, struct attr *attr)
|
||||||
{
|
{
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
@ -1624,6 +1657,15 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||||
|
if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
|
||||||
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
||||||
|
attr->local_pref = BGP_GSHUT_LOCAL_PREF;
|
||||||
|
} else {
|
||||||
|
bgp_attr_add_gshut_community(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* After route-map has been applied, we check to see if the nexthop to
|
/* After route-map has been applied, we check to see if the nexthop to
|
||||||
* be carried in the attribute (that is used for the announcement) can
|
* be carried in the attribute (that is used for the announcement) can
|
||||||
* be cleared off or not. We do this in all cases where we would be
|
* be cleared off or not. We do this in all cases where we would be
|
||||||
@ -2737,6 +2779,22 @@ int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
|||||||
goto filtered;
|
goto filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (peer->sort == BGP_PEER_EBGP) {
|
||||||
|
|
||||||
|
/* If we receive the graceful-shutdown community from an eBGP peer we
|
||||||
|
* must lower local-preference */
|
||||||
|
if (new_attr.community &&
|
||||||
|
community_include(new_attr.community, COMMUNITY_GSHUT)) {
|
||||||
|
new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
||||||
|
new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
|
||||||
|
|
||||||
|
/* If graceful-shutdown is configured then add the GSHUT community to
|
||||||
|
* all paths received from eBGP peers */
|
||||||
|
} else if (bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||||
|
bgp_attr_add_gshut_community(&new_attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* next hop check. */
|
/* next hop check. */
|
||||||
if (bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
|
if (bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
|
||||||
reason = "martian or self next-hop;";
|
reason = "martian or self next-hop;";
|
||||||
@ -4057,9 +4115,18 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p,
|
|||||||
bgp_static_withdraw(bgp, p, afi, safi);
|
bgp_static_withdraw(bgp, p, afi, safi);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
|
||||||
|
bgp_attr_add_gshut_community(&attr_tmp);
|
||||||
|
|
||||||
attr_new = bgp_attr_intern(&attr_tmp);
|
attr_new = bgp_attr_intern(&attr_tmp);
|
||||||
} else
|
} else {
|
||||||
|
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
|
||||||
|
bgp_attr_add_gshut_community(&attr);
|
||||||
|
|
||||||
attr_new = bgp_attr_intern(&attr);
|
attr_new = bgp_attr_intern(&attr);
|
||||||
|
}
|
||||||
|
|
||||||
for (ri = rn->info; ri; ri = ri->next)
|
for (ri = rn->info; ri; ri = ri->next)
|
||||||
if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
|
if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
|
||||||
@ -6154,6 +6221,9 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
|
||||||
|
bgp_attr_add_gshut_community(&attr_new);
|
||||||
|
|
||||||
bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
|
bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
|
||||||
SAFI_UNICAST, p, NULL);
|
SAFI_UNICAST, p, NULL);
|
||||||
|
|
||||||
@ -8044,8 +8114,8 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
|
|||||||
static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
|
static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
|
||||||
const char *regstr, afi_t afi,
|
const char *regstr, afi_t afi,
|
||||||
safi_t safi, enum bgp_show_type type);
|
safi_t safi, enum bgp_show_type type);
|
||||||
static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc,
|
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
|
||||||
struct cmd_token **argv, int exact, afi_t afi,
|
const char *comstr, int exact, afi_t afi,
|
||||||
safi_t safi);
|
safi_t safi);
|
||||||
|
|
||||||
static int bgp_show_table(struct vty *vty, struct bgp *bgp,
|
static int bgp_show_table(struct vty *vty, struct bgp *bgp,
|
||||||
@ -8860,7 +8930,7 @@ DEFUN (show_ip_bgp,
|
|||||||
|prefix-list WORD\
|
|prefix-list WORD\
|
||||||
|filter-list WORD\
|
|filter-list WORD\
|
||||||
|statistics\
|
|statistics\
|
||||||
|community <AA:NN|local-AS|no-advertise|no-export> [exact-match]\
|
|community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
|
||||||
|community-list <(1-500)|WORD> [exact-match]\
|
|community-list <(1-500)|WORD> [exact-match]\
|
||||||
|A.B.C.D/M longer-prefixes\
|
|A.B.C.D/M longer-prefixes\
|
||||||
|X:X::X:X/M longer-prefixes\
|
|X:X::X:X/M longer-prefixes\
|
||||||
@ -8885,6 +8955,7 @@ DEFUN (show_ip_bgp,
|
|||||||
"Do not send outside local AS (well-known community)\n"
|
"Do not send outside local AS (well-known community)\n"
|
||||||
"Do not advertise to any peer (well-known community)\n"
|
"Do not advertise to any peer (well-known community)\n"
|
||||||
"Do not export to next AS (well-known community)\n"
|
"Do not export to next AS (well-known community)\n"
|
||||||
|
"Graceful shutdown (well-known community)\n"
|
||||||
"Exact match of the communities\n"
|
"Exact match of the communities\n"
|
||||||
"Display routes matching the community-list\n"
|
"Display routes matching the community-list\n"
|
||||||
"community-list number\n"
|
"community-list number\n"
|
||||||
@ -8900,6 +8971,7 @@ DEFUN (show_ip_bgp,
|
|||||||
int exact_match = 0;
|
int exact_match = 0;
|
||||||
struct bgp *bgp = NULL;
|
struct bgp *bgp = NULL;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
int idx_community_type = 0;
|
||||||
|
|
||||||
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
|
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
|
||||||
&bgp);
|
&bgp);
|
||||||
@ -8928,12 +9000,15 @@ DEFUN (show_ip_bgp,
|
|||||||
|
|
||||||
if (argv_find(argv, argc, "community", &idx)) {
|
if (argv_find(argv, argc, "community", &idx)) {
|
||||||
/* show a specific community */
|
/* show a specific community */
|
||||||
if (argv_find(argv, argc, "local-AS", &idx)
|
if (argv_find(argv, argc, "local-AS", &idx_community_type)
|
||||||
|| argv_find(argv, argc, "no-advertise", &idx)
|
|| argv_find(argv, argc, "no-advertise", &idx_community_type)
|
||||||
|| argv_find(argv, argc, "no-export", &idx)) {
|
|| argv_find(argv, argc, "no-export", &idx_community_type)
|
||||||
if (argv_find(argv, argc, "exact_match", &idx))
|
|| argv_find(argv, argc, "graceful-shutdown", &idx_community_type)
|
||||||
|
|| argv_find(argv, argc, "AA:NN", &idx_community_type)) {
|
||||||
|
|
||||||
|
if (argv_find(argv, argc, "exact-match", &idx))
|
||||||
exact_match = 1;
|
exact_match = 1;
|
||||||
return bgp_show_community(vty, bgp, argc, argv,
|
return bgp_show_community(vty, bgp, argv[idx_community_type]->arg,
|
||||||
exact_match, afi, safi);
|
exact_match, afi, safi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9221,39 +9296,16 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
|
|||||||
return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
|
return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc,
|
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
|
||||||
struct cmd_token **argv, int exact, afi_t afi,
|
const char *comstr, int exact, afi_t afi,
|
||||||
safi_t safi)
|
safi_t safi)
|
||||||
{
|
{
|
||||||
struct community *com;
|
struct community *com;
|
||||||
struct buffer *b;
|
|
||||||
int i;
|
|
||||||
char *str;
|
|
||||||
int first = 0;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
b = buffer_new(1024);
|
com = community_str2com(comstr);
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
if (first)
|
|
||||||
buffer_putc(b, ' ');
|
|
||||||
else {
|
|
||||||
if (strmatch(argv[i]->text, "unicast")
|
|
||||||
|| strmatch(argv[i]->text, "multicast"))
|
|
||||||
continue;
|
|
||||||
first = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_putstr(b, argv[i]->arg);
|
|
||||||
}
|
|
||||||
buffer_putc(b, '\0');
|
|
||||||
|
|
||||||
str = buffer_getstr(b);
|
|
||||||
buffer_free(b);
|
|
||||||
|
|
||||||
com = community_str2com(str);
|
|
||||||
XFREE(MTYPE_TMP, str);
|
|
||||||
if (!com) {
|
if (!com) {
|
||||||
vty_out(vty, "%% Community malformed: \n");
|
vty_out(vty, "%% Community malformed: %s\n", comstr);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,6 +424,7 @@ extern void bgp_info_restore(struct bgp_node *, struct bgp_info *);
|
|||||||
extern int bgp_info_cmp_compatible(struct bgp *, struct bgp_info *,
|
extern int bgp_info_cmp_compatible(struct bgp *, struct bgp_info *,
|
||||||
struct bgp_info *, char *pfx_buf, afi_t afi,
|
struct bgp_info *, char *pfx_buf, afi_t afi,
|
||||||
safi_t safi);
|
safi_t safi);
|
||||||
|
extern void bgp_attr_add_gshut_community(struct attr *attr);
|
||||||
|
|
||||||
extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
|
extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
|
||||||
struct bgp_maxpaths_cfg *mpath_cfg,
|
struct bgp_maxpaths_cfg *mpath_cfg,
|
||||||
|
@ -3771,6 +3771,11 @@ DEFUN (set_community,
|
|||||||
buffer_putstr(b, "no-export");
|
buffer_putstr(b, "no-export");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (strncmp(argv[i]->arg, "graceful-shutdown", strlen(argv[i]->arg))
|
||||||
|
== 0) {
|
||||||
|
buffer_putstr(b, "graceful-shutdown");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
buffer_putstr(b, argv[i]->arg);
|
buffer_putstr(b, argv[i]->arg);
|
||||||
}
|
}
|
||||||
buffer_putc(b, '\0');
|
buffer_putc(b, '\0');
|
||||||
|
@ -691,6 +691,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
|||||||
|
|
||||||
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
||||||
aspath = attr.aspath;
|
aspath = attr.aspath;
|
||||||
|
|
||||||
attr.local_pref = bgp->default_local_pref;
|
attr.local_pref = bgp->default_local_pref;
|
||||||
|
|
||||||
if (afi == AFI_IP)
|
if (afi == AFI_IP)
|
||||||
@ -749,6 +750,11 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
|
|||||||
} else {
|
} else {
|
||||||
if (!CHECK_FLAG(subgrp->sflags,
|
if (!CHECK_FLAG(subgrp->sflags,
|
||||||
SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
|
SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
|
||||||
|
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||||
|
bgp_attr_add_gshut_community(&attr);
|
||||||
|
}
|
||||||
|
|
||||||
SET_FLAG(subgrp->sflags,
|
SET_FLAG(subgrp->sflags,
|
||||||
SUBGRP_STATUS_DEFAULT_ORIGINATE);
|
SUBGRP_STATUS_DEFAULT_ORIGINATE);
|
||||||
subgroup_default_update_packet(subgrp, &attr, from);
|
subgroup_default_update_packet(subgrp, &attr, from);
|
||||||
|
@ -1794,6 +1794,69 @@ DEFUN (no_bgp_graceful_restart_preserve_fw,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bgp_redistribute_redo(struct bgp *bgp)
|
||||||
|
{
|
||||||
|
afi_t afi;
|
||||||
|
int i;
|
||||||
|
struct list *red_list;
|
||||||
|
struct listnode *node;
|
||||||
|
struct bgp_redist *red;
|
||||||
|
|
||||||
|
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||||
|
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||||
|
|
||||||
|
red_list = bgp->redist[afi][i];
|
||||||
|
if (!red_list)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
|
||||||
|
bgp_redistribute_resend(bgp, afi, i,
|
||||||
|
red->instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "bgp graceful-shutdown" configuration */
|
||||||
|
DEFUN (bgp_graceful_shutdown,
|
||||||
|
bgp_graceful_shutdown_cmd,
|
||||||
|
"bgp graceful-shutdown",
|
||||||
|
BGP_STR
|
||||||
|
"Graceful shutdown parameters\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
|
||||||
|
if (!bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||||
|
bgp_flag_set(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN);
|
||||||
|
bgp_static_redo_import_check(bgp);
|
||||||
|
bgp_redistribute_redo(bgp);
|
||||||
|
bgp_clear_star_soft_out(vty, bgp->name);
|
||||||
|
bgp_clear_star_soft_in(vty, bgp->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_bgp_graceful_shutdown,
|
||||||
|
no_bgp_graceful_shutdown_cmd,
|
||||||
|
"no bgp graceful-shutdown",
|
||||||
|
NO_STR
|
||||||
|
BGP_STR
|
||||||
|
"Graceful shutdown parameters\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||||||
|
bgp_flag_unset(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN);
|
||||||
|
bgp_static_redo_import_check(bgp);
|
||||||
|
bgp_redistribute_redo(bgp);
|
||||||
|
bgp_clear_star_soft_out(vty, bgp->name);
|
||||||
|
bgp_clear_star_soft_in(vty, bgp->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* "bgp fast-external-failover" configuration. */
|
/* "bgp fast-external-failover" configuration. */
|
||||||
DEFUN (bgp_fast_external_failover,
|
DEFUN (bgp_fast_external_failover,
|
||||||
bgp_fast_external_failover_cmd,
|
bgp_fast_external_failover_cmd,
|
||||||
@ -10489,6 +10552,7 @@ DEFUN (bgp_redistribute_ipv4,
|
|||||||
vty_out(vty, "%% Invalid route type\n");
|
vty_out(vty, "%% Invalid route type\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bgp_redist_add(bgp, AFI_IP, type, 0);
|
bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
||||||
}
|
}
|
||||||
@ -11359,6 +11423,10 @@ void bgp_vty_init(void)
|
|||||||
install_element(BGP_NODE, &bgp_graceful_restart_preserve_fw_cmd);
|
install_element(BGP_NODE, &bgp_graceful_restart_preserve_fw_cmd);
|
||||||
install_element(BGP_NODE, &no_bgp_graceful_restart_preserve_fw_cmd);
|
install_element(BGP_NODE, &no_bgp_graceful_restart_preserve_fw_cmd);
|
||||||
|
|
||||||
|
/* "bgp graceful-shutdown" commands */
|
||||||
|
install_element(BGP_NODE, &bgp_graceful_shutdown_cmd);
|
||||||
|
install_element(BGP_NODE, &no_bgp_graceful_shutdown_cmd);
|
||||||
|
|
||||||
/* "bgp fast-external-failover" commands */
|
/* "bgp fast-external-failover" commands */
|
||||||
install_element(BGP_NODE, &bgp_fast_external_failover_cmd);
|
install_element(BGP_NODE, &bgp_fast_external_failover_cmd);
|
||||||
install_element(BGP_NODE, &no_bgp_fast_external_failover_cmd);
|
install_element(BGP_NODE, &no_bgp_fast_external_failover_cmd);
|
||||||
|
@ -7185,6 +7185,10 @@ int bgp_config_write(struct vty *vty)
|
|||||||
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART))
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART))
|
||||||
vty_out(vty, " bgp graceful-restart\n");
|
vty_out(vty, " bgp graceful-restart\n");
|
||||||
|
|
||||||
|
/* BGP graceful-shutdown */
|
||||||
|
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
|
||||||
|
vty_out(vty, " bgp graceful-shutdown\n");
|
||||||
|
|
||||||
/* BGP graceful-restart Preserve State F bit. */
|
/* BGP graceful-restart Preserve State F bit. */
|
||||||
if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD))
|
if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD))
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
|
@ -303,6 +303,7 @@ struct bgp {
|
|||||||
#define BGP_FLAG_FORCE_STATIC_PROCESS (1 << 18)
|
#define BGP_FLAG_FORCE_STATIC_PROCESS (1 << 18)
|
||||||
#define BGP_FLAG_SHOW_HOSTNAME (1 << 19)
|
#define BGP_FLAG_SHOW_HOSTNAME (1 << 19)
|
||||||
#define BGP_FLAG_GR_PRESERVE_FWD (1 << 20)
|
#define BGP_FLAG_GR_PRESERVE_FWD (1 << 20)
|
||||||
|
#define BGP_FLAG_GRACEFUL_SHUTDOWN (1 << 21)
|
||||||
|
|
||||||
/* BGP Per AF flags */
|
/* BGP Per AF flags */
|
||||||
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
|
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
|
||||||
@ -1098,6 +1099,10 @@ struct bgp_nlri {
|
|||||||
/* BGP default local preference. */
|
/* BGP default local preference. */
|
||||||
#define BGP_DEFAULT_LOCAL_PREF 100
|
#define BGP_DEFAULT_LOCAL_PREF 100
|
||||||
|
|
||||||
|
/* BGP local-preference to send when 'bgp graceful-shutdown'
|
||||||
|
* is configured */
|
||||||
|
#define BGP_GSHUT_LOCAL_PREF 0
|
||||||
|
|
||||||
/* BGP default subgroup packet queue max . */
|
/* BGP default subgroup packet queue max . */
|
||||||
#define BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX 40
|
#define BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX 40
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user