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