Browse Source

ospf6d: compute interface cost from its bandwidth

Previously, the interface cost was a fixed default value that a user
was allowed to change with "ipv6 ospf6 cost XX". As what is done with
OSPFv2, we change this behaviour to compute the default interface cost
from the interface bandwidth.

The user can still force a cost with "ipv6 ospf6 cost XX". He can get
the default value with "no ipv6 ospf6 cost". Moreover, the default
cost value was 1. The cost is now computed from the bandwidth and a
default reference bandwidth of 100 MBps (as for OSPFv2). Since the
default bandwidth for an interface is 10 MBps, the "default" cost
becomes 10 instead of 1.

[DL: resolved conflict in ospf6d/ospf6_interface.c]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Vincent Bernat 7 years ago
parent
commit
c19543b223
5 changed files with 92 additions and 18 deletions
  1. 1 1
      doc/ospf6d.texi
  2. 1 1
      ospf6d/README
  3. 84 14
      ospf6d/ospf6_interface.c
  4. 4 0
      ospf6d/ospf6_interface.h
  5. 2 2
      ospf6d/ospf6_zebra.c

+ 1 - 1
doc/ospf6d.texi

@@ -75,7 +75,7 @@ Area support for OSPFv3 is not yet implemented.
 @section OSPF6 interface
 
 @deffn {Interface Command} {ipv6 ospf6 cost COST} {}
-Sets interface's output cost.  Default value is 1.
+Sets interface's output cost.  Default value depends on the interface bandwidth.
 @end deffn
 
 @deffn {Interface Command} {ipv6 ospf6 hello-interval HELLOINTERVAL} {}

+ 1 - 1
ospf6d/README

@@ -60,7 +60,7 @@ CONFIG NODE:
 
 INTERFACE NODE:
   ipv6 ospf6 cost COST
-    Sets the interface's output cost. default 1
+    Sets the interface's output cost. Depends on interface bandwidth by default.
 
   ipv6 ospf6 hello-interval HELLOINTERVAL
     Sets the interface's Hello Interval. default 10

+ 84 - 14
ospf6d/ospf6_interface.c

@@ -117,6 +117,52 @@ ospf6_default_iftype(struct interface *ifp)
     return OSPF_IFTYPE_BROADCAST;
 }
 
+static u_int32_t
+ospf6_interface_get_cost (struct ospf6_interface *oi)
+{
+  /* If all else fails, use default OSPF cost */
+  u_int32_t cost;
+  u_int32_t bw, refbw;
+
+  bw = oi->interface->bandwidth ? oi->interface->bandwidth : OSPF6_INTERFACE_BANDWIDTH;
+  refbw = OSPF6_REFERENCE_BANDWIDTH;
+
+  /* A specifed ip ospf cost overrides a calculated one. */
+  if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
+    cost = oi->cost;
+  else
+    {
+      cost = (u_int32_t) ((double)refbw / (double)bw + (double)0.5);
+      if (cost < 1) cost = 1;
+      else if (cost > UINT32_MAX) cost = UINT32_MAX;
+    }
+
+  return cost;
+}
+
+static void
+ospf6_interface_recalculate_cost (struct ospf6_interface *oi)
+{
+  u_int32_t newcost;
+
+  newcost = ospf6_interface_get_cost (oi);
+  if (newcost == oi->cost) return;
+  oi->cost = newcost;
+
+  /* update cost held in route_connected list in ospf6_interface */
+  ospf6_interface_connected_route_update (oi->interface);
+
+  /* execute LSA hooks */
+  if (oi->area)
+    {
+      OSPF6_LINK_LSA_SCHEDULE (oi);
+      OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
+      OSPF6_NETWORK_LSA_SCHEDULE (oi);
+      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
+    }
+}
+
 /* Create new ospf6 interface structure */
 struct ospf6_interface *
 ospf6_interface_create (struct interface *ifp)
@@ -144,7 +190,6 @@ ospf6_interface_create (struct interface *ifp)
   oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
   oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
   oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
-  oi->cost = OSPF6_INTERFACE_COST;
   oi->type = ospf6_default_iftype (ifp);
   oi->state = OSPF6_INTERFACE_DOWN;
   oi->flag = 0;
@@ -175,6 +220,9 @@ ospf6_interface_create (struct interface *ifp)
   oi->interface = ifp;
   ifp->info = oi;
 
+  /* Compute cost. */
+  oi->cost = ospf6_interface_get_cost(oi);
+
   return oi;
 }
 
@@ -658,6 +706,9 @@ interface_up (struct thread *thread)
 	return 0;
     }
 
+  /* Recompute cost */
+  ospf6_interface_recalculate_cost (oi);
+
   /* if already enabled, do nothing */
   if (oi->state > OSPF6_INTERFACE_DOWN)
     {
@@ -1214,19 +1265,37 @@ DEFUN (ipv6_ospf6_cost,
     return CMD_SUCCESS;
   
   oi->cost = lcost;
-  
-  /* update cost held in route_connected list in ospf6_interface */
-  ospf6_interface_connected_route_update (oi->interface);
+  SET_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
 
-  /* execute LSA hooks */
-  if (oi->area)
-    {
-      OSPF6_LINK_LSA_SCHEDULE (oi);
-      OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
-      OSPF6_NETWORK_LSA_SCHEDULE (oi);
-      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
-      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
-    }
+  ospf6_interface_recalculate_cost(oi);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_ospf6_cost,
+       no_ipv6_ospf6_cost_cmd,
+       "no ipv6 ospf6 cost",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Calculate interface cost from bandwidth\n"
+       )
+{
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+  unsigned long int lcost;
+
+  ifp = (struct interface *) vty->index;
+  assert (ifp);
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL)
+    oi = ospf6_interface_create (ifp);
+  assert (oi);
+
+  UNSET_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
+
+  ospf6_interface_recalculate_cost(oi);
 
   return CMD_SUCCESS;
 }
@@ -1681,7 +1750,7 @@ config_write_ospf6_interface (struct vty *vty)
       if (ifp->mtu6 != oi->ifmtu)
         vty_out (vty, " ipv6 ospf6 ifmtu %d%s", oi->ifmtu, VNL);
 
-      if (oi->cost != OSPF6_INTERFACE_COST)
+      if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
         vty_out (vty, " ipv6 ospf6 cost %d%s",
                  oi->cost, VNL);
 
@@ -1764,6 +1833,7 @@ ospf6_interface_init (void)
   install_element (INTERFACE_NODE, &interface_desc_cmd);
   install_element (INTERFACE_NODE, &no_interface_desc_cmd);
   install_element (INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
+  install_element (INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
   install_element (INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
   install_element (INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);

+ 4 - 0
ospf6d/ospf6_interface.h

@@ -128,6 +128,7 @@ extern const char *ospf6_interface_state_str[];
 /* flags */
 #define OSPF6_INTERFACE_DISABLE      0x01
 #define OSPF6_INTERFACE_PASSIVE      0x02
+#define OSPF6_INTERFACE_NOAUTOCOST   0x04
 
 /* default values */
 #define OSPF6_INTERFACE_HELLO_INTERVAL 10
@@ -137,6 +138,9 @@ extern const char *ospf6_interface_state_str[];
 #define OSPF6_INTERFACE_PRIORITY       1
 #define OSPF6_INTERFACE_TRANSDELAY     1
 #define OSPF6_INTERFACE_INSTANCE_ID    0
+#define OSPF6_INTERFACE_BANDWIDTH      10000   /* Kbps */
+#define OSPF6_REFERENCE_BANDWIDTH      100000  /* Kbps */
+
 
 
 /* Function Prototypes */

+ 2 - 2
ospf6d/ospf6_zebra.c

@@ -139,9 +139,9 @@ ospf6_zebra_if_state_update (int command, struct zclient *zclient,
   
   if (IS_OSPF6_DEBUG_ZEBRA (RECV))
     zlog_debug ("Zebra Interface state change: "
-                "%s index %d flags %llx metric %d mtu %d",
+                "%s index %d flags %llx metric %d mtu %d bandwidth %d",
 		ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, 
-		ifp->metric, ifp->mtu6);
+		ifp->metric, ifp->mtu6, ifp->bandwidth);
 
   ospf6_interface_state_update (ifp);
   return 0;