📄 bgp_route.c
字号:
/* If community is not disabled check the no-export and local. */ if (! transparent && bgp_community_filter (peer, ri->attr)) return 0; /* If the attribute has originator-id and it is same as remote peer's id. */ if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) { if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->originator_id)) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_INFO, "%s [Update:SEND] %s/%d originator-id is same as remote router-id", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); return 0; } } /* ORF prefix-list filter check */ if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))) if (peer->orf_plist[afi][safi]) { if (prefix_list_apply (peer->orf_plist[afi][safi], p) == PREFIX_DENY) return 0; } /* Output filter check. */ if (bgp_output_filter (peer, p, ri->attr, afi, safi) == FILTER_DENY) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_INFO, "%s [Update:SEND] %s/%d is filtered", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); return 0; }#ifdef BGP_SEND_ASPATH_CHECK /* AS path loop check. */ if (aspath_loop_check (ri->attr->aspath, peer->as)) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_INFO, "%s [Update:SEND] suppress announcement to peer AS %d is AS path.", peer->host, peer->as); return 0; }#endif /* BGP_SEND_ASPATH_CHECK */ /* If we're a CONFED we need to loop check the CONFED ID too */ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { if (aspath_loop_check(ri->attr->aspath, bgp->confed_id)) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_INFO, "%s [Update:SEND] suppress announcement to peer AS %d is AS path.", peer->host, bgp->confed_id); return 0; } } /* Route-Reflect check. */ if (peer_sort (from) == BGP_PEER_IBGP && peer_sort (peer) == BGP_PEER_IBGP) reflect = 1; else reflect = 0; /* IBGP reflection check. */ if (reflect) { /* A route from a Client peer. */ if (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) { /* Reflect to all the Non-Client peers and also to the Client peers other than the originator. Originator check is already done. So there is noting to do. */ /* no bgp client-to-client reflection check. */ if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) return 0; } else { /* A route from a Non-client peer. Reflect to all other clients. */ if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) return 0; } } /* For modify attribute, copy it to temporary structure. */ *attr = *ri->attr; /* If local-preference is not set. */ if ((peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED) && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))) { attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); attr->local_pref = bgp->default_local_pref; } /* Remove MED if its an EBGP peer - will get overwritten by route-maps */ if (peer_sort (peer) == BGP_PEER_EBGP && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) { if (ri->peer != bgp->peer_self && ! transparent && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)); } /* next-hop-set */ if (transparent || reflect || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) && ((p->family == AF_INET && attr->nexthop.s_addr)#ifdef HAVE_IPV6 || (p->family == AF_INET6 && ri->peer != bgp->peer_self)#endif /* HAVE_IPV6 */ ))) { /* NEXT-HOP Unchanged. */ } else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) || (p->family == AF_INET && attr->nexthop.s_addr == 0)#ifdef HAVE_IPV6 || (p->family == AF_INET6 && ri->peer == bgp->peer_self)#endif /* HAVE_IPV6 */ || (peer_sort (peer) == BGP_PEER_EBGP && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0)) { /* Set IPv4 nexthop. */ if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) memcpy (&attr->mp_nexthop_global_in, &peer->nexthop.v4, IPV4_MAX_BYTELEN); else memcpy (&attr->nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN); }#ifdef HAVE_IPV6 /* Set IPv6 nexthop. */ if (p->family == AF_INET6) { /* IPv6 global nexthop must be included. */ memcpy (&attr->mp_nexthop_global, &peer->nexthop.v6_global, IPV6_MAX_BYTELEN); attr->mp_nexthop_len = 16; }#endif /* HAVE_IPV6 */ }#ifdef HAVE_IPV6 if (p->family == AF_INET6) { /* Link-local address should not be transit to different peer. */ attr->mp_nexthop_len = 16; /* Set link-local address for shared network peer. */ if (peer->shared_network && ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) { memcpy (&attr->mp_nexthop_local, &peer->nexthop.v6_local, IPV6_MAX_BYTELEN); attr->mp_nexthop_len = 32; } /* If bgpd act as BGP-4+ route-reflector, do not send link-local address.*/ if (reflect) attr->mp_nexthop_len = 16; /* If BGP-4+ link-local nexthop is not link-local nexthop. */ if (! IN6_IS_ADDR_LINKLOCAL (&peer->nexthop.v6_local)) attr->mp_nexthop_len = 16; }#endif /* HAVE_IPV6 */ /* If this is EBGP peer and remove-private-AS is set. */ if (peer_sort (peer) == BGP_PEER_EBGP && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && aspath_private_as_check (attr->aspath)) attr->aspath = aspath_empty_get (); /* Route map & unsuppress-map apply. */ if (ROUTE_MAP_OUT_NAME (filter) || ri->suppress) { info.peer = peer; info.attr = attr; /* The route reflector is not allowed to modify the attributes of the reflected IBGP routes. */ if (peer_sort (from) == BGP_PEER_IBGP && peer_sort (peer) == BGP_PEER_IBGP) { dummy_attr = *attr; info.attr = &dummy_attr; } SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); if (ri->suppress) ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); else ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); peer->rmap_type = 0; if (ret == RMAP_DENYMATCH) { bgp_attr_flush (attr); return 0; } } return 1;}intbgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi){ struct prefix *p; struct bgp_info *ri; struct bgp_info *new_select; struct bgp_info *old_select; struct listnode *nn; struct peer *peer; struct attr attr; struct bgp_info *ri1; struct bgp_info *ri2; p = &rn->p; /* bgp deterministic-med */ new_select = NULL; if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) for (ri1 = rn->info; ri1; ri1 = ri1->next) { if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK)) continue; if (BGP_INFO_HOLDDOWN (ri1)) continue; new_select = ri1; if (ri1->next) for (ri2 = ri1->next; ri2; ri2 = ri2->next) { if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK)) continue; if (BGP_INFO_HOLDDOWN (ri2)) continue; if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath) || aspath_cmp_left_confed (ri1->attr->aspath, ri2->attr->aspath)) { if (bgp_info_cmp (bgp, ri2, new_select)) { UNSET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED); new_select = ri2; } SET_FLAG (ri2->flags, BGP_INFO_DMED_CHECK); } } SET_FLAG (new_select->flags, BGP_INFO_DMED_CHECK); SET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED); } /* Check old selected route and new selected route. */ old_select = NULL; new_select = NULL; for (ri = rn->info; ri; ri = ri->next) { if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) old_select = ri; if (BGP_INFO_HOLDDOWN (ri)) continue; if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED))) { UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK); continue; } UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK); UNSET_FLAG (ri->flags, BGP_INFO_DMED_SELECTED); if (bgp_info_cmp (bgp, ri, new_select)) new_select = ri; } /* Nothing to do. */ if (old_select && old_select == new_select) { if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED)) { if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED)) bgp_zebra_announce (p, old_select, bgp); return 0; } } if (old_select) UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED); if (new_select) { SET_FLAG (new_select->flags, BGP_INFO_SELECTED); UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED); } /* Check each BGP peer. */ LIST_LOOP (bgp->peer, peer, nn) { /* Announce route to Established peer. */ if (peer->status != Established) continue; /* Address family configuration check. */ if (! peer->afc_nego[afi][safi]) continue; /* First update is deferred until ORF or ROUTE-REFRESH is received */ if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) continue; /* Announcement to peer->conf. If the route is filtered, withdraw it. */ if (new_select && bgp_announce_check (new_select, peer, p, &attr, afi, safi)) bgp_adj_out_set (rn, peer, p, &attr, afi, safi, new_select); else bgp_adj_out_unset (rn, peer, p, afi, safi); } /* FIB update. */ if (safi == SAFI_UNICAST && ! bgp->name && ! bgp_option_check (BGP_OPT_NO_FIB)) { if (new_select && new_select->type == ZEBRA_ROUTE_BGP && new_select->sub_type == BGP_ROUTE_NORMAL) bgp_zebra_announce (p, new_select, bgp); else { /* Withdraw the route from the kernel. */ if (old_select && old_select->type == ZEBRA_ROUTE_BGP && old_select->sub_type == BGP_ROUTE_NORMAL) bgp_zebra_withdraw (p, old_select); } } return 0;}intbgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi, int always){ if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) return 0; if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) { if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT) && ! always) return 0; zlog (peer->log, LOG_INFO, "%%MAXPFXEXCEED: No. of prefix received from %s (afi %d): %ld exceed limit %ld", peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]); SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) return 0; { char ndata[7]; ndata[0] = (u_char)(afi >> 8); ndata[1] = (u_char) afi; ndata[3] = (u_char)(peer->pmax[afi][safi] >> 24); ndata[4] = (u_char)(peer->pmax[afi][safi] >> 16); ndata[5] = (u_char)(peer->pmax[afi][safi] >> 8); ndata[6] = (u_char)(peer->pmax[afi][safi]); if (safi == SAFI_MPLS_VPN) safi = BGP_SAFI_VPNV4; ndata[2] = (u_char) safi; SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7); } return 1; } else UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); if (peer->pcount[afi][safi] > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) { if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD) && ! always) return 0; zlog (peer->log, LOG_INFO, "%%MAXPFX: No. of prefix received from %s (afi %d) reaches %ld, max %ld", peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]); SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); } else UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); return 0;}voidbgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, afi_t afi, safi_t safi){ if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) { peer->pcount[afi][safi]--; bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); UNSET_FLAG (ri->flags, BGP_INFO_VALID); bgp_process (peer->bgp, rn, afi, safi); } bgp_info_delete (rn, ri); bgp_info_free (ri); bgp_unlock_node (rn);}voidbgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, afi_t afi, safi_t safi, int force){ int valid; int status = BGP_DAMP_NONE; if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) { peer->pcount[afi][safi]--; bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); } if (! force) { if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer_sort (peer) == BGP_PEER_EBGP) status = bgp_damp_withdraw (ri, rn, afi, safi, 0); if (status == BGP_DAMP_SUPPRESSED) return; } valid = CHECK_FLAG (ri->flags, BGP_INFO_VALID); UNSET_FLAG (ri->flags, BGP_INFO_VALID); bgp_process (peer->bgp, rn, afi, safi); if (valid) SET_FLAG (ri->flags, BGP_INFO_VALID); if (status != BGP_DAMP_USED) { bgp_info_delete (rn, ri); bgp_info_free (ri); bgp_unlock_node (rn); }}intbgp_update (struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type, struct prefix_rd *prd, u_char *tag, int soft_reconfig){ int ret; int aspath_loop_count = 0; struct bgp_node *rn; struct bgp *bgp; struct attr new_attr; struct attr *attr_new; struct bgp_info *ri; struct bgp_info *new; char *reason; char buf[SU_ADDRSTRLEN]; bgp = peer->bgp; rn = bgp_afi_node_get (bgp, afi, safi, p, prd); /* When peer's soft reconfiguration enabled. Record input packet in Adj-RIBs-In. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) && peer != bgp->peer_self && ! soft_reconfig) bgp_adj_in_set (rn, peer, attr); /* Check previously received route. */ for (ri = rn->info; ri; ri = ri->next) if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -