]> git.proxmox.com Git - mirror_frr.git/commitdiff
per-interface ospf enable and area set command.
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:58:14 +0000 (17:58 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:58:14 +0000 (17:58 -0700)
doc/ospfd.texi
ospfd/ospf_interface.h
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.h

index 856a2ba05fe8a8d1509a4b496ff566e0c7977e43..5b1b2acb2a9f2b8fdc9acdeea8ae33f4ffa18c32 100644 (file)
@@ -507,6 +507,11 @@ incremented by this value when transmitting.
 The default value is 1 seconds.
 @end deffn
 
+@deffn {Interface Command} {ip ospf area (A.B.C.D|<0-4294967295>)} {}
+@deffnx {Interface Command} {no ip ospf area} {}
+Enable ospf on an interface and set associated area.
+@end deffn
+
 @node Redistribute routes to OSPF
 @section Redistribute routes to OSPF
 
index 75a8d060ffc4db8e16551a3808932d65f056b53d..e2d929020fe8b212c972ec11884cb5f6910cecbf 100644 (file)
@@ -48,6 +48,8 @@ struct ospf_if_params
   DECLARE_IF_PARAM (u_char, bfd);                    /* Respond to BFD events */
   DECLARE_IF_PARAM (u_char, passive_interface);      /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */
   DECLARE_IF_PARAM (u_char, priority);               /* OSPF Interface priority */
+  /* Enable OSPF on this interface with area if_area */
+  DECLARE_IF_PARAM (struct in_addr, if_area);
   DECLARE_IF_PARAM (u_char, type);                   /* type of interface */
 #define OSPF_IF_ACTIVE                  0
 #define OSPF_IF_PASSIVE                        1
index 84251fe44b89635a03babe5e9f9129a984dcbf4e..2854a41b4f4c7fad7201dd49d56c7fc07609559d 100644 (file)
@@ -446,6 +446,13 @@ DEFUN (ospf_network_area,
   struct in_addr area_id;
   int ret, format;
 
+  if (ospf->if_ospf_cli_count > 0)
+    {
+      vty_out (vty, "Please remove all ip ospf area x.x.x.x commands first.%s",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
   /* Get network prefix and Area ID. */
   VTY_GET_IPV4_PREFIX ("network prefix", p, argv[0]);
   VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]);
@@ -5887,6 +5894,95 @@ ALIAS (no_ip_ospf_transmit_delay,
        "OSPF interface commands\n"
        "Link state transmit delay\n")
 
+DEFUN (ip_ospf_area,
+       ip_ospf_area_cmd,
+       "ip ospf area (A.B.C.D|<0-4294967295>)",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable OSPF on this interface\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n")
+{
+  struct interface *ifp = vty->index;
+  int format, ret;
+  struct in_addr area_id;
+  struct ospf *ospf;
+  struct ospf_if_params *params;
+  struct route_node *rn;
+
+  ospf = ospf_lookup ();
+  if (ospf == NULL)
+    {
+      vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  ret = ospf_str2area_id (argv[0], &area_id, &format);
+  if (ret < 0)
+    {
+      vty_out (vty, "Please specify area by A.B.C.D|<0-4294967295>%s",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  if (memcmp (ifp->name, "VLINK", 5) == 0)
+    {
+      vty_out (vty, "Cannot enable OSPF on a virtual link.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  params = IF_DEF_PARAMS (ifp);
+  if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
+    {
+      return CMD_WARNING;
+    }
+
+  for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
+    {
+      if (rn->info != NULL)
+        {
+          vty_out (vty, "Please remove all network commands first.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+    }
+
+  /* enable ospf on this interface with area_id */
+  ospf_interface_set (ifp, area_id);
+  ospf->if_ospf_cli_count++;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_ospf_area,
+       no_ip_ospf_area_cmd,
+       "no ip ospf area",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Disable OSPF on this interface\n")
+{
+  struct interface *ifp = vty->index;
+  struct ospf *ospf;
+  struct ospf_if_params *params;
+
+  ospf = ospf_lookup ();
+  if (ospf == NULL)
+    {
+      vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  params = IF_DEF_PARAMS (ifp);
+  if (!OSPF_IF_PARAM_CONFIGURED(params, if_area))
+    {
+      vty_out (vty, "Can't find specified inteface area configuration.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ospf_interface_unset (ifp);
+  ospf->if_ospf_cli_count--;
+  return CMD_SUCCESS;
+}
+
 DEFUN (ospf_redistribute_source,
        ospf_redistribute_source_cmd,
        "redistribute " QUAGGA_REDIST_STR_OSPFD
@@ -6951,6 +7047,14 @@ config_write_interface (struct vty *vty)
            vty_out (vty, "%s", VTY_NEWLINE);
          }
 
+       /* Area  print. */
+       if (OSPF_IF_PARAM_CONFIGURED (params, if_area))
+         {
+           vty_out (vty, " ip ospf area %s%s",
+                    inet_ntoa (params->if_area), VTY_NEWLINE);
+
+         }
+
        /* bfd  print. */
        if (OSPF_IF_PARAM_CONFIGURED (params, bfd))
          vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE);
@@ -7601,6 +7705,10 @@ ospf_vty_if_init (void)
   install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd);
   install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_cmd);
 
+  /* "ip ospf area" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_area_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd);
+
   /* These commands are compatibitliy for previous version. */
   install_element (INTERFACE_NODE, &ospf_authentication_key_cmd);
   install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd);
index 272c544bc67fc158f52c516c2350adeb24025441..a69b5595d76185ff7b6fa99881762fc43c08f031 100644 (file)
@@ -403,6 +403,7 @@ ospf_finish_final (struct ospf *ospf)
   struct route_node *rn;
   struct ospf_nbr_nbma *nbr_nbma;
   struct ospf_lsa *lsa;
+  struct interface *ifp;
   struct ospf_interface *oi;
   struct ospf_area *area;
   struct ospf_vl_data *vl_data;
@@ -429,6 +430,16 @@ ospf_finish_final (struct ospf *ospf)
   
   list_delete (ospf->vlinks);
 
+  /* Remove any ospf interface config params */
+  for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
+    {
+      struct ospf_if_params *params;
+
+      params = IF_DEF_PARAMS (ifp);
+      if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
+        UNSET_IF_PARAM (params, if_area);
+    }
+
   /* Reset interface. */
   for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
     ospf_if_free (oi);
@@ -721,6 +732,76 @@ ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
   listnode_delete (area->oiflist, oi);
 }
 
+static struct ospf_interface *
+add_ospf_interface (struct interface *ifp, struct ospf_area *area,
+                    struct connected *co)
+{
+  struct ospf_interface *oi;
+
+  oi = ospf_if_new (area->ospf, ifp, co->address);
+  oi->connected = co;
+
+  oi->area = area;
+
+  oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
+  oi->output_cost = ospf_if_get_output_cost (oi);
+
+  /* Add pseudo neighbor. */
+  ospf_nbr_add_self (oi);
+
+  /* Relate ospf interface to ospf instance. */
+  oi->ospf = area->ospf;
+
+  /* update network type as interface flag */
+  /* If network type is specified previously,
+     skip network type setting. */
+  oi->type = IF_DEF_PARAMS (ifp)->type;
+
+  ospf_area_add_if (oi->area, oi);
+
+  /* if router_id is not configured, dont bring up
+   * interfaces.
+   * ospf_router_id_update() will call ospf_if_update
+   * whenever r-id is configured instead.
+   */
+  if ((area->ospf->router_id.s_addr != 0)
+      && if_is_operative (ifp))
+    ospf_if_up (oi);
+
+  return (oi);
+}
+
+static void update_redistributed(struct ospf *ospf, int add_to_ospf)
+{
+  struct route_node *rn;
+  struct external_info *ei;
+
+  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
+    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
+      {
+        for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
+             rn; rn = route_next (rn))
+          {
+            if ((ei = rn->info) != NULL)
+              {
+                if (add_to_ospf)
+                  {
+                    if (ospf_external_info_find_lsa (ospf, &ei->p))
+                      if (!ospf_distribute_check_connected (ospf, ei))
+                        ospf_external_lsa_flush (ospf, ei->type, &ei->p,
+                                                 ei->ifindex /*, ei->nexthop */);
+                  }
+                else
+                  {
+                    if (!ospf_external_info_find_lsa (ospf, &ei->p))
+                      if (ospf_distribute_check_connected (ospf, ei))
+                        ospf_external_lsa_originate (ospf, ei);
+                  }
+              }
+          }
+      }
+}
+
 
 /* Config network statement related functions. */
 static struct ospf_network *
@@ -750,7 +831,6 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
   struct ospf_network *network;
   struct ospf_area *area;
   struct route_node *rn;
-  struct external_info *ei;
   int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
 
   rn = route_node_get (ospf->networks, (struct prefix *)p);
@@ -768,15 +848,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
   ospf_network_run ((struct prefix *)p, area);
 
   /* Update connected redistribute. */
-  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
-    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
-      for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
-          rn; rn = route_next (rn))
-       if ((ei = rn->info) != NULL)
-         if (ospf_external_info_find_lsa (ospf, &ei->p))
-           if (!ospf_distribute_check_connected (ospf, ei))
-             ospf_external_lsa_flush (ospf, ei->type, &ei->p,
-                                      ei->ifindex /*, ei->nexthop */);
+  update_redistributed(ospf, 1); /* interfaces possibly added */
 
   ospf_area_check_free (ospf, area_id);
 
@@ -789,7 +861,6 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
 {
   struct route_node *rn;
   struct ospf_network *network;
-  struct external_info *ei;
   struct listnode *node, *nnode;
   struct ospf_interface *oi;
 
@@ -833,14 +904,76 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
     }
   
   /* Update connected redistribute. */
-  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
-    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
-      for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
-          rn; rn = route_next (rn))
-       if ((ei = rn->info) != NULL)
-         if (!ospf_external_info_find_lsa (ospf, &ei->p))
-           if (ospf_distribute_check_connected (ospf, ei))
-             ospf_external_lsa_originate (ospf, ei);
+  update_redistributed(ospf, 0); /* interfaces possibly removed */
+  ospf_area_check_free (ospf, area_id);
+
+  return 1;
+}
+
+int
+ospf_interface_set (struct interface *ifp, struct in_addr area_id)
+{
+  struct ospf_area *area;
+  struct listnode *cnode;
+  struct connected *co;
+  struct ospf *ospf;
+  struct ospf_if_params *params;
+  int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
+
+  if ((ospf = ospf_lookup ()) == NULL)
+    return 1; /* Ospf not ready yet */
+
+  params = IF_DEF_PARAMS (ifp);
+
+  SET_IF_PARAM (params, if_area);
+  params->if_area = area_id;
+
+  area = ospf_area_get (ospf, area_id, ret);
+
+  for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
+    {
+      if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
+        continue;
+
+      if (co->address->family == AF_INET
+          && !ospf_if_table_lookup(ifp, co->address))
+        {
+          add_ospf_interface(ifp, area, co);
+        }
+    }
+
+  /* Update connected redistribute. */
+  update_redistributed(ospf, 1); /* interface possibly added */
+  return 1;
+}
+
+int
+ospf_interface_unset (struct interface *ifp)
+{
+  struct ospf *ospf;
+  struct ospf_if_params *params;
+  struct listnode *node, *nnode;
+  struct ospf_interface *oi;
+  struct in_addr area_id;
+
+  ospf = ospf_lookup ();
+  if (!ospf)
+    return 1; /* Ospf not ready yet */
+
+  params = IF_DEF_PARAMS (ifp);
+  UNSET_IF_PARAM (params, if_area);
+  area_id = params->if_area;
+
+  for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
+    {
+      if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+        continue;
+      if (oi->ifp == ifp) ospf_if_free (oi);
+    }
+
+  /* Update connected redistribute. */
+  update_redistributed(ospf, 0); /* interfaces possibly removed */
+  ospf_area_check_free (ospf, area_id);
 
   return 1;
 }
@@ -960,7 +1093,8 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp)
   struct route_node *rn;
   struct ospf_network *network;
   struct ospf_area *area;
-  
+  struct ospf_if_params *params;
+
   if (!ospf)
     ospf = ospf_lookup ();
 
@@ -976,6 +1110,13 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp)
         area = ospf_area_get (ospf, network->area_id, network->format);
         ospf_network_run_interface (&rn->p, area, ifp);
       }
+
+  /* create oif for any new co */
+  params = IF_DEF_PARAMS (ifp);
+  if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
+    {
+      ospf_interface_set (ifp, params->if_area);
+    }
 }
 
 void
index 11525a5fb87c3addb01431bf80f7497042460fe5..d98519a16990ff080fa42bfa1690169966a0c488 100644 (file)
@@ -284,6 +284,9 @@ struct ospf
   /* Statistics for LSA used for new instantiation. */
   u_int32_t rx_lsa_count;
  
+  /* Counter of "ip ospf area x.x.x.x" */
+  u_int32_t if_ospf_cli_count;
+
   struct route_table *distance_table;
 };
 
@@ -572,4 +575,6 @@ extern void ospf_snmp_init (void);
 
 extern void ospf_master_init (void);
 
+extern int ospf_interface_set (struct interface *ifp, struct in_addr area_id);
+extern int ospf_interface_unset (struct interface *ifp);
 #endif /* _ZEBRA_OSPFD_H */