]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospf6d/ospf6_interface.c
ospfd, ospf6d: add qobj registrations
[mirror_frr.git] / ospf6d / ospf6_interface.c
index 94b599be5641000f962a8145110a5d58e226f039..dd63f00c7ee05788e1489b6dfd4e72117e5e1afd 100644 (file)
@@ -28,6 +28,7 @@
 #include "thread.h"
 #include "prefix.h"
 #include "plist.h"
+#include "zclient.h"
 
 #include "ospf6_lsa.h"
 #include "ospf6_lsdb.h"
 #include "ospf6_neighbor.h"
 #include "ospf6_intra.h"
 #include "ospf6_spf.h"
+#include "ospf6_snmp.h"
 #include "ospf6d.h"
+#include "ospf6_bfd.h"
+
+DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names")
+DEFINE_QOBJ_TYPE(ospf6_interface)
 
 unsigned char conf_debug_ospf6_interface = 0;
 
@@ -58,7 +64,7 @@ const char *ospf6_interface_state_str[] =
 };
 
 struct ospf6_interface *
-ospf6_interface_lookup_by_ifindex (int ifindex)
+ospf6_interface_lookup_by_ifindex (ifindex_t ifindex)
 {
   struct ospf6_interface *oi;
   struct interface *ifp;
@@ -73,7 +79,7 @@ ospf6_interface_lookup_by_ifindex (int ifindex)
 
 /* schedule routing table recalculation */
 static void
-ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
+ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa, unsigned int reason)
 {
   struct ospf6_interface *oi;
 
@@ -86,7 +92,8 @@ ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
       case OSPF6_LSTYPE_LINK:
         if (oi->state == OSPF6_INTERFACE_DR)
           OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
-        ospf6_spf_schedule (oi->area->ospf6);
+        if (oi->area)
+          ospf6_spf_schedule (oi->area->ospf6, reason);
         break;
 
       default:
@@ -94,6 +101,18 @@ ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
     }
 }
 
+static void
+ospf6_interface_lsdb_hook_add (struct ospf6_lsa *lsa)
+{
+  ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
+}
+
+static void
+ospf6_interface_lsdb_hook_remove (struct ospf6_lsa *lsa)
+{
+  ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
+}
+
 static u_char
 ospf6_default_iftype(struct interface *ifp)
 {
@@ -105,6 +124,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 ? ospf6->ref_bandwidth : 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)
@@ -132,7 +197,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;
@@ -149,11 +213,13 @@ ospf6_interface_create (struct interface *ifp)
       oi->ifmtu = iobuflen;
     }
 
+  QOBJ_REG (oi, ospf6_interface);
+
   oi->lsupdate_list = ospf6_lsdb_create (oi);
   oi->lsack_list = ospf6_lsdb_create (oi);
   oi->lsdb = ospf6_lsdb_create (oi);
-  oi->lsdb->hook_add = ospf6_interface_lsdb_hook;
-  oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;
+  oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
+  oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
   oi->lsdb_self = ospf6_lsdb_create (oi);
 
   oi->route_connected = OSPF6_ROUTE_TABLE_CREATE (INTERFACE, CONNECTED_ROUTES);
@@ -163,6 +229,9 @@ ospf6_interface_create (struct interface *ifp)
   oi->interface = ifp;
   ifp->info = oi;
 
+  /* Compute cost. */
+  oi->cost = ospf6_interface_get_cost(oi);
+
   return oi;
 }
 
@@ -172,6 +241,8 @@ ospf6_interface_delete (struct ospf6_interface *oi)
   struct listnode *node, *nnode;
   struct ospf6_neighbor *on;
 
+  QOBJ_UNREG (oi);
+
   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
       ospf6_neighbor_delete (on);
   
@@ -198,7 +269,9 @@ ospf6_interface_delete (struct ospf6_interface *oi)
 
   /* plist_name */
   if (oi->plist_name)
-    XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
+    XFREE (MTYPE_CFG_PLIST_NAME, oi->plist_name);
+
+  ospf6_bfd_info_free(&(oi->bfd_info));
 
   XFREE (MTYPE_OSPF6_IF, oi);
 }
