2 * Copyright (C) 2000 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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
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.
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
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"
42 #include "bgpd/bgp_nht.h"
43 #include "bgpd/bgp_debug.h"
44 #include "bgpd/bgp_damp.h"
45 #include "bgpd/bgp_fsm.h"
46 #include "bgpd/bgp_vty.h"
48 DEFINE_MTYPE_STATIC(BGPD
, MARTIAN_STRING
, "BGP Martian Address Intf String");
50 static void bgp_ipv6_address_add(struct bgp
*bgp
, struct connected
*ifc
,
52 static void bgp_ipv6_address_del(struct bgp
*bgp
, struct connected
*ifc
,
55 char *bnc_str(struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
57 prefix2str(&(bnc
->node
->p
), buf
, size
);
61 void bnc_nexthop_free(struct bgp_nexthop_cache
*bnc
)
63 nexthops_free(bnc
->nexthop
);
66 struct bgp_nexthop_cache
*bnc_new(void)
68 struct bgp_nexthop_cache
*bnc
;
70 bnc
= XCALLOC(MTYPE_BGP_NEXTHOP_CACHE
,
71 sizeof(struct bgp_nexthop_cache
));
72 LIST_INIT(&(bnc
->paths
));
76 void bnc_free(struct bgp_nexthop_cache
*bnc
)
78 bnc_nexthop_free(bnc
);
79 XFREE(MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
82 /* Reset and free all BGP nexthop cache. */
83 static void bgp_nexthop_cache_reset(struct bgp_table
*table
)
86 struct bgp_nexthop_cache
*bnc
;
88 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
89 bnc
= bgp_node_get_bgp_nexthop_info(rn
);
93 while (!LIST_EMPTY(&(bnc
->paths
))) {
94 struct bgp_path_info
*path
= LIST_FIRST(&(bnc
->paths
));
96 path_nh_map(path
, bnc
, false);
100 bgp_node_set_bgp_nexthop_info(rn
, NULL
);
105 static void *bgp_tip_hash_alloc(void *p
)
107 const struct in_addr
*val
= (const struct in_addr
*)p
;
108 struct tip_addr
*addr
;
110 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
112 addr
->addr
.s_addr
= val
->s_addr
;
117 static void bgp_tip_hash_free(void *addr
)
119 XFREE(MTYPE_TIP_ADDR
, addr
);
122 static unsigned int bgp_tip_hash_key_make(void *p
)
124 const struct tip_addr
*addr
= p
;
126 return jhash_1word(addr
->addr
.s_addr
, 0);
129 static bool bgp_tip_hash_cmp(const void *p1
, const void *p2
)
131 const struct tip_addr
*addr1
= p1
;
132 const struct tip_addr
*addr2
= p2
;
134 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
137 void bgp_tip_hash_init(struct bgp
*bgp
)
139 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
, bgp_tip_hash_cmp
,
143 void bgp_tip_hash_destroy(struct bgp
*bgp
)
145 if (bgp
->tip_hash
== NULL
)
147 hash_clean(bgp
->tip_hash
, bgp_tip_hash_free
);
148 hash_free(bgp
->tip_hash
);
149 bgp
->tip_hash
= NULL
;
152 void bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
155 struct tip_addr
*addr
;
159 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
166 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
169 struct tip_addr
*addr
;
173 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
174 /* may have been deleted earlier by bgp_interface_down() */
180 if (addr
->refcnt
== 0) {
181 hash_release(bgp
->tip_hash
, addr
);
182 XFREE(MTYPE_TIP_ADDR
, addr
);
186 /* BGP own address structure */
189 struct list
*ifp_name_list
;
192 static void show_address_entry(struct hash_bucket
*bucket
, void *args
)
194 struct vty
*vty
= (struct vty
*)args
;
195 struct bgp_addr
*addr
= (struct bgp_addr
*)bucket
->data
;
197 struct listnode
*node
;
199 vty_out(vty
, "addr: %s, count: %d : ", inet_ntoa(addr
->addr
),
200 addr
->ifp_name_list
->count
);
202 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
203 vty_out(vty
, " %s,", name
);
209 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
211 hash_iterate(bgp
->address_hash
,
212 (void (*)(struct hash_bucket
*, void *))show_address_entry
,
216 static void bgp_address_hash_string_del(void *val
)
220 XFREE(MTYPE_MARTIAN_STRING
, data
);
223 static void *bgp_address_hash_alloc(void *p
)
225 const struct in_addr
*val
= (const struct in_addr
*)p
;
226 struct bgp_addr
*addr
;
228 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
229 addr
->addr
.s_addr
= val
->s_addr
;
231 addr
->ifp_name_list
= list_new();
232 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
237 static void bgp_address_hash_free(void *data
)
239 struct bgp_addr
*addr
= data
;
241 list_delete(&addr
->ifp_name_list
);
242 XFREE(MTYPE_BGP_ADDR
, addr
);
245 static unsigned int bgp_address_hash_key_make(void *p
)
247 const struct bgp_addr
*addr
= p
;
249 return jhash_1word(addr
->addr
.s_addr
, 0);
252 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
254 const struct bgp_addr
*addr1
= p1
;
255 const struct bgp_addr
*addr2
= p2
;
257 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
260 void bgp_address_init(struct bgp
*bgp
)
263 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
267 void bgp_address_destroy(struct bgp
*bgp
)
269 if (bgp
->address_hash
== NULL
)
271 hash_clean(bgp
->address_hash
, bgp_address_hash_free
);
272 hash_free(bgp
->address_hash
);
273 bgp
->address_hash
= NULL
;
276 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
280 struct bgp_addr
*addr
;
281 struct listnode
*node
;
284 tmp
.addr
= p
->u
.prefix4
;
286 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
288 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
289 if (strcmp(ifc
->ifp
->name
, name
) == 0)
293 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
294 listnode_add(addr
->ifp_name_list
, name
);
298 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
302 struct bgp_addr
*addr
;
303 struct listnode
*node
;
306 tmp
.addr
= p
->u
.prefix4
;
308 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
309 /* may have been deleted earlier by bgp_interface_down() */
313 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
314 if (strcmp(ifc
->ifp
->name
, name
) == 0)
319 list_delete_node(addr
->ifp_name_list
, node
);
320 XFREE(MTYPE_MARTIAN_STRING
, name
);
323 if (addr
->ifp_name_list
->count
== 0) {
324 hash_release(bgp
->address_hash
, addr
);
325 list_delete(&addr
->ifp_name_list
);
326 XFREE(MTYPE_BGP_ADDR
, addr
);
331 struct bgp_connected_ref
{
335 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
340 struct bgp_connected_ref
*bc
;
341 struct listnode
*node
, *nnode
;
346 p
= *(CONNECTED_PREFIX(ifc
));
347 if (addr
->family
== AF_INET
) {
348 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
350 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
353 bgp_address_add(bgp
, ifc
, addr
);
355 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP
],
356 (struct prefix
*)&p
);
357 bc
= bgp_node_get_bgp_connected_ref_info(rn
);
361 bc
= XCALLOC(MTYPE_BGP_CONN
,
362 sizeof(struct bgp_connected_ref
));
364 bgp_node_set_bgp_connected_ref_info(rn
, bc
);
367 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
369 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
370 && peer
->status
!= Established
371 && !CHECK_FLAG(peer
->flags
,
372 PEER_FLAG_IFPEER_V6ONLY
)) {
373 if (peer_active(peer
))
374 BGP_EVENT_ADD(peer
, BGP_Stop
);
375 BGP_EVENT_ADD(peer
, BGP_Start
);
378 } else if (addr
->family
== AF_INET6
) {
379 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
381 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
384 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
387 bgp_ipv6_address_add(bgp
, ifc
, addr
);
389 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP6
],
390 (struct prefix
*)&p
);
392 bc
= bgp_node_get_bgp_connected_ref_info(rn
);
396 bc
= XCALLOC(MTYPE_BGP_CONN
,
397 sizeof(struct bgp_connected_ref
));
399 bgp_node_set_bgp_connected_ref_info(rn
, bc
);
404 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
408 struct bgp_node
*rn
= NULL
;
409 struct bgp_connected_ref
*bc
;
413 p
= *(CONNECTED_PREFIX(ifc
));
415 if (addr
->family
== AF_INET
) {
416 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
419 bgp_address_del(bgp
, ifc
, addr
);
421 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
422 } else if (addr
->family
== AF_INET6
) {
423 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
426 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
429 bgp_ipv6_address_del(bgp
, ifc
, addr
);
431 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
],
432 (struct prefix
*)&p
);
438 bc
= bgp_node_get_bgp_connected_ref_info(rn
);
440 if (bc
->refcnt
== 0) {
441 XFREE(MTYPE_BGP_CONN
, bc
);
442 bgp_node_set_bgp_connected_ref_info(rn
, NULL
);
448 static void bgp_connected_cleanup(struct route_table
*table
,
449 struct route_node
*rn
)
451 struct bgp_connected_ref
*bc
;
452 struct bgp_node
*bn
= bgp_node_from_rnode(rn
);
454 bc
= bgp_node_get_bgp_connected_ref_info(bn
);
459 if (bc
->refcnt
== 0) {
460 XFREE(MTYPE_BGP_CONN
, bc
);
461 bgp_node_set_bgp_connected_ref_info(bn
, NULL
);
465 int bgp_nexthop_self(struct bgp
*bgp
, struct in_addr nh_addr
)
467 struct bgp_addr tmp
, *addr
;
468 struct tip_addr tmp_tip
, *tip
;
472 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
476 tmp_tip
.addr
= nh_addr
;
477 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
484 int bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
486 struct bgp_node
*rn1
;
487 struct bgp_node
*rn2
;
492 p
.prefixlen
= IPV4_MAX_BITLEN
;
493 p
.u
.prefix4
= nexthop
;
495 rn1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
500 p
.prefixlen
= IPV4_MAX_BITLEN
;
501 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
503 rn2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
505 bgp_unlock_node(rn1
);
509 ret
= (rn1
== rn2
) ? 1 : 0;
511 bgp_unlock_node(rn1
);
512 bgp_unlock_node(rn2
);
517 int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
518 struct update_subgroup
*subgrp
)
520 struct bgp_node
*rn1
, *rn2
;
526 np
.prefixlen
= IPV4_MAX_BITLEN
;
527 np
.u
.prefix4
= nexthop
;
530 p
.prefixlen
= IPV4_MAX_BITLEN
;
532 bgp
= SUBGRP_INST(subgrp
);
533 rn1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
537 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
538 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
540 rn2
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &p
);
542 bgp_unlock_node(rn1
);
543 bgp_unlock_node(rn2
);
548 bgp_unlock_node(rn2
);
551 bgp_unlock_node(rn1
);
555 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
556 struct bgp_nexthop_cache
*bnc
)
558 char buf
[PREFIX2STR_BUFFER
];
559 struct nexthop
*nexthop
;
561 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
562 switch (nexthop
->type
) {
563 case NEXTHOP_TYPE_IPV6
:
564 vty_out(vty
, " gate %s\n",
565 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
568 case NEXTHOP_TYPE_IPV6_IFINDEX
:
569 vty_out(vty
, " gate %s, if %s\n",
570 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
572 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
574 case NEXTHOP_TYPE_IPV4
:
575 vty_out(vty
, " gate %s\n",
576 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
579 case NEXTHOP_TYPE_IFINDEX
:
580 vty_out(vty
, " if %s\n",
581 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
583 case NEXTHOP_TYPE_IPV4_IFINDEX
:
584 vty_out(vty
, " gate %s, if %s\n",
585 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
587 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
589 case NEXTHOP_TYPE_BLACKHOLE
:
590 vty_out(vty
, " blackhole\n");
593 vty_out(vty
, " invalid nexthop type %u\n",
598 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
, int detail
,
602 struct bgp_nexthop_cache
*bnc
;
603 char buf
[PREFIX2STR_BUFFER
];
606 struct bgp_table
**table
;
609 vty_out(vty
, "Current BGP import check cache:\n");
611 vty_out(vty
, "Current BGP nexthop cache:\n");
613 table
= bgp
->import_check_table
;
615 table
= bgp
->nexthop_cache_table
;
616 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
617 if (!table
|| !table
[afi
])
619 for (rn
= bgp_table_top(table
[afi
]); rn
;
620 rn
= bgp_route_next(rn
)) {
621 bnc
= bgp_node_get_bgp_nexthop_info(rn
);
625 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
627 " %s valid [IGP metric %d], #paths %d\n",
628 inet_ntop(rn
->p
.family
,
629 &rn
->p
.u
.prefix
, buf
,
631 bnc
->metric
, bnc
->path_count
);
636 bgp_show_nexthops_detail(vty
, bgp
, bnc
);
639 vty_out(vty
, " %s invalid\n",
640 inet_ntop(rn
->p
.family
,
641 &rn
->p
.u
.prefix
, buf
,
643 if (CHECK_FLAG(bnc
->flags
,
644 BGP_NEXTHOP_CONNECTED
))
645 vty_out(vty
, " Must be Connected\n");
646 if (!CHECK_FLAG(bnc
->flags
,
647 BGP_NEXTHOP_REGISTERED
))
648 vty_out(vty
, " Is not Registered\n");
650 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
651 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
657 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
658 int detail
, bool import_table
)
663 bgp
= bgp_lookup_by_name(name
);
665 bgp
= bgp_get_default();
667 vty_out(vty
, "%% No such BGP instance exist\n");
671 bgp_show_nexthops(vty
, bgp
, detail
, import_table
);
676 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
)
678 struct listnode
*node
, *nnode
;
681 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
682 vty_out(vty
, "\nInstance %s:\n",
683 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
686 bgp_show_nexthops(vty
, bgp
, 0, false);
690 DEFUN (show_ip_bgp_nexthop
,
691 show_ip_bgp_nexthop_cmd
,
692 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
696 BGP_INSTANCE_HELP_STR
697 "BGP nexthop table\n"
698 "Show detailed information\n")
703 if (argv_find(argv
, argc
, "view", &idx
)
704 || argv_find(argv
, argc
, "vrf", &idx
))
705 vrf
= argv
[++idx
]->arg
;
706 int detail
= argv_find(argv
, argc
, "detail", &idx
) ? 1 : 0;
708 return show_ip_bgp_nexthop_table(vty
, vrf
, detail
, false);
711 DEFUN (show_ip_bgp_import_check
,
712 show_ip_bgp_import_check_cmd
,
713 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
717 BGP_INSTANCE_HELP_STR
718 "BGP import check table\n"
719 "Show detailed information\n")
724 if (argv_find(argv
, argc
, "view", &idx
)
725 || argv_find(argv
, argc
, "vrf", &idx
))
726 vrf
= argv
[++idx
]->arg
;
727 int detail
= argv_find(argv
, argc
, "detail", &idx
) ? 1 : 0;
728 return show_ip_bgp_nexthop_table(vty
, vrf
, detail
, true);
731 DEFUN (show_ip_bgp_instance_all_nexthop
,
732 show_ip_bgp_instance_all_nexthop_cmd
,
733 "show [ip] bgp <view|vrf> all nexthop",
737 BGP_INSTANCE_ALL_HELP_STR
738 "BGP nexthop table\n")
740 bgp_show_all_instances_nexthops_vty(vty
);
744 void bgp_scan_init(struct bgp
*bgp
)
748 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
749 bgp
->nexthop_cache_table
[afi
] =
750 bgp_table_init(bgp
, afi
, SAFI_UNICAST
);
751 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
753 bgp
->import_check_table
[afi
] =
754 bgp_table_init(bgp
, afi
, SAFI_UNICAST
);
758 void bgp_scan_vty_init(void)
760 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
761 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
762 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
765 void bgp_scan_finish(struct bgp
*bgp
)
769 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
770 /* Only the current one needs to be reset. */
771 bgp_nexthop_cache_reset(bgp
->nexthop_cache_table
[afi
]);
772 bgp_table_unlock(bgp
->nexthop_cache_table
[afi
]);
773 bgp
->nexthop_cache_table
[afi
] = NULL
;
775 bgp
->connected_table
[afi
]->route_table
->cleanup
=
776 bgp_connected_cleanup
;
777 bgp_table_unlock(bgp
->connected_table
[afi
]);
778 bgp
->connected_table
[afi
] = NULL
;
780 bgp_table_unlock(bgp
->import_check_table
[afi
]);
781 bgp
->import_check_table
[afi
] = NULL
;
785 static void *bgp_ipv6_address_hash_alloc(void *p
)
787 const struct in6_addr
*v6addr
= (const struct in6_addr
*)p
;
788 struct bgp_addrv6
*addr
;
790 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addrv6
));
791 addr
->addrv6
= *v6addr
;
793 addr
->ifp_name_list
= list_new();
794 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
799 static void bgp_ipv6_address_hash_free(void *data
)
801 struct bgp_addrv6
*v6addr
= data
;
803 list_delete(&v6addr
->ifp_name_list
);
804 XFREE(MTYPE_BGP_ADDR
, v6addr
);
807 static unsigned int bgp_ipv6_address_hash_key_make(void *p
)
809 const struct bgp_addrv6
*v6
= p
;
811 return __ipv6_addr_jhash(&v6
->addrv6
, 0);
814 static bool bgp_ipv6_address_hash_cmp(const void *p1
,
817 const struct bgp_addrv6
*addr1
= p1
;
818 const struct bgp_addrv6
*addr2
= p2
;
820 return(!memcmp(&addr1
->addrv6
, &addr2
->addrv6
,
821 sizeof(struct in6_addr
)));
824 void bgp_ipv6_address_init(struct bgp
*bgp
)
826 bgp
->ipv6_address_hash
= hash_create(bgp_ipv6_address_hash_key_make
,
827 bgp_ipv6_address_hash_cmp
,
828 "BGP IPV6 Address Hash");
831 void bgp_ipv6_address_destroy(struct bgp
*bgp
)
833 if (bgp
->ipv6_address_hash
== NULL
)
835 hash_clean(bgp
->ipv6_address_hash
,
836 bgp_ipv6_address_hash_free
);
838 hash_free(bgp
->ipv6_address_hash
);
839 bgp
->ipv6_address_hash
= NULL
;
842 static void bgp_ipv6_address_add(struct bgp
*bgp
, struct connected
*ifc
,
845 struct bgp_addrv6 tmp
= {0};
846 struct bgp_addrv6
*addr
= NULL
;
847 struct listnode
*node
= NULL
;
850 tmp
.addrv6
= p
->u
.prefix6
;
852 addr
= hash_get(bgp
->ipv6_address_hash
, &tmp
,
853 bgp_ipv6_address_hash_alloc
);
857 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
858 if (strcmp(ifc
->ifp
->name
, name
) == 0)
863 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
864 listnode_add(addr
->ifp_name_list
, name
);
869 static void bgp_ipv6_address_del(struct bgp
*bgp
, struct connected
*ifc
,
872 struct bgp_addrv6 tmp
;
873 struct bgp_addrv6
*addr
;
874 struct listnode
*node
;
878 tmp
.addrv6
= p
->u
.prefix6
;
880 addr
= hash_lookup(bgp
->ipv6_address_hash
, &tmp
);
881 /* may have been deleted earlier by bgp_interface_down() */
885 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
886 if (strcmp(ifc
->ifp
->name
, name
) == 0)
891 list_delete_node(addr
->ifp_name_list
, node
);
892 XFREE(MTYPE_MARTIAN_STRING
, name
);
895 if (addr
->ifp_name_list
->count
== 0) {
896 hash_release(bgp
->ipv6_address_hash
, addr
);
897 list_delete(&addr
->ifp_name_list
);
898 XFREE(MTYPE_BGP_ADDR
, addr
);
901 int bgp_nexthop_self_ipv6(struct bgp
*bgp
, struct in6_addr
*addr
)
903 struct bgp_addrv6 tmp
;
906 return (!!hash_lookup(bgp
->ipv6_address_hash
, &tmp
));