]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
zebra: Use neigh_list instead of neigh_refcnt for zebra_mac and zebra_neigh binding
[mirror_frr.git] / bgpd / bgp_nexthop.c
CommitLineData
718e3744 1/* BGP nexthop scan
896014f4
DL
2 * Copyright (C) 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 "command.h"
24#include "thread.h"
25#include "prefix.h"
26#include "zclient.h"
27#include "stream.h"
28#include "network.h"
29#include "log.h"
30#include "memory.h"
10f9bf3f
JBD
31#include "hash.h"
32#include "jhash.h"
fb018d25 33#include "nexthop.h"
3f9c7369 34#include "queue.h"
039f3a34 35#include "filter.h"
718e3744 36
37#include "bgpd/bgpd.h"
38#include "bgpd/bgp_table.h"
39#include "bgpd/bgp_route.h"
40#include "bgpd/bgp_attr.h"
41#include "bgpd/bgp_nexthop.h"
fb018d25 42#include "bgpd/bgp_nht.h"
718e3744 43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_damp.h"
8ffedcea 45#include "bgpd/bgp_fsm.h"
8386ac43 46#include "bgpd/bgp_vty.h"
718e3744 47#include "zebra/rib.h"
d62a17ae 48#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
718e3744 49
d62a17ae 50char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
fb018d25 51{
d62a17ae 52 prefix2str(&(bnc->node->p), buf, size);
53 return buf;
fb018d25
DS
54}
55
d62a17ae 56void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
718e3744 57{
d62a17ae 58 nexthops_free(bnc->nexthop);
718e3744 59}
60
d62a17ae 61struct bgp_nexthop_cache *bnc_new(void)
718e3744 62{
d62a17ae 63 struct bgp_nexthop_cache *bnc;
fb018d25 64
d62a17ae 65 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
66 sizeof(struct bgp_nexthop_cache));
67 LIST_INIT(&(bnc->paths));
68 return bnc;
718e3744 69}
70
d62a17ae 71void bnc_free(struct bgp_nexthop_cache *bnc)
718e3744 72{
d62a17ae 73 bnc_nexthop_free(bnc);
74 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
718e3744 75}
6b0655a2 76
718e3744 77/* Reset and free all BGP nexthop cache. */
d62a17ae 78static void bgp_nexthop_cache_reset(struct bgp_table *table)
718e3744 79{
d62a17ae 80 struct bgp_node *rn;
81 struct bgp_nexthop_cache *bnc;
82
83 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
84 if ((bnc = rn->info) != NULL) {
85 bnc_free(bnc);
86 rn->info = NULL;
87 bgp_unlock_node(rn);
88 }
718e3744 89}
90
10f9bf3f 91/* BGP own address structure */
d62a17ae 92struct bgp_addr {
93 struct in_addr addr;
94 int refcnt;
10f9bf3f
JBD
95};
96
d62a17ae 97static void *bgp_address_hash_alloc(void *p)
10f9bf3f 98{
d62a17ae 99 const struct in_addr *val = (const struct in_addr *)p;
100 struct bgp_addr *addr;
10f9bf3f 101
d62a17ae 102 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
103 addr->refcnt = 0;
104 addr->addr.s_addr = val->s_addr;
10f9bf3f 105
d62a17ae 106 return addr;
10f9bf3f
JBD
107}
108
d62a17ae 109static void bgp_address_hash_free(void *addr)
37d361e7 110{
d62a17ae 111 XFREE(MTYPE_BGP_ADDR, addr);
37d361e7
RW
112}
113
d62a17ae 114static unsigned int bgp_address_hash_key_make(void *p)
10f9bf3f 115{
d62a17ae 116 const struct bgp_addr *addr = p;
10f9bf3f 117
d62a17ae 118 return jhash_1word(addr->addr.s_addr, 0);
10f9bf3f
JBD
119}
120
d62a17ae 121static int bgp_address_hash_cmp(const void *p1, const void *p2)
10f9bf3f 122{
d62a17ae 123 const struct bgp_addr *addr1 = p1;
124 const struct bgp_addr *addr2 = p2;
10f9bf3f 125
d62a17ae 126 return addr1->addr.s_addr == addr2->addr.s_addr;
10f9bf3f
JBD
127}
128
d62a17ae 129void bgp_address_init(struct bgp *bgp)
10f9bf3f 130{
d62a17ae 131 bgp->address_hash = hash_create(bgp_address_hash_key_make,
132 bgp_address_hash_cmp, NULL);
10f9bf3f
JBD
133}
134
d62a17ae 135void bgp_address_destroy(struct bgp *bgp)
bb86c601 136{
d62a17ae 137 if (bgp->address_hash == NULL)
138 return;
139 hash_clean(bgp->address_hash, bgp_address_hash_free);
140 hash_free(bgp->address_hash);
141 bgp->address_hash = NULL;
bb86c601
LB
142}
143
d62a17ae 144static void bgp_address_add(struct bgp *bgp, struct prefix *p)
10f9bf3f 145{
d62a17ae 146 struct bgp_addr tmp;
147 struct bgp_addr *addr;
10f9bf3f 148
d62a17ae 149 tmp.addr = p->u.prefix4;
10f9bf3f 150
d62a17ae 151 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
152 if (!addr)
153 return;
5ce10e92 154
d62a17ae 155 addr->refcnt++;
10f9bf3f
JBD
156}
157
d62a17ae 158static void bgp_address_del(struct bgp *bgp, struct prefix *p)
10f9bf3f 159{
d62a17ae 160 struct bgp_addr tmp;
161 struct bgp_addr *addr;
10f9bf3f 162
d62a17ae 163 tmp.addr = p->u.prefix4;
10f9bf3f 164
d62a17ae 165 addr = hash_lookup(bgp->address_hash, &tmp);
166 /* may have been deleted earlier by bgp_interface_down() */
167 if (addr == NULL)
168 return;
9e47abd8 169
d62a17ae 170 addr->refcnt--;
10f9bf3f 171
d62a17ae 172 if (addr->refcnt == 0) {
173 hash_release(bgp->address_hash, addr);
174 XFREE(MTYPE_BGP_ADDR, addr);
175 }
10f9bf3f
JBD
176}
177
6b0655a2 178
d62a17ae 179struct bgp_connected_ref {
180 unsigned int refcnt;
718e3744 181};
182
d62a17ae 183void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
718e3744 184{
d62a17ae 185 struct prefix p;
186 struct prefix *addr;
187 struct bgp_node *rn;
188 struct bgp_connected_ref *bc;
189 struct listnode *node, *nnode;
190 struct peer *peer;
191
192 addr = ifc->address;
193
194 p = *(CONNECTED_PREFIX(ifc));
195 if (addr->family == AF_INET) {
196 apply_mask_ipv4((struct prefix_ipv4 *)&p);
197
198 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
199 return;
200
201 bgp_address_add(bgp, addr);
202
203 rn = bgp_node_get(bgp->connected_table[AFI_IP],
204 (struct prefix *)&p);
205 if (rn->info) {
206 bc = rn->info;
207 bc->refcnt++;
208 } else {
209 bc = XCALLOC(MTYPE_BGP_CONN,
210 sizeof(struct bgp_connected_ref));
211 bc->refcnt = 1;
212 rn->info = bc;
213 }
8ffedcea 214
d62a17ae 215 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
216 if (peer->conf_if
217 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
218 && peer->status != Established
219 && !CHECK_FLAG(peer->flags,
220 PEER_FLAG_IFPEER_V6ONLY)) {
221 if (peer_active(peer))
222 BGP_EVENT_ADD(peer, BGP_Stop);
223 BGP_EVENT_ADD(peer, BGP_Start);
224 }
225 }
226 } else if (addr->family == AF_INET6) {
227 apply_mask_ipv6((struct prefix_ipv6 *)&p);
228
229 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
230 return;
231
232 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
233 return;
234
235 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
236 (struct prefix *)&p);
237 if (rn->info) {
238 bc = rn->info;
239 bc->refcnt++;
240 } else {
241 bc = XCALLOC(MTYPE_BGP_CONN,
242 sizeof(struct bgp_connected_ref));
243 bc->refcnt = 1;
244 rn->info = bc;
245 }
718e3744 246 }
718e3744 247}
248
d62a17ae 249void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
718e3744 250{
d62a17ae 251 struct prefix p;
252 struct prefix *addr;
253 struct bgp_node *rn;
254 struct bgp_connected_ref *bc;
718e3744 255
d62a17ae 256 addr = ifc->address;
718e3744 257
d62a17ae 258 p = *(CONNECTED_PREFIX(ifc));
259 if (addr->family == AF_INET) {
260 apply_mask_ipv4((struct prefix_ipv4 *)&p);
718e3744 261
d62a17ae 262 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
263 return;
718e3744 264
d62a17ae 265 bgp_address_del(bgp, addr);
10f9bf3f 266
d62a17ae 267 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
268 if (!rn)
269 return;
718e3744 270
d62a17ae 271 bc = rn->info;
272 bc->refcnt--;
273 if (bc->refcnt == 0) {
274 XFREE(MTYPE_BGP_CONN, bc);
275 rn->info = NULL;
276 }
277 bgp_unlock_node(rn);
278 bgp_unlock_node(rn);
279 } else if (addr->family == AF_INET6) {
280 apply_mask_ipv6((struct prefix_ipv6 *)&p);
281
282 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
283 return;
284
285 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
286 return;
287
288 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
289 (struct prefix *)&p);
290 if (!rn)
291 return;
292
293 bc = rn->info;
294 bc->refcnt--;
295 if (bc->refcnt == 0) {
296 XFREE(MTYPE_BGP_CONN, bc);
297 rn->info = NULL;
298 }
299 bgp_unlock_node(rn);
300 bgp_unlock_node(rn);
718e3744 301 }
718e3744 302}
303
d62a17ae 304int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
718e3744 305{
d62a17ae 306 struct bgp_addr tmp, *addr;
718e3744 307
d62a17ae 308 tmp.addr = nh_addr;
10f9bf3f 309
d62a17ae 310 addr = hash_lookup(bgp->address_hash, &tmp);
311 if (addr)
312 return 1;
718e3744 313
d62a17ae 314 return 0;
718e3744 315}
6b0655a2 316
d62a17ae 317int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
718e3744 318{
d62a17ae 319 struct bgp_node *rn1;
320 struct bgp_node *rn2;
321 struct prefix p;
322 int ret;
323
324 p.family = AF_INET;
325 p.prefixlen = IPV4_MAX_BITLEN;
326 p.u.prefix4 = nexthop;
327
328 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
329 if (!rn1)
330 return 0;
331
332 p.family = AF_INET;
333 p.prefixlen = IPV4_MAX_BITLEN;
334 p.u.prefix4 = peer->su.sin.sin_addr;
335
336 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
337 if (!rn2) {
338 bgp_unlock_node(rn1);
339 return 0;
340 }
718e3744 341
d62a17ae 342 ret = (rn1 == rn2) ? 1 : 0;
718e3744 343
d62a17ae 344 bgp_unlock_node(rn1);
345 bgp_unlock_node(rn2);
718e3744 346
d62a17ae 347 return (ret);
718e3744 348}
349
d62a17ae 350static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
fb018d25 351{
d62a17ae 352 struct bgp_node *rn;
353 struct bgp_nexthop_cache *bnc;
354 char buf[PREFIX2STR_BUFFER];
355 struct nexthop *nexthop;
356 time_t tbuf;
357 afi_t afi;
358
359 vty_out(vty, "Current BGP nexthop cache:\n");
360 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
361 if (!bgp->nexthop_cache_table[afi])
362 continue;
363
364 for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
365 rn = bgp_route_next(rn)) {
366 if ((bnc = rn->info) != NULL) {
367 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
368 vty_out(vty,
369 " %s valid [IGP metric %d], #paths %d\n",
370 inet_ntop(rn->p.family,
371 &rn->p.u.prefix, buf,
372 sizeof(buf)),
373 bnc->metric, bnc->path_count);
374 if (detail)
375 for (nexthop = bnc->nexthop;
376 nexthop;
377 nexthop = nexthop->next)
378 switch (nexthop->type) {
379 case NEXTHOP_TYPE_IPV6:
380 vty_out(vty,
381 " gate %s\n",
382 inet_ntop(
383 AF_INET6,
384 &nexthop->gate
385 .ipv6,
386 buf,
387 sizeof(buf)));
388 break;
389 case NEXTHOP_TYPE_IPV6_IFINDEX:
390 vty_out(vty,
391 " gate %s, if %s\n",
392 inet_ntop(
393 AF_INET6,
394 &nexthop->gate
395 .ipv6,
396 buf,
397 sizeof(buf)),
398 ifindex2ifname(
399 nexthop->ifindex,
400 bgp->vrf_id));
401 break;
402 case NEXTHOP_TYPE_IPV4:
403 vty_out(vty,
404 " gate %s\n",
405 inet_ntop(
406 AF_INET,
407 &nexthop->gate
408 .ipv4,
409 buf,
410 sizeof(buf)));
411 break;
412 case NEXTHOP_TYPE_IFINDEX:
413 vty_out(vty,
414 " if %s\n",
415 ifindex2ifname(
416 nexthop->ifindex,
417 bgp->vrf_id));
418 break;
419 case NEXTHOP_TYPE_IPV4_IFINDEX:
420 vty_out(vty,
421 " gate %s, if %s\n",
422 inet_ntop(
423 AF_INET,
424 &nexthop->gate
425 .ipv4,
426 buf,
427 sizeof(buf)),
428 ifindex2ifname(
429 nexthop->ifindex,
430 bgp->vrf_id));
431 break;
432 default:
433 vty_out(vty,
434 " invalid nexthop type %u\n",
435 nexthop->type);
436 }
437 } else {
438 vty_out(vty, " %s invalid\n",
439 inet_ntop(rn->p.family,
440 &rn->p.u.prefix, buf,
441 sizeof(buf)));
442 if (CHECK_FLAG(bnc->flags,
443 BGP_NEXTHOP_CONNECTED))
444 vty_out(vty,
445 " Must be Connected\n");
446 }
447 tbuf = time(NULL)
448 - (bgp_clock() - bnc->last_update);
449 vty_out(vty, " Last update: %s", ctime(&tbuf));
450 vty_out(vty, "\n");
da11a696
DS
451 }
452 }
fb018d25 453 }
f186de26 454}
455
d62a17ae 456static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
457 int detail)
f186de26 458{
d62a17ae 459 struct bgp *bgp;
460
461 if (name)
462 bgp = bgp_lookup_by_name(name);
463 else
464 bgp = bgp_get_default();
465 if (!bgp) {
466 vty_out(vty, "%% No such BGP instance exist\n");
467 return CMD_WARNING;
468 }
f186de26 469
d62a17ae 470 bgp_show_nexthops(vty, bgp, detail);
f186de26 471
d62a17ae 472 return CMD_SUCCESS;
fb018d25
DS
473}
474
d62a17ae 475static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
f186de26 476{
d62a17ae 477 struct listnode *node, *nnode;
478 struct bgp *bgp;
479
480 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
481 vty_out(vty, "\nInstance %s:\n",
482 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
483 ? "Default"
484 : bgp->name);
485 bgp_show_nexthops(vty, bgp, 0);
486 }
f186de26 487}
488
fb018d25
DS
489DEFUN (show_ip_bgp_nexthop,
490 show_ip_bgp_nexthop_cmd,
18c57037 491 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
50ef26d4 492 SHOW_STR
493 IP_STR
494 BGP_STR
8386ac43 495 BGP_INSTANCE_HELP_STR
3a2d747c
QY
496 "BGP nexthop table\n"
497 "Show detailed information\n")
50ef26d4 498{
d62a17ae 499 int idx = 0;
500 char *vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
501 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
502 return show_ip_bgp_nexthop_table(vty, vrf, detail);
50ef26d4 503}
504
f186de26 505DEFUN (show_ip_bgp_instance_all_nexthop,
506 show_ip_bgp_instance_all_nexthop_cmd,
bec37ba5 507 "show [ip] bgp <view|vrf> all nexthop",
f186de26 508 SHOW_STR
509 IP_STR
510 BGP_STR
511 BGP_INSTANCE_ALL_HELP_STR
512 "BGP nexthop table\n")
513{
d62a17ae 514 bgp_show_all_instances_nexthops_vty(vty);
515 return CMD_SUCCESS;
f186de26 516}
517
d62a17ae 518void bgp_scan_init(struct bgp *bgp)
718e3744 519{
d62a17ae 520 afi_t afi;
521
522 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
523 bgp->nexthop_cache_table[afi] =
524 bgp_table_init(afi, SAFI_UNICAST);
525 bgp->connected_table[afi] = bgp_table_init(afi, SAFI_UNICAST);
526 bgp->import_check_table[afi] =
527 bgp_table_init(afi, SAFI_UNICAST);
528 }
fc9a856f
DS
529}
530
d62a17ae 531void bgp_scan_vty_init(void)
fc9a856f 532{
d62a17ae 533 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
534 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 535}
228da428 536
d62a17ae 537void bgp_scan_finish(struct bgp *bgp)
228da428 538{
d62a17ae 539 afi_t afi;
6c88b44d 540
d62a17ae 541 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
542 /* Only the current one needs to be reset. */
543 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
544 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
545 bgp->nexthop_cache_table[afi] = NULL;
228da428 546
d62a17ae 547 bgp_table_unlock(bgp->connected_table[afi]);
548 bgp->connected_table[afi] = NULL;
078430f6 549
d62a17ae 550 bgp_table_unlock(bgp->import_check_table[afi]);
551 bgp->import_check_table[afi] = NULL;
552 }
228da428 553}