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