]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_updgrp_adv.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / bgpd / bgp_updgrp_adv.c
index 594eec59eb75261b2ebbb2b7dbca1836332eb965..3870df593f51a2278c1770167212aec5b8b59da7 100644 (file)
 #include "bgpd/bgp_mplsvpn.h"
 #include "bgpd/bgp_updgrp.h"
 #include "bgpd/bgp_advertise.h"
+#include "bgpd/bgp_addpath.h"
 
 
 /********************
  * PRIVATE FUNCTIONS
  ********************/
+static int bgp_adj_out_compare(const struct bgp_adj_out *o1,
+                              const struct bgp_adj_out *o2)
+{
+       if (o1->subgroup < o2->subgroup)
+               return -1;
+
+       if (o1->subgroup > o2->subgroup)
+               return 1;
+
+       return 0;
+}
+RB_GENERATE(bgp_adj_out_rb, bgp_adj_out, adj_entry, bgp_adj_out_compare);
 
 static inline struct bgp_adj_out *adj_lookup(struct bgp_node *rn,
                                             struct update_subgroup *subgrp,
                                             uint32_t addpath_tx_id)
 {
-       struct bgp_adj_out *adj;
+       struct bgp_adj_out *adj, lookup;
        struct peer *peer;
        afi_t afi;
        safi_t safi;
@@ -75,19 +88,16 @@ static inline struct bgp_adj_out *adj_lookup(struct bgp_node *rn,
 
        /* update-groups that do not support addpath will pass 0 for
         * addpath_tx_id so do not both matching against it */
-       for (adj = rn->adj_out; adj; adj = adj->next) {
-               if (adj->subgroup == subgrp) {
-                       if (addpath_capable) {
-                               if (adj->addpath_tx_id == addpath_tx_id) {
-                                       break;
-                               }
-                       } else {
-                               break;
-                       }
-               }
+       lookup.subgroup = subgrp;
+       adj = RB_FIND(bgp_adj_out_rb, &rn->adj_out, &lookup);
+       if (adj) {
+               if (addpath_capable) {
+                       if (adj->addpath_tx_id == addpath_tx_id)
+                               return adj;
+               } else
+                       return adj;
        }
-
-       return adj;
+       return NULL;
 }
 
 static void adj_free(struct bgp_adj_out *adj)
@@ -97,11 +107,45 @@ static void adj_free(struct bgp_adj_out *adj)
        XFREE(MTYPE_BGP_ADJ_OUT, adj);
 }
 
+static void subgrp_withdraw_stale_addpath(struct updwalk_context *ctx,
+                                         struct update_subgroup *subgrp)
+{
+       struct bgp_adj_out *adj, *adj_next;
+       uint32_t id;
+       struct bgp_path_info *pi;
+       afi_t afi = SUBGRP_AFI(subgrp);
+       safi_t safi = SUBGRP_SAFI(subgrp);
+       struct peer *peer = SUBGRP_PEER(subgrp);
+
+       /* Look through all of the paths we have advertised for this rn and send
+        * a withdraw for the ones that are no longer present */
+       RB_FOREACH_SAFE (adj, bgp_adj_out_rb, &ctx->rn->adj_out, adj_next) {
+
+               if (adj->subgroup == subgrp) {
+                       for (pi = bgp_node_get_bgp_path_info(ctx->rn);
+                            pi; pi = pi->next) {
+                               id = bgp_addpath_id_for_peer(peer, afi, safi,
+                                       &pi->tx_addpath);
+
+                               if (id == adj->addpath_tx_id) {
+                                       break;
+                               }
+                       }
+
+                       if (!pi) {
+                               subgroup_process_announce_selected(
+                                       subgrp, NULL, ctx->rn,
+                                       adj->addpath_tx_id);
+                       }
+               }
+       }
+}
+
 static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
 {
        struct updwalk_context *ctx = arg;
        struct update_subgroup *subgrp;
-       struct bgp_info *ri;
+       struct bgp_path_info *pi;
        afi_t afi;
        safi_t safi;
        struct peer *peer;
@@ -131,66 +175,48 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
                if (!subgrp->t_coalesce) {
                        /* An update-group that uses addpath */
                        if (addpath_capable) {
-                               /* Look through all of the paths we have
-                                * advertised for this rn and
-                                * send a withdraw for the ones that are no
-                                * longer present */
-                               for (adj = ctx->rn->adj_out; adj;
-                                    adj = adj_next) {
-                                       adj_next = adj->next;
-
-                                       if (adj->subgroup == subgrp) {
-                                               for (ri = ctx->rn->info; ri;
-                                                    ri = ri->next) {
-                                                       if (ri->addpath_tx_id
-                                                           == adj->addpath_tx_id) {
-                                                               break;
-                                                       }
-                                               }
+                               subgrp_withdraw_stale_addpath(ctx, subgrp);
 
-                                               if (!ri) {
-                                                       subgroup_process_announce_selected(
-                                                               subgrp, NULL,
-                                                               ctx->rn,
-                                                               adj->addpath_tx_id);
-                                               }
-                                       }
-                               }
-
-                               for (ri = ctx->rn->info; ri; ri = ri->next) {
+                               for (pi = bgp_node_get_bgp_path_info(ctx->rn);
+                                    pi; pi = pi->next) {
                                        /* Skip the bestpath for now */
-                                       if (ri == ctx->ri)
+                                       if (pi == ctx->pi)
                                                continue;
 
                                        subgroup_process_announce_selected(
-                                               subgrp, ri, ctx->rn,
-                                               ri->addpath_tx_id);
+                                               subgrp, pi, ctx->rn,
+                                               bgp_addpath_id_for_peer(
+                                                       peer, afi, safi,
+                                                       &pi->tx_addpath));
                                }
 
                                /* Process the bestpath last so the "show [ip]
                                 * bgp neighbor x.x.x.x advertised"
                                 * output shows the attributes from the bestpath
                                 */
-                               if (ctx->ri)
+                               if (ctx->pi)
                                        subgroup_process_announce_selected(
-                                               subgrp, ctx->ri, ctx->rn,
-                                               ctx->ri->addpath_tx_id);
+                                               subgrp, ctx->pi, ctx->rn,
+                                               bgp_addpath_id_for_peer(
+                                                       peer, afi, safi,
+                                                       &ctx->pi->tx_addpath));
                        }
 
                        /* An update-group that does not use addpath */
                        else {
-                               if (ctx->ri) {
+                               if (ctx->pi) {
                                        subgroup_process_announce_selected(
-                                               subgrp, ctx->ri, ctx->rn,
-                                               ctx->ri->addpath_tx_id);
+                                               subgrp, ctx->pi, ctx->rn,
+                                               bgp_addpath_id_for_peer(
+                                                       peer, afi, safi,
+                                                       &ctx->pi->tx_addpath));
                                } else {
                                        /* Find the addpath_tx_id of the path we
                                         * had advertised and
                                         * send a withdraw */
-                                       for (adj = ctx->rn->adj_out; adj;
-                                            adj = adj_next) {
-                                               adj_next = adj->next;
-
+                                       RB_FOREACH_SAFE (adj, bgp_adj_out_rb,
+                                                        &ctx->rn->adj_out,
+                                                        adj_next) {
                                                if (adj->subgroup == subgrp) {
                                                        subgroup_process_announce_selected(
                                                                subgrp, NULL,
@@ -226,7 +252,7 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
        output_count = 0;
 
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
-               for (adj = rn->adj_out; adj; adj = adj->next)
+               RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
                        if (adj->subgroup == subgrp) {
                                if (header1) {
                                        vty_out(vty,
@@ -377,7 +403,7 @@ struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
        adj = XCALLOC(MTYPE_BGP_ADJ_OUT, sizeof(struct bgp_adj_out));
        adj->subgroup = subgrp;
        if (rn) {
-               BGP_ADJ_OUT_ADD(rn, adj);
+               RB_INSERT(bgp_adj_out_rb, &rn->adj_out, adj);
                bgp_lock_node(rn);
                adj->rn = rn;
        }
@@ -429,19 +455,31 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
 
 void bgp_adj_out_set_subgroup(struct bgp_node *rn,
                              struct update_subgroup *subgrp, struct attr *attr,
-                             struct bgp_info *binfo)
+                             struct bgp_path_info *path)
 {
        struct bgp_adj_out *adj = NULL;
        struct bgp_advertise *adv;
+       struct peer *peer;
+       afi_t afi;
+       safi_t safi;
+
+       peer = SUBGRP_PEER(subgrp);
+       afi = SUBGRP_AFI(subgrp);
+       safi = SUBGRP_SAFI(subgrp);
 
        if (DISABLE_BGP_ANNOUNCE)
                return;
 
        /* Look for adjacency information. */
-       adj = adj_lookup(rn, subgrp, binfo->addpath_tx_id);
+       adj = adj_lookup(
+               rn, subgrp,
+               bgp_addpath_id_for_peer(peer, afi, safi, &path->tx_addpath));
 
        if (!adj) {
-               adj = bgp_adj_out_alloc(subgrp, rn, binfo->addpath_tx_id);
+               adj = bgp_adj_out_alloc(
+                       subgrp, rn,
+                       bgp_addpath_id_for_peer(peer, afi, safi,
+                                             &path->tx_addpath));
                if (!adj)
                        return;
        }
@@ -452,8 +490,9 @@ void bgp_adj_out_set_subgroup(struct bgp_node *rn,
 
        adv = adj->adv;
        adv->rn = rn;
-       assert(adv->binfo == NULL);
-       adv->binfo = bgp_info_lock(binfo); /* bgp_info adj_out reference */
+       assert(adv->pathi == NULL);
+       /* bgp_path_info adj_out reference */
+       adv->pathi = bgp_path_info_lock(path);
 
        if (attr)
                adv->baa = bgp_advertise_intern(subgrp->hash, attr);
@@ -521,7 +560,7 @@ void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
                                subgroup_trigger_write(subgrp);
                } else {
                        /* Remove myself from adjacency. */
-                       BGP_ADJ_OUT_DEL(rn, adj);
+                       RB_REMOVE(bgp_adj_out_rb, &rn->adj_out, adj);
 
                        /* Free allocated information.  */
                        adj_free(adj);
@@ -542,7 +581,7 @@ void bgp_adj_out_remove_subgroup(struct bgp_node *rn, struct bgp_adj_out *adj,
        if (adj->adv)
                bgp_advertise_clean_subgroup(subgrp, adj);
 
-       BGP_ADJ_OUT_DEL(rn, adj);
+       RB_REMOVE(bgp_adj_out_rb, &rn->adj_out, adj);
        adj_free(adj);
 }
 
@@ -568,7 +607,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
                             struct bgp_table *table)
 {
        struct bgp_node *rn;
-       struct bgp_info *ri;
+       struct bgp_path_info *ri;
        struct attr attr;
        struct peer *peer;
        afi_t afi;
@@ -592,11 +631,13 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
                subgroup_default_originate(subgrp, 0);
 
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
-               for (ri = rn->info; ri; ri = ri->next)
+               for (ri = bgp_node_get_bgp_path_info(rn); ri; ri = ri->next)
 
-                       if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
+                       if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED)
                            || (addpath_capable
-                               && bgp_addpath_tx_path(peer, afi, safi, ri))) {
+                               && bgp_addpath_tx_path(
+                                          peer->addpath_type[afi][safi],
+                                          ri))) {
                                if (subgroup_announce_check(rn, ri, subgrp,
                                                            &rn->p, &attr))
                                        bgp_adj_out_set_subgroup(rn, subgrp,
@@ -604,7 +645,9 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
                                else
                                        bgp_adj_out_unset_subgroup(
                                                rn, subgrp, 1,
-                                               ri->addpath_tx_id);
+                                               bgp_addpath_id_for_peer(
+                                                       peer, afi, safi,
+                                                       &ri->tx_addpath));
                        }
 
        /*
@@ -654,9 +697,12 @@ void subgroup_announce_route(struct update_subgroup *subgrp)
                subgroup_announce_table(subgrp, NULL);
        else
                for (rn = bgp_table_top(update_subgroup_rib(subgrp)); rn;
-                    rn = bgp_route_next(rn))
-                       if ((table = (rn->info)) != NULL)
-                               subgroup_announce_table(subgrp, table);
+                    rn = bgp_route_next(rn)) {
+                       table = bgp_node_get_bgp_table_info(rn);
+                       if (!table)
+                               continue;
+                       subgroup_announce_table(subgrp, table);
+               }
 }
 
 void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
@@ -664,10 +710,11 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
        struct bgp *bgp;
        struct attr attr;
        struct aspath *aspath;
+       struct bgp_path_info tmp_info;
        struct prefix p;
        struct peer *from;
        struct bgp_node *rn;
-       struct bgp_info *ri;
+       struct bgp_path_info *ri;
        struct peer *peer;
        int ret = RMAP_DENYMATCH;
        afi_t afi;
@@ -690,7 +737,6 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
        aspath = attr.aspath;
 
        attr.local_pref = bgp->default_local_pref;
-       attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
 
        memset(&p, 0, sizeof(p));
        p.family = afi2family(afi);
@@ -711,21 +757,19 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
                SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
                for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
                     rn = bgp_route_next(rn)) {
-                       for (ri = rn->info; ri; ri = ri->next) {
+                       for (ri = bgp_node_get_bgp_path_info(rn);
+                            ri; ri = ri->next) {
                                struct attr dummy_attr;
-                               struct bgp_info info;
 
                                /* Provide dummy so the route-map can't modify
                                 * the attributes */
                                bgp_attr_dup(&dummy_attr, ri->attr);
-                               info.peer = ri->peer;
-                               info.attr = &dummy_attr;
+                               tmp_info.peer = ri->peer;
+                               tmp_info.attr = &dummy_attr;
 
                                ret = route_map_apply(
                                        peer->default_rmap[afi][safi].map,
-                                       &rn->p, RMAP_BGP, &info);
-
-                               attr.med = info.attr->med;
+                                       &rn->p, RMAP_BGP, &tmp_info);
 
                                /* The route map might have set attributes. If
                                 * we don't flush them
@@ -821,10 +865,10 @@ void subgroup_announce_all(struct update_subgroup *subgrp)
  * input route.
  */
 void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
-                         struct bgp_node *rn, struct bgp_info *ri)
+                         struct bgp_node *rn, struct bgp_path_info *pi)
 {
        struct updwalk_context ctx;
-       ctx.ri = ri;
+       ctx.pi = pi;
        ctx.rn = rn;
        update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx);
 }