@@ -207,31 +280,28 @@ void
 ospf6_interface_enable (struct ospf6_interface *oi)
 {
   UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
-
-  oi->thread_send_hello =
-    thread_add_event (master, ospf6_hello_send, oi, 0);
+  ospf6_interface_state_update (oi->interface);
 }
 
 void
 ospf6_interface_disable (struct ospf6_interface *oi)
 {
-  struct listnode *node, *nnode;
-  struct ospf6_neighbor *on;
-
   SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
 
-  for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
-      ospf6_neighbor_delete (on);
-
-  list_delete_all_node (oi->neighbor_list);
+  thread_execute (master, interface_down, oi, 0);
 
   ospf6_lsdb_remove_all (oi->lsdb);
+  ospf6_lsdb_remove_all (oi->lsdb_self);
   ospf6_lsdb_remove_all (oi->lsupdate_list);
   ospf6_lsdb_remove_all (oi->lsack_list);
 
   THREAD_OFF (oi->thread_send_hello);
   THREAD_OFF (oi->thread_send_lsupdate);
   THREAD_OFF (oi->thread_send_lsack);
+
+  THREAD_OFF (oi->thread_network_lsa);
+  THREAD_OFF (oi->thread_link_lsa);
+  THREAD_OFF (oi->thread_intra_prefix_lsa);
 }
 
 static struct in6_addr *
@@ -278,8 +348,7 @@ ospf6_interface_if_add (struct interface *ifp)
     }
 
   /* interface start */
-  if (oi->area)
-    thread_add_event (master, interface_up, oi, 0);
+  ospf6_interface_state_update(oi->interface);
 }
 
 void
@@ -315,8 +384,12 @@ ospf6_interface_state_update (struct interface *ifp)
     return;
   if (oi->area == NULL)
     return;
+  if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
+    return;
 
-  if (if_is_up (ifp))
+  if (if_is_operative (ifp)
+      && (ospf6_interface_get_linklocal_address(oi->interface)
+          || if_is_loopback(oi->interface)))
     thread_add_event (master, interface_up, oi, 0);
   else
     thread_add_event (master, interface_down, oi, 0);
@@ -331,6 +404,7 @@ ospf6_interface_connected_route_update (struct interface *ifp)
   struct ospf6_route *route;
   struct connected *c;
   struct listnode *node, *nnode;
+  struct in6_addr nh_addr;
 
   oi = (struct ospf6_interface *) ifp->info;
   if (oi == NULL)
@@ -343,6 +417,9 @@ ospf6_interface_connected_route_update (struct interface *ifp)
   if (oi->area == NULL)
     return;
 
+  if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
+    return;
+
   /* update "route to advertise" interface route table */
   ospf6_route_remove_all (oi->route_connected);
 
@@ -362,7 +439,7 @@ ospf6_interface_connected_route_update (struct interface *ifp)
         {
           struct prefix_list *plist;
           enum prefix_list_type ret;
-          char buf[128];
+          char buf[PREFIX2STR_BUFFER];
 
           prefix2str (c->address, buf, sizeof (buf));
           plist = prefix_list_lookup (AFI_IP6, oi->plist_name);
@@ -383,8 +460,8 @@ ospf6_interface_connected_route_update (struct interface *ifp)
       route->path.area_id = oi->area->area_id;
       route->path.type = OSPF6_PATH_TYPE_INTRA;
       route->path.cost = oi->cost;
-      route->nexthop[0].ifindex = oi->interface->ifindex;
-      inet_pton (AF_INET6, "::1", &route->nexthop[0].address);
+      inet_pton (AF_INET6, "::1", &nh_addr);
+      ospf6_route_add_nexthop (route, oi->interface->ifindex, &nh_addr);
       ospf6_route_add (route, oi->route_connected);
     }
 
@@ -453,7 +530,7 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
 
 }
 
-\f
+
 /* DR Election, RFC2328 section 9.4 */
 
 #define IS_ELIGIBLE(n) \
@@ -610,7 +687,7 @@ dr_election (struct ospf6_interface *oi)
   return next_state;
 }
 
-\f
+
 /* Interface State Machine */
 int
 interface_up (struct thread *thread)
@@ -625,7 +702,7 @@ interface_up (struct thread *thread)
                oi->interface->name);
 
   /* check physical interface is up */
