diff options
Diffstat (limited to 'eigrpd/eigrp_network.c')
| -rw-r--r-- | eigrpd/eigrp_network.c | 697 | 
1 files changed, 345 insertions, 352 deletions
diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index 74cb6de188..80610e04a7 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -49,412 +49,405 @@ extern struct zebra_privs_t eigrpd_privs;  #include "eigrpd/eigrp_vty.h"  #include "eigrpd/eigrp_network.h" -static int -eigrp_network_match_iface(const struct connected *, const struct prefix *); -static void -eigrp_network_run_interface(struct eigrp *, struct prefix *, struct interface *); +static int eigrp_network_match_iface(const struct connected *, +				     const struct prefix *); +static void eigrp_network_run_interface(struct eigrp *, struct prefix *, +					struct interface *); -int -eigrp_sock_init(void) +int eigrp_sock_init(void)  { -  int eigrp_sock; -  int ret, hincl = 1; - -  if (eigrpd_privs.change(ZPRIVS_RAISE)) -    zlog_err("eigrp_sock_init: could not raise privs, %s", -             safe_strerror(errno)); - -  eigrp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP); -  if (eigrp_sock < 0) -    { -      int save_errno = errno; -      if (eigrpd_privs.change(ZPRIVS_LOWER)) -        zlog_err("eigrp_sock_init: could not lower privs, %s", -                 safe_strerror(errno)); -      zlog_err("eigrp_read_sock_init: socket: %s", safe_strerror(save_errno)); -      exit(1); -    } +	int eigrp_sock; +	int ret, hincl = 1; + +	if (eigrpd_privs.change(ZPRIVS_RAISE)) +		zlog_err("eigrp_sock_init: could not raise privs, %s", +			 safe_strerror(errno)); + +	eigrp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP); +	if (eigrp_sock < 0) { +		int save_errno = errno; +		if (eigrpd_privs.change(ZPRIVS_LOWER)) +			zlog_err("eigrp_sock_init: could not lower privs, %s", +				 safe_strerror(errno)); +		zlog_err("eigrp_read_sock_init: socket: %s", +			 safe_strerror(save_errno)); +		exit(1); +	}  #ifdef IP_HDRINCL -  /* we will include IP header with packet */ -  ret = setsockopt(eigrp_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)); -  if (ret < 0) -    { -      int save_errno = errno; -      if (eigrpd_privs.change(ZPRIVS_LOWER)) -        zlog_err("eigrp_sock_init: could not lower privs, %s", -                 safe_strerror(errno)); -      zlog_warn("Can't set IP_HDRINCL option for fd %d: %s", eigrp_sock, -                safe_strerror(save_errno)); - -    } -#elif defined (IPTOS_PREC_INTERNETCONTROL) +	/* we will include IP header with packet */ +	ret = setsockopt(eigrp_sock, IPPROTO_IP, IP_HDRINCL, &hincl, +			 sizeof(hincl)); +	if (ret < 0) { +		int save_errno = errno; +		if (eigrpd_privs.change(ZPRIVS_LOWER)) +			zlog_err("eigrp_sock_init: could not lower privs, %s", +				 safe_strerror(errno)); +		zlog_warn("Can't set IP_HDRINCL option for fd %d: %s", +			  eigrp_sock, safe_strerror(save_errno)); +	} +#elif defined(IPTOS_PREC_INTERNETCONTROL)  #warning "IP_HDRINCL not available on this system"  #warning "using IPTOS_PREC_INTERNETCONTROL" -  ret = setsockopt_ipv4_tos (eigrp_sock, IPTOS_PREC_INTERNETCONTROL); -  if (ret < 0) -    { -      int save_errno = errno; -      if ( eigrpd_privs.change (ZPRIVS_LOWER) ) -        zlog_err ("eigrpd_sock_init: could not lower privs, %s", -                  safe_strerror (errno) ); -      zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s", -                 tos, eigrp_sock, safe_strerror (save_errno)); -      close (eigrp_sock); /* Prevent sd leak. */ -      return ret; -    } +	ret = setsockopt_ipv4_tos(eigrp_sock, IPTOS_PREC_INTERNETCONTROL); +	if (ret < 0) { +		int save_errno = errno; +		if (eigrpd_privs.change(ZPRIVS_LOWER)) +			zlog_err("eigrpd_sock_init: could not lower privs, %s", +				 safe_strerror(errno)); +		zlog_warn("can't set sockopt IP_TOS %d to socket %d: %s", tos, +			  eigrp_sock, safe_strerror(save_errno)); +		close(eigrp_sock); /* Prevent sd leak. */ +		return ret; +	}  #else /* !IPTOS_PREC_INTERNETCONTROL */  #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL" -  zlog_warn ("IP_HDRINCL option not available"); +	zlog_warn("IP_HDRINCL option not available");  #endif /* IP_HDRINCL */ -  ret = setsockopt_ifindex(AF_INET, eigrp_sock, 1); +	ret = setsockopt_ifindex(AF_INET, eigrp_sock, 1); -  if (ret < 0) -    zlog_warn("Can't set pktinfo option for fd %d", eigrp_sock); +	if (ret < 0) +		zlog_warn("Can't set pktinfo option for fd %d", eigrp_sock); -  if (eigrpd_privs.change(ZPRIVS_LOWER)) -    { -      zlog_err("eigrp_sock_init: could not lower privs, %s", -               safe_strerror(errno)); -    } +	if (eigrpd_privs.change(ZPRIVS_LOWER)) { +		zlog_err("eigrp_sock_init: could not lower privs, %s", +			 safe_strerror(errno)); +	} -  return eigrp_sock; +	return eigrp_sock;  } -void -eigrp_adjust_sndbuflen(struct eigrp * eigrp, unsigned int buflen) +void eigrp_adjust_sndbuflen(struct eigrp *eigrp, unsigned int buflen)  { -  int newbuflen; -  /* Check if any work has to be done at all. */ -  if (eigrp->maxsndbuflen >= buflen) -    return; -  if (eigrpd_privs.change(ZPRIVS_RAISE)) -    zlog_err("%s: could not raise privs, %s", __func__, safe_strerror(errno)); - -  /* Now we try to set SO_SNDBUF to what our caller has requested -   * (the MTU of a newly added interface). However, if the OS has -   * truncated the actual buffer size to somewhat less size, try -   * to detect it and update our records appropriately. The OS -   * may allocate more buffer space, than requested, this isn't -   * a error. -   */ -  setsockopt_so_sendbuf(eigrp->fd, buflen); -  newbuflen = getsockopt_so_sendbuf(eigrp->fd); -  if (newbuflen < 0 || newbuflen < (int) buflen) -    zlog_warn("%s: tried to set SO_SNDBUF to %u, but got %d", __func__, buflen, -              newbuflen); -  if (newbuflen >= 0) -    eigrp->maxsndbuflen = (unsigned int) newbuflen; -  else -    zlog_warn("%s: failed to get SO_SNDBUF", __func__); -  if (eigrpd_privs.change(ZPRIVS_LOWER)) -    zlog_err("%s: could not lower privs, %s", __func__, safe_strerror(errno)); +	int newbuflen; +	/* Check if any work has to be done at all. */ +	if (eigrp->maxsndbuflen >= buflen) +		return; +	if (eigrpd_privs.change(ZPRIVS_RAISE)) +		zlog_err("%s: could not raise privs, %s", __func__, +			 safe_strerror(errno)); + +	/* Now we try to set SO_SNDBUF to what our caller has requested +	 * (the MTU of a newly added interface). However, if the OS has +	 * truncated the actual buffer size to somewhat less size, try +	 * to detect it and update our records appropriately. The OS +	 * may allocate more buffer space, than requested, this isn't +	 * a error. +	 */ +	setsockopt_so_sendbuf(eigrp->fd, buflen); +	newbuflen = getsockopt_so_sendbuf(eigrp->fd); +	if (newbuflen < 0 || newbuflen < (int)buflen) +		zlog_warn("%s: tried to set SO_SNDBUF to %u, but got %d", +			  __func__, buflen, newbuflen); +	if (newbuflen >= 0) +		eigrp->maxsndbuflen = (unsigned int)newbuflen; +	else +		zlog_warn("%s: failed to get SO_SNDBUF", __func__); +	if (eigrpd_privs.change(ZPRIVS_LOWER)) +		zlog_err("%s: could not lower privs, %s", __func__, +			 safe_strerror(errno));  } -int -eigrp_if_ipmulticast(struct eigrp *top, struct prefix *p, unsigned int ifindex) +int eigrp_if_ipmulticast(struct eigrp *top, struct prefix *p, +			 unsigned int ifindex)  { -  u_char val; -  int ret, len; - -  val = 0; -  len = sizeof(val); - -  /* Prevent receiving self-origined multicast packets. */ -  ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &val, len); -  if (ret < 0) -    zlog_warn("can't setsockopt IP_MULTICAST_LOOP (0) for fd %d: %s", top->fd, -        safe_strerror(errno)); - -  /* Explicitly set multicast ttl to 1 -- endo. */ -  val = 1; -  ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *) &val, len); -  if (ret < 0) -    zlog_warn("can't setsockopt IP_MULTICAST_TTL (1) for fd %d: %s", top->fd, -              safe_strerror(errno)); - -  ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); -  if (ret < 0) -    zlog_warn("can't setsockopt IP_MULTICAST_IF (fd %d, addr %s, " -              "ifindex %u): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, -              safe_strerror(errno)); - -  return ret; +	u_char val; +	int ret, len; + +	val = 0; +	len = sizeof(val); + +	/* Prevent receiving self-origined multicast packets. */ +	ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, +			 len); +	if (ret < 0) +		zlog_warn( +			"can't setsockopt IP_MULTICAST_LOOP (0) for fd %d: %s", +			top->fd, safe_strerror(errno)); + +	/* Explicitly set multicast ttl to 1 -- endo. */ +	val = 1; +	ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, +			 len); +	if (ret < 0) +		zlog_warn("can't setsockopt IP_MULTICAST_TTL (1) for fd %d: %s", +			  top->fd, safe_strerror(errno)); + +	ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); +	if (ret < 0) +		zlog_warn( +			"can't setsockopt IP_MULTICAST_IF (fd %d, addr %s, " +			"ifindex %u): %s", +			top->fd, inet_ntoa(p->u.prefix4), ifindex, +			safe_strerror(errno)); + +	return ret;  }  /* Join to the EIGRP multicast group. */ -int -eigrp_if_add_allspfrouters(struct eigrp *top, struct prefix *p, -                           unsigned int ifindex) +int eigrp_if_add_allspfrouters(struct eigrp *top, struct prefix *p, +			       unsigned int ifindex)  { -  int ret; - -  ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP, p->u.prefix4, -                                  htonl(EIGRP_MULTICAST_ADDRESS), ifindex); -  if (ret < 0) -    zlog_warn("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " -              "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " -              "on # of multicast group memberships has been exceeded?", top->fd, -              inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); -  else -    zlog_debug("interface %s [%u] join EIGRP Multicast group.", -               inet_ntoa(p->u.prefix4), ifindex); - -  return ret; +	int ret; + +	ret = setsockopt_ipv4_multicast( +		top->fd, IP_ADD_MEMBERSHIP, p->u.prefix4, +		htonl(EIGRP_MULTICAST_ADDRESS), ifindex); +	if (ret < 0) +		zlog_warn( +			"can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " +			"ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " +			"on # of multicast group memberships has been exceeded?", +			top->fd, inet_ntoa(p->u.prefix4), ifindex, +			safe_strerror(errno)); +	else +		zlog_debug("interface %s [%u] join EIGRP Multicast group.", +			   inet_ntoa(p->u.prefix4), ifindex); + +	return ret;  } -int -eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, -                            unsigned int ifindex) +int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, +				unsigned int ifindex)  { -  int ret; - -  ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP, p->u.prefix4, -                                  htonl(EIGRP_MULTICAST_ADDRESS), ifindex); -  if (ret < 0) -    zlog_warn("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " -              "ifindex %u, AllSPFRouters): %s", top->fd, inet_ntoa(p->u.prefix4), -              ifindex, safe_strerror(errno)); -  else -    zlog_debug("interface %s [%u] leave EIGRP Multicast group.", -               inet_ntoa(p->u.prefix4), ifindex); - -  return ret; +	int ret; + +	ret = setsockopt_ipv4_multicast( +		top->fd, IP_DROP_MEMBERSHIP, p->u.prefix4, +		htonl(EIGRP_MULTICAST_ADDRESS), ifindex); +	if (ret < 0) +		zlog_warn( +			"can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " +			"ifindex %u, AllSPFRouters): %s", +			top->fd, inet_ntoa(p->u.prefix4), ifindex, +			safe_strerror(errno)); +	else +		zlog_debug("interface %s [%u] leave EIGRP Multicast group.", +			   inet_ntoa(p->u.prefix4), ifindex); + +	return ret;  } -int -eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)  { -  struct route_node *rn; -  struct interface *ifp; -  struct listnode *node; - -  rn = route_node_get(eigrp->networks, (struct prefix *) p); -  if (rn->info) -    { -      /* There is already same network statement. */ -      route_unlock_node(rn); -      return 0; -    } - -  struct prefix_ipv4 *pref = prefix_ipv4_new(); -  PREFIX_COPY_IPV4(pref,p); -  rn->info = (void *) pref; - -  /* Schedule Router ID Update. */ -  if (eigrp->router_id == 0) -    eigrp_router_id_update(eigrp); -  /* Run network config now. */ -  /* Get target interface. */ -  for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) -    { -      zlog_debug("Setting up %s", ifp->name); -      eigrp_network_run_interface(eigrp, (struct prefix *) p, ifp); -    } -  return 1; +	struct route_node *rn; +	struct interface *ifp; +	struct listnode *node; + +	rn = route_node_get(eigrp->networks, (struct prefix *)p); +	if (rn->info) { +		/* There is already same network statement. */ +		route_unlock_node(rn); +		return 0; +	} + +	struct prefix_ipv4 *pref = prefix_ipv4_new(); +	PREFIX_COPY_IPV4(pref, p); +	rn->info = (void *)pref; + +	/* Schedule Router ID Update. */ +	if (eigrp->router_id == 0) +		eigrp_router_id_update(eigrp); +	/* Run network config now. */ +	/* Get target interface. */ +	for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { +		zlog_debug("Setting up %s", ifp->name); +		eigrp_network_run_interface(eigrp, (struct prefix *)p, ifp); +	} +	return 1;  }  /* Check whether interface matches given network   * returns: 1, true. 0, false   */ -static int -eigrp_network_match_iface(const struct connected *co, const struct prefix *net) +static int eigrp_network_match_iface(const struct connected *co, +				     const struct prefix *net)  { -  /* new approach: more elegant and conceptually clean */ -  return prefix_match_network_statement(net, CONNECTED_PREFIX (co)); +	/* new approach: more elegant and conceptually clean */ +	return prefix_match_network_statement(net, CONNECTED_PREFIX(co));  } -static void -eigrp_network_run_interface(struct eigrp *eigrp, struct prefix *p, -                            struct interface *ifp) +static void eigrp_network_run_interface(struct eigrp *eigrp, struct prefix *p, +					struct interface *ifp)  { -  struct listnode *cnode; -  struct connected *co; - -  /* if interface prefix is match specified prefix, -     then create socket and join multicast group. */ -  for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co)) -    { - -      if (CHECK_FLAG (co->flags,ZEBRA_IFA_SECONDARY)) -        continue; - -      if (p->family == co->address->family -          && !eigrp_if_table_lookup(ifp, co->address) -          && eigrp_network_match_iface(co, p)) -        { -          struct eigrp_interface *ei; - -          ei = eigrp_if_new(eigrp, ifp, co->address); -          ei->connected = co; - -          ei->params = eigrp_lookup_if_params(ifp, ei->address->u.prefix4); - -          /* Relate eigrp interface to eigrp instance. */ -          ei->eigrp = eigrp; - -          /* update network type as interface flag */ -          /* If network type is specified previously, -             skip network type setting. */ -          ei->type = IF_DEF_PARAMS (ifp)->type; - -          /* if router_id is not configured, dont bring up -           * interfaces. -           * eigrp_router_id_update() will call eigrp_if_update -           * whenever r-id is configured instead. -           */ -          if (if_is_operative(ifp)) -            eigrp_if_up(ei); -        } -    } +	struct listnode *cnode; +	struct connected *co; + +	/* if interface prefix is match specified prefix, +	   then create socket and join multicast group. */ +	for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co)) { + +		if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY)) +			continue; + +		if (p->family == co->address->family +		    && !eigrp_if_table_lookup(ifp, co->address) +		    && eigrp_network_match_iface(co, p)) { +			struct eigrp_interface *ei; + +			ei = eigrp_if_new(eigrp, ifp, co->address); +			ei->connected = co; + +			ei->params = eigrp_lookup_if_params( +				ifp, ei->address->u.prefix4); + +			/* Relate eigrp interface to eigrp instance. */ +			ei->eigrp = eigrp; + +			/* update network type as interface flag */ +			/* If network type is specified previously, +			   skip network type setting. */ +			ei->type = IF_DEF_PARAMS(ifp)->type; + +			/* if router_id is not configured, dont bring up +			 * interfaces. +			 * eigrp_router_id_update() will call eigrp_if_update +			 * whenever r-id is configured instead. +			 */ +			if (if_is_operative(ifp)) +				eigrp_if_up(ei); +		} +	}  } -void -eigrp_if_update(struct interface *ifp) +void eigrp_if_update(struct interface *ifp)  { -  struct listnode *node, *nnode; -  struct route_node *rn; -  struct eigrp *eigrp; - -  /* -   * In the event there are multiple eigrp autonymnous systems running, -   * we need to check eac one and add the interface as approperate -   */ -  for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) -    { -      /* EIGRP must be on and Router-ID must be configured. */ -      if (!eigrp || eigrp->router_id == 0) -        continue; - -      /* Run each network for this interface. */ -      for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) -        if (rn->info != NULL) -          { -            eigrp_network_run_interface(eigrp, &rn->p, ifp); -          } -    } +	struct listnode *node, *nnode; +	struct route_node *rn; +	struct eigrp *eigrp; + +	/* +	 * In the event there are multiple eigrp autonymnous systems running, +	 * we need to check eac one and add the interface as approperate +	 */ +	for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) { +		/* EIGRP must be on and Router-ID must be configured. */ +		if (!eigrp || eigrp->router_id == 0) +			continue; + +		/* Run each network for this interface. */ +		for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) +			if (rn->info != NULL) { +				eigrp_network_run_interface(eigrp, &rn->p, ifp); +			} +	}  } -int -eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p)  { -  struct route_node *rn; -  struct listnode *node, *nnode; -  struct eigrp_interface *ei; -  struct prefix *pref; - -  rn = route_node_lookup(eigrp->networks, (struct prefix *) p); -  if (rn == NULL) -    return 0; - -  pref = rn->info; -  route_unlock_node (rn); - -  if (!IPV4_ADDR_SAME (&pref->u.prefix4, &p->prefix)) -    return 0; - -  prefix_ipv4_free(rn->info); -  rn->info = NULL; -  route_unlock_node(rn); /* initial reference */ - -  /* Find interfaces that not configured already.  */ -  for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) -    { -      int found = 0; -      struct connected *co = ei->connected; - -      for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) -        { -          if (rn->info == NULL) -            continue; - -          if (eigrp_network_match_iface(co, &rn->p)) -            { -              found = 1; -              route_unlock_node(rn); -              break; -            } -        } - -      if (found == 0) -        { -          eigrp_if_free(ei, INTERFACE_DOWN_BY_VTY); -        } -    } - -  return 1; +	struct route_node *rn; +	struct listnode *node, *nnode; +	struct eigrp_interface *ei; +	struct prefix *pref; + +	rn = route_node_lookup(eigrp->networks, (struct prefix *)p); +	if (rn == NULL) +		return 0; + +	pref = rn->info; +	route_unlock_node(rn); + +	if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->prefix)) +		return 0; + +	prefix_ipv4_free(rn->info); +	rn->info = NULL; +	route_unlock_node(rn); /* initial reference */ + +	/* Find interfaces that not configured already.  */ +	for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) { +		int found = 0; +		struct connected *co = ei->connected; + +		for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) { +			if (rn->info == NULL) +				continue; + +			if (eigrp_network_match_iface(co, &rn->p)) { +				found = 1; +				route_unlock_node(rn); +				break; +			} +		} + +		if (found == 0) { +			eigrp_if_free(ei, INTERFACE_DOWN_BY_VTY); +		} +	} + +	return 1;  } -u_int32_t -eigrp_calculate_metrics(struct eigrp *eigrp, struct eigrp_metrics metric) +u_int32_t eigrp_calculate_metrics(struct eigrp *eigrp, +				  struct eigrp_metrics metric)  { -  uint64_t temp_metric; -  temp_metric = 0; - -  if(metric.delay == EIGRP_MAX_METRIC) -    return EIGRP_MAX_METRIC; - -  // EIGRP Metric = {K1*BW+[(K2*BW)/(256-load)]+(K3*delay)}*{K5/(reliability+K4)} - -  if (eigrp->k_values[0]) -    temp_metric += (eigrp->k_values[0] * metric.bandwith); -  if (eigrp->k_values[1]) -    temp_metric += ((eigrp->k_values[1] * metric.bandwith) -                    / (256 - metric.load)); -  if (eigrp->k_values[2]) -    temp_metric += (eigrp->k_values[2] * metric.delay); -  if (eigrp->k_values[3] && !eigrp->k_values[4]) -    temp_metric *= eigrp->k_values[3]; -  if (!eigrp->k_values[3] && eigrp->k_values[4]) -    temp_metric *= (eigrp->k_values[4] / metric.reliability); -  if (eigrp->k_values[3] && eigrp->k_values[4]) -    temp_metric *= ((eigrp->k_values[4] / metric.reliability) -                    + eigrp->k_values[3]); - -  if (temp_metric <= EIGRP_MAX_METRIC) -    return (u_int32_t) temp_metric; -  else -    return EIGRP_MAX_METRIC; +	uint64_t temp_metric; +	temp_metric = 0; + +	if (metric.delay == EIGRP_MAX_METRIC) +		return EIGRP_MAX_METRIC; + +	// EIGRP Metric = +	// {K1*BW+[(K2*BW)/(256-load)]+(K3*delay)}*{K5/(reliability+K4)} + +	if (eigrp->k_values[0]) +		temp_metric += (eigrp->k_values[0] * metric.bandwith); +	if (eigrp->k_values[1]) +		temp_metric += ((eigrp->k_values[1] * metric.bandwith) +				/ (256 - metric.load)); +	if (eigrp->k_values[2]) +		temp_metric += (eigrp->k_values[2] * metric.delay); +	if (eigrp->k_values[3] && !eigrp->k_values[4]) +		temp_metric *= eigrp->k_values[3]; +	if (!eigrp->k_values[3] && eigrp->k_values[4]) +		temp_metric *= (eigrp->k_values[4] / metric.reliability); +	if (eigrp->k_values[3] && eigrp->k_values[4]) +		temp_metric *= ((eigrp->k_values[4] / metric.reliability) +				+ eigrp->k_values[3]); + +	if (temp_metric <= EIGRP_MAX_METRIC) +		return (u_int32_t)temp_metric; +	else +		return EIGRP_MAX_METRIC;  } -u_int32_t -eigrp_calculate_total_metrics(struct eigrp *eigrp, -                              struct eigrp_neighbor_entry *entry) +u_int32_t eigrp_calculate_total_metrics(struct eigrp *eigrp, +					struct eigrp_neighbor_entry *entry)  { -  entry->total_metric = entry->reported_metric; -  uint64_t temp_delay = (uint64_t) entry->total_metric.delay -    + (uint64_t) eigrp_delay_to_scaled (EIGRP_IF_PARAM (entry->ei, delay)); -  entry->total_metric.delay = -    temp_delay > EIGRP_MAX_METRIC ? EIGRP_MAX_METRIC : (u_int32_t) temp_delay; - -  u_int32_t bw = eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (entry->ei,bandwidth)); -  entry->total_metric.bandwith = -    entry->total_metric.bandwith > bw ? bw : entry->total_metric.bandwith; - -  return eigrp_calculate_metrics(eigrp, entry->total_metric); +	entry->total_metric = entry->reported_metric; +	uint64_t temp_delay = (uint64_t)entry->total_metric.delay +			      + (uint64_t)eigrp_delay_to_scaled( +					EIGRP_IF_PARAM(entry->ei, delay)); +	entry->total_metric.delay = temp_delay > EIGRP_MAX_METRIC +					    ? EIGRP_MAX_METRIC +					    : (u_int32_t)temp_delay; + +	u_int32_t bw = +		eigrp_bandwidth_to_scaled(EIGRP_IF_PARAM(entry->ei, bandwidth)); +	entry->total_metric.bandwith = entry->total_metric.bandwith > bw +					       ? bw +					       : entry->total_metric.bandwith; + +	return eigrp_calculate_metrics(eigrp, entry->total_metric);  } -u_char -eigrp_metrics_is_same(struct eigrp_metrics metric1, -                      struct eigrp_metrics metric2) +u_char eigrp_metrics_is_same(struct eigrp_metrics metric1, +			     struct eigrp_metrics metric2)  { -  if ((metric1.bandwith == metric2.bandwith) -      && (metric1.delay == metric2.delay) -      && (metric1.hop_count == metric2.hop_count) -      && (metric1.load == metric2.load) -      && (metric1.reliability == metric2.reliability) -      && (metric1.mtu[0] == metric2.mtu[0]) -      && (metric1.mtu[1] == metric2.mtu[1]) -      && (metric1.mtu[2] == metric2.mtu[2])) -      return 1; - -  return 0; // if different +	if ((metric1.bandwith == metric2.bandwith) +	    && (metric1.delay == metric2.delay) +	    && (metric1.hop_count == metric2.hop_count) +	    && (metric1.load == metric2.load) +	    && (metric1.reliability == metric2.reliability) +	    && (metric1.mtu[0] == metric2.mtu[0]) +	    && (metric1.mtu[1] == metric2.mtu[1]) +	    && (metric1.mtu[2] == metric2.mtu[2])) +		return 1; + +	return 0; // if different  } -void -eigrp_external_routes_refresh (struct eigrp *eigrp, int type) +void eigrp_external_routes_refresh(struct eigrp *eigrp, int type)  { -  } -  | 
