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