-  if (! if_is_up (oi->interface))
+  if (! if_is_operative (oi->interface))
     {
       if (IS_OSPF6_DEBUG_INTERFACE)
         zlog_debug ("Interface %s is down, can't execute [InterfaceUp]",
@@ -633,6 +710,19 @@ interface_up (struct thread *thread)
       return 0;
     }
 
+  /* check interface has a link-local address */
+  if (! (ospf6_interface_get_linklocal_address(oi->interface)
+         || if_is_loopback(oi->interface)))
+    {
+      if (IS_OSPF6_DEBUG_INTERFACE)
+       zlog_debug ("Interface %s has no link local address, can't execute [InterfaceUp]",
+                   oi->interface->name);
+       return 0;
+    }
+
+  /* Recompute cost */
+  ospf6_interface_recalculate_cost (oi);
+
   /* if already enabled, do nothing */
   if (oi->state > OSPF6_INTERFACE_DOWN)
     {
@@ -642,15 +732,35 @@ interface_up (struct thread *thread)
       return 0;
     }
 
+  /* If no area assigned, return */
+  if (oi->area == NULL)
+    {
+      zlog_debug ("%s: Not scheduleing Hello for %s as there is no area assigned yet", __func__,
+                 oi->interface->name);
+      return 0;
+    }
+
   /* Join AllSPFRouters */
-  ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP);
+  if (ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP) < 0)
+    {
+      if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX)
+        {
+          zlog_info("Scheduling %s for sso retry, trial count: %d",
+                    oi->interface->name, oi->sso_try_cnt);
+          thread_add_timer (master, interface_up, oi,
+                            OSPF6_INTERFACE_SSO_RETRY_INT);
+        }
+      return 0;
+    }
+  oi->sso_try_cnt = 0; /* Reset on success */
 
   /* Update interface route */
   ospf6_interface_connected_route_update (oi->interface);
 
   /* Schedule Hello */
-  if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
-    thread_add_event (master, ospf6_hello_send, oi, 0);
+  if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE) &&
+      !if_is_loopback (oi->interface))
+    oi->thread_send_hello = thread_add_event (master, ospf6_hello_send, oi, 0);
 
   /* decide next interface state */
   if ((if_is_pointopoint (oi->interface)) ||
@@ -738,6 +848,9 @@ interface_down (struct thread *thread)
     zlog_debug ("Interface Event %s: [InterfaceDown]",
                oi->interface->name);
 
+  /* Stop Hellos */
+  THREAD_OFF (oi->thread_send_hello);
+
   /* Leave AllSPFRouters */
   if (oi->state > OSPF6_INTERFACE_DOWN)
     ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_LEAVE_GROUP);
@@ -749,10 +862,14 @@ interface_down (struct thread *thread)
   
   list_delete_all_node (oi->neighbor_list);
 
+  /* When interface state is reset, also reset information about
+   * DR election, as it is no longer valid. */
+  oi->drouter = oi->prev_drouter = htonl(0);
+  oi->bdrouter = oi->prev_bdrouter = htonl(0);
   return 0;
 }
 
-\f
+
 /* show specified interface structure */
 static int
 ospf6_interface_show (struct vty *vty, struct interface *ifp)
@@ -761,7 +878,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
   struct connected *c;
   struct prefix *p;
   struct listnode *i;
-  char strbuf[64], drouter[32], bdrouter[32];
+  char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32];
   const char *updown[3] = {"down", "up", NULL};
   const char *type;
   struct timeval res, now;
@@ -779,7 +896,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
     type = "UNKNOWN";
 
   vty_out (vty, "%s is %s, type %s%s",
-           ifp->name, updown[if_is_up (ifp)], type,
+           ifp->name, updown[if_is_operative (ifp)], type,
           VNL);
   vty_out (vty, "  Interface ID: %d%s", ifp->ifindex, VNL);
 
@@ -822,7 +939,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
               "disabled" : "enabled", VNL);
       inet_ntop (AF_INET, &oi->area->area_id,
                  strbuf, sizeof (strbuf));
-      vty_out (vty, "  Area ID %s, Cost %hu%s", strbuf, oi->cost,
+      vty_out (vty, "  Area ID %s, Cost %u%s", strbuf, oi->cost,
               VNL);
     }
   else
@@ -869,30 +986,30 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
   for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     vty_out (vty, "      %s%s", lsa->name, VNL);
-
+  ospf6_bfd_show_info(vty, oi->bfd_info, 1);
   return 0;
 }
 
 /* show interface */
 DEFUN (show_ipv6_ospf6_interface,
        show_ipv6_ospf6_interface_ifname_cmd,
-       "show ipv6 ospf6 interface IFNAME",
+       "show ipv6 ospf6 interface [IFNAME]",
        SHOW_STR
        IP6_STR
        OSPF6_STR
        INTERFACE_STR
-       IFNAME_STR
-       )
+       IFNAME_STR)
 {
+  int idx_ifname = 4;
   struct interface *ifp;
   struct listnode *i;
 
-  if (argc)
+  if (argc == 5)
     {
-      ifp = if_lookup_by_name (argv[0]);
+      ifp = if_lookup_by_name (argv[idx_ifname]->arg);
       if (ifp == NULL)
         {
-          vty_out (vty, "No such Interface: %s%s", argv[0],
+          vty_out (vty, "No such Interface: %s%s", argv[idx_ifname]->arg,
                    VNL);
           return CMD_WARNING;
         }
@@ -900,148 +1017,92 @@ DEFUN (show_ipv6_ospf6_interface,
     }
   else
     {
-      for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
+      for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, ifp))
         ospf6_interface_show (vty, ifp);
     }
 
   return CMD_SUCCESS;
 }
 
-ALIAS (show_ipv6_ospf6_interface,
-       show_ipv6_ospf6_interface_cmd,
-       "show ipv6 ospf6 interface",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       INTERFACE_STR
-       )
-
 DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
        show_ipv6_ospf6_interface_ifname_prefix_cmd,
-       "show ipv6 ospf6 interface IFNAME prefix",
+       "show ipv6 ospf6 interface IFNAME prefix [<X:X::X:X|X:X::X:X/M>] [<match|detail>]",
        SHOW_STR
        IP6_STR
        OSPF6_STR
        INTERFACE_STR
        IFNAME_STR
        "Display connected prefixes to advertise\n"
-       )
+       OSPF6_ROUTE_ADDRESS_STR
+       OSPF6_ROUTE_PREFIX_STR
+       OSPF6_ROUTE_MATCH_STR
+       "Display details of the prefixes\n")
 {
+  int idx_ifname = 4;
+  int idx_prefix = 6;
   struct interface *ifp;
   struct ospf6_interface *oi;
 
-  ifp = if_lookup_by_name (argv[0]);
+  ifp = if_lookup_by_name (argv[idx_ifname]->arg);
   if (ifp == NULL)
     {
-      vty_out (vty, "No such Interface: %s%s", argv[0], VNL);
+      vty_out (vty, "No such Interface: %s%s", argv[idx_ifname]->arg, VNL);
       return CMD_WARNING;
     }
 
   oi = ifp->info;
   if (oi == NULL)
     {
-      vty_out (vty, "OSPFv3 is not enabled on %s%s", argv[0], VNL);
+      vty_out (vty, "OSPFv3 is not enabled on %s%s", argv[idx_ifname]->arg, VNL);
       return CMD_WARNING;
     }
 
-  argc--;
-  argv++;
-  ospf6_route_table_show (vty, argc, argv, oi->route_connected);
+  ospf6_route_table_show (vty, idx_prefix, argc, argv, oi->route_connected);
 
   return CMD_SUCCESS;
 }
 
-ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
-       show_ipv6_ospf6_interface_ifname_prefix_detail_cmd,
-       "show ipv6 ospf6 interface IFNAME prefix (X:X::X:X|X:X::X:X/M|detail)",
+DEFUN (show_ipv6_ospf6_interface_prefix,
+       show_ipv6_ospf6_interface_prefix_cmd,
+       "show ipv6 ospf6 interface prefix [<X:X::X:X|X:X::X:X/M>] [<match|detail>]",
        SHOW_STR
        IP6_STR
        OSPF6_STR
        INTERFACE_STR
-       IFNAME_STR
        "Display connected prefixes to advertise\n"
        OSPF6_ROUTE_ADDRESS_STR
        OSPF6_ROUTE_PREFIX_STR
-       "Display details of the prefixes\n"
-       )
-
-ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
-       show_ipv6_ospf6_interface_ifname_prefix_match_cmd,
-       "show ipv6 ospf6 interface IFNAME prefix X:X::X:X/M (match|detail)",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       INTERFACE_STR
-       IFNAME_STR
-       "Display connected prefixes to advertise\n"
-       OSPF6_ROUTE_PREFIX_STR
        OSPF6_ROUTE_MATCH_STR
