📄 bgpd.c
字号:
peer_group_bind2 (struct bgp *bgp, union sockunion *su, struct peer_group *group, afi_t afi, safi_t safi, as_t *as){ struct peer *peer; int first_member = 0; /* Lookup the peer. */ peer = peer_lookup (bgp, su); /* Create a new peer. */ if (! peer) { if (! group->conf->as) return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) && afi == AFI_IP && safi == SAFI_UNICAST) { peer = peer_create (su, bgp, bgp->as, group->conf->as, 0, 0); peer->group = group; listnode_add (group->peer, peer); peer_group_global_config_copy (group->conf, peer); } else { peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi); peer->group = group; listnode_add (group->peer, peer); peer_group_global_config_copy (group->conf, peer); peer_group_af_config_copy (group->conf, peer, afi, safi); peer_activate (group->conf, afi, safi); } return 0; } /* When the peer already belongs to peer group, check the consistency. */ if (peer_group_member (peer)) { if (strcmp (peer->group->name, group->name) != 0) return BGP_ERR_PEER_GROUP_CANT_CHANGE; return peer_activate (peer, afi, safi); } if (! group->conf->as) { if (peer_sort (group->conf) == BGP_PEER_INTERNAL) first_member = 1; else if (peer_sort (group->conf) != peer_sort (peer)) { if (as) *as = peer->as; return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; } } peer->group = group; listnode_add (group->peer, peer); if (first_member) { /* Advertisement-interval reset */ if (peer_sort (group->conf) == BGP_PEER_IBGP) group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; else group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; /* ebgp-multihop reset */ if (peer_sort (group->conf) == BGP_PEER_IBGP) group->conf->ttl = 255; /* local-as reset */ if (peer_sort (group->conf) != BGP_PEER_EBGP) { group->conf->change_local_as = 0; UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); } } peer_group_global_config_copy (group->conf, peer); return peer_activate (peer, afi,safi);}intpeer_group_unbind (struct bgp *bgp, struct peer *peer, struct peer_group *group, afi_t afi, safi_t safi){ if (! peer->afc[afi][safi]) return 0; if (group != peer->group) return BGP_ERR_PEER_GROUP_MISMATCH; peer->afc[afi][safi] = 0; peer_af_flag_reset (peer, afi, safi); if (! peer_active (peer)) { peer_delete (peer); return 0; } if (peer->status == Established) { peer->last_reset = PEER_DOWN_RMAP_UNBIND; bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else BGP_EVENT_ADD (peer, BGP_Stop); return 0;}/* BGP instance creation by `router bgp' commands. */struct bgp *bgp_create (as_t *as, char *name){ struct bgp *bgp; afi_t afi; safi_t safi; bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp)); bgp->peer_self = peer_new (); bgp->peer_self->bgp = bgp; bgp->peer_self->host = strdup ("Static announcement"); bgp->peer = list_new (); bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp; bgp->group = list_new (); bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp; for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { bgp->route[afi][safi] = bgp_table_init (); bgp->aggregate[afi][safi] = bgp_table_init (); bgp->rib[afi][safi] = bgp_table_init (); } bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; bgp->restart_time = BGP_DEFAULT_RESTART_TIME; bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; bgp->as = *as; if (name) bgp->name = strdup (name); return bgp;}/* Return first entry of BGP. */struct bgp *bgp_get_default (){ if (bm->bgp->head) return bm->bgp->head->data; return NULL;}/* Lookup BGP entry. */struct bgp *bgp_lookup (as_t as, char *name){ struct bgp *bgp; struct listnode *nn; LIST_LOOP (bm->bgp, bgp, nn) if (bgp->as == as && ((bgp->name == NULL && name == NULL) || (bgp->name && name && strcmp (bgp->name, name) == 0))) return bgp; return NULL;}/* Lookup BGP structure by view name. */struct bgp *bgp_lookup_by_name (char *name){ struct bgp *bgp; struct listnode *nn; LIST_LOOP (bm->bgp, bgp, nn) if ((bgp->name == NULL && name == NULL) || (bgp->name && name && strcmp (bgp->name, name) == 0)) return bgp; return NULL;}/* Called from VTY commands. */intbgp_get (struct bgp **bgp_val, as_t *as, char *name){ struct bgp *bgp; /* Multiple instance check. */ if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) { if (name) bgp = bgp_lookup_by_name (name); else bgp = bgp_get_default (); /* Already exists. */ if (bgp) { if (bgp->as != *as) { *as = bgp->as; return BGP_ERR_INSTANCE_MISMATCH; } *bgp_val = bgp; return 0; } } else { /* BGP instance name can not be specified for single instance. */ if (name) return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET; /* Get default BGP structure if exists. */ bgp = bgp_get_default (); if (bgp) { if (bgp->as != *as) { *as = bgp->as; return BGP_ERR_AS_MISMATCH; } *bgp_val = bgp; return 0; } } bgp = bgp_create (as, name); listnode_add (bm->bgp, bgp); bgp_if_update_all (); *bgp_val = bgp; return 0;}/* Delete BGP instance. */intbgp_delete (struct bgp *bgp){ struct peer *peer; struct peer_group *group; struct listnode *nn; struct listnode *next; afi_t afi; safi_t safi; int i; /* Delete static route. */ bgp_static_delete (bgp); /* Unset redistribution. */ for (afi = AFI_IP; afi < AFI_MAX; afi++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) if (i != ZEBRA_ROUTE_BGP) bgp_redistribute_unset (bgp, afi, i); for (nn = bgp->group->head; nn; nn = next) { group = nn->data; next = nn->next; peer_group_delete (group); } for (nn = bgp->peer->head; nn; nn = next) { peer = nn->data; next = nn->next; peer_delete (peer); } listnode_delete (bm->bgp, bgp); if (bgp->name) free (bgp->name); for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { if (bgp->route[afi][safi]) bgp_table_finish (bgp->route[afi][safi]); if (bgp->aggregate[afi][safi]) bgp_table_finish (bgp->aggregate[afi][safi]); if (bgp->rib[afi][safi]) bgp_table_finish (bgp->rib[afi][safi]); } peer_delete (bgp->peer_self); XFREE (MTYPE_BGP, bgp); return 0;}struct peer *peer_lookup (struct bgp *bgp, union sockunion *su){ struct peer *peer; struct listnode *nn; if (! bgp) bgp = bgp_get_default (); if (! bgp) return NULL; LIST_LOOP (bgp->peer, peer, nn) { if (sockunion_same (&peer->su, su) && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) return peer; } return NULL;}struct peer *peer_lookup_with_open (union sockunion *su, as_t remote_as, struct in_addr *remote_id, int *as){ struct peer *peer; struct listnode *nn; struct bgp *bgp; bgp = bgp_get_default (); if (! bgp) return NULL; LIST_LOOP (bgp->peer, peer, nn) { if (sockunion_same (&peer->su, su) && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) { if (peer->as == remote_as && peer->remote_id.s_addr == remote_id->s_addr) return peer; if (peer->as == remote_as) *as = 1; } } LIST_LOOP (bgp->peer, peer, nn) { if (sockunion_same (&peer->su, su) && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) { if (peer->as == remote_as && peer->remote_id.s_addr == 0) return peer; if (peer->as == remote_as) *as = 1; } } return NULL;}/* If peer is configured at least one address family return 1. */intpeer_active (struct peer *peer){ if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_UNICAST] || peer->afc[AFI_IP6][SAFI_MULTICAST]) return 1; return 0;}/* If peer is negotiated at least one address family return 1. */intpeer_active_nego (struct peer *peer){ if (peer->afc_nego[AFI_IP][SAFI_UNICAST] || peer->afc_nego[AFI_IP][SAFI_MULTICAST] || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP6][SAFI_UNICAST] || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]) return 1; return 0;}/* peer_flag_change_type. */enum peer_change_type{ peer_change_none, peer_change_reset, peer_change_reset_in, peer_change_reset_out,};voidpeer_change_action (struct peer *peer, afi_t afi, safi_t safi, enum peer_change_type type){ if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) return; if (type == peer_change_reset) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); else if (type == peer_change_reset_in) { if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); else bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); } else if (type == peer_change_reset_out) bgp_announce_route (peer, afi, safi);}struct peer_flag_action{ /* Peer's flag. */ u_int32_t flag; /* This flag can be set for peer-group member. */ u_char not_for_member; /* Action when the flag is changed. */ enum peer_change_type type; /* Peer down cause */ u_char peer_down;};struct peer_flag_action peer_flag_action_list[] = { { PEER_FLAG_CONNECT_MODE_PASSIVE, 0, peer_change_reset }, { PEER_FLAG_CONNECT_MODE_ACTIVE, 0, peer_change_reset }, { PEER_FLAG_SHUTDOWN, 0, peer_change_reset }, { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none }, { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none }, { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none }, { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset }, { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset }, { 0, 0, 0 } };struct peer_flag_action peer_af_flag_action_list[] = { { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out }, { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out }, { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out }, { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in }, { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset }, { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset }, { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out }, { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out }, { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out }, { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out }, { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in }, { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset }, { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset }, { 0, 0, 0 } };/* Proper action set. */intpeer_flag_action_set (struct peer_flag_action *action_list, int size, struct peer_flag_action *action, u_int32_t flag){ int i; int found = 0; int reset_in = 0; int reset_out = 0; struct peer_flag_action *match = NULL; /* Check peer's frag action. */ for (i = 0; i < size; i++) { match = &action_list[i]; if (match->flag == 0) break; if (match->flag & flag) { found = 1; if (match->type == peer_change_reset_in) reset_in = 1; if (match->type == peer_change_reset_out) reset_out = 1; if (match->type == peer_change_reset) { reset_in = 1; reset_out = 1; } if (match->not_for_member) action->not_for_member = 1; } } /* Set peer clear type. */ if (reset_in && reset_out) action->type = peer_change_reset; else if (reset_in) action->type = peer_change_reset_in; else if (reset_out) action->type = peer_change_reset_out; else action->type = peer_change_none; return found;}voidpeer_flag_modify_action (struct peer *peer, u_int32_t flag){ if (flag == PEER_FLAG_SHUTDOWN) { if (CHECK_FLAG (peer->flags, flag)) { if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) peer_nsf_stop (peer); UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); if (peer->t_pmax_restart) { BGP_TIMER_OFF (peer->t_pmax_restart); if (BGP_DEBUG (events, EVENTS)) zlog_info ("%s Maximum-prefix restart timer canceled", peer->host); } if (peer->status == Established) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); else BGP_EVENT_ADD (peer, BGP_Stop); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -