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