-       "Display details of the prefixes\n"
-       )
-
-DEFUN (show_ipv6_ospf6_interface_prefix,
-       show_ipv6_ospf6_interface_prefix_cmd,
-       "show ipv6 ospf6 interface prefix",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       INTERFACE_STR
-       "Display connected prefixes to advertise\n"
-       )
+       "Display details of the prefixes\n")
 {
+  int idx_prefix = 5;
   struct listnode *i;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
-  for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, ifp))
     {
       oi = (struct ospf6_interface *) ifp->info;
       if (oi == NULL)
         continue;
 
-      ospf6_route_table_show (vty, argc, argv, oi->route_connected);
+      ospf6_route_table_show (vty, idx_prefix, argc, argv, oi->route_connected);
     }
 
   return CMD_SUCCESS;
 }
 
-ALIAS (show_ipv6_ospf6_interface_prefix,
-       show_ipv6_ospf6_interface_prefix_detail_cmd,
-       "show ipv6 ospf6 interface prefix (X:X::X:X|X:X::X:X/M|detail)",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       INTERFACE_STR
-       "Display connected prefixes to advertise\n"
-       OSPF6_ROUTE_ADDRESS_STR
-       OSPF6_ROUTE_PREFIX_STR
-       "Display details of the prefixes\n"
-       )
-
-ALIAS (show_ipv6_ospf6_interface_prefix,
-       show_ipv6_ospf6_interface_prefix_match_cmd,
-       "show ipv6 ospf6 interface prefix X:X::X:X/M (match|detail)",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       INTERFACE_STR
-       "Display connected prefixes to advertise\n"
-       OSPF6_ROUTE_PREFIX_STR
-       OSPF6_ROUTE_MATCH_STR
-       "Display details of the prefixes\n"
-       )
-
-
 /* interface variable set command */
 DEFUN (ipv6_ospf6_ifmtu,
        ipv6_ospf6_ifmtu_cmd,
-       "ipv6 ospf6 ifmtu <1-65535>",
+       "ipv6 ospf6 ifmtu (1-65535)",
        IP6_STR
        OSPF6_STR
        "Interface MTU\n"
        "OSPFv3 Interface MTU\n"
        )
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
   unsigned int ifmtu, iobuflen;
