Acked-by: Donald Sharp <[email protected]>

On Wed, Dec 23, 2015 at 9:47 AM, Timo Teräs <[email protected]> wrote:

> FIB override routes are for routing protocols that establish
> shortcut routes, or establish point-to-point routes that should
> not be redistributed. Namely this is useful NHRP daemon to come.
>
> Zebra is extended to select two entries from RIB the "best" entry
> from routing protocols, and the FIB entry to install to kernel.
> FIB override routes are never selected as best entry, and thus
> are never adverticed to other routing daemons. The best FIB
> override, or if it does not exist the otherwise best RIB is
> selected as FIB entry to be installed.
>
> Signed-off-by: Timo Teräs <[email protected]>
> ---
>  lib/zebra.h       |  1 +
>  zebra/rib.h       |  1 +
>  zebra/zebra_fpm.c |  2 +-
>  zebra/zebra_rib.c | 82
> +++++++++++++++++++++++++++++++++++++++----------------
>  zebra/zebra_vty.c |  4 +++
>  zebra/zserv.c     | 12 ++++----
>  6 files changed, 71 insertions(+), 31 deletions(-)
>
> diff --git a/lib/zebra.h b/lib/zebra.h
> index a607437..bf5980c 100644
> --- a/lib/zebra.h
> +++ b/lib/zebra.h
> @@ -464,6 +464,7 @@ extern const char *zserv_command_string (unsigned int
> command);
>  #define ZEBRA_FLAG_BLACKHOLE          0x04
>  #define ZEBRA_FLAG_IBGP               0x08
>  #define ZEBRA_FLAG_SELECTED           0x10
> +#define ZEBRA_FLAG_FIB_OVERRIDE       0x20
>  #define ZEBRA_FLAG_STATIC             0x40
>  #define ZEBRA_FLAG_REJECT             0x80
>
> diff --git a/zebra/rib.h b/zebra/rib.h
> index ffe7e2f..67ffe8d 100644
> --- a/zebra/rib.h
> +++ b/zebra/rib.h
> @@ -83,6 +83,7 @@ struct rib
>    u_char status;
>  #define RIB_ENTRY_REMOVED      (1 << 0)
>  #define RIB_ENTRY_CHANGED      (1 << 1)
> +#define RIB_ENTRY_SELECTED_FIB (1 << 2)
>
>    /* Nexthop information. */
>    u_char nexthop_num;
> diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
> index 292dbb6..cb04f21 100644
> --- a/zebra/zebra_fpm.c
> +++ b/zebra/zebra_fpm.c
> @@ -889,7 +889,7 @@ zfpm_route_for_update (rib_dest_t *dest)
>
>    RIB_DEST_FOREACH_ROUTE (dest, rib)
>      {
> -      if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
> +      if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
>         continue;
>
>        return rib;
> diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
> index 9264087..d06382c 100644
> --- a/zebra/zebra_rib.c
> +++ b/zebra/zebra_rib.c
> @@ -387,7 +387,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop
> *nexthop, int set,
>         {
>           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
>             continue;
> -         if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
> +         if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
>             break;
>         }
>
> @@ -521,7 +521,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop
> *nexthop, int set,
>         {
>           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
>             continue;
> -         if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
> +         if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
>             break;
>         }
>
> @@ -633,7 +633,7 @@ rib_match_ipv4_safi (struct in_addr addr, safi_t safi,
> int skip_bgp,
>         {
>           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
>             continue;
> -         if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
> +         if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
>             break;
>         }
>
> @@ -778,7 +778,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t
> vrf_id)
>      {
>        if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
>         continue;
> -      if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
> +      if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
>         break;
>      }
>
> @@ -838,7 +838,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union
> sockunion * qgate,
>      {
>        if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
>         continue;
> -      if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
> +      if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
>         break;
>      }
>
> @@ -904,7 +904,7 @@ rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
>         {
>           if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
>             continue;
> -         if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
> +         if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB))
>             break;
>         }
>
> @@ -1139,7 +1139,7 @@ rib_uninstall (struct route_node *rn, struct rib
> *rib)
>  {
>    rib_table_info_t *info = rn->table->info;
>
> -  if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
> +  if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
>      {
>        if (info->safi == SAFI_UNICAST)
>          zfpm_trigger_update (rn, "rib_uninstall");
> @@ -1259,6 +1259,8 @@ rib_process (struct route_node *rn)
>  {
>    struct rib *rib;
>    struct rib *next;
> +  struct rib *old_selected = NULL;
> +  struct rib *new_selected = NULL;
>    struct rib *old_fib = NULL;
>    struct rib *new_fib = NULL;
>    int installed = 0;
> @@ -1275,6 +1277,11 @@ rib_process (struct route_node *rn)
>        /* Currently installed rib. */
>        if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
>          {
> +          assert (old_selected == NULL);
> +          old_selected = rib;
> +        }
> +      if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
> +        {
>            assert (old_fib == NULL);
>            old_fib = rib;
>          }
> @@ -1291,17 +1298,31 @@ rib_process (struct route_node *rn)
>        if (rib->distance == DISTANCE_INFINITY)
>          continue;
>
> -      new_fib = rib_choose_best(new_fib, rib);
> +      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
> +        new_fib = rib_choose_best(new_fib, rib);
> +      else
> +        new_selected = rib_choose_best(new_selected, rib);
>      } /* RNODE_FOREACH_RIB_SAFE */
>
> +  /* If no FIB override route, use the selected route also for FIB */
> +  if (new_fib == NULL)
> +    new_fib = new_selected;
> +
>    /* After the cycle is finished, the following pointers will be set:
> -   * old_fib --- RIB entry currently having SELECTED
> -   * new_fib --- RIB entry that is newly SELECTED
> +   * old_selected --- RIB entry currently having SELECTED
> +   * new_selected --- RIB entry that is newly SELECTED
> +   * old_fib      --- RIB entry currently in kernel FIB
> +   * new_fib      --- RIB entry that is newly to be in kernel FIB
> +   *
> +   * new_selected will get SELECTED flag, and is going to be redistributed
> +   * the zclients. new_fib (which can be new_selected) will be installed
> in kernel.
>     */
>
>    /* Set real nexthops. */
>    if (new_fib)
>      nexthop_active_update (rn, new_fib, 1);
> +  if (new_selected && new_selected != new_fib)
> +     nexthop_active_update (rn, new_selected, 1);
>
>    /* Update kernel if FIB entry has changed */
>    if (old_fib != new_fib
> @@ -1309,20 +1330,15 @@ rib_process (struct route_node *rn)
>      {
>          if (old_fib && old_fib != new_fib)
>            {
> -            if (! new_fib)
> -              redistribute_delete (&rn->p, old_fib);
> -
>              if (! RIB_SYSTEM_ROUTE (old_fib) && (! new_fib ||
> RIB_SYSTEM_ROUTE (new_fib)))
>                rib_update_kernel (rn, old_fib, NULL);
> -            UNSET_FLAG (old_fib->flags, ZEBRA_FLAG_SELECTED);
> +            UNSET_FLAG (old_fib->status, RIB_ENTRY_SELECTED_FIB);
>            }
>
>          if (new_fib)
>            {
>              /* Install new or replace existing FIB entry */
> -            SET_FLAG (new_fib->flags, ZEBRA_FLAG_SELECTED);
> -            redistribute_add (&rn->p, new_fib);
> -
> +            SET_FLAG (new_fib->status, RIB_ENTRY_SELECTED_FIB);
>              if (! RIB_SYSTEM_ROUTE (new_fib))
>                rib_update_kernel (rn, old_fib, new_fib);
>            }
> @@ -1346,6 +1362,26 @@ rib_process (struct route_node *rn)
>          rib_update_kernel (rn, NULL, new_fib);
>      }
>
> +  /* Redistribute SELECTED entry */
> +  if (old_selected != new_selected
> +      || (new_selected && CHECK_FLAG (new_selected->status,
> RIB_ENTRY_CHANGED)))
> +    {
> +      if (old_selected)
> +        {
> +          if (! new_selected)
> +            redistribute_delete (&rn->p, old_selected);
> +          if (old_selected != new_selected)
> +            UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED);
> +        }
> +
> +      if (new_selected)
> +        {
> +          /* Install new or replace existing redistributed entry */
> +          SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED);
> +          redistribute_add (&rn->p, new_selected);
> +        }
> +     }
> +
>    /* Remove all RIB entries queued for removal */
>    RNODE_FOREACH_RIB_SAFE (rn, rib, next)
>      {
> @@ -1947,7 +1983,7 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p)
>     */
>    RNODE_FOREACH_RIB (rn, rib)
>    {
> -    if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
> +    if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB) &&
>        ! RIB_SYSTEM_ROUTE (rib))
>      {
>        changed = 1;
> @@ -2098,7 +2134,7 @@ rib_delete_ipv4 (int type, int flags, struct
> prefix_ipv4 *p,
>        if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
>          continue;
>
> -      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
> +      if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
>         fib = rib;
>
>        if (rib->type != type)
> @@ -2146,7 +2182,7 @@ rib_delete_ipv4 (int type, int flags, struct
> prefix_ipv4 *p,
>           for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
>             UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
>
> -         UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
> +         UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
>         }
>        else
>         {
> @@ -2675,7 +2711,7 @@ rib_delete_ipv6 (int type, int flags, struct
> prefix_ipv6 *p,
>        if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
>          continue;
>
> -      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
> +      if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
>         fib = rib;
>
>        if (rib->type != type)
> @@ -2724,7 +2760,7 @@ rib_delete_ipv6 (int type, int flags, struct
> prefix_ipv6 *p,
>           for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
>             UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
>
> -         UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
> +         UNSET_FLAG (fib->status, RIB_ENTRY_SELECTED_FIB);
>         }
>        else
>         {
> @@ -3058,7 +3094,7 @@ rib_close_table (struct route_table *table)
>      for (rn = route_top (table); rn; rn = route_next (rn))
>        RNODE_FOREACH_RIB (rn, rib)
>          {
> -          if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
> +          if (!CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
>             continue;
>
>            if (info->safi == SAFI_UNICAST)
> diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
> index 656f55d..21b92ea 100644
> --- a/zebra/zebra_vty.c
> +++ b/zebra/zebra_vty.c
> @@ -1295,6 +1295,10 @@ vty_show_ip_route_detail (struct vty *vty, struct
> route_node *rn, int mcast)
>        vty_out (vty, ", vrf %u", rib->vrf_id);
>        if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
>          vty_out (vty, ", best");
> +      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_FIB_OVERRIDE))
> +        vty_out (vty, ", fib-override");
> +      if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
> +        vty_out (vty, ", fib");
>        if (rib->refcnt)
>          vty_out (vty, ", refcnt %ld", rib->refcnt);
>        if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
> diff --git a/zebra/zserv.c b/zebra/zserv.c
> index 7a75ed4..600b0e5 100644
> --- a/zebra/zserv.c
> +++ b/zebra/zserv.c
> @@ -397,8 +397,7 @@ zsend_route_multipath (int cmd, struct zserv *client,
> struct prefix *p,
>
>    for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
>      {
> -      if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
> -          || nexthop_has_fib_child(nexthop))
> +      if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
>          {
>            SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
>            SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
> @@ -504,7 +503,7 @@ zsend_ipv6_nexthop_lookup (struct zserv *client,
> struct in6_addr *addr,
>         * are looking up. Therefore, we will just iterate over the top
>         * chain of nexthops. */
>        for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
> -       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
> +       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
>           {
>             stream_putc (s, nexthop->type);
>             switch (nexthop->type)
> @@ -574,7 +573,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client,
> struct in_addr addr,
>         * are looking up. Therefore, we will just iterate over the top
>         * chain of nexthops. */
>        for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
> -       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
> +       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
>           {
>             stream_putc (s, nexthop->type);
>             switch (nexthop->type)
> @@ -644,7 +643,7 @@ zsend_ipv4_nexthop_lookup_mrib (struct zserv *client,
> struct in_addr addr,
>         * are looking up. Therefore, we will just iterate over the top
>         * chain of nexthops. */
>        for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
> -       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
> +       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
>           {
>             stream_putc (s, nexthop->type);
>             switch (nexthop->type)
> @@ -709,8 +708,7 @@ zsend_ipv4_import_lookup (struct zserv *client, struct
> prefix_ipv4 *p,
>        nump = stream_get_endp(s);
>        stream_putc (s, 0);
>        for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
> -       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
> -            || nexthop_has_fib_child(nexthop))
> +       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
>           {
>             stream_putc (s, nexthop->type);
>             switch (nexthop->type)
> --
> 2.6.4
>
>
> _______________________________________________
> Quagga-dev mailing list
> [email protected]
> https://lists.quagga.net/mailman/listinfo/quagga-dev
_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to