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