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