]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_aspath.c
bgpd: Adding BGP GR Global & Per Neighbour FSM changes
[mirror_frr.git] / bgpd / bgp_aspath.c
index f5652b07c5e46cb66ef3a1ea2c5fbd26dd4b6411..a781e70d2f58798c98fa5a6a596e9b496e09def2 100644 (file)
@@ -102,8 +102,10 @@ static void assegment_data_free(as_t *asdata)
        XFREE(MTYPE_AS_SEG_DATA, asdata);
 }
 
-const char *aspath_segment_type_str[] = {"as-invalid", "as-set", "as-sequence",
-                                        "as-confed-sequence", "as-confed-set"};
+const char *const aspath_segment_type_str[] = {
+       "as-invalid", "as-set", "as-sequence", "as-confed-sequence",
+       "as-confed-set"
+};
 
 /* Get a new segment. Note that 0 is an allowed length,
  * and will result in a segment with no allocated data segment.
@@ -414,6 +416,19 @@ unsigned int aspath_count_hops(const struct aspath *aspath)
        return count;
 }
 
+/* Check if aspath has AS_SET or AS_CONFED_SET */
+bool aspath_check_as_sets(struct aspath *aspath)
+{
+       struct assegment *seg = aspath->segments;
+
+       while (seg) {
+               if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
+                       return true;
+               seg = seg->next;
+       }
+       return false;
+}
+
 /* Estimate size aspath /might/ take if encoded into an
  * ASPATH attribute.
  *
@@ -576,7 +591,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
                        if (make_json)
                                json_object_array_add(
                                        jseg_list,
-                                       json_object_new_int(seg->as[i]));
+                                       json_object_new_int64(seg->as[i]));
 
                        len += snprintf(str_buf + len, str_size - len, "%u",
                                        seg->as[i]);
@@ -2114,15 +2129,12 @@ static void *bgp_aggr_aspath_hash_alloc(void *p)
 
 static void bgp_aggr_aspath_prepare(struct hash_backet *hb, void *arg)
 {
-       struct aspath *asmerge = NULL;
        struct aspath *hb_aspath = hb->data;
        struct aspath **aggr_aspath = arg;
 
-       if (*aggr_aspath) {
-               asmerge = aspath_aggregate(*aggr_aspath, hb_aspath);
-               aspath_free(*aggr_aspath);
-               *aggr_aspath = asmerge;
-       } else
+       if (*aggr_aspath)
+               *aggr_aspath = aspath_aggregate(*aggr_aspath, hb_aspath);
+       else
                *aggr_aspath = aspath_dup(hb_aspath);
 }
 
@@ -2135,6 +2147,15 @@ void bgp_aggr_aspath_remove(void *arg)
 
 void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
                                  struct aspath *aspath)
+{
+       bgp_compute_aggregate_aspath_hash(aggregate, aspath);
+
+       bgp_compute_aggregate_aspath_val(aggregate);
+
+}
+
+void bgp_compute_aggregate_aspath_hash(struct bgp_aggregate *aggregate,
+                                      struct aspath *aspath)
 {
        struct aspath *aggr_aspath = NULL;
 
@@ -2154,17 +2175,29 @@ void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
                 */
                aggr_aspath = hash_get(aggregate->aspath_hash, aspath,
                                       bgp_aggr_aspath_hash_alloc);
+       }
 
-               /* Compute aggregate's as-path.
-                */
+       /* Increment reference counter.
+        */
+       aggr_aspath->refcnt++;
+}
+
+void bgp_compute_aggregate_aspath_val(struct bgp_aggregate *aggregate)
+{
+       if (aggregate == NULL)
+               return;
+       /* Re-compute aggregate's as-path.
+        */
+       if (aggregate->aspath) {
+               aspath_free(aggregate->aspath);
+               aggregate->aspath = NULL;
+       }
+       if (aggregate->aspath_hash
+           && aggregate->aspath_hash->count) {
                hash_iterate(aggregate->aspath_hash,
                             bgp_aggr_aspath_prepare,
                             &aggregate->aspath);
        }
-
-       /* Increment refernce counter.
-        */
-       aggr_aspath->refcnt++;
 }
 
 void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
@@ -2173,10 +2206,9 @@ void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
        struct aspath *aggr_aspath = NULL;
        struct aspath *ret_aspath = NULL;
 
-       if ((aggregate == NULL) || (aspath == NULL))
-               return;
-
-       if (aggregate->aspath_hash == NULL)
+       if ((!aggregate)
+           || (!aggregate->aspath_hash)
+           || (!aspath))
                return;
 
        /* Look-up the aspath in the hash.
@@ -2189,17 +2221,41 @@ void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
                        ret_aspath = hash_release(aggregate->aspath_hash,
                                                  aggr_aspath);
                        aspath_free(ret_aspath);
+                       ret_aspath = NULL;
 
                        /* Remove aggregate's old as-path.
                         */
                        aspath_free(aggregate->aspath);
                        aggregate->aspath = NULL;
 
-                       /* Compute aggregate's as-path.
-                        */
-                       hash_iterate(aggregate->aspath_hash,
-                                    bgp_aggr_aspath_prepare,
-                                    &aggregate->aspath);
+                       bgp_compute_aggregate_aspath_val(aggregate);
+               }
+       }
+}
+
+void bgp_remove_aspath_from_aggregate_hash(struct bgp_aggregate *aggregate,
+                                          struct aspath *aspath)
+{
+       struct aspath *aggr_aspath = NULL;
+       struct aspath *ret_aspath = NULL;
+
+       if ((!aggregate)
+           || (!aggregate->aspath_hash)
+           || (!aspath))
+               return;
+
+       /* Look-up the aspath in the hash.
+        */
+       aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+       if (aggr_aspath) {
+               aggr_aspath->refcnt--;
+
+               if (aggr_aspath->refcnt == 0) {
+                       ret_aspath = hash_release(aggregate->aspath_hash,
+                                                 aggr_aspath);
+                       aspath_free(ret_aspath);
+                       ret_aspath = NULL;
                }
        }
 }
+