📄 bgp_route.c
字号:
/* BGP routing information Copyright (C) 1996, 97, 98, 99 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 "prefix.h"#include "linklist.h"#include "memory.h"#include "command.h"#include "stream.h"#include "filter.h"#include "str.h"#include "log.h"#include "routemap.h"#include "buffer.h"#include "sockunion.h"#include "plist.h"#include "thread.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_table.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_aspath.h"#include "bgpd/bgp_regex.h"#include "bgpd/bgp_community.h"#include "bgpd/bgp_ecommunity.h"#include "bgpd/bgp_clist.h"#include "bgpd/bgp_packet.h"#include "bgpd/bgp_filter.h"#include "bgpd/bgp_fsm.h"#include "bgpd/bgp_mplsvpn.h"#include "bgpd/bgp_nexthop.h"#include "bgpd/bgp_damp.h"#include "bgpd/bgp_advertise.h"#include "bgpd/bgp_zebra.h"/* Extern from bgp_dump.c */extern char *bgp_origin_str[];extern char *bgp_origin_long_str[];struct bgp_node *bgp_afi_node_get (struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p, struct prefix_rd *prd){ struct bgp_node *rn; struct bgp_node *prn = NULL; struct bgp_table *table; if (safi == SAFI_MPLS_VPN) { prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd); if (prn->info == NULL) prn->info = bgp_table_init (); else bgp_unlock_node (prn); table = prn->info; } else table = bgp->rib[afi][safi]; rn = bgp_node_get (table, p); if (safi == SAFI_MPLS_VPN) rn->prn = prn; return rn;}/* Allocate new bgp info structure. */struct bgp_info *bgp_info_new (){ struct bgp_info *new; new = XMALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); memset (new, 0, sizeof (struct bgp_info)); return new;}/* Free bgp route information. */voidbgp_info_free (struct bgp_info *binfo){ if (binfo->attr) bgp_attr_unintern (binfo->attr); if (binfo->damp_info) bgp_damp_info_free (binfo->damp_info, 0); XFREE (MTYPE_BGP_ROUTE, binfo);}voidbgp_info_add (struct bgp_node *rn, struct bgp_info *ri){ struct bgp_info *top; top = rn->info; ri->next = rn->info; ri->prev = NULL; if (top) top->prev = ri; rn->info = ri;}voidbgp_info_delete (struct bgp_node *rn, struct bgp_info *ri){ if (ri->next) ri->next->prev = ri->prev; if (ri->prev) ri->prev->next = ri->next; else rn->info = ri->next;}/* Get MED value. If MED value is missing and "bgp bestpath missing-as-worst" is specified, treat it as the worst value. */u_int32_tbgp_med_value (struct attr *attr, struct bgp *bgp){ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) return attr->med; else { if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) return 4294967295ul; else return 0; }}/* Compare two bgp route entity. br is preferable then return 1. */intbgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist){ u_int32_t new_pref; u_int32_t exist_pref; u_int32_t new_med; u_int32_t exist_med; struct in_addr new_id; struct in_addr exist_id; int new_cluster; int exist_cluster; int internal_as_route = 0; int confed_as_route = 0; int ret; /* 0. Null check. */ if (new == NULL) return 0; if (exist == NULL) return 1; /* 1. Weight check. */ if (new->attr->weight > exist->attr->weight) return 1; if (new->attr->weight < exist->attr->weight) return 0; /* 2. Local preference check. */ if (new->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) new_pref = new->attr->local_pref; else new_pref = bgp->default_local_pref; if (exist->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) exist_pref = exist->attr->local_pref; else exist_pref = bgp->default_local_pref; if (new_pref > exist_pref) return 1; if (new_pref < exist_pref) return 0; /* 3. Local route check. */ if (new->sub_type == BGP_ROUTE_STATIC) return 1; if (exist->sub_type == BGP_ROUTE_STATIC) return 0; if (new->sub_type == BGP_ROUTE_REDISTRIBUTE) return 1; if (exist->sub_type == BGP_ROUTE_REDISTRIBUTE) return 0; if (new->sub_type == BGP_ROUTE_AGGREGATE) return 1; if (exist->sub_type == BGP_ROUTE_AGGREGATE) return 0; /* 4. AS path length check. */ if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE)) { if (new->attr->aspath->count < exist->attr->aspath->count) return 1; if (new->attr->aspath->count > exist->attr->aspath->count) return 0; } /* 5. Origin check. */ if (new->attr->origin < exist->attr->origin) return 1; if (new->attr->origin > exist->attr->origin) return 0; /* 6. MED check. */ internal_as_route = (new->attr->aspath->length == 0 && exist->attr->aspath->length == 0); confed_as_route = (new->attr->aspath->length > 0 && exist->attr->aspath->length > 0 && new->attr->aspath->count == 0 && exist->attr->aspath->count == 0); if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED) || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) && confed_as_route) || aspath_cmp_left (new->attr->aspath, exist->attr->aspath) || aspath_cmp_left_confed (new->attr->aspath, exist->attr->aspath) || internal_as_route) { new_med = bgp_med_value (new->attr, bgp); exist_med = bgp_med_value (exist->attr, bgp); if (new_med < exist_med) return 1; if (new_med > exist_med) return 0; } /* 7. Peer type check. */ if (peer_sort (new->peer) == BGP_PEER_EBGP && peer_sort (exist->peer) == BGP_PEER_IBGP) return 1; if (peer_sort (new->peer) == BGP_PEER_EBGP && peer_sort (exist->peer) == BGP_PEER_CONFED) return 1; if (peer_sort (new->peer) == BGP_PEER_IBGP && peer_sort (exist->peer) == BGP_PEER_EBGP) return 0; if (peer_sort (new->peer) == BGP_PEER_CONFED && peer_sort (exist->peer) == BGP_PEER_EBGP) return 0; /* 8. IGP metric check. */ if (new->igpmetric < exist->igpmetric) return 1; if (new->igpmetric > exist->igpmetric) return 0; /* 9. Maximum path check. */ /* 10. If both paths are external, prefer the path that was received first (the oldest one). This step minimizes route-flap, since a newer path won't displace an older one, even if it was the preferred route based on the additional decision criteria below. */ if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID) && peer_sort (new->peer) == BGP_PEER_EBGP && peer_sort (exist->peer) == BGP_PEER_EBGP) { if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED)) return 1; if (CHECK_FLAG (exist->flags, BGP_INFO_SELECTED)) return 0; } /* 11. Rourter-ID comparision. */ if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) new_id.s_addr = new->attr->originator_id.s_addr; else new_id.s_addr = new->peer->remote_id.s_addr; if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) exist_id.s_addr = exist->attr->originator_id.s_addr; else exist_id.s_addr = exist->peer->remote_id.s_addr; if (ntohl (new_id.s_addr) < ntohl (exist_id.s_addr)) return 1; if (ntohl (new_id.s_addr) > ntohl (exist_id.s_addr)) return 0; /* 12. Cluster length comparision. */ if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) new_cluster = new->attr->cluster->length; else new_cluster = 0; if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) exist_cluster = exist->attr->cluster->length; else exist_cluster = 0; if (new_cluster < exist_cluster) return 1; if (new_cluster > exist_cluster) return 0; /* 13. Neighbor address comparision. */ ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote); if (ret == 1) return 0; if (ret == -1) return 1; return 1;}enum filter_typebgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi){ struct bgp_filter *filter; filter = &peer->filter[afi][safi]; if (DISTRIBUTE_IN_NAME (filter)) if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY) return FILTER_DENY; if (PREFIX_LIST_IN_NAME (filter)) if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY) return FILTER_DENY; if (FILTER_LIST_IN_NAME (filter)) if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY) return FILTER_DENY; return FILTER_PERMIT;}enum filter_typebgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi){ struct bgp_filter *filter; filter = &peer->filter[afi][safi]; if (DISTRIBUTE_OUT_NAME (filter)) if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY) return FILTER_DENY; if (PREFIX_LIST_OUT_NAME (filter)) if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY) return FILTER_DENY; if (FILTER_LIST_OUT_NAME (filter)) if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY) return FILTER_DENY; return FILTER_PERMIT;}/* If community attribute includes no_export then return 1. */intbgp_community_filter (struct peer *peer, struct attr *attr){ if (attr->community) { /* NO_ADVERTISE check. */ if (community_include (attr->community, COMMUNITY_NO_ADVERTISE)) return 1; /* NO_EXPORT check. */ if (peer_sort (peer) == BGP_PEER_EBGP && community_include (attr->community, COMMUNITY_NO_EXPORT)) return 1; /* NO_EXPORT_SUBCONFED check. */ if (peer_sort (peer) == BGP_PEER_EBGP || peer_sort (peer) == BGP_PEER_CONFED) if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED)) return 1; } return 0;}/* Route reflection loop check. */static intbgp_cluster_filter (struct peer *peer, struct attr *attr){ struct in_addr cluster_id; if (attr->cluster) { if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) cluster_id = peer->bgp->cluster_id; else cluster_id = peer->bgp->router_id; if (cluster_loop_check (attr->cluster, cluster_id)) return 1; } return 0;}intbgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi){ struct bgp_filter *filter; struct bgp_info info; route_map_result_t ret; filter = &peer->filter[afi][safi]; /* Apply default weight value. */ attr->weight = peer->weight; /* Route map apply. */ if (ROUTE_MAP_IN_NAME (filter)) { /* Duplicate current value to new strucutre for modification. */ info.peer = peer; info.attr = attr; SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN); /* Apply BGP route map to the attribute. */ ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info); peer->rmap_type = 0; if (ret == RMAP_DENYMATCH) { /* Free newly generated AS path and community by route-map. */ bgp_attr_flush (attr); return RMAP_DENY; } } return RMAP_PERMIT;}intbgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi){ int ret; char buf[SU_ADDRSTRLEN]; struct bgp_filter *filter; struct bgp_info info; struct peer *from; struct bgp *bgp; struct attr dummy_attr; int transparent; int reflect; from = ri->peer; filter = &peer->filter[afi][safi]; bgp = peer->bgp; #ifdef DISABLE_BGP_ANNOUNCE return 0;#endif /* Do not send back route to sender. */ if (from == peer) return 0; /* Aggregate-address suppress check. */ if (ri->suppress) if (! UNSUPPRESS_MAP_NAME (filter)) return 0; /* Default route check. */ if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE)) { if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY) return 0;#ifdef HAVE_IPV6 else if (p->family == AF_INET6 && p->prefixlen == 0) return 0;#endif /* HAVE_IPV6 */ } /* Transparency check. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) && CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) transparent = 1; else transparent = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -