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

📄 zebra_rib.c

📁 zebra测试源代码用于 SOCKET 通信
💻 C
📖 第 1 页 / 共 4 页
字号:
      /* If there is no selected route or matched route is EGP, go up         tree. */      if (! match 	  || match->type == ZEBRA_ROUTE_BGP)	{	  do {	    rn = rn->parent;	  } while (rn && rn->info == NULL);	  if (rn)	    route_lock_node (rn);	}      else	{	  if (match->type == ZEBRA_ROUTE_CONNECT)	    /* Directly point connected route. */	    return match;	  else	    {	      for (newhop = match->nexthop; newhop; newhop = newhop->next)		if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))		  return match;	      return NULL;	    }	}    }  return NULL;}struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *p){  struct route_table *table;  struct route_node *rn;  struct rib *match;  struct nexthop *nexthop;  /* Lookup table.  */  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);  if (! table)    return 0;  rn = route_node_lookup (table, (struct prefix *) p);  /* No route for this prefix. */  if (! rn)    return NULL;  /* Unlock node. */  route_unlock_node (rn);  /* Pick up selected route. */  for (match = rn->info; match; match = match->next)    if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))      break;  if (! match || match->type == ZEBRA_ROUTE_BGP)    return NULL;  if (match->type == ZEBRA_ROUTE_CONNECT)    return match;    for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)    if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))      return match;  return NULL;}#ifdef HAVE_IPV6struct rib *rib_match_ipv6 (struct in6_addr *addr){  struct prefix_ipv6 p;  struct route_table *table;  struct route_node *rn;  struct rib *match;  struct nexthop *newhop;  /* Lookup table.  */  table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);  if (! table)    return 0;  memset (&p, 0, sizeof (struct prefix_ipv6));  p.family = AF_INET6;  p.prefixlen = IPV6_MAX_PREFIXLEN;  IPV6_ADDR_COPY (&p.prefix, addr);  rn = route_node_match (table, (struct prefix *) &p);  while (rn)    {      route_unlock_node (rn);            /* Pick up selected route. */      for (match = rn->info; match; match = match->next)	if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))	  break;      /* If there is no selected route or matched route is EGP, go up         tree. */      if (! match 	  || match->type == ZEBRA_ROUTE_BGP)	{	  do {	    rn = rn->parent;	  } while (rn && rn->info == NULL);	  if (rn)	    route_lock_node (rn);	}      else	{	  if (match->type == ZEBRA_ROUTE_CONNECT)	    /* Directly point connected route. */	    return match;	  else	    {	      for (newhop = match->nexthop; newhop; newhop = newhop->next)		if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))		  return match;	      return NULL;	    }	}    }  return NULL;}#endif /* HAVE_IPV6 */intnexthop_active_check (struct route_node *rn, struct rib *rib,		      struct nexthop *nexthop, int set){  struct interface *ifp;  switch (nexthop->type)    {    case NEXTHOP_TYPE_IFINDEX:      ifp = if_lookup_by_index (nexthop->ifindex);      if (ifp && if_is_up (ifp))	SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      else	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      break;    case NEXTHOP_TYPE_IFNAME:    case NEXTHOP_TYPE_IPV6_IFNAME:      ifp = if_lookup_by_name (nexthop->ifname);      if (ifp && if_is_up (ifp))	{	  if (set)	    nexthop->ifindex = ifp->ifindex;	  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);	}      else	{	  if (set)	    nexthop->ifindex = 0;	  UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);	}      break;    case NEXTHOP_TYPE_IPV4:    case NEXTHOP_TYPE_IPV4_IFINDEX:      if (nexthop_active_ipv4 (rib, nexthop, set, rn))	SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      else	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      break;#ifdef HAVE_IPV6    case NEXTHOP_TYPE_IPV6:      if (nexthop_active_ipv6 (rib, nexthop, set, rn))	SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      else	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      break;    case NEXTHOP_TYPE_IPV6_IFINDEX:      if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))	{	  ifp = if_lookup_by_index (nexthop->ifindex);	  if (ifp && if_is_up (ifp))	    SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);	  else	    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);	}      else	{	  if (nexthop_active_ipv6 (rib, nexthop, set, rn))	    SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);	  else	    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);	}      break;#endif /* HAVE_IPV6 */    case NEXTHOP_TYPE_BLACKHOLE:      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      break;    default:      break;    }  return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);}intnexthop_active_update (struct route_node *rn, struct rib *rib, int set){  struct nexthop *nexthop;  int active;  rib->nexthop_active_num = 0;  UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)    {      active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);      rib->nexthop_active_num += nexthop_active_check (rn, rib, nexthop, set);      if (active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))	SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);    }  return rib->nexthop_active_num;}#define RIB_SYSTEM_ROUTE(R) \        ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)voidnewrib_free (struct rib *rib){  struct nexthop *nexthop;  struct nexthop *next;  for (nexthop = rib->nexthop; nexthop; nexthop = next)    {      next = nexthop->next;      nexthop_free (nexthop);    }  XFREE (MTYPE_RIB, rib);}voidrib_install_kernel (struct route_node *rn, struct rib *rib){  int ret = 0;  struct nexthop *nexthop;  switch (PREFIX_FAMILY (&rn->p))    {    case AF_INET:      ret = kernel_add_ipv4 (&rn->p, rib);      break;#ifdef HAVE_IPV6    case AF_INET6:      ret = kernel_add_ipv6 (&rn->p, rib);      break;#endif /* HAVE_IPV6 */    }  if (ret < 0)    {      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);    }}/* Uninstall the route from kernel. */intrib_uninstall_kernel (struct route_node *rn, struct rib *rib){  int ret = 0;  struct nexthop *nexthop;  switch (PREFIX_FAMILY (&rn->p))    {    case AF_INET:      ret = kernel_delete_ipv4 (&rn->p, rib);      break;#ifdef HAVE_IPV6    case AF_INET6:      ret = kernel_delete_ipv6 (&rn->p, rib);      break;#endif /* HAVE_IPV6 */    }  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);  return ret;}/* Uninstall the route from kernel. */voidrib_uninstall (struct route_node *rn, struct rib *rib){  if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))    {      redistribute_delete (&rn->p, rib);      if (! RIB_SYSTEM_ROUTE (rib))	rib_uninstall_kernel (rn, rib);      UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);    }}/* Core function for processing routing information base. */voidrib_process (struct route_node *rn, struct rib *del){  struct rib *rib;  struct rib *next;  struct rib *fib = NULL;  struct rib *select = NULL;  for (rib = rn->info; rib; rib = next)    {      next = rib->next;      /* Currently installed rib. */      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))	fib = rib;      /* Skip unreachable nexthop. */      if (! nexthop_active_update (rn, rib, 0))	continue;      /* Infinit distance. */      if (rib->distance == DISTANCE_INFINITY)	continue;      /* Newly selected rib. */      if (! select || rib->distance < select->distance 	  || rib->type == ZEBRA_ROUTE_CONNECT)	select = rib;    }  /* Deleted route check. */  if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))    fib = del;  /* Same route is selected. */  if (select && select == fib)    {      if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))	{	  redistribute_delete (&rn->p, select);	  if (! RIB_SYSTEM_ROUTE (select))	    rib_uninstall_kernel (rn, select);	  /* Set real nexthop. */	  nexthop_active_update (rn, select, 1);  	  if (! RIB_SYSTEM_ROUTE (select))	    rib_install_kernel (rn, select);	  redistribute_add (&rn->p, select);	}      return;    }  /* Uninstall old rib from forwarding table. */  if (fib)    {      redistribute_delete (&rn->p, fib);      if (! RIB_SYSTEM_ROUTE (fib))	rib_uninstall_kernel (rn, fib);      UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);      /* Set real nexthop. */      nexthop_active_update (rn, fib, 1);    }  /* Install new rib into forwarding table. */  if (select)    {      /* Set real nexthop. */      nexthop_active_update (rn, select, 1);      if (! RIB_SYSTEM_ROUTE (select))	rib_install_kernel (rn, select);      SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);      redistribute_add (&rn->p, select);    }}/* Add RIB to head of the route node. */voidrib_addnode (struct route_node *rn, struct rib *rib){  struct rib *head;  head = rn->info;  if (head)    head->prev = rib;  rib->next = head;  rn->info = rib;}voidrib_delnode (struct route_node *rn, struct rib *rib){  if (rib->next)    rib->next->prev = rib->prev;  if (rib->prev)    rib->prev->next = rib->next;  else    rn->info = rib->next;}intrib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, 	      struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,	      u_int32_t metric, u_char distance){  struct rib *rib;  struct rib *same = NULL;  struct route_table *table;  struct route_node *rn;  struct nexthop *nexthop;  /* Lookup table.  */  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);  if (! table)    return 0;  /* Make it sure prefixlen is applied to the prefix. */  apply_mask_ipv4 (p);  /* Set default distance by route type. */  if (distance == 0)    {      distance = route_info[type].distance;      /* iBGP distance is 200. */      if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))	distance = 200;    }  /* Lookup route node.*/  rn = route_node_get (table, (struct prefix *) p);  /* If same type of route are installed, treat it as a implicit     withdraw. */  for (rib = rn->info; rib; rib = rib->next)    {      if (rib->type == ZEBRA_ROUTE_CONNECT)	{	  nexthop = rib->nexthop;	  /* Duplicate connected route comes in. */	  if (rib->type == type	      && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX	      && nexthop->ifindex == ifindex)	    {	      rib->refcnt++;	      return 0 ;	    }	}      else if (rib->type == type)	{	  same = rib;	  rib_delnode (rn, same);	  route_unlock_node (rn);	  break;	}    }  /* Allocate new rib structure. */  rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));  memset (rib, 0, sizeof (struct rib));  rib->type = type;  rib->distance = distance;  rib->flags = flags;  rib->metric = metric;  rib->nexthop_num = 0;  rib->uptime = time (NULL);  /* Nexthop settings. */  if (gate)    {      if (ifindex)	nexthop_ipv4_ifindex_add (rib, gate, ifindex);      else	nexthop_ipv4_add (rib, gate);    }  else    nexthop_ifindex_add (rib, ifindex);  /* If this route is kernel route, set FIB flag to the route. */  if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)    for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);  /* Link new rib to node.*/  rib_addnode (rn, rib);  /* Process this route node. */  rib_process (rn, same);  /* Free implicit route.*/  if (same)    newrib_free (same);  return 0;}intrib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib){  struct route_table *table;  struct route_node *rn;  struct rib *same;  struct nexthop *nexthop;  /* Lookup table.  */  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);  if (! table)    return 0;  /* Make it sure prefixlen is applied to the prefix. */  apply_mask_ipv4 (p);  /* Set default distance by route type. */  if (rib->distance == 0)    {      rib->distance = route_info[rib->type].distance;      /* iBGP distance is 200. */      if (rib->type == ZEBRA_ROUTE_BGP 	  && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))	rib->distance = 200;    }  /* Lookup route node.*/  rn = route_node_get (table, (struct prefix *) p);  /* If same type of route are installed, treat it as a implicit     withdraw. */  for (same = rn->info; same; same = same->next)    {      if (same->type == rib->type && same->table == rib->table	  && same->type != ZEBRA_ROUTE_CONNECT)	{	  rib_delnode (rn, same);	  route_unlock_node (rn);	  break;	}    }  /* If this route is kernel route, set FIB flag to the route. */  if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)    for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);  /* Link new rib to node.*/  rib_addnode (rn, rib);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -