mirror of
https://github.com/bgp/bgpq4.git
synced 2024-05-11 05:55:05 +00:00
aggregation added.
This commit is contained in:
2
CHANGES
2
CHANGES
@ -1,3 +1,5 @@
|
||||
0.1.3 (2008-05-20):
|
||||
- aggregation (-A) now supported for Cisco prefix-lists.
|
||||
|
||||
0.1.2 (2008-05-19):
|
||||
- final support for asn32, now with correct syntax for Juniper.
|
||||
|
22
bgpq3.c
22
bgpq3.c
@ -17,15 +17,18 @@
|
||||
#include "sx_report.h"
|
||||
|
||||
extern int debug_expander;
|
||||
extern int debug_aggregation;
|
||||
extern int pipelining;
|
||||
|
||||
int
|
||||
usage(int ecode)
|
||||
{
|
||||
printf("\nUsage: bgpq3 [-h] [-S sources] [-P|G <number>|f <number>] [-36]"
|
||||
printf("\nUsage: bgpq3 [-h] [-S sources] [-P|G <number>|f <number>] [-36A]"
|
||||
" <OBJECTS>...\n");
|
||||
printf(" -3 : assume that your device is asn32-safe\n");
|
||||
printf(" -6 : generate IPv6 prefix-lists (IPv4 by default)\n");
|
||||
printf(" -A : try to aggregate prefix-lists as much as possible"
|
||||
" (Cisco only)\n");
|
||||
printf(" -d : generate some debugging output\n");
|
||||
printf(" -f number : generate input as-path access-list\n");
|
||||
printf(" -G number : generate output as-path access-list\n");
|
||||
@ -90,12 +93,12 @@ main(int argc, char* argv[])
|
||||
int c;
|
||||
struct bgpq_expander expander;
|
||||
int af=AF_INET;
|
||||
int widthSet=0;
|
||||
int widthSet=0, aggregate=0;
|
||||
|
||||
bgpq_expander_init(&expander,af);
|
||||
expander.sources=getenv("IRRD_SOURCES");
|
||||
|
||||
while((c=getopt(argc,argv,"36dhS:Jf:l:W:PG:T"))!=EOF) {
|
||||
while((c=getopt(argc,argv,"36AdhS:Jf:l:W:PG:T"))!=EOF) {
|
||||
switch(c) {
|
||||
case '3':
|
||||
expander.asn32=1;
|
||||
@ -104,6 +107,10 @@ main(int argc, char* argv[])
|
||||
expander.family=AF_INET6;
|
||||
expander.tree->family=AF_INET6;
|
||||
break;
|
||||
case 'A':
|
||||
if(aggregate) debug_aggregation++;
|
||||
aggregate=1;
|
||||
break;
|
||||
case 'd': debug_expander++;
|
||||
break;
|
||||
case 'J': expander.vendor=V_JUNIPER;
|
||||
@ -172,6 +179,12 @@ main(int argc, char* argv[])
|
||||
expander.asnumber=23456;
|
||||
};
|
||||
|
||||
if(aggregate && expander.vendor==V_JUNIPER) {
|
||||
sx_report(SX_FATAL, "Sorry, aggregation (-A) does not work with"
|
||||
" Juniper\n");
|
||||
exit(1);
|
||||
};
|
||||
|
||||
if(!argv[0]) usage(1);
|
||||
|
||||
while(argv[0]) {
|
||||
@ -195,6 +208,9 @@ main(int argc, char* argv[])
|
||||
exit(1);
|
||||
};
|
||||
|
||||
if(aggregate)
|
||||
sx_radix_tree_aggregate(expander.tree);
|
||||
|
||||
switch(expander.generation) {
|
||||
case T_NONE: sx_report(SX_FATAL,"Unreachable point... call snar\n");
|
||||
exit(1);
|
||||
|
@ -202,11 +202,26 @@ bgpq3_print_cprefix(struct sx_radix_node* n, void* ff)
|
||||
{
|
||||
char prefix[128];
|
||||
FILE* f=(FILE*)ff;
|
||||
if(n->isGlue) return;
|
||||
if(!f) f=stdout;
|
||||
if(n->isGlue) goto checkSon;
|
||||
sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix));
|
||||
fprintf(f,"%s prefix-list %s permit %s\n",
|
||||
(n->prefix.family==AF_INET)?"ip":"ipv6",bname?bname:"NN",prefix);
|
||||
if(n->isAggregate) {
|
||||
if(n->aggregateLow>n->prefix.masklen) {
|
||||
fprintf(f,"%s prefix-list %s permit %s ge %u le %u\n",
|
||||
n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN",prefix,
|
||||
n->aggregateLow,n->aggregateHi);
|
||||
} else {
|
||||
fprintf(f,"%s prefix-list %s permit %s le %u\n",
|
||||
n->prefix.family==AF_INET?"ip":"ipv6",bname?bname:"NN",prefix,
|
||||
n->aggregateHi);
|
||||
};
|
||||
} else {
|
||||
fprintf(f,"%s prefix-list %s permit %s\n",
|
||||
(n->prefix.family==AF_INET)?"ip":"ipv6",bname?bname:"NN",prefix);
|
||||
};
|
||||
checkSon:
|
||||
if(n->son)
|
||||
bgpq3_print_cprefix(n->son,ff);
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -506,6 +506,7 @@ bgpq_expand(struct bgpq_expander* b)
|
||||
snprintf(sources,sizeof(sources),"!s%s\n", b->sources);
|
||||
fseek(f,0,SEEK_END);
|
||||
fwrite(sources,strlen(sources),1,f);
|
||||
fgets(sources,sizeof(sources),f);
|
||||
};
|
||||
|
||||
if(b->identify) {
|
||||
@ -513,6 +514,7 @@ bgpq_expand(struct bgpq_expander* b)
|
||||
snprintf(ident,sizeof(ident),"!n" PACKAGE_STRING "\n");
|
||||
fseek(f,0,SEEK_END);
|
||||
fwrite(ident,strlen(ident),1,f);
|
||||
fgets(ident,sizeof(ident),f);
|
||||
};
|
||||
|
||||
for(mc=b->macroses;mc;mc=mc->next) {
|
||||
|
170
sx_prefix.c
170
sx_prefix.c
@ -11,6 +11,8 @@
|
||||
#include "sx_prefix.h"
|
||||
#include "sx_report.h"
|
||||
|
||||
int debug_aggregation=0;
|
||||
|
||||
struct sx_prefix*
|
||||
sx_prefix_alloc(struct sx_prefix* p)
|
||||
{
|
||||
@ -451,6 +453,174 @@ sx_radix_tree_foreach(struct sx_radix_tree* tree,
|
||||
sx_radix_node_foreach(tree->head,func,udata);
|
||||
return 0;
|
||||
};
|
||||
|
||||
int
|
||||
sx_radix_node_aggregate(struct sx_radix_node* node)
|
||||
{
|
||||
if(node->l)
|
||||
sx_radix_node_aggregate(node->l);
|
||||
if(node->r)
|
||||
sx_radix_node_aggregate(node->r);
|
||||
|
||||
if(debug_aggregation) {
|
||||
printf("Aggregating on node: ");
|
||||
sx_prefix_fprint(stdout,&node->prefix);
|
||||
printf(" %s%s%u,%u\n", node->isGlue?"Glue ":"",
|
||||
node->isAggregate?"Aggregate ":"",node->aggregateLow,
|
||||
node->aggregateHi);
|
||||
if(node->r) {
|
||||
printf("R-Tree: ");
|
||||
sx_prefix_fprint(stdout,&node->r->prefix);
|
||||
printf(" %s%s%u,%u\n", (node->r->isGlue)?"Glue ":"",
|
||||
(node->r->isAggregate)?"Aggregate ":"",
|
||||
node->r->aggregateLow,node->r->aggregateHi);
|
||||
if(node->r->son) {
|
||||
printf("R-Son: ");
|
||||
sx_prefix_fprint(stdout,&node->r->son->prefix);
|
||||
printf(" %s%s%u,%u\n",node->r->son->isGlue?"Glue ":"",
|
||||
node->r->son->isAggregate?"Aggregate ":"",
|
||||
node->r->son->aggregateLow,node->r->son->aggregateHi);
|
||||
};
|
||||
};
|
||||
if(node->l) {
|
||||
printf("L-Tree: ");
|
||||
sx_prefix_fprint(stdout,&node->l->prefix);
|
||||
printf(" %s%s%u,%u\n",node->l->isGlue?"Glue ":"",
|
||||
node->l->isAggregate?"Aggregate ":"",
|
||||
node->l->aggregateLow,node->l->aggregateHi);
|
||||
if(node->l->son) {
|
||||
printf("L-Son: ");
|
||||
sx_prefix_fprint(stdout,&node->l->son->prefix);
|
||||
printf(" %s%s%u,%u\n",node->l->son->isGlue?"Glue ":"",
|
||||
node->l->son->isAggregate?"Aggregate ":"",
|
||||
node->l->son->aggregateLow,node->l->son->aggregateHi);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if(node->r && node->l) {
|
||||
if(!node->r->isAggregate && !node->l->isAggregate &&
|
||||
!node->r->isGlue && !node->l->isGlue &&
|
||||
node->r->prefix.masklen==node->l->prefix.masklen) {
|
||||
if(node->r->prefix.masklen==node->prefix.masklen+1) {
|
||||
node->isAggregate=1;
|
||||
node->r->isGlue=1;
|
||||
node->l->isGlue=1;
|
||||
node->aggregateHi=node->r->prefix.masklen;
|
||||
if(node->isGlue) {
|
||||
node->isGlue=0;
|
||||
node->aggregateLow=node->r->prefix.masklen;
|
||||
} else {
|
||||
node->aggregateLow=node->prefix.masklen;
|
||||
};
|
||||
};
|
||||
if(node->r->son && node->l->son &&
|
||||
node->r->son->isAggregate && node->l->son->isAggregate &&
|
||||
node->r->son->aggregateHi==node->l->son->aggregateHi &&
|
||||
node->r->son->aggregateLow==node->l->son->aggregateLow)
|
||||
{
|
||||
node->son=sx_radix_node_new(&node->prefix);
|
||||
node->son->isGlue=0;
|
||||
node->son->isAggregate=1;
|
||||
node->son->aggregateHi=node->r->son->aggregateHi;
|
||||
node->son->aggregateLow=node->r->son->aggregateLow;
|
||||
node->r->son->isGlue=1;
|
||||
node->l->son->isGlue=1;
|
||||
};
|
||||
} else if(node->r->isAggregate && node->l->isAggregate &&
|
||||
node->r->aggregateHi==node->l->aggregateHi &&
|
||||
node->r->aggregateLow==node->l->aggregateLow) {
|
||||
if(node->r->prefix.masklen==node->prefix.masklen+1) {
|
||||
if(node->isGlue) {
|
||||
node->r->isGlue=1;
|
||||
node->l->isGlue=1;
|
||||
node->isAggregate=1;
|
||||
node->isGlue=0;
|
||||
node->aggregateHi=node->r->aggregateHi;
|
||||
node->aggregateLow=node->r->aggregateLow;
|
||||
} else if(node->r->prefix.masklen==node->r->aggregateLow) {
|
||||
node->r->isGlue=1;
|
||||
node->l->isGlue=1;
|
||||
node->isAggregate=1;
|
||||
node->aggregateHi=node->r->aggregateHi;
|
||||
node->aggregateLow=node->prefix.masklen;
|
||||
} else {
|
||||
node->son=sx_radix_node_new(&node->prefix);
|
||||
node->son->isGlue=0;
|
||||
node->son->isAggregate=1;
|
||||
node->son->aggregateHi=node->r->aggregateHi;
|
||||
node->son->aggregateLow=node->r->aggregateLow;
|
||||
node->r->isGlue=1;
|
||||
node->l->isGlue=1;
|
||||
if(node->r->son && node->l->son &&
|
||||
node->r->son->aggregateHi==node->l->son->aggregateHi &&
|
||||
node->r->son->aggregateLow==node->l->son->aggregateLow)
|
||||
{
|
||||
node->son->son=sx_radix_node_new(&node->prefix);
|
||||
node->son->son->isGlue=0;
|
||||
node->son->son->isAggregate=1;
|
||||
node->son->son->aggregateHi=node->r->son->aggregateHi;
|
||||
node->son->son->aggregateLow=node->r->son->aggregateLow;
|
||||
node->r->son->isGlue=1;
|
||||
node->l->son->isGlue=1;
|
||||
};
|
||||
};
|
||||
};
|
||||
} else if(node->l->son &&
|
||||
node->r->isAggregate && node->l->son->isAggregate &&
|
||||
node->r->aggregateHi==node->l->son->aggregateHi &&
|
||||
node->r->aggregateLow==node->l->son->aggregateLow) {
|
||||
if(node->r->prefix.masklen==node->prefix.masklen+1) {
|
||||
if(node->isGlue) {
|
||||
node->r->isGlue=1;
|
||||
node->l->son->isGlue=1;
|
||||
node->isAggregate=1;
|
||||
node->isGlue=0;
|
||||
node->aggregateHi=node->r->aggregateHi;
|
||||
node->aggregateLow=node->r->aggregateLow;
|
||||
} else {
|
||||
node->son=sx_radix_node_new(&node->prefix);
|
||||
node->son->isGlue=0;
|
||||
node->son->isAggregate=1;
|
||||
node->son->aggregateHi=node->r->aggregateHi;
|
||||
node->son->aggregateLow=node->r->aggregateLow;
|
||||
node->r->isGlue=1;
|
||||
node->l->son->isGlue=1;
|
||||
};
|
||||
};
|
||||
} else if(node->r->son &&
|
||||
node->l->isAggregate && node->r->son->isAggregate &&
|
||||
node->l->aggregateHi==node->r->son->aggregateHi &&
|
||||
node->l->aggregateLow==node->r->son->aggregateLow) {
|
||||
if(node->l->prefix.masklen==node->prefix.masklen+1) {
|
||||
if(node->isGlue) {
|
||||
node->l->isGlue=1;
|
||||
node->r->son->isGlue=1;
|
||||
node->isAggregate=1;
|
||||
node->isGlue=0;
|
||||
node->aggregateHi=node->l->aggregateHi;
|
||||
node->aggregateLow=node->l->aggregateLow;
|
||||
} else {
|
||||
node->son=sx_radix_node_new(&node->prefix);
|
||||
node->son->isGlue=0;
|
||||
node->son->isAggregate=1;
|
||||
node->son->aggregateHi=node->l->aggregateHi;
|
||||
node->son->aggregateLow=node->l->aggregateLow;
|
||||
node->l->isGlue=1;
|
||||
node->r->son->isGlue=1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
int
|
||||
sx_radix_tree_aggregate(struct sx_radix_tree* tree)
|
||||
{
|
||||
if(tree && tree->head) return sx_radix_node_aggregate(tree->head);
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
10
sx_prefix.h
10
sx_prefix.h
@ -17,9 +17,13 @@ typedef struct sx_prefix {
|
||||
} sx_prefix_t;
|
||||
|
||||
typedef struct sx_radix_node {
|
||||
struct sx_radix_node* parent, *l, *r;
|
||||
struct sx_radix_node* parent, *l, *r, *son;
|
||||
void* payload;
|
||||
int isGlue;
|
||||
unsigned int isGlue:1;
|
||||
unsigned int isAggregated:1;
|
||||
unsigned int isAggregate:1;
|
||||
unsigned int aggregateLow;
|
||||
unsigned int aggregateHi;
|
||||
struct sx_prefix prefix;
|
||||
} sx_radix_node_t;
|
||||
|
||||
@ -52,5 +56,7 @@ int sx_radix_node_foreach(struct sx_radix_node* node,
|
||||
void (*func)(struct sx_radix_node*, void*), void* udata);
|
||||
int sx_radix_tree_foreach(struct sx_radix_tree* tree,
|
||||
void (*func)(struct sx_radix_node*, void*), void* udata);
|
||||
int sx_radix_tree_aggregate(struct sx_radix_tree* tree);
|
||||
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user