📄 bgp_route.c
字号:
break; /* AS path local-as loop check. */ if (peer->change_local_as) { if (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) aspath_loop_count = 1; if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count) { reason = "as-path contains our own AS;"; goto filtered; } } /* AS path loop check. */ if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi] || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && aspath_loop_check(attr->aspath, bgp->confed_id) > peer->allowas_in[afi][safi])) { reason = "as-path contains our own AS;"; goto filtered; } /* Route reflector originator ID check. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) && IPV4_ADDR_SAME (&bgp->router_id, &attr->originator_id)) { reason = "originator is us;"; goto filtered; } /* Route reflector cluster ID check. */ if (bgp_cluster_filter (peer, attr)) { reason = "reflected from the same cluster;"; goto filtered; } /* Apply incoming filter. */ if (bgp_input_filter (peer, p, attr, afi, safi) == FILTER_DENY) { reason = "filter;"; goto filtered; } /* Apply incoming route-map. */ new_attr = *attr; if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY) { reason = "route-map;"; goto filtered; } /* IPv4 unicast next hop check. */ if (afi == AFI_IP && safi == SAFI_UNICAST) { /* If the peer is EBGP and nexthop is not on connected route, discard it. */ if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1 && ! bgp_nexthop_check_ebgp (afi, &new_attr) && ! CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP)) { reason = "non-connected next-hop;"; goto filtered; } /* Next hop must not be 0.0.0.0 nor Class E address. Next hop must not be my own address. */ if (bgp_nexthop_self (afi, &new_attr) || new_attr.nexthop.s_addr == 0 || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000) { reason = "martian next-hop;"; goto filtered; } } attr_new = bgp_attr_intern (&new_attr); /* If the update is implicit withdraw. */ if (ri) { ri->uptime = time (NULL); /* Same attribute comes in. */ if (attrhash_cmp (ri->attr, attr_new)) { UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer_sort (peer) == BGP_PEER_EBGP && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) { if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "%s rcvd %s/%d", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); peer->pcount[afi][safi]++; ret = bgp_damp_update (ri, rn, afi, safi); if (ret != BGP_DAMP_SUPPRESSED) { bgp_aggregate_increment (bgp, p, ri, afi, safi); bgp_process (bgp, rn, afi, safi); } } else { if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "%s rcvd %s/%d...duplicate ignored", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); } bgp_unlock_node (rn); bgp_attr_unintern (attr_new); return 0; } /* Received Logging. */ if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "%s rcvd %s/%d", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); /* The attribute is changed. */ SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); /* Update bgp route dampening information. */ if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer_sort (peer) == BGP_PEER_EBGP) { /* This is implicit withdraw so we should update dampening information. */ if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) bgp_damp_withdraw (ri, rn, afi, safi, 1); else peer->pcount[afi][safi]++; } bgp_aggregate_decrement (bgp, p, ri, afi, safi); /* Update to new attribute. */ bgp_attr_unintern (ri->attr); ri->attr = attr_new; /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) memcpy (ri->tag, tag, 3); /* Update bgp route dampening information. */ if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer_sort (peer) == BGP_PEER_EBGP) { /* Now we do normal update dampening. */ ret = bgp_damp_update (ri, rn, afi, safi); if (ret == BGP_DAMP_SUPPRESSED) { bgp_unlock_node (rn); return 0; } } /* Nexthop reachability check. */ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST && (peer_sort (peer) == BGP_PEER_IBGP || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))) { if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL)) SET_FLAG (ri->flags, BGP_INFO_VALID); else UNSET_FLAG (ri->flags, BGP_INFO_VALID); } else SET_FLAG (ri->flags, BGP_INFO_VALID); /* Process change. */ bgp_aggregate_increment (bgp, p, ri, afi, safi); bgp_process (bgp, rn, afi, safi); bgp_unlock_node (rn); return 0; } /* Received Logging. */ if (BGP_DEBUG (update, UPDATE_IN)) { zlog (peer->log, LOG_INFO, "%s rcvd %s/%d", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); } /* Increment prefix counter */ peer->pcount[afi][safi]++; /* Make new BGP info. */ new = bgp_info_new (); new->type = type; new->sub_type = sub_type; new->peer = peer; new->attr = attr_new; new->uptime = time (NULL); /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) memcpy (new->tag, tag, 3); /* Nexthop reachability check. */ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST && (peer_sort (peer) == BGP_PEER_IBGP || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))) { if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL)) SET_FLAG (new->flags, BGP_INFO_VALID); else UNSET_FLAG (new->flags, BGP_INFO_VALID); } else SET_FLAG (new->flags, BGP_INFO_VALID); /* Aggregate address increment. */ bgp_aggregate_increment (bgp, p, new, afi, safi); /* Register new BGP information. */ bgp_info_add (rn, new); /* If maximum prefix count is configured and current prefix count exeed it. */ if (bgp_maximum_prefix_overflow (peer, afi, safi, 0)) return -1; /* Process change. */ bgp_process (bgp, rn, afi, safi); return 0; /* This BGP update is filtered. Log the reason then update BGP entry. */ filtered: if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "%s rcvd UPDATE about %s/%d -- DENIED due to: %s", peer->host, inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen, reason); if (ri) bgp_rib_withdraw (rn, ri, peer, afi, safi, 1); bgp_unlock_node (rn); return 0;}intbgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, int afi, int safi, int type, int sub_type, struct prefix_rd *prd, u_char *tag){ struct bgp *bgp; char buf[SU_ADDRSTRLEN]; struct bgp_node *rn; struct bgp_info *ri; bgp = peer->bgp; /* Logging. */ if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "%s rcvd UPDATE about %s/%d -- withdrawn", peer->host, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); /* Lookup node. */ rn = bgp_afi_node_get (bgp, afi, safi, p, prd); /* If peer is soft reconfiguration enabled. Record input packet for further calculation. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) && peer != bgp->peer_self) bgp_adj_in_unset (rn, peer); /* Lookup withdrawn route. */ for (ri = rn->info; ri; ri = ri->next) if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type) break; /* Withdraw specified route from routing table. */ if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) bgp_rib_withdraw (rn, ri, peer, afi, safi, 0); else if (BGP_DEBUG (update, UPDATE_IN)) zlog (peer->log, LOG_INFO, "%s Can't find the route %s/%d", peer->host, inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen); /* Unlock bgp_node_get() lock. */ bgp_unlock_node (rn); return 0;}voidbgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw){ struct bgp *bgp; struct attr attr; struct aspath *aspath; struct prefix p; struct bgp_info binfo; struct peer *from; int ret = RMAP_DENYMATCH; bgp = peer->bgp; from = bgp->peer_self; bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); aspath = attr.aspath; attr.local_pref = bgp->default_local_pref; memcpy (&attr.nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN); if (afi == AFI_IP) str2prefix ("0.0.0.0/0", &p);#ifdef HAVE_IPV6 else if (afi == AFI_IP6) { str2prefix ("::/0", &p); /* IPv6 global nexthop must be included. */ memcpy (&attr.mp_nexthop_global, &peer->nexthop.v6_global, IPV6_MAX_BYTELEN); attr.mp_nexthop_len = 16; /* If the peer is on shared nextwork and we have link-local nexthop set it. */ 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; } }#endif /* HAVE_IPV6 */ else return; if (peer->default_rmap[afi][safi].name) { binfo.peer = bgp->peer_self; binfo.attr = &attr; ret = route_map_apply (peer->default_rmap[afi][safi].map, &p, RMAP_BGP, &binfo); if (ret == RMAP_DENYMATCH) { bgp_attr_flush (&attr); withdraw = 1; } } if (withdraw) { if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE)) bgp_default_withdraw_send (peer, afi, safi); UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE); } else { SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE); bgp_default_update_send (peer, &attr, afi, safi, from); } aspath_unintern (aspath);}static voidbgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_table *table){ struct bgp_node *rn; struct bgp_info *ri; struct attr attr; if (! table) table = peer->bgp->rib[afi][safi]; if (safi != SAFI_MPLS_VPN && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) bgp_default_originate (peer, afi, safi, 0); for (rn = bgp_table_top (table); rn; rn = bgp_route_next(rn)) for (ri = rn->info; ri; ri = ri->next) if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) && ri->peer != peer) { if (bgp_announce_check (ri, peer, &rn->p, &attr, afi, safi)) bgp_adj_out_set (rn, peer, &rn->p, &attr, afi, safi, ri); else bgp_adj_out_unset (rn, peer, &rn->p, afi, safi); }}voidbgp_announce_route (struct peer *peer, afi_t afi, safi_t safi){ struct bgp_node *rn; struct bgp_table *table; if (peer->status != Established) return; if (! peer->afc_nego[afi][safi]) return; /* First update is deferred until ORF or ROUTE-REFRESH is received */ if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) return; if (safi != SAFI_MPLS_VPN) bgp_announce_table (peer, afi, safi, NULL); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) if ((table = (rn->info)) != NULL) bgp_announce_table (peer, afi, safi, table);}voidbgp_announce_route_all (struct peer *peer){ afi_t afi; safi_t safi; for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) bgp_announce_route (peer, afi, safi);}static voidbgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_table *table){ int ret; struct bgp_node *rn; struct bgp_adj_in *ain; if (! table) table = peer->bgp->rib[afi][safi]; for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) for (ain = rn->adj_in; ain; ain = ain->next) { if (ain->peer == peer) { ret = bgp_update (peer, &rn->p, ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 1); if (ret < 0) { bgp_unlock_node (rn); return; } continue; } }}voidbgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi){ struct bgp_node *rn; struct bgp_table *table; if (peer->status != Established) return; if (safi != SAFI_MPLS_VPN) bgp_soft_reconfig_table (peer, afi, safi, NULL); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) if ((table = rn->info) != NULL) bgp_soft_reconfig_table (peer, afi, safi, table);}static voidbgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_table *table){ struct bgp_node *rn; struct bgp_adj_in *ain;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -