juniper route-filter-lists (junos 16.2+).

This commit is contained in:
Alexandre Snarskii
2017-09-08 19:40:25 +03:00
parent aed955f868
commit c6c5d7d4a6
6 changed files with 68 additions and 13 deletions

View File

@@ -1,4 +1,5 @@
untagged yet (2017-07-19)
untagged yet (2017-09-08)
- initial support for Juniper route-filter-lists (JunOS 16.2+).
- too large (>124bytes) sources list was not handled correctly.
Reported by Pier Carlo Chiodi.

View File

@@ -7,7 +7,7 @@ SYNOPSIS
--------
```
bgpq3 [-h host[:port]] [-S sources] [-EP] [-f asn | -F fmt | -G asn] [-2346ABbDdJjpsX] [-a asn] [-r len] [-R len] [-m max] [-W len] OBJECTS [...] EXCEPT OBJECTS
bgpq3 [-h host[:port]] [-S sources] [-EPz] [-f asn | -F fmt | -G asn] [-2346ABbDdJjpsX] [-a asn] [-r len] [-R len] [-m max] [-W len] OBJECTS [...] EXCEPT OBJECTS
```
DESCRIPTION
@@ -149,6 +149,10 @@ Generate as-path strings of a given length maximum (0 for infinity).
Generate config for Cisco IOS XR devices (plain IOS by default).
#### -z
Generate Juniper route-filter-list (JunOS 16.2+).
#### `OBJECTS`
`OBJECTS` means networks (in prefix format), autonomous systems, as-sets and

View File

@@ -32,7 +32,7 @@
.Nm
.Op Fl h Ar host[:port]
.Op Fl S Ar sources
.Op Fl EP
.Op Fl EPz
.Oo
.Fl f Ar asn |
.Fl F Ar fmt |
@@ -120,6 +120,8 @@ disable pipelining.
generate as-path strings of no more than len items (use 0 for inifinity).
.It Fl X
generate config for Cisco IOS XR devices (plain IOS by default).
.It Fl z
generate route-filter-lists (JunOS 16.2+).
.It Ar OBJECTS
means networks (in prefix format), autonomous systems, as-sets and route-sets.
.It Ar EXCEPT OBJECTS

25
bgpq3.c
View File

@@ -137,7 +137,7 @@ main(int argc, char* argv[])
if (getenv("IRRD_SOURCES"))
expander.sources=getenv("IRRD_SOURCES");
while((c=getopt(argc,argv,"2346a:AbBdDEF:S:jJf:l:L:m:M:NW:Ppr:R:G:Th:Xs"))
while((c=getopt(argc,argv,"2346a:AbBdDEF:S:jJf:l:L:m:M:NW:Ppr:R:G:Th:Xsz"))
!=EOF) {
switch(c) {
case '2':
@@ -308,6 +308,10 @@ main(int argc, char* argv[])
case 'X': if(expander.vendor) vendor_exclusive();
expander.vendor=V_CISCO_XR;
break;
case 'z':
if(expander.generation) exclusive();
expander.generation=T_ROUTE_FILTER_LIST;
break;
default : usage(1);
};
};
@@ -368,6 +372,10 @@ main(int argc, char* argv[])
"compatible with -R/-r options\n");
exit(1);
};
if(expander.generation==T_ROUTE_FILTER_LIST && expander.vendor!=V_JUNIPER) {
sx_report(SX_FATAL, "Route-filter-lists (-z) supported for Juniper (-J)"
" output only\n");
};
if(expander.asdot && expander.vendor!=V_CISCO) {
sx_report(SX_FATAL,"asdot notation supported only for Cisco, "
@@ -381,8 +389,9 @@ main(int argc, char* argv[])
if(aggregate && expander.vendor==V_JUNIPER &&
expander.generation==T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) does not work in"
" Juniper prefix-lists\nYou can try route-filters (-E) instead"
" of prefix-lists (-P, default)\n");
" Juniper prefix-lists\nYou can try route-filters (-E) "
"or route-filter-lists (-z) instead of prefix-lists "
"(-P, default)\n");
exit(1);
};
@@ -447,11 +456,13 @@ main(int argc, char* argv[])
if(refine) {
sx_report(SX_FATAL, "Sorry, more-specific filters (-R %u) "
"is not supported for Juniper prefix-lists.\n"
"Use router-filters (-E) instead\n", refine);
"Use router-filters (-E) or route-filter-lists (-z) "
"instead\n", refine);
} else {
sx_report(SX_FATAL, "Sorry, more-specific filters (-r %u) "
"is not supported for Juniper prefix-lists.\n"
"Use route-filters (-E) instead\n", refineLow);
"Use route-filters (-E) or route-filter-lists (-z) "
"instead\n", refineLow);
};
};
@@ -568,7 +579,6 @@ main(int argc, char* argv[])
sx_radix_tree_aggregate(expander.tree);
switch(expander.generation) {
default :
case T_NONE: sx_report(SX_FATAL,"Unreachable point... call snar\n");
exit(1);
case T_ASPATH: bgpq3_print_aspath(stdout,&expander);
@@ -579,6 +589,9 @@ main(int argc, char* argv[])
break;
case T_EACL: bgpq3_print_eacl(stdout,&expander);
break;
case T_ROUTE_FILTER_LIST:
bgpq3_print_route_filter_list(stdout, &expander);
break;
};
return 0;

View File

@@ -26,7 +26,8 @@ typedef enum {
T_ASPATH,
T_OASPATH,
T_PREFIXLIST,
T_EACL
T_EACL,
T_ROUTE_FILTER_LIST
} bgpq_gen_t;
struct bgpq_expander;
@@ -82,6 +83,7 @@ int bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* b);
int bgpq3_print_eacl(FILE* f, struct bgpq_expander* b);
int bgpq3_print_aspath(FILE* f, struct bgpq_expander* b);
int bgpq3_print_oaspath(FILE* f, struct bgpq_expander* b);
int bgpq3_print_route_filter_list(FILE* f, struct bgpq_expander* b);
#ifndef HAVE_STRLCPY
size_t strlcpy(char* dst, const char* src, size_t size);

View File

@@ -639,6 +639,8 @@ bgpq3_print_openbgpd_aspath(FILE* f, struct bgpq_expander* b)
return 0;
};
static int jrfilter_prefixed=1;
void
bgpq3_print_jrfilter(struct sx_radix_node* n, void* ff)
{
@@ -648,13 +650,17 @@ bgpq3_print_jrfilter(struct sx_radix_node* n, void* ff)
if(!f) f=stdout;
sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix));
if(!n->isAggregate) {
fprintf(f," route-filter %s exact;\n", prefix);
fprintf(f," %s%s exact;\n",
jrfilter_prefixed ? "route-filter " : "", prefix);
} else {
if(n->aggregateLow>n->prefix.masklen) {
fprintf(f," route-filter %s prefix-length-range /%u-/%u;\n",
fprintf(f," %s%s prefix-length-range /%u-/%u;\n",
jrfilter_prefixed ? "route-filter " : "",
prefix,n->aggregateLow,n->aggregateHi);
} else {
fprintf(f," route-filter %s upto /%u;\n", prefix,n->aggregateHi);
fprintf(f," %s%s upto /%u;\n",
jrfilter_prefixed ? "route-filter " : "",
prefix,n->aggregateHi);
};
};
checkSon:
@@ -852,6 +858,7 @@ bgpq3_print_juniper_routefilter(FILE* f, struct bgpq_expander* b)
fprintf(f," %s;\n",b->match);
};
if(!sx_radix_tree_empty(b->tree)) {
jrfilter_prefixed=1;
sx_radix_tree_foreach(b->tree,bgpq3_print_jrfilter,f);
} else {
fprintf(f," route-filter %s/0 orlonger reject;\n",
@@ -1057,3 +1064,29 @@ bgpq3_print_eacl(FILE* f, struct bgpq_expander* b)
};
return 0;
};
int
bgpq3_print_juniper_route_filter_list(FILE* f, struct bgpq_expander* b)
{
fprintf(f, "policy-options {\nreplace:\n route-filter-list %s {\n",
b->name?b->name:"NN");
if (sx_radix_tree_empty(b->tree)) {
fprintf(f, " route-filter %s/0 orlonger reject;\n",
b->tree->family == AF_INET ? "0.0.0.0" : "::");
} else {
jrfilter_prefixed=0;
sx_radix_tree_foreach(b->tree,bgpq3_print_jrfilter,f);
};
fprintf(f, " }\n}\n");
return 0;
};
int
bgpq3_print_route_filter_list(FILE* f, struct bgpq_expander* b)
{
switch(b->vendor) {
case V_JUNIPER: return bgpq3_print_juniper_route_filter_list(f,b);
default: sx_report(SX_FATAL, "unreachable point\n");
};
return 0;
};