📄 ospf_zebra.c
字号:
metric_value (ospf, DEFAULT_ROUTE)); if (ospf->router_id.s_addr == 0) ospf->external_origin |= (1 << DEFAULT_ROUTE); else thread_add_timer (master, ospf_default_originate_timer, &ospf->default_originate, 1); ospf_asbr_status_update (ospf, ++ospf->redistribute); return CMD_SUCCESS;}intospf_redistribute_default_unset (struct ospf *ospf){ if (!ospf_is_type_redistributed (DEFAULT_ROUTE)) return CMD_SUCCESS; ospf->default_originate = DEFAULT_ORIGINATE_NONE; ospf->dmetric[DEFAULT_ROUTE].type = -1; ospf->dmetric[DEFAULT_ROUTE].value = -1; zclient_redistribute_default_unset (zclient); if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[DEFAULT]: Stop"); ospf_asbr_status_update (ospf, --ospf->redistribute); return CMD_SUCCESS;}intospf_external_lsa_originate_check (struct ospf *ospf, struct external_info *ei){ /* If prefix is multicast, then do not originate LSA. */ if (IN_MULTICAST (htonl (ei->p.prefix.s_addr))) { zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, " "Prefix belongs multicast", inet_ntoa (ei->p.prefix)); return 0; } /* Take care of default-originate. */ if (is_prefix_default (&ei->p)) if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) { zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA " "for default"); return 0; } return 1;}/* If connected prefix is OSPF enable interface, then do not announce. */intospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei){ struct route_node *rn; for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) if (rn->info != NULL) if (prefix_match (&rn->p, (struct prefix *)&ei->p)) { route_unlock_node (rn); return 0; } return 1;}/* return 1 if external LSA must be originated, 0 otherwise */intospf_redistribute_check (struct ospf *ospf, struct external_info *ei, int *changed){ struct route_map_set_values save_values; struct prefix_ipv4 *p = &ei->p; u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type; if (changed) *changed = 0; if (!ospf_external_lsa_originate_check (ospf, ei)) return 0; /* Take care connected route. */ if (type == ZEBRA_ROUTE_CONNECT && !ospf_distribute_check_connected (ospf, ei)) return 0; if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type)) /* distirbute-list exists, but access-list may not? */ if (DISTRIBUTE_LIST (ospf, type)) if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY) { if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[%s]: %s/%d filtered by ditribute-list.", LOOKUP (ospf_redistributed_proto, type), inet_ntoa (p->prefix), p->prefixlen); return 0; } save_values = ei->route_map_set; ospf_reset_route_map_set_values (&ei->route_map_set); /* apply route-map if needed */ if (ROUTEMAP_NAME (ospf, type)) { int ret; ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *)p, RMAP_OSPF, ei); if (ret == RMAP_DENYMATCH) { ei->route_map_set = save_values; if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) zlog_info ("Redistribute[%s]: %s/%d filtered by route-map.", LOOKUP (ospf_redistributed_proto, type), inet_ntoa (p->prefix), p->prefixlen); return 0; } /* check if 'route-map set' changed something */ if (changed) *changed = !ospf_route_map_set_compare (&ei->route_map_set, &save_values); } return 1;}/* OSPF route-map set for redistribution */voidospf_routemap_set (struct ospf *ospf, int type, char *name){ if (ROUTEMAP_NAME (ospf, type)) free (ROUTEMAP_NAME (ospf, type)); ROUTEMAP_NAME (ospf, type) = strdup (name); ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);}voidospf_routemap_unset (struct ospf *ospf, int type){ if (ROUTEMAP_NAME (ospf, type)) free (ROUTEMAP_NAME (ospf, type)); ROUTEMAP_NAME (ospf, type) = NULL; ROUTEMAP (ospf, type) = NULL;}/* Zebra route add and delete treatment. */intospf_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length){ struct stream *s; struct zapi_ipv4 api; unsigned long ifindex; struct in_addr nexthop; struct prefix_ipv4 p; struct external_info *ei; struct ospf *ospf; s = zclient->ibuf; ifindex = 0; nexthop.s_addr = 0; /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv4 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); nexthop.s_addr = stream_get_ipv4 (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); ospf = ospf_lookup (); if (ospf == NULL) return 0; if (command == ZEBRA_IPV4_ROUTE_ADD) { ei = ospf_external_info_add (api.type, p, ifindex, nexthop); if (ospf->router_id.s_addr == 0) /* Set flags to generate AS-external-LSA originate event for each redistributed protocols later. */ ospf->external_origin |= (1 << api.type); else { if (ei) { if (is_prefix_default (&p)) ospf_external_lsa_refresh_default (ospf); else { struct ospf_lsa *current; current = ospf_external_info_find_lsa (ospf, &ei->p); if (!current) ospf_external_lsa_originate (ospf, ei); else if (IS_LSA_MAXAGE (current)) ospf_external_lsa_refresh (ospf, current, ei, LSA_REFRESH_FORCE); else zlog_warn ("ospf_zebra_read_ipv4() : %s already exists", inet_ntoa (p.prefix)); } } } } else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ { ospf_external_info_delete (api.type, p); if ( !is_prefix_default (&p)) ospf_external_lsa_flush (ospf, api.type, &p, ifindex, nexthop); else ospf_external_lsa_refresh_default (ospf); } return 0;}intospf_distribute_list_out_set (struct ospf *ospf, int type, char *name){ /* Lookup access-list for distribute-list. */ DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name); /* Clear previous distribute-name. */ if (DISTRIBUTE_NAME (ospf, type)) free (DISTRIBUTE_NAME (ospf, type)); /* Set distribute-name. */ DISTRIBUTE_NAME (ospf, type) = strdup (name); /* If access-list have been set, schedule update timer. */ if (DISTRIBUTE_LIST (ospf, type)) ospf_distribute_list_update (ospf, type); return CMD_SUCCESS;}intospf_distribute_list_out_unset (struct ospf *ospf, int type, char *name){ /* Schedule update timer. */ if (DISTRIBUTE_LIST (ospf, type)) ospf_distribute_list_update (ospf, type); /* Unset distribute-list. */ DISTRIBUTE_LIST (ospf, type) = NULL; /* Clear distribute-name. */ if (DISTRIBUTE_NAME (ospf, type)) free (DISTRIBUTE_NAME (ospf, type)); DISTRIBUTE_NAME (ospf, type) = NULL; return CMD_SUCCESS;}/* distribute-list update timer. */intospf_distribute_list_update_timer (struct thread *thread){ struct route_node *rn; struct external_info *ei; struct route_table *rt; struct ospf_lsa *lsa; u_char type; struct ospf *ospf; type = (int) THREAD_ARG (thread); rt = EXTERNAL_INFO (type); ospf = ospf_lookup (); if (ospf == NULL) return 0; ospf->t_distribute_update = NULL; zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!"); /* foreach all external info. */ if (rt) for (rn = route_top (rt); rn; rn = route_next (rn)) if ((ei = rn->info) != NULL) { if (is_prefix_default (&ei->p)) ospf_external_lsa_refresh_default (ospf); else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p))) ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED); else ospf_external_lsa_originate (ospf, ei); } return 0;}#define OSPF_DISTRIBUTE_UPDATE_DELAY 5/* Update distribute-list and set timer to apply access-list. */voidospf_distribute_list_update (struct ospf *ospf, int type){ struct route_table *rt; /* External info does not exist. */ if (!(rt = EXTERNAL_INFO (type))) return; /* If exists previously invoked thread, then cancel it. */ if (ospf->t_distribute_update) OSPF_TIMER_OFF (ospf->t_distribute_update); /* Set timer. */ ospf->t_distribute_update = thread_add_timer (master, ospf_distribute_list_update_timer, (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);}/* If access-list is updated, apply some check. */voidospf_filter_update (struct access_list *access){ struct ospf *ospf; int type; int abr_inv = 0; struct ospf_area *area; listnode node; /* If OSPF instatnce does not exist, return right now. */ ospf = ospf_lookup (); if (ospf == NULL) return; /* Update distribute-list, and apply filter. */ for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { if (ROUTEMAP (ospf, type) != NULL) { /* if route-map is not NULL it may be using this access list */ ospf_distribute_list_update (ospf, type); continue; } if (DISTRIBUTE_NAME (ospf, type)) { /* Keep old access-list for distribute-list. */ struct access_list *old = DISTRIBUTE_LIST (ospf, type); /* Update access-list for distribute-list. */ DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type)); /* No update for this distribute type. */ if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL) continue; /* Schedule distribute-list update timer. */ if (DISTRIBUTE_LIST (ospf, type) == NULL || strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0) ospf_distribute_list_update (ospf, type); } } /* Update Area access-list. */ for (node = listhead (ospf->areas); node; nextnode (node)) if ((area = getdata (node)) != NULL) { if (EXPORT_NAME (area)) { EXPORT_LIST (area) = NULL; abr_inv++; } if (IMPORT_NAME (area)) { IMPORT_LIST (area) = NULL; abr_inv++; } } /* Schedule ABR tasks -- this will be changed -- takada. */ if (IS_OSPF_ABR (ospf) && abr_inv) ospf_schedule_abr_task (ospf);}struct ospf_distance *ospf_distance_new (){ struct ospf_distance *new; new = XMALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance)); memset (new, 0, sizeof (struct ospf_distance)); return new;}voidospf_distance_free (struct ospf_distance *odistance){ XFREE (MTYPE_OSPF_DISTANCE, odistance);}intospf_distance_set (struct vty *vty, struct ospf *ospf, char *distance_str, char *ip_str, char *access_list_str){ int ret; struct prefix_ipv4 p; u_char distance; struct route_node *rn; struct ospf_distance *odistance; ret = str2prefix_ipv4 (ip_str, &p); if (ret == 0) { vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); return CMD_WARNING; } distance = atoi (distance_str); /* Get OSPF distance node. */ rn = route_node_get (ospf->distance_table, (struct prefix *) &p); if (rn->info) { odistance = rn->info; route_unlock_node (rn); } else { odistance = ospf_distance_new (); rn->info = odistance; } /* Set distance value. */ odistance->distance = distance; /* Reset access-list configuration. */ if (odistance->access_list) { free (odistance->access_list); odistance->access_list = NULL; } if (access_list_str) odistance->access_list = strdup (access_list_str); return CMD_SUCCESS;}intospf_distance_unset (struct vty *vty, struct ospf *ospf, char *distance_str, char *ip_str, char *access_list_str){ int ret; struct prefix_ipv4 p; u_char distance; struct route_node *rn; struct ospf_distance *odistance; ret = str2prefix_ipv4 (ip_str, &p); if (ret == 0) { vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); return CMD_WARNING; } distance = atoi (distance_str); rn = route_node_lookup (ospf->distance_table, (struct prefix *)&p); if (! rn) { vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE); return CMD_WARNING; } odistance = rn->info; if (odistance->access_list) free (odistance->access_list); ospf_distance_free (odistance); rn->info = NULL; route_unlock_node (rn); route_unlock_node (rn); return CMD_SUCCESS;}voidospf_distance_reset (struct ospf *ospf){ struct route_node *rn; struct ospf_distance *odistance; for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn)) if ((odistance = rn->info) != NULL) { if (odistance->access_list) free (odistance->access_list); ospf_distance_free (odistance); rn->info = NULL; route_unlock_node (rn); }}u_charospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or){ struct ospf *ospf; ospf = ospf_lookup (); if (ospf == NULL) return 0; if (ospf->distance_intra) if (or->path_type == OSPF_PATH_INTRA_AREA) return ospf->distance_intra; if (ospf->distance_inter) if (or->path_type == OSPF_PATH_INTER_AREA) return ospf->distance_inter; if (ospf->distance_external) if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL || or->path_type == OSPF_PATH_TYPE2_EXTERNAL) return ospf->distance_external; if (ospf->distance_all) return ospf->distance_all; return 0;}voidospf_zebra_init (){ /* Allocate zebra structure. */ zclient = zclient_new (); zclient_init (zclient, ZEBRA_ROUTE_OSPF); zclient->interface_add = ospf_interface_add; zclient->interface_delete = ospf_interface_delete; zclient->interface_up = ospf_interface_state_up; zclient->interface_down = ospf_interface_state_down; zclient->interface_address_add = ospf_interface_address_add; zclient->interface_address_delete = ospf_interface_address_delete; zclient->ipv4_route_add = ospf_zebra_read_ipv4; zclient->ipv4_route_delete = ospf_zebra_read_ipv4; access_list_add_hook (ospf_filter_update); access_list_delete_hook (ospf_filter_update);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -