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