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