Acked-by: Donald Sharp <sha...@cumulusnetworks.com>

On Tue, Oct 20, 2015 at 9:47 AM, Paul Jakma <p...@jakma.org> wrote:

> From: Paul Jakma <p...@quagga.net>
>
> * ospfd.c: (general) Clean up the whole running of OSPF on interfaces.
>   (add_ospf_interface) taking (struct interface *) arg is pointless here.
>   (ospf_is_ready) new helper.
>   (ospf_network_run_subnet) Put all the code for choosing whether to enable
>   OSPF on a subnet, and if so which area configuration to use, here. If a
>   subnet should not be enabled, ensure an existing oi is freed.
>   (ospf_network_run_interface) Just call run_subnet for all subnets on an
>   interface.
>   (ospf_network_run) Just call run_interface for all interfaces.
>   (ospf_if_update) Just call run_interface for the given interface.
>   (ospf_network_unset) Just call run_subnet for existing ois.
>   (ospf_update_interface_area) helper: update area on an oi, or create it.
>   (ospf_interface_set) renamed to ospf_interface_area_set for clarity.
>   Ensures OSPF is created, then into if_update.
>   (ospf_interface_unset) renamed to ospf_interface_area_unset and collapses
>   down to simple loop to call run_subnet for all ois.
> * ospf_interface.h: add a more general OSPF_IF_PARAM_IS_SET, which does
> the right
>   and takes default config into account.
> * ospf_vty.c: (OSPF_VTY_GET_IF_PARAMS) new macro with common code for
> handling
>   interface parameter commands - only used for 'ip ospf area' in this
> commit.
>   (OSPF_VTY_PARAM_UNSET) similar
>   ({no,}ip_ospf_area) Use said macros.
> * doc/ospfd.texi: add 'ip ospf area' command.
> ---
>  doc/ospfd.texi         |  18 +++
>  ospfd/ospf_interface.h |  11 +-
>  ospfd/ospf_vty.c       |  88 +++++++++-----
>  ospfd/ospfd.c          | 302
> ++++++++++++++++++++++++++-----------------------
>  ospfd/ospfd.h          |   3 +
>  5 files changed, 253 insertions(+), 169 deletions(-)
>
> diff --git a/doc/ospfd.texi b/doc/ospfd.texi
> index 856a2ba..7ddc9db 100644
> --- a/doc/ospfd.texi
> +++ b/doc/ospfd.texi
> @@ -216,6 +216,7 @@ OSPF domain.
>  @deffnx {OSPF Command} {network @var{a.b.c.d/m} area
> @var{<0-4294967295>}} {}
>  @deffnx {OSPF Command} {no network @var{a.b.c.d/m} area @var{a.b.c.d}} {}
>  @deffnx {OSPF Command} {no network @var{a.b.c.d/m} area
> @var{<0-4294967295>}} {}
> +@anchor{OSPF network command}
>  This command specifies the OSPF enabled interface(s).  If the interface
> has
>  an address from range 192.168.1.0/24 then the command below enables ospf
>  on this interface so router can provide network information to the other
> @@ -239,6 +240,10 @@ Currently, if a peer prefix has been configured,
>  then we test whether the prefix in the network command contains
>  the destination prefix.  Otherwise, we test whether the network command
> prefix
>  contains the local address prefix of the interface.
> +
> +In some cases it may be more convenient to enable OSPF on a per
> +interface/subnet basis (@pxref{OSPF ip ospf area command}).
> +
>  @end deffn
>
>  @node OSPF area
> @@ -406,6 +411,19 @@ settings will override any per-area authentication
> setting.
>  @node OSPF interface
>  @section OSPF interface
>
> +@deffn {Interface Command} {ip ospf area @var{AREA} [@var{ADDR}]} {}
> +@deffnx {Interface Command} {no ip ospf area [@var{ADDR}]} {}
> +@anchor{OSPF ip ospf area command}
> +
> +Enable OSPF on the interface, optionally restricted to just the IP address
> +given by @var{ADDR}, putting it in the @var{AREA} area. Per interface area
> +settings take precedence to network commands (@pxref{OSPF network
> command}).
> +
> +If you have a lot of interfaces, and/or a lot of subnets, then enabling
> OSPF
> +via this command may result in a slight performance improvement.
> +
> +@end deffn
> +
>  @deffn {Interface Command} {ip ospf authentication-key @var{AUTH_KEY}} {}
>  @deffnx {Interface Command} {no ip ospf authentication-key} {}
>  Set OSPF authentication key to a simple password.  After setting
> @var{AUTH_KEY},
> diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
> index a437bfb..2ed426f 100644
> --- a/ospfd/ospf_interface.h
> +++ b/ospfd/ospf_interface.h
> @@ -30,8 +30,17 @@
>  #define IF_DEF_PARAMS(I) (IF_OSPF_IF_INFO (I)->def_params)
>  #define IF_OIFS(I)  (IF_OSPF_IF_INFO (I)->oifs)
>  #define IF_OIFS_PARAMS(I) (IF_OSPF_IF_INFO (I)->params)
> -
> +
> +/* Despite the name, this macro probably is for specialist use only */
>  #define OSPF_IF_PARAM_CONFIGURED(S, P) ((S) && (S)->P##__config)
> +
> +/* Test whether an OSPF interface parameter is set, generally, given some
> + * existing ospf interface
> + */
> +#define OSPF_IF_PARAM_IS_SET(O,P) \
> +      (OSPF_IF_PARAM_CONFIGURED ((O)->params, P) || \
> +      OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp)->P))
> +
>  #define OSPF_IF_PARAM(O, P) \
>          (OSPF_IF_PARAM_CONFIGURED ((O)->params, P)?\
>                          (O)->params->P:IF_DEF_PARAMS((O)->ifp)->P)
> diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
> index 26abf38..8111a1d 100644
> --- a/ospfd/ospf_vty.c
> +++ b/ospfd/ospf_vty.c
> @@ -292,6 +292,41 @@ ospf_passive_interface_update (struct ospf *ospf,
> struct interface *ifp,
>      }
>  }
>
> +/* get the appropriate ospf parameters structure, checking if
> + * there's a valid interface address at the argi'th argv index
> + */
> +enum {
> +  VTY_SET = 0,
> +  VTY_UNSET,
> +};
> +#define OSPF_VTY_GET_IF_PARAMS(ifp,params,argi,addr,set) \
> +  (params) = IF_DEF_PARAMS ((ifp));           \
> +                                              \
> +  if (argc == (argi) + 1)                     \
> +    {                                         \
> +      int ret = inet_aton(argv[(argi)], &(addr)); \
> +      if (!ret)                               \
> +       {                                     \
> +         vty_out (vty, "Please specify interface address by A.B.C.D%s", \
> +                  VTY_NEWLINE);              \
> +         return CMD_WARNING;                 \
> +       }                                     \
> +      (params) = ospf_get_if_params ((ifp), (addr)); \
> +                                              \
> +      if (set)                                \
> +        ospf_if_update_params ((ifp), (addr));  \
> +      else if ((params) == NULL)              \
> +        return CMD_SUCCESS;                   \
> +    }
> +
> +#define OSPF_VTY_PARAM_UNSET(params,var,ifp,addr) \
> +  UNSET_IF_PARAM ((params), var);               \
> +    if ((params) != IF_DEF_PARAMS ((ifp)))        \
> +    {                                             \
> +      ospf_free_if_params ((ifp), (addr));        \
> +      ospf_if_update_params ((ifp), (addr));      \
> +    }
> +
>  DEFUN (ospf_passive_interface,
>         ospf_passive_interface_addr_cmd,
>         "passive-interface IFNAME A.B.C.D",
> @@ -453,7 +488,7 @@ DEFUN (ospf_network_area,
>         "OSPF area ID in IP address format\n"
>         "OSPF area ID as a decimal value\n")
>  {
> -  struct ospf *ospf= vty->index;
> +  struct ospf *ospf = vty->index;
>    struct prefix_ipv4 p;
>    struct in_addr area_id;
>    int ret, format;
> @@ -5885,31 +5920,28 @@ ALIAS (no_ip_ospf_transmit_delay,
>
>  DEFUN (ip_ospf_area,
>         ip_ospf_area_cmd,
> -       "ip ospf area (A.B.C.D|<0-4294967295>)",
> +       "ip ospf area (A.B.C.D|<0-4294967295>) [A.B.C.D]",
>         "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")
> +       "OSPF area ID as a decimal value\n"
> +       "Address of interface\n")
>  {
>    struct interface *ifp = vty->index;
> -  int format, ret;
>    struct in_addr area_id;
> -  struct ospf *ospf;
> +  struct in_addr addr;
> +  int format;
>    struct ospf_if_params *params;
>
> -  ret = ospf_str2area_id (argv[0], &area_id, &format);
> +  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
>
> -  if (ret < 0)
> -    {
> -      vty_out (vty, "Please specify area by A.B.C.D|<0-4294967295>%s",
> -              VTY_NEWLINE);
> -      return CMD_WARNING;
> -    }
> -  params = IF_DEF_PARAMS (ifp);
> +  OSPF_VTY_GET_IF_PARAMS(ifp, params, 1, addr, VTY_SET);
> +
>    if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
>      {
> -      vty_out (vty, "There is already a interface statement.%s",
> VTY_NEWLINE);
> +      vty_out (vty, "There is already an interface area statement.%s",
> +              VTY_NEWLINE);
>        return CMD_WARNING;
>      }
>    if (memcmp (ifp->name, "VLINK", 5) == 0)
> @@ -5917,33 +5949,36 @@ DEFUN (ip_ospf_area,
>        vty_out (vty, "Cannot enable OSPF on a virtual link.%s",
> VTY_NEWLINE);
>        return CMD_WARNING;
>      }
> -
> +
>    SET_IF_PARAM (params, if_area);
>    params->if_area = area_id;
> -  ospf_interface_set (ifp);
> +  ospf_interface_area_set (ifp);
>
>    return CMD_SUCCESS;
>  }
>
>  DEFUN (no_ip_ospf_area,
>         no_ip_ospf_area_cmd,
> -       "no ip ospf area",
> +       "no ip ospf area [A.B.C.D]",
>         NO_STR
>         "IP Information\n"
>         "OSPF interface commands\n"
> -       "Disable OSPF on this interface\n")
> +       "Disable OSPF on this interface\n"
> +       "Address of interface\n")
>  {
>    struct interface *ifp = vty->index;
> -  struct ospf *ospf;
>    struct ospf_if_params *params;
> +  struct in_addr addr;
>
> -  params = IF_DEF_PARAMS (ifp);
> +  OSPF_VTY_GET_IF_PARAMS(ifp, params, 0, addr, VTY_UNSET);
> +
>    if (!OSPF_IF_PARAM_CONFIGURED(params, if_area))
>      return CMD_SUCCESS;
> +
> +  OSPF_VTY_PARAM_UNSET(params, if_area, ifp, addr);
> +
> +  ospf_interface_area_unset (ifp);
>
> -  UNSET_IF_PARAM (params, if_area);
> -
> -  ospf_interface_unset (ifp);
>    return CMD_SUCCESS;
>  }
>
> @@ -7014,9 +7049,10 @@ config_write_interface (struct vty *vty)
>         /* 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);
> +           vty_out (vty, " ip ospf area %s", inet_ntoa (params->if_area));
> +           if (params != IF_DEF_PARAMS (ifp))
> +             vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
> +            vty_out (vty, "%s", VTY_NEWLINE);
>           }
>
>      /* MTU ignore print. */
> diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
> index 6831ab8..a1d1f9d 100644
> --- a/ospfd/ospfd.c
> +++ b/ospfd/ospfd.c
> @@ -69,8 +69,10 @@ static void ospf_remove_vls_through_area (struct ospf
> *, struct ospf_area *);
>  static void ospf_network_free (struct ospf *, struct ospf_network *);
>  static void ospf_area_free (struct ospf_area *);
>  static void ospf_network_run (struct prefix *, struct ospf_area *);
> -static void ospf_network_run_interface (struct prefix *, struct ospf_area
> *,
> -                                        struct interface *);
> +static void ospf_network_run_interface (struct ospf *, struct interface *,
> +                                        struct prefix *, struct ospf_area
> *);
> +static void ospf_network_run_subnet (struct ospf *, struct connected *,
> +                                     struct prefix *, struct ospf_area *);
>  static int ospf_network_match_iface (const struct connected *,
>                                      const struct prefix *);
>  static void ospf_finish_final (struct ospf *);
> @@ -258,6 +260,16 @@ ospf_lookup ()
>    return listgetdata (listhead (om->ospf));
>  }
>
> +static int
> +ospf_is_ready (struct ospf *ospf)
> +{
> +  /* OSPF must be on and Router-ID must be configured. */
> +  if (!ospf || ospf->router_id.s_addr == 0)
> +    return 0;
> +
> +  return 1;
> +}
> +
>  static void
>  ospf_add (struct ospf *ospf)
>  {
> @@ -754,18 +766,17 @@ ospf_network_new (struct in_addr area_id, int format)
>    return new;
>  }
>
> -static void
> -add_ospf_interface (struct interface *ifp, struct ospf_area *area,
> -                    struct connected *co)
> +static void
> +add_ospf_interface (struct connected *co, struct ospf_area *area)
>  {
>    struct ospf_interface *oi;
>
> -  oi = ospf_if_new (area->ospf, ifp, co->address);
> +  oi = ospf_if_new (area->ospf, co->ifp, co->address);
>    oi->connected = co;
>
>    oi->area = area;
>
> -  oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
> +  oi->params = ospf_lookup_if_params (co->ifp, oi->address->u.prefix4);
>    oi->output_cost = ospf_if_get_output_cost (oi);
>
>    /* Add pseudo neighbor. */
> @@ -777,7 +788,7 @@ add_ospf_interface (struct interface *ifp, struct
> ospf_area *area,
>    /* update network type as interface flag */
>    /* If network type is specified previously,
>       skip network type setting. */
> -  oi->type = IF_DEF_PARAMS (ifp)->type;
> +  oi->type = IF_DEF_PARAMS (co->ifp)->type;
>
>    ospf_area_add_if (oi->area, oi);
>
> @@ -787,7 +798,7 @@ add_ospf_interface (struct interface *ifp, struct
> ospf_area *area,
>     * whenever r-id is configured instead.
>     */
>    if ((area->ospf->router_id.s_addr != 0)
> -      && if_is_operative (ifp))
> +      && if_is_operative (co->ifp))
>      ospf_if_up (oi);
>  }
>
> @@ -808,7 +819,7 @@ update_redistributed (struct ospf *ospf, int
> 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
> */);
> +                                              ei->ifindex /*, ei->nexthop
> */);
>                }
>              else
>                {
> @@ -851,7 +862,8 @@ ospf_network_set (struct ospf *ospf, struct
> prefix_ipv4 *p,
>    ospf_network_run ((struct prefix *)p, area);
>
>    /* Update connected redistribute. */
> -  update_redistributed(ospf, 1); /* interfaces possibly added */
> +  update_redistributed(ospf, 1);
> +
>    ospf_area_check_free (ospf, area_id);
>
>    return 1;
> @@ -882,131 +894,64 @@ ospf_network_unset (struct ospf *ospf, struct
> prefix_ipv4 *p,
>    /* Find interfaces that not configured already.  */
>    for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
>      {
> -      struct ospf_if_params *params;
> -      int found = 0;
> -      struct connected *co = oi->connected;
> -
>        if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
>          continue;
>
> -      params = IF_DEF_PARAMS (oi->ifp);
> -      if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
> -        continue;
> -
> -      for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
> -        {
> -          if (rn->info == NULL)
> -            continue;
> -
> -          if (ospf_network_match_iface(co,&rn->p))
> -            {
> -              found = 1;
> -              route_unlock_node (rn);
> -              break;
> -            }
> -        }
> -
> -      if (found == 0)
> -       {
> -         ospf_if_free (oi);
> -         ospf_area_check_free (ospf, area_id);
> -       }
> +      ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
>      }
>
>    /* Update connected redistribute. */
> -  update_redistributed(ospf, 0); /* interfaces possibly removed */
> +  update_redistributed(ospf, 0);
> +
> +  ospf_area_check_free (ospf, area_id);
> +
>    return 1;
>  }
>
> -int
> -ospf_interface_set (struct interface *ifp)
> +/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
> + * there might not be any 'router ospf' config.
> + *
> + * Otherwise, doesn't do anything different to ospf_if_update for now
> + */
> +void
> +ospf_interface_area_set (struct interface *ifp)
>  {
> -  struct ospf_area *area;
> -  struct listnode *cnode;
> -  struct connected *co;
> -  struct ospf *ospf;
> -  struct ospf_if_params *params;
> -  struct in_addr area_id;
> -  int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
> -
> -  if ((ospf = ospf_lookup ()) == NULL)
> -      return 1; /* Ospf not ready yet */
> -
> -  params = IF_DEF_PARAMS (ifp);
> -  area_id = params->if_area;
> -
> -  area = ospf_area_get (ospf, area_id, ret);
> -
> -  for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
> -    {
> -      struct ospf_interface *oi;
> -
> -      if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
> -       continue;
> -
> -      oi = ospf_if_table_lookup(ifp, co->address);
> -      if (oi)
> -       { /* Just adjust area for existing interface */
> -         ospf_area_del_if (oi->area, oi);
> -         oi->area = area;
> -         ospf_area_add_if (oi->area, oi);
> -       }
> -      else
> -       {
> -         add_ospf_interface(ifp, area, co);
> -       }
> -    }
> -
> -  /* Update connected redistribute. */
> -  update_redistributed(ospf, 1); /* interface possibly added */
> -  ospf_area_check_free (ospf, area_id);
> -
> -  return 1;
> +  struct ospf *ospf = ospf_get();
> +
> +  ospf_if_update (ospf, ifp);
> +  /* if_update does a update_redistributed */
> +
> +  return;
>  }
>
> -int
> -ospf_interface_unset (struct interface *ifp)
> +void
> +ospf_interface_area_unset (struct interface *ifp)
>  {
> -  struct route_node *rn_oi, *rn;
> +  struct route_node *rn_oi;
>    struct ospf *ospf;
>
>    if ((ospf = ospf_lookup ()) == NULL)
> -    return 1; /* Ospf not ready yet */
> -
> +    return; /* Ospf not ready yet */
> +
>    /* Find interfaces that may need to be removed. */
>    for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next
> (rn_oi))
>      {
>        struct ospf_interface *oi;
> -      struct connected *co;
> -      int found = 0;
>
>        if ( (oi = rn_oi->info) == NULL)
>         continue;
> +
>        if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
>         continue;
> -      co = oi->connected;
> -
> -      for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
> -       {
> -         if (rn->info == NULL)
> -           continue;
> -
> -         if (ospf_network_match_iface(co,&rn->p))
> -           {
> -             found = 1;
> -             route_unlock_node (rn);
> -             break;
> -           }
> -       }
> -
> -      if (found == 0)
> -       ospf_if_free (oi);
> +
> +      ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
>      }
>
>    /* Update connected redistribute. */
> -  update_redistributed(ospf, 0); /* interfaces possibly removed */
> -   return 1;
> - }
> +  update_redistributed (ospf, 0); /* interfaces possibly removed */
> +
> +  return;
> +}
>
>
>  /* Check whether interface matches given network
> @@ -1020,8 +965,101 @@ ospf_network_match_iface(const struct connected
> *co, const struct prefix *net)
>  }
>
>  static void
> -ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
> -                            struct interface *ifp)
> +ospf_update_interface_area (struct connected *co, struct ospf_area *area)
> +{
> +  struct ospf_interface *oi = ospf_if_table_lookup (co->ifp, co->address);
> +
> +  /* nothing to be done case */
> +  if (oi && oi->area == area)
> +    return;
> +
> +  if (oi)
> +    ospf_if_free (oi);
> +
> +  add_ospf_interface (co, area);
> +}
> +
> +/* Run OSPF for the given subnet, taking into account the following
> + * possible sources of area configuration, in the given order of
> preference:
> + *
> + * - Whether there is interface+address specific area configuration
> + * - Whether there is a default area for the interface
> + * - Whether there is an area given as a parameter.
> + * - If no specific network prefix/area is supplied, whether there's
> + *   a matching network configured.
> + */
> +static void
> +ospf_network_run_subnet (struct ospf *ospf, struct connected *co,
> +                         struct prefix *p, struct ospf_area *given_area)
> +{
> +  struct ospf_interface *oi;
> +  struct ospf_if_params *params;
> +  struct ospf_area *area = NULL;
> +  struct route_node *rn;
> +  int configed = 0;
> +
> +  if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
> +    return;
> +
> +  if (co->address->family != AF_INET)
> +    return;
> +
> +  /* Try determine the appropriate area for this interface + address
> +   * Start by checking interface config
> +   */
> +  if (!(params = ospf_lookup_if_params (co->ifp, co->address->u.prefix4)))
> +    params = IF_DEF_PARAMS (co->ifp);
> +
> +  if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
> +    area = (ospf_area_get (ospf, params->if_area,
> +                           OSPF_AREA_ID_FORMAT_ADDRESS));
> +
> +  /* If we've found an interface and/or addr specific area, then we're
> +   * done
> +   */
> +  if (area)
> +    {
> +      ospf_update_interface_area (co, area);
> +      return;
> +    }
> +
> +  /* Otherwise, only remaining possibility is a matching network
> statement */
> +  if (p)
> +    {
> +      assert (given_area != NULL);
> +
> +      /* Which either was supplied as a parameter.. (e.g. cause a new
> +       * network/area was just added)..
> +       */
> +      if (p->family == co->address->family
> +          && ospf_network_match_iface (co, p))
> +        ospf_update_interface_area (co, given_area);
> +
> +      return;
> +    }
> +
> +  /* Else we have to search the existing network/area config to see
> +   * if any match..
> +   */
> +  for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
> +    if (rn->info != NULL
> +        && ospf_network_match_iface (co, &rn->p))
> +      {
> +        struct ospf_network *network = (struct ospf_network *) rn->info;
> +        area = ospf_area_get (ospf, network->area_id, network->format);
> +        ospf_update_interface_area (co, area);
> +        configed = 1;
> +      }
> +
> +  /* If the subnet isn't in any area, deconfigure */
> +  if (!configed && (oi = ospf_if_table_lookup (co->ifp, co->address)))
> +    ospf_if_free (oi);
> +}
> +
> +static void
> +ospf_network_run_interface (struct ospf *ospf, struct interface *ifp,
> +                            struct prefix *p,
> +                            struct ospf_area *given_area)
>  {
>    struct listnode *cnode;
>    struct connected *co;
> @@ -1029,21 +1067,14 @@ ospf_network_run_interface (struct prefix *p,
> struct ospf_area *area,
>    if (memcmp (ifp->name, "VLINK", 5) == 0)
>      return;
>
> +  /* Network prefix without area is nonsensical */
> +  if (p)
> +    assert (given_area != NULL);
> +
>    /* 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
> -         && ! ospf_if_table_lookup(ifp, co->address)
> -          && ospf_network_match_iface(co,p))
> -       {
> -         add_ospf_interface(ifp, area, co);
> -       }
> -    }
> +    ospf_network_run_subnet (ospf, co, p, given_area);
>  }
>
>  static void
> @@ -1058,7 +1089,7 @@ ospf_network_run (struct prefix *p, struct ospf_area
> *area)
>
>    /* Get target interface. */
>    for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
> -    ospf_network_run_interface (p, area, ifp);
> +    ospf_network_run_interface (area->ospf, ifp, p, area);
>  }
>
>  void
> @@ -1091,30 +1122,17 @@ ospf_ls_upd_queue_empty (struct ospf_interface *oi)
>  void
>  ospf_if_update (struct ospf *ospf, struct interface *ifp)
>  {
> -  struct route_node *rn;
> -  struct ospf_network *network;
> -  struct ospf_area *area;
> -
>    if (!ospf)
>      ospf = ospf_lookup ();
>
> -  /* OSPF must be on and Router-ID must be configured. */
> -  if (!ospf || ospf->router_id.s_addr == 0)
> +  /* OSPF must be ready. */
> +  if (!ospf_is_ready (ospf))
>      return;
>
> -  if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS (ifp), if_area))
> -    ospf_interface_set (ifp);
> -  else
> -    {
> -      /* Run each netowrk for this interface. */
> -      for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
> -       if (rn->info != NULL)
> -         {
> -           network = (struct ospf_network *) rn->info;
> -           area = ospf_area_get (ospf, network->area_id, network->format);
> -           ospf_network_run_interface (&rn->p, area, ifp);
> -         }
> -    }
> +  ospf_network_run_interface (ospf, ifp, NULL, NULL);
> +
> +  /* Update connected redistribute. */
> +  update_redistributed(ospf, 1);
>  }
>
>  void
> diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
> index 116f48f..fe8dcc1 100644
> --- a/ospfd/ospfd.h
> +++ b/ospfd/ospfd.h
> @@ -565,6 +565,9 @@ extern struct ospf_area *ospf_area_lookup_by_area_id
> (struct ospf *,
>  extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface
> *);
>  extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface
> *);
>
> +extern void ospf_interface_area_set (struct interface *);
> +extern void ospf_interface_area_unset (struct interface *);
> +
>  extern void ospf_route_map_init (void);
>  extern void ospf_snmp_init (void);
>
> --
> 2.1.0
>
>
> _______________________________________________
> Quagga-dev mailing list
> Quagga-dev@lists.quagga.net
> https://lists.quagga.net/mailman/listinfo/quagga-dev
>
_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to