]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
Merge pull request #11900 from patrasar/pimv6_lmqt
[mirror_frr.git] / bgpd / bgpd.c
CommitLineData
718e3744 1/* BGP-4, BGP-4+ daemon program
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
74ffbfe6 27#include "ringbuf.h"
718e3744 28#include "command.h"
29#include "sockunion.h"
e9a0c656 30#include "sockopt.h"
718e3744 31#include "network.h"
32#include "memory.h"
33#include "filter.h"
34#include "routemap.h"
718e3744 35#include "log.h"
36#include "plist.h"
37#include "linklist.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
88177fe3 40#include "zclient.h"
7f342629 41#include "bfd.h"
dd793e4a
DW
42#include "hash.h"
43#include "jhash.h"
587ff0fd 44#include "table.h"
4dcadbef 45#include "lib/json.h"
4ab46701 46#include "lib/sockopt.h"
0ca8b79f 47#include "frr_pthread.h"
92708db6 48#include "bitfield.h"
718e3744 49
50#include "bgpd/bgpd.h"
51#include "bgpd/bgp_table.h"
52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_route.h"
54#include "bgpd/bgp_dump.h"
55#include "bgpd/bgp_debug.h"
14454c9f 56#include "bgpd/bgp_errors.h"
718e3744 57#include "bgpd/bgp_community.h"
ed0e57e3 58#include "bgpd/bgp_community_alias.h"
7f7940e6 59#include "bgpd/bgp_conditional_adv.h"
718e3744 60#include "bgpd/bgp_attr.h"
61#include "bgpd/bgp_regex.h"
62#include "bgpd/bgp_clist.h"
63#include "bgpd/bgp_fsm.h"
64#include "bgpd/bgp_packet.h"
65#include "bgpd/bgp_zebra.h"
66#include "bgpd/bgp_open.h"
67#include "bgpd/bgp_filter.h"
68#include "bgpd/bgp_nexthop.h"
69#include "bgpd/bgp_damp.h"
70#include "bgpd/bgp_mplsvpn.h"
49e5a4a0 71#ifdef ENABLE_BGP_VNC
f8b6f499
LB
72#include "bgpd/rfapi/bgp_rfapi_cfg.h"
73#include "bgpd/rfapi/rfapi_backend.h"
65efcfce 74#endif
7ef5a232 75#include "bgpd/bgp_evpn.h"
718e3744 76#include "bgpd/bgp_advertise.h"
77#include "bgpd/bgp_network.h"
78#include "bgpd/bgp_vty.h"
165b5fff 79#include "bgpd/bgp_mpath.h"
fc9a856f 80#include "bgpd/bgp_nht.h"
3f9c7369 81#include "bgpd/bgp_updgrp.h"
c43ed2e4 82#include "bgpd/bgp_bfd.h"
4a1ab8e4 83#include "bgpd/bgp_memory.h"
784d3a42 84#include "bgpd/bgp_evpn_vty.h"
2d4ee774 85#include "bgpd/bgp_keepalives.h"
56257a44 86#include "bgpd/bgp_io.h"
41d6d607 87#include "bgpd/bgp_ecommunity.h"
7c40bf39 88#include "bgpd/bgp_flowspec.h"
955bfd98 89#include "bgpd/bgp_labelpool.h"
f3d32faa 90#include "bgpd/bgp_pbr.h"
dcc68b5e 91#include "bgpd/bgp_addpath.h"
85c8d83b 92#include "bgpd/bgp_evpn_private.h"
c44ab6f1 93#include "bgpd/bgp_evpn_mh.h"
48ecf8f5 94#include "bgpd/bgp_mac.h"
73d70fa6
DL
95
96DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
85c8d83b 97DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
96244aca
DL
98DEFINE_QOBJ_TYPE(bgp_master);
99DEFINE_QOBJ_TYPE(bgp);
100DEFINE_QOBJ_TYPE(peer);
8451921b 101DEFINE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));
19df7279 102
718e3744 103/* BGP process wide configuration. */
104static struct bgp_master bgp_master;
105
106/* BGP process wide configuration pointer to export. */
107struct bgp_master *bm;
108
109/* BGP community-list. */
110struct community_list_handler *bgp_clist;
6b0655a2 111
37fe7731
DS
112unsigned int multipath_num = MULTIPATH_NUM;
113
c208c586
S
114/* Number of bgp instances configured for suppress fib config */
115unsigned int bgp_suppress_fib_count;
116
d62a17ae 117static void bgp_if_finish(struct bgp *bgp);
cc32742c 118static void peer_drop_dynamic_neighbor(struct peer *peer);
b33adb7c 119
ad4cbda1 120extern struct zclient *zclient;
1ff9a340 121
e5619c28
PG
122/* handle main socket creation or deletion */
123static int bgp_check_main_socket(bool create, struct bgp *bgp)
124{
125 static int bgp_server_main_created;
85e9cd9a
AMR
126 struct listnode *node;
127 char *address;
e5619c28 128
d8729f8c 129 if (create) {
e5619c28
PG
130 if (bgp_server_main_created)
131 return 0;
85e9cd9a
AMR
132 if (list_isempty(bm->addresses)) {
133 if (bgp_socket(bgp, bm->port, NULL) < 0)
134 return BGP_ERR_INVALID_VALUE;
135 } else {
136 for (ALL_LIST_ELEMENTS_RO(bm->addresses, node, address))
137 if (bgp_socket(bgp, bm->port, address) < 0)
138 return BGP_ERR_INVALID_VALUE;
139 }
e5619c28
PG
140 bgp_server_main_created = 1;
141 return 0;
142 }
143 if (!bgp_server_main_created)
144 return 0;
e5619c28
PG
145 bgp_close();
146 bgp_server_main_created = 0;
147 return 0;
148}
149
d62a17ae 150void bgp_session_reset(struct peer *peer)
1ff9a340 151{
d62a17ae 152 if (peer->doppelganger && (peer->doppelganger->status != Deleted)
153 && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
154 peer_delete(peer->doppelganger);
1ff9a340 155
d62a17ae 156 BGP_EVENT_ADD(peer, BGP_Stop);
1ff9a340
DS
157}
158
159/*
160 * During session reset, we may delete the doppelganger peer, which would
161 * be the next node to the current node. If the session reset was invoked
162 * during walk of peer list, we would end up accessing the freed next
163 * node. This function moves the next node along.
164 */
d62a17ae 165static void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode)
1ff9a340 166{
d62a17ae 167 struct listnode *n;
168 struct peer *npeer;
1ff9a340 169
d62a17ae 170 n = (nnode) ? *nnode : NULL;
171 npeer = (n) ? listgetdata(n) : NULL;
1ff9a340 172
d62a17ae 173 if (peer->doppelganger && (peer->doppelganger->status != Deleted)
174 && !(CHECK_FLAG(peer->doppelganger->flags,
175 PEER_FLAG_CONFIG_NODE))) {
176 if (peer->doppelganger == npeer)
177 /* nnode and *nnode are confirmed to be non-NULL here */
178 *nnode = (*nnode)->next;
179 peer_delete(peer->doppelganger);
180 }
1ff9a340 181
d62a17ae 182 BGP_EVENT_ADD(peer, BGP_Stop);
1ff9a340
DS
183}
184
718e3744 185/* BGP global flag manipulation. */
d62a17ae 186int bgp_option_set(int flag)
187{
188 switch (flag) {
189 case BGP_OPT_NO_FIB:
d62a17ae 190 case BGP_OPT_NO_LISTEN:
0b014ea6 191 case BGP_OPT_NO_ZEBRA:
d62a17ae 192 SET_FLAG(bm->options, flag);
193 break;
194 default:
195 return BGP_ERR_INVALID_FLAG;
196 }
197 return 0;
198}
199
200int bgp_option_unset(int flag)
201{
202 switch (flag) {
d62a17ae 203 /* Fall through. */
0b014ea6 204 case BGP_OPT_NO_ZEBRA:
d62a17ae 205 case BGP_OPT_NO_FIB:
d62a17ae 206 UNSET_FLAG(bm->options, flag);
207 break;
208 default:
209 return BGP_ERR_INVALID_FLAG;
210 }
211 return 0;
212}
213
214int bgp_option_check(int flag)
215{
216 return CHECK_FLAG(bm->options, flag);
718e3744 217}
6b0655a2 218
c163f297
DS
219/* set the bgp no-rib option during runtime and remove installed routes */
220void bgp_option_norib_set_runtime(void)
221{
222 struct bgp *bgp;
223 struct listnode *node;
224 afi_t afi;
225 safi_t safi;
226
227 if (bgp_option_check(BGP_OPT_NO_FIB))
228 return;
229
230 bgp_option_set(BGP_OPT_NO_FIB);
231
232 zlog_info("Disabled BGP route installation to RIB (Zebra)");
233
234 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
56b91d10
DS
235 FOREACH_AFI_SAFI (afi, safi) {
236 /*
237 * Stop a crash, more work is needed
238 * here to properly add/remove these types of
239 * routes from zebra.
240 */
241 if (!bgp_fibupd_safi(safi))
242 continue;
243
c163f297 244 bgp_zebra_withdraw_table_all_subtypes(bgp, afi, safi);
56b91d10 245 }
c163f297
DS
246 }
247
248 zlog_info("All routes have been withdrawn from RIB (Zebra)");
249}
250
251/* unset the bgp no-rib option during runtime and announce routes to Zebra */
252void bgp_option_norib_unset_runtime(void)
253{
254 struct bgp *bgp;
255 struct listnode *node;
256 afi_t afi;
257 safi_t safi;
258
259 if (!bgp_option_check(BGP_OPT_NO_FIB))
260 return;
261
262 bgp_option_unset(BGP_OPT_NO_FIB);
263
264 zlog_info("Enabled BGP route installation to RIB (Zebra)");
265
266 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
56b91d10
DS
267 FOREACH_AFI_SAFI (afi, safi) {
268 /*
269 * Stop a crash, more work is needed
270 * here to properly add/remove these types
271 * of routes from zebra
272 */
273 if (!bgp_fibupd_safi(safi))
274 continue;
275
c163f297 276 bgp_zebra_announce_table_all_subtypes(bgp, afi, safi);
56b91d10 277 }
c163f297
DS
278 }
279
280 zlog_info("All routes have been installed in RIB (Zebra)");
281}
282
718e3744 283/* Internal function to set BGP structure configureation flag. */
d62a17ae 284static void bgp_config_set(struct bgp *bgp, int config)
718e3744 285{
d62a17ae 286 SET_FLAG(bgp->config, config);
718e3744 287}
288
d62a17ae 289static void bgp_config_unset(struct bgp *bgp, int config)
718e3744 290{
d62a17ae 291 UNSET_FLAG(bgp->config, config);
718e3744 292}
293
d62a17ae 294static int bgp_config_check(struct bgp *bgp, int config)
718e3744 295{
d62a17ae 296 return CHECK_FLAG(bgp->config, config);
718e3744 297}
6b0655a2 298
e65fe398
MS
299/* Set BGP router identifier; distinguish between explicit config and other
300 * cases.
301 */
302static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id,
303 bool is_config)
718e3744 304{
d62a17ae 305 struct peer *peer;
306 struct listnode *node, *nnode;
718e3744 307
d62a17ae 308 if (IPV4_ADDR_SAME(&bgp->router_id, id))
309 return 0;
718e3744 310
d62a17ae 311 /* EVPN uses router id in RD, withdraw them */
94c2f693 312 if (is_evpn_enabled())
2951a7a4 313 bgp_evpn_handle_router_id_update(bgp, true);
2d48ee25 314
2951a7a4 315 vpn_handle_router_id_update(bgp, true, is_config);
636f7608 316
d62a17ae 317 IPV4_ADDR_COPY(&bgp->router_id, id);
718e3744 318
d62a17ae 319 /* Set all peer's local identifier with this value. */
320 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
321 IPV4_ADDR_COPY(&peer->local_id, id);
718e3744 322
d62a17ae 323 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
324 peer->last_reset = PEER_DOWN_RID_CHANGE;
325 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
326 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
327 }
328 }
14c1a7bf 329
d62a17ae 330 /* EVPN uses router id in RD, update them */
94c2f693 331 if (is_evpn_enabled())
2951a7a4 332 bgp_evpn_handle_router_id_update(bgp, false);
2d48ee25 333
2951a7a4 334 vpn_handle_router_id_update(bgp, false, is_config);
636f7608 335
d62a17ae 336 return 0;
718e3744 337}
338
d62a17ae 339void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id)
0e6cb743 340{
d62a17ae 341 struct listnode *node, *nnode;
342 struct bgp *bgp;
36dc7588 343 struct in_addr *addr = NULL;
344
345 if (router_id != NULL)
346 addr = (struct in_addr *)&(router_id->u.prefix4);
0e6cb743 347
d62a17ae 348 if (vrf_id == VRF_DEFAULT) {
349 /* Router-id change for default VRF has to also update all
350 * views. */
351 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
352 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
353 continue;
0e6cb743 354
36dc7588 355 if (addr)
356 bgp->router_id_zebra = *addr;
357 else
358 addr = &bgp->router_id_zebra;
359
360 if (!bgp->router_id_static.s_addr) {
361 /* Router ID is updated if there are no active
362 * peer sessions
363 */
364 if (bgp->established_peers == 0) {
365 if (BGP_DEBUG(zebra, ZEBRA))
137147c6 366 zlog_debug(
23d0a753 367 "RID change : vrf %s(%u), RTR ID %pI4",
137147c6 368 bgp->name_pretty,
23d0a753 369 bgp->vrf_id, addr);
3c2a1ad1
DS
370 /*
371 * if old router-id was 0x0, set flag
372 * to use this new value
373 */
374 bgp_router_id_set(bgp, addr,
375 (bgp->router_id.s_addr
376 == INADDR_ANY)
377 ? true
378 : false);
36dc7588 379 }
380 }
d62a17ae 381 }
382 } else {
383 bgp = bgp_lookup_by_vrf_id(vrf_id);
384 if (bgp) {
36dc7588 385 if (addr)
386 bgp->router_id_zebra = *addr;
387 else
388 addr = &bgp->router_id_zebra;
389
390 if (!bgp->router_id_static.s_addr) {
391 /* Router ID is updated if there are no active
392 * peer sessions
393 */
394 if (bgp->established_peers == 0) {
395 if (BGP_DEBUG(zebra, ZEBRA))
137147c6 396 zlog_debug(
23d0a753 397 "RID change : vrf %s(%u), RTR ID %pI4",
137147c6 398 bgp->name_pretty,
23d0a753 399 bgp->vrf_id, addr);
3c2a1ad1
DS
400 /*
401 * if old router-id was 0x0, set flag
402 * to use this new value
403 */
404 bgp_router_id_set(bgp, addr,
405 (bgp->router_id.s_addr
406 == INADDR_ANY)
407 ? true
408 : false);
36dc7588 409 }
410 }
0e6cb743 411
d62a17ae 412 }
413 }
0e6cb743
DL
414}
415
3dc339cd 416void bgp_router_id_static_set(struct bgp *bgp, struct in_addr id)
0e6cb743 417{
d62a17ae 418 bgp->router_id_static = id;
975a328e
DA
419 bgp_router_id_set(bgp,
420 id.s_addr != INADDR_ANY ? &id : &bgp->router_id_zebra,
2951a7a4 421 true /* is config */);
0e6cb743
DL
422}
423
9acb67cb
DS
424void bm_wait_for_fib_set(bool set)
425{
426 bool send_msg = false;
427
428 if (bm->wait_for_fib == set)
429 return;
430
431 bm->wait_for_fib = set;
432 if (set) {
433 if (bgp_suppress_fib_count == 0)
434 send_msg = true;
435 bgp_suppress_fib_count++;
436 } else {
437 bgp_suppress_fib_count--;
438 if (bgp_suppress_fib_count == 0)
439 send_msg = true;
440 }
441
442 if (send_msg && zclient)
443 zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST,
444 zclient, set);
445}
446
c208c586
S
447/* Set the suppress fib pending for the bgp configuration */
448void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
449{
450 bool send_msg = false;
451
452 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
453 return;
454
455 if (set) {
456 SET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING);
457 /* Send msg to zebra for the first instance of bgp enabled
458 * with suppress fib
459 */
460 if (bgp_suppress_fib_count == 0)
461 send_msg = true;
462 bgp_suppress_fib_count++;
463 } else {
464 UNSET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING);
465 bgp_suppress_fib_count--;
466
467 /* Send msg to zebra if there are no instances enabled
468 * with suppress fib
469 */
470 if (bgp_suppress_fib_count == 0)
471 send_msg = true;
472 }
473 /* Send route notify request to RIB */
474 if (send_msg) {
475 if (BGP_DEBUG(zebra, ZEBRA))
476 zlog_debug("Sending ZEBRA_ROUTE_NOTIFY_REQUEST");
477
478 if (zclient)
479 zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST,
480 zclient, set);
481 }
482}
483
718e3744 484/* BGP's cluster-id control. */
0b1fb52c 485void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
718e3744 486{
d62a17ae 487 struct peer *peer;
488 struct listnode *node, *nnode;
718e3744 489
1ca2fd11
IR
490 if (bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID)
491 && IPV4_ADDR_SAME(&bgp->cluster_id, cluster_id))
0b1fb52c 492 return;
1ca2fd11 493
d62a17ae 494 IPV4_ADDR_COPY(&bgp->cluster_id, cluster_id);
495 bgp_config_set(bgp, BGP_CONFIG_CLUSTER_ID);
718e3744 496
d62a17ae 497 /* Clear all IBGP peer. */
498 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
499 if (peer->sort != BGP_PEER_IBGP)
500 continue;
718e3744 501
d62a17ae 502 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
503 peer->last_reset = PEER_DOWN_CLID_CHANGE;
504 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
505 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
506 }
507 }
718e3744 508}
509
0b1fb52c 510void bgp_cluster_id_unset(struct bgp *bgp)
718e3744 511{
d62a17ae 512 struct peer *peer;
513 struct listnode *node, *nnode;
718e3744 514
d62a17ae 515 if (!bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID))
0b1fb52c 516 return;
718e3744 517
d62a17ae 518 bgp->cluster_id.s_addr = 0;
519 bgp_config_unset(bgp, BGP_CONFIG_CLUSTER_ID);
718e3744 520
d62a17ae 521 /* Clear all IBGP peer. */
522 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
523 if (peer->sort != BGP_PEER_IBGP)
524 continue;
718e3744 525
d62a17ae 526 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
527 peer->last_reset = PEER_DOWN_CLID_CHANGE;
528 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
529 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
530 }
531 }
718e3744 532}
6b0655a2 533
718e3744 534/* BGP timer configuration. */
3dc339cd 535void bgp_timers_set(struct bgp *bgp, uint32_t keepalive, uint32_t holdtime,
6c537a18 536 uint32_t connect_retry, uint32_t delayopen)
718e3744 537{
d62a17ae 538 bgp->default_keepalive =
539 (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
540 bgp->default_holdtime = holdtime;
5d5393b9 541 bgp->default_connect_retry = connect_retry;
6c537a18 542 bgp->default_delayopen = delayopen;
718e3744 543}
544
5d5393b9 545/* mostly for completeness - CLI uses its own defaults */
3dc339cd 546void bgp_timers_unset(struct bgp *bgp)
718e3744 547{
d62a17ae 548 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
549 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
5d5393b9 550 bgp->default_connect_retry = BGP_DEFAULT_CONNECT_RETRY;
6c537a18 551 bgp->default_delayopen = BGP_DEFAULT_DELAYOPEN;
718e3744 552}
6b0655a2 553
718e3744 554/* BGP confederation configuration. */
ff8a8a7a 555void bgp_confederation_id_set(struct bgp *bgp, as_t as)
d62a17ae 556{
557 struct peer *peer;
558 struct listnode *node, *nnode;
559 int already_confed;
560
561 if (as == 0)
ff8a8a7a 562 return;
d62a17ae 563
564 /* Remember - were we doing confederation before? */
565 already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION);
566 bgp->confed_id = as;
567 bgp_config_set(bgp, BGP_CONFIG_CONFEDERATION);
568
569 /* If we were doing confederation already, this is just an external
570 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
571 were not doing confederation before, reset all EBGP sessions. */
572 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
3061acc2 573 enum bgp_peer_sort ptype = peer_sort(peer);
469cbb0f 574
d62a17ae 575 /* We're looking for peers who's AS is not local or part of our
576 confederation. */
577 if (already_confed) {
469cbb0f 578 if (ptype == BGP_PEER_EBGP) {
d62a17ae 579 peer->local_as = as;
580 if (BGP_IS_VALID_STATE_FOR_NOTIF(
581 peer->status)) {
582 peer->last_reset =
583 PEER_DOWN_CONFED_ID_CHANGE;
584 bgp_notify_send(
585 peer, BGP_NOTIFY_CEASE,
586 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
587 } else
588 bgp_session_reset_safe(peer, &nnode);
589 }
590 } else {
591 /* Not doign confederation before, so reset every
592 non-local
593 session */
469cbb0f 594 if (ptype != BGP_PEER_IBGP) {
d62a17ae 595 /* Reset the local_as to be our EBGP one */
469cbb0f 596 if (ptype == BGP_PEER_EBGP)
d62a17ae 597 peer->local_as = as;
598 if (BGP_IS_VALID_STATE_FOR_NOTIF(
599 peer->status)) {
600 peer->last_reset =
601 PEER_DOWN_CONFED_ID_CHANGE;
602 bgp_notify_send(
603 peer, BGP_NOTIFY_CEASE,
604 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
605 } else
606 bgp_session_reset_safe(peer, &nnode);
607 }
608 }
718e3744 609 }
ff8a8a7a 610 return;
718e3744 611}
612
0b1fb52c 613void bgp_confederation_id_unset(struct bgp *bgp)
718e3744 614{
d62a17ae 615 struct peer *peer;
616 struct listnode *node, *nnode;
617
618 bgp->confed_id = 0;
619 bgp_config_unset(bgp, BGP_CONFIG_CONFEDERATION);
718e3744 620
d62a17ae 621 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
622 /* We're looking for peers who's AS is not local */
623 if (peer_sort(peer) != BGP_PEER_IBGP) {
624 peer->local_as = bgp->as;
625 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
626 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
627 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
628 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
629 }
718e3744 630
d62a17ae 631 else
632 bgp_session_reset_safe(peer, &nnode);
633 }
634 }
718e3744 635}
636
d62a17ae 637/* Is an AS part of the confed or not? */
3dc339cd 638bool bgp_confederation_peers_check(struct bgp *bgp, as_t as)
718e3744 639{
d62a17ae 640 int i;
718e3744 641
d62a17ae 642 if (!bgp)
3dc339cd 643 return false;
718e3744 644
d62a17ae 645 for (i = 0; i < bgp->confed_peers_cnt; i++)
646 if (bgp->confed_peers[i] == as)
3dc339cd 647 return true;
718e3744 648
3dc339cd 649 return false;
d62a17ae 650}
718e3744 651
d62a17ae 652/* Add an AS to the confederation set. */
0b1fb52c 653void bgp_confederation_peers_add(struct bgp *bgp, as_t as)
d62a17ae 654{
655 struct peer *peer;
656 struct listnode *node, *nnode;
657
d62a17ae 658 if (bgp->as == as)
0b1fb52c 659 return;
d62a17ae 660
661 if (bgp_confederation_peers_check(bgp, as))
0b1fb52c 662 return;
d62a17ae 663
0b04fa0e
DS
664 bgp->confed_peers =
665 XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers,
666 (bgp->confed_peers_cnt + 1) * sizeof(as_t));
d62a17ae 667
668 bgp->confed_peers[bgp->confed_peers_cnt] = as;
669 bgp->confed_peers_cnt++;
670
671 if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
672 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
673 if (peer->as == as) {
b50a0610 674 (void)peer_sort(peer);
d62a17ae 675 peer->local_as = bgp->as;
676 if (BGP_IS_VALID_STATE_FOR_NOTIF(
677 peer->status)) {
678 peer->last_reset =
679 PEER_DOWN_CONFED_PEER_CHANGE;
680 bgp_notify_send(
681 peer, BGP_NOTIFY_CEASE,
682 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
683 } else
684 bgp_session_reset_safe(peer, &nnode);
685 }
686 }
687 }
718e3744 688}
689
690/* Delete an AS from the confederation set. */
0b1fb52c 691void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
d62a17ae 692{
693 int i;
694 int j;
695 struct peer *peer;
696 struct listnode *node, *nnode;
697
698 if (!bgp)
0b1fb52c 699 return;
d62a17ae 700
701 if (!bgp_confederation_peers_check(bgp, as))
0b1fb52c 702 return;
d62a17ae 703
704 for (i = 0; i < bgp->confed_peers_cnt; i++)
705 if (bgp->confed_peers[i] == as)
706 for (j = i + 1; j < bgp->confed_peers_cnt; j++)
707 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
708
709 bgp->confed_peers_cnt--;
710
711 if (bgp->confed_peers_cnt == 0) {
712 if (bgp->confed_peers)
713 XFREE(MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
714 bgp->confed_peers = NULL;
715 } else
716 bgp->confed_peers =
717 XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers,
718 bgp->confed_peers_cnt * sizeof(as_t));
719
720 /* Now reset any peer who's remote AS has just been removed from the
721 CONFED */
722 if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
723 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
724 if (peer->as == as) {
b50a0610 725 (void)peer_sort(peer);
d62a17ae 726 peer->local_as = bgp->confed_id;
727 if (BGP_IS_VALID_STATE_FOR_NOTIF(
728 peer->status)) {
729 peer->last_reset =
730 PEER_DOWN_CONFED_PEER_CHANGE;
731 bgp_notify_send(
732 peer, BGP_NOTIFY_CEASE,
733 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
734 } else
735 bgp_session_reset_safe(peer, &nnode);
736 }
737 }
718e3744 738 }
718e3744 739}
6b0655a2 740
718e3744 741/* Local preference configuration. */
0b1fb52c 742void bgp_default_local_preference_set(struct bgp *bgp, uint32_t local_pref)
718e3744 743{
d62a17ae 744 if (!bgp)
0b1fb52c 745 return;
718e3744 746
d62a17ae 747 bgp->default_local_pref = local_pref;
718e3744 748}
749
0b1fb52c 750void bgp_default_local_preference_unset(struct bgp *bgp)
718e3744 751{
d62a17ae 752 if (!bgp)
0b1fb52c 753 return;
718e3744 754
d62a17ae 755 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
718e3744 756}
6b0655a2 757
3f9c7369 758/* Local preference configuration. */
0b1fb52c
DA
759void bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp,
760 uint32_t queue_size)
3f9c7369 761{
d62a17ae 762 if (!bgp)
0b1fb52c 763 return;
3f9c7369 764
d62a17ae 765 bgp->default_subgroup_pkt_queue_max = queue_size;
3f9c7369
DS
766}
767
0b1fb52c 768void bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp)
3f9c7369 769{
d62a17ae 770 if (!bgp)
0b1fb52c 771 return;
d62a17ae 772 bgp->default_subgroup_pkt_queue_max =
773 BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
3f9c7369
DS
774}
775
f14e6fdb 776/* Listen limit configuration. */
0b1fb52c 777void bgp_listen_limit_set(struct bgp *bgp, int listen_limit)
f14e6fdb 778{
d62a17ae 779 if (!bgp)
0b1fb52c 780 return;
f14e6fdb 781
d62a17ae 782 bgp->dynamic_neighbors_limit = listen_limit;
f14e6fdb
DS
783}
784
0b1fb52c 785void bgp_listen_limit_unset(struct bgp *bgp)
f14e6fdb 786{
d62a17ae 787 if (!bgp)
0b1fb52c 788 return;
f14e6fdb 789
d62a17ae 790 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
f14e6fdb
DS
791}
792
5c525538
RW
793int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
794 afi_t *afi, safi_t *safi)
9cabb64b 795{
d62a17ae 796 /* Map from IANA values to internal values, return error if
797 * values are unrecognized.
798 */
799 *afi = afi_iana2int(pkt_afi);
800 *safi = safi_iana2int(pkt_safi);
801 if (*afi == AFI_MAX || *safi == SAFI_MAX)
802 return -1;
9cabb64b 803
d62a17ae 804 return 0;
9cabb64b 805}
806
d62a17ae 807int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi, iana_afi_t *pkt_afi,
5c525538 808 iana_safi_t *pkt_safi)
9cabb64b 809{
d62a17ae 810 /* Map from internal values to IANA values, return error if
811 * internal values are bad (unexpected).
812 */
813 if (afi == AFI_MAX || safi == SAFI_MAX)
814 return -1;
815 *pkt_afi = afi_int2iana(afi);
816 *pkt_safi = safi_int2iana(safi);
817 return 0;
9cabb64b 818}
819
d62a17ae 820struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
3f9c7369 821{
d62a17ae 822 struct peer_af *af;
823 int afid;
210ec2a0 824 struct bgp *bgp;
3f9c7369 825
d62a17ae 826 if (!peer)
827 return NULL;
3f9c7369 828
d62a17ae 829 afid = afindex(afi, safi);
830 if (afid >= BGP_AF_MAX)
831 return NULL;
3f9c7369 832
210ec2a0 833 bgp = peer->bgp;
d62a17ae 834 assert(peer->peer_af_array[afid] == NULL);
3f9c7369 835
d62a17ae 836 /* Allocate new peer af */
837 af = XCALLOC(MTYPE_BGP_PEER_AF, sizeof(struct peer_af));
c8560b44 838
d62a17ae 839 peer->peer_af_array[afid] = af;
840 af->afi = afi;
841 af->safi = safi;
842 af->afid = afid;
843 af->peer = peer;
210ec2a0 844 bgp->af_peer_count[afi][safi]++;
3f9c7369 845
d62a17ae 846 return af;
3f9c7369
DS
847}
848
d62a17ae 849struct peer_af *peer_af_find(struct peer *peer, afi_t afi, safi_t safi)
3f9c7369 850{
d62a17ae 851 int afid;
3f9c7369 852
d62a17ae 853 if (!peer)
854 return NULL;
3f9c7369 855
d62a17ae 856 afid = afindex(afi, safi);
857 if (afid >= BGP_AF_MAX)
858 return NULL;
3f9c7369 859
d62a17ae 860 return peer->peer_af_array[afid];
3f9c7369
DS
861}
862
d62a17ae 863int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
3f9c7369 864{
d62a17ae 865 struct peer_af *af;
866 int afid;
210ec2a0 867 struct bgp *bgp;
3f9c7369 868
d62a17ae 869 if (!peer)
870 return -1;
3f9c7369 871
d62a17ae 872 afid = afindex(afi, safi);
873 if (afid >= BGP_AF_MAX)
874 return -1;
3f9c7369 875
d62a17ae 876 af = peer->peer_af_array[afid];
877 if (!af)
878 return -1;
3f9c7369 879
210ec2a0 880 bgp = peer->bgp;
46aeabed
LS
881 bgp_soft_reconfig_table_task_cancel(bgp, bgp->rib[afi][safi], peer);
882
d62a17ae 883 bgp_stop_announce_route_timer(af);
3f9c7369 884
d62a17ae 885 if (PAF_SUBGRP(af)) {
886 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
887 zlog_debug("u%" PRIu64 ":s%" PRIu64 " remove peer %s",
888 af->subgroup->update_group->id,
889 af->subgroup->id, peer->host);
890 }
3f9c7369 891
210ec2a0 892
d62a17ae 893 update_subgroup_remove_peer(af->subgroup, af);
3f9c7369 894
210ec2a0
AS
895 if (bgp->af_peer_count[afi][safi])
896 bgp->af_peer_count[afi][safi]--;
897
d62a17ae 898 peer->peer_af_array[afid] = NULL;
899 XFREE(MTYPE_BGP_PEER_AF, af);
900 return 0;
3f9c7369
DS
901}
902
eb821189 903/* Peer comparison function for sorting. */
d62a17ae 904int peer_cmp(struct peer *p1, struct peer *p2)
718e3744 905{
d62a17ae 906 if (p1->group && !p2->group)
907 return -1;
0aaa34db 908
d62a17ae 909 if (!p1->group && p2->group)
910 return 1;
0aaa34db 911
d62a17ae 912 if (p1->group == p2->group) {
913 if (p1->conf_if && !p2->conf_if)
914 return -1;
0aaa34db 915
d62a17ae 916 if (!p1->conf_if && p2->conf_if)
917 return 1;
0aaa34db 918
d62a17ae 919 if (p1->conf_if && p2->conf_if)
920 return if_cmp_name_func(p1->conf_if, p2->conf_if);
921 } else
922 return strcmp(p1->group->name, p2->group->name);
0aaa34db 923
d62a17ae 924 return sockunion_cmp(&p1->su, &p2->su);
718e3744 925}
926
d8b87afe 927static unsigned int peer_hash_key_make(const void *p)
dd793e4a 928{
d8b87afe 929 const struct peer *peer = p;
d62a17ae 930 return sockunion_hash(&peer->su);
dd793e4a
DW
931}
932
74df8d6d 933static bool peer_hash_same(const void *p1, const void *p2)
dd793e4a 934{
d62a17ae 935 const struct peer *peer1 = p1;
936 const struct peer *peer2 = p2;
937 return (sockunion_same(&peer1->su, &peer2->su)
938 && CHECK_FLAG(peer1->flags, PEER_FLAG_CONFIG_NODE)
939 == CHECK_FLAG(peer2->flags, PEER_FLAG_CONFIG_NODE));
dd793e4a
DW
940}
941
83194f39 942void peer_flag_inherit(struct peer *peer, uint64_t flag)
9fb964de
PM
943{
944 bool group_val;
945
946 /* Skip if peer is not a peer-group member. */
947 if (!peer_group_active(peer))
948 return;
949
950 /* Unset override flag to signal inheritance from peer-group. */
951 UNSET_FLAG(peer->flags_override, flag);
952
953 /*
954 * Inherit flag state from peer-group. If the flag of the peer-group is
955 * not being inverted, the peer must inherit the inverse of the current
956 * peer-group flag state.
957 */
958 group_val = CHECK_FLAG(peer->group->conf->flags, flag);
959 if (!CHECK_FLAG(peer->group->conf->flags_invert, flag)
960 && CHECK_FLAG(peer->flags_invert, flag))
961 COND_FLAG(peer->flags, flag, !group_val);
962 else
963 COND_FLAG(peer->flags, flag, group_val);
964}
965
d7c0a89a 966int peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
718e3744 967{
d62a17ae 968 return CHECK_FLAG(peer->af_flags[afi][safi], flag);
718e3744 969}
970
598ce6bd 971void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
da5e1a58 972 uint64_t flag)
88b8ed8d 973{
527de3dc
PM
974 bool group_val;
975
598ce6bd
PM
976 /* Skip if peer is not a peer-group member. */
977 if (!peer_group_active(peer))
978 return;
88b8ed8d 979
598ce6bd
PM
980 /* Unset override flag to signal inheritance from peer-group. */
981 UNSET_FLAG(peer->af_flags_override[afi][safi], flag);
88b8ed8d 982
527de3dc
PM
983 /*
984 * Inherit flag state from peer-group. If the flag of the peer-group is
985 * not being inverted, the peer must inherit the inverse of the current
986 * peer-group flag state.
987 */
988 group_val = CHECK_FLAG(peer->group->conf->af_flags[afi][safi], flag);
989 if (!CHECK_FLAG(peer->group->conf->af_flags_invert[afi][safi], flag)
990 && CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
991 COND_FLAG(peer->af_flags[afi][safi], flag, !group_val);
598ce6bd 992 else
527de3dc 993 COND_FLAG(peer->af_flags[afi][safi], flag, group_val);
598ce6bd 994}
88b8ed8d 995
6d85b15b 996/* Check peer's AS number and determines if this peer is IBGP or EBGP */
3061acc2 997static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
718e3744 998{
d62a17ae 999 struct bgp *bgp;
718e3744 1000
d62a17ae 1001 bgp = peer->bgp;
718e3744 1002
d62a17ae 1003 /* Peer-group */
1004 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
1005 if (peer->as_type == AS_INTERNAL)
1006 return BGP_PEER_IBGP;
66b199b2 1007
d62a17ae 1008 else if (peer->as_type == AS_EXTERNAL)
1009 return BGP_PEER_EBGP;
66b199b2 1010
b575a12c
A
1011 else if (peer->as_type == AS_SPECIFIED && peer->as) {
1012 assert(bgp);
d62a17ae 1013 return (bgp->as == peer->as ? BGP_PEER_IBGP
1014 : BGP_PEER_EBGP);
b575a12c 1015 }
66b199b2 1016
d62a17ae 1017 else {
1018 struct peer *peer1;
d4f8b537 1019
1020 assert(peer->group);
d62a17ae 1021 peer1 = listnode_head(peer->group->peer);
1022
1023 if (peer1)
1024 return peer1->sort;
1025 }
1026 return BGP_PEER_INTERNAL;
1027 }
1028
1029 /* Normal peer */
1030 if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1031 if (peer->local_as == 0)
1032 return BGP_PEER_INTERNAL;
1033
1034 if (peer->local_as == peer->as) {
1035 if (bgp->as == bgp->confed_id) {
1036 if (peer->local_as == bgp->as)
1037 return BGP_PEER_IBGP;
1038 else
1039 return BGP_PEER_EBGP;
1040 } else {
1041 if (peer->local_as == bgp->confed_id)
1042 return BGP_PEER_EBGP;
1043 else
1044 return BGP_PEER_IBGP;
1045 }
1046 }
1047
1048 if (bgp_confederation_peers_check(bgp, peer->as))
1049 return BGP_PEER_CONFED;
1050
1051 return BGP_PEER_EBGP;
1052 } else {
faa16034
DS
1053 if (peer->as_type == AS_UNSPECIFIED) {
1054 /* check if in peer-group with AS information */
1055 if (peer->group
1056 && (peer->group->conf->as_type != AS_UNSPECIFIED)) {
1057 if (peer->group->conf->as_type
1058 == AS_SPECIFIED) {
1059 if (peer->local_as
1060 == peer->group->conf->as)
1061 return BGP_PEER_IBGP;
1062 else
1063 return BGP_PEER_EBGP;
1064 } else if (peer->group->conf->as_type
1065 == AS_INTERNAL)
1066 return BGP_PEER_IBGP;
1067 else
1068 return BGP_PEER_EBGP;
1069 }
1070 /* no AS information anywhere, let caller know */
1071 return BGP_PEER_UNSPECIFIED;
1072 } else if (peer->as_type != AS_SPECIFIED)
d62a17ae 1073 return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
1074 : BGP_PEER_EBGP);
1075
1076 return (peer->local_as == 0
1077 ? BGP_PEER_INTERNAL
1078 : peer->local_as == peer->as ? BGP_PEER_IBGP
1079 : BGP_PEER_EBGP);
1080 }
718e3744 1081}
1082
6d85b15b 1083/* Calculate and cache the peer "sort" */
3061acc2 1084enum bgp_peer_sort peer_sort(struct peer *peer)
d62a17ae 1085{
1086 peer->sort = peer_calc_sort(peer);
1087 return peer->sort;
1088}
1089
3061acc2 1090enum bgp_peer_sort peer_sort_lookup(struct peer *peer)
bf0d28dc
DS
1091{
1092 return peer->sort;
1093}
1094
d62a17ae 1095static void peer_free(struct peer *peer)
1096{
dcc68b5e
MS
1097 afi_t afi;
1098 safi_t safi;
1099
d62a17ae 1100 assert(peer->status == Deleted);
1101
1102 QOBJ_UNREG(peer);
1103
1104 /* this /ought/ to have been done already through bgp_stop earlier,
1105 * but just to be sure..
1106 */
1107 bgp_timer_set(peer);
424ab01d
QY
1108 bgp_reads_off(peer);
1109 bgp_writes_off(peer);
1110 assert(!peer->t_write);
1111 assert(!peer->t_read);
d62a17ae 1112 BGP_EVENT_FLUSH(peer);
1113
424ab01d
QY
1114 pthread_mutex_destroy(&peer->io_mtx);
1115
d62a17ae 1116 /* Free connected nexthop, if present */
1117 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
1118 && !peer_dynamic_neighbor(peer))
1119 bgp_delete_connected_nexthop(family2afi(peer->su.sa.sa_family),
1120 peer);
1121
3d1c148b
DS
1122 FOREACH_AFI_SAFI (afi, safi) {
1123 if (peer->filter[afi][safi].advmap.aname)
1124 XFREE(MTYPE_BGP_FILTER_NAME,
1125 peer->filter[afi][safi].advmap.aname);
1126 if (peer->filter[afi][safi].advmap.cname)
1127 XFREE(MTYPE_BGP_FILTER_NAME,
1128 peer->filter[afi][safi].advmap.cname);
1129 }
1130
d62a17ae 1131 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
1132
e1b36e13
QY
1133 XFREE(MTYPE_PEER_DESC, peer->desc);
1134 XFREE(MTYPE_BGP_PEER_HOST, peer->host);
1135 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
1136 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
d62a17ae 1137
1138 /* Update source configuration. */
1139 if (peer->update_source) {
1140 sockunion_free(peer->update_source);
1141 peer->update_source = NULL;
1142 }
1143
e1b36e13 1144 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
d62a17ae 1145
eea685b6 1146 XFREE(MTYPE_BGP_NOTIFICATION, peer->notify.data);
d62a17ae 1147 memset(&peer->notify, 0, sizeof(struct bgp_notify));
1148
e208c8f9
DS
1149 if (peer->clear_node_queue)
1150 work_queue_free_and_null(&peer->clear_node_queue);
d62a17ae 1151
1152 bgp_sync_delete(peer);
1153
e1b36e13 1154 XFREE(MTYPE_PEER_CONF_IF, peer->conf_if);
d62a17ae 1155
21bfce98
RZ
1156 /* Remove BFD configuration. */
1157 if (peer->bfd_config)
1158 bgp_peer_remove_bfd_config(peer);
d62a17ae 1159
3d1c148b
DS
1160 FOREACH_AFI_SAFI (afi, safi)
1161 bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE);
dcc68b5e 1162
d62a17ae 1163 bgp_unlock(peer->bgp);
1164
1165 memset(peer, 0, sizeof(struct peer));
1166
1167 XFREE(MTYPE_BGP_PEER, peer);
1168}
1169
200df115 1170/* increase reference count on a struct peer */
d62a17ae 1171struct peer *peer_lock_with_caller(const char *name, struct peer *peer)
200df115 1172{
d62a17ae 1173 assert(peer && (peer->lock >= 0));
28066f4b 1174
d62a17ae 1175 peer->lock++;
1176
1177 return peer;
200df115 1178}
1179
1180/* decrease reference count on a struct peer
1181 * struct peer is freed and NULL returned if last reference
1182 */
d62a17ae 1183struct peer *peer_unlock_with_caller(const char *name, struct peer *peer)
200df115 1184{
d62a17ae 1185 assert(peer && (peer->lock > 0));
28066f4b 1186
d62a17ae 1187 peer->lock--;
1188
1189 if (peer->lock == 0) {
1190 peer_free(peer);
1191 return NULL;
1192 }
1193
1194 return peer;
200df115 1195}
794b37d5 1196/* BGP GR changes */
1197
1198int bgp_global_gr_init(struct bgp *bgp)
1199{
1200 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
1201 zlog_debug("%s called ..", __func__);
1202
2ba1fe69 1203 int local_GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE][BGP_GLOBAL_GR_EVENT_CMD] = {
794b37d5 1204 /* GLOBAL_HELPER Mode */
1205 {
1206 /*Event -> */
1207 /*GLOBAL_GR_cmd*/ /*no_Global_GR_cmd*/
1208 GLOBAL_GR, GLOBAL_INVALID,
1209 /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/
1210 GLOBAL_DISABLE, GLOBAL_INVALID
1211 },
1212 /* GLOBAL_GR Mode */
1213 {
1214 /*Event -> */
1215 /*GLOBAL_GR_cmd*/ /*no_Global_GR_cmd*/
62403772 1216 GLOBAL_GR, GLOBAL_HELPER,
794b37d5 1217 /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/
1218 GLOBAL_DISABLE, GLOBAL_INVALID
1219 },
1220 /* GLOBAL_DISABLE Mode */
1221 {
1222 /*Event -> */
1223 /*GLOBAL_GR_cmd */ /*no_Global_GR_cmd*/
1224 GLOBAL_GR, GLOBAL_INVALID,
1225 /*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/
1226 GLOBAL_INVALID, GLOBAL_HELPER
1227 },
1228 /* GLOBAL_INVALID Mode */
1229 {
1230 /*Event -> */
1231 /*GLOBAL_GR_cmd*/ /*no_Global_GR_cmd*/
1232 GLOBAL_INVALID, GLOBAL_INVALID,
1233 /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/
1234 GLOBAL_INVALID, GLOBAL_INVALID
1235 }
1236 };
1237 memcpy(bgp->GLOBAL_GR_FSM, local_GLOBAL_GR_FSM,
1238 sizeof(local_GLOBAL_GR_FSM));
1239
1240 bgp->global_gr_present_state = GLOBAL_HELPER;
dc95985f 1241 bgp->present_zebra_gr_state = ZEBRA_GR_DISABLE;
794b37d5 1242
1243 return BGP_GR_SUCCESS;
1244}
1245
1246int bgp_peer_gr_init(struct peer *peer)
1247{
1248 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
1249 zlog_debug("%s called ..", __func__);
1250
2ba1fe69 1251 struct bgp_peer_gr local_Peer_GR_FSM[BGP_PEER_GR_MODE]
1252 [BGP_PEER_GR_EVENT_CMD] = {
794b37d5 1253 {
1254 /* PEER_HELPER Mode */
1255 /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
1256 { PEER_GR, bgp_peer_gr_action }, {PEER_INVALID, NULL },
2ba1fe69 1257 /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
794b37d5 1258 {PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL },
1259 /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
1260 { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT,
1261 bgp_peer_gr_action }
1262 },
1263 {
1264 /* PEER_GR Mode */
1265 /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
1266 { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
1267 bgp_peer_gr_action },
2ba1fe69 1268 /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
794b37d5 1269 {PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL },
1270 /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
1271 { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
1272 },
1273 {
1274 /* PEER_DISABLE Mode */
1275 /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
1276 { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL },
2ba1fe69 1277 /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
794b37d5 1278 { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
1279 bgp_peer_gr_action },
1280 /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
1281 { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
1282 },
1283 {
1284 /* PEER_INVALID Mode */
1285 /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
1286 { PEER_INVALID, NULL }, { PEER_INVALID, NULL },
2ba1fe69 1287 /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
794b37d5 1288 { PEER_INVALID, NULL }, { PEER_INVALID, NULL },
1289 /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
1290 { PEER_INVALID, NULL }, { PEER_INVALID, NULL },
1291 },
1292 {
1293 /* PEER_GLOBAL_INHERIT Mode */
1294 /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
1295 { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL },
2ba1fe69 1296 /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
794b37d5 1297 { PEER_DISABLE, bgp_peer_gr_action}, { PEER_INVALID, NULL },
1298 /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
1299 { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
1300 }
1301 };
1302 memcpy(&peer->PEER_GR_FSM, local_Peer_GR_FSM,
1303 sizeof(local_Peer_GR_FSM));
1304 peer->peer_gr_present_state = PEER_GLOBAL_INHERIT;
1305 bgp_peer_move_to_gr_mode(peer, PEER_GLOBAL_INHERIT);
1306
1307 return BGP_GR_SUCCESS;
1308}
1ff9a340 1309
92a9e6f2
HS
1310static void bgp_srv6_init(struct bgp *bgp)
1311{
1312 bgp->srv6_enabled = false;
1313 memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name));
1314 bgp->srv6_locator_chunks = list_new();
1315 bgp->srv6_functions = list_new();
1316}
1317
1318static void bgp_srv6_cleanup(struct bgp *bgp)
1319{
124f7236
HS
1320 if (bgp->srv6_locator_chunks)
1321 list_delete(&bgp->srv6_locator_chunks);
1322 if (bgp->srv6_functions)
1323 list_delete(&bgp->srv6_functions);
92a9e6f2
HS
1324}
1325
200df115 1326/* Allocate new peer object, implicitely locked. */
d62a17ae 1327struct peer *peer_new(struct bgp *bgp)
1328{
1329 afi_t afi;
1330 safi_t safi;
1331 struct peer *peer;
1332 struct servent *sp;
1333
1334 /* bgp argument is absolutely required */
1335 assert(bgp);
d62a17ae 1336
1337 /* Allocate new peer. */
1338 peer = XCALLOC(MTYPE_BGP_PEER, sizeof(struct peer));
1339
1340 /* Set default value. */
1341 peer->fd = -1;
1342 peer->v_start = BGP_INIT_START_TIMER;
5d5393b9 1343 peer->v_connect = bgp->default_connect_retry;
d62a17ae 1344 peer->status = Idle;
1345 peer->ostatus = Idle;
1346 peer->cur_event = peer->last_event = peer->last_major_event = 0;
92375c91 1347 peer->bgp = bgp_lock(bgp);
d62a17ae 1348 peer = peer_lock(peer); /* initial reference */
8f2d6021
EB
1349 peer->local_role = ROLE_UNDEFINED;
1350 peer->remote_role = ROLE_UNDEFINED;
d62a17ae 1351 peer->password = NULL;
0db06e37 1352 peer->max_packet_size = BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE;
d62a17ae 1353
27c05d4d 1354 /* Set default flags. */
05c7a1cc 1355 FOREACH_AFI_SAFI (afi, safi) {
d8a9922d
DS
1356 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
1357 SET_FLAG(peer->af_flags[afi][safi],
1358 PEER_FLAG_SEND_EXT_COMMUNITY);
1359 SET_FLAG(peer->af_flags[afi][safi],
1360 PEER_FLAG_SEND_LARGE_COMMUNITY);
1361
1362 SET_FLAG(peer->af_flags_invert[afi][safi],
1363 PEER_FLAG_SEND_COMMUNITY);
1364 SET_FLAG(peer->af_flags_invert[afi][safi],
1365 PEER_FLAG_SEND_EXT_COMMUNITY);
1366 SET_FLAG(peer->af_flags_invert[afi][safi],
1367 PEER_FLAG_SEND_LARGE_COMMUNITY);
dcc68b5e 1368 peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
01da2d26 1369 peer->soo[afi][safi] = NULL;
05c7a1cc 1370 }
637315fc 1371
bd23c840
PR
1372 /* set nexthop-unchanged for l2vpn evpn by default */
1373 SET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
1374 PEER_FLAG_NEXTHOP_UNCHANGED);
1375
d62a17ae 1376 SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
718e3744 1377
794b37d5 1378 /* Initialize per peer bgp GR FSM */
1379 bgp_peer_gr_init(peer);
1380
d62a17ae 1381 /* Create buffers. */
424ab01d 1382 peer->ibuf = stream_fifo_new();
d62a17ae 1383 peer->obuf = stream_fifo_new();
424ab01d 1384 pthread_mutex_init(&peer->io_mtx, NULL);
0a91ff55 1385
424ab01d 1386 /* We use a larger buffer for peer->obuf_work in the event that:
d62a17ae 1387 * - We RX a BGP_UPDATE where the attributes alone are just
556beacf 1388 * under BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE.
d62a17ae 1389 * - The user configures an outbound route-map that does many as-path
09f6d019
QY
1390 * prepends or adds many communities. At most they can have
1391 * CMD_ARGC_MAX args in a route-map so there is a finite limit on how
1392 * large they can make the attributes.
d62a17ae 1393 *
1394 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid
09f6d019
QY
1395 * bounds checking for every single attribute as we construct an
1396 * UPDATE.
d62a17ae 1397 */
556beacf
QY
1398 peer->obuf_work =
1399 stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
1400 peer->ibuf_work =
1401 ringbuf_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
74ffbfe6 1402
556beacf 1403 peer->scratch = stream_new(BGP_MAX_PACKET_SIZE);
718e3744 1404
d62a17ae 1405 bgp_sync_init(peer);
718e3744 1406
d62a17ae 1407 /* Get service port number. */
1408 sp = getservbyname("bgp", "tcp");
1409 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port);
718e3744 1410
d62a17ae 1411 QOBJ_REG(peer, peer);
1412 return peer;
718e3744 1413}
1414
1ff9a340
DS
1415/*
1416 * This function is invoked when a duplicate peer structure associated with
1417 * a neighbor is being deleted. If this about-to-be-deleted structure is
1418 * the one with all the config, then we have to copy over the info.
1419 */
d62a17ae 1420void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
1421{
1422 struct peer_af *paf;
1423 afi_t afi;
1424 safi_t safi;
1425 int afidx;
1426
1427 assert(peer_src);
1428 assert(peer_dst);
1429
1430 /* The following function is used by both peer group config copy to
1431 * individual peer and when we transfer config
1432 */
1433 if (peer_src->change_local_as)
1434 peer_dst->change_local_as = peer_src->change_local_as;
1435
1436 /* peer flags apply */
1437 peer_dst->flags = peer_src->flags;
d62a17ae 1438
d7b3cda6 1439 peer_dst->peer_gr_present_state = peer_src->peer_gr_present_state;
1440 peer_dst->peer_gr_new_status_flag = peer_src->peer_gr_new_status_flag;
1441
d62a17ae 1442 peer_dst->local_as = peer_src->local_as;
d62a17ae 1443 peer_dst->port = peer_src->port;
4ab46701
AR
1444 /* copy tcp_mss value */
1445 peer_dst->tcp_mss = peer_src->tcp_mss;
82417ac2 1446 (void)peer_sort(peer_dst);
d62a17ae 1447 peer_dst->rmap_type = peer_src->rmap_type;
d864dd9e 1448 peer_dst->local_role = peer_src->local_role;
d62a17ae 1449
0db06e37
DA
1450 peer_dst->max_packet_size = peer_src->max_packet_size;
1451
d62a17ae 1452 /* Timers */
1453 peer_dst->holdtime = peer_src->holdtime;
1454 peer_dst->keepalive = peer_src->keepalive;
1455 peer_dst->connect = peer_src->connect;
6c537a18 1456 peer_dst->delayopen = peer_src->delayopen;
d62a17ae 1457 peer_dst->v_holdtime = peer_src->v_holdtime;
1458 peer_dst->v_keepalive = peer_src->v_keepalive;
1459 peer_dst->routeadv = peer_src->routeadv;
1460 peer_dst->v_routeadv = peer_src->v_routeadv;
6c537a18 1461 peer_dst->v_delayopen = peer_src->v_delayopen;
d62a17ae 1462
1463 /* password apply */
1464 if (peer_src->password && !peer_dst->password)
1465 peer_dst->password =
1466 XSTRDUP(MTYPE_PEER_PASSWORD, peer_src->password);
1467
05c7a1cc
QY
1468 FOREACH_AFI_SAFI (afi, safi) {
1469 peer_dst->afc[afi][safi] = peer_src->afc[afi][safi];
1470 peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi];
1471 peer_dst->allowas_in[afi][safi] =
1472 peer_src->allowas_in[afi][safi];
1473 peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
dcc68b5e
MS
1474 peer_dst->addpath_type[afi][safi] =
1475 peer_src->addpath_type[afi][safi];
05c7a1cc 1476 }
d62a17ae 1477
1478 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
1479 paf = peer_src->peer_af_array[afidx];
e84c59af
DA
1480 if (paf != NULL) {
1481 if (!peer_af_find(peer_dst, paf->afi, paf->safi))
1482 peer_af_create(peer_dst, paf->afi, paf->safi);
1483 }
d62a17ae 1484 }
1485
1486 /* update-source apply */
1487 if (peer_src->update_source) {
1488 if (peer_dst->update_source)
1489 sockunion_free(peer_dst->update_source);
e1b36e13 1490 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
d62a17ae 1491 peer_dst->update_source =
1492 sockunion_dup(peer_src->update_source);
1493 } else if (peer_src->update_if) {
0a22ddfb 1494 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
d62a17ae 1495 if (peer_dst->update_source) {
1496 sockunion_free(peer_dst->update_source);
1497 peer_dst->update_source = NULL;
1498 }
1499 peer_dst->update_if =
1500 XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if);
1501 }
1502
1503 if (peer_src->ifname) {
0a22ddfb 1504 XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname);
d62a17ae 1505
1506 peer_dst->ifname =
1507 XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname);
1508 }
1509}
1510
1511static int bgp_peer_conf_if_to_su_update_v4(struct peer *peer,
1512 struct interface *ifp)
1513{
1514 struct connected *ifc;
1515 struct prefix p;
d7c0a89a 1516 uint32_t addr;
d62a17ae 1517 struct listnode *node;
1518
1519 /* If our IPv4 address on the interface is /30 or /31, we can derive the
1520 * IPv4 address of the other end.
1521 */
1522 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
1523 if (ifc->address && (ifc->address->family == AF_INET)) {
b08dcc3f 1524 prefix_copy(&p, CONNECTED_PREFIX(ifc));
d62a17ae 1525 if (p.prefixlen == 30) {
1526 peer->su.sa.sa_family = AF_INET;
1527 addr = ntohl(p.u.prefix4.s_addr);
1528 if (addr % 4 == 1)
1529 peer->su.sin.sin_addr.s_addr =
1530 htonl(addr + 1);
1531 else if (addr % 4 == 2)
1532 peer->su.sin.sin_addr.s_addr =
1533 htonl(addr - 1);
8ffedcea 1534#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 1535 peer->su.sin.sin_len =
1536 sizeof(struct sockaddr_in);
8ffedcea 1537#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
d62a17ae 1538 return 1;
1539 } else if (p.prefixlen == 31) {
1540 peer->su.sa.sa_family = AF_INET;
1541 addr = ntohl(p.u.prefix4.s_addr);
1542 if (addr % 2 == 0)
1543 peer->su.sin.sin_addr.s_addr =
1544 htonl(addr + 1);
1545 else
1546 peer->su.sin.sin_addr.s_addr =
1547 htonl(addr - 1);
8ffedcea 1548#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
d62a17ae 1549 peer->su.sin.sin_len =
1550 sizeof(struct sockaddr_in);
8ffedcea 1551#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
d62a17ae 1552 return 1;
1553 } else if (bgp_debug_neighbor_events(peer))
1554 zlog_debug(
1555 "%s: IPv4 interface address is not /30 or /31, v4 session not started",
1556 peer->conf_if);
1557 }
1558 }
1559
1560 return 0;
1561}
1562
3dc339cd
DA
1563static bool bgp_peer_conf_if_to_su_update_v6(struct peer *peer,
1564 struct interface *ifp)
d62a17ae 1565{
1566 struct nbr_connected *ifc_nbr;
1567
1568 /* Have we learnt the peer's IPv6 link-local address? */
1569 if (ifp->nbr_connected
1570 && (ifc_nbr = listnode_head(ifp->nbr_connected))) {
1571 peer->su.sa.sa_family = AF_INET6;
1572 memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix,
1573 sizeof(struct in6_addr));
a80beece 1574#ifdef SIN6_LEN
d62a17ae 1575 peer->su.sin6.sin6_len = sizeof(struct sockaddr_in6);
a80beece 1576#endif
d62a17ae 1577 peer->su.sin6.sin6_scope_id = ifp->ifindex;
3dc339cd 1578 return true;
d62a17ae 1579 }
8ffedcea 1580
3dc339cd 1581 return false;
89ca90fa 1582}
1583
1584/*
1585 * Set or reset the peer address socketunion structure based on the
1586 * learnt/derived peer address. If the address has changed, update the
1587 * password on the listen socket, if needed.
1588 */
d62a17ae 1589void bgp_peer_conf_if_to_su_update(struct peer *peer)
1590{
1591 struct interface *ifp;
1592 int prev_family;
1593 int peer_addr_updated = 0;
1594
1595 if (!peer->conf_if)
1596 return;
1597
d12b745c
DS
1598 /*
1599 * Our peer structure is stored in the bgp->peerhash
1600 * release it before we modify anything.
1601 */
1602 hash_release(peer->bgp->peerhash, peer);
1603
d62a17ae 1604 prev_family = peer->su.sa.sa_family;
a36898e7 1605 if ((ifp = if_lookup_by_name(peer->conf_if, peer->bgp->vrf_id))) {
d62a17ae 1606 peer->ifp = ifp;
1607 /* If BGP unnumbered is not "v6only", we first see if we can
1608 * derive the
1609 * peer's IPv4 address.
1610 */
1611 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
1612 peer_addr_updated =
1613 bgp_peer_conf_if_to_su_update_v4(peer, ifp);
1614
1615 /* If "v6only" or we can't derive peer's IPv4 address, see if
1616 * we've
1617 * learnt the peer's IPv6 link-local address. This is from the
1618 * source
1619 * IPv6 address in router advertisement.
1620 */
1621 if (!peer_addr_updated)
1622 peer_addr_updated =
1623 bgp_peer_conf_if_to_su_update_v6(peer, ifp);
1624 }
1625 /* If we could derive the peer address, we may need to install the
1626 * password
1627 * configured for the peer, if any, on the listen socket. Otherwise,
1628 * mark
1629 * that peer's address is not available and uninstall the password, if
1630 * needed.
1631 */
1632 if (peer_addr_updated) {
a14810f4
PM
1633 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)
1634 && prev_family == AF_UNSPEC)
d62a17ae 1635 bgp_md5_set(peer);
1636 } else {
a14810f4
PM
1637 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)
1638 && prev_family != AF_UNSPEC)
d62a17ae 1639 bgp_md5_unset(peer);
1640 peer->su.sa.sa_family = AF_UNSPEC;
1641 memset(&peer->su.sin6.sin6_addr, 0, sizeof(struct in6_addr));
1642 }
1643
d12b745c
DS
1644 /*
1645 * Since our su changed we need to del/add peer to the peerhash
1646 */
8e3aae66 1647 (void)hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
a80beece
DS
1648}
1649
1479ed2f 1650void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, safi_t safi)
318cac96 1651{
9bcb3eef 1652 struct bgp_dest *dest, *ndest;
67009e22 1653 struct bgp_table *table;
318cac96 1654
9bcb3eef
DS
1655 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
1656 dest = bgp_route_next(dest)) {
1657 table = bgp_dest_get_bgp_table_info(dest);
67009e22 1658 if (table != NULL) {
318cac96
DW
1659 /* Special handling for 2-level routing
1660 * tables. */
a4d82a8a 1661 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
318cac96 1662 || safi == SAFI_EVPN) {
9bcb3eef
DS
1663 for (ndest = bgp_table_top(table); ndest;
1664 ndest = bgp_route_next(ndest))
1665 bgp_process(bgp, ndest, afi, safi);
318cac96 1666 } else
9bcb3eef 1667 bgp_process(bgp, dest, afi, safi);
318cac96
DW
1668 }
1669 }
1670}
1671
06370dac
DW
1672/* Force a bestpath recalculation for all prefixes. This is used
1673 * when 'bgp bestpath' commands are entered.
1674 */
d62a17ae 1675void bgp_recalculate_all_bestpaths(struct bgp *bgp)
1676{
1677 afi_t afi;
1678 safi_t safi;
d62a17ae 1679
05c7a1cc
QY
1680 FOREACH_AFI_SAFI (afi, safi) {
1681 bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi);
d62a17ae 1682 }
06370dac
DW
1683}
1684
19bd3dff
DS
1685/*
1686 * Create new BGP peer.
1687 *
1688 * conf_if and su are mutually exclusive if configuring from the cli.
1689 * If we are handing a doppelganger, then we *must* pass in both
1690 * the original peer's su and conf_if, so that we can appropriately
1691 * track the bgp->peerhash( ie we don't want to remove the current
1692 * one from the config ).
1693 */
d62a17ae 1694struct peer *peer_create(union sockunion *su, const char *conf_if,
1695 struct bgp *bgp, as_t local_as, as_t remote_as,
e84c59af 1696 int as_type, struct peer_group *group)
d62a17ae 1697{
1698 int active;
1699 struct peer *peer;
1700 char buf[SU_ADDRSTRLEN];
e84c59af
DA
1701 afi_t afi;
1702 safi_t safi;
d62a17ae 1703
1704 peer = peer_new(bgp);
1705 if (conf_if) {
1706 peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if);
19bd3dff
DS
1707 if (su)
1708 peer->su = *su;
1709 else
1710 bgp_peer_conf_if_to_su_update(peer);
0a22ddfb 1711 XFREE(MTYPE_BGP_PEER_HOST, peer->host);
d62a17ae 1712 peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if);
1713 } else if (su) {
1714 peer->su = *su;
1715 sockunion2str(su, buf, SU_ADDRSTRLEN);
0a22ddfb 1716 XFREE(MTYPE_BGP_PEER_HOST, peer->host);
d62a17ae 1717 peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf);
1718 }
1719 peer->local_as = local_as;
1720 peer->as = remote_as;
1721 peer->as_type = as_type;
1722 peer->local_id = bgp->router_id;
1723 peer->v_holdtime = bgp->default_holdtime;
1724 peer->v_keepalive = bgp->default_keepalive;
b90a8e13
PM
1725 peer->v_routeadv = (peer_sort(peer) == BGP_PEER_IBGP)
1726 ? BGP_DEFAULT_IBGP_ROUTEADV
1727 : BGP_DEFAULT_EBGP_ROUTEADV;
aa24a36a
DA
1728 if (bgp_config_inprocess())
1729 peer->shut_during_cfg = true;
d62a17ae 1730
1731 peer = peer_lock(peer); /* bgp peer list reference */
1732 peer->group = group;
1733 listnode_add_sort(bgp->peer, peer);
8e3aae66 1734 (void)hash_get(bgp->peerhash, peer, hash_alloc_intern);
d62a17ae 1735
4961a5a2 1736 /* Adjust update-group coalesce timer heuristics for # peers. */
37a333fe 1737 if (bgp->heuristic_coalesce) {
14b8641a
QY
1738 long ct = BGP_DEFAULT_SUBGROUP_COALESCE_TIME
1739 + (bgp->peer->count
1740 * BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME);
1741 bgp->coalesce_time = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME, ct);
1742 }
4961a5a2 1743
d62a17ae 1744 active = peer_active(peer);
05912a17
DD
1745 if (!active) {
1746 if (peer->su.sa.sa_family == AF_UNSPEC)
1747 peer->last_reset = PEER_DOWN_NBR_ADDR;
1748 else
1749 peer->last_reset = PEER_DOWN_NOAFI_ACTIVATED;
1750 }
d62a17ae 1751
1752 /* Last read and reset time set */
083ec940 1753 peer->readtime = peer->resettime = monotime(NULL);
d62a17ae 1754
1755 /* Default TTL set. */
a0903cd2 1756 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : BGP_DEFAULT_TTL;
d62a17ae 1757
8336c896
DA
1758 /* Default configured keepalives count for shutdown rtt command */
1759 peer->rtt_keepalive_conf = 1;
1760
d62a17ae 1761 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
1762
b16bcbba
TA
1763 /* If 'bgp default <afi>-<safi>' is configured, then activate the
1764 * neighbor for the corresponding address family. IPv4 Unicast is
1765 * the only address family enabled by default without expliict
1766 * configuration.
e84c59af
DA
1767 */
1768 FOREACH_AFI_SAFI (afi, safi) {
38d11af5
TA
1769 if (bgp->default_af[afi][safi]) {
1770 peer->afc[afi][safi] = 1;
1771 peer_af_create(peer, afi, safi);
e84c59af 1772 }
d62a17ae 1773 }
1774
f26845f9
QY
1775 /* auto shutdown if configured */
1776 if (bgp->autoshutdown)
1777 peer_flag_set(peer, PEER_FLAG_SHUTDOWN);
d62a17ae 1778 /* Set up peer's events and timers. */
f26845f9 1779 else if (!active && peer_active(peer))
d62a17ae 1780 bgp_timer_set(peer);
1781
794b37d5 1782 bgp_peer_gr_flags_update(peer);
36235319 1783 BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer);
dc95985f 1784
d62a17ae 1785 return peer;
718e3744 1786}
1787
dd793e4a 1788/* Make accept BGP peer. This function is only called from the test code */
d62a17ae 1789struct peer *peer_create_accept(struct bgp *bgp)
eb821189 1790{
d62a17ae 1791 struct peer *peer;
eb821189 1792
d62a17ae 1793 peer = peer_new(bgp);
1ff9a340 1794
d62a17ae 1795 peer = peer_lock(peer); /* bgp peer list reference */
1796 listnode_add_sort(bgp->peer, peer);
eb821189 1797
d62a17ae 1798 return peer;
eb821189 1799}
1800
318cac96
DW
1801/*
1802 * Return true if we have a peer configured to use this afi/safi
1803 */
0b1fb52c 1804bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
318cac96
DW
1805{
1806 struct listnode *node;
1807 struct peer *peer;
1808
1809 for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
1810 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1811 continue;
1812
1813 if (peer->afc[afi][safi])
0b1fb52c 1814 return true;
318cac96
DW
1815 }
1816
0b1fb52c 1817 return false;
318cac96
DW
1818}
1819
718e3744 1820/* Change peer's AS number. */
d62a17ae 1821void peer_as_change(struct peer *peer, as_t as, int as_specified)
1822{
3061acc2 1823 enum bgp_peer_sort origtype, newtype;
d62a17ae 1824
1825 /* Stop peer. */
1826 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
1827 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
1828 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
1829 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
1830 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1831 } else
1832 bgp_session_reset(peer);
1833 }
469cbb0f 1834 origtype = peer_sort_lookup(peer);
d62a17ae 1835 peer->as = as;
1836 peer->as_type = as_specified;
1837
1838 if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION)
1839 && !bgp_confederation_peers_check(peer->bgp, as)
1840 && peer->bgp->as != as)
1841 peer->local_as = peer->bgp->confed_id;
1842 else
1843 peer->local_as = peer->bgp->as;
1844
469cbb0f 1845 newtype = peer_sort(peer);
d62a17ae 1846 /* Advertisement-interval reset */
b90a8e13 1847 if (!CHECK_FLAG(peer->flags, PEER_FLAG_ROUTEADV)) {
469cbb0f 1848 peer->v_routeadv = (newtype == BGP_PEER_IBGP)
b90a8e13
PM
1849 ? BGP_DEFAULT_IBGP_ROUTEADV
1850 : BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 1851 }
b90a8e13 1852
d62a17ae 1853 /* TTL reset */
469cbb0f 1854 if (newtype == BGP_PEER_IBGP)
d62a17ae 1855 peer->ttl = MAXTTL;
469cbb0f 1856 else if (origtype == BGP_PEER_IBGP)
a0903cd2 1857 peer->ttl = BGP_DEFAULT_TTL;
d62a17ae 1858
1859 /* reflector-client reset */
469cbb0f 1860 if (newtype != BGP_PEER_IBGP) {
d62a17ae 1861 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST],
1862 PEER_FLAG_REFLECTOR_CLIENT);
1863 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST],
1864 PEER_FLAG_REFLECTOR_CLIENT);
1865 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_LABELED_UNICAST],
1866 PEER_FLAG_REFLECTOR_CLIENT);
1867 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1868 PEER_FLAG_REFLECTOR_CLIENT);
1869 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_ENCAP],
1870 PEER_FLAG_REFLECTOR_CLIENT);
7c40bf39 1871 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_FLOWSPEC],
1872 PEER_FLAG_REFLECTOR_CLIENT);
d62a17ae 1873 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_UNICAST],
1874 PEER_FLAG_REFLECTOR_CLIENT);
1875 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1876 PEER_FLAG_REFLECTOR_CLIENT);
1877 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_LABELED_UNICAST],
1878 PEER_FLAG_REFLECTOR_CLIENT);
1879 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1880 PEER_FLAG_REFLECTOR_CLIENT);
1881 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_ENCAP],
1882 PEER_FLAG_REFLECTOR_CLIENT);
7c40bf39 1883 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_FLOWSPEC],
1884 PEER_FLAG_REFLECTOR_CLIENT);
d62a17ae 1885 UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
1886 PEER_FLAG_REFLECTOR_CLIENT);
1887 }
1888
1889 /* local-as reset */
469cbb0f 1890 if (newtype != BGP_PEER_EBGP) {
d62a17ae 1891 peer->change_local_as = 0;
a14810f4
PM
1892 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
1893 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1894 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
d62a17ae 1895 }
718e3744 1896}
1897
1898/* If peer does not exist, create new one. If peer already exists,
1899 set AS number to the peer. */
d62a17ae 1900int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
e84c59af 1901 as_t *as, int as_type)
d62a17ae 1902{
1903 struct peer *peer;
1904 as_t local_as;
1905
1906 if (conf_if)
1907 peer = peer_lookup_by_conf_if(bgp, conf_if);
1908 else
1909 peer = peer_lookup(bgp, su);
1910
1911 if (peer) {
1912 /* Not allowed for a dynamic peer. */
1913 if (peer_dynamic_neighbor(peer)) {
1914 *as = peer->as;
1915 return BGP_ERR_INVALID_FOR_DYNAMIC_PEER;
1916 }
718e3744 1917
d62a17ae 1918 /* When this peer is a member of peer-group. */
1919 if (peer->group) {
faa16034
DS
1920 /* peer-group already has AS number/internal/external */
1921 if (peer->group->conf->as
1922 || peer->group->conf->as_type) {
d62a17ae 1923 /* Return peer group's AS number. */
1924 *as = peer->group->conf->as;
1925 return BGP_ERR_PEER_GROUP_MEMBER;
1926 }
faa16034 1927
3061acc2
DA
1928 enum bgp_peer_sort peer_sort_type =
1929 peer_sort(peer->group->conf);
faa16034
DS
1930
1931 /* Explicit AS numbers used, compare AS numbers */
1932 if (as_type == AS_SPECIFIED) {
1933 if (((peer_sort_type == BGP_PEER_IBGP)
1934 && (bgp->as != *as))
1935 || ((peer_sort_type == BGP_PEER_EBGP)
1936 && (bgp->as == *as))) {
d62a17ae 1937 *as = peer->as;
1938 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1939 }
1940 } else {
faa16034
DS
1941 /* internal/external used, compare as-types */
1942 if (((peer_sort_type == BGP_PEER_IBGP)
1943 && (as_type != AS_INTERNAL))
1944 || ((peer_sort_type == BGP_PEER_EBGP)
1945 && (as_type != AS_EXTERNAL))) {
d62a17ae 1946 *as = peer->as;
1947 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1948 }
1949 }
1950 }
93406d87 1951
d62a17ae 1952 /* Existing peer's AS number change. */
1953 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)
1954 || (peer->as_type != as_type))
1955 peer_as_change(peer, *as, as_type);
1956 } else {
1957 if (conf_if)
1958 return BGP_ERR_NO_INTERFACE_CONFIG;
1959
1960 /* If the peer is not part of our confederation, and its not an
1961 iBGP peer then spoof the source AS */
1962 if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)
1963 && !bgp_confederation_peers_check(bgp, *as)
1964 && bgp->as != *as)
1965 local_as = bgp->confed_id;
1966 else
1967 local_as = bgp->as;
1968
e84c59af 1969 peer_create(su, conf_if, bgp, local_as, *as, as_type, NULL);
d62a17ae 1970 }
718e3744 1971
d62a17ae 1972 return 0;
1973}
718e3744 1974
8f2d6021 1975const char *bgp_get_name_by_role(uint8_t role)
d864dd9e 1976{
865a7e7b
EB
1977 switch (role) {
1978 case ROLE_PROVIDER:
1979 return "provider";
1980 case ROLE_RS_SERVER:
1981 return "rs-server";
1982 case ROLE_RS_CLIENT:
1983 return "rs-client";
1984 case ROLE_CUSTOMER:
1985 return "customer";
1986 case ROLE_PEER:
1987 return "peer";
1988 case ROLE_UNDEFINED:
8f2d6021 1989 return "undefined";
865a7e7b 1990 }
d864dd9e
EB
1991 return "unknown";
1992}
1993
9790f44f
DS
1994static void peer_group2peer_config_copy_af(struct peer_group *group,
1995 struct peer *peer, afi_t afi,
1996 safi_t safi)
1997{
1998 int in = FILTER_IN;
1999 int out = FILTER_OUT;
da5e1a58
DA
2000 uint64_t flags_tmp;
2001 uint64_t pflags_ovrd;
e7103a96 2002 uint8_t *pfilter_ovrd;
9790f44f 2003 struct peer *conf;
9790f44f
DS
2004
2005 conf = group->conf;
e7103a96
PM
2006 pflags_ovrd = peer->af_flags_override[afi][safi];
2007 pfilter_ovrd = &peer->filter_override[afi][safi][in];
9790f44f
DS
2008
2009 /* peer af_flags apply */
4c391142
PM
2010 flags_tmp = conf->af_flags[afi][safi] & ~pflags_ovrd;
2011 flags_tmp ^= conf->af_flags_invert[afi][safi]
2012 ^ peer->af_flags_invert[afi][safi];
2013 flags_tmp &= ~pflags_ovrd;
2014
2015 UNSET_FLAG(peer->af_flags[afi][safi], ~pflags_ovrd);
2016 SET_FLAG(peer->af_flags[afi][safi], flags_tmp);
2017 SET_FLAG(peer->af_flags_invert[afi][safi],
2018 conf->af_flags_invert[afi][safi]);
9790f44f
DS
2019
2020 /* maximum-prefix */
e7103a96
PM
2021 if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_MAX_PREFIX)) {
2022 PEER_ATTR_INHERIT(peer, group, pmax[afi][safi]);
2023 PEER_ATTR_INHERIT(peer, group, pmax_threshold[afi][safi]);
2024 PEER_ATTR_INHERIT(peer, group, pmax_restart[afi][safi]);
2025 }
9790f44f 2026
80444d30
LS
2027 /* maximum-prefix-out */
2028 if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_MAX_PREFIX_OUT))
2029 PEER_ATTR_INHERIT(peer, group, pmax_out[afi][safi]);
2030
9790f44f 2031 /* allowas-in */
e7103a96
PM
2032 if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_ALLOWAS_IN))
2033 PEER_ATTR_INHERIT(peer, group, allowas_in[afi][safi]);
9790f44f 2034
01da2d26
DA
2035 /* soo */
2036 if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_SOO))
2037 PEER_ATTR_INHERIT(peer, group, soo[afi][safi]);
2038
9790f44f 2039 /* weight */
e7103a96
PM
2040 if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_WEIGHT))
2041 PEER_ATTR_INHERIT(peer, group, weight[afi][safi]);
9790f44f
DS
2042
2043 /* default-originate route-map */
e7103a96
PM
2044 if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_DEFAULT_ORIGINATE)) {
2045 PEER_STR_ATTR_INHERIT(peer, group, default_rmap[afi][safi].name,
2046 MTYPE_ROUTE_MAP_NAME);
2047 PEER_ATTR_INHERIT(peer, group, default_rmap[afi][safi].map);
9790f44f
DS
2048 }
2049
2050 /* inbound filter apply */
e7103a96
PM
2051 if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_DISTRIBUTE_LIST)) {
2052 PEER_STR_ATTR_INHERIT(peer, group,
2053 filter[afi][safi].dlist[in].name,
2054 MTYPE_BGP_FILTER_NAME);
2055 PEER_ATTR_INHERIT(peer, group,
2056 filter[afi][safi].dlist[in].alist);
9790f44f
DS
2057 }
2058
e7103a96
PM
2059 if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_PREFIX_LIST)) {
2060 PEER_STR_ATTR_INHERIT(peer, group,
2061 filter[afi][safi].plist[in].name,
2062 MTYPE_BGP_FILTER_NAME);
2063 PEER_ATTR_INHERIT(peer, group,
2064 filter[afi][safi].plist[in].plist);
9790f44f
DS
2065 }
2066
e7103a96
PM
2067 if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_FILTER_LIST)) {
2068 PEER_STR_ATTR_INHERIT(peer, group,
2069 filter[afi][safi].aslist[in].name,
2070 MTYPE_BGP_FILTER_NAME);
2071 PEER_ATTR_INHERIT(peer, group,
2072 filter[afi][safi].aslist[in].aslist);
9790f44f
DS
2073 }
2074
e7103a96
PM
2075 if (!CHECK_FLAG(pfilter_ovrd[RMAP_IN], PEER_FT_ROUTE_MAP)) {
2076 PEER_STR_ATTR_INHERIT(peer, group,
2077 filter[afi][safi].map[in].name,
2078 MTYPE_BGP_FILTER_NAME);
2079 PEER_ATTR_INHERIT(peer, group,
2080 filter[afi][safi].map[RMAP_IN].map);
9790f44f
DS
2081 }
2082
2083 /* outbound filter apply */
e7103a96
PM
2084 if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_DISTRIBUTE_LIST)) {
2085 PEER_STR_ATTR_INHERIT(peer, group,
2086 filter[afi][safi].dlist[out].name,
2087 MTYPE_BGP_FILTER_NAME);
2088 PEER_ATTR_INHERIT(peer, group,
2089 filter[afi][safi].dlist[out].alist);
9790f44f
DS
2090 }
2091
e7103a96
PM
2092 if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_PREFIX_LIST)) {
2093 PEER_STR_ATTR_INHERIT(peer, group,
2094 filter[afi][safi].plist[out].name,
2095 MTYPE_BGP_FILTER_NAME);
2096 PEER_ATTR_INHERIT(peer, group,
2097 filter[afi][safi].plist[out].plist);
9790f44f
DS
2098 }
2099
e7103a96
PM
2100 if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_FILTER_LIST)) {
2101 PEER_STR_ATTR_INHERIT(peer, group,
2102 filter[afi][safi].aslist[out].name,
2103 MTYPE_BGP_FILTER_NAME);
2104 PEER_ATTR_INHERIT(peer, group,
2105 filter[afi][safi].aslist[out].aslist);
2106 }
2107
2108 if (!CHECK_FLAG(pfilter_ovrd[RMAP_OUT], PEER_FT_ROUTE_MAP)) {
2109 PEER_STR_ATTR_INHERIT(peer, group,
2110 filter[afi][safi].map[RMAP_OUT].name,
2111 MTYPE_BGP_FILTER_NAME);
2112 PEER_ATTR_INHERIT(peer, group,
2113 filter[afi][safi].map[RMAP_OUT].map);
2114 }
2115
2116 /* nondirectional filter apply */
2117 if (!CHECK_FLAG(pfilter_ovrd[0], PEER_FT_UNSUPPRESS_MAP)) {
2118 PEER_STR_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.name,
2119 MTYPE_BGP_FILTER_NAME);
2120 PEER_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.map);
9790f44f 2121 }
dcc68b5e 2122
9118301e
DA
2123 /* Conditional Advertisements */
2124 if (!CHECK_FLAG(pfilter_ovrd[RMAP_OUT], PEER_FT_ADVERTISE_MAP)) {
2125 PEER_STR_ATTR_INHERIT(peer, group,
2126 filter[afi][safi].advmap.aname,
2127 MTYPE_BGP_FILTER_NAME);
2128 PEER_ATTR_INHERIT(peer, group, filter[afi][safi].advmap.amap);
2129 PEER_STR_ATTR_INHERIT(peer, group,
2130 filter[afi][safi].advmap.cname,
2131 MTYPE_BGP_FILTER_NAME);
2132 PEER_ATTR_INHERIT(peer, group, filter[afi][safi].advmap.cmap);
2133 PEER_ATTR_INHERIT(peer, group,
2134 filter[afi][safi].advmap.condition);
2135 }
2136
dcc68b5e
MS
2137 if (peer->addpath_type[afi][safi] == BGP_ADDPATH_NONE) {
2138 peer->addpath_type[afi][safi] = conf->addpath_type[afi][safi];
2139 bgp_addpath_type_changed(conf->bgp);
2140 }
9790f44f
DS
2141}
2142
2143static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
d62a17ae 2144{
2145 int active;
9bf904cc 2146 struct peer *other;
718e3744 2147
d62a17ae 2148 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
e50f7cfd 2149 flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s",
1c50c1c0 2150 __func__, peer->host);
d62a17ae 2151 return 1;
2152 }
3f9c7369 2153
d62a17ae 2154 /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST
2155 */
2156 if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST])
2157 || (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST]))
2158 return BGP_ERR_PEER_SAFI_CONFLICT;
2159
2160 /* Nothing to do if we've already activated this peer */
2161 if (peer->afc[afi][safi])
2162 return 0;
2163
2164 if (peer_af_create(peer, afi, safi) == NULL)
2165 return 1;
2166
2167 active = peer_active(peer);
2168 peer->afc[afi][safi] = 1;
2169
9790f44f 2170 if (peer->group)
a4d82a8a 2171 peer_group2peer_config_copy_af(peer->group, peer, afi, safi);
9790f44f 2172
d62a17ae 2173 if (!active && peer_active(peer)) {
2174 bgp_timer_set(peer);
2175 } else {
feb17238 2176 if (peer_established(peer)) {
d62a17ae 2177 if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) {
2178 peer->afc_adv[afi][safi] = 1;
2179 bgp_capability_send(peer, afi, safi,
2180 CAPABILITY_CODE_MP,
2181 CAPABILITY_ACTION_SET);
2182 if (peer->afc_recv[afi][safi]) {
2183 peer->afc_nego[afi][safi] = 1;
e1a32ec1
DS
2184 bgp_announce_route(peer, afi, safi,
2185 false);
d62a17ae 2186 }
2187 } else {
2188 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
2189 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2190 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2191 }
2192 }
64c1a9b5
DS
2193 if (peer->status == OpenSent || peer->status == OpenConfirm) {
2194 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
2195 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2196 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2197 }
9bf904cc
DS
2198 /*
2199 * If we are turning on a AFI/SAFI locally and we've
2200 * started bringing a peer up, we need to tell
2201 * the other peer to restart because we might loose
2202 * configuration here because when the doppelganger
2203 * gets to a established state due to how
2204 * we resolve we could just overwrite the afi/safi
2205 * activation.
2206 */
2207 other = peer->doppelganger;
2208 if (other
2209 && (other->status == OpenSent
2210 || other->status == OpenConfirm)) {
2211 other->last_reset = PEER_DOWN_AF_ACTIVATE;
2212 bgp_notify_send(other, BGP_NOTIFY_CEASE,
2213 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2214 }
d62a17ae 2215 }
04b6bdc0 2216
d62a17ae 2217 return 0;
2218}
9e08021c 2219
d62a17ae 2220/* Activate the peer or peer group for specified AFI and SAFI. */
2221int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
2222{
2223 int ret = 0;
2224 struct peer_group *group;
2225 struct listnode *node, *nnode;
2226 struct peer *tmp_peer;
318cac96 2227 struct bgp *bgp;
d62a17ae 2228
2229 /* Nothing to do if we've already activated this peer */
2230 if (peer->afc[afi][safi])
2231 return ret;
2232
318cac96
DW
2233 bgp = peer->bgp;
2234
d62a17ae 2235 /* This is a peer-group so activate all of the members of the
2236 * peer-group as well */
2237 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
2238
2239 /* Do not activate a peer for both SAFI_UNICAST and
2240 * SAFI_LABELED_UNICAST */
2241 if ((safi == SAFI_UNICAST
2242 && peer->afc[afi][SAFI_LABELED_UNICAST])
2243 || (safi == SAFI_LABELED_UNICAST
2244 && peer->afc[afi][SAFI_UNICAST]))
2245 return BGP_ERR_PEER_SAFI_CONFLICT;
2246
2247 peer->afc[afi][safi] = 1;
2248 group = peer->group;
2249
2250 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
9790f44f 2251 ret |= peer_activate_af(tmp_peer, afi, safi);
d62a17ae 2252 }
2253 } else {
9790f44f 2254 ret |= peer_activate_af(peer, afi, safi);
d62a17ae 2255 }
718e3744 2256
a4d82a8a
PZ
2257 /* If this is the first peer to be activated for this
2258 * afi/labeled-unicast recalc bestpaths to trigger label allocation */
0f3ac819 2259 if (ret != BGP_ERR_PEER_SAFI_CONFLICT && safi == SAFI_LABELED_UNICAST
a4d82a8a 2260 && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
318cac96
DW
2261
2262 if (BGP_DEBUG(zebra, ZEBRA))
4cb5e18b 2263 zlog_debug(
a4d82a8a 2264 "peer(s) are now active for labeled-unicast, allocate MPLS labels");
318cac96
DW
2265
2266 bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1;
2267 bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
2268 }
2269
b98f7728
PG
2270 if (safi == SAFI_FLOWSPEC) {
2271 /* connect to table manager */
6818e7e5 2272 bgp_zebra_init_tm_connect(bgp);
b98f7728 2273 }
d62a17ae 2274 return ret;
718e3744 2275}
6b0655a2 2276
3dc339cd
DA
2277static bool non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
2278 safi_t safi)
718e3744 2279{
d62a17ae 2280 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
e50f7cfd 2281 flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s",
1c50c1c0 2282 __func__, peer->host);
3dc339cd 2283 return true;
d62a17ae 2284 }
718e3744 2285
d62a17ae 2286 /* Nothing to do if we've already deactivated this peer */
2287 if (!peer->afc[afi][safi])
3dc339cd 2288 return false;
718e3744 2289
d62a17ae 2290 /* De-activate the address family configuration. */
2291 peer->afc[afi][safi] = 0;
718e3744 2292
d62a17ae 2293 if (peer_af_delete(peer, afi, safi) != 0) {
e50f7cfd 2294 flog_err(EC_BGP_PEER_DELETE,
601837df
DS
2295 "couldn't delete af structure for peer %s(%s, %s)",
2296 peer->host, afi2str(afi), safi2str(safi));
3dc339cd 2297 return true;
d62a17ae 2298 }
718e3744 2299
feb17238 2300 if (peer_established(peer)) {
d62a17ae 2301 if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) {
2302 peer->afc_adv[afi][safi] = 0;
2303 peer->afc_nego[afi][safi] = 0;
2304
2305 if (peer_active_nego(peer)) {
2306 bgp_capability_send(peer, afi, safi,
2307 CAPABILITY_CODE_MP,
2308 CAPABILITY_ACTION_UNSET);
2309 bgp_clear_route(peer, afi, safi);
2310 peer->pcount[afi][safi] = 0;
2311 } else {
2312 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
2313 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2314 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2315 }
2316 } else {
2317 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
2318 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2319 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2320 }
2321 }
718e3744 2322
3dc339cd 2323 return false;
d62a17ae 2324}
718e3744 2325
d62a17ae 2326int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
718e3744 2327{
d62a17ae 2328 int ret = 0;
2329 struct peer_group *group;
2330 struct peer *tmp_peer;
2331 struct listnode *node, *nnode;
318cac96 2332 struct bgp *bgp;
718e3744 2333
d62a17ae 2334 /* Nothing to do if we've already de-activated this peer */
2335 if (!peer->afc[afi][safi])
2336 return ret;
718e3744 2337
d62a17ae 2338 /* This is a peer-group so de-activate all of the members of the
2339 * peer-group as well */
2340 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
2341 peer->afc[afi][safi] = 0;
2342 group = peer->group;
718e3744 2343
d62a17ae 2344 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
2345 ret |= non_peergroup_deactivate_af(tmp_peer, afi, safi);
2346 }
2347 } else {
2348 ret |= non_peergroup_deactivate_af(peer, afi, safi);
2349 }
718e3744 2350
318cac96
DW
2351 bgp = peer->bgp;
2352
a4d82a8a
PZ
2353 /* If this is the last peer to be deactivated for this
2354 * afi/labeled-unicast recalc bestpaths to trigger label deallocation */
2355 if (safi == SAFI_LABELED_UNICAST
2356 && bgp->allocate_mpls_labels[afi][SAFI_UNICAST]
2357 && !bgp_afi_safi_peer_exists(bgp, afi, safi)) {
318cac96
DW
2358
2359 if (BGP_DEBUG(zebra, ZEBRA))
4cb5e18b 2360 zlog_debug(
a4d82a8a 2361 "peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
318cac96
DW
2362
2363 bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0;
2364 bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
2365 }
d62a17ae 2366 return ret;
2367}
718e3744 2368
d7b3cda6 2369void peer_nsf_stop(struct peer *peer)
718e3744 2370{
d62a17ae 2371 afi_t afi;
2372 safi_t safi;
718e3744 2373
d62a17ae 2374 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
2375 UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
718e3744 2376
df8d723c
DA
2377 FOREACH_AFI_SAFI_NSF (afi, safi)
2378 peer->nsf[afi][safi] = 0;
d62a17ae 2379
2380 if (peer->t_gr_restart) {
fa5806c3 2381 THREAD_OFF(peer->t_gr_restart);
d62a17ae 2382 if (bgp_debug_neighbor_events(peer))
f70c91dc 2383 zlog_debug("%pBP graceful restart timer stopped", peer);
1ff9a340 2384 }
d62a17ae 2385 if (peer->t_gr_stale) {
fa5806c3 2386 THREAD_OFF(peer->t_gr_stale);
d62a17ae 2387 if (bgp_debug_neighbor_events(peer))
2388 zlog_debug(
f70c91dc
DA
2389 "%pBP graceful restart stalepath timer stopped",
2390 peer);
d62a17ae 2391 }
2392 bgp_clear_route_all(peer);
2393}
718e3744 2394
d62a17ae 2395/* Delete peer from confguration.
2396 *
2397 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
2398 * it to "cool off" and refcounts to hit 0, at which state it is freed.
2399 *
2400 * This function /should/ take care to be idempotent, to guard against
2401 * it being called multiple times through stray events that come in
2402 * that happen to result in this function being called again. That
2403 * said, getting here for a "Deleted" peer is a bug in the neighbour
2404 * FSM.
2405 */
2406int peer_delete(struct peer *peer)
2407{
2408 int i;
2409 afi_t afi;
2410 safi_t safi;
2411 struct bgp *bgp;
2412 struct bgp_filter *filter;
2413 struct listnode *pn;
2414 int accept_peer;
f14e6fdb 2415
d62a17ae 2416 assert(peer->status != Deleted);
718e3744 2417
d62a17ae 2418 bgp = peer->bgp;
2419 accept_peer = CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
080b97f2 2420
46aeabed
LS
2421 bgp_soft_reconfig_table_task_cancel(bgp, NULL, peer);
2422
0a6469e5 2423 bgp_keepalives_off(peer);
424ab01d
QY
2424 bgp_reads_off(peer);
2425 bgp_writes_off(peer);
2426 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
2427 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
0a6469e5 2428 assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON));
424ab01d 2429
d62a17ae 2430 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
2431 peer_nsf_stop(peer);
718e3744 2432
d62a17ae 2433 SET_FLAG(peer->flags, PEER_FLAG_DELETE);
718e3744 2434
21bfce98
RZ
2435 /* Remove BFD settings. */
2436 if (peer->bfd_config)
2437 bgp_peer_remove_bfd_config(peer);
e8ba5293 2438
d62a17ae 2439 /* If this peer belongs to peer group, clear up the
2440 relationship. */
2441 if (peer->group) {
2442 if (peer_dynamic_neighbor(peer))
2443 peer_drop_dynamic_neighbor(peer);
718e3744 2444
d62a17ae 2445 if ((pn = listnode_lookup(peer->group->peer, peer))) {
2446 peer = peer_unlock(
2447 peer); /* group->peer list reference */
2448 list_delete_node(peer->group->peer, pn);
2449 }
2450 peer->group = NULL;
2451 }
718e3744 2452
d62a17ae 2453 /* Withdraw all information from routing table. We can not use
2454 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
2455 * executed after peer structure is deleted.
2456 */
2457 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
2458 bgp_stop(peer);
2459 UNSET_FLAG(peer->flags, PEER_FLAG_DELETE);
2460
2461 if (peer->doppelganger) {
2462 peer->doppelganger->doppelganger = NULL;
2463 peer->doppelganger = NULL;
2464 }
718e3744 2465
d62a17ae 2466 UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
2467 bgp_fsm_change_status(peer, Deleted);
718e3744 2468
d62a17ae 2469 /* Remove from NHT */
2470 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
2471 bgp_unlink_nexthop_by_peer(peer);
1ff9a340 2472
d62a17ae 2473 /* Password configuration */
a14810f4 2474 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)) {
d62a17ae 2475 XFREE(MTYPE_PEER_PASSWORD, peer->password);
d62a17ae 2476 if (!accept_peer && !BGP_PEER_SU_UNSPEC(peer)
2734ff6b
PR
2477 && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
2478 && !CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR))
d62a17ae 2479 bgp_md5_unset(peer);
1ff9a340 2480 }
718e3744 2481
d62a17ae 2482 bgp_timer_set(peer); /* stops all timers for Deleted */
718e3744 2483
d62a17ae 2484 /* Delete from all peer list. */
2485 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
2486 && (pn = listnode_lookup(bgp->peer, peer))) {
2487 peer_unlock(peer); /* bgp peer list reference */
2488 list_delete_node(bgp->peer, pn);
2489 hash_release(bgp->peerhash, peer);
2490 }
718e3744 2491
d62a17ae 2492 /* Buffers. */
2493 if (peer->ibuf) {
424ab01d 2494 stream_fifo_free(peer->ibuf);
d62a17ae 2495 peer->ibuf = NULL;
2496 }
f14e6fdb 2497
d62a17ae 2498 if (peer->obuf) {
2499 stream_fifo_free(peer->obuf);
2500 peer->obuf = NULL;
2501 }
f14e6fdb 2502
424ab01d 2503 if (peer->ibuf_work) {
74ffbfe6 2504 ringbuf_del(peer->ibuf_work);
424ab01d
QY
2505 peer->ibuf_work = NULL;
2506 }
2507
2508 if (peer->obuf_work) {
2509 stream_free(peer->obuf_work);
2510 peer->obuf_work = NULL;
d62a17ae 2511 }
f14e6fdb 2512
d62a17ae 2513 if (peer->scratch) {
2514 stream_free(peer->scratch);
2515 peer->scratch = NULL;
2516 }
f14e6fdb 2517
d62a17ae 2518 /* Local and remote addresses. */
2519 if (peer->su_local) {
2520 sockunion_free(peer->su_local);
2521 peer->su_local = NULL;
2522 }
f14e6fdb 2523
d62a17ae 2524 if (peer->su_remote) {
2525 sockunion_free(peer->su_remote);
2526 peer->su_remote = NULL;
2527 }
f14e6fdb 2528
d62a17ae 2529 /* Free filter related memory. */
05c7a1cc
QY
2530 FOREACH_AFI_SAFI (afi, safi) {
2531 filter = &peer->filter[afi][safi];
d62a17ae 2532
05c7a1cc 2533 for (i = FILTER_IN; i < FILTER_MAX; i++) {
e1b36e13
QY
2534 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name);
2535 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name);
2536 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name);
05c7a1cc 2537 }
d62a17ae 2538
05c7a1cc 2539 for (i = RMAP_IN; i < RMAP_MAX; i++) {
e1b36e13 2540 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name);
05c7a1cc
QY
2541 }
2542
e1b36e13
QY
2543 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
2544 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
01da2d26 2545 ecommunity_free(&peer->soo[afi][safi]);
05c7a1cc
QY
2546 }
2547
a2addae8
RW
2548 FOREACH_AFI_SAFI (afi, safi)
2549 peer_af_delete(peer, afi, safi);
f14e6fdb 2550
e1b36e13
QY
2551 XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
2552 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
f14e6fdb 2553
d62a17ae 2554 peer_unlock(peer); /* initial reference */
f14e6fdb 2555
d62a17ae 2556 return 0;
fe7d2a48
DS
2557}
2558
d62a17ae 2559static int peer_group_cmp(struct peer_group *g1, struct peer_group *g2)
2560{
2561 return strcmp(g1->name, g2->name);
6aeb9e78
DS
2562}
2563
d62a17ae 2564/* Peer group cofiguration. */
2565static struct peer_group *peer_group_new(void)
718e3744 2566{
9f5dc319 2567 return XCALLOC(MTYPE_PEER_GROUP, sizeof(struct peer_group));
718e3744 2568}
2569
d62a17ae 2570static void peer_group_free(struct peer_group *group)
718e3744 2571{
d62a17ae 2572 XFREE(MTYPE_PEER_GROUP, group);
718e3744 2573}
2574
d62a17ae 2575struct peer_group *peer_group_lookup(struct bgp *bgp, const char *name)
718e3744 2576{
d62a17ae 2577 struct peer_group *group;
2578 struct listnode *node, *nnode;
2579
2580 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
2581 if (strcmp(group->name, name) == 0)
2582 return group;
2583 }
2584 return NULL;
2585}
2586
2587struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
2588{
2589 struct peer_group *group;
2590 afi_t afi;
38d11af5 2591 safi_t safi;
d62a17ae 2592
2593 group = peer_group_lookup(bgp, name);
2594 if (group)
2595 return group;
2596
2597 group = peer_group_new();
2598 group->bgp = bgp;
0a22ddfb 2599 XFREE(MTYPE_PEER_GROUP_HOST, group->name);
d62a17ae 2600 group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name);
2601 group->peer = list_new();
2602 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2603 group->listen_range[afi] = list_new();
2604 group->conf = peer_new(bgp);
38d11af5
TA
2605 FOREACH_AFI_SAFI (afi, safi) {
2606 if (bgp->default_af[afi][safi])
2607 group->conf->afc[afi][safi] = 1;
2608 }
0a22ddfb 2609 XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
d62a17ae 2610 group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name);
2611 group->conf->group = group;
2612 group->conf->as = 0;
a0903cd2 2613 group->conf->ttl = BGP_DEFAULT_TTL;
e2521429 2614 group->conf->gtsm_hops = BGP_GTSM_HOPS_DISABLED;
d62a17ae 2615 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 2616 SET_FLAG(group->conf->sflags, PEER_STATUS_GROUP);
2617 listnode_add_sort(bgp->group, group);
718e3744 2618
d62a17ae 2619 return group;
718e3744 2620}
2621
d62a17ae 2622static void peer_group2peer_config_copy(struct peer_group *group,
2623 struct peer *peer)
ad4cbda1 2624{
4c391142 2625 uint32_t flags_tmp;
d62a17ae 2626 struct peer *conf;
ad4cbda1 2627
d62a17ae 2628 conf = group->conf;
ad4cbda1 2629
d62a17ae 2630 /* remote-as */
2631 if (conf->as)
2632 peer->as = conf->as;
718e3744 2633
a14810f4
PM
2634 /* local-as */
2635 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_LOCAL_AS))
d62a17ae 2636 peer->change_local_as = conf->change_local_as;
1758dbaa 2637
a0903cd2
DA
2638 /* If peer-group has configured TTL then override it */
2639 if (conf->ttl != BGP_DEFAULT_TTL)
2640 peer->ttl = conf->ttl;
518f0eb1 2641
d62a17ae 2642 /* GTSM hops */
2643 peer->gtsm_hops = conf->gtsm_hops;
ad12dde6 2644
4c391142
PM
2645 /* peer flags apply */
2646 flags_tmp = conf->flags & ~peer->flags_override;
2647 flags_tmp ^= conf->flags_invert ^ peer->flags_invert;
2648 flags_tmp &= ~peer->flags_override;
2649
2650 UNSET_FLAG(peer->flags, ~peer->flags_override);
2651 SET_FLAG(peer->flags, flags_tmp);
2652 SET_FLAG(peer->flags_invert, conf->flags_invert);
ad4cbda1 2653
d62a17ae 2654 /* peer timers apply */
b90a8e13
PM
2655 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER)) {
2656 PEER_ATTR_INHERIT(peer, group, holdtime);
2657 PEER_ATTR_INHERIT(peer, group, keepalive);
2658 }
6aeb9e78 2659
b90a8e13
PM
2660 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER_CONNECT)) {
2661 PEER_ATTR_INHERIT(peer, group, connect);
2662 if (CHECK_FLAG(conf->flags, PEER_FLAG_TIMER_CONNECT))
2663 peer->v_connect = conf->connect;
2664 else
5d5393b9 2665 peer->v_connect = peer->bgp->default_connect_retry;
b90a8e13
PM
2666 }
2667
6c537a18
DS
2668 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER_DELAYOPEN)) {
2669 PEER_ATTR_INHERIT(peer, group, delayopen);
2670 if (CHECK_FLAG(conf->flags, PEER_FLAG_TIMER_DELAYOPEN))
2671 peer->v_delayopen = conf->delayopen;
2672 else
2673 peer->v_delayopen = peer->bgp->default_delayopen;
2674 }
2675
b90a8e13
PM
2676 /* advertisement-interval apply */
2677 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_ROUTEADV)) {
2678 PEER_ATTR_INHERIT(peer, group, routeadv);
2679 if (CHECK_FLAG(conf->flags, PEER_FLAG_ROUTEADV))
2680 peer->v_routeadv = conf->routeadv;
2681 else
2682 peer->v_routeadv = (peer_sort(peer) == BGP_PEER_IBGP)
2683 ? BGP_DEFAULT_IBGP_ROUTEADV
2684 : BGP_DEFAULT_EBGP_ROUTEADV;
2685 }
718e3744 2686
b3a3290e
DS
2687 /* capability extended-nexthop apply */
2688 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_CAPABILITY_ENHE))
2689 if (CHECK_FLAG(conf->flags, PEER_FLAG_CAPABILITY_ENHE))
2690 SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE);
2691
d62a17ae 2692 /* password apply */
a14810f4
PM
2693 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
2694 PEER_STR_ATTR_INHERIT(peer, group, password,
2695 MTYPE_PEER_PASSWORD);
718e3744 2696
d62a17ae 2697 if (!BGP_PEER_SU_UNSPEC(peer))
2698 bgp_md5_set(peer);
d4a7a753 2699
d62a17ae 2700 /* update-source apply */
a14810f4
PM
2701 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_UPDATE_SOURCE)) {
2702 if (conf->update_source) {
d62a17ae 2703 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
a14810f4
PM
2704 PEER_SU_ATTR_INHERIT(peer, group, update_source);
2705 } else if (conf->update_if) {
d62a17ae 2706 sockunion_free(peer->update_source);
a14810f4
PM
2707 PEER_STR_ATTR_INHERIT(peer, group, update_if,
2708 MTYPE_PEER_UPDATE_SOURCE);
d62a17ae 2709 }
d62a17ae 2710 }
cd92e548 2711
7dddd1f7
DA
2712 /* role */
2713 PEER_ATTR_INHERIT(peer, group, local_role);
2714
0c0b85b5
NT
2715 /* Update GR flags for the peer. */
2716 bgp_peer_gr_flags_update(peer);
2717
21bfce98
RZ
2718 /* Apply BFD settings from group to peer if it exists. */
2719 if (conf->bfd_config) {
2720 bgp_peer_configure_bfd(peer, false);
2721 bgp_peer_config_apply(peer, group);
2722 }
ad4cbda1 2723}
718e3744 2724
d62a17ae 2725/* Peer group's remote AS configuration. */
2726int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,
2727 int as_type)
f14e6fdb 2728{
d62a17ae 2729 struct peer_group *group;
2730 struct peer *peer;
2731 struct listnode *node, *nnode;
f14e6fdb 2732
d62a17ae 2733 group = peer_group_lookup(bgp, group_name);
2734 if (!group)
2735 return -1;
f14e6fdb 2736
d62a17ae 2737 if ((as_type == group->conf->as_type) && (group->conf->as == *as))
2738 return 0;
f14e6fdb 2739
f14e6fdb 2740
d62a17ae 2741 /* When we setup peer-group AS number all peer group member's AS
2742 number must be updated to same number. */
2743 peer_as_change(group->conf, *as, as_type);
f14e6fdb 2744
d62a17ae 2745 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2746 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)
2747 || (peer->as_type != as_type))
2748 peer_as_change(peer, *as, as_type);
2749 }
f14e6fdb 2750
d62a17ae 2751 return 0;
f14e6fdb
DS
2752}
2753
3dc339cd 2754void peer_notify_unconfig(struct peer *peer)
4e2786df
DA
2755{
2756 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2757 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2758 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
4e2786df
DA
2759}
2760
3dc339cd 2761void peer_group_notify_unconfig(struct peer_group *group)
4e2786df
DA
2762{
2763 struct peer *peer, *other;
2764 struct listnode *node, *nnode;
2765
2766 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2767 other = peer->doppelganger;
2768 if (other && other->status != Deleted) {
2769 other->group = NULL;
2770 peer_notify_unconfig(other);
2771 } else
2772 peer_notify_unconfig(peer);
2773 }
4e2786df
DA
2774}
2775
d62a17ae 2776int peer_group_delete(struct peer_group *group)
f14e6fdb 2777{
d62a17ae 2778 struct bgp *bgp;
2779 struct peer *peer;
2780 struct prefix *prefix;
2781 struct peer *other;
2782 struct listnode *node, *nnode;
2783 afi_t afi;
f14e6fdb 2784
d62a17ae 2785 bgp = group->bgp;
f14e6fdb 2786
d62a17ae 2787 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2788 other = peer->doppelganger;
b3a3290e
DS
2789
2790 if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
2791 bgp_zebra_terminate_radv(bgp, peer);
2792
d62a17ae 2793 peer_delete(peer);
2794 if (other && other->status != Deleted) {
2795 other->group = NULL;
2796 peer_delete(other);
2797 }
2798 }
6a154c88 2799 list_delete(&group->peer);
f14e6fdb 2800
d62a17ae 2801 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
2802 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
2803 prefix)) {
63265b5c 2804 prefix_free(&prefix);
d62a17ae 2805 }
6a154c88 2806 list_delete(&group->listen_range[afi]);
d62a17ae 2807 }
f14e6fdb 2808
d62a17ae 2809 XFREE(MTYPE_PEER_GROUP_HOST, group->name);
2810 group->name = NULL;
0299c004 2811
21bfce98
RZ
2812 if (group->conf->bfd_config)
2813 bgp_peer_remove_bfd_config(group->conf);
f14e6fdb 2814
d62a17ae 2815 group->conf->group = NULL;
2816 peer_delete(group->conf);
f14e6fdb 2817
d62a17ae 2818 /* Delete from all peer_group list. */
2819 listnode_delete(bgp->group, group);
f14e6fdb 2820
d62a17ae 2821 peer_group_free(group);
f14e6fdb 2822
d62a17ae 2823 return 0;
2824}
f14e6fdb 2825
d62a17ae 2826int peer_group_remote_as_delete(struct peer_group *group)
2827{
2828 struct peer *peer, *other;
2829 struct listnode *node, *nnode;
f14e6fdb 2830
d62a17ae 2831 if ((group->conf->as_type == AS_UNSPECIFIED)
2832 || ((!group->conf->as) && (group->conf->as_type == AS_SPECIFIED)))
2833 return 0;
f14e6fdb 2834
d62a17ae 2835 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2836 other = peer->doppelganger;
f14e6fdb 2837
b3a3290e
DS
2838 if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
2839 bgp_zebra_terminate_radv(peer->bgp, peer);
2840
d62a17ae 2841 peer_delete(peer);
f14e6fdb 2842
d62a17ae 2843 if (other && other->status != Deleted) {
2844 other->group = NULL;
2845 peer_delete(other);
2846 }
2847 }
2848 list_delete_all_node(group->peer);
f14e6fdb 2849
d62a17ae 2850 group->conf->as = 0;
2851 group->conf->as_type = AS_UNSPECIFIED;
f14e6fdb 2852
d62a17ae 2853 return 0;
f14e6fdb 2854}
d62a17ae 2855
2856int peer_group_listen_range_add(struct peer_group *group, struct prefix *range)
f14e6fdb 2857{
d62a17ae 2858 struct prefix *prefix;
2859 struct listnode *node, *nnode;
2860 afi_t afi;
f14e6fdb 2861
d62a17ae 2862 afi = family2afi(range->family);
f14e6fdb 2863
d62a17ae 2864 /* Group needs remote AS configured. */
2865 if (group->conf->as_type == AS_UNSPECIFIED)
2866 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
718e3744 2867
d62a17ae 2868 /* Ensure no duplicates. Currently we don't care about overlaps. */
2869 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) {
2870 if (prefix_same(range, prefix))
2871 return 0;
2872 }
2873
2874 prefix = prefix_new();
2875 prefix_copy(prefix, range);
2876 listnode_add(group->listen_range[afi], prefix);
9e7d9a61
QY
2877
2878 /* Update passwords for new ranges */
2879 if (group->conf->password)
a4faae3a 2880 bgp_md5_set_prefix(group->bgp, prefix, group->conf->password);
9e7d9a61 2881
d62a17ae 2882 return 0;
718e3744 2883}
6b0655a2 2884
d62a17ae 2885int peer_group_listen_range_del(struct peer_group *group, struct prefix *range)
718e3744 2886{
d62a17ae 2887 struct prefix *prefix, prefix2;
2888 struct listnode *node, *nnode;
2889 struct peer *peer;
2890 afi_t afi;
718e3744 2891
d62a17ae 2892 afi = family2afi(range->family);
1ff9a340 2893
d62a17ae 2894 /* Identify the listen range. */
2895 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) {
2896 if (prefix_same(range, prefix))
2897 break;
1ff9a340 2898 }
718e3744 2899
d62a17ae 2900 if (!prefix)
2901 return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND;
2902
d62a17ae 2903 /* Dispose off any dynamic neighbors that exist due to this listen range
2904 */
2905 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2906 if (!peer_dynamic_neighbor(peer))
2907 continue;
2908
0154d8ce
DS
2909 if (sockunion2hostprefix(&peer->su, &prefix2)
2910 && prefix_match(prefix, &prefix2)) {
d62a17ae 2911 if (bgp_debug_neighbor_events(peer))
2912 zlog_debug(
2dbe669b
DA
2913 "Deleting dynamic neighbor %s group %s upon delete of listen range %pFX",
2914 peer->host, group->name, prefix);
d62a17ae 2915 peer_delete(peer);
2916 }
2917 }
718e3744 2918
d62a17ae 2919 /* Get rid of the listen range */
2920 listnode_delete(group->listen_range[afi], prefix);
718e3744 2921
9e7d9a61
QY
2922 /* Remove passwords for deleted ranges */
2923 if (group->conf->password)
a4faae3a 2924 bgp_md5_unset_prefix(group->bgp, prefix);
9e7d9a61 2925
d62a17ae 2926 return 0;
2927}
e0701b79 2928
d62a17ae 2929/* Bind specified peer to peer group. */
2930int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
2931 struct peer_group *group, as_t *as)
2932{
2933 int first_member = 0;
2934 afi_t afi;
2935 safi_t safi;
3061acc2 2936 enum bgp_peer_sort ptype, gtype;
d62a17ae 2937
2938 /* Lookup the peer. */
2939 if (!peer)
2940 peer = peer_lookup(bgp, su);
2941
2942 /* The peer exist, bind it to the peer-group */
2943 if (peer) {
ed9fb826 2944 /* When the peer already belongs to a peer-group, check the
d62a17ae 2945 * consistency. */
ed9fb826
DW
2946 if (peer_group_active(peer)) {
2947
2948 /* The peer is already bound to the peer-group,
d8a079e8
DW
2949 * nothing to do
2950 */
ed9fb826
DW
2951 if (strcmp(peer->group->name, group->name) == 0)
2952 return 0;
2953 else
2954 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
2955 }
d62a17ae 2956
2957 /* The peer has not specified a remote-as, inherit it from the
2958 * peer-group */
2959 if (peer->as_type == AS_UNSPECIFIED) {
2960 peer->as_type = group->conf->as_type;
2961 peer->as = group->conf->as;
faa16034 2962 peer->sort = group->conf->sort;
d62a17ae 2963 }
718e3744 2964
469cbb0f
DS
2965 ptype = peer_sort(peer);
2966 if (!group->conf->as && ptype != BGP_PEER_UNSPECIFIED) {
2967 gtype = peer_sort(group->conf);
2968 if ((gtype != BGP_PEER_INTERNAL) && (gtype != ptype)) {
d62a17ae 2969 if (as)
2970 *as = peer->as;
2971 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
2972 }
718e3744 2973
469cbb0f 2974 if (gtype == BGP_PEER_INTERNAL)
d62a17ae 2975 first_member = 1;
2976 }
718e3744 2977
d62a17ae 2978 peer_group2peer_config_copy(group, peer);
2979
05c7a1cc
QY
2980 FOREACH_AFI_SAFI (afi, safi) {
2981 if (group->conf->afc[afi][safi]) {
2982 peer->afc[afi][safi] = 1;
2983
2984 if (peer_af_find(peer, afi, safi)
2985 || peer_af_create(peer, afi, safi)) {
2986 peer_group2peer_config_copy_af(
2987 group, peer, afi, safi);
2988 }
2989 } else if (peer->afc[afi][safi])
2990 peer_deactivate(peer, afi, safi);
a4d82a8a 2991 }
d62a17ae 2992
2993 if (peer->group) {
2994 assert(group && peer->group == group);
2995 } else {
0866cdaf
A
2996 listnode_delete(bgp->peer, peer);
2997
d62a17ae 2998 peer->group = group;
2999 listnode_add_sort(bgp->peer, peer);
3000
3001 peer = peer_lock(peer); /* group->peer list reference */
3002 listnode_add(group->peer, peer);
3003 }
718e3744 3004
d62a17ae 3005 if (first_member) {
469cbb0f 3006 gtype = peer_sort(group->conf);
d62a17ae 3007 /* Advertisement-interval reset */
b90a8e13
PM
3008 if (!CHECK_FLAG(group->conf->flags,
3009 PEER_FLAG_ROUTEADV)) {
3010 group->conf->v_routeadv =
469cbb0f 3011 (gtype == BGP_PEER_IBGP)
b90a8e13
PM
3012 ? BGP_DEFAULT_IBGP_ROUTEADV
3013 : BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 3014 }
3015
3016 /* ebgp-multihop reset */
469cbb0f 3017 if (gtype == BGP_PEER_IBGP)
d62a17ae 3018 group->conf->ttl = MAXTTL;
3019
3020 /* local-as reset */
469cbb0f 3021 if (gtype != BGP_PEER_EBGP) {
d62a17ae 3022 group->conf->change_local_as = 0;
a14810f4
PM
3023 peer_flag_unset(group->conf,
3024 PEER_FLAG_LOCAL_AS);
3025 peer_flag_unset(group->conf,
3026 PEER_FLAG_LOCAL_AS_NO_PREPEND);
3027 peer_flag_unset(group->conf,
3028 PEER_FLAG_LOCAL_AS_REPLACE_AS);
d62a17ae 3029 }
3030 }
718e3744 3031
d62a17ae 3032 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 3033
d62a17ae 3034 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
3035 peer->last_reset = PEER_DOWN_RMAP_BIND;
3036 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3037 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3038 } else {
3039 bgp_session_reset(peer);
3040 }
3041 }
718e3744 3042
d62a17ae 3043 /* Create a new peer. */
3044 else {
3045 if ((group->conf->as_type == AS_SPECIFIED)
3046 && (!group->conf->as)) {
3047 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
3048 }
718e3744 3049
d62a17ae 3050 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
e84c59af 3051 group->conf->as_type, group);
718e3744 3052
d62a17ae 3053 peer = peer_lock(peer); /* group->peer list reference */
3054 listnode_add(group->peer, peer);
718e3744 3055
d62a17ae 3056 peer_group2peer_config_copy(group, peer);
a4ed4829 3057
d62a17ae 3058 /* If the peer-group is active for this afi/safi then activate
3059 * for this peer */
05c7a1cc
QY
3060 FOREACH_AFI_SAFI (afi, safi) {
3061 if (group->conf->afc[afi][safi]) {
3062 peer->afc[afi][safi] = 1;
e84c59af
DA
3063
3064 if (!peer_af_find(peer, afi, safi))
3065 peer_af_create(peer, afi, safi);
3066
05c7a1cc
QY
3067 peer_group2peer_config_copy_af(group, peer, afi,
3068 safi);
3069 } else if (peer->afc[afi][safi])
3070 peer_deactivate(peer, afi, safi);
3071 }
718e3744 3072
d62a17ae 3073 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 3074
d62a17ae 3075 /* Set up peer's events and timers. */
3076 if (peer_active(peer))
3077 bgp_timer_set(peer);
3078 }
718e3744 3079
d62a17ae 3080 return 0;
718e3744 3081}
3082
cc9f21da 3083static void bgp_startup_timer_expire(struct thread *thread)
d62a17ae 3084{
3085 struct bgp *bgp;
718e3744 3086
d62a17ae 3087 bgp = THREAD_ARG(thread);
3088 bgp->t_startup = NULL;
d62a17ae 3089}
e0701b79 3090
829e590b
DS
3091/*
3092 * On shutdown we call the cleanup function which
3093 * does a free of the link list nodes, free up
3094 * the data we are pointing at too.
3095 */
3096static void bgp_vrf_string_name_delete(void *data)
3097{
3098 char *vname = data;
3099
3100 XFREE(MTYPE_TMP, vname);
3101}
3102
d62a17ae 3103/* BGP instance creation by `router bgp' commands. */
3104static struct bgp *bgp_create(as_t *as, const char *name,
3105 enum bgp_instance_type inst_type)
3106{
0291c246
MK
3107 struct bgp *bgp;
3108 afi_t afi;
3109 safi_t safi;
d62a17ae 3110
4953391b 3111 bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp));
d62a17ae 3112
3113 if (BGP_DEBUG(zebra, ZEBRA)) {
3114 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3115 zlog_debug("Creating Default VRF, AS %u", *as);
3116 else
3117 zlog_debug("Creating %s %s, AS %u",
3118 (inst_type == BGP_INSTANCE_TYPE_VRF)
3119 ? "VRF"
3120 : "VIEW",
3121 name, *as);
718e3744 3122 }
adbac85e 3123
e2f3a930
T
3124 /* Default the EVPN VRF to the default one */
3125 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !bgp_master.bgp_evpn) {
3126 bgp_lock(bgp);
3127 bm->bgp_evpn = bgp;
3128 }
3129
d62a17ae 3130 bgp_lock(bgp);
b6c386bb 3131
8666265e 3132 bgp->allow_martian = false;
b6c386bb 3133 bgp_process_queue_init(bgp);
9df5ac49 3134 bgp->heuristic_coalesce = true;
d62a17ae 3135 bgp->inst_type = inst_type;
3136 bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT
3137 : VRF_UNKNOWN;
3138 bgp->peer_self = peer_new(bgp);
0a22ddfb 3139 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
d62a17ae 3140 bgp->peer_self->host =
3141 XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
e1b36e13 3142 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->hostname);
6b3ee3a0 3143 if (cmd_hostname_get())
60466a63
QY
3144 bgp->peer_self->hostname =
3145 XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_hostname_get());
d77114b7 3146
e1b36e13 3147 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->domainname);
6b3ee3a0 3148 if (cmd_domainname_get())
60466a63
QY
3149 bgp->peer_self->domainname =
3150 XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_domainname_get());
d62a17ae 3151 bgp->peer = list_new();
3152 bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
a4d82a8a 3153 bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same,
3f65c5b1 3154 "BGP Peer Hash");
40520c36 3155 bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
d62a17ae 3156
3157 bgp->group = list_new();
3158 bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
3159
05c7a1cc 3160 FOREACH_AFI_SAFI (afi, safi) {
960035b2
PZ
3161 bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
3162 bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi);
3163 bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
05c7a1cc
QY
3164
3165 /* Enable maximum-paths */
3166 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
3167 multipath_num, 0);
3168 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP,
3169 multipath_num, 0);
cfd47646 3170 /* Initialize graceful restart info */
3171 bgp->gr_info[afi][safi].eor_required = 0;
3172 bgp->gr_info[afi][safi].eor_received = 0;
3173 bgp->gr_info[afi][safi].t_select_deferral = NULL;
3174 bgp->gr_info[afi][safi].t_route_select = NULL;
26742171 3175 bgp->gr_info[afi][safi].gr_deferred = 0;
05c7a1cc 3176 }
d62a17ae 3177
d70583f7
D
3178 bgp->v_update_delay = bm->v_update_delay;
3179 bgp->v_establish_wait = bm->v_establish_wait;
d62a17ae 3180 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
3181 bgp->default_subgroup_pkt_queue_max =
3182 BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
5d5393b9 3183 bgp_timers_unset(bgp);
b042667a 3184 bgp->default_min_holdtime = 0;
d62a17ae 3185 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
3186 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
cfd47646 3187 bgp->select_defer_time = BGP_DEFAULT_SELECT_DEFERRAL_TIME;
dc95985f 3188 bgp->rib_stale_time = BGP_DEFAULT_RIB_STALE_TIME;
d62a17ae 3189 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
3190 bgp->dynamic_neighbors_count = 0;
b1875e65 3191 bgp->lb_ref_bw = BGP_LINK_BW_REF_BW;
f7e1c681 3192 bgp->lb_handling = BGP_LINK_BW_ECMP;
7f972cd8 3193 bgp->reject_as_sets = false;
389e4f92 3194 bgp->condition_check_period = DEFAULT_CONDITIONAL_ROUTES_POLL_TIME;
dcc68b5e 3195 bgp_addpath_init_bgp_data(&bgp->tx_addpath);
f852eb98 3196 bgp->fast_convergence = false;
d62a17ae 3197 bgp->as = *as;
8606be87 3198 bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
d62a17ae 3199
49e5a4a0 3200#ifdef ENABLE_BGP_VNC
d62a17ae 3201 if (inst_type != BGP_INSTANCE_TYPE_VRF) {
3202 bgp->rfapi = bgp_rfapi_new(bgp);
3203 assert(bgp->rfapi);
3204 assert(bgp->rfapi_cfg);
3205 }
3206#endif /* ENABLE_BGP_VNC */
adbac85e 3207
ddb5b488 3208 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
e70e9f8e
PZ
3209 bgp->vpn_policy[afi].bgp = bgp;
3210 bgp->vpn_policy[afi].afi = afi;
ddb5b488
PZ
3211 bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
3212 bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
3213 MPLS_LABEL_NONE;
12a844a5
DS
3214
3215 bgp->vpn_policy[afi].import_vrf = list_new();
829e590b
DS
3216 bgp->vpn_policy[afi].import_vrf->del =
3217 bgp_vrf_string_name_delete;
12a844a5 3218 bgp->vpn_policy[afi].export_vrf = list_new();
829e590b
DS
3219 bgp->vpn_policy[afi].export_vrf->del =
3220 bgp_vrf_string_name_delete;
a486300b
PG
3221 SET_FLAG(bgp->af_flags[afi][SAFI_MPLS_VPN],
3222 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
ddb5b488 3223 }
dc95985f 3224 if (name)
d62a17ae 3225 bgp->name = XSTRDUP(MTYPE_BGP, name);
dc95985f 3226
3227 thread_add_timer(bm->master, bgp_startup_timer_expire, bgp,
36235319 3228 bgp->restart_time, &bgp->t_startup);
06370dac 3229
3572fb26
PZ
3230 /* printable name we can use in debug messages */
3231 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
3232 bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
3233 } else {
3234 const char *n;
3235 int len;
3236
3237 if (bgp->name)
3238 n = bgp->name;
3239 else
3240 n = "?";
3241
3242 len = 4 + 1 + strlen(n) + 1; /* "view foo\0" */
3243
3244 bgp->name_pretty = XCALLOC(MTYPE_BGP, len);
3245 snprintf(bgp->name_pretty, len, "%s %s",
3246 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3247 ? "VRF"
3248 : "VIEW",
3249 n);
3250 }
3251
555e09d4
QY
3252 atomic_store_explicit(&bgp->wpkt_quanta, BGP_WRITE_PACKET_MAX,
3253 memory_order_relaxed);
3254 atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
3255 memory_order_relaxed);
d62a17ae 3256 bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
b16bcbba 3257 bgp->default_af[AFI_IP][SAFI_UNICAST] = true;
adbac85e 3258
d62a17ae 3259 QOBJ_REG(bgp, bgp);
adbac85e 3260
d62a17ae 3261 update_bgp_group_init(bgp);
92708db6 3262
3263 /* assign a unique rd id for auto derivation of vrf's RD */
3264 bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
3265
85c8d83b
CS
3266 bgp->evpn_info = XCALLOC(MTYPE_BGP_EVPN_INFO,
3267 sizeof(struct bgp_evpn_info));
d62a17ae 3268 bgp_evpn_init(bgp);
c589d847 3269 bgp_evpn_vrf_es_init(bgp);
f3d32faa 3270 bgp_pbr_init(bgp);
92a9e6f2 3271 bgp_srv6_init(bgp);
794b37d5 3272
3273 /*initilize global GR FSM */
3274 bgp_global_gr_init(bgp);
b17826b7
DS
3275
3276 memset(&bgp->ebgprequirespolicywarning, 0,
3277 sizeof(bgp->ebgprequirespolicywarning));
3278
d62a17ae 3279 return bgp;
718e3744 3280}
3281
d62a17ae 3282/* Return the "default VRF" instance of BGP. */
3283struct bgp *bgp_get_default(void)
718e3744 3284{
d62a17ae 3285 struct bgp *bgp;
3286 struct listnode *node, *nnode;
3287
3288 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3289 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3290 return bgp;
3291 return NULL;
718e3744 3292}
3293
d62a17ae 3294/* Lookup BGP entry. */
3295struct bgp *bgp_lookup(as_t as, const char *name)
718e3744 3296{
d62a17ae 3297 struct bgp *bgp;
3298 struct listnode *node, *nnode;
6b0655a2 3299
d62a17ae 3300 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3301 if (bgp->as == as
3302 && ((bgp->name == NULL && name == NULL)
3303 || (bgp->name && name && strcmp(bgp->name, name) == 0)))
3304 return bgp;
3305 return NULL;
3306}
73d70fa6 3307
d62a17ae 3308/* Lookup BGP structure by view name. */
3309struct bgp *bgp_lookup_by_name(const char *name)
73d70fa6 3310{
d62a17ae 3311 struct bgp *bgp;
3312 struct listnode *node, *nnode;
3313
3314 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3315 if ((bgp->name == NULL && name == NULL)
3316 || (bgp->name && name && strcmp(bgp->name, name) == 0))
3317 return bgp;
3318 return NULL;
73d70fa6
DL
3319}
3320
d62a17ae 3321/* Lookup BGP instance based on VRF id. */
3322/* Note: Only to be used for incoming messages from Zebra. */
3323struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
73d70fa6 3324{
d62a17ae 3325 struct vrf *vrf;
3326
3327 /* Lookup VRF (in tree) and follow link. */
3328 vrf = vrf_lookup_by_id(vrf_id);
3329 if (!vrf)
3330 return NULL;
3331 return (vrf->info) ? (struct bgp *)vrf->info : NULL;
73d70fa6
DL
3332}
3333
e2f3a930
T
3334/* Sets the BGP instance where EVPN is enabled */
3335void bgp_set_evpn(struct bgp *bgp)
3336{
3337 if (bm->bgp_evpn == bgp)
3338 return;
3339
3340 /* First, release the reference count we hold on the instance */
3341 if (bm->bgp_evpn)
3342 bgp_unlock(bm->bgp_evpn);
3343
3344 bm->bgp_evpn = bgp;
3345
3346 /* Increase the reference count on this new VRF */
3347 if (bm->bgp_evpn)
3348 bgp_lock(bm->bgp_evpn);
3349}
3350
3351/* Returns the BGP instance where EVPN is enabled, if any */
3352struct bgp *bgp_get_evpn(void)
3353{
3354 return bm->bgp_evpn;
3355}
3356
e5619c28
PG
3357/* handle socket creation or deletion, if necessary
3358 * this is called for all new BGP instances
3359 */
996c9314
LB
3360int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id,
3361 bool create)
e5619c28 3362{
85e9cd9a
AMR
3363 struct listnode *node;
3364 char *address;
e5619c28
PG
3365
3366 /* Create BGP server socket, if listen mode not disabled */
3367 if (!bgp || bgp_option_check(BGP_OPT_NO_LISTEN))
3368 return 0;
3ad00234 3369 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
e5619c28
PG
3370 /*
3371 * suppress vrf socket
3372 */
a8f58eb6 3373 if (!create) {
3ad00234
LB
3374 bgp_close_vrf_socket(bgp);
3375 return 0;
e5619c28 3376 }
3ad00234
LB
3377 if (vrf == NULL)
3378 return BGP_ERR_INVALID_VALUE;
e5619c28
PG
3379 /* do nothing
3380 * if vrf_id did not change
3381 */
3382 if (vrf->vrf_id == old_vrf_id)
3383 return 0;
3384 if (old_vrf_id != VRF_UNKNOWN) {
3385 /* look for old socket. close it. */
3386 bgp_close_vrf_socket(bgp);
3387 }
3388 /* if backend is not yet identified ( VRF_UNKNOWN) then
3389 * creation will be done later
3390 */
3391 if (vrf->vrf_id == VRF_UNKNOWN)
3392 return 0;
85e9cd9a
AMR
3393 if (list_isempty(bm->addresses)) {
3394 if (bgp_socket(bgp, bm->port, NULL) < 0)
3395 return BGP_ERR_INVALID_VALUE;
3396 } else {
3397 for (ALL_LIST_ELEMENTS_RO(bm->addresses, node, address))
3398 if (bgp_socket(bgp, bm->port, address) < 0)
3399 return BGP_ERR_INVALID_VALUE;
3400 }
3ad00234
LB
3401 return 0;
3402 } else
3403 return bgp_check_main_socket(create, bgp);
e5619c28
PG
3404}
3405
bdaadb91
CS
3406int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,
3407 enum bgp_instance_type inst_type)
d62a17ae 3408{
3409 struct bgp *bgp;
3410
3411 /* Multiple instance check. */
8fbb4853
DS
3412 if (name)
3413 bgp = bgp_lookup_by_name(name);
3414 else
d62a17ae 3415 bgp = bgp_get_default();
3416
8fbb4853 3417 if (bgp) {
0d6d0208 3418 *bgp_val = bgp;
8fbb4853
DS
3419 if (bgp->as != *as) {
3420 *as = bgp->as;
d09328e5 3421 return BGP_ERR_AS_MISMATCH;
d62a17ae 3422 }
8fbb4853
DS
3423 if (bgp->inst_type != inst_type)
3424 return BGP_ERR_INSTANCE_MISMATCH;
d5568431 3425 return BGP_SUCCESS;
d62a17ae 3426 }
bdaadb91
CS
3427 *bgp_val = NULL;
3428
3429 return BGP_SUCCESS;
3430}
3431
3432/* Called from VTY commands. */
3433int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
3434 enum bgp_instance_type inst_type)
3435{
3436 struct bgp *bgp;
3437 struct vrf *vrf = NULL;
3438 int ret = 0;
3439
3440 ret = bgp_lookup_by_as_name_type(bgp_val, as, name, inst_type);
d09328e5 3441 if (ret || *bgp_val)
bdaadb91 3442 return ret;
73d70fa6 3443
d62a17ae 3444 bgp = bgp_create(as, name, inst_type);
e7682ccd
DS
3445
3446 /*
3447 * view instances will never work inside of a vrf
3448 * as such they must always be in the VRF_DEFAULT
3449 * Also we must set this to something useful because
3450 * of the vrf socket code needing an actual useful
3451 * default value to send to the underlying OS.
3452 *
3453 * This code is currently ignoring vrf based
3454 * code using the -Z option( and that is probably
3455 * best addressed elsewhere in the code )
3456 */
3457 if (inst_type == BGP_INSTANCE_TYPE_VIEW)
3458 bgp->vrf_id = VRF_DEFAULT;
3459
2951a7a4 3460 bgp_router_id_set(bgp, &bgp->router_id_zebra, true);
d62a17ae 3461 bgp_address_init(bgp);
db0e1937 3462 bgp_tip_hash_init(bgp);
d62a17ae 3463 bgp_scan_init(bgp);
3464 *bgp_val = bgp;
eb821189 3465
d62a17ae 3466 bgp->t_rmap_def_originate_eval = NULL;
e5cc509c 3467
d62a17ae 3468 /* If Default instance or VRF, link to the VRF structure, if present. */
3469 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
3470 || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
d62a17ae 3471 vrf = bgp_vrf_lookup_by_instance_type(bgp);
3472 if (vrf)
3473 bgp_vrf_link(bgp, vrf);
3474 }
e5619c28
PG
3475 /* BGP server socket already processed if BGP instance
3476 * already part of the list
3477 */
3478 bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, true);
3479 listnode_add(bm->bgp, bgp);
718e3744 3480
bb4ef1ae
DS
3481 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
3482 if (BGP_DEBUG(zebra, ZEBRA))
3483 zlog_debug("%s: Registering BGP instance %s to zebra",
15569c58 3484 __func__, name);
d62a17ae 3485 bgp_zebra_instance_register(bgp);
bb4ef1ae 3486 }
718e3744 3487
5d5393b9 3488 return BGP_CREATED;
718e3744 3489}
6b0655a2 3490
6cc0114b
IR
3491static void bgp_zclient_set_redist(afi_t afi, int type, unsigned short instance,
3492 vrf_id_t vrf_id, bool set)
3493{
3494 if (instance) {
3495 if (set)
3496 redist_add_instance(&zclient->mi_redist[afi][type],
3497 instance);
3498 else
3499 redist_del_instance(&zclient->mi_redist[afi][type],
3500 instance);
3501 } else {
3502 if (set)
3503 vrf_bitmap_set(zclient->redist[afi][type], vrf_id);
3504 else
3505 vrf_bitmap_unset(zclient->redist[afi][type], vrf_id);
3506 }
3507}
3508
3509static void bgp_set_redist_vrf_bitmaps(struct bgp *bgp, bool set)
3510{
3511 afi_t afi;
3512 int i;
3513 struct list *red_list;
3514 struct listnode *node;
3515 struct bgp_redist *red;
3516
3517 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
3518 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
3519
3520 red_list = bgp->redist[afi][i];
3521 if (!red_list)
3522 continue;
3523
3524 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
3525 bgp_zclient_set_redist(afi, i, red->instance,
3526 bgp->vrf_id, set);
3527 }
3528 }
3529}
3530
d62a17ae 3531/*
3532 * Make BGP instance "up". Applies only to VRFs (non-default) and
3533 * implies the VRF has been learnt from Zebra.
3534 */
3535void bgp_instance_up(struct bgp *bgp)
718e3744 3536{
d62a17ae 3537 struct peer *peer;
3538 struct listnode *node, *next;
718e3744 3539
6cc0114b
IR
3540 bgp_set_redist_vrf_bitmaps(bgp, true);
3541
d62a17ae 3542 /* Register with zebra. */
3543 bgp_zebra_instance_register(bgp);
718e3744 3544
d62a17ae 3545 /* Kick off any peers that may have been configured. */
3546 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3547 if (!BGP_PEER_START_SUPPRESSED(peer))
3548 BGP_EVENT_ADD(peer, BGP_Start);
718e3744 3549 }
3550
d62a17ae 3551 /* Process any networks that have been configured. */
3552 bgp_static_add(bgp);
3553}
3554
3555/*
3556 * Make BGP instance "down". Applies only to VRFs (non-default) and
3557 * implies the VRF has been deleted by Zebra.
3558 */
3559void bgp_instance_down(struct bgp *bgp)
3560{
3561 struct peer *peer;
3562 struct listnode *node;
3563 struct listnode *next;
3564
3565 /* Stop timers. */
3566 if (bgp->t_rmap_def_originate_eval) {
fa5806c3 3567 THREAD_OFF(bgp->t_rmap_def_originate_eval);
d62a17ae 3568 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3569 why? */
718e3744 3570 }
3571
d62a17ae 3572 /* Bring down peers, so corresponding routes are purged. */
3573 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3574 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3575 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3576 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3577 else
3578 bgp_session_reset(peer);
3579 }
718e3744 3580
d62a17ae 3581 /* Purge network and redistributed routes. */
3582 bgp_purge_static_redist_routes(bgp);
ee7ca6c0 3583
3584 /* Cleanup registered nexthops (flags) */
3585 bgp_cleanup_nexthops(bgp);
6cc0114b
IR
3586
3587 bgp_zebra_instance_deregister(bgp);
3588
3589 bgp_set_redist_vrf_bitmaps(bgp, false);
718e3744 3590}
3591
d62a17ae 3592/* Delete BGP instance. */
3593int bgp_delete(struct bgp *bgp)
3594{
3595 struct peer *peer;
3596 struct peer_group *group;
3597 struct listnode *node, *next;
3598 struct vrf *vrf;
3599 afi_t afi;
cfd47646 3600 safi_t safi;
d62a17ae 3601 int i;
cfd47646 3602 struct graceful_restart_info *gr_info;
d62a17ae 3603
bf383464 3604 assert(bgp);
2b9bcf30 3605
46aeabed
LS
3606 bgp_soft_reconfig_table_task_cancel(bgp, NULL, NULL);
3607
1bfd9dcc
PR
3608 /* make sure we withdraw any exported routes */
3609 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(),
3610 bgp);
3611 vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp_get_default(),
3612 bgp);
3613
3614 bgp_vpn_leak_unimport(bgp);
3615
2b9bcf30
DL
3616 hook_call(bgp_inst_delete, bgp);
3617
d62a17ae 3618 THREAD_OFF(bgp->t_startup);
c969b2ed
DS
3619 THREAD_OFF(bgp->t_maxmed_onstartup);
3620 THREAD_OFF(bgp->t_update_delay);
3621 THREAD_OFF(bgp->t_establish_wait);
d62a17ae 3622
9f822fa2 3623 /* Set flag indicating bgp instance delete in progress */
892fedb6 3624 SET_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS);
9f822fa2 3625
cfd47646 3626 /* Delete the graceful restart info */
3627 FOREACH_AFI_SAFI (afi, safi) {
56c226e7
DS
3628 struct thread *t;
3629
cfd47646 3630 gr_info = &bgp->gr_info[afi][safi];
13909c4f
DS
3631 if (!gr_info)
3632 continue;
3633
fa5806c3 3634 THREAD_OFF(gr_info->t_select_deferral);
56c226e7
DS
3635
3636 t = gr_info->t_route_select;
3637 if (t) {
3638 void *info = THREAD_ARG(t);
3639
3640 XFREE(MTYPE_TMP, info);
3641 }
fa5806c3 3642 THREAD_OFF(gr_info->t_route_select);
cfd47646 3643 }
3644
d62a17ae 3645 if (BGP_DEBUG(zebra, ZEBRA)) {
3646 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3647 zlog_debug("Deleting Default VRF");
3648 else
3649 zlog_debug("Deleting %s %s",
3650 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3651 ? "VRF"
3652 : "VIEW",
3653 bgp->name);
718e3744 3654 }
3655
10ebe1ab
MK
3656 /* unmap from RT list */
3657 bgp_evpn_vrf_delete(bgp);
3658
dfd17258
PG
3659 /* unmap bgp vrf label */
3660 vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
3661 vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
3662
d62a17ae 3663 /* Stop timers. */
3664 if (bgp->t_rmap_def_originate_eval) {
fa5806c3 3665 THREAD_OFF(bgp->t_rmap_def_originate_eval);
d62a17ae 3666 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3667 why? */
718e3744 3668 }
3669
d62a17ae 3670 /* Inform peers we're going down. */
3671 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3672 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3673 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3674 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
718e3744 3675 }
3676
d62a17ae 3677 /* Delete static routes (networks). */
3678 bgp_static_delete(bgp);
6b0655a2 3679
d62a17ae 3680 /* Unset redistribution. */
3681 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3682 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3683 if (i != ZEBRA_ROUTE_BGP)
3684 bgp_redistribute_unset(bgp, afi, i, 0);
718e3744 3685
d62a17ae 3686 /* Free peers and peer-groups. */
3687 for (ALL_LIST_ELEMENTS(bgp->group, node, next, group))
3688 peer_group_delete(group);
718e3744 3689
d62a17ae 3690 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
3691 peer_delete(peer);
3692
3693 if (bgp->peer_self) {
3694 peer_delete(bgp->peer_self);
3695 bgp->peer_self = NULL;
718e3744 3696 }
3697
d62a17ae 3698 update_bgp_group_free(bgp);
718e3744 3699
d62a17ae 3700/* TODO - Other memory may need to be freed - e.g., NHT */
3701
49e5a4a0 3702#ifdef ENABLE_BGP_VNC
d62a17ae 3703 rfapi_delete(bgp);
3704#endif
3705 bgp_cleanup_routes(bgp);
718e3744 3706
301ad80a
PG
3707 for (afi = 0; afi < AFI_MAX; ++afi) {
3708 if (!bgp->vpn_policy[afi].import_redirect_rtlist)
3709 continue;
3710 ecommunity_free(
3711 &bgp->vpn_policy[afi]
3712 .import_redirect_rtlist);
3713 bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
3714 }
718e3744 3715
d62a17ae 3716 /* Deregister from Zebra, if needed */
bb4ef1ae
DS
3717 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
3718 if (BGP_DEBUG(zebra, ZEBRA))
5e81f5dd
DS
3719 zlog_debug(
3720 "%s: deregistering this bgp %s instance from zebra",
3721 __func__, bgp->name);
d62a17ae 3722 bgp_zebra_instance_deregister(bgp);
bb4ef1ae 3723 }
718e3744 3724
de6058ab
AK
3725 /* Remove visibility via the master list - there may however still be
3726 * routes to be processed still referencing the struct bgp.
3727 */
3728 listnode_delete(bm->bgp, bgp);
3729
d62a17ae 3730 /* Free interfaces in this instance. */
3731 bgp_if_finish(bgp);
718e3744 3732
d62a17ae 3733 vrf = bgp_vrf_lookup_by_instance_type(bgp);
e5619c28 3734 bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
d62a17ae 3735 if (vrf)
3736 bgp_vrf_unlink(bgp, vrf);
718e3744 3737
e2f3a930
T
3738 /* Update EVPN VRF pointer */
3739 if (bm->bgp_evpn == bgp) {
3740 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3741 bgp_set_evpn(NULL);
3742 else
3743 bgp_set_evpn(bgp_get_default());
3744 }
3745
b6c386bb
DS
3746 if (bgp->process_queue)
3747 work_queue_free_and_null(&bgp->process_queue);
3748
d62a17ae 3749 thread_master_free_unused(bm->master);
3750 bgp_unlock(bgp); /* initial reference */
718e3744 3751
d62a17ae 3752 return 0;
718e3744 3753}
6b0655a2 3754
92375c91 3755void bgp_free(struct bgp *bgp)
d93f7ffc 3756{
d62a17ae 3757 afi_t afi;
3758 safi_t safi;
3759 struct bgp_table *table;
9bcb3eef 3760 struct bgp_dest *dest;
f8265580 3761 struct bgp_rmap *rmap;
d93f7ffc 3762
d62a17ae 3763 QOBJ_UNREG(bgp);
d93f7ffc 3764
6a154c88
DL
3765 list_delete(&bgp->group);
3766 list_delete(&bgp->peer);
966f821c 3767
d62a17ae 3768 if (bgp->peerhash) {
3769 hash_free(bgp->peerhash);
3770 bgp->peerhash = NULL;
3771 }
718e3744 3772
05c7a1cc
QY
3773 FOREACH_AFI_SAFI (afi, safi) {
3774 /* Special handling for 2-level routing tables. */
3775 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
3776 || safi == SAFI_EVPN) {
9bcb3eef
DS
3777 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
3778 dest = bgp_route_next(dest)) {
3779 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc 3780 bgp_table_finish(&table);
d62a17ae 3781 }
d62a17ae 3782 }
05c7a1cc
QY
3783 if (bgp->route[afi][safi])
3784 bgp_table_finish(&bgp->route[afi][safi]);
3785 if (bgp->aggregate[afi][safi])
3786 bgp_table_finish(&bgp->aggregate[afi][safi]);
3787 if (bgp->rib[afi][safi])
3788 bgp_table_finish(&bgp->rib[afi][safi]);
3789 rmap = &bgp->table_map[afi][safi];
0a22ddfb 3790 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
05c7a1cc 3791 }
718e3744 3792
d62a17ae 3793 bgp_scan_finish(bgp);
3794 bgp_address_destroy(bgp);
db0e1937 3795 bgp_tip_hash_destroy(bgp);
966f821c 3796
92708db6 3797 /* release the auto RD id */
3798 bf_release_index(bm->rd_idspace, bgp->vrf_rd_id);
3799
d62a17ae 3800 bgp_evpn_cleanup(bgp);
a6b07429 3801 bgp_pbr_cleanup(bgp);
92a9e6f2 3802 bgp_srv6_cleanup(bgp);
85c8d83b 3803 XFREE(MTYPE_BGP_EVPN_INFO, bgp->evpn_info);
829e590b
DS
3804
3805 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
9c2fd3fe 3806 enum vpn_policy_direction dir;
829e590b
DS
3807
3808 if (bgp->vpn_policy[afi].import_vrf)
6a154c88 3809 list_delete(&bgp->vpn_policy[afi].import_vrf);
829e590b 3810 if (bgp->vpn_policy[afi].export_vrf)
6a154c88 3811 list_delete(&bgp->vpn_policy[afi].export_vrf);
829e590b
DS
3812
3813 dir = BGP_VPN_POLICY_DIR_FROMVPN;
3814 if (bgp->vpn_policy[afi].rtlist[dir])
3815 ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
3816 dir = BGP_VPN_POLICY_DIR_TOVPN;
3817 if (bgp->vpn_policy[afi].rtlist[dir])
3818 ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
3819 }
3820
0a22ddfb
QY
3821 XFREE(MTYPE_BGP, bgp->name);
3822 XFREE(MTYPE_BGP, bgp->name_pretty);
0d020cd6 3823 XFREE(MTYPE_BGP, bgp->snmp_stats);
966f821c 3824
d62a17ae 3825 XFREE(MTYPE_BGP, bgp);
718e3744 3826}
3827
d62a17ae 3828struct peer *peer_lookup_by_conf_if(struct bgp *bgp, const char *conf_if)
718e3744 3829{
d62a17ae 3830 struct peer *peer;
3831 struct listnode *node, *nnode;
966f821c 3832
d62a17ae 3833 if (!conf_if)
3834 return NULL;
6b0655a2 3835
d62a17ae 3836 if (bgp != NULL) {
3837 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3838 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3839 && !CHECK_FLAG(peer->sflags,
3840 PEER_STATUS_ACCEPT_PEER))
3841 return peer;
3842 } else if (bm->bgp != NULL) {
3843 struct listnode *bgpnode, *nbgpnode;
3844
3845 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3846 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3847 if (peer->conf_if
3848 && !strcmp(peer->conf_if, conf_if)
3849 && !CHECK_FLAG(peer->sflags,
3850 PEER_STATUS_ACCEPT_PEER))
3851 return peer;
3852 }
3853 return NULL;
718e3744 3854}
3855
d62a17ae 3856struct peer *peer_lookup_by_hostname(struct bgp *bgp, const char *hostname)
718e3744 3857{
d62a17ae 3858 struct peer *peer;
3859 struct listnode *node, *nnode;
6b0655a2 3860
d62a17ae 3861 if (!hostname)
3862 return NULL;
6b0655a2 3863
d62a17ae 3864 if (bgp != NULL) {
3865 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3866 if (peer->hostname && !strcmp(peer->hostname, hostname)
3867 && !CHECK_FLAG(peer->sflags,
3868 PEER_STATUS_ACCEPT_PEER))
3869 return peer;
3870 } else if (bm->bgp != NULL) {
3871 struct listnode *bgpnode, *nbgpnode;
3872
3873 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3874 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3875 if (peer->hostname
3876 && !strcmp(peer->hostname, hostname)
3877 && !CHECK_FLAG(peer->sflags,
3878 PEER_STATUS_ACCEPT_PEER))
3879 return peer;
3880 }
3881 return NULL;
3882}
3883
3884struct peer *peer_lookup(struct bgp *bgp, union sockunion *su)
3885{
3886 struct peer *peer = NULL;
3887 struct peer tmp_peer;
3888
3889 memset(&tmp_peer, 0, sizeof(struct peer));
3890
3891 /*
3892 * We do not want to find the doppelganger peer so search for the peer
3893 * in
3894 * the hash that has PEER_FLAG_CONFIG_NODE
3895 */
3896 SET_FLAG(tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
3897
3898 tmp_peer.su = *su;
3899
3900 if (bgp != NULL) {
3901 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3902 } else if (bm->bgp != NULL) {
3903 struct listnode *bgpnode, *nbgpnode;
3904
3905 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) {
d62a17ae 3906 peer = hash_lookup(bgp->peerhash, &tmp_peer);
d62a17ae 3907 if (peer)
3908 break;
3909 }
3910 }
3911
3912 return peer;
3913}
3914
3915struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp,
3916 union sockunion *su,
3917 struct peer_group *group)
3918{
3919 struct peer *peer;
3920 afi_t afi;
3921 safi_t safi;
3922
3923 /* Create peer first; we've already checked group config is valid. */
3924 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
e84c59af 3925 group->conf->as_type, group);
d62a17ae 3926 if (!peer)
3927 return NULL;
3928
3929 /* Link to group */
3930 peer = peer_lock(peer);
3931 listnode_add(group->peer, peer);
3932
3933 peer_group2peer_config_copy(group, peer);
3934
3935 /*
3936 * Bind peer for all AFs configured for the group. We don't call
3937 * peer_group_bind as that is sub-optimal and does some stuff we don't
3938 * want.
3939 */
05c7a1cc
QY
3940 FOREACH_AFI_SAFI (afi, safi) {
3941 if (!group->conf->afc[afi][safi])
3942 continue;
3943 peer->afc[afi][safi] = 1;
d62a17ae 3944
05c7a1cc
QY
3945 if (!peer_af_find(peer, afi, safi))
3946 peer_af_create(peer, afi, safi);
d62a17ae 3947
05c7a1cc
QY
3948 peer_group2peer_config_copy_af(group, peer, afi, safi);
3949 }
d62a17ae 3950
3951 /* Mark as dynamic, but also as a "config node" for other things to
3952 * work. */
3953 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
3954 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
3955
3956 return peer;
3957}
3958
3959struct prefix *
3960peer_group_lookup_dynamic_neighbor_range(struct peer_group *group,
3961 struct prefix *prefix)
3962{
3963 struct listnode *node, *nnode;
3964 struct prefix *range;
3965 afi_t afi;
3966
3967 afi = family2afi(prefix->family);
3968
3969 if (group->listen_range[afi])
3970 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
3971 range))
3972 if (prefix_match(range, prefix))
3973 return range;
3974
3975 return NULL;
3976}
3977
3978struct peer_group *
3979peer_group_lookup_dynamic_neighbor(struct bgp *bgp, struct prefix *prefix,
3980 struct prefix **listen_range)
3981{
3982 struct prefix *range = NULL;
3983 struct peer_group *group = NULL;
3984 struct listnode *node, *nnode;
3985
3986 *listen_range = NULL;
3987 if (bgp != NULL) {
3988 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3989 if ((range = peer_group_lookup_dynamic_neighbor_range(
3990 group, prefix)))
3991 break;
3992 } else if (bm->bgp != NULL) {
3993 struct listnode *bgpnode, *nbgpnode;
3994
3995 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3996 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3997 if ((range = peer_group_lookup_dynamic_neighbor_range(
3998 group, prefix)))
3999 goto found_range;
4000 }
4001
4002found_range:
4003 *listen_range = range;
4004 return (group && range) ? group : NULL;
4005}
4006
4007struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
4008{
4009 struct peer_group *group;
4010 struct bgp *gbgp;
4011 struct peer *peer;
4012 struct prefix prefix;
4013 struct prefix *listen_range;
4014 int dncount;
d62a17ae 4015
0154d8ce
DS
4016 if (!sockunion2hostprefix(su, &prefix))
4017 return NULL;
d62a17ae 4018
4019 /* See if incoming connection matches a configured listen range. */
4020 group = peer_group_lookup_dynamic_neighbor(bgp, &prefix, &listen_range);
4021
4022 if (!group)
4023 return NULL;
4024
4025
4026 gbgp = group->bgp;
4027
4028 if (!gbgp)
4029 return NULL;
4030
d62a17ae 4031 if (bgp_debug_neighbor_events(NULL))
4032 zlog_debug(
511211bf
DA
4033 "Dynamic Neighbor %pFX matches group %s listen range %pFX",
4034 &prefix, group->name, listen_range);
d62a17ae 4035
4036 /* Are we within the listen limit? */
4037 dncount = gbgp->dynamic_neighbors_count;
4038
4039 if (dncount >= gbgp->dynamic_neighbors_limit) {
4040 if (bgp_debug_neighbor_events(NULL))
511211bf
DA
4041 zlog_debug(
4042 "Dynamic Neighbor %pFX rejected - at limit %d",
4043 &prefix, gbgp->dynamic_neighbors_limit);
d62a17ae 4044 return NULL;
4045 }
4046
4047 /* Ensure group is not disabled. */
4048 if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) {
4049 if (bgp_debug_neighbor_events(NULL))
4050 zlog_debug(
511211bf
DA
4051 "Dynamic Neighbor %pFX rejected - group %s disabled",
4052 &prefix, group->name);
d62a17ae 4053 return NULL;
4054 }
4055
4056 /* Check that at least one AF is activated for the group. */
4057 if (!peer_group_af_configured(group)) {
4058 if (bgp_debug_neighbor_events(NULL))
4059 zlog_debug(
511211bf
DA
4060 "Dynamic Neighbor %pFX rejected - no AF activated for group %s",
4061 &prefix, group->name);
d62a17ae 4062 return NULL;
4063 }
4064
4065 /* Create dynamic peer and bind to associated group. */
4066 peer = peer_create_bind_dynamic_neighbor(gbgp, su, group);
4067 assert(peer);
4068
4069 gbgp->dynamic_neighbors_count = ++dncount;
4070
4071 if (bgp_debug_neighbor_events(peer))
4072 zlog_debug("%s Dynamic Neighbor added, group %s count %d",
4073 peer->host, group->name, dncount);
4074
4075 return peer;
4076}
4077
cc32742c 4078static void peer_drop_dynamic_neighbor(struct peer *peer)
d62a17ae 4079{
4080 int dncount = -1;
cc32742c 4081 if (peer->group->bgp) {
d62a17ae 4082 dncount = peer->group->bgp->dynamic_neighbors_count;
4083 if (dncount)
4084 peer->group->bgp->dynamic_neighbors_count = --dncount;
4085 }
4086 if (bgp_debug_neighbor_events(peer))
4087 zlog_debug("%s dropped from group %s, count %d", peer->host,
4088 peer->group->name, dncount);
4089}
4090
d62a17ae 4091/* If peer is configured at least one address family return 1. */
3dc339cd 4092bool peer_active(struct peer *peer)
d62a17ae 4093{
4094 if (BGP_PEER_SU_UNSPEC(peer))
3dc339cd 4095 return false;
d62a17ae 4096 if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
4097 || peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
4098 || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
7c40bf39 4099 || peer->afc[AFI_IP][SAFI_FLOWSPEC]
d62a17ae 4100 || peer->afc[AFI_IP6][SAFI_UNICAST]
4101 || peer->afc[AFI_IP6][SAFI_MULTICAST]
4102 || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]
4103 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
4104 || peer->afc[AFI_IP6][SAFI_ENCAP]
7c40bf39 4105 || peer->afc[AFI_IP6][SAFI_FLOWSPEC]
d62a17ae 4106 || peer->afc[AFI_L2VPN][SAFI_EVPN])
3dc339cd
DA
4107 return true;
4108 return false;
d62a17ae 4109}
4110
4111/* If peer is negotiated at least one address family return 1. */
3dc339cd 4112bool peer_active_nego(struct peer *peer)
d62a17ae 4113{
4114 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
4115 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
4116 || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
4117 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
4118 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
7c40bf39 4119 || peer->afc_nego[AFI_IP][SAFI_FLOWSPEC]
d62a17ae 4120 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
4121 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
4122 || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST]
4123 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
4124 || peer->afc_nego[AFI_IP6][SAFI_ENCAP]
7c40bf39 4125 || peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC]
d62a17ae 4126 || peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
3dc339cd
DA
4127 return true;
4128 return false;
d62a17ae 4129}
4130
10711563
DA
4131/* If peer received at least one address family MP, return true */
4132bool peer_afc_received(struct peer *peer)
4133{
4134 afi_t afi;
4135 safi_t safi;
4136
4137 FOREACH_AFI_SAFI (afi, safi)
4138 if (peer->afc_recv[afi][safi])
4139 return true;
4140
4141 return false;
4142}
4143
4144/* If peer advertised at least one address family MP, return true */
4145bool peer_afc_advertised(struct peer *peer)
4146{
4147 afi_t afi;
4148 safi_t safi;
4149
4150 FOREACH_AFI_SAFI (afi, safi)
4151 if (peer->afc_adv[afi][safi])
4152 return true;
4153
4154 return false;
4155}
4156
dcc68b5e 4157void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
d62a17ae 4158 enum peer_change_type type)
4159{
8b56739e
DA
4160 struct peer_af *paf;
4161
d62a17ae 4162 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4163 return;
4164
feb17238 4165 if (!peer_established(peer))
d62a17ae 4166 return;
4167
4168 if (type == peer_change_reset) {
4169 /* If we're resetting session, we've to delete both peer struct
4170 */
4171 if ((peer->doppelganger)
4172 && (peer->doppelganger->status != Deleted)
4173 && (!CHECK_FLAG(peer->doppelganger->flags,
4174 PEER_FLAG_CONFIG_NODE)))
4175 peer_delete(peer->doppelganger);
4176
4177 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4178 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4179 } else if (type == peer_change_reset_in) {
4180 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4181 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
9af52ccf
DA
4182 bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
4183 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 4184 else {
4185 if ((peer->doppelganger)
4186 && (peer->doppelganger->status != Deleted)
4187 && (!CHECK_FLAG(peer->doppelganger->flags,
4188 PEER_FLAG_CONFIG_NODE)))
4189 peer_delete(peer->doppelganger);
4190
4191 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4192 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4193 }
4194 } else if (type == peer_change_reset_out) {
8b56739e
DA
4195 paf = peer_af_find(peer, afi, safi);
4196 if (paf && paf->subgroup)
4197 SET_FLAG(paf->subgroup->sflags,
4198 SUBGRP_STATUS_FORCE_UPDATES);
4199
4200 update_group_adjust_peer(paf);
e1a32ec1 4201 bgp_announce_route(peer, afi, safi, false);
d62a17ae 4202 }
4203}
4204
4205struct peer_flag_action {
4206 /* Peer's flag. */
83194f39 4207 uint64_t flag;
d62a17ae 4208
4209 /* This flag can be set for peer-group member. */
d7c0a89a 4210 uint8_t not_for_member;
d62a17ae 4211
4212 /* Action when the flag is changed. */
4213 enum peer_change_type type;
d62a17ae 4214};
4215
4216static const struct peer_flag_action peer_flag_action_list[] = {
4217 {PEER_FLAG_PASSIVE, 0, peer_change_reset},
4218 {PEER_FLAG_SHUTDOWN, 0, peer_change_reset},
8336c896 4219 {PEER_FLAG_RTT_SHUTDOWN, 0, peer_change_none},
d62a17ae 4220 {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none},
4221 {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none},
4222 {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none},
4223 {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
4224 {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
4225 {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
47cbc09b 4226 {PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
afad5ced 4227 {PEER_FLAG_IFPEER_V6ONLY, 0, peer_change_reset},
b90a8e13
PM
4228 {PEER_FLAG_ROUTEADV, 0, peer_change_none},
4229 {PEER_FLAG_TIMER, 0, peer_change_none},
4230 {PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
6c537a18 4231 {PEER_FLAG_TIMER_DELAYOPEN, 0, peer_change_none},
a14810f4
PM
4232 {PEER_FLAG_PASSWORD, 0, peer_change_none},
4233 {PEER_FLAG_LOCAL_AS, 0, peer_change_none},
4234 {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_none},
4235 {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
4236 {PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
27aa23a4 4237 {PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
d08c0c80 4238 {PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
7dddd1f7
DA
4239 {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_reset},
4240 {PEER_FLAG_ROLE, 0, peer_change_reset},
c41e9372 4241 {PEER_FLAG_PORT, 0, peer_change_reset},
d62a17ae 4242 {0, 0, 0}};
4243
4244static const struct peer_flag_action peer_af_flag_action_list[] = {
4245 {PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out},
4246 {PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out},
4247 {PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out},
4248 {PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out},
4249 {PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset},
4250 {PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset},
4251 {PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in},
4252 {PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out},
4253 {PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out},
4254 {PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out},
598ce6bd 4255 {PEER_FLAG_DEFAULT_ORIGINATE, 0, peer_change_none},
d62a17ae 4256 {PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out},
4257 {PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in},
4258 {PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in},
4259 {PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset},
4260 {PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset},
598ce6bd
PM
4261 {PEER_FLAG_MAX_PREFIX, 0, peer_change_none},
4262 {PEER_FLAG_MAX_PREFIX_WARNING, 0, peer_change_none},
9cbd06e0 4263 {PEER_FLAG_MAX_PREFIX_FORCE, 0, peer_change_none},
80444d30 4264 {PEER_FLAG_MAX_PREFIX_OUT, 0, peer_change_none},
d62a17ae 4265 {PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out},
4266 {PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out},
4267 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out},
4268 {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out},
4269 {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
4270 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
d62a17ae 4271 {PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
7c0e4312 4272 {PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
01da2d26 4273 {PEER_FLAG_SOO, 0, peer_change_reset},
d62a17ae 4274 {0, 0, 0}};
4275
4276/* Proper action set. */
4277static int peer_flag_action_set(const struct peer_flag_action *action_list,
4278 int size, struct peer_flag_action *action,
83194f39 4279 uint64_t flag)
d62a17ae 4280{
4281 int i;
4282 int found = 0;
4283 int reset_in = 0;
4284 int reset_out = 0;
4285 const struct peer_flag_action *match = NULL;
4286
4287 /* Check peer's frag action. */
4288 for (i = 0; i < size; i++) {
4289 match = &action_list[i];
4290
4291 if (match->flag == 0)
4292 break;
4293
4294 if (match->flag & flag) {
4295 found = 1;
4296
4297 if (match->type == peer_change_reset_in)
4298 reset_in = 1;
4299 if (match->type == peer_change_reset_out)
4300 reset_out = 1;
4301 if (match->type == peer_change_reset) {
4302 reset_in = 1;
4303 reset_out = 1;
4304 }
4305 if (match->not_for_member)
4306 action->not_for_member = 1;
4307 }
4308 }
4309
4310 /* Set peer clear type. */
4311 if (reset_in && reset_out)
4312 action->type = peer_change_reset;
4313 else if (reset_in)
4314 action->type = peer_change_reset_in;
4315 else if (reset_out)
4316 action->type = peer_change_reset_out;
4317 else
4318 action->type = peer_change_none;
4319
4320 return found;
4321}
4322
d7c0a89a 4323static void peer_flag_modify_action(struct peer *peer, uint32_t flag)
d62a17ae 4324{
4325 if (flag == PEER_FLAG_SHUTDOWN) {
4326 if (CHECK_FLAG(peer->flags, flag)) {
4327 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
4328 peer_nsf_stop(peer);
4329
4330 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
8336c896 4331
d62a17ae 4332 if (peer->t_pmax_restart) {
fa5806c3 4333 THREAD_OFF(peer->t_pmax_restart);
d62a17ae 4334 if (bgp_debug_neighbor_events(peer))
4335 zlog_debug(
f70c91dc
DA
4336 "%pBP Maximum-prefix restart timer canceled",
4337 peer);
d62a17ae 4338 }
4339
d62a17ae 4340 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4341 char *msg = peer->tx_shutdown_message;
4342 size_t msglen;
9f33eea3 4343 uint8_t msgbuf[BGP_ADMIN_SHUTDOWN_MSG_LEN + 1];
d62a17ae 4344
4345 if (!msg && peer_group_active(peer))
4346 msg = peer->group->conf
4347 ->tx_shutdown_message;
4348 msglen = msg ? strlen(msg) : 0;
9f33eea3
DA
4349 if (msglen > BGP_ADMIN_SHUTDOWN_MSG_LEN)
4350 msglen = BGP_ADMIN_SHUTDOWN_MSG_LEN;
d62a17ae 4351
4352 if (msglen) {
d62a17ae 4353 msgbuf[0] = msglen;
4354 memcpy(msgbuf + 1, msg, msglen);
4355
4356 bgp_notify_send_with_data(
4357 peer, BGP_NOTIFY_CEASE,
4358 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN,
4359 msgbuf, msglen + 1);
4360 } else
4361 bgp_notify_send(
4362 peer, BGP_NOTIFY_CEASE,
4363 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
4364 } else
4365 bgp_session_reset(peer);
4366 } else {
4367 peer->v_start = BGP_INIT_START_TIMER;
4368 BGP_EVENT_ADD(peer, BGP_Stop);
4369 }
4370 } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4371 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
4372 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
4373 else if (flag == PEER_FLAG_PASSIVE)
4374 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
4375 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
4376 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
4377
4378 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4379 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4380 } else
4381 bgp_session_reset(peer);
4382}
4383
9cf59432 4384/* Enable global administrative shutdown of all peers of BGP instance */
736b68f3 4385void bgp_shutdown_enable(struct bgp *bgp, const char *msg)
9cf59432
DS
4386{
4387 struct peer *peer;
4388 struct listnode *node;
202a1711
DA
4389 /* length(1) + message(N) */
4390 uint8_t data[BGP_ADMIN_SHUTDOWN_MSG_LEN + 1];
9cf59432
DS
4391
4392 /* do nothing if already shut down */
4393 if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN))
4394 return;
4395
8389c83a
DS
4396 /* informational log message */
4397 zlog_info("Enabled administrative shutdown on BGP instance AS %u",
4398 bgp->as);
e03f1f18 4399
9cf59432
DS
4400 /* iterate through peers of BGP instance */
4401 for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
4402 /* continue, if peer is already in administrative shutdown. */
4403 if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
4404 continue;
4405
4406 /* send a RFC 4486 notification message if necessary */
4407 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
ed284e23
DA
4408 if (msg) {
4409 size_t datalen = strlen(msg);
4410
4411 if (datalen > BGP_ADMIN_SHUTDOWN_MSG_LEN)
4412 datalen = BGP_ADMIN_SHUTDOWN_MSG_LEN;
4413
4414 data[0] = datalen;
4415 memcpy(data + 1, msg, datalen);
4416
736b68f3
DS
4417 bgp_notify_send_with_data(
4418 peer, BGP_NOTIFY_CEASE,
202a1711
DA
4419 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, data,
4420 datalen + 1);
ed284e23 4421 } else {
736b68f3
DS
4422 bgp_notify_send(
4423 peer, BGP_NOTIFY_CEASE,
4424 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
ed284e23 4425 }
9cf59432
DS
4426 }
4427
4428 /* reset start timer to initial value */
4429 peer->v_start = BGP_INIT_START_TIMER;
4430
4431 /* trigger a RFC 4271 ManualStop event */
4432 BGP_EVENT_ADD(peer, BGP_Stop);
4433 }
4434
4435 /* set the BGP instances shutdown flag */
4436 SET_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN);
4437}
4438
4439/* Disable global administrative shutdown of all peers of BGP instance */
4440void bgp_shutdown_disable(struct bgp *bgp)
4441{
9cf59432
DS
4442 /* do nothing if not shut down. */
4443 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN))
4444 return;
4445
8389c83a
DS
4446 /* informational log message */
4447 zlog_info("Disabled administrative shutdown on BGP instance AS %u",
4448 bgp->as);
9cf59432
DS
4449
4450 /* clear the BGP instances shutdown flag */
4451 UNSET_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN);
4452}
4453
d62a17ae 4454/* Change specified peer flag. */
83194f39 4455static int peer_flag_modify(struct peer *peer, uint64_t flag, int set)
d62a17ae 4456{
4457 int found;
4458 int size;
9fb964de
PM
4459 bool invert, member_invert;
4460 struct peer *member;
d62a17ae 4461 struct listnode *node, *nnode;
4462 struct peer_flag_action action;
4463
4464 memset(&action, 0, sizeof(struct peer_flag_action));
0d6f7fd6 4465 size = sizeof(peer_flag_action_list) / sizeof(struct peer_flag_action);
d62a17ae 4466
9fb964de 4467 invert = CHECK_FLAG(peer->flags_invert, flag);
d62a17ae 4468 found = peer_flag_action_set(peer_flag_action_list, size, &action,
4469 flag);
4470
9fb964de 4471 /* Abort if no flag action exists. */
d62a17ae 4472 if (!found)
4473 return BGP_ERR_INVALID_FLAG;
4474
9fb964de 4475 /* Check for flag conflict: STRICT_CAP_MATCH && OVERRIDE_CAPABILITY */
d62a17ae 4476 if (set && CHECK_FLAG(peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
4477 && CHECK_FLAG(peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
4478 return BGP_ERR_PEER_FLAG_CONFLICT;
4479
9fb964de 4480 /* Handle flag updates where desired state matches current state. */
d62a17ae 4481 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
9fb964de
PM
4482 if (set && CHECK_FLAG(peer->flags, flag)) {
4483 COND_FLAG(peer->flags_override, flag, !invert);
d62a17ae 4484 return 0;
9fb964de
PM
4485 }
4486
4487 if (!set && !CHECK_FLAG(peer->flags, flag)) {
4488 COND_FLAG(peer->flags_override, flag, invert);
d62a17ae 4489 return 0;
9fb964de 4490 }
d62a17ae 4491 }
4492
9fb964de
PM
4493 /* Inherit from peer-group or set/unset flags accordingly. */
4494 if (peer_group_active(peer) && set == invert)
4495 peer_flag_inherit(peer, flag);
d62a17ae 4496 else
9fb964de 4497 COND_FLAG(peer->flags, flag, set);
d62a17ae 4498
9fb964de 4499 /* Check if handling a regular peer. */
d62a17ae 4500 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
9fb964de
PM
4501 /* Update flag override state accordingly. */
4502 COND_FLAG(peer->flags_override, flag, set != invert);
4503
b3a3290e
DS
4504 /*
4505 * For the extended next-hop encoding flag we need to turn RAs
4506 * on if flag is being set, but only turn RAs off if the flag
4507 * is being unset on this peer and if this peer is a member of a
4508 * peer-group, the peer-group also doesn't have the flag set.
4509 */
4510 if (flag == PEER_FLAG_CAPABILITY_ENHE) {
4511 if (set) {
4512 bgp_zebra_initiate_radv(peer->bgp, peer);
4513 } else if (peer_group_active(peer)) {
28168b1b
DS
4514 if (!CHECK_FLAG(peer->group->conf->flags,
4515 flag) &&
4516 !peer->conf_if)
b3a3290e
DS
4517 bgp_zebra_terminate_radv(peer->bgp,
4518 peer);
4519 } else
4520 bgp_zebra_terminate_radv(peer->bgp, peer);
4521 }
087a1c6c 4522
9fb964de 4523 /* Execute flag action on peer. */
d62a17ae 4524 if (action.type == peer_change_reset)
4525 peer_flag_modify_action(peer, flag);
4526
9fb964de 4527 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4528 return 0;
4529 }
4530
9fb964de 4531 /*
f75b9163 4532 * Update peer-group members, unless they are explicitly overriding
9fb964de
PM
4533 * peer-group configuration.
4534 */
4535 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4536 /* Skip peers with overridden configuration. */
4537 if (CHECK_FLAG(member->flags_override, flag))
4538 continue;
d62a17ae 4539
527de3dc
PM
4540 /* Check if only member without group is inverted. */
4541 member_invert =
4542 CHECK_FLAG(member->flags_invert, flag) && !invert;
d62a17ae 4543
9fb964de
PM
4544 /* Skip peers with equivalent configuration. */
4545 if (set != member_invert && CHECK_FLAG(member->flags, flag))
d62a17ae 4546 continue;
4547
9fb964de 4548 if (set == member_invert && !CHECK_FLAG(member->flags, flag))
d62a17ae 4549 continue;
4550
9fb964de
PM
4551 /* Update flag on peer-group member. */
4552 COND_FLAG(member->flags, flag, set != member_invert);
d62a17ae 4553
28168b1b 4554 if (flag == PEER_FLAG_CAPABILITY_ENHE && !member->conf_if)
b3a3290e
DS
4555 set ? bgp_zebra_initiate_radv(member->bgp, member)
4556 : bgp_zebra_terminate_radv(member->bgp, member);
1ea03b90 4557
9fb964de 4558 /* Execute flag action on peer-group member. */
d62a17ae 4559 if (action.type == peer_change_reset)
9fb964de 4560 peer_flag_modify_action(member, flag);
d62a17ae 4561 }
9fb964de 4562
d62a17ae 4563 return 0;
4564}
4565
83194f39 4566int peer_flag_set(struct peer *peer, uint64_t flag)
d62a17ae 4567{
4568 return peer_flag_modify(peer, flag, 1);
4569}
4570
83194f39 4571int peer_flag_unset(struct peer *peer, uint64_t flag)
d62a17ae 4572{
4573 return peer_flag_modify(peer, flag, 0);
4574}
4575
4576static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
da5e1a58 4577 uint64_t flag, bool set)
d62a17ae 4578{
4579 int found;
4580 int size;
527de3dc 4581 bool invert, member_invert;
527de3dc 4582 struct peer *member;
d62a17ae 4583 struct listnode *node, *nnode;
d62a17ae 4584 struct peer_flag_action action;
3061acc2 4585 enum bgp_peer_sort ptype;
d62a17ae 4586
4587 memset(&action, 0, sizeof(struct peer_flag_action));
0d6f7fd6 4588 size = sizeof(peer_af_flag_action_list)
d62a17ae 4589 / sizeof(struct peer_flag_action);
4590
27c05d4d 4591 invert = CHECK_FLAG(peer->af_flags_invert[afi][safi], flag);
d62a17ae 4592 found = peer_flag_action_set(peer_af_flag_action_list, size, &action,
4593 flag);
4594
527de3dc 4595 /* Abort if flag action exists. */
d62a17ae 4596 if (!found)
4597 return BGP_ERR_INVALID_FLAG;
4598
469cbb0f 4599 ptype = peer_sort(peer);
d62a17ae 4600 /* Special check for reflector client. */
469cbb0f 4601 if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
d62a17ae 4602 return BGP_ERR_NOT_INTERNAL_PEER;
4603
4604 /* Special check for remove-private-AS. */
469cbb0f 4605 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
d62a17ae 4606 return BGP_ERR_REMOVE_PRIVATE_AS;
4607
4608 /* as-override is not allowed for IBGP peers */
469cbb0f 4609 if (flag & PEER_FLAG_AS_OVERRIDE && ptype == BGP_PEER_IBGP)
d62a17ae 4610 return BGP_ERR_AS_OVERRIDE;
4611
527de3dc 4612 /* Handle flag updates where desired state matches current state. */
d62a17ae 4613 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
598ce6bd 4614 if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
527de3dc
PM
4615 COND_FLAG(peer->af_flags_override[afi][safi], flag,
4616 !invert);
d62a17ae 4617 return 0;
598ce6bd
PM
4618 }
4619
4620 if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
527de3dc
PM
4621 COND_FLAG(peer->af_flags_override[afi][safi], flag,
4622 invert);
d62a17ae 4623 return 0;
598ce6bd 4624 }
d62a17ae 4625 }
4626
ace295a9
MK
4627 /*
4628 * For EVPN we implicitly set the NEXTHOP_UNCHANGED flag,
4629 * if we are setting/unsetting flags which conflict with this flag
4630 * handle accordingly
4631 */
4632 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
4633 if (set) {
4634
3518f352
DS
4635 /*
4636 * if we are setting NEXTHOP_SELF, we need to unset the
4637 * NEXTHOP_UNCHANGED flag
4638 */
ace295a9
MK
4639 if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
4640 CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
4641 UNSET_FLAG(peer->af_flags[afi][safi],
4642 PEER_FLAG_NEXTHOP_UNCHANGED);
4643 } else {
4644
3518f352
DS
4645 /*
4646 * if we are unsetting NEXTHOP_SELF, we need to set the
ace295a9
MK
4647 * NEXTHOP_UNCHANGED flag to reset the defaults for EVPN
4648 */
4649 if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
4650 CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
4651 SET_FLAG(peer->af_flags[afi][safi],
4652 PEER_FLAG_NEXTHOP_UNCHANGED);
4653 }
4654 }
4655
99819027
DS
4656 /*
4657 * If the peer is a route server client let's not
4658 * muck with the nexthop on the way out the door
4659 */
4660 if (flag & PEER_FLAG_RSERVER_CLIENT) {
4661 if (set)
4662 SET_FLAG(peer->af_flags[afi][safi],
4663 PEER_FLAG_NEXTHOP_UNCHANGED);
4664 else
4665 UNSET_FLAG(peer->af_flags[afi][safi],
4666 PEER_FLAG_NEXTHOP_UNCHANGED);
4667 }
4668
527de3dc
PM
4669 /* Inherit from peer-group or set/unset flags accordingly. */
4670 if (peer_group_active(peer) && set == invert)
4671 peer_af_flag_inherit(peer, afi, safi, flag);
4672 else
4673 COND_FLAG(peer->af_flags[afi][safi], flag, set);
d62a17ae 4674
4675 /* Execute action when peer is established. */
4676 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
feb17238 4677 && peer_established(peer)) {
d62a17ae 4678 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
4679 bgp_clear_adj_in(peer, afi, safi);
4680 else {
4681 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
4682 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
4683 else if (flag == PEER_FLAG_RSERVER_CLIENT)
4684 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
4685 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
4686 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
4687 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
4688 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
4689
4690 peer_change_action(peer, afi, safi, action.type);
4691 }
4692 }
4693
527de3dc
PM
4694 /* Check if handling a regular peer. */
4695 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4696 COND_FLAG(peer->af_flags_override[afi][safi], flag,
4697 set != invert);
4698 } else {
4699 /*
f75b9163 4700 * Update peer-group members, unless they are explicitly
527de3dc
PM
4701 * overriding peer-group configuration.
4702 */
4703 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode,
4704 member)) {
4705 /* Skip peers with overridden configuration. */
4706 if (CHECK_FLAG(member->af_flags_override[afi][safi],
598ce6bd
PM
4707 flag))
4708 continue;
4709
527de3dc
PM
4710 /* Check if only member without group is inverted. */
4711 member_invert =
4712 CHECK_FLAG(member->af_flags_invert[afi][safi],
4713 flag)
4714 && !invert;
4715
4716 /* Skip peers with equivalent configuration. */
4717 if (set != member_invert
4718 && CHECK_FLAG(member->af_flags[afi][safi], flag))
d62a17ae 4719 continue;
4720
527de3dc
PM
4721 if (set == member_invert
4722 && !CHECK_FLAG(member->af_flags[afi][safi], flag))
d62a17ae 4723 continue;
4724
527de3dc
PM
4725 /* Update flag on peer-group member. */
4726 COND_FLAG(member->af_flags[afi][safi], flag,
4727 set != member_invert);
d62a17ae 4728
527de3dc 4729 /* Execute flag action on peer-group member. */
feb17238 4730 if (peer_established(member)) {
d62a17ae 4731 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
527de3dc 4732 bgp_clear_adj_in(member, afi, safi);
d62a17ae 4733 else {
4734 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
527de3dc 4735 member->last_reset =
d62a17ae 4736 PEER_DOWN_RR_CLIENT_CHANGE;
4737 else if (flag
4738 == PEER_FLAG_RSERVER_CLIENT)
527de3dc 4739 member->last_reset =
d62a17ae 4740 PEER_DOWN_RS_CLIENT_CHANGE;
4741 else if (flag
4742 == PEER_FLAG_ORF_PREFIX_SM)
527de3dc 4743 member->last_reset =
d62a17ae 4744 PEER_DOWN_CAPABILITY_CHANGE;
4745 else if (flag
4746 == PEER_FLAG_ORF_PREFIX_RM)
527de3dc 4747 member->last_reset =
d62a17ae 4748 PEER_DOWN_CAPABILITY_CHANGE;
4749
527de3dc 4750 peer_change_action(member, afi, safi,
d62a17ae 4751 action.type);
4752 }
4753 }
4754 }
4755 }
4756
d62a17ae 4757 return 0;
4758}
4759
da5e1a58 4760int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, uint64_t flag)
d62a17ae 4761{
4762 return peer_af_flag_modify(peer, afi, safi, flag, 1);
4763}
4764
da5e1a58 4765int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, uint64_t flag)
d62a17ae 4766{
4767 return peer_af_flag_modify(peer, afi, safi, flag, 0);
4768}
4769
4770
3dc339cd 4771void peer_tx_shutdown_message_set(struct peer *peer, const char *msg)
d62a17ae 4772{
4773 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
4774 peer->tx_shutdown_message =
4775 msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL;
d62a17ae 4776}
4777
3dc339cd 4778void peer_tx_shutdown_message_unset(struct peer *peer)
d62a17ae 4779{
4780 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
d62a17ae 4781}
4782
4783
4784/* EBGP multihop configuration. */
4785int peer_ebgp_multihop_set(struct peer *peer, int ttl)
4786{
4787 struct peer_group *group;
4788 struct listnode *node, *nnode;
4789 struct peer *peer1;
4790
4791 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
4792 return 0;
8ffeaddb
EDP
4793
4794 /* is there anything to do? */
4795 if (peer->ttl == ttl)
4796 return 0;
d62a17ae 4797
4798 /* see comment in peer_ttl_security_hops_set() */
4799 if (ttl != MAXTTL) {
4800 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4801 group = peer->group;
e2521429 4802 if (group->conf->gtsm_hops != BGP_GTSM_HOPS_DISABLED)
d62a17ae 4803 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4804
4805 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
4806 peer1)) {
4807 if (peer1->sort == BGP_PEER_IBGP)
4808 continue;
4809
e2521429 4810 if (peer1->gtsm_hops != BGP_GTSM_HOPS_DISABLED)
d62a17ae 4811 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4812 }
4813 } else {
e2521429 4814 if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED)
d62a17ae 4815 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4816 }
4817 }
4818
4819 peer->ttl = ttl;
4820
4821 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3557ed3d 4822 if (peer->sort != BGP_PEER_IBGP) {
d62a17ae 4823 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4824 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4825 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4826 else
4827 bgp_session_reset(peer);
4ba37eb6
RZ
4828
4829 /* Reconfigure BFD peer with new TTL. */
4830 if (peer->bfd_config)
4831 bgp_peer_bfd_update_source(peer);
d62a17ae 4832 }
4833 } else {
4834 group = peer->group;
4835 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4836 if (peer->sort == BGP_PEER_IBGP)
4837 continue;
4838
4839 peer->ttl = group->conf->ttl;
4840
4841 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4842 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4843 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4844 else
4845 bgp_session_reset(peer);
4ba37eb6
RZ
4846
4847 /* Reconfigure BFD peer with new TTL. */
4848 if (peer->bfd_config)
4849 bgp_peer_bfd_update_source(peer);
d62a17ae 4850 }
4851 }
4852 return 0;
4853}
4854
4855int peer_ebgp_multihop_unset(struct peer *peer)
4856{
4857 struct peer_group *group;
4858 struct listnode *node, *nnode;
6e26b2e2 4859 int ttl;
d62a17ae 4860
4861 if (peer->sort == BGP_PEER_IBGP)
4862 return 0;
4863
e2521429 4864 if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED && peer->ttl != MAXTTL)
d62a17ae 4865 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4866
4867 if (peer_group_active(peer))
6e26b2e2 4868 ttl = peer->group->conf->ttl;
d62a17ae 4869 else
6e26b2e2
DS
4870 ttl = BGP_DEFAULT_TTL;
4871
4872 if (ttl == peer->ttl)
4873 return 0;
4874
4875 peer->ttl = ttl;
d62a17ae 4876
4877 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4878 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4879 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4880 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4881 else
4882 bgp_session_reset(peer);
4ba37eb6
RZ
4883
4884 /* Reconfigure BFD peer with new TTL. */
4885 if (peer->bfd_config)
4886 bgp_peer_bfd_update_source(peer);
d62a17ae 4887 } else {
4888 group = peer->group;
4889 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4890 if (peer->sort == BGP_PEER_IBGP)
4891 continue;
4892
a0903cd2 4893 peer->ttl = BGP_DEFAULT_TTL;
d62a17ae 4894
4895 if (peer->fd >= 0) {
4896 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4897 bgp_notify_send(
4898 peer, BGP_NOTIFY_CEASE,
4899 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4900 else
4901 bgp_session_reset(peer);
4902 }
4ba37eb6
RZ
4903
4904 /* Reconfigure BFD peer with new TTL. */
4905 if (peer->bfd_config)
4906 bgp_peer_bfd_update_source(peer);
d62a17ae 4907 }
4908 }
4909 return 0;
4910}
4911
d864dd9e 4912/* Set Open Policy Role and check its correctness */
8f2d6021 4913int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode)
d864dd9e 4914{
7dddd1f7
DA
4915 struct peer *member;
4916 struct listnode *node, *nnode;
4917
4918 peer_flag_set(peer, PEER_FLAG_ROLE);
4919
4920 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4921 if (peer->sort != BGP_PEER_EBGP)
4922 return BGP_ERR_INVALID_INTERNAL_ROLE;
4923
4924 if (peer->local_role == role) {
4925 if (CHECK_FLAG(peer->flags,
4926 PEER_FLAG_ROLE_STRICT_MODE) &&
4927 !strict_mode)
4928 /* TODO: Is session restart needed if it was
4929 * down?
4930 */
4931 UNSET_FLAG(peer->flags,
4932 PEER_FLAG_ROLE_STRICT_MODE);
4933 if (!CHECK_FLAG(peer->flags,
4934 PEER_FLAG_ROLE_STRICT_MODE) &&
4935 strict_mode) {
4936 SET_FLAG(peer->flags,
4937 PEER_FLAG_ROLE_STRICT_MODE);
4938 /* Restart session to throw Role Mismatch
4939 * Notification
4940 */
4941 if (peer->remote_role == ROLE_UNDEFINED)
4942 bgp_session_reset(peer);
4943 }
4944 } else {
4945 peer->local_role = role;
4946 if (strict_mode)
4947 SET_FLAG(peer->flags,
4948 PEER_FLAG_ROLE_STRICT_MODE);
4949 else
4950 UNSET_FLAG(peer->flags,
4951 PEER_FLAG_ROLE_STRICT_MODE);
4952 bgp_session_reset(peer);
d864dd9e 4953 }
7dddd1f7
DA
4954
4955 return CMD_SUCCESS;
d864dd9e 4956 }
7dddd1f7
DA
4957
4958 peer->local_role = role;
4959 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4960 if (member->sort != BGP_PEER_EBGP)
4961 return BGP_ERR_INVALID_INTERNAL_ROLE;
4962
4963 if (member->local_role == role) {
4964 if (CHECK_FLAG(member->flags,
4965 PEER_FLAG_ROLE_STRICT_MODE) &&
4966 !strict_mode)
4967 /* TODO: Is session restart needed if it was
4968 * down?
4969 */
4970 UNSET_FLAG(member->flags,
4971 PEER_FLAG_ROLE_STRICT_MODE);
4972 if (!CHECK_FLAG(member->flags,
4973 PEER_FLAG_ROLE_STRICT_MODE) &&
4974 strict_mode) {
4975 SET_FLAG(peer->flags,
4976 PEER_FLAG_ROLE_STRICT_MODE);
4977 SET_FLAG(member->flags,
4978 PEER_FLAG_ROLE_STRICT_MODE);
4979 /* Restart session to throw Role Mismatch
4980 * Notification
4981 */
4982 if (member->remote_role == ROLE_UNDEFINED)
4983 bgp_session_reset(member);
4984 }
4985 } else {
4986 member->local_role = role;
4987
4988 if (strict_mode) {
4989 SET_FLAG(peer->flags,
4990 PEER_FLAG_ROLE_STRICT_MODE);
4991 SET_FLAG(member->flags,
4992 PEER_FLAG_ROLE_STRICT_MODE);
4993 } else {
4994 UNSET_FLAG(member->flags,
4995 PEER_FLAG_ROLE_STRICT_MODE);
4996 }
4997 bgp_session_reset(member);
4998 }
4999 }
5000
5001 return CMD_SUCCESS;
d864dd9e
EB
5002}
5003
5004int peer_role_unset(struct peer *peer)
5005{
7dddd1f7
DA
5006 struct peer *member;
5007 struct listnode *node, *nnode;
5008
5009 peer_flag_unset(peer, PEER_FLAG_ROLE);
5010
5011 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5012 return peer_role_set(peer, ROLE_UNDEFINED, 0);
5013
5014 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member))
5015 peer_role_set(member, ROLE_UNDEFINED, 0);
5016
5017 return CMD_SUCCESS;
d864dd9e
EB
5018}
5019
d62a17ae 5020/* Neighbor description. */
3dc339cd 5021void peer_description_set(struct peer *peer, const char *desc)
d62a17ae 5022{
0a22ddfb 5023 XFREE(MTYPE_PEER_DESC, peer->desc);
d62a17ae 5024
5025 peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
d62a17ae 5026}
5027
3dc339cd 5028void peer_description_unset(struct peer *peer)
d62a17ae 5029{
0a22ddfb 5030 XFREE(MTYPE_PEER_DESC, peer->desc);
d62a17ae 5031}
5032
5033/* Neighbor update-source. */
5034int peer_update_source_if_set(struct peer *peer, const char *ifname)
5035{
a14810f4 5036 struct peer *member;
d62a17ae 5037 struct listnode *node, *nnode;
5038
a14810f4
PM
5039 /* Set flag and configuration on peer. */
5040 peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
d62a17ae 5041 if (peer->update_if) {
a14810f4 5042 if (strcmp(peer->update_if, ifname) == 0)
d62a17ae 5043 return 0;
d62a17ae 5044 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
d62a17ae 5045 }
d62a17ae 5046 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
a14810f4
PM
5047 sockunion_free(peer->update_source);
5048 peer->update_source = NULL;
d62a17ae 5049
a14810f4 5050 /* Check if handling a regular peer. */
d62a17ae 5051 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 5052 /* Send notification or reset peer depending on state. */
d62a17ae 5053 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
5054 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
5055 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5056 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5057 } else
5058 bgp_session_reset(peer);
a14810f4 5059
7196f56e
RZ
5060 /* Apply new source configuration to BFD session. */
5061 if (peer->bfd_config)
5062 bgp_peer_bfd_update_source(peer);
5063
a14810f4 5064 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5065 return 0;
5066 }
5067
a14810f4
PM
5068 /*
5069 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5070 * explicitly overriding peer-group configuration.
a14810f4
PM
5071 */
5072 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5073 /* Skip peers with overridden configuration. */
5074 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
5075 continue;
d62a17ae 5076
a14810f4
PM
5077 /* Skip peers with the same configuration. */
5078 if (member->update_if) {
5079 if (strcmp(member->update_if, ifname) == 0)
5080 continue;
5081 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
d62a17ae 5082 }
5083
a14810f4
PM
5084 /* Set flag and configuration on peer-group member. */
5085 SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
5086 member->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
5087 sockunion_free(member->update_source);
5088 member->update_source = NULL;
5089
5090 /* Send notification or reset peer depending on state. */
5091 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
5092 member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
5093 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 5094 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5095 } else
a14810f4 5096 bgp_session_reset(member);
7196f56e
RZ
5097
5098 /* Apply new source configuration to BFD session. */
5099 if (member->bfd_config)
5100 bgp_peer_bfd_update_source(member);
d62a17ae 5101 }
a14810f4 5102
d62a17ae 5103 return 0;
5104}
5105
0b1fb52c 5106void peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
d62a17ae 5107{
a14810f4 5108 struct peer *member;
d62a17ae 5109 struct listnode *node, *nnode;
5110
a14810f4
PM
5111 /* Set flag and configuration on peer. */
5112 peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
d62a17ae 5113 if (peer->update_source) {
a14810f4 5114 if (sockunion_cmp(peer->update_source, su) == 0)
0b1fb52c 5115 return;
d62a17ae 5116 sockunion_free(peer->update_source);
d62a17ae 5117 }
d62a17ae 5118 peer->update_source = sockunion_dup(su);
a14810f4 5119 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
d62a17ae 5120
a14810f4 5121 /* Check if handling a regular peer. */
d62a17ae 5122 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 5123 /* Send notification or reset peer depending on state. */
d62a17ae 5124 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
5125 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
5126 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5127 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5128 } else
5129 bgp_session_reset(peer);
a14810f4 5130
7196f56e
RZ
5131 /* Apply new source configuration to BFD session. */
5132 if (peer->bfd_config)
5133 bgp_peer_bfd_update_source(peer);
5134
a14810f4 5135 /* Skip peer-group mechanics for regular peers. */
0b1fb52c 5136 return;
d62a17ae 5137 }
5138
a14810f4
PM
5139 /*
5140 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5141 * explicitly overriding peer-group configuration.
a14810f4
PM
5142 */
5143 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5144 /* Skip peers with overridden configuration. */
5145 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
5146 continue;
d62a17ae 5147
a14810f4
PM
5148 /* Skip peers with the same configuration. */
5149 if (member->update_source) {
5150 if (sockunion_cmp(member->update_source, su) == 0)
5151 continue;
5152 sockunion_free(member->update_source);
d62a17ae 5153 }
5154
a14810f4
PM
5155 /* Set flag and configuration on peer-group member. */
5156 SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
5157 member->update_source = sockunion_dup(su);
5158 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
5159
5160 /* Send notification or reset peer depending on state. */
5161 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
5162 member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
5163 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 5164 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5165 } else
a14810f4 5166 bgp_session_reset(member);
7196f56e
RZ
5167
5168 /* Apply new source configuration to BFD session. */
5169 if (member->bfd_config)
5170 bgp_peer_bfd_update_source(member);
d62a17ae 5171 }
d62a17ae 5172}
5173
0b1fb52c 5174void peer_update_source_unset(struct peer *peer)
d62a17ae 5175{
a14810f4 5176 struct peer *member;
d62a17ae 5177 struct listnode *node, *nnode;
5178
a14810f4 5179 if (!CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE))
0b1fb52c 5180 return;
d62a17ae 5181
a14810f4
PM
5182 /* Inherit configuration from peer-group if peer is member. */
5183 if (peer_group_active(peer)) {
5184 peer_flag_inherit(peer, PEER_FLAG_UPDATE_SOURCE);
5185 PEER_SU_ATTR_INHERIT(peer, peer->group, update_source);
5186 PEER_STR_ATTR_INHERIT(peer, peer->group, update_if,
5187 MTYPE_PEER_UPDATE_SOURCE);
5188 } else {
5189 /* Otherwise remove flag and configuration from peer. */
5190 peer_flag_unset(peer, PEER_FLAG_UPDATE_SOURCE);
d62a17ae 5191 sockunion_free(peer->update_source);
5192 peer->update_source = NULL;
d62a17ae 5193 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
d62a17ae 5194 }
5195
a14810f4 5196 /* Check if handling a regular peer. */
d62a17ae 5197 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 5198 /* Send notification or reset peer depending on state. */
d62a17ae 5199 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
5200 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
5201 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5202 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5203 } else
5204 bgp_session_reset(peer);
a14810f4 5205
7196f56e
RZ
5206 /* Apply new source configuration to BFD session. */
5207 if (peer->bfd_config)
5208 bgp_peer_bfd_update_source(peer);
5209
a14810f4 5210 /* Skip peer-group mechanics for regular peers. */
0b1fb52c 5211 return;
d62a17ae 5212 }
5213
a14810f4
PM
5214 /*
5215 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5216 * explicitly overriding peer-group configuration.
a14810f4
PM
5217 */
5218 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5219 /* Skip peers with overridden configuration. */
5220 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
d62a17ae 5221 continue;
5222
a14810f4
PM
5223 /* Skip peers with the same configuration. */
5224 if (!CHECK_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE)
5225 && !member->update_source && !member->update_if)
5226 continue;
d62a17ae 5227
a14810f4
PM
5228 /* Remove flag and configuration on peer-group member. */
5229 UNSET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
5230 sockunion_free(member->update_source);
5231 member->update_source = NULL;
5232 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
5233
5234 /* Send notification or reset peer depending on state. */
5235 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
5236 member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
5237 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 5238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5239 } else
a14810f4 5240 bgp_session_reset(member);
7196f56e
RZ
5241
5242 /* Apply new source configuration to BFD session. */
5243 if (member->bfd_config)
5244 bgp_peer_bfd_update_source(member);
d62a17ae 5245 }
d62a17ae 5246}
5247
5248int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
1de27621 5249 const char *rmap, struct route_map *route_map)
d62a17ae 5250{
598ce6bd 5251 struct peer *member;
d62a17ae 5252 struct listnode *node, *nnode;
42427e39 5253 struct update_subgroup *subgrp;
d62a17ae 5254
598ce6bd
PM
5255 /* Set flag and configuration on peer. */
5256 peer_af_flag_set(peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE);
42427e39
IS
5257
5258 subgrp = peer_subgroup(peer, afi, safi);
5259
598ce6bd
PM
5260 if (rmap) {
5261 if (!peer->default_rmap[afi][safi].name
5262 || strcmp(rmap, peer->default_rmap[afi][safi].name) != 0) {
d62a17ae 5263 if (peer->default_rmap[afi][safi].name)
5264 XFREE(MTYPE_ROUTE_MAP_NAME,
5265 peer->default_rmap[afi][safi].name);
598ce6bd 5266
42427e39
IS
5267 /*
5268 * When there is a change in route-map policy,
5269 * this flow gets triggered. Since, the default
5270 * route is already originated, the flag is set.
5271 * The flag should be unset here,
5272 * to trigger the flow of sending update message.
5273 */
5274 if (subgrp)
5275 UNSET_FLAG(subgrp->sflags,
5276 SUBGRP_STATUS_DEFAULT_ORIGINATE);
5277
b4897fa5 5278 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
d62a17ae 5279 peer->default_rmap[afi][safi].name =
5280 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
1de27621 5281 peer->default_rmap[afi][safi].map = route_map;
b4897fa5 5282 route_map_counter_increment(route_map);
d62a17ae 5283 }
598ce6bd
PM
5284 } else if (!rmap) {
5285 if (peer->default_rmap[afi][safi].name)
5286 XFREE(MTYPE_ROUTE_MAP_NAME,
5287 peer->default_rmap[afi][safi].name);
5288
42427e39
IS
5289 /*
5290 * This is triggered in case of route-map deletion.
5291 * The flag needs to be unset, to trigger the flow
5292 * of sending an update message.
5293 */
5294 if (subgrp)
5295 UNSET_FLAG(subgrp->sflags,
5296 SUBGRP_STATUS_DEFAULT_ORIGINATE);
5297
b4897fa5 5298 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
598ce6bd
PM
5299 peer->default_rmap[afi][safi].name = NULL;
5300 peer->default_rmap[afi][safi].map = NULL;
d62a17ae 5301 }
5302
598ce6bd 5303 /* Check if handling a regular peer. */
d62a17ae 5304 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
598ce6bd 5305 /* Update peer route announcements. */
feb17238 5306 if (peer_established(peer) && peer->afc_nego[afi][safi]) {
d62a17ae 5307 update_group_adjust_peer(peer_af_find(peer, afi, safi));
5308 bgp_default_originate(peer, afi, safi, 0);
e1a32ec1 5309 bgp_announce_route(peer, afi, safi, false);
d62a17ae 5310 }
598ce6bd
PM
5311
5312 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5313 return 0;
5314 }
5315
598ce6bd
PM
5316 /*
5317 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5318 * explicitly overriding peer-group configuration.
598ce6bd
PM
5319 */
5320 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5321 /* Skip peers with overridden configuration. */
5322 if (CHECK_FLAG(member->af_flags_override[afi][safi],
5323 PEER_FLAG_DEFAULT_ORIGINATE))
5324 continue;
d62a17ae 5325
598ce6bd
PM
5326 /* Set flag and configuration on peer-group member. */
5327 SET_FLAG(member->af_flags[afi][safi],
5328 PEER_FLAG_DEFAULT_ORIGINATE);
d62a17ae 5329 if (rmap) {
598ce6bd 5330 if (member->default_rmap[afi][safi].name)
d62a17ae 5331 XFREE(MTYPE_ROUTE_MAP_NAME,
598ce6bd 5332 member->default_rmap[afi][safi].name);
b4897fa5 5333 route_map_counter_decrement(
5334 member->default_rmap[afi][safi].map);
598ce6bd 5335 member->default_rmap[afi][safi].name =
d62a17ae 5336 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
1de27621 5337 member->default_rmap[afi][safi].map = route_map;
b4897fa5 5338 route_map_counter_increment(route_map);
d62a17ae 5339 }
5340
598ce6bd 5341 /* Update peer route announcements. */
feb17238 5342 if (peer_established(member) && member->afc_nego[afi][safi]) {
598ce6bd
PM
5343 update_group_adjust_peer(
5344 peer_af_find(member, afi, safi));
5345 bgp_default_originate(member, afi, safi, 0);
e1a32ec1 5346 bgp_announce_route(member, afi, safi, false);
d62a17ae 5347 }
5348 }
598ce6bd 5349
d62a17ae 5350 return 0;
5351}
5352
5353int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
5354{
598ce6bd 5355 struct peer *member;
d62a17ae 5356 struct listnode *node, *nnode;
5357
598ce6bd
PM
5358 /* Inherit configuration from peer-group if peer is member. */
5359 if (peer_group_active(peer)) {
5360 peer_af_flag_inherit(peer, afi, safi,
5361 PEER_FLAG_DEFAULT_ORIGINATE);
e7103a96
PM
5362 PEER_STR_ATTR_INHERIT(peer, peer->group,
5363 default_rmap[afi][safi].name,
5364 MTYPE_ROUTE_MAP_NAME);
5365 PEER_ATTR_INHERIT(peer, peer->group,
5366 default_rmap[afi][safi].map);
598ce6bd
PM
5367 } else {
5368 /* Otherwise remove flag and configuration from peer. */
5369 peer_af_flag_unset(peer, afi, safi,
5370 PEER_FLAG_DEFAULT_ORIGINATE);
d62a17ae 5371 if (peer->default_rmap[afi][safi].name)
5372 XFREE(MTYPE_ROUTE_MAP_NAME,
5373 peer->default_rmap[afi][safi].name);
b4897fa5 5374 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
d62a17ae 5375 peer->default_rmap[afi][safi].name = NULL;
5376 peer->default_rmap[afi][safi].map = NULL;
5377 }
5378
598ce6bd 5379 /* Check if handling a regular peer. */
d62a17ae 5380 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
598ce6bd 5381 /* Update peer route announcements. */
feb17238 5382 if (peer_established(peer) && peer->afc_nego[afi][safi]) {
d62a17ae 5383 update_group_adjust_peer(peer_af_find(peer, afi, safi));
5384 bgp_default_originate(peer, afi, safi, 1);
e1a32ec1 5385 bgp_announce_route(peer, afi, safi, false);
d62a17ae 5386 }
598ce6bd
PM
5387
5388 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5389 return 0;
5390 }
5391
598ce6bd
PM
5392 /*
5393 * Remove flag and configuration from all peer-group members, unless
f75b9163 5394 * they are explicitly overriding peer-group configuration.
598ce6bd
PM
5395 */
5396 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5397 /* Skip peers with overridden configuration. */
5398 if (CHECK_FLAG(member->af_flags_override[afi][safi],
5399 PEER_FLAG_DEFAULT_ORIGINATE))
5400 continue;
5401
5402 /* Remove flag and configuration on peer-group member. */
66de9680 5403 UNSET_FLAG(member->af_flags[afi][safi],
d62a17ae 5404 PEER_FLAG_DEFAULT_ORIGINATE);
66de9680 5405 if (member->default_rmap[afi][safi].name)
d62a17ae 5406 XFREE(MTYPE_ROUTE_MAP_NAME,
66de9680
S
5407 member->default_rmap[afi][safi].name);
5408 route_map_counter_decrement(member->default_rmap[afi][safi].map);
5409 member->default_rmap[afi][safi].name = NULL;
5410 member->default_rmap[afi][safi].map = NULL;
d62a17ae 5411
598ce6bd 5412 /* Update peer route announcements. */
feb17238 5413 if (peer_established(member) && member->afc_nego[afi][safi]) {
66de9680
S
5414 update_group_adjust_peer(peer_af_find(member, afi, safi));
5415 bgp_default_originate(member, afi, safi, 1);
e1a32ec1 5416 bgp_announce_route(member, afi, safi, false);
d62a17ae 5417 }
5418 }
598ce6bd 5419
d62a17ae 5420 return 0;
5421}
5422
3dc339cd 5423void peer_port_set(struct peer *peer, uint16_t port)
d62a17ae 5424{
5425 peer->port = port;
c41e9372 5426 peer_flag_set(peer, PEER_FLAG_PORT);
d62a17ae 5427}
5428
3dc339cd 5429void peer_port_unset(struct peer *peer)
d62a17ae 5430{
5431 peer->port = BGP_PORT_DEFAULT;
c41e9372 5432 peer_flag_unset(peer, PEER_FLAG_PORT);
d62a17ae 5433}
5434
4ab46701
AR
5435/* Set the TCP-MSS value in the peer structure,
5436 * This gets applied only after connection reset
5437 * So this value will be used in bgp_connect.
5438 */
5439void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss)
5440{
5441 peer->tcp_mss = tcp_mss;
5442 SET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
5443}
5444
5445/* Reset the TCP-MSS value in the peer structure,
5446 * This gets applied only after connection reset
5447 * So this value will be used in bgp_connect.
5448 */
5449void peer_tcp_mss_unset(struct peer *peer)
5450{
5451 UNSET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
5452 peer->tcp_mss = 0;
5453}
5454
d62a17ae 5455/*
5456 * Helper function that is called after the name of the policy
5457 * being used by a peer has changed (AF specific). Automatically
5458 * initiates inbound or outbound processing as needed.
5459 */
5460static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
5461 int outbound)
5462{
5463 if (outbound) {
5464 update_group_adjust_peer(peer_af_find(peer, afi, safi));
feb17238 5465 if (peer_established(peer))
e1a32ec1 5466 bgp_announce_route(peer, afi, safi, false);
d62a17ae 5467 } else {
feb17238 5468 if (!peer_established(peer))
d62a17ae 5469 return;
5470
5471 if (CHECK_FLAG(peer->af_flags[afi][safi],
f1aa4929 5472 PEER_FLAG_SOFT_RECONFIG)) {
d62a17ae 5473 bgp_soft_reconfig_in(peer, afi, safi);
f1aa4929
DA
5474 } else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) ||
5475 CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) {
5476 if (CHECK_FLAG(peer->af_cap[afi][safi],
5477 PEER_CAP_ORF_PREFIX_SM_ADV) &&
5478 (CHECK_FLAG(peer->af_cap[afi][safi],
5479 PEER_CAP_ORF_PREFIX_RM_RCV) ||
5480 CHECK_FLAG(peer->af_cap[afi][safi],
5481 PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
5482 peer_clear_soft(peer, afi, safi,
5483 BGP_CLEAR_SOFT_IN_ORF_PREFIX);
5484 else
5485 bgp_route_refresh_send(
5486 peer, afi, safi, 0, 0, 0,
5487 BGP_ROUTE_REFRESH_NORMAL);
5488 }
d62a17ae 5489 }
5490}
5491
5492
5493/* neighbor weight. */
d7c0a89a 5494int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, uint16_t weight)
d62a17ae 5495{
598ce6bd 5496 struct peer *member;
d62a17ae 5497 struct listnode *node, *nnode;
5498
598ce6bd
PM
5499 /* Set flag and configuration on peer. */
5500 peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT);
d62a17ae 5501 if (peer->weight[afi][safi] != weight) {
5502 peer->weight[afi][safi] = weight;
d62a17ae 5503 peer_on_policy_change(peer, afi, safi, 0);
5504 }
5505
598ce6bd 5506 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5507 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5508 return 0;
5509
598ce6bd
PM
5510 /*
5511 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5512 * explicitly overriding peer-group configuration.
598ce6bd
PM
5513 */
5514 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5515 /* Skip peers with overridden configuration. */
5516 if (CHECK_FLAG(member->af_flags_override[afi][safi],
5517 PEER_FLAG_WEIGHT))
5518 continue;
5519
5520 /* Set flag and configuration on peer-group member. */
5521 SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
5522 if (member->weight[afi][safi] != weight) {
5523 member->weight[afi][safi] = weight;
5524 peer_on_policy_change(member, afi, safi, 0);
d62a17ae 5525 }
5526 }
598ce6bd 5527
d62a17ae 5528 return 0;
5529}
5530
5531int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi)
5532{
598ce6bd 5533 struct peer *member;
d62a17ae 5534 struct listnode *node, *nnode;
5535
598ce6bd
PM
5536 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
5537 return 0;
5538
5539 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 5540 if (peer_group_active(peer)) {
598ce6bd 5541 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_WEIGHT);
e7103a96 5542 PEER_ATTR_INHERIT(peer, peer->group, weight[afi][safi]);
d62a17ae 5543
598ce6bd
PM
5544 peer_on_policy_change(peer, afi, safi, 0);
5545 return 0;
d62a17ae 5546 }
5547
598ce6bd
PM
5548 /* Remove flag and configuration from peer. */
5549 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT);
5550 peer->weight[afi][safi] = 0;
5551 peer_on_policy_change(peer, afi, safi, 0);
d62a17ae 5552
598ce6bd
PM
5553 /* Skip peer-group mechanics for regular peers. */
5554 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5555 return 0;
d62a17ae 5556
598ce6bd
PM
5557 /*
5558 * Remove flag and configuration from all peer-group members, unless
f75b9163 5559 * they are explicitly overriding peer-group configuration.
598ce6bd
PM
5560 */
5561 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5562 /* Skip peers with overridden configuration. */
5563 if (CHECK_FLAG(member->af_flags_override[afi][safi],
5564 PEER_FLAG_WEIGHT))
5565 continue;
5566
5567 /* Skip peers where flag is already disabled. */
5568 if (!CHECK_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT))
5569 continue;
5570
5571 /* Remove flag and configuration on peer-group member. */
5572 UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
5573 member->weight[afi][safi] = 0;
5574 peer_on_policy_change(member, afi, safi, 0);
d62a17ae 5575 }
598ce6bd 5576
d62a17ae 5577 return 0;
5578}
5579
d7c0a89a 5580int peer_timers_set(struct peer *peer, uint32_t keepalive, uint32_t holdtime)
d62a17ae 5581{
b90a8e13 5582 struct peer *member;
d62a17ae 5583 struct listnode *node, *nnode;
5584
48e1932b 5585 if (keepalive > UINT16_MAX)
d62a17ae 5586 return BGP_ERR_INVALID_VALUE;
5587
48e1932b 5588 if (holdtime > UINT16_MAX)
d62a17ae 5589 return BGP_ERR_INVALID_VALUE;
5590
d62a17ae 5591 if (holdtime < 3 && holdtime != 0)
5592 return BGP_ERR_INVALID_VALUE;
5593
b90a8e13
PM
5594 /* Set flag and configuration on peer. */
5595 peer_flag_set(peer, PEER_FLAG_TIMER);
d62a17ae 5596 peer->holdtime = holdtime;
5597 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
5598
b90a8e13
PM
5599 /* Skip peer-group mechanics for regular peers. */
5600 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5601 return 0;
d25e4efc 5602
b90a8e13
PM
5603 /*
5604 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5605 * explicitly overriding peer-group configuration.
b90a8e13
PM
5606 */
5607 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5608 /* Skip peers with overridden configuration. */
5609 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER))
5610 continue;
d25e4efc 5611
b90a8e13
PM
5612 /* Set flag and configuration on peer-group member. */
5613 SET_FLAG(member->flags, PEER_FLAG_TIMER);
b28a12e6 5614 PEER_ATTR_INHERIT(member, peer->group, holdtime);
5615 PEER_ATTR_INHERIT(member, peer->group, keepalive);
d62a17ae 5616 }
d25e4efc 5617
d62a17ae 5618 return 0;
5619}
5620
5621int peer_timers_unset(struct peer *peer)
5622{
b90a8e13 5623 struct peer *member;
d62a17ae 5624 struct listnode *node, *nnode;
5625
b90a8e13
PM
5626 /* Inherit configuration from peer-group if peer is member. */
5627 if (peer_group_active(peer)) {
5628 peer_flag_inherit(peer, PEER_FLAG_TIMER);
5629 PEER_ATTR_INHERIT(peer, peer->group, holdtime);
5630 PEER_ATTR_INHERIT(peer, peer->group, keepalive);
5631 } else {
5632 /* Otherwise remove flag and configuration from peer. */
5633 peer_flag_unset(peer, PEER_FLAG_TIMER);
d25e4efc 5634 peer->holdtime = 0;
b90a8e13
PM
5635 peer->keepalive = 0;
5636 }
d25e4efc 5637
b90a8e13
PM
5638 /* Skip peer-group mechanics for regular peers. */
5639 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5640 return 0;
5641
5642 /*
5643 * Remove flag and configuration from all peer-group members, unless
f75b9163 5644 * they are explicitly overriding peer-group configuration.
b90a8e13
PM
5645 */
5646 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5647 /* Skip peers with overridden configuration. */
5648 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER))
5649 continue;
d25e4efc 5650
b90a8e13
PM
5651 /* Remove flag and configuration on peer-group member. */
5652 UNSET_FLAG(member->flags, PEER_FLAG_TIMER);
5653 member->holdtime = 0;
5654 member->keepalive = 0;
d62a17ae 5655 }
5656
5657 return 0;
5658}
5659
d7c0a89a 5660int peer_timers_connect_set(struct peer *peer, uint32_t connect)
d62a17ae 5661{
b90a8e13 5662 struct peer *member;
d62a17ae 5663 struct listnode *node, *nnode;
5664
48e1932b 5665 if (connect > UINT16_MAX)
d62a17ae 5666 return BGP_ERR_INVALID_VALUE;
5667
b90a8e13
PM
5668 /* Set flag and configuration on peer. */
5669 peer_flag_set(peer, PEER_FLAG_TIMER_CONNECT);
d62a17ae 5670 peer->connect = connect;
d62a17ae 5671 peer->v_connect = connect;
5672
b90a8e13 5673 /* Skip peer-group mechanics for regular peers. */
91de6fa2 5674 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
feb17238 5675 if (!peer_established(peer)) {
91de6fa2 5676 if (peer_active(peer))
5677 BGP_EVENT_ADD(peer, BGP_Stop);
5678 BGP_EVENT_ADD(peer, BGP_Start);
5679 }
d62a17ae 5680 return 0;
91de6fa2 5681 }
b90a8e13
PM
5682 /*
5683 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5684 * explicitly overriding peer-group configuration.
b90a8e13
PM
5685 */
5686 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5687 /* Skip peers with overridden configuration. */
5688 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER_CONNECT))
5689 continue;
5690
5691 /* Set flag and configuration on peer-group member. */
5692 SET_FLAG(member->flags, PEER_FLAG_TIMER_CONNECT);
5693 member->connect = connect;
5694 member->v_connect = connect;
91de6fa2 5695
feb17238 5696 if (!peer_established(member)) {
91de6fa2 5697 if (peer_active(member))
5698 BGP_EVENT_ADD(member, BGP_Stop);
5699 BGP_EVENT_ADD(member, BGP_Start);
5700 }
d62a17ae 5701 }
b90a8e13 5702
d62a17ae 5703 return 0;
5704}
5705
5706int peer_timers_connect_unset(struct peer *peer)
5707{
b90a8e13 5708 struct peer *member;
d62a17ae 5709 struct listnode *node, *nnode;
5710
b90a8e13
PM
5711 /* Inherit configuration from peer-group if peer is member. */
5712 if (peer_group_active(peer)) {
5713 peer_flag_inherit(peer, PEER_FLAG_TIMER_CONNECT);
5714 PEER_ATTR_INHERIT(peer, peer->group, connect);
5715 } else {
5716 /* Otherwise remove flag and configuration from peer. */
5717 peer_flag_unset(peer, PEER_FLAG_TIMER_CONNECT);
5718 peer->connect = 0;
5719 }
d62a17ae 5720
b90a8e13
PM
5721 /* Set timer with fallback to default value. */
5722 if (peer->connect)
5723 peer->v_connect = peer->connect;
5724 else
5d5393b9 5725 peer->v_connect = peer->bgp->default_connect_retry;
d62a17ae 5726
b90a8e13 5727 /* Skip peer-group mechanics for regular peers. */
91de6fa2 5728 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
feb17238 5729 if (!peer_established(peer)) {
91de6fa2 5730 if (peer_active(peer))
5731 BGP_EVENT_ADD(peer, BGP_Stop);
5732 BGP_EVENT_ADD(peer, BGP_Start);
5733 }
d62a17ae 5734 return 0;
91de6fa2 5735 }
b90a8e13
PM
5736 /*
5737 * Remove flag and configuration from all peer-group members, unless
f75b9163 5738 * they are explicitly overriding peer-group configuration.
b90a8e13
PM
5739 */
5740 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5741 /* Skip peers with overridden configuration. */
5742 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER_CONNECT))
5743 continue;
5744
5745 /* Remove flag and configuration on peer-group member. */
5746 UNSET_FLAG(member->flags, PEER_FLAG_TIMER_CONNECT);
5747 member->connect = 0;
5d5393b9 5748 member->v_connect = peer->bgp->default_connect_retry;
91de6fa2 5749
feb17238 5750 if (!peer_established(member)) {
91de6fa2 5751 if (peer_active(member))
5752 BGP_EVENT_ADD(member, BGP_Stop);
5753 BGP_EVENT_ADD(member, BGP_Start);
5754 }
d62a17ae 5755 }
b90a8e13 5756
d62a17ae 5757 return 0;
5758}
5759
d7c0a89a 5760int peer_advertise_interval_set(struct peer *peer, uint32_t routeadv)
d62a17ae 5761{
b90a8e13 5762 struct peer *member;
d62a17ae 5763 struct listnode *node, *nnode;
5764
5765 if (routeadv > 600)
5766 return BGP_ERR_INVALID_VALUE;
5767
b90a8e13
PM
5768 /* Set flag and configuration on peer. */
5769 peer_flag_set(peer, PEER_FLAG_ROUTEADV);
d62a17ae 5770 peer->routeadv = routeadv;
5771 peer->v_routeadv = routeadv;
5772
b90a8e13 5773 /* Check if handling a regular peer. */
d62a17ae 5774 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
b90a8e13 5775 /* Update peer route announcements. */
d62a17ae 5776 update_group_adjust_peer_afs(peer);
feb17238 5777 if (peer_established(peer))
d62a17ae 5778 bgp_announce_route_all(peer);
b90a8e13
PM
5779
5780 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5781 return 0;
5782 }
5783
b90a8e13
PM
5784 /*
5785 * Set flag and configuration on all peer-group members, unless they are
f75b9163 5786 * explicitly overriding peer-group configuration.
b90a8e13
PM
5787 */
5788 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5789 /* Skip peers with overridden configuration. */
5790 if (CHECK_FLAG(member->flags_override, PEER_FLAG_ROUTEADV))
5791 continue;
5792
5793 /* Set flag and configuration on peer-group member. */
5794 SET_FLAG(member->flags, PEER_FLAG_ROUTEADV);
5795 member->routeadv = routeadv;
5796 member->v_routeadv = routeadv;
5797
5798 /* Update peer route announcements. */
5799 update_group_adjust_peer_afs(member);
feb17238 5800 if (peer_established(member))
b90a8e13 5801 bgp_announce_route_all(member);
d62a17ae 5802 }
5803
5804 return 0;
5805}
5806
5807int peer_advertise_interval_unset(struct peer *peer)
5808{
b90a8e13 5809 struct peer *member;
d62a17ae 5810 struct listnode *node, *nnode;
5811
b90a8e13
PM
5812 /* Inherit configuration from peer-group if peer is member. */
5813 if (peer_group_active(peer)) {
5814 peer_flag_inherit(peer, PEER_FLAG_ROUTEADV);
5815 PEER_ATTR_INHERIT(peer, peer->group, routeadv);
5816 } else {
5817 /* Otherwise remove flag and configuration from peer. */
5818 peer_flag_unset(peer, PEER_FLAG_ROUTEADV);
5819 peer->routeadv = 0;
5820 }
d62a17ae 5821
b90a8e13
PM
5822 /* Set timer with fallback to default value. */
5823 if (peer->routeadv)
5824 peer->v_routeadv = peer->routeadv;
d62a17ae 5825 else
b90a8e13
PM
5826 peer->v_routeadv = (peer->sort == BGP_PEER_IBGP)
5827 ? BGP_DEFAULT_IBGP_ROUTEADV
5828 : BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 5829
b90a8e13 5830 /* Check if handling a regular peer. */
d62a17ae 5831 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
b90a8e13 5832 /* Update peer route announcements. */
d62a17ae 5833 update_group_adjust_peer_afs(peer);
feb17238 5834 if (peer_established(peer))
d62a17ae 5835 bgp_announce_route_all(peer);
b90a8e13
PM
5836
5837 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5838 return 0;
5839 }
5840
b90a8e13
PM
5841 /*
5842 * Remove flag and configuration from all peer-group members, unless
f75b9163 5843 * they are explicitly overriding peer-group configuration.
b90a8e13
PM
5844 */
5845 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5846 /* Skip peers with overridden configuration. */
5847 if (CHECK_FLAG(member->flags_override, PEER_FLAG_ROUTEADV))
5848 continue;
d62a17ae 5849
b90a8e13
PM
5850 /* Remove flag and configuration on peer-group member. */
5851 UNSET_FLAG(member->flags, PEER_FLAG_ROUTEADV);
5852 member->routeadv = 0;
5853 member->v_routeadv = (member->sort == BGP_PEER_IBGP)
5854 ? BGP_DEFAULT_IBGP_ROUTEADV
5855 : BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 5856
b90a8e13
PM
5857 /* Update peer route announcements. */
5858 update_group_adjust_peer_afs(member);
feb17238 5859 if (peer_established(member))
b90a8e13 5860 bgp_announce_route_all(member);
d62a17ae 5861 }
5862
5863 return 0;
5864}
5865
6c537a18
DS
5866/* set the peers RFC 4271 DelayOpen session attribute flag and DelayOpenTimer
5867 * interval
5868 */
5869int peer_timers_delayopen_set(struct peer *peer, uint32_t delayopen)
5870{
5871 struct peer *member;
5872 struct listnode *node;
5873
5874 /* Set peers session attribute flag and timer interval. */
5875 peer_flag_set(peer, PEER_FLAG_TIMER_DELAYOPEN);
5876 peer->delayopen = delayopen;
5877 peer->v_delayopen = delayopen;
5878
5879 /* Skip group mechanics for regular peers. */
5880 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5881 return 0;
5882
5883 /* Set flag and configuration on all peer-group members, unless they are
f75b9163 5884 * explicitly overriding peer-group configuration.
6c537a18
DS
5885 */
5886 for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
5887 /* Skip peers with overridden configuration. */
5888 if (CHECK_FLAG(member->flags_override,
5889 PEER_FLAG_TIMER_DELAYOPEN))
5890 continue;
5891
5892 /* Set session attribute flag and timer intervals on peer-group
5893 * member.
5894 */
5895 SET_FLAG(member->flags, PEER_FLAG_TIMER_DELAYOPEN);
5896 member->delayopen = delayopen;
5897 member->v_delayopen = delayopen;
5898 }
5899
5900 return 0;
5901}
5902
5903/* unset the peers RFC 4271 DelayOpen session attribute flag and reset the
5904 * DelayOpenTimer interval to the default value.
5905 */
5906int peer_timers_delayopen_unset(struct peer *peer)
5907{
5908 struct peer *member;
5909 struct listnode *node;
5910
5911 /* Inherit configuration from peer-group if peer is member. */
5912 if (peer_group_active(peer)) {
5913 peer_flag_inherit(peer, PEER_FLAG_TIMER_DELAYOPEN);
5914 PEER_ATTR_INHERIT(peer, peer->group, delayopen);
5915 } else {
5916 /* Otherwise remove session attribute flag and set timer
5917 * interval to default value.
5918 */
5919 peer_flag_unset(peer, PEER_FLAG_TIMER_DELAYOPEN);
5920 peer->delayopen = peer->bgp->default_delayopen;
5921 }
5922
5923 /* Set timer value to zero */
5924 peer->v_delayopen = 0;
5925
5926 /* Skip peer-group mechanics for regular peers. */
5927 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5928 return 0;
5929
5930 /* Remove flag and configuration from all peer-group members, unless
f75b9163 5931 * they are explicitly overriding peer-group configuration.
6c537a18
DS
5932 */
5933 for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
5934 /* Skip peers with overridden configuration. */
5935 if (CHECK_FLAG(member->flags_override,
5936 PEER_FLAG_TIMER_DELAYOPEN))
5937 continue;
5938
5939 /* Remove session attribute flag, reset the timer interval to
5940 * the default value and set the timer value to zero.
5941 */
5942 UNSET_FLAG(member->flags, PEER_FLAG_TIMER_DELAYOPEN);
5943 member->delayopen = peer->bgp->default_delayopen;
5944 member->v_delayopen = 0;
5945 }
5946
5947 return 0;
5948}
5949
d62a17ae 5950/* neighbor interface */
5951void peer_interface_set(struct peer *peer, const char *str)
5952{
0a22ddfb 5953 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
d62a17ae 5954 peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
5955}
5956
5957void peer_interface_unset(struct peer *peer)
5958{
0a22ddfb 5959 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
d62a17ae 5960}
5961
5962/* Allow-as in. */
5963int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
5964 int allow_num, int origin)
5965{
598ce6bd 5966 struct peer *member;
d62a17ae 5967 struct listnode *node, *nnode;
5968
598ce6bd
PM
5969 if (!origin && (allow_num < 1 || allow_num > 10))
5970 return BGP_ERR_INVALID_VALUE;
5971
5972 /* Set flag and configuration on peer. */
5973 peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
d62a17ae 5974 if (origin) {
598ce6bd 5975 if (peer->allowas_in[afi][safi] != 0
d62a17ae 5976 || !CHECK_FLAG(peer->af_flags[afi][safi],
5977 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
d62a17ae 5978 peer_af_flag_set(peer, afi, safi,
5979 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd 5980 peer->allowas_in[afi][safi] = 0;
d62a17ae 5981 peer_on_policy_change(peer, afi, safi, 0);
5982 }
d62a17ae 5983 } else {
d62a17ae 5984 if (peer->allowas_in[afi][safi] != allow_num
5985 || CHECK_FLAG(peer->af_flags[afi][safi],
5986 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
598ce6bd 5987
d62a17ae 5988 peer_af_flag_unset(peer, afi, safi,
5989 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd 5990 peer->allowas_in[afi][safi] = allow_num;
d62a17ae 5991 peer_on_policy_change(peer, afi, safi, 0);
5992 }
598ce6bd 5993 }
d62a17ae 5994
598ce6bd
PM
5995 /* Skip peer-group mechanics for regular peers. */
5996 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5997 return 0;
d62a17ae 5998
598ce6bd
PM
5999 /*
6000 * Set flag and configuration on all peer-group members, unless
f75b9163 6001 * they are explicitly overriding peer-group configuration.
598ce6bd
PM
6002 */
6003 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6004 /* Skip peers with overridden configuration. */
6005 if (CHECK_FLAG(member->af_flags_override[afi][safi],
246bb5f0 6006 PEER_FLAG_ALLOWAS_IN))
598ce6bd
PM
6007 continue;
6008
6009 /* Set flag and configuration on peer-group member. */
6010 SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
6011 if (origin) {
6012 if (member->allowas_in[afi][safi] != 0
6013 || !CHECK_FLAG(member->af_flags[afi][safi],
cf9ac8bf 6014 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
598ce6bd 6015 SET_FLAG(member->af_flags[afi][safi],
cf9ac8bf 6016 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd
PM
6017 member->allowas_in[afi][safi] = 0;
6018 peer_on_policy_change(peer, afi, safi, 0);
6019 }
6020 } else {
6021 if (member->allowas_in[afi][safi] != allow_num
6022 || CHECK_FLAG(member->af_flags[afi][safi],
d62a17ae 6023 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
598ce6bd
PM
6024 UNSET_FLAG(member->af_flags[afi][safi],
6025 PEER_FLAG_ALLOWAS_IN_ORIGIN);
6026 member->allowas_in[afi][safi] = allow_num;
d62a17ae 6027 peer_on_policy_change(peer, afi, safi, 0);
6028 }
6029 }
6030 }
6031
6032 return 0;
6033}
6034
6035int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
6036{
598ce6bd 6037 struct peer *member;
d62a17ae 6038 struct listnode *node, *nnode;
6039
598ce6bd
PM
6040 /* Skip peer if flag is already disabled. */
6041 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
6042 return 0;
d62a17ae 6043
598ce6bd
PM
6044 /* Inherit configuration from peer-group if peer is member. */
6045 if (peer_group_active(peer)) {
6046 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
6047 peer_af_flag_inherit(peer, afi, safi,
cf9ac8bf 6048 PEER_FLAG_ALLOWAS_IN_ORIGIN);
e7103a96 6049 PEER_ATTR_INHERIT(peer, peer->group, allowas_in[afi][safi]);
d62a17ae 6050 peer_on_policy_change(peer, afi, safi, 0);
598ce6bd
PM
6051
6052 return 0;
6053 }
6054
6055 /* Remove flag and configuration from peer. */
6056 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
6057 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN);
6058 peer->allowas_in[afi][safi] = 0;
6059 peer_on_policy_change(peer, afi, safi, 0);
6060
6061 /* Skip peer-group mechanics if handling a regular peer. */
6062 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
6063 return 0;
6064
6065 /*
6066 * Remove flags and configuration from all peer-group members, unless
f75b9163 6067 * they are explicitly overriding peer-group configuration.
598ce6bd
PM
6068 */
6069 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6070 /* Skip peers with overridden configuration. */
6071 if (CHECK_FLAG(member->af_flags_override[afi][safi],
cf9ac8bf 6072 PEER_FLAG_ALLOWAS_IN))
598ce6bd
PM
6073 continue;
6074
598ce6bd 6075 /* Remove flags and configuration on peer-group member. */
cf9ac8bf 6076 UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
598ce6bd 6077 UNSET_FLAG(member->af_flags[afi][safi],
cf9ac8bf 6078 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd
PM
6079 member->allowas_in[afi][safi] = 0;
6080 peer_on_policy_change(member, afi, safi, 0);
d62a17ae 6081 }
6082
6083 return 0;
6084}
6085
f4b8ec07
CS
6086int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
6087 bool replace_as)
d62a17ae 6088{
a14810f4 6089 bool old_no_prepend, old_replace_as;
d62a17ae 6090 struct bgp *bgp = peer->bgp;
a14810f4 6091 struct peer *member;
d62a17ae 6092 struct listnode *node, *nnode;
3061acc2 6093 enum bgp_peer_sort ptype = peer_sort(peer);
d62a17ae 6094
469cbb0f 6095 if (ptype != BGP_PEER_EBGP && ptype != BGP_PEER_INTERNAL)
d62a17ae 6096 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
6097
6098 if (bgp->as == as)
6099 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
6100
6101 if (peer->as == as)
6102 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
6103
a14810f4
PM
6104 /* Save previous flag states. */
6105 old_no_prepend =
6106 !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
6107 old_replace_as =
6108 !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
d62a17ae 6109
a14810f4
PM
6110 /* Set flag and configuration on peer. */
6111 peer_flag_set(peer, PEER_FLAG_LOCAL_AS);
6112 peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND, no_prepend);
6113 peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS, replace_as);
d62a17ae 6114
a14810f4
PM
6115 if (peer->change_local_as == as && old_no_prepend == no_prepend
6116 && old_replace_as == replace_as)
6117 return 0;
6118 peer->change_local_as = as;
d62a17ae 6119
a14810f4 6120 /* Check if handling a regular peer. */
d62a17ae 6121 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 6122 /* Send notification or reset peer depending on state. */
d62a17ae 6123 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
6124 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
6125 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
6126 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6127 } else
6128 bgp_session_reset(peer);
a14810f4
PM
6129
6130 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6131 return 0;
6132 }
6133
a14810f4
PM
6134 /*
6135 * Set flag and configuration on all peer-group members, unless they are
f75b9163 6136 * explicitly overriding peer-group configuration.
a14810f4
PM
6137 */
6138 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6139 /* Skip peers with overridden configuration. */
6140 if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
6141 continue;
d62a17ae 6142
a14810f4
PM
6143 /* Skip peers with the same configuration. */
6144 old_no_prepend = CHECK_FLAG(member->flags,
6145 PEER_FLAG_LOCAL_AS_NO_PREPEND);
6146 old_replace_as = CHECK_FLAG(member->flags,
6147 PEER_FLAG_LOCAL_AS_REPLACE_AS);
6148 if (member->change_local_as == as
6149 && CHECK_FLAG(member->flags, PEER_FLAG_LOCAL_AS)
6150 && old_no_prepend == no_prepend
6151 && old_replace_as == replace_as)
6152 continue;
d62a17ae 6153
a14810f4
PM
6154 /* Set flag and configuration on peer-group member. */
6155 SET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
6156 COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND,
6157 no_prepend);
6158 COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,
6159 replace_as);
6160 member->change_local_as = as;
6161
6162 /* Send notification or stop peer depending on state. */
6163 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
6164 member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
6165 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 6166 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6167 } else
a14810f4 6168 BGP_EVENT_ADD(member, BGP_Stop);
d62a17ae 6169 }
6170
6171 return 0;
6172}
6173
6174int peer_local_as_unset(struct peer *peer)
6175{
a14810f4 6176 struct peer *member;
d62a17ae 6177 struct listnode *node, *nnode;
6178
a14810f4 6179 if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS))
d62a17ae 6180 return 0;
6181
a14810f4
PM
6182 /* Inherit configuration from peer-group if peer is member. */
6183 if (peer_group_active(peer)) {
6184 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS);
6185 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
6186 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
6187 PEER_ATTR_INHERIT(peer, peer->group, change_local_as);
6188 } else {
6189 /* Otherwise remove flag and configuration from peer. */
6190 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
6191 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
6192 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
6193 peer->change_local_as = 0;
6194 }
d62a17ae 6195
a14810f4 6196 /* Check if handling a regular peer. */
d62a17ae 6197 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 6198 /* Send notification or stop peer depending on state. */
d62a17ae 6199 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
6200 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
6201 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
6202 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6203 } else
6204 BGP_EVENT_ADD(peer, BGP_Stop);
6205
a14810f4 6206 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6207 return 0;
6208 }
6209
a14810f4
PM
6210 /*
6211 * Remove flag and configuration from all peer-group members, unless
f75b9163 6212 * they are explicitly overriding peer-group configuration.
a14810f4
PM
6213 */
6214 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6215 /* Skip peers with overridden configuration. */
6216 if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
6217 continue;
d62a17ae 6218
a14810f4
PM
6219 /* Remove flag and configuration on peer-group member. */
6220 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
6221 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
6222 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
6223 member->change_local_as = 0;
6224
6225 /* Send notification or stop peer depending on state. */
6226 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
6227 member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
6228 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 6229 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6230 } else
a14810f4 6231 bgp_session_reset(member);
d62a17ae 6232 }
a14810f4 6233
d62a17ae 6234 return 0;
6235}
6236
6237/* Set password for authenticating with the peer. */
6238int peer_password_set(struct peer *peer, const char *password)
6239{
a14810f4
PM
6240 struct peer *member;
6241 struct listnode *node, *nnode;
d62a17ae 6242 int len = password ? strlen(password) : 0;
6243 int ret = BGP_SUCCESS;
6244
6245 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
6246 return BGP_ERR_INVALID_VALUE;
6247
a14810f4
PM
6248 /* Set flag and configuration on peer. */
6249 peer_flag_set(peer, PEER_FLAG_PASSWORD);
6250 if (peer->password && strcmp(peer->password, password) == 0)
d62a17ae 6251 return 0;
a14810f4 6252 XFREE(MTYPE_PEER_PASSWORD, peer->password);
d62a17ae 6253 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
6254
a14810f4 6255 /* Check if handling a regular peer. */
d62a17ae 6256 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 6257 /* Send notification or reset peer depending on state. */
d62a17ae 6258 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
6259 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
6260 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6261 else
6262 bgp_session_reset(peer);
6263
a14810f4
PM
6264 /*
6265 * Attempt to install password on socket and skip peer-group
6266 * mechanics.
6267 */
d62a17ae 6268 if (BGP_PEER_SU_UNSPEC(peer))
6269 return BGP_SUCCESS;
d62a17ae 6270 return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS
6271 : BGP_ERR_TCPSIG_FAILED;
6272 }
6273
a14810f4
PM
6274 /*
6275 * Set flag and configuration on all peer-group members, unless they are
f75b9163 6276 * explicitly overriding peer-group configuration.
a14810f4
PM
6277 */
6278 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6279 /* Skip peers with overridden configuration. */
6280 if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
d62a17ae 6281 continue;
6282
a14810f4
PM
6283 /* Skip peers with the same password. */
6284 if (member->password && strcmp(member->password, password) == 0)
6285 continue;
d62a17ae 6286
a14810f4
PM
6287 /* Set flag and configuration on peer-group member. */
6288 SET_FLAG(member->flags, PEER_FLAG_PASSWORD);
6289 if (member->password)
6290 XFREE(MTYPE_PEER_PASSWORD, member->password);
6291 member->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
6292
6293 /* Send notification or reset peer depending on state. */
6294 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
6295 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 6296 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6297 else
a14810f4 6298 bgp_session_reset(member);
d62a17ae 6299
a14810f4
PM
6300 /* Attempt to install password on socket. */
6301 if (!BGP_PEER_SU_UNSPEC(member) && bgp_md5_set(member) < 0)
6302 ret = BGP_ERR_TCPSIG_FAILED;
d62a17ae 6303 }
6304
9e7d9a61
QY
6305 /* Set flag and configuration on all peer-group listen ranges */
6306 struct listnode *ln;
6307 struct prefix *lr;
6308
6309 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
a4faae3a 6310 bgp_md5_set_prefix(peer->bgp, lr, password);
9e7d9a61 6311 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
a4faae3a 6312 bgp_md5_set_prefix(peer->bgp, lr, password);
9e7d9a61 6313
d62a17ae 6314 return ret;
6315}
6316
6317int peer_password_unset(struct peer *peer)
6318{
a14810f4
PM
6319 struct peer *member;
6320 struct listnode *node, *nnode;
d62a17ae 6321
a14810f4 6322 if (!CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD))
d62a17ae 6323 return 0;
6324
a14810f4
PM
6325 /* Inherit configuration from peer-group if peer is member. */
6326 if (peer_group_active(peer)) {
6327 peer_flag_inherit(peer, PEER_FLAG_PASSWORD);
6328 PEER_STR_ATTR_INHERIT(peer, peer->group, password,
6329 MTYPE_PEER_PASSWORD);
6330 } else {
6331 /* Otherwise remove flag and configuration from peer. */
6332 peer_flag_unset(peer, PEER_FLAG_PASSWORD);
6333 XFREE(MTYPE_PEER_PASSWORD, peer->password);
6334 }
6335
6336 /* Check if handling a regular peer. */
d62a17ae 6337 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 6338 /* Send notification or reset peer depending on state. */
d62a17ae 6339 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
6340 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
6341 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6342 else
6343 bgp_session_reset(peer);
6344
a14810f4 6345 /* Attempt to uninstall password on socket. */
d62a17ae 6346 if (!BGP_PEER_SU_UNSPEC(peer))
6347 bgp_md5_unset(peer);
a14810f4 6348 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6349 return 0;
6350 }
6351
a14810f4
PM
6352 /*
6353 * Remove flag and configuration from all peer-group members, unless
f75b9163 6354 * they are explicitly overriding peer-group configuration.
a14810f4
PM
6355 */
6356 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6357 /* Skip peers with overridden configuration. */
6358 if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
d62a17ae 6359 continue;
6360
a14810f4
PM
6361 /* Remove flag and configuration on peer-group member. */
6362 UNSET_FLAG(member->flags, PEER_FLAG_PASSWORD);
6363 XFREE(MTYPE_PEER_PASSWORD, member->password);
6364
6365 /* Send notification or reset peer depending on state. */
6366 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
6367 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 6368 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
6369 else
a14810f4 6370 bgp_session_reset(member);
d62a17ae 6371
a14810f4
PM
6372 /* Attempt to uninstall password on socket. */
6373 if (!BGP_PEER_SU_UNSPEC(member))
6374 bgp_md5_unset(member);
d62a17ae 6375 }
6376
9e7d9a61
QY
6377 /* Set flag and configuration on all peer-group listen ranges */
6378 struct listnode *ln;
6379 struct prefix *lr;
6380
6381 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
a4faae3a 6382 bgp_md5_unset_prefix(peer->bgp, lr);
9e7d9a61 6383 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
a4faae3a 6384 bgp_md5_unset_prefix(peer->bgp, lr);
9e7d9a61 6385
d62a17ae 6386 return 0;
6387}
6b0655a2 6388
3f9c7369 6389
718e3744 6390/* Set distribute list to the peer. */
d62a17ae 6391int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
6392 const char *name)
6393{
70ee29b4 6394 struct peer *member;
d62a17ae 6395 struct bgp_filter *filter;
d62a17ae 6396 struct listnode *node, *nnode;
6397
6398 if (direct != FILTER_IN && direct != FILTER_OUT)
6399 return BGP_ERR_INVALID_VALUE;
6400
70ee29b4 6401 /* Set configuration on peer. */
d62a17ae 6402 filter = &peer->filter[afi][safi];
d62a17ae 6403 if (filter->plist[direct].name)
6404 return BGP_ERR_PEER_FILTER_CONFLICT;
d62a17ae 6405 if (filter->dlist[direct].name)
6406 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
6407 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6408 filter->dlist[direct].alist = access_list_lookup(afi, name);
6409
70ee29b4 6410 /* Check if handling a regular peer. */
d62a17ae 6411 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
6412 /* Set override-flag and process peer route updates. */
6413 SET_FLAG(peer->filter_override[afi][safi][direct],
6414 PEER_FT_DISTRIBUTE_LIST);
d62a17ae 6415 peer_on_policy_change(peer, afi, safi,
6416 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6417
6418 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6419 return 0;
6420 }
6421
70ee29b4
PM
6422 /*
6423 * Set configuration on all peer-group members, un less they are
f75b9163 6424 * explicitly overriding peer-group configuration.
70ee29b4
PM
6425 */
6426 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6427 /* Skip peers with overridden configuration. */
6428 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6429 PEER_FT_DISTRIBUTE_LIST))
6430 continue;
d62a17ae 6431
70ee29b4
PM
6432 /* Set configuration on peer-group member. */
6433 filter = &member->filter[afi][safi];
d62a17ae 6434 if (filter->dlist[direct].name)
6435 XFREE(MTYPE_BGP_FILTER_NAME,
6436 filter->dlist[direct].name);
6437 filter->dlist[direct].name =
6438 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6439 filter->dlist[direct].alist = access_list_lookup(afi, name);
70ee29b4
PM
6440
6441 /* Process peer route updates. */
6442 peer_on_policy_change(member, afi, safi,
d62a17ae 6443 (direct == FILTER_OUT) ? 1 : 0);
6444 }
6445
6446 return 0;
6447}
6448
6449int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
6450{
70ee29b4 6451 struct peer *member;
d62a17ae 6452 struct bgp_filter *filter;
d62a17ae 6453 struct listnode *node, *nnode;
6454
6455 if (direct != FILTER_IN && direct != FILTER_OUT)
6456 return BGP_ERR_INVALID_VALUE;
6457
70ee29b4
PM
6458 /* Unset override-flag unconditionally. */
6459 UNSET_FLAG(peer->filter_override[afi][safi][direct],
6460 PEER_FT_DISTRIBUTE_LIST);
d62a17ae 6461
70ee29b4 6462 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 6463 if (peer_group_active(peer)) {
e7103a96
PM
6464 PEER_STR_ATTR_INHERIT(peer, peer->group,
6465 filter[afi][safi].dlist[direct].name,
6466 MTYPE_BGP_FILTER_NAME);
6467 PEER_ATTR_INHERIT(peer, peer->group,
6468 filter[afi][safi].dlist[direct].alist);
70ee29b4
PM
6469 } else {
6470 /* Otherwise remove configuration from peer. */
6471 filter = &peer->filter[afi][safi];
6472 if (filter->dlist[direct].name)
6473 XFREE(MTYPE_BGP_FILTER_NAME,
6474 filter->dlist[direct].name);
6475 filter->dlist[direct].name = NULL;
6476 filter->dlist[direct].alist = NULL;
d62a17ae 6477 }
6478
70ee29b4 6479 /* Check if handling a regular peer. */
d62a17ae 6480 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 6481 /* Process peer route updates. */
d62a17ae 6482 peer_on_policy_change(peer, afi, safi,
6483 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6484
6485 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6486 return 0;
6487 }
6488
70ee29b4
PM
6489 /*
6490 * Remove configuration on all peer-group members, unless they are
f75b9163 6491 * explicitly overriding peer-group configuration.
70ee29b4
PM
6492 */
6493 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6494 /* Skip peers with overridden configuration. */
6495 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6496 PEER_FT_DISTRIBUTE_LIST))
6497 continue;
d62a17ae 6498
70ee29b4
PM
6499 /* Remove configuration on peer-group member. */
6500 filter = &member->filter[afi][safi];
d62a17ae 6501 if (filter->dlist[direct].name)
6502 XFREE(MTYPE_BGP_FILTER_NAME,
6503 filter->dlist[direct].name);
6504 filter->dlist[direct].name = NULL;
6505 filter->dlist[direct].alist = NULL;
70ee29b4
PM
6506
6507 /* Process peer route updates. */
6508 peer_on_policy_change(member, afi, safi,
d62a17ae 6509 (direct == FILTER_OUT) ? 1 : 0);
6510 }
6511
6512 return 0;
6513}
6514
6515/* Update distribute list. */
6516static void peer_distribute_update(struct access_list *access)
6517{
6518 afi_t afi;
6519 safi_t safi;
6520 int direct;
6521 struct listnode *mnode, *mnnode;
6522 struct listnode *node, *nnode;
6523 struct bgp *bgp;
6524 struct peer *peer;
6525 struct peer_group *group;
6526 struct bgp_filter *filter;
6527
6528 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
6529 if (access->name)
b0a007df
IR
6530 update_group_policy_update(bgp,
6531 BGP_POLICY_DISTRIBUTE_LIST,
f1aa4929 6532 access->name, true, 0);
d62a17ae 6533 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
05c7a1cc
QY
6534 FOREACH_AFI_SAFI (afi, safi) {
6535 filter = &peer->filter[afi][safi];
6536
6537 for (direct = FILTER_IN; direct < FILTER_MAX;
6538 direct++) {
6539 if (filter->dlist[direct].name)
6540 filter->dlist[direct]
6541 .alist = access_list_lookup(
6542 afi,
d62a17ae 6543 filter->dlist[direct]
05c7a1cc
QY
6544 .name);
6545 else
6546 filter->dlist[direct].alist =
6547 NULL;
d62a17ae 6548 }
05c7a1cc 6549 }
d62a17ae 6550 }
6551 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
05c7a1cc
QY
6552 FOREACH_AFI_SAFI (afi, safi) {
6553 filter = &group->conf->filter[afi][safi];
6554
6555 for (direct = FILTER_IN; direct < FILTER_MAX;
6556 direct++) {
6557 if (filter->dlist[direct].name)
6558 filter->dlist[direct]
6559 .alist = access_list_lookup(
6560 afi,
d62a17ae 6561 filter->dlist[direct]
05c7a1cc
QY
6562 .name);
6563 else
6564 filter->dlist[direct].alist =
6565 NULL;
d62a17ae 6566 }
05c7a1cc 6567 }
d62a17ae 6568 }
49e5a4a0 6569#ifdef ENABLE_BGP_VNC
d62a17ae 6570 vnc_prefix_list_update(bgp);
6571#endif
6572 }
6573}
6574
6575/* Set prefix list to the peer. */
6576int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
6577 const char *name)
6578{
70ee29b4 6579 struct peer *member;
d62a17ae 6580 struct bgp_filter *filter;
d62a17ae 6581 struct listnode *node, *nnode;
6582
6583 if (direct != FILTER_IN && direct != FILTER_OUT)
6584 return BGP_ERR_INVALID_VALUE;
6585
70ee29b4 6586 /* Set configuration on peer. */
d62a17ae 6587 filter = &peer->filter[afi][safi];
d62a17ae 6588 if (filter->dlist[direct].name)
6589 return BGP_ERR_PEER_FILTER_CONFLICT;
d62a17ae 6590 if (filter->plist[direct].name)
6591 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
6592 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6593 filter->plist[direct].plist = prefix_list_lookup(afi, name);
6594
70ee29b4 6595 /* Check if handling a regular peer. */
d62a17ae 6596 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
6597 /* Set override-flag and process peer route updates. */
6598 SET_FLAG(peer->filter_override[afi][safi][direct],
6599 PEER_FT_PREFIX_LIST);
d62a17ae 6600 peer_on_policy_change(peer, afi, safi,
6601 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6602
6603 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6604 return 0;
6605 }
6606
70ee29b4
PM
6607 /*
6608 * Set configuration on all peer-group members, unless they are
f75b9163 6609 * explicitly overriding peer-group configuration.
70ee29b4
PM
6610 */
6611 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6612 /* Skip peers with overridden configuration. */
6613 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6614 PEER_FT_PREFIX_LIST))
6615 continue;
d62a17ae 6616
70ee29b4
PM
6617 /* Set configuration on peer-group member. */
6618 filter = &member->filter[afi][safi];
d62a17ae 6619 if (filter->plist[direct].name)
6620 XFREE(MTYPE_BGP_FILTER_NAME,
6621 filter->plist[direct].name);
6622 filter->plist[direct].name =
6623 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6624 filter->plist[direct].plist = prefix_list_lookup(afi, name);
70ee29b4
PM
6625
6626 /* Process peer route updates. */
6627 peer_on_policy_change(member, afi, safi,
d62a17ae 6628 (direct == FILTER_OUT) ? 1 : 0);
6629 }
70ee29b4 6630
d62a17ae 6631 return 0;
6632}
6633
6634int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi,
6635 int direct)
6636{
70ee29b4 6637 struct peer *member;
d62a17ae 6638 struct bgp_filter *filter;
d62a17ae 6639 struct listnode *node, *nnode;
6640
6641 if (direct != FILTER_IN && direct != FILTER_OUT)
6642 return BGP_ERR_INVALID_VALUE;
6643
70ee29b4
PM
6644 /* Unset override-flag unconditionally. */
6645 UNSET_FLAG(peer->filter_override[afi][safi][direct],
6646 PEER_FT_PREFIX_LIST);
d62a17ae 6647
70ee29b4 6648 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 6649 if (peer_group_active(peer)) {
e7103a96
PM
6650 PEER_STR_ATTR_INHERIT(peer, peer->group,
6651 filter[afi][safi].plist[direct].name,
6652 MTYPE_BGP_FILTER_NAME);
6653 PEER_ATTR_INHERIT(peer, peer->group,
6654 filter[afi][safi].plist[direct].plist);
70ee29b4
PM
6655 } else {
6656 /* Otherwise remove configuration from peer. */
6657 filter = &peer->filter[afi][safi];
6658 if (filter->plist[direct].name)
6659 XFREE(MTYPE_BGP_FILTER_NAME,
6660 filter->plist[direct].name);
6661 filter->plist[direct].name = NULL;
6662 filter->plist[direct].plist = NULL;
d62a17ae 6663 }
6664
70ee29b4 6665 /* Check if handling a regular peer. */
d62a17ae 6666 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 6667 /* Process peer route updates. */
d62a17ae 6668 peer_on_policy_change(peer, afi, safi,
6669 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6670
6671 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6672 return 0;
6673 }
6674
70ee29b4
PM
6675 /*
6676 * Remove configuration on all peer-group members, unless they are
f75b9163 6677 * explicitly overriding peer-group configuration.
70ee29b4
PM
6678 */
6679 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6680 /* Skip peers with overridden configuration. */
6681 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6682 PEER_FT_PREFIX_LIST))
6683 continue;
d62a17ae 6684
70ee29b4
PM
6685 /* Remove configuration on peer-group member. */
6686 filter = &member->filter[afi][safi];
d62a17ae 6687 if (filter->plist[direct].name)
6688 XFREE(MTYPE_BGP_FILTER_NAME,
6689 filter->plist[direct].name);
6690 filter->plist[direct].name = NULL;
6691 filter->plist[direct].plist = NULL;
70ee29b4
PM
6692
6693 /* Process peer route updates. */
6694 peer_on_policy_change(member, afi, safi,
d62a17ae 6695 (direct == FILTER_OUT) ? 1 : 0);
6696 }
6697
6698 return 0;
6699}
6700
6701/* Update prefix-list list. */
6702static void peer_prefix_list_update(struct prefix_list *plist)
6703{
6704 struct listnode *mnode, *mnnode;
6705 struct listnode *node, *nnode;
6706 struct bgp *bgp;
6707 struct peer *peer;
6708 struct peer_group *group;
6709 struct bgp_filter *filter;
6710 afi_t afi;
6711 safi_t safi;
6712 int direct;
6713
6714 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
6715
6716 /*
6717 * Update the prefix-list on update groups.
6718 */
6719 update_group_policy_update(
6720 bgp, BGP_POLICY_PREFIX_LIST,
f1aa4929 6721 plist ? prefix_list_name(plist) : NULL, true, 0);
d62a17ae 6722
6723 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
05c7a1cc
QY
6724 FOREACH_AFI_SAFI (afi, safi) {
6725 filter = &peer->filter[afi][safi];
6726
6727 for (direct = FILTER_IN; direct < FILTER_MAX;
6728 direct++) {
6729 if (filter->plist[direct].name)
6730 filter->plist[direct]
6731 .plist = prefix_list_lookup(
6732 afi,
d62a17ae 6733 filter->plist[direct]
05c7a1cc
QY
6734 .name);
6735 else
6736 filter->plist[direct].plist =
6737 NULL;
d62a17ae 6738 }
f1aa4929
DA
6739
6740 /* If we touch prefix-list, we need to process
6741 * new updates. This is important for ORF to
6742 * work correctly as well.
6743 */
6744 if (peer->afc_nego[afi][safi])
6745 peer_on_policy_change(peer, afi, safi,
6746 0);
05c7a1cc 6747 }
d62a17ae 6748 }
6749 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
05c7a1cc
QY
6750 FOREACH_AFI_SAFI (afi, safi) {
6751 filter = &group->conf->filter[afi][safi];
6752
6753 for (direct = FILTER_IN; direct < FILTER_MAX;
6754 direct++) {
6755 if (filter->plist[direct].name)
6756 filter->plist[direct]
6757 .plist = prefix_list_lookup(
6758 afi,
d62a17ae 6759 filter->plist[direct]
05c7a1cc
QY
6760 .name);
6761 else
6762 filter->plist[direct].plist =
6763 NULL;
d62a17ae 6764 }
05c7a1cc 6765 }
d62a17ae 6766 }
6767 }
6768}
6769
6770int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
6771 const char *name)
6772{
70ee29b4 6773 struct peer *member;
d62a17ae 6774 struct bgp_filter *filter;
d62a17ae 6775 struct listnode *node, *nnode;
6776
6777 if (direct != FILTER_IN && direct != FILTER_OUT)
6778 return BGP_ERR_INVALID_VALUE;
6779
70ee29b4 6780 /* Set configuration on peer. */
d62a17ae 6781 filter = &peer->filter[afi][safi];
d62a17ae 6782 if (filter->aslist[direct].name)
6783 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
6784 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6785 filter->aslist[direct].aslist = as_list_lookup(name);
6786
70ee29b4 6787 /* Check if handling a regular peer. */
d62a17ae 6788 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
6789 /* Set override-flag and process peer route updates. */
6790 SET_FLAG(peer->filter_override[afi][safi][direct],
6791 PEER_FT_FILTER_LIST);
d62a17ae 6792 peer_on_policy_change(peer, afi, safi,
6793 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6794
6795 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6796 return 0;
6797 }
6798
70ee29b4
PM
6799 /*
6800 * Set configuration on all peer-group members, unless they are
f75b9163 6801 * explicitly overriding peer-group configuration.
70ee29b4
PM
6802 */
6803 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6804 /* Skip peers with overridden configuration. */
6805 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6806 PEER_FT_FILTER_LIST))
6807 continue;
d62a17ae 6808
70ee29b4
PM
6809 /* Set configuration on peer-group member. */
6810 filter = &member->filter[afi][safi];
d62a17ae 6811 if (filter->aslist[direct].name)
6812 XFREE(MTYPE_BGP_FILTER_NAME,
6813 filter->aslist[direct].name);
6814 filter->aslist[direct].name =
6815 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6816 filter->aslist[direct].aslist = as_list_lookup(name);
70ee29b4
PM
6817
6818 /* Process peer route updates. */
6819 peer_on_policy_change(member, afi, safi,
d62a17ae 6820 (direct == FILTER_OUT) ? 1 : 0);
6821 }
70ee29b4 6822
d62a17ae 6823 return 0;
6824}
6825
6826int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
6827{
70ee29b4 6828 struct peer *member;
d62a17ae 6829 struct bgp_filter *filter;
d62a17ae 6830 struct listnode *node, *nnode;
6831
6832 if (direct != FILTER_IN && direct != FILTER_OUT)
6833 return BGP_ERR_INVALID_VALUE;
6834
70ee29b4
PM
6835 /* Unset override-flag unconditionally. */
6836 UNSET_FLAG(peer->filter_override[afi][safi][direct],
6837 PEER_FT_FILTER_LIST);
d62a17ae 6838
70ee29b4 6839 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 6840 if (peer_group_active(peer)) {
e7103a96
PM
6841 PEER_STR_ATTR_INHERIT(peer, peer->group,
6842 filter[afi][safi].aslist[direct].name,
6843 MTYPE_BGP_FILTER_NAME);
6844 PEER_ATTR_INHERIT(peer, peer->group,
70ee29b4
PM
6845 filter[afi][safi].aslist[direct].aslist);
6846 } else {
6847 /* Otherwise remove configuration from peer. */
6848 filter = &peer->filter[afi][safi];
6849 if (filter->aslist[direct].name)
6850 XFREE(MTYPE_BGP_FILTER_NAME,
6851 filter->aslist[direct].name);
6852 filter->aslist[direct].name = NULL;
6853 filter->aslist[direct].aslist = NULL;
d62a17ae 6854 }
6855
70ee29b4 6856 /* Check if handling a regular peer. */
d62a17ae 6857 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 6858 /* Process peer route updates. */
d62a17ae 6859 peer_on_policy_change(peer, afi, safi,
6860 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6861
6862 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6863 return 0;
6864 }
6865
70ee29b4
PM
6866 /*
6867 * Remove configuration on all peer-group members, unless they are
f75b9163 6868 * explicitly overriding peer-group configuration.
70ee29b4
PM
6869 */
6870 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6871 /* Skip peers with overridden configuration. */
6872 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6873 PEER_FT_FILTER_LIST))
6874 continue;
d62a17ae 6875
70ee29b4
PM
6876 /* Remove configuration on peer-group member. */
6877 filter = &member->filter[afi][safi];
d62a17ae 6878 if (filter->aslist[direct].name)
6879 XFREE(MTYPE_BGP_FILTER_NAME,
6880 filter->aslist[direct].name);
6881 filter->aslist[direct].name = NULL;
6882 filter->aslist[direct].aslist = NULL;
70ee29b4
PM
6883
6884 /* Process peer route updates. */
6885 peer_on_policy_change(member, afi, safi,
d62a17ae 6886 (direct == FILTER_OUT) ? 1 : 0);
6887 }
6888
6889 return 0;
6890}
6891
6892static void peer_aslist_update(const char *aslist_name)
6893{
6894 afi_t afi;
6895 safi_t safi;
6896 int direct;
6897 struct listnode *mnode, *mnnode;
6898 struct listnode *node, *nnode;
6899 struct bgp *bgp;
6900 struct peer *peer;
6901 struct peer_group *group;
6902 struct bgp_filter *filter;
6903
6904 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
6905 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
f1aa4929 6906 aslist_name, true, 0);
d62a17ae 6907
6908 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
05c7a1cc
QY
6909 FOREACH_AFI_SAFI (afi, safi) {
6910 filter = &peer->filter[afi][safi];
6911
6912 for (direct = FILTER_IN; direct < FILTER_MAX;
6913 direct++) {
6914 if (filter->aslist[direct].name)
6915 filter->aslist[direct]
6916 .aslist = as_list_lookup(
d62a17ae 6917 filter->aslist[direct]
05c7a1cc
QY
6918 .name);
6919 else
6920 filter->aslist[direct].aslist =
6921 NULL;
d62a17ae 6922 }
05c7a1cc 6923 }
d62a17ae 6924 }
6925 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
05c7a1cc
QY
6926 FOREACH_AFI_SAFI (afi, safi) {
6927 filter = &group->conf->filter[afi][safi];
6928
6929 for (direct = FILTER_IN; direct < FILTER_MAX;
6930 direct++) {
6931 if (filter->aslist[direct].name)
6932 filter->aslist[direct]
6933 .aslist = as_list_lookup(
d62a17ae 6934 filter->aslist[direct]
05c7a1cc
QY
6935 .name);
6936 else
6937 filter->aslist[direct].aslist =
6938 NULL;
d62a17ae 6939 }
05c7a1cc 6940 }
d62a17ae 6941 }
6942 }
6943}
6944
6945static void peer_aslist_add(char *aslist_name)
6946{
6947 peer_aslist_update(aslist_name);
c4efd0f4 6948 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_ADDED);
d62a17ae 6949}
6950
6951static void peer_aslist_del(const char *aslist_name)
6952{
6953 peer_aslist_update(aslist_name);
6954 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
6955}
6956
6957
6958int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
1de27621 6959 const char *name, struct route_map *route_map)
d62a17ae 6960{
70ee29b4 6961 struct peer *member;
d62a17ae 6962 struct bgp_filter *filter;
d62a17ae 6963 struct listnode *node, *nnode;
6964
6965 if (direct != RMAP_IN && direct != RMAP_OUT)
6966 return BGP_ERR_INVALID_VALUE;
6967
70ee29b4 6968 /* Set configuration on peer. */
d62a17ae 6969 filter = &peer->filter[afi][safi];
6c3247bd
NT
6970 if (filter->map[direct].name) {
6971 /* If the neighbor is configured with the same route-map
6972 * again then, ignore the duplicate configuration.
6973 */
6974 if (strcmp(filter->map[direct].name, name) == 0)
6975 return 0;
6976
d62a17ae 6977 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
6c3247bd 6978 }
b4897fa5 6979 route_map_counter_decrement(filter->map[direct].map);
d62a17ae 6980 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 6981 filter->map[direct].map = route_map;
b4897fa5 6982 route_map_counter_increment(route_map);
d62a17ae 6983
70ee29b4 6984 /* Check if handling a regular peer. */
d62a17ae 6985 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
6986 /* Set override-flag and process peer route updates. */
6987 SET_FLAG(peer->filter_override[afi][safi][direct],
6988 PEER_FT_ROUTE_MAP);
d62a17ae 6989 peer_on_policy_change(peer, afi, safi,
6990 (direct == RMAP_OUT) ? 1 : 0);
70ee29b4
PM
6991
6992 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6993 return 0;
6994 }
6995
70ee29b4
PM
6996 /*
6997 * Set configuration on all peer-group members, unless they are
f75b9163 6998 * explicitly overriding peer-group configuration.
70ee29b4
PM
6999 */
7000 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7001 /* Skip peers with overridden configuration. */
7002 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
7003 PEER_FT_ROUTE_MAP))
7004 continue;
d62a17ae 7005
70ee29b4
PM
7006 /* Set configuration on peer-group member. */
7007 filter = &member->filter[afi][safi];
d62a17ae 7008 if (filter->map[direct].name)
7009 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
b4897fa5 7010 route_map_counter_decrement(filter->map[direct].map);
d62a17ae 7011 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 7012 filter->map[direct].map = route_map;
b4897fa5 7013 route_map_counter_increment(route_map);
70ee29b4
PM
7014
7015 /* Process peer route updates. */
7016 peer_on_policy_change(member, afi, safi,
d62a17ae 7017 (direct == RMAP_OUT) ? 1 : 0);
7018 }
7019 return 0;
7020}
7021
7022/* Unset route-map from the peer. */
7023int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
7024{
70ee29b4 7025 struct peer *member;
d62a17ae 7026 struct bgp_filter *filter;
d62a17ae 7027 struct listnode *node, *nnode;
7028
7029 if (direct != RMAP_IN && direct != RMAP_OUT)
7030 return BGP_ERR_INVALID_VALUE;
7031
70ee29b4
PM
7032 /* Unset override-flag unconditionally. */
7033 UNSET_FLAG(peer->filter_override[afi][safi][direct], PEER_FT_ROUTE_MAP);
d62a17ae 7034
70ee29b4 7035 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 7036 if (peer_group_active(peer)) {
e7103a96
PM
7037 PEER_STR_ATTR_INHERIT(peer, peer->group,
7038 filter[afi][safi].map[direct].name,
7039 MTYPE_BGP_FILTER_NAME);
7040 PEER_ATTR_INHERIT(peer, peer->group,
7041 filter[afi][safi].map[direct].map);
70ee29b4
PM
7042 } else {
7043 /* Otherwise remove configuration from peer. */
7044 filter = &peer->filter[afi][safi];
7045 if (filter->map[direct].name)
7046 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
b4897fa5 7047 route_map_counter_decrement(filter->map[direct].map);
70ee29b4
PM
7048 filter->map[direct].name = NULL;
7049 filter->map[direct].map = NULL;
d62a17ae 7050 }
7051
70ee29b4 7052 /* Check if handling a regular peer. */
d62a17ae 7053 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 7054 /* Process peer route updates. */
d62a17ae 7055 peer_on_policy_change(peer, afi, safi,
7056 (direct == RMAP_OUT) ? 1 : 0);
70ee29b4
PM
7057
7058 /* Skip peer-group mechanics for regular peers. */
d62a17ae 7059 return 0;
7060 }
7061
70ee29b4
PM
7062 /*
7063 * Remove configuration on all peer-group members, unless they are
f75b9163 7064 * explicitly overriding peer-group configuration.
70ee29b4
PM
7065 */
7066 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7067 /* Skip peers with overridden configuration. */
7068 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
7069 PEER_FT_ROUTE_MAP))
7070 continue;
d62a17ae 7071
70ee29b4
PM
7072 /* Remove configuration on peer-group member. */
7073 filter = &member->filter[afi][safi];
d62a17ae 7074 if (filter->map[direct].name)
7075 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
b4897fa5 7076 route_map_counter_decrement(filter->map[direct].map);
d62a17ae 7077 filter->map[direct].name = NULL;
7078 filter->map[direct].map = NULL;
70ee29b4
PM
7079
7080 /* Process peer route updates. */
7081 peer_on_policy_change(member, afi, safi,
d62a17ae 7082 (direct == RMAP_OUT) ? 1 : 0);
7083 }
70ee29b4 7084
d62a17ae 7085 return 0;
7086}
7087
7088/* Set unsuppress-map to the peer. */
7089int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
1de27621 7090 const char *name, struct route_map *route_map)
d62a17ae 7091{
70ee29b4 7092 struct peer *member;
d62a17ae 7093 struct bgp_filter *filter;
d62a17ae 7094 struct listnode *node, *nnode;
7095
70ee29b4 7096 /* Set configuration on peer. */
d62a17ae 7097 filter = &peer->filter[afi][safi];
d62a17ae 7098 if (filter->usmap.name)
7099 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 7100 route_map_counter_decrement(filter->usmap.map);
d62a17ae 7101 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 7102 filter->usmap.map = route_map;
b4897fa5 7103 route_map_counter_increment(route_map);
d62a17ae 7104
70ee29b4 7105 /* Check if handling a regular peer. */
d62a17ae 7106 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
7107 /* Set override-flag and process peer route updates. */
7108 SET_FLAG(peer->filter_override[afi][safi][0],
7109 PEER_FT_UNSUPPRESS_MAP);
d62a17ae 7110 peer_on_policy_change(peer, afi, safi, 1);
70ee29b4
PM
7111
7112 /* Skip peer-group mechanics for regular peers. */
d62a17ae 7113 return 0;
7114 }
7115
70ee29b4
PM
7116 /*
7117 * Set configuration on all peer-group members, unless they are
f75b9163 7118 * explicitly overriding peer-group configuration.
70ee29b4
PM
7119 */
7120 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7121 /* Skip peers with overridden configuration. */
246bb5f0 7122 if (CHECK_FLAG(member->filter_override[afi][safi][0],
70ee29b4
PM
7123 PEER_FT_UNSUPPRESS_MAP))
7124 continue;
d62a17ae 7125
70ee29b4
PM
7126 /* Set configuration on peer-group member. */
7127 filter = &member->filter[afi][safi];
d62a17ae 7128 if (filter->usmap.name)
7129 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 7130 route_map_counter_decrement(filter->usmap.map);
d62a17ae 7131 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 7132 filter->usmap.map = route_map;
b4897fa5 7133 route_map_counter_increment(route_map);
70ee29b4
PM
7134
7135 /* Process peer route updates. */
7136 peer_on_policy_change(member, afi, safi, 1);
d62a17ae 7137 }
70ee29b4 7138
d62a17ae 7139 return 0;
7140}
7141
7142/* Unset route-map from the peer. */
7143int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
718e3744 7144{
70ee29b4 7145 struct peer *member;
d62a17ae 7146 struct bgp_filter *filter;
d62a17ae 7147 struct listnode *node, *nnode;
7148
70ee29b4
PM
7149 /* Unset override-flag unconditionally. */
7150 UNSET_FLAG(peer->filter_override[afi][safi][0], PEER_FT_UNSUPPRESS_MAP);
718e3744 7151
70ee29b4
PM
7152 /* Inherit configuration from peer-group if peer is member. */
7153 if (peer_group_active(peer)) {
e7103a96
PM
7154 PEER_STR_ATTR_INHERIT(peer, peer->group,
7155 filter[afi][safi].usmap.name,
7156 MTYPE_BGP_FILTER_NAME);
7157 PEER_ATTR_INHERIT(peer, peer->group,
7158 filter[afi][safi].usmap.map);
70ee29b4
PM
7159 } else {
7160 /* Otherwise remove configuration from peer. */
7161 filter = &peer->filter[afi][safi];
7162 if (filter->usmap.name)
7163 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 7164 route_map_counter_decrement(filter->usmap.map);
70ee29b4
PM
7165 filter->usmap.name = NULL;
7166 filter->usmap.map = NULL;
7167 }
718e3744 7168
70ee29b4 7169 /* Check if handling a regular peer. */
d62a17ae 7170 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 7171 /* Process peer route updates. */
d62a17ae 7172 peer_on_policy_change(peer, afi, safi, 1);
70ee29b4
PM
7173
7174 /* Skip peer-group mechanics for regular peers. */
d62a17ae 7175 return 0;
7176 }
718e3744 7177
70ee29b4
PM
7178 /*
7179 * Remove configuration on all peer-group members, unless they are
f75b9163 7180 * explicitly overriding peer-group configuration.
70ee29b4
PM
7181 */
7182 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7183 /* Skip peers with overridden configuration. */
7184 if (CHECK_FLAG(member->filter_override[afi][safi][0],
7185 PEER_FT_UNSUPPRESS_MAP))
7186 continue;
718e3744 7187
70ee29b4
PM
7188 /* Remove configuration on peer-group member. */
7189 filter = &member->filter[afi][safi];
d62a17ae 7190 if (filter->usmap.name)
7191 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 7192 route_map_counter_decrement(filter->usmap.map);
d62a17ae 7193 filter->usmap.name = NULL;
7194 filter->usmap.map = NULL;
70ee29b4
PM
7195
7196 /* Process peer route updates. */
7197 peer_on_policy_change(member, afi, safi, 1);
d62a17ae 7198 }
70ee29b4 7199
d62a17ae 7200 return 0;
7201}
718e3744 7202
fa36596c
MK
7203static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
7204 safi_t safi, const char *amap_name,
7205 struct route_map *amap,
7206 const char *cmap_name,
7207 struct route_map *cmap,
7208 bool condition, bool set)
cf2ad4d8
MK
7209{
7210 struct bgp_filter *filter;
7211 bool filter_exists = false;
7212
7213 filter = &peer->filter[afi][safi];
7214
fa36596c
MK
7215 /* advertise-map is already configured. */
7216 if (filter->advmap.aname) {
7217 filter_exists = true;
7218 XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
7219 XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
7220 }
cf2ad4d8 7221
fa36596c 7222 route_map_counter_decrement(filter->advmap.amap);
cf2ad4d8 7223
fa36596c
MK
7224 /* Removed advertise-map configuration */
7225 if (!set) {
5b083e4e 7226 memset(&filter->advmap, 0, sizeof(filter->advmap));
cf2ad4d8 7227
fa36596c
MK
7228 /* decrement condition_filter_count delete timer if
7229 * this is the last advertise-map to be removed.
7230 */
7231 if (filter_exists)
7232 bgp_conditional_adv_disable(peer, afi, safi);
cf2ad4d8 7233
fa36596c
MK
7234 return;
7235 }
7236
7237 /* Update filter data with newly configured values. */
7238 filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
7239 filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
7240 filter->advmap.amap = amap;
7241 filter->advmap.cmap = cmap;
7242 filter->advmap.condition = condition;
7243 route_map_counter_increment(filter->advmap.amap);
7244 peer->advmap_config_change[afi][safi] = true;
7245
7246 /* Increment condition_filter_count and/or create timer. */
7247 if (!filter_exists) {
ecf2b628 7248 filter->advmap.update_type = UPDATE_TYPE_ADVERTISE;
fa36596c 7249 bgp_conditional_adv_enable(peer, afi, safi);
cf2ad4d8 7250 }
06bb44c8
DA
7251
7252 /* Process peer route updates. */
7253 peer_on_policy_change(peer, afi, safi, 1);
cf2ad4d8
MK
7254}
7255
06bb44c8 7256/* Set advertise-map to the peer. */
7f7940e6
MK
7257int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
7258 const char *advertise_name,
cf2ad4d8 7259 struct route_map *advertise_map,
7f7940e6 7260 const char *condition_name,
cf2ad4d8 7261 struct route_map *condition_map, bool condition)
7f7940e6 7262{
7f7940e6 7263 struct peer *member;
7f7940e6
MK
7264 struct listnode *node, *nnode;
7265
cf2ad4d8 7266 /* Set configuration on peer. */
fa36596c
MK
7267 peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
7268 advertise_map, condition_name,
7269 condition_map, condition, true);
7f7940e6 7270
cf2ad4d8 7271 /* Check if handling a regular peer & Skip peer-group mechanics. */
7f7940e6
MK
7272 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7273 /* Set override-flag and process peer route updates. */
7274 SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
7275 PEER_FT_ADVERTISE_MAP);
7f7940e6
MK
7276 return 0;
7277 }
7278
7279 /*
7280 * Set configuration on all peer-group members, unless they are
f75b9163 7281 * explicitly overriding peer-group configuration.
7f7940e6
MK
7282 */
7283 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7284 /* Skip peers with overridden configuration. */
7285 if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
7286 PEER_FT_ADVERTISE_MAP))
7287 continue;
7288
7289 /* Set configuration on peer-group member. */
fa36596c
MK
7290 peer_advertise_map_filter_update(
7291 member, afi, safi, advertise_name, advertise_map,
7292 condition_name, condition_map, condition, true);
7f7940e6
MK
7293 }
7294
7295 return 0;
7296}
7297
7298/* Unset advertise-map from the peer. */
7299int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
7300 const char *advertise_name,
cf2ad4d8 7301 struct route_map *advertise_map,
7f7940e6 7302 const char *condition_name,
cf2ad4d8 7303 struct route_map *condition_map, bool condition)
7f7940e6 7304{
7f7940e6 7305 struct peer *member;
7f7940e6
MK
7306 struct listnode *node, *nnode;
7307
fa36596c
MK
7308 /* advertise-map is not configured */
7309 if (!peer->filter[afi][safi].advmap.aname)
7310 return 0;
cf2ad4d8 7311
7f7940e6
MK
7312 /* Unset override-flag unconditionally. */
7313 UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
7314 PEER_FT_ADVERTISE_MAP);
7315
7316 /* Inherit configuration from peer-group if peer is member. */
7317 if (peer_group_active(peer)) {
7318 PEER_STR_ATTR_INHERIT(peer, peer->group,
7319 filter[afi][safi].advmap.aname,
7320 MTYPE_BGP_FILTER_NAME);
7321 PEER_ATTR_INHERIT(peer, peer->group,
7322 filter[afi][safi].advmap.amap);
cf2ad4d8 7323 } else
fa36596c
MK
7324 peer_advertise_map_filter_update(
7325 peer, afi, safi, advertise_name, advertise_map,
7326 condition_name, condition_map, condition, false);
7f7940e6 7327
cf2ad4d8 7328 /* Check if handling a regular peer and skip peer-group mechanics. */
7f7940e6
MK
7329 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7330 /* Process peer route updates. */
e73c112e
MK
7331 if (BGP_DEBUG(update, UPDATE_OUT))
7332 zlog_debug("%s: Send normal update to %s for %s",
7333 __func__, peer->host,
7334 get_afi_safi_str(afi, safi, false));
7335
7f7940e6
MK
7336 return 0;
7337 }
7338
7339 /*
7340 * Remove configuration on all peer-group members, unless they are
f75b9163 7341 * explicitly overriding peer-group configuration.
7f7940e6
MK
7342 */
7343 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7344 /* Skip peers with overridden configuration. */
7345 if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
7346 PEER_FT_ADVERTISE_MAP))
7347 continue;
7f7940e6 7348 /* Remove configuration on peer-group member. */
fa36596c
MK
7349 peer_advertise_map_filter_update(
7350 member, afi, safi, advertise_name, advertise_map,
7351 condition_name, condition_map, condition, false);
7f7940e6
MK
7352
7353 /* Process peer route updates. */
e73c112e
MK
7354 if (BGP_DEBUG(update, UPDATE_OUT))
7355 zlog_debug("%s: Send normal update to %s for %s ",
7356 __func__, member->host,
7357 get_afi_safi_str(afi, safi, false));
7f7940e6
MK
7358 }
7359
7360 return 0;
7361}
7362
ac4522e6
DM
7363static bool peer_maximum_prefix_clear_overflow(struct peer *peer)
7364{
7365 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
7366 return false;
7367
7368 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
7369 if (peer->t_pmax_restart) {
fa5806c3 7370 THREAD_OFF(peer->t_pmax_restart);
ac4522e6 7371 if (bgp_debug_neighbor_events(peer))
a7d91a8c 7372 zlog_debug(
f70c91dc
DA
7373 "%pBP Maximum-prefix restart timer cancelled",
7374 peer);
ac4522e6
DM
7375 }
7376 BGP_EVENT_ADD(peer, BGP_Start);
7377 return true;
7378}
7379
d62a17ae 7380int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
d7c0a89a 7381 uint32_t max, uint8_t threshold, int warning,
9cbd06e0 7382 uint16_t restart, bool force)
d62a17ae 7383{
598ce6bd 7384 struct peer *member;
d62a17ae 7385 struct listnode *node, *nnode;
7386
598ce6bd
PM
7387 /* Set flags and configuration on peer. */
7388 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
9cbd06e0
DA
7389
7390 if (force)
7391 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_FORCE);
7392 else
7393 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_FORCE);
7394
d62a17ae 7395 if (warning)
598ce6bd 7396 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
d62a17ae 7397 else
598ce6bd
PM
7398 peer_af_flag_unset(peer, afi, safi,
7399 PEER_FLAG_MAX_PREFIX_WARNING);
7400
04e1c5bb
QY
7401 peer->pmax[afi][safi] = max;
7402 peer->pmax_threshold[afi][safi] = threshold;
7403 peer->pmax_restart[afi][safi] = restart;
d62a17ae 7404
598ce6bd
PM
7405 /* Check if handling a regular peer. */
7406 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7407 /* Re-check if peer violates maximum-prefix. */
feb17238 7408 if ((peer_established(peer)) && (peer->afc[afi][safi]))
d62a17ae 7409 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
04e1c5bb 7410
598ce6bd
PM
7411 /* Skip peer-group mechanics for regular peers. */
7412 return 0;
7413 }
04e1c5bb 7414
598ce6bd
PM
7415 /*
7416 * Set flags and configuration on all peer-group members, unless they
f75b9163 7417 * are explicitly overriding peer-group configuration.
598ce6bd
PM
7418 */
7419 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7420 /* Skip peers with overridden configuration. */
7421 if (CHECK_FLAG(member->af_flags_override[afi][safi],
7422 PEER_FLAG_MAX_PREFIX))
7423 continue;
04e1c5bb 7424
598ce6bd
PM
7425 /* Set flag and configuration on peer-group member. */
7426 member->pmax[afi][safi] = max;
7427 member->pmax_threshold[afi][safi] = threshold;
7428 member->pmax_restart[afi][safi] = restart;
9cbd06e0
DA
7429
7430 if (force)
7431 SET_FLAG(member->af_flags[afi][safi],
7432 PEER_FLAG_MAX_PREFIX_FORCE);
7433 else
7434 UNSET_FLAG(member->af_flags[afi][safi],
7435 PEER_FLAG_MAX_PREFIX_FORCE);
7436
04e1c5bb 7437 if (warning)
598ce6bd 7438 SET_FLAG(member->af_flags[afi][safi],
04e1c5bb
QY
7439 PEER_FLAG_MAX_PREFIX_WARNING);
7440 else
598ce6bd 7441 UNSET_FLAG(member->af_flags[afi][safi],
04e1c5bb 7442 PEER_FLAG_MAX_PREFIX_WARNING);
598ce6bd
PM
7443
7444 /* Re-check if peer violates maximum-prefix. */
feb17238 7445 if ((peer_established(member)) && (member->afc[afi][safi]))
598ce6bd 7446 bgp_maximum_prefix_overflow(member, afi, safi, 1);
d62a17ae 7447 }
718e3744 7448
d62a17ae 7449 return 0;
7450}
718e3744 7451
d62a17ae 7452int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
7453{
598ce6bd
PM
7454 /* Inherit configuration from peer-group if peer is member. */
7455 if (peer_group_active(peer)) {
7456 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
9cbd06e0
DA
7457 peer_af_flag_inherit(peer, afi, safi,
7458 PEER_FLAG_MAX_PREFIX_FORCE);
598ce6bd
PM
7459 peer_af_flag_inherit(peer, afi, safi,
7460 PEER_FLAG_MAX_PREFIX_WARNING);
e7103a96
PM
7461 PEER_ATTR_INHERIT(peer, peer->group, pmax[afi][safi]);
7462 PEER_ATTR_INHERIT(peer, peer->group, pmax_threshold[afi][safi]);
7463 PEER_ATTR_INHERIT(peer, peer->group, pmax_restart[afi][safi]);
04e1c5bb 7464
d62a17ae 7465 return 0;
04e1c5bb 7466 }
d62a17ae 7467
598ce6bd
PM
7468 /* Remove flags and configuration from peer. */
7469 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
9cbd06e0 7470 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_FORCE);
598ce6bd
PM
7471 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
7472 peer->pmax[afi][safi] = 0;
7473 peer->pmax_threshold[afi][safi] = 0;
7474 peer->pmax_restart[afi][safi] = 0;
7475
04e1c5bb 7476 /*
598ce6bd 7477 * Remove flags and configuration from all peer-group members, unless
f75b9163 7478 * they are explicitly overriding peer-group configuration.
04e1c5bb 7479 */
6282637d
RW
7480 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7481 struct peer *member;
7482 struct listnode *node;
598ce6bd 7483
6282637d
RW
7484 for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
7485 /* Skip peers with overridden configuration. */
7486 if (CHECK_FLAG(member->af_flags_override[afi][safi],
7487 PEER_FLAG_MAX_PREFIX))
7488 continue;
7489
7490 /* Remove flag and configuration on peer-group member.
7491 */
7492 UNSET_FLAG(member->af_flags[afi][safi],
7493 PEER_FLAG_MAX_PREFIX);
9cbd06e0
DA
7494 UNSET_FLAG(member->af_flags[afi][safi],
7495 PEER_FLAG_MAX_PREFIX_FORCE);
6282637d
RW
7496 UNSET_FLAG(member->af_flags[afi][safi],
7497 PEER_FLAG_MAX_PREFIX_WARNING);
7498 member->pmax[afi][safi] = 0;
7499 member->pmax_threshold[afi][safi] = 0;
7500 member->pmax_restart[afi][safi] = 0;
ac4522e6
DM
7501
7502 peer_maximum_prefix_clear_overflow(member);
6282637d 7503 }
ac4522e6
DM
7504 } else {
7505 peer_maximum_prefix_clear_overflow(peer);
d62a17ae 7506 }
598ce6bd 7507
d62a17ae 7508 return 0;
718e3744 7509}
7510
d0bf49ec
LS
7511void peer_maximum_prefix_out_refresh_routes(struct peer *peer, afi_t afi,
7512 safi_t safi)
7513{
7514 update_group_adjust_peer(peer_af_find(peer, afi, safi));
7515
7516 if (peer_established(peer))
7517 bgp_announce_route(peer, afi, safi, false);
7518}
7519
80444d30
LS
7520int peer_maximum_prefix_out_set(struct peer *peer, afi_t afi, safi_t safi,
7521 uint32_t max)
7522{
7523 struct peer *member;
7524 struct listnode *node, *nnode;
7525
7526 /* Set flag on peer and peer-group member if any */
7527 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT);
7528 /* Set configuration on peer. */
7529 peer->pmax_out[afi][safi] = max;
7530
7531 /* Check if handling a regular peer. */
7532 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7533 /* Skip peer-group mechanics for regular peers. */
7534 peer_maximum_prefix_out_refresh_routes(peer, afi, safi);
7535 return 0;
7536 }
7537
7538 /*
7539 * Set flag and configuration on all peer-group members, unless they
f75b9163 7540 * are explicitly overriding peer-group configuration.
80444d30
LS
7541 */
7542 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
7543 /* Skip peers with overridden configuration. */
7544 if (CHECK_FLAG(member->af_flags_override[afi][safi],
7545 PEER_FLAG_MAX_PREFIX_OUT))
7546 continue;
7547
7548 /* Set configuration on peer-group member. */
7549 member->pmax_out[afi][safi] = max;
7550
7551 peer_maximum_prefix_out_refresh_routes(member, afi, safi);
7552 }
7553 return 0;
7554}
7555
7556int peer_maximum_prefix_out_unset(struct peer *peer, afi_t afi, safi_t safi)
7557{
7558 struct peer *member;
7559 struct listnode *node;
7560 /* Inherit configuration from peer-group if peer is member. */
7561 if (peer_group_active(peer)) {
7562 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT);
7563 PEER_ATTR_INHERIT(peer, peer->group, pmax_out[afi][safi]);
7564
7565 peer_maximum_prefix_out_refresh_routes(peer, afi, safi);
7566 return 0;
7567 }
7568
7569 /* Remove flag and configuration from peer. */
7570 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT);
7571 peer->pmax_out[afi][safi] = 0;
7572
7573 /* Check if handling a regular peer. */
7574 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7575 /* Skip peer-group mechanics for regular peers. */
7576 peer_maximum_prefix_out_refresh_routes(peer, afi, safi);
7577 return 0;
7578 }
7579
7580 /*
7581 * Remove flag and configuration from all peer-group members, unless
f75b9163 7582 * they are explicitly overriding peer-group configuration.
80444d30
LS
7583 */
7584 for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
7585 /* Skip peers with overridden configuration. */
7586 if (CHECK_FLAG(member->af_flags_override[afi][safi],
7587 PEER_FLAG_MAX_PREFIX_OUT))
7588 continue;
7589
7590 /* Remove flag and configuration on peer-group member.
7591 */
7592 UNSET_FLAG(member->af_flags[afi][safi],
7593 PEER_FLAG_MAX_PREFIX_OUT);
7594 member->pmax_out[afi][safi] = 0;
7595
7596 peer_maximum_prefix_out_refresh_routes(member, afi, safi);
7597 }
7598 return 0;
7599}
7600
d62a17ae 7601int is_ebgp_multihop_configured(struct peer *peer)
718e3744 7602{
d62a17ae 7603 struct peer_group *group;
7604 struct listnode *node, *nnode;
7605 struct peer *peer1;
718e3744 7606
d62a17ae 7607 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7608 group = peer->group;
7609 if ((peer_sort(peer) != BGP_PEER_IBGP)
c8d6f0d6 7610 && (group->conf->ttl != BGP_DEFAULT_TTL))
d62a17ae 7611 return 1;
718e3744 7612
d62a17ae 7613 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) {
7614 if ((peer_sort(peer1) != BGP_PEER_IBGP)
c8d6f0d6 7615 && (peer1->ttl != BGP_DEFAULT_TTL))
d62a17ae 7616 return 1;
7617 }
7618 } else {
c8d6f0d6
DA
7619 if ((peer_sort(peer) != BGP_PEER_IBGP)
7620 && (peer->ttl != BGP_DEFAULT_TTL))
d62a17ae 7621 return 1;
7622 }
7623 return 0;
7624}
718e3744 7625
d62a17ae 7626/* Set # of hops between us and BGP peer. */
7627int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
7628{
7629 struct peer_group *group;
4ec7a71a 7630 struct peer *gpeer;
d62a17ae 7631 struct listnode *node, *nnode;
7632 int ret;
7633
84c320dc
DA
7634 zlog_debug("%s: set gtsm_hops to %d for %s", __func__, gtsm_hops,
7635 peer->host);
d62a17ae 7636
7637 /* We cannot configure ttl-security hops when ebgp-multihop is already
7638 set. For non peer-groups, the check is simple. For peer-groups,
7639 it's
7640 slightly messy, because we need to check both the peer-group
7641 structure
7642 and all peer-group members for any trace of ebgp-multihop
7643 configuration
7644 before actually applying the ttl-security rules. Cisco really made a
7645 mess of this configuration parameter, and OpenBGPD got it right.
7646 */
7647
e2521429
DA
7648 if ((peer->gtsm_hops == BGP_GTSM_HOPS_DISABLED)
7649 && (peer->sort != BGP_PEER_IBGP)) {
d62a17ae 7650 if (is_ebgp_multihop_configured(peer))
7651 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
7652
7653 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7654 peer->gtsm_hops = gtsm_hops;
7655
7656 /* Calling ebgp multihop also resets the session.
7657 * On restart, NHT will get setup correctly as will the
7658 * min & max ttls on the socket. The return value is
7659 * irrelevant.
7660 */
7661 ret = peer_ebgp_multihop_set(peer, MAXTTL);
7662
7663 if (ret != 0)
7664 return ret;
7665 } else {
7666 group = peer->group;
4ec7a71a 7667 group->conf->gtsm_hops = gtsm_hops;
d62a17ae 7668 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
4ec7a71a
DS
7669 gpeer)) {
7670 gpeer->gtsm_hops = group->conf->gtsm_hops;
d62a17ae 7671
7672 /* Calling ebgp multihop also resets the
7673 * session.
7674 * On restart, NHT will get setup correctly as
7675 * will the
7676 * min & max ttls on the socket. The return
7677 * value is
7678 * irrelevant.
7679 */
4ec7a71a 7680 peer_ebgp_multihop_set(gpeer, MAXTTL);
d62a17ae 7681 }
7682 }
7683 } else {
7684 /* Post the first gtsm setup or if its ibgp, maxttl setting
7685 * isn't
7686 * necessary, just set the minttl.
7687 */
7688 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7689 peer->gtsm_hops = gtsm_hops;
7690
7691 if (peer->fd >= 0)
7692 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
7693 MAXTTL + 1 - gtsm_hops);
7694 if ((peer->status < Established) && peer->doppelganger
7695 && (peer->doppelganger->fd >= 0))
7696 sockopt_minttl(peer->su.sa.sa_family,
7697 peer->doppelganger->fd,
7698 MAXTTL + 1 - gtsm_hops);
7699 } else {
7700 group = peer->group;
4ec7a71a 7701 group->conf->gtsm_hops = gtsm_hops;
d62a17ae 7702 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
4ec7a71a
DS
7703 gpeer)) {
7704 gpeer->gtsm_hops = group->conf->gtsm_hops;
d62a17ae 7705
7706 /* Change setting of existing peer
7707 * established then change value (may break
7708 * connectivity)
7709 * not established yet (teardown session and
7710 * restart)
7711 * no session then do nothing (will get
7712 * handled by next connection)
7713 */
4ec7a71a
DS
7714 if (gpeer->fd >= 0
7715 && gpeer->gtsm_hops
e2521429 7716 != BGP_GTSM_HOPS_DISABLED)
d62a17ae 7717 sockopt_minttl(
4ec7a71a
DS
7718 gpeer->su.sa.sa_family,
7719 gpeer->fd,
7720 MAXTTL + 1 - gpeer->gtsm_hops);
7721 if ((gpeer->status < Established)
7722 && gpeer->doppelganger
7723 && (gpeer->doppelganger->fd >= 0))
7724 sockopt_minttl(gpeer->su.sa.sa_family,
7725 gpeer->doppelganger->fd,
d62a17ae 7726 MAXTTL + 1 - gtsm_hops);
7727 }
7728 }
7729 }
718e3744 7730
d62a17ae 7731 return 0;
718e3744 7732}
7733
d62a17ae 7734int peer_ttl_security_hops_unset(struct peer *peer)
7735{
7736 struct peer_group *group;
7737 struct listnode *node, *nnode;
7738 int ret = 0;
7739
84c320dc 7740 zlog_debug("%s: set gtsm_hops to zero for %s", __func__, peer->host);
d62a17ae 7741
7742 /* if a peer-group member, then reset to peer-group default rather than
7743 * 0 */
7744 if (peer_group_active(peer))
7745 peer->gtsm_hops = peer->group->conf->gtsm_hops;
7746 else
e2521429 7747 peer->gtsm_hops = BGP_GTSM_HOPS_DISABLED;
d62a17ae 7748
7749 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7750 /* Invoking ebgp_multihop_set will set the TTL back to the
7751 * original
7752 * value as well as restting the NHT and such. The session is
7753 * reset.
7754 */
7755 if (peer->sort == BGP_PEER_EBGP)
7756 ret = peer_ebgp_multihop_unset(peer);
7757 else {
7758 if (peer->fd >= 0)
7759 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
7760 0);
7761
7762 if ((peer->status < Established) && peer->doppelganger
7763 && (peer->doppelganger->fd >= 0))
7764 sockopt_minttl(peer->su.sa.sa_family,
7765 peer->doppelganger->fd, 0);
7766 }
7767 } else {
7768 group = peer->group;
7769 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
e2521429 7770 peer->gtsm_hops = BGP_GTSM_HOPS_DISABLED;
d62a17ae 7771 if (peer->sort == BGP_PEER_EBGP)
7772 ret = peer_ebgp_multihop_unset(peer);
7773 else {
7774 if (peer->fd >= 0)
7775 sockopt_minttl(peer->su.sa.sa_family,
7776 peer->fd, 0);
7777
7778 if ((peer->status < Established)
7779 && peer->doppelganger
7780 && (peer->doppelganger->fd >= 0))
7781 sockopt_minttl(peer->su.sa.sa_family,
7782 peer->doppelganger->fd,
7783 0);
7784 }
7785 }
7786 }
718e3744 7787
d62a17ae 7788 return ret;
7789}
7790
3cb14f26
DS
7791static void peer_reset_message_stats(struct peer *peer)
7792{
7793 if (peer) {
7794 atomic_store_explicit(&peer->open_in, 0, memory_order_relaxed);
7795 atomic_store_explicit(&peer->open_out, 0, memory_order_relaxed);
7796 atomic_store_explicit(&peer->update_in, 0,
7797 memory_order_relaxed);
7798 atomic_store_explicit(&peer->update_out, 0,
7799 memory_order_relaxed);
7800 atomic_store_explicit(&peer->keepalive_in, 0,
7801 memory_order_relaxed);
7802 atomic_store_explicit(&peer->keepalive_out, 0,
7803 memory_order_relaxed);
7804 atomic_store_explicit(&peer->notify_in, 0,
7805 memory_order_relaxed);
7806 atomic_store_explicit(&peer->notify_out, 0,
7807 memory_order_relaxed);
7808 atomic_store_explicit(&peer->refresh_in, 0,
7809 memory_order_relaxed);
7810 atomic_store_explicit(&peer->refresh_out, 0,
7811 memory_order_relaxed);
7812 atomic_store_explicit(&peer->dynamic_cap_in, 0,
7813 memory_order_relaxed);
7814 atomic_store_explicit(&peer->dynamic_cap_out, 0,
7815 memory_order_relaxed);
7816 }
7817}
7818
d62a17ae 7819/*
7820 * If peer clear is invoked in a loop for all peers on the BGP instance,
7821 * it may end up freeing the doppelganger, and if this was the next node
7822 * to the current node, we would end up accessing the freed next node.
7823 * Pass along additional parameter which can be updated if next node
7824 * is freed; only required when walking the peer list on BGP instance.
7825 */
7826int peer_clear(struct peer *peer, struct listnode **nnode)
7827{
cb9196e7
DS
7828 if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)
7829 || !CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN)) {
ac4522e6 7830 if (peer_maximum_prefix_clear_overflow(peer))
d62a17ae 7831 return 0;
d62a17ae 7832
7833 peer->v_start = BGP_INIT_START_TIMER;
7834 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
7835 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
7836 BGP_NOTIFY_CEASE_ADMIN_RESET);
7837 else
7838 bgp_session_reset_safe(peer, nnode);
718e3744 7839 }
d62a17ae 7840 return 0;
718e3744 7841}
6b0655a2 7842
d62a17ae 7843int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
7844 enum bgp_clear_type stype)
718e3744 7845{
d62a17ae 7846 struct peer_af *paf;
718e3744 7847
feb17238 7848 if (!peer_established(peer))
d62a17ae 7849 return 0;
718e3744 7850
d62a17ae 7851 if (!peer->afc[afi][safi])
7852 return BGP_ERR_AF_UNCONFIGURED;
718e3744 7853
d62a17ae 7854 peer->rtt = sockopt_tcp_rtt(peer->fd);
718e3744 7855
d62a17ae 7856 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) {
7857 /* Clear the "neighbor x.x.x.x default-originate" flag */
7858 paf = peer_af_find(peer, afi, safi);
7859 if (paf && paf->subgroup
7860 && CHECK_FLAG(paf->subgroup->sflags,
7861 SUBGRP_STATUS_DEFAULT_ORIGINATE))
7862 UNSET_FLAG(paf->subgroup->sflags,
7863 SUBGRP_STATUS_DEFAULT_ORIGINATE);
718e3744 7864
e1a32ec1 7865 bgp_announce_route(peer, afi, safi, false);
d62a17ae 7866 }
718e3744 7867
d62a17ae 7868 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
7869 if (CHECK_FLAG(peer->af_cap[afi][safi],
7870 PEER_CAP_ORF_PREFIX_SM_ADV)
7871 && (CHECK_FLAG(peer->af_cap[afi][safi],
7872 PEER_CAP_ORF_PREFIX_RM_RCV)
7873 || CHECK_FLAG(peer->af_cap[afi][safi],
7874 PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) {
7875 struct bgp_filter *filter = &peer->filter[afi][safi];
d7c0a89a 7876 uint8_t prefix_type;
d62a17ae 7877
7878 if (CHECK_FLAG(peer->af_cap[afi][safi],
7879 PEER_CAP_ORF_PREFIX_RM_RCV))
7880 prefix_type = ORF_TYPE_PREFIX;
7881 else
7882 prefix_type = ORF_TYPE_PREFIX_OLD;
7883
7884 if (filter->plist[FILTER_IN].plist) {
7885 if (CHECK_FLAG(peer->af_sflags[afi][safi],
7886 PEER_STATUS_ORF_PREFIX_SEND))
7887 bgp_route_refresh_send(
7888 peer, afi, safi, prefix_type,
9af52ccf
DA
7889 REFRESH_DEFER, 1,
7890 BGP_ROUTE_REFRESH_NORMAL);
7891 bgp_route_refresh_send(
7892 peer, afi, safi, prefix_type,
7893 REFRESH_IMMEDIATE, 0,
7894 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 7895 } else {
7896 if (CHECK_FLAG(peer->af_sflags[afi][safi],
7897 PEER_STATUS_ORF_PREFIX_SEND))
7898 bgp_route_refresh_send(
7899 peer, afi, safi, prefix_type,
9af52ccf
DA
7900 REFRESH_IMMEDIATE, 1,
7901 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 7902 else
9af52ccf
DA
7903 bgp_route_refresh_send(
7904 peer, afi, safi, 0, 0, 0,
7905 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 7906 }
7907 return 0;
7908 }
7909 }
718e3744 7910
d62a17ae 7911 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
7912 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
7913 /* If neighbor has soft reconfiguration inbound flag.
7914 Use Adj-RIB-In database. */
7915 if (CHECK_FLAG(peer->af_flags[afi][safi],
7916 PEER_FLAG_SOFT_RECONFIG))
7917 bgp_soft_reconfig_in(peer, afi, safi);
7918 else {
7919 /* If neighbor has route refresh capability, send route
7920 refresh
7921 message to the peer. */
7922 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
7923 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
9af52ccf
DA
7924 bgp_route_refresh_send(
7925 peer, afi, safi, 0, 0, 0,
7926 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 7927 else
7928 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
7929 }
7930 }
3cb14f26
DS
7931
7932 if (stype == BGP_CLEAR_MESSAGE_STATS)
7933 peer_reset_message_stats(peer);
7934
d62a17ae 7935 return 0;
718e3744 7936}
7937
d62a17ae 7938/* Display peer uptime.*/
9f049418 7939char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json,
d62a17ae 7940 json_object *json)
7941{
7942 time_t uptime1, epoch_tbuf;
a2700b50 7943 struct tm tm;
d62a17ae 7944
d62a17ae 7945 /* If there is no connection has been done before print `never'. */
7946 if (uptime2 == 0) {
7947 if (use_json) {
7948 json_object_string_add(json, "peerUptime", "never");
7949 json_object_int_add(json, "peerUptimeMsec", 0);
7950 } else
7951 snprintf(buf, len, "never");
7952 return buf;
7953 }
718e3744 7954
d62a17ae 7955 /* Get current time. */
083ec940 7956 uptime1 = monotime(NULL);
d62a17ae 7957 uptime1 -= uptime2;
a2700b50 7958 gmtime_r(&uptime1, &tm);
718e3744 7959
d62a17ae 7960 if (uptime1 < ONE_DAY_SECOND)
a2700b50
MS
7961 snprintf(buf, len, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
7962 tm.tm_sec);
d62a17ae 7963 else if (uptime1 < ONE_WEEK_SECOND)
a2700b50
MS
7964 snprintf(buf, len, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
7965 tm.tm_min);
d62a17ae 7966 else if (uptime1 < ONE_YEAR_SECOND)
a2700b50
MS
7967 snprintf(buf, len, "%02dw%dd%02dh", tm.tm_yday / 7,
7968 tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
d62a17ae 7969 else
a2700b50
MS
7970 snprintf(buf, len, "%02dy%02dw%dd", tm.tm_year - 70,
7971 tm.tm_yday / 7,
7972 tm.tm_yday - ((tm.tm_yday / 7) * 7));
d62a17ae 7973
7974 if (use_json) {
7975 epoch_tbuf = time(NULL) - uptime1;
7976 json_object_string_add(json, "peerUptime", buf);
7977 json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000);
7978 json_object_int_add(json, "peerUptimeEstablishedEpoch",
7979 epoch_tbuf);
7980 }
718e3744 7981
d62a17ae 7982 return buf;
718e3744 7983}
7984
85e9cd9a
AMR
7985void bgp_master_init(struct thread_master *master, const int buffer_size,
7986 struct list *addresses)
718e3744 7987{
d62a17ae 7988 qobj_init();
0e64d123 7989
6006b807 7990 memset(&bgp_master, 0, sizeof(bgp_master));
718e3744 7991
d62a17ae 7992 bm = &bgp_master;
7993 bm->bgp = list_new();
7994 bm->listen_sockets = list_new();
7995 bm->port = BGP_PORT_DEFAULT;
85e9cd9a 7996 bm->addresses = addresses;
d62a17ae 7997 bm->master = master;
083ec940 7998 bm->start_time = monotime(NULL);
d62a17ae 7999 bm->t_rmap_update = NULL;
8000 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
d70583f7
D
8001 bm->v_update_delay = BGP_UPDATE_DELAY_DEF;
8002 bm->v_establish_wait = BGP_UPDATE_DELAY_DEF;
97b4a0ec 8003 bm->terminating = false;
c2d020ad 8004 bm->socket_buffer = buffer_size;
9acb67cb 8005 bm->wait_for_fib = false;
425bd64b 8006 bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
495f0b13 8007
48ecf8f5 8008 bgp_mac_init();
e9eb5f63 8009 /* init the rd id space.
8010 assign 0th index in the bitfield,
523cafc4 8011 so that we start with id 1
8012 */
e9eb5f63 8013 bf_init(bm->rd_idspace, UINT16_MAX);
8014 bf_assign_zero_index(bm->rd_idspace);
8015
955bfd98 8016 /* mpls label dynamic allocation pool */
e70e9f8e 8017 bgp_lp_init(bm->master, &bm->labelpool);
955bfd98 8018
c589d847 8019 bgp_l3nhg_init();
c44ab6f1 8020 bgp_evpn_mh_init();
d62a17ae 8021 QOBJ_REG(bm, bgp_master);
718e3744 8022}
200df115 8023
ad4cbda1 8024/*
009b18fc 8025 * Free up connected routes and interfaces for a BGP instance. Invoked upon
8026 * instance delete (non-default only) or BGP exit.
ad4cbda1 8027 */
d62a17ae 8028static void bgp_if_finish(struct bgp *bgp)
ad4cbda1 8029{
ee66b77f 8030 struct vrf *vrf;
d62a17ae 8031 struct interface *ifp;
8032
ee66b77f
PG
8033 vrf = bgp_vrf_lookup_by_instance_type(bgp);
8034
f4e14fdb 8035 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW || !vrf)
d62a17ae 8036 return;
ad4cbda1 8037
451fda4f 8038 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 8039 struct listnode *c_node, *c_nnode;
8040 struct connected *c;
ad4cbda1 8041
d62a17ae 8042 for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c))
8043 bgp_connected_delete(bgp, c);
8044 }
ad4cbda1 8045}
6b0655a2 8046
d62a17ae 8047static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token)
18c57037 8048{
d62a17ae 8049 struct vrf *vrf = NULL;
8050 struct listnode *next;
8051 struct bgp *bgp;
18c57037 8052
6a8ca00f
PG
8053 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
8054 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
18c57037 8055
d62a17ae 8056 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
8057 if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
8058 continue;
18c57037 8059
d62a17ae 8060 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name));
8061 }
18c57037
DS
8062}
8063
2ed9fe4a
DL
8064static void bgp_instasn_autocomplete(vector comps, struct cmd_token *token)
8065{
8066 struct listnode *next, *next2;
8067 struct bgp *bgp, *bgp2;
8068 char buf[11];
8069
8070 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
8071 /* deduplicate */
8072 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next2, bgp2)) {
8073 if (bgp2->as == bgp->as)
8074 break;
8075 if (bgp2 == bgp)
8076 break;
8077 }
8078 if (bgp2 != bgp)
8079 continue;
8080
8081 snprintf(buf, sizeof(buf), "%u", bgp->as);
8082 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, buf));
8083 }
8084}
8085
18c57037 8086static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = {
d62a17ae 8087 {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete},
2ed9fe4a 8088 {.varname = "instasn", .completions = bgp_instasn_autocomplete},
d62a17ae 8089 {.completions = NULL},
18c57037
DS
8090};
8091
1ac267a2
DL
8092struct frr_pthread *bgp_pth_io;
8093struct frr_pthread *bgp_pth_ka;
8094
4d762f26 8095static void bgp_pthreads_init(void)
2d4ee774 8096{
1ac267a2
DL
8097 assert(!bgp_pth_io);
8098 assert(!bgp_pth_ka);
8099
a715eab3 8100 struct frr_pthread_attr io = {
a715eab3
QY
8101 .start = frr_pthread_attr_default.start,
8102 .stop = frr_pthread_attr_default.stop,
a715eab3
QY
8103 };
8104 struct frr_pthread_attr ka = {
a715eab3
QY
8105 .start = bgp_keepalives_start,
8106 .stop = bgp_keepalives_stop,
a715eab3 8107 };
1ac267a2
DL
8108 bgp_pth_io = frr_pthread_new(&io, "BGP I/O thread", "bgpd_io");
8109 bgp_pth_ka = frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka");
419dfe6a
QY
8110}
8111
4d762f26 8112void bgp_pthreads_run(void)
419dfe6a 8113{
1ac267a2
DL
8114 frr_pthread_run(bgp_pth_io, NULL);
8115 frr_pthread_run(bgp_pth_ka, NULL);
88b24dee 8116
a715eab3 8117 /* Wait until threads are ready. */
1ac267a2
DL
8118 frr_pthread_wait_running(bgp_pth_io);
8119 frr_pthread_wait_running(bgp_pth_ka);
2d4ee774
QY
8120}
8121
4d762f26 8122void bgp_pthreads_finish(void)
2d4ee774 8123{
0ca8b79f 8124 frr_pthread_stop_all();
2d4ee774
QY
8125}
8126
aa24a36a
DA
8127static int peer_unshut_after_cfg(struct bgp *bgp)
8128{
8129 struct listnode *node;
8130 struct peer *peer;
8131
8132 for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
8133 if (!peer->shut_during_cfg)
8134 continue;
8135
8136 if (bgp_debug_neighbor_events(peer))
8137 zlog_debug("%s: released from config-pending hold",
8138 peer->host);
8139
8140 peer->shut_during_cfg = false;
8141 if (peer_active(peer) && peer->status != Established) {
8142 if (peer->status != Idle)
8143 BGP_EVENT_ADD(peer, BGP_Stop);
8144 BGP_EVENT_ADD(peer, BGP_Start);
8145 }
8146 }
8147
8148 return 0;
8149}
8150
f533be73 8151void bgp_init(unsigned short instance)
718e3744 8152{
aa24a36a 8153 hook_register(bgp_config_end, peer_unshut_after_cfg);
fc9a856f 8154
d62a17ae 8155 /* allocates some vital data structures used by peer commands in
8156 * vty_init */
718e3744 8157
419dfe6a
QY
8158 /* pre-init pthreads */
8159 bgp_pthreads_init();
8160
d62a17ae 8161 /* Init zebra. */
f533be73 8162 bgp_zebra_init(bm->master, instance);
718e3744 8163
49e5a4a0 8164#ifdef ENABLE_BGP_VNC
d62a17ae 8165 vnc_zebra_init(bm->master);
65efcfce
LB
8166#endif
8167
d62a17ae 8168 /* BGP VTY commands installation. */
8169 bgp_vty_init();
8170
8171 /* BGP inits. */
8172 bgp_attr_init();
8173 bgp_debug_init();
ed0e57e3 8174 bgp_community_alias_init();
d62a17ae 8175 bgp_dump_init();
8176 bgp_route_init();
8177 bgp_route_map_init();
8178 bgp_scan_vty_init();
8179 bgp_mplsvpn_init();
49e5a4a0 8180#ifdef ENABLE_BGP_VNC
d62a17ae 8181 rfapi_init();
65efcfce 8182#endif
d62a17ae 8183 bgp_ethernetvpn_init();
7c40bf39 8184 bgp_flowspec_vty_init();
d62a17ae 8185
8186 /* Access list initialize. */
8187 access_list_init();
8188 access_list_add_hook(peer_distribute_update);
8189 access_list_delete_hook(peer_distribute_update);
8190
8191 /* Filter list initialize. */
8192 bgp_filter_init();
8193 as_list_add_hook(peer_aslist_add);
8194 as_list_delete_hook(peer_aslist_del);
8195
8196 /* Prefix list initialize.*/
8197 prefix_list_init();
8198 prefix_list_add_hook(peer_prefix_list_update);
8199 prefix_list_delete_hook(peer_prefix_list_update);
8200
8201 /* Community list initialize. */
8202 bgp_clist = community_list_init();
8203
8204 /* BFD init */
21bfce98 8205 bgp_bfd_init(bm->master);
d62a17ae 8206
e3ea6503
PR
8207 bgp_lp_vty_init();
8208
d62a17ae 8209 cmd_variable_handler_register(bgp_viewvrf_var_handlers);
8210}
8211
8212void bgp_terminate(void)
8213{
8214 struct bgp *bgp;
8215 struct peer *peer;
8216 struct listnode *node, *nnode;
8217 struct listnode *mnode, *mnnode;
8218
8219 QOBJ_UNREG(bm);
8220
8221 /* Close the listener sockets first as this prevents peers from
8222 * attempting
8223 * to reconnect on receiving the peer unconfig message. In the presence
8224 * of a large number of peers this will ensure that no peer is left with
8225 * a dangling connection
8226 */
d62a17ae 8227
3f22218b
DS
8228 bgp_close();
8229 /* reverse bgp_master_init */
8230 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
8231 bgp_close_vrf_socket(bgp);
d62a17ae 8232 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
feb17238 8233 if (peer_established(peer) || peer->status == OpenSent
d62a17ae 8234 || peer->status == OpenConfirm)
8235 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
8236 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
3f22218b
DS
8237 }
8238
8239 if (bm->listen_sockets)
8240 list_delete(&bm->listen_sockets);
d62a17ae 8241
fa5806c3 8242 THREAD_OFF(bm->t_rmap_update);
955bfd98 8243
48ecf8f5 8244 bgp_mac_finish();
545acafb 8245}
dcc1615e
DD
8246
8247struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
8248 const char *ip_str, bool use_json)
8249{
8250 int ret;
8251 struct peer *peer;
8252 union sockunion su;
8253
8254 /* Get peer sockunion. */
8255 ret = str2sockunion(ip_str, &su);
8256 if (ret < 0) {
8257 peer = peer_lookup_by_conf_if(bgp, ip_str);
8258 if (!peer) {
8259 peer = peer_lookup_by_hostname(bgp, ip_str);
8260
8261 if (!peer) {
8262 if (use_json) {
8263 json_object *json_no = NULL;
8264 json_no = json_object_new_object();
8265 json_object_string_add(
8266 json_no,
8267 "malformedAddressOrName",
8268 ip_str);
75eeda93 8269 vty_json(vty, json_no);
dcc1615e
DD
8270 } else
8271 vty_out(vty,
8272 "%% Malformed address or name: %s\n",
8273 ip_str);
8274 return NULL;
8275 }
8276 }
8277 return peer;
8278 }
8279
8280 /* Peer structure lookup. */
8281 peer = peer_lookup(bgp, &su);
8282 if (!peer) {
8283 if (use_json) {
8284 json_object *json_no = NULL;
8285 json_no = json_object_new_object();
8286 json_object_string_add(json_no, "warning",
8287 "No such neighbor in this view/vrf");
75eeda93 8288 vty_json(vty, json_no);
dcc1615e 8289 } else
1c49e813 8290 vty_out(vty, "No such neighbor in this view/vrf\n");
dcc1615e
DD
8291 return NULL;
8292 }
8293
8294 return peer;
8295}
8296
794b37d5 8297void bgp_gr_apply_running_config(void)
8298{
8299 struct peer *peer = NULL;
8300 struct bgp *bgp = NULL;
8301 struct listnode *node, *nnode;
dc95985f 8302 bool gr_router_detected = false;
794b37d5 8303
8304 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
36235319 8305 zlog_debug("[BGP_GR] %s called !", __func__);
794b37d5 8306
dc95985f 8307 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
8308 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
794b37d5 8309 bgp_peer_gr_flags_update(peer);
36235319 8310 if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART))
dc95985f 8311 gr_router_detected = true;
8312 }
8313
36235319
QY
8314 if (gr_router_detected
8315 && bgp->present_zebra_gr_state == ZEBRA_GR_DISABLE) {
2ba1fe69 8316 bgp_zebra_send_capabilities(bgp, true);
36235319
QY
8317 } else if (!gr_router_detected
8318 && bgp->present_zebra_gr_state == ZEBRA_GR_ENABLE) {
2ba1fe69 8319 bgp_zebra_send_capabilities(bgp, false);
dc95985f 8320 }
8321
8322 gr_router_detected = false;
8323 }
794b37d5 8324}
f70c91dc
DA
8325
8326printfrr_ext_autoreg_p("BP", printfrr_bp);
8327static ssize_t printfrr_bp(struct fbuf *buf, struct printfrr_eargs *ea,
8328 const void *ptr)
8329{
8330 const struct peer *peer = ptr;
8331
8332 if (!peer)
8333 return bputs(buf, "(null)");
8334
8335 return bprintfrr(buf, "%s(%s)", peer->host,
8336 peer->hostname ? peer->hostname : "Unknown");
8337}