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