📄 bgp_nexthop.c
字号:
/* BGP nexthop scan Copyright (C) 2000 Kunihiro IshiguroThis file is part of GNU Zebra.GNU Zebra is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.GNU Zebra is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Zebra; see the file COPYING. If not, write to the FreeSoftware Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. */#include <zebra.h>#include "command.h"#include "thread.h"#include "prefix.h"#include "zclient.h"#include "stream.h"#include "network.h"#include "log.h"#include "memory.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_table.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_nexthop.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_damp.h"#include "zebra/rib.h"#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */struct bgp_nexthop_cache *zlookup_query (struct in_addr);#ifdef HAVE_IPV6struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);#endif /* HAVE_IPV6 *//* Only one BGP scan thread are activated at the same time. */struct thread *bgp_scan_thread = NULL;/* BGP import thread */struct thread *bgp_import_thread = NULL;/* BGP scan interval. */int bgp_scan_interval;/* BGP import interval. */int bgp_import_interval;/* Route table for next-hop lookup cache. */struct bgp_table *bgp_nexthop_cache_ipv4;struct bgp_table *cache1;struct bgp_table *cache2;/* Route table for next-hop lookup cache. */struct bgp_table *bgp_nexthop_cache_ipv6;struct bgp_table *cache6_1;struct bgp_table *cache6_2;/* Route table for connected route. */struct bgp_table *bgp_connected_ipv4;/* Route table for connected route. */struct bgp_table *bgp_connected_ipv6;/* BGP nexthop lookup query client. */static struct zclient *zlookup = NULL;/* BGP process function. */int bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);/* Add nexthop to the end of the list. */voidbnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop){ struct nexthop *last; for (last = bnc->nexthop; last && last->next; last = last->next) ; if (last) last->next = nexthop; else bnc->nexthop = nexthop; nexthop->prev = last;}voidbnc_nexthop_free (struct bgp_nexthop_cache *bnc){ struct nexthop *nexthop; struct nexthop *next = NULL; for (nexthop = bnc->nexthop; nexthop; nexthop = next) { next = nexthop->next; XFREE (MTYPE_NEXTHOP, nexthop); }}struct bgp_nexthop_cache *bnc_new (){ struct bgp_nexthop_cache *new; new = XMALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache)); memset (new, 0, sizeof (struct bgp_nexthop_cache)); return new;}voidbnc_free (struct bgp_nexthop_cache *bnc){ bnc_nexthop_free (bnc); XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);}intbgp_nexthop_same (struct nexthop *next1, struct nexthop *next2){ if (next1->type != next2->type) return 0; switch (next1->type) { case ZEBRA_NEXTHOP_IPV4: if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)) return 0; break; case ZEBRA_NEXTHOP_IFINDEX: case ZEBRA_NEXTHOP_IFNAME: if (next1->ifindex != next2->ifindex) return 0; break;#ifdef HAVE_IPV6 case ZEBRA_NEXTHOP_IPV6: if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) return 0; break; case ZEBRA_NEXTHOP_IPV6_IFINDEX: case ZEBRA_NEXTHOP_IPV6_IFNAME: if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) return 0; if (next1->ifindex != next2->ifindex) return 0; break;#endif /* HAVE_IPV6 */ } return 1;}intbgp_nexthop_cache_changed (struct bgp_nexthop_cache *bnc1, struct bgp_nexthop_cache *bnc2){ int i; struct nexthop *next1, *next2; if (bnc1->nexthop_num != bnc2->nexthop_num) return 1; next1 = bnc1->nexthop; next2 = bnc2->nexthop; for (i = 0; i < bnc1->nexthop_num; i++) { if (! bgp_nexthop_same (next1, next2)) return 1; next1 = next1->next; next2 = next2->next; } return 0;}/* If nexthop exists on connected network return 1. */intbgp_nexthop_check_ebgp (afi_t afi, struct attr *attr){ struct bgp_node *rn; /* If zebra is not enabled return */ if (zlookup->sock < 0) return 1; /* Lookup the address is onlink or not. */ if (afi == AFI_IP) { rn = bgp_node_match_ipv4 (bgp_connected_ipv4, &attr->nexthop); if (rn) { bgp_unlock_node (rn); return 1; } }#ifdef HAVE_IPV6 else if (afi == AFI_IP6) { if (attr->mp_nexthop_len == 32) return 1; else if (attr->mp_nexthop_len == 16) { if (IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global)) return 1; rn = bgp_node_match_ipv6 (bgp_connected_ipv6, &attr->mp_nexthop_global); if (rn) { bgp_unlock_node (rn); return 1; } } }#endif /* HAVE_IPV6 */ return 0;}#ifdef HAVE_IPV6/* Check specified next-hop is reachable or not. */intbgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed, int *metricchanged){ struct bgp_node *rn; struct prefix p; struct bgp_nexthop_cache *bnc; struct attr *attr; /* If lookup is not enabled, return valid. */ if (zlookup->sock < 0) { ri->igpmetric = 0; return 1; } /* Only check IPv6 global address only nexthop. */ attr = ri->attr; if (attr->mp_nexthop_len != 16 || IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global)) return 1; memset (&p, 0, sizeof (struct prefix)); p.family = AF_INET6; p.prefixlen = IPV6_MAX_BITLEN; p.u.prefix6 = attr->mp_nexthop_global; /* IBGP or ebgp-multihop */ rn = bgp_node_get (bgp_nexthop_cache_ipv6, &p); if (rn->info) { bnc = rn->info; bgp_unlock_node (rn); } else { bnc = zlookup_query_ipv6 (&attr->mp_nexthop_global); if (bnc) { struct bgp_table *old; struct bgp_node *oldrn; struct bgp_nexthop_cache *oldbnc; if (changed) { if (bgp_nexthop_cache_ipv6 == cache6_1) old = cache6_2; else old = cache6_1; oldrn = bgp_node_lookup (old, &p); if (oldrn) { oldbnc = oldrn->info; bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc); if (bnc->metric != oldbnc->metric) bnc->metricchanged = 1; } } } else { bnc = bnc_new (); bnc->valid = 0; } rn->info = bnc; } if (changed) *changed = bnc->changed; if (metricchanged) *metricchanged = bnc->metricchanged; if (bnc->valid) ri->igpmetric = bnc->metric; else ri->igpmetric = 0; return bnc->valid;}#endif /* HAVE_IPV6 *//* Check specified next-hop is reachable or not. */intbgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri, int *changed, int *metricchanged){ struct bgp_node *rn; struct prefix p; struct bgp_nexthop_cache *bnc; struct in_addr addr; /* If lookup is not enabled, return valid. */ if (zlookup->sock < 0) { ri->igpmetric = 0; return 1; }#ifdef HAVE_IPV6 if (afi == AFI_IP6) return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);#endif /* HAVE_IPV6 */ addr = ri->attr->nexthop; memset (&p, 0, sizeof (struct prefix)); p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; p.u.prefix4 = addr; /* IBGP or ebgp-multihop */ rn = bgp_node_get (bgp_nexthop_cache_ipv4, &p); if (rn->info) { bnc = rn->info; bgp_unlock_node (rn); } else { bnc = zlookup_query (addr); if (bnc) { struct bgp_table *old; struct bgp_node *oldrn; struct bgp_nexthop_cache *oldbnc; if (changed) { if (bgp_nexthop_cache_ipv4 == cache1) old = cache2; else old = cache1; oldrn = bgp_node_lookup (old, &p); if (oldrn) { oldbnc = oldrn->info; bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc); if (bnc->metric != oldbnc->metric) bnc->metricchanged = 1; } } } else { bnc = bnc_new (); bnc->valid = 0; } rn->info = bnc; } if (changed) *changed = bnc->changed; if (metricchanged) *metricchanged = bnc->metricchanged; if (bnc->valid) ri->igpmetric = bnc->metric; else ri->igpmetric = 0; return bnc->valid;}/* Reset and free all BGP nexthop cache. */voidbgp_nexthop_cache_reset (struct bgp_table *table){ struct bgp_node *rn; struct bgp_nexthop_cache *bnc; for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) if ((bnc = rn->info) != NULL) { bnc_free (bnc); rn->info = NULL; bgp_unlock_node (rn); }}voidbgp_scan_ipv4 (){ struct bgp_node *rn; struct bgp *bgp; struct bgp_info *bi; struct bgp_info *next; struct peer *peer; struct listnode *nn; int valid; int current; int changed; int metricchanged; /* Change cache. */ if (bgp_nexthop_cache_ipv4 == cache1) bgp_nexthop_cache_ipv4 = cache2; else bgp_nexthop_cache_ipv4 = cache1; /* Get default bgp. */ bgp = bgp_get_default (); if (bgp == NULL) return; /* Maximum prefix check */ LIST_LOOP (bgp->peer, peer, nn) { if (peer->status != Established) continue; if (peer->afc[AFI_IP][SAFI_UNICAST]) bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_UNICAST, 1); if (peer->afc[AFI_IP][SAFI_MULTICAST]) bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MULTICAST, 1); if (peer->afc[AFI_IP][SAFI_MPLS_VPN]) bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MPLS_VPN, 1); } for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]); rn; rn = bgp_route_next (rn)) { for (bi = rn->info; bi; bi = next) { next = bi->next; if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL) { changed = 0; metricchanged = 0; if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -