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