@@ -1056,7 +1117,7 @@ DEFUN (ipv6_ospf6_ifmtu,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  ifmtu = strtol (argv[0], NULL, 10);
+  ifmtu = strtol (argv[idx_number]->arg, NULL, 10);
 
   if (oi->ifmtu == ifmtu)
     return CMD_SUCCESS;
@@ -1143,13 +1204,14 @@ DEFUN (no_ipv6_ospf6_ifmtu,
 
 DEFUN (ipv6_ospf6_cost,
        ipv6_ospf6_cost_cmd,
-       "ipv6 ospf6 cost <1-65535>",
+       "ipv6 ospf6 cost (1-65535)",
        IP6_STR
        OSPF6_STR
        "Interface cost\n"
        "Outgoing metric of this interface\n"
        )
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
   unsigned long int lcost;
@@ -1162,7 +1224,7 @@ DEFUN (ipv6_ospf6_cost,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  lcost = strtol (argv[0], NULL, 10);
+  lcost = strtol (argv[idx_number]->arg, NULL, 10);
 
   if (lcost > UINT32_MAX)
     {
@@ -1174,32 +1236,108 @@ 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_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;
+
+  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;
+}
+
+DEFUN (auto_cost_reference_bandwidth,
+       auto_cost_reference_bandwidth_cmd,
+       "auto-cost reference-bandwidth (1-4294967)",
+       "Calculate OSPF interface cost according to bandwidth\n"
+       "Use reference bandwidth method to assign OSPF cost\n"
+       "The reference bandwidth in terms of Mbits per second\n")
+{
+  int idx_number = 2;
+  struct ospf6 *o = vty->index;
+  struct ospf6_area *oa;
+  struct ospf6_interface *oi;
+  struct listnode *i, *j;
+  u_int32_t refbw;
+
+  refbw = strtol (argv[idx_number]->arg, NULL, 10);
+  if (refbw < 1 || refbw > 4294967)
     {
-      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);
+      vty_out (vty, "reference-bandwidth value is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
     }
 
+  /* If reference bandwidth is changed. */
+  if ((refbw) == o->ref_bandwidth)
+    return CMD_SUCCESS;
+
+  o->ref_bandwidth = refbw;
+  for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
+      for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
+          ospf6_interface_recalculate_cost (oi);
+
   return CMD_SUCCESS;
 }
 
+DEFUN (no_auto_cost_reference_bandwidth,
+       no_auto_cost_reference_bandwidth_cmd,
+       "no auto-cost reference-bandwidth [(1-4294967)]",
+       NO_STR
+       "Calculate OSPF interface cost according to bandwidth\n"
+       "Use reference bandwidth method to assign OSPF cost\n"
+       "The reference bandwidth in terms of Mbits per second\n")
+{
+  struct ospf6 *o = vty->index;
+  struct ospf6_area *oa;
+  struct ospf6_interface *oi;
+  struct listnode *i, *j;
+
+  if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH)
+    return CMD_SUCCESS;
+
+  o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
+  for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
+      for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
+          ospf6_interface_recalculate_cost (oi);
+
+  return CMD_SUCCESS;
+}
+
+
 DEFUN (ipv6_ospf6_hellointerval,
        ipv6_ospf6_hellointerval_cmd,
-       "ipv6 ospf6 hello-interval <1-65535>",
+       "ipv6 ospf6 hello-interval (1-65535)",
        IP6_STR
        OSPF6_STR
-       "Interval time of Hello packets\n"
+       "Time between HELLO packets\n"
        SECONDS_STR
        )
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1211,20 +1349,21 @@ DEFUN (ipv6_ospf6_hellointerval,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  oi->hello_interval = strtol (argv[0], NULL, 10);
+  oi->hello_interval = strtol (argv[idx_number]->arg, NULL, 10);
   return CMD_SUCCESS;
 }
 
 /* interface variable set command */
 DEFUN (ipv6_ospf6_deadinterval,
        ipv6_ospf6_deadinterval_cmd,
-       "ipv6 ospf6 dead-interval <1-65535>",
+       "ipv6 ospf6 dead-interval (1-65535)",
        IP6_STR
        OSPF6_STR
        "Interval time after which a neighbor is declared down\n"
        SECONDS_STR
        )
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1236,20 +1375,20 @@ DEFUN (ipv6_ospf6_deadinterval,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  oi->dead_interval = strtol (argv[0], NULL, 10);
+  oi->dead_interval = strtol (argv[idx_number]->arg, NULL, 10);
   return CMD_SUCCESS;
 }
 
 /* interface variable set command */
 DEFUN (ipv6_ospf6_transmitdelay,
        ipv6_ospf6_transmitdelay_cmd,
-       "ipv6 ospf6 transmit-delay <1-3600>",
+       "ipv6 ospf6 transmit-delay (1-3600)",
        IP6_STR
        OSPF6_STR
-       "Transmit delay of this interface\n"
-       SECONDS_STR
-       )
+       "Link state transmit delay\n"
+       SECONDS_STR)
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1261,20 +1400,21 @@ DEFUN (ipv6_ospf6_transmitdelay,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  oi->transdelay = strtol (argv[0], NULL, 10);
+  oi->transdelay = strtol (argv[idx_number]->arg, NULL, 10);
   return CMD_SUCCESS;
 }
 
 /* interface variable set command */
 DEFUN (ipv6_ospf6_retransmitinterval,
        ipv6_ospf6_retransmitinterval_cmd,
-       "ipv6 ospf6 retransmit-interval <1-65535>",
+       "ipv6 ospf6 retransmit-interval (1-65535)",
        IP6_STR
        OSPF6_STR
        "Time between retransmitting lost link state advertisements\n"
        SECONDS_STR
        )
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1286,20 +1426,21 @@ DEFUN (ipv6_ospf6_retransmitinterval,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  oi->rxmt_interval = strtol (argv[0], NULL, 10);
+  oi->rxmt_interval = strtol (argv[idx_number]->arg, NULL, 10);
   return CMD_SUCCESS;
 }
 
 /* interface variable set command */
 DEFUN (ipv6_ospf6_priority,
        ipv6_ospf6_priority_cmd,
-       "ipv6 ospf6 priority <0-255>",
+       "ipv6 ospf6 priority (0-255)",
        IP6_STR
        OSPF6_STR
        "Router priority\n"
        "Priority value\n"
        )
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1311,9 +1452,12 @@ DEFUN (ipv6_ospf6_priority,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  oi->priority = strtol (argv[0], NULL, 10);
+  oi->priority = strtol (argv[idx_number]->arg, NULL, 10);
 
-  if (oi->area)
+  if (oi->area &&
+      (oi->state == OSPF6_INTERFACE_DROTHER ||
+       oi->state == OSPF6_INTERFACE_BDR ||
+       oi->state == OSPF6_INTERFACE_DR))
     ospf6_interface_state_change (dr_election (oi), oi);
 
   return CMD_SUCCESS;
@@ -1321,13 +1465,14 @@ DEFUN (ipv6_ospf6_priority,
 
 DEFUN (ipv6_ospf6_instance,
        ipv6_ospf6_instance_cmd,
-       "ipv6 ospf6 instance-id <0-255>",
+       "ipv6 ospf6 instance-id (0-255)",
        IP6_STR
        OSPF6_STR
        "Instance ID for this interface\n"
        "Instance ID value\n"
        )
 {
+  int idx_number = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1339,7 +1484,7 @@ DEFUN (ipv6_ospf6_instance,
     oi = ospf6_interface_create (ifp);
   assert (oi);
 
-  oi->instance_id = strtol (argv[0], NULL, 10);
+  oi->instance_id = strtol (argv[idx_number]->arg, NULL, 10);
   return CMD_SUCCESS;
 }
 
@@ -1348,7 +1493,7 @@ DEFUN (ipv6_ospf6_passive,
        "ipv6 ospf6 passive",
        IP6_STR
        OSPF6_STR
-       "passive interface, No adjacency will be formed on this interface\n"
+       "Passive interface; no adjacency will be formed on this interface\n"
        )
 {
   struct ospf6_interface *oi;
@@ -1409,7 +1554,7 @@ DEFUN (ipv6_ospf6_mtu_ignore,
        "ipv6 ospf6 mtu-ignore",
        IP6_STR
        OSPF6_STR
-       "Ignore MTU mismatch on this interface\n"
+       "Disable MTU mismatch detection on this interface\n"
        )
 {
   struct ospf6_interface *oi;
@@ -1434,7 +1579,7 @@ DEFUN (no_ipv6_ospf6_mtu_ignore,
        NO_STR
        IP6_STR
        OSPF6_STR
-       "Ignore MTU mismatch on this interface\n"
+       "Disable MTU mismatch detection on this interface\n"
        )
 {
   struct ospf6_interface *oi;
@@ -1463,6 +1608,7 @@ DEFUN (ipv6_ospf6_advertise_prefix_list,
        "Prefix list name\n"
        )
 {
+  int idx_word = 4;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1475,8 +1621,8 @@ DEFUN (ipv6_ospf6_advertise_prefix_list,
   assert (oi);
 
   if (oi->plist_name)
-    XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
-  oi->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, argv[0]);
+    XFREE (MTYPE_CFG_PLIST_NAME, oi->plist_name);
+  oi->plist_name = XSTRDUP (MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg);
 
   ospf6_interface_connected_route_update (oi->interface);
 
@@ -1517,7 +1663,7 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
 
   if (oi->plist_name)
     {
-      XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
+      XFREE (MTYPE_CFG_PLIST_NAME, oi->plist_name);
       oi->plist_name = NULL;
     }
 
@@ -1539,14 +1685,15 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
 
 DEFUN (ipv6_ospf6_network,
        ipv6_ospf6_network_cmd,
-       "ipv6 ospf6 network (broadcast|point-to-point)",
+       "ipv6 ospf6 network <broadcast|point-to-point>",
        IP6_STR
        OSPF6_STR
-       "Network Type\n"
-       "Specify OSPFv6 broadcast network\n"
+       "Network type\n"
+       "Specify OSPF6 broadcast network\n"
        "Specify OSPF6 point-to-point network\n"
        )
 {
+  int idx_network = 3;
   struct ospf6_interface *oi;
   struct interface *ifp;
 
@@ -1559,14 +1706,14 @@ DEFUN (ipv6_ospf6_network,
   }
   assert (oi);
 
-  if (strncmp (argv[0], "b", 1) == 0)
+  if (strncmp (argv[idx_network]->arg, "b", 1) == 0)
     {
       if (oi->type == OSPF_IFTYPE_BROADCAST)
        return CMD_SUCCESS;
 
       oi->type = OSPF_IFTYPE_BROADCAST;
     }
-    else if (strncmp (argv[0], "point-to-p", 10) == 0)
+    else if (strncmp (argv[idx_network]->arg, "point-to-p", 10) == 0)
       {
        if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
          return CMD_SUCCESS;
@@ -1587,7 +1734,7 @@ DEFUN (no_ipv6_ospf6_network,
        NO_STR
        IP6_STR
        OSPF6_STR
-       "Network Type\n"
+       "Network type\n"
        "Default to whatever interface type system specifies"
        )
 {
@@ -1624,7 +1771,7 @@ config_write_ospf6_interface (struct vty *vty)
   struct ospf6_interface *oi;
   struct interface *ifp;
 
-  for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, ifp))
     {
       oi = (struct ospf6_interface *) ifp->info;
       if (oi == NULL)
@@ -1638,7 +1785,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);
 
@@ -1676,10 +1823,15 @@ config_write_ospf6_interface (struct vty *vty)
       if (oi->mtu_ignore)
         vty_out (vty, " ipv6 ospf6 mtu-ignore%s", VNL);
 
-      if (oi->type == OSPF_IFTYPE_POINTOPOINT)
-        vty_out (vty, " ipv6 ospf6 network point-to-point%s", VNL);
-      else if (oi->type == OSPF_IFTYPE_BROADCAST)
-       vty_out (vty, " ipv6 ospf6 network broadcast%s", VNL);
+      if (oi->type != ospf6_default_iftype(ifp))
+        {
+          if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+            vty_out (vty, " ipv6 ospf6 network point-to-point%s", VNL);
+          else if (oi->type == OSPF_IFTYPE_BROADCAST)
+            vty_out (vty, " ipv6 ospf6 network broadcast%s", VNL);
+        }
+
+      ospf6_bfd_write_config(vty, oi);
 
       vty_out (vty, "!%s", VNL);
     }
@@ -1698,29 +1850,14 @@ ospf6_interface_init (void)
 {
   /* Install interface node. */
   install_node (&interface_node, config_write_ospf6_interface);
+  if_cmd_init ();
 
-  install_element (VIEW_NODE, &show_ipv6_ospf6_interface_cmd);
   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_detail_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_match_cmd);
   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
   install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_detail_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_match_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_detail_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_match_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_detail_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_match_cmd);
-
-  install_element (CONFIG_NODE, &interface_cmd);
-  install_default (INTERFACE_NODE);
-  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);
@@ -1741,6 +1878,71 @@ ospf6_interface_init (void)
 
   install_element (INTERFACE_NODE, &ipv6_ospf6_network_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
+
+  /* reference bandwidth commands */
+  install_element (OSPF6_NODE, &auto_cost_reference_bandwidth_cmd);
+  install_element (OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd);
+}
+
+/* Clear the specified interface structure */
+static void
+ospf6_interface_clear (struct vty *vty, struct interface *ifp)
+{
+  struct ospf6_interface *oi;
+
+  if (!if_is_operative (ifp))
+    return;
+
+  if (ifp->info == NULL)
+    return;
+
+  oi = (struct ospf6_interface *) ifp->info;
+
+  if (IS_OSPF6_DEBUG_INTERFACE)
+    zlog_debug ("Interface %s: clear by reset", ifp->name);
+
+  /* Reset the interface */
+  thread_add_event (master, interface_down, oi, 0);
+  thread_add_event (master, interface_up, oi, 0);
+}
+
+/* Clear interface */
+DEFUN (clear_ipv6_ospf6_interface,
+       clear_ipv6_ospf6_interface_cmd,
+       "clear ipv6 ospf6 interface [IFNAME]",
+       CLEAR_STR
+       IP6_STR
+       OSPF6_STR
+       INTERFACE_STR
+       IFNAME_STR
+       )
+{
+  int idx_ifname = 4;
+  struct interface *ifp;
+  struct listnode *node;
+
+  if (argc == 4) /* Clear all the ospfv3 interfaces. */
+    {
+      for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
+        ospf6_interface_clear (vty, ifp);
+    }
+  else /* Interface name is specified. */
+    {
+      if ((ifp = if_lookup_by_name (argv[idx_ifname]->arg)) == NULL)
+        {
+          vty_out (vty, "No such Interface: %s%s", argv[idx_ifname]->arg, VNL);
+          return CMD_WARNING;
+        }
+      ospf6_interface_clear (vty, ifp);
+    }
+
+  return CMD_SUCCESS;
+}
+
+void
+install_element_ospf6_clear_interface (void)
+{
+  install_element (ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd);
 }
 
 DEFUN (debug_ospf6_interface,