]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Configuring default-originate withdraws default route 6184/head
authorSoman K S <somanks@gmail.com>
Wed, 8 Apr 2020 09:34:10 +0000 (15:04 +0530)
committerSoman K S <somanks@gmail.com>
Wed, 22 Apr 2020 17:04:12 +0000 (22:34 +0530)
Issue:
Configuring default-originate when static default route is previously
advertised results in withdrawal of the route.

Fix :
Delete the adj-out entry for the previously advertised static
default route without sending explicit withdraw message.

Signed-off-by: kssoman <somanks@gmail.com>
bgpd/bgp_updgrp_adv.c

index e40b3320ea4642536dd6281928a5cbaac69a902e..6399bc93aa26c6be61502d3b57227bca741600d9 100644 (file)
@@ -533,6 +533,14 @@ void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
                if (adj->adv)
                        bgp_advertise_clean_subgroup(subgrp, adj);
 
+               /* If default originate is enabled and the route is default
+                * route, do not send withdraw. This will prevent deletion of
+                * the default route at the peer.
+                */
+               if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)
+                   && is_default_prefix(&rn->p))
+                       return;
+
                if (adj->attr && withdraw) {
                        /* We need advertisement structure.  */
                        adj->adv = bgp_advertise_new();
@@ -636,12 +644,25 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
                                                            rn_p, &attr))
                                        bgp_adj_out_set_subgroup(rn, subgrp,
                                                                 &attr, ri);
-                               else
+                               else {
+                                       /* If default originate is enabled for
+                                        * the peer, do not send explicit
+                                        * withdraw. This will prevent deletion
+                                        * of default route advertised through
+                                        * default originate
+                                        */
+                                       if (CHECK_FLAG(
+                                                   peer->af_flags[afi][safi],
+                                                   PEER_FLAG_DEFAULT_ORIGINATE)
+                                           && is_default_prefix(&rn->p))
+                                               break;
+
                                        bgp_adj_out_unset_subgroup(
                                                rn, subgrp, 1,
                                                bgp_addpath_id_for_peer(
                                                        peer, afi, safi,
                                                        &ri->tx_addpath));
+                               }
                        }
        }
 
@@ -709,7 +730,9 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
        struct prefix p;
        struct peer *from;
        struct bgp_node *rn;
+       struct bgp_path_info *pi;
        struct peer *peer;
+       struct bgp_adj_out *adj;
        route_map_result_t ret = RMAP_DENYMATCH;
        afi_t afi;
        safi_t safi;
@@ -732,10 +755,6 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
 
        attr.local_pref = bgp->default_local_pref;
 
-       memset(&p, 0, sizeof(p));
-       p.family = afi2family(afi);
-       p.prefixlen = 0;
-
        if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
                /* IPv6 global nexthop must be included. */
                attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
@@ -778,21 +797,40 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
                }
        }
 
+       /* Check if the default route is in local BGP RIB which is
+        * installed through redistribute or network command
+        */
+       memset(&p, 0, sizeof(p));
+       p.family = afi2family(afi);
+       p.prefixlen = 0;
+       rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, &p, NULL);
+
        if (withdraw) {
+               /* Withdraw the default route advertised using default
+                * originate
+                */
                if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
                        subgroup_default_withdraw_packet(subgrp);
                UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
+
+               /* If default route is present in the local RIB, advertise the
+                * route
+                */
+               if (rn != NULL) {
+                       for (pi = bgp_node_get_bgp_path_info(rn); pi;
+                            pi = pi->next) {
+                               if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
+                                       if (subgroup_announce_check(
+                                                   rn, pi, subgrp, &rn->p,
+                                                   &attr))
+                                               bgp_adj_out_set_subgroup(
+                                                       rn, subgrp, &attr, pi);
+                       }
+               }
        } else {
                if (!CHECK_FLAG(subgrp->sflags,
                                SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
 
-                       if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
-                               bgp_attr_add_gshut_community(new_attr);
-
-                       SET_FLAG(subgrp->sflags,
-                                SUBGRP_STATUS_DEFAULT_ORIGINATE);
-                       subgroup_default_update_packet(subgrp, new_attr, from);
-
                        /* The 'neighbor x.x.x.x default-originate' default will
                         * act as an
                         * implicit withdraw for any previous UPDATEs sent for
@@ -800,15 +838,37 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
                         * clear adj_out for the 0.0.0.0/0 prefix in the BGP
                         * table.
                         */
-                       memset(&p, 0, sizeof(p));
-                       p.family = afi2family(afi);
-                       p.prefixlen = 0;
-
-                       rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
-                                             &p, NULL);
-                       bgp_adj_out_unset_subgroup(
-                               rn, subgrp, 0,
-                               BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+                       if (rn != NULL) {
+                               /* Remove the adjacency for the previously
+                                * advertised default route
+                                */
+                               adj = adj_lookup(
+                                      rn, subgrp,
+                                      BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+                               if (adj != NULL) {
+                                       /* Clean up previous advertisement.  */
+                                       if (adj->adv)
+                                               bgp_advertise_clean_subgroup(
+                                                       subgrp, adj);
+
+                                       /* Remove  from adjacency. */
+                                       RB_REMOVE(bgp_adj_out_rb, &rn->adj_out,
+                                                 adj);
+
+                                       /* Free allocated information.  */
+                                       adj_free(adj);
+
+                                       bgp_unlock_node(rn);
+                               }
+                       }
+
+                       /* Advertise the default route */
+                       if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
+                               bgp_attr_add_gshut_community(new_attr);
+
+                       SET_FLAG(subgrp->sflags,
+                                SUBGRP_STATUS_DEFAULT_ORIGINATE);
+                       subgroup_default_update_packet(subgrp, new_attr, from);
                }
        }