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.
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.
*
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]);
}
/* Replace all private ASNs with our own ASN */
-struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
+struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn,
+ as_t peer_asn)
{
struct aspath *new;
struct assegment *seg;
int i;
for (i = 0; i < seg->length; i++) {
- if (BGP_AS_IS_PRIVATE(seg->as[i]))
+ /* Don't replace if public ASN or peer's ASN */
+ if (BGP_AS_IS_PRIVATE(seg->as[i])
+ && (seg->as[i] != peer_asn))
seg->as[i] = asn;
}
seg = seg->next;
}
/* Remove all private ASNs */
-struct aspath *aspath_remove_private_asns(struct aspath *aspath)
+struct aspath *aspath_remove_private_asns(struct aspath *aspath, as_t peer_asn)
{
struct aspath *new;
struct assegment *seg;
}
}
- // The entire segment is private so skip it
- if (!public) {
- seg = seg->next;
- continue;
- }
-
// The entire segment is public so copy it
- else if (public == seg->length) {
+ if (public == seg->length)
new_seg = assegment_dup(seg);
- }
// The segment is a mix of public and private ASNs. Copy as many
// spots as
new_seg = assegment_new(seg->type, public);
j = 0;
for (i = 0; i < seg->length; i++) {
- // ASN is public
- if (!BGP_AS_IS_PRIVATE(seg->as[i])) {
+ // keep ASN if public or matches peer's ASN
+ if (!BGP_AS_IS_PRIVATE(seg->as[i])
+ || (seg->as[i] == peer_asn)) {
new_seg->as[j] = seg->as[i];
j++;
}
/* Not reached */
}
-/* Iterate over AS_PATH segments and wipe all occurences of the
+/* Iterate over AS_PATH segments and wipe all occurrences of the
* listed AS numbers. Hence some segments may lose some or even
* all data on the way, the operation is implemented as a smarter
* version of aspath_dup(), which allocates memory to hold the new
const char *p = buf;
/* Skip seperators (space for sequences, ',' for sets). */
- while (isspace((int)*p) || *p == ',')
+ while (isspace((unsigned char)*p) || *p == ',')
p++;
/* Check the end of the string and type specify characters
}
/* Check actual AS value. */
- if (isdigit((int)*p)) {
+ if (isdigit((unsigned char)*p)) {
as_t asval;
*token = as_token_asval;
asval = (*p - '0');
p++;
- while (isdigit((int)*p)) {
+ while (isdigit((unsigned char)*p)) {
asval *= 10;
asval += (*p - '0');
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);
}
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;
*/
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,
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.
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;
}
}
}
+