⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ospf_zebra.c

📁 router source code for the ospdf.
💻 C
📖 第 1 页 / 共 2 页
字号:
	       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 + -