📄 bgpd.c
字号:
{ 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->host = "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->as = *as; if (name) bgp->name = strdup (name); return bgp;}/* Return master of BGP. */struct bgp_master *bgp_get_master (){ if (bm) return bm; return NULL;}/* 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 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); bgp->group->del = (void (*)(void *)) peer_group_delete; list_delete (bgp->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]) XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]); if (bgp->aggregate[afi][safi]) XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ; if (bgp->rib[afi][safi]) XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]); } 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_PASSIVE, 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_NO_ROUTE_REFRESH_CAP, 0, peer_change_reset }, { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset }, { PEER_FLAG_ENFORCE_MULTIHOP, 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 (peer->status == Established) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); else BGP_EVENT_ADD (peer, BGP_Stop); } else { peer->v_start = BGP_INIT_START_TIMER; BGP_EVENT_ADD (peer, BGP_Stop); } } else if (peer->status == Established) { if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP && CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV)) { if (CHECK_FLAG (peer->flags, flag)) UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); else SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); bgp_capability_send (peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_REFRESH, CHECK_FLAG (peer->flags, flag) ? CAPABILITY_ACTION_UNSET : CAPABILITY_ACTION_SET); } else { if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP) peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; else if (flag == PEER_FLAG_DYNAMIC_CAPABILITY) peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; else if (flag == PEER_FLAG_PASSIVE) peer->last_reset = PEER_DOWN_PASSIVE_CHANGE; else if (flag == PEER_FLAG_ENFORCE_MULTIHOP) peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE; bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); } } else BGP_EVENT_ADD (peer, BGP_Stop);}/* Change specified peer flag. */intpeer_flag_modify (struct peer *peer, u_int32_t flag, int set){ int found; int size; struct peer_group *group; struct listnode *nn; struct peer_flag_action action; memset (&action, 0, sizeof (struct peer_flag_action)); size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action); found = peer_flag_action_set (peer_flag_action_list, size, &action, flag); /* No flag action is found. */ if (! found) return BGP_ERR_INVALID_FLAG; /* Not for peer-group member. */ if (action.not_for_member && peer_group_active (peer)) return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; /* When unset the peer-group member's flag we have to check peer-group configuration. */ if (! set && peer_group_active (peer)) if (CHECK_FLAG (peer->group->conf->flags, flag)) { if (flag == PEER_FLAG_SHUTDOWN) return BGP_ERR_PEER_GROUP_SHUTDOWN; else return BGP_ERR_PEER_GROUP_HAS_THE_FLAG; } /* Flag conflict check. */ if (set && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH) && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY)) return BGP_ERR_PEER_FLAG_CONFLICT; if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { if (set && CHECK_FLAG (peer->flags, flag) == flag) return 0; if (! set && ! CHECK_FLAG (peer->flags, flag)) return 0; } if (set) SET_FLAG (peer->flags, flag); else UNSET_FLAG (peer->flags, flag); if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { if (action.type == peer_change_reset) peer_flag_modify_action (peer, flag); return 0; } /* peer-group member updates. */ group = peer->group; LIST_LOOP (group->peer, peer, nn) { if (set && CHECK_FLAG (peer->flags, flag) == flag) continue; if (! set && ! CHECK_FLAG (peer->flags, flag)) continue; if (set) SET_FLAG (peer->flags, flag); else UNSET_FLAG (peer->flags, flag); if (action.type == peer_change_reset) peer_flag_modify_action (peer, flag);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -