mirror of
https://github.com/bgp/bgpq4
synced 2025-02-28 08:53:11 +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):
|
0.1.2 (2008-05-19):
|
||||||
- final support for asn32, now with correct syntax for Juniper.
|
- final support for asn32, now with correct syntax for Juniper.
|
||||||
|
|||||||
22
bgpq3.c
22
bgpq3.c
@@ -17,15 +17,18 @@
|
|||||||
#include "sx_report.h"
|
#include "sx_report.h"
|
||||||
|
|
||||||
extern int debug_expander;
|
extern int debug_expander;
|
||||||
|
extern int debug_aggregation;
|
||||||
extern int pipelining;
|
extern int pipelining;
|
||||||
|
|
||||||
int
|
int
|
||||||
usage(int ecode)
|
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");
|
" <OBJECTS>...\n");
|
||||||
printf(" -3 : assume that your device is asn32-safe\n");
|
printf(" -3 : assume that your device is asn32-safe\n");
|
||||||
printf(" -6 : generate IPv6 prefix-lists (IPv4 by default)\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(" -d : generate some debugging output\n");
|
||||||
printf(" -f number : generate input as-path access-list\n");
|
printf(" -f number : generate input as-path access-list\n");
|
||||||
printf(" -G number : generate output 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;
|
int c;
|
||||||
struct bgpq_expander expander;
|
struct bgpq_expander expander;
|
||||||
int af=AF_INET;
|
int af=AF_INET;
|
||||||
int widthSet=0;
|
int widthSet=0, aggregate=0;
|
||||||
|
|
||||||
bgpq_expander_init(&expander,af);
|
bgpq_expander_init(&expander,af);
|
||||||
expander.sources=getenv("IRRD_SOURCES");
|
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) {
|
switch(c) {
|
||||||
case '3':
|
case '3':
|
||||||
expander.asn32=1;
|
expander.asn32=1;
|
||||||
@@ -104,6 +107,10 @@ main(int argc, char* argv[])
|
|||||||
expander.family=AF_INET6;
|
expander.family=AF_INET6;
|
||||||
expander.tree->family=AF_INET6;
|
expander.tree->family=AF_INET6;
|
||||||
break;
|
break;
|
||||||
|
case 'A':
|
||||||
|
if(aggregate) debug_aggregation++;
|
||||||
|
aggregate=1;
|
||||||
|
break;
|
||||||
case 'd': debug_expander++;
|
case 'd': debug_expander++;
|
||||||
break;
|
break;
|
||||||
case 'J': expander.vendor=V_JUNIPER;
|
case 'J': expander.vendor=V_JUNIPER;
|
||||||
@@ -172,6 +179,12 @@ main(int argc, char* argv[])
|
|||||||
expander.asnumber=23456;
|
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);
|
if(!argv[0]) usage(1);
|
||||||
|
|
||||||
while(argv[0]) {
|
while(argv[0]) {
|
||||||
@@ -195,6 +208,9 @@ main(int argc, char* argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(aggregate)
|
||||||
|
sx_radix_tree_aggregate(expander.tree);
|
||||||
|
|
||||||
switch(expander.generation) {
|
switch(expander.generation) {
|
||||||
case T_NONE: sx_report(SX_FATAL,"Unreachable point... call snar\n");
|
case T_NONE: sx_report(SX_FATAL,"Unreachable point... call snar\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@@ -202,11 +202,26 @@ bgpq3_print_cprefix(struct sx_radix_node* n, void* ff)
|
|||||||
{
|
{
|
||||||
char prefix[128];
|
char prefix[128];
|
||||||
FILE* f=(FILE*)ff;
|
FILE* f=(FILE*)ff;
|
||||||
if(n->isGlue) return;
|
|
||||||
if(!f) f=stdout;
|
if(!f) f=stdout;
|
||||||
|
if(n->isGlue) goto checkSon;
|
||||||
sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix));
|
sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix));
|
||||||
fprintf(f,"%s prefix-list %s permit %s\n",
|
if(n->isAggregate) {
|
||||||
(n->prefix.family==AF_INET)?"ip":"ipv6",bname?bname:"NN",prefix);
|
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
|
int
|
||||||
|
|||||||
@@ -506,6 +506,7 @@ bgpq_expand(struct bgpq_expander* b)
|
|||||||
snprintf(sources,sizeof(sources),"!s%s\n", b->sources);
|
snprintf(sources,sizeof(sources),"!s%s\n", b->sources);
|
||||||
fseek(f,0,SEEK_END);
|
fseek(f,0,SEEK_END);
|
||||||
fwrite(sources,strlen(sources),1,f);
|
fwrite(sources,strlen(sources),1,f);
|
||||||
|
fgets(sources,sizeof(sources),f);
|
||||||
};
|
};
|
||||||
|
|
||||||
if(b->identify) {
|
if(b->identify) {
|
||||||
@@ -513,6 +514,7 @@ bgpq_expand(struct bgpq_expander* b)
|
|||||||
snprintf(ident,sizeof(ident),"!n" PACKAGE_STRING "\n");
|
snprintf(ident,sizeof(ident),"!n" PACKAGE_STRING "\n");
|
||||||
fseek(f,0,SEEK_END);
|
fseek(f,0,SEEK_END);
|
||||||
fwrite(ident,strlen(ident),1,f);
|
fwrite(ident,strlen(ident),1,f);
|
||||||
|
fgets(ident,sizeof(ident),f);
|
||||||
};
|
};
|
||||||
|
|
||||||
for(mc=b->macroses;mc;mc=mc->next) {
|
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_prefix.h"
|
||||||
#include "sx_report.h"
|
#include "sx_report.h"
|
||||||
|
|
||||||
|
int debug_aggregation=0;
|
||||||
|
|
||||||
struct sx_prefix*
|
struct sx_prefix*
|
||||||
sx_prefix_alloc(struct sx_prefix* p)
|
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);
|
sx_radix_node_foreach(tree->head,func,udata);
|
||||||
return 0;
|
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;
|
} sx_prefix_t;
|
||||||
|
|
||||||
typedef struct sx_radix_node {
|
typedef struct sx_radix_node {
|
||||||
struct sx_radix_node* parent, *l, *r;
|
struct sx_radix_node* parent, *l, *r, *son;
|
||||||
void* payload;
|
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;
|
struct sx_prefix prefix;
|
||||||
} sx_radix_node_t;
|
} 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);
|
void (*func)(struct sx_radix_node*, void*), void* udata);
|
||||||
int sx_radix_tree_foreach(struct sx_radix_tree* tree,
|
int sx_radix_tree_foreach(struct sx_radix_tree* tree,
|
||||||
void (*func)(struct sx_radix_node*, void*), void* udata);
|
void (*func)(struct sx_radix_node*, void*), void* udata);
|
||||||
|
int sx_radix_tree_aggregate(struct sx_radix_tree* tree);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user