From 5ca55d741b2fe99cfa11b571485be9162f853352 Mon Sep 17 00:00:00 2001 From: Mike Nowak Date: Tue, 10 Oct 2017 17:04:44 +0900 Subject: [PATCH] Support for vyatta --- README.md | 5 ++ bgpq3.8 | 2 + bgpq3.c | 14 ++++- bgpq3.h | 3 +- bgpq3_printer.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 85f3f4d..cdf60cd 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,11 @@ Use specified sources only (recommended: RADB,RIPE,APNIC). Disable pipelining. (not recommended) +#### -V + +Generate config for Vyatta/VyOS/EdgeOS (default: Cisco) + + #### -W `length` Generate as-path strings of a given length maximum (0 for infinity). diff --git a/bgpq3.8 b/bgpq3.8 index 08bad2f..762b3d7 100644 --- a/bgpq3.8 +++ b/bgpq3.8 @@ -116,6 +116,8 @@ generate sequence numbers in IOS-style prefix-lists. use specified sources only (recommended: RADB,RIPE,APNIC). .It Fl T disable pipelining. +.It Fl N +generate config for Vyatta/Vyos/EdgeOS (Cisco IOS by default). .It Fl W Ar len generate as-path strings of no more than len items (use 0 for inifinity). .It Fl X diff --git a/bgpq3.c b/bgpq3.c index 540d5fa..61aa4fc 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -65,6 +65,7 @@ usage(int ecode) " RADB,RIPE,APNIC)\n"); printf(" -s : generate sequence numbers in prefix-lists (IOS only)\n"); printf(" -T : disable pipelining (experimental, faster mode)\n"); + printf(" -V : generate config for Vyatta/VyOS/EdgeOS (Cisco IOS by default)\n"); printf(" -W len : specify max-entries on as-path line (use 0 for " "infinity)\n"); printf(" -X : generate config for IOS XR (Cisco IOS by default)\n"); @@ -85,7 +86,7 @@ void vendor_exclusive() { fprintf(stderr, "-b (BIRD), -B (OpenBGPD), -F (formatted), -J (JunOS), " - "-j (JSON), -N (NOKIA SR OS) and -X (IOS XR) options are mutually exclusive\n"); + "-j (JSON), -N (NOKIA SR OS), -X (IOS XR) -V (Vyatta) options are mutually exclusive\n"); exit(1); }; @@ -137,7 +138,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:Xsz")) + while((c=getopt(argc,argv,"2346a:AbBdDEF:S:jJf:l:L:m:M:NVW:Ppr:R:G:Th:Xsz")) !=EOF) { switch(c) { case '2': @@ -298,6 +299,9 @@ main(int argc, char* argv[]) break; case 'S': expander.sources=optarg; break; + case 'V': if(expander.vendor) vendor_exclusive(); + expander.vendor=V_VYATTA; + break; case 'W': expander.aswidth=atoi(optarg); if(expander.aswidth<0) { sx_report(SX_FATAL,"Invalid as-width: %s\n", optarg); @@ -407,6 +411,12 @@ main(int argc, char* argv[]) exit(1); }; + if(expander.vendor==V_VYATTA && expander.generation!=T_PREFIXLIST && + expander.generation!=T_ASPATH && expander.generation!=T_OASPATH) { + sx_report(SX_FATAL, "Sorry, only prefix-sets and as-paths " + "supported for Vyatta output\n"); + }; + if(aggregate && expander.generationvendor==V_NOKIA) { return bgpq3_print_nokia_aspath(f,b); + } else if(b->vendor==V_VYATTA) { + return bgpq3_print_vyatta_aspath(f,b); } else { sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor); }; @@ -448,6 +453,8 @@ bgpq3_print_oaspath(FILE* f, struct bgpq_expander* b) return bgpq3_print_openbgpd_oaspath(f,b); } else if(b->vendor==V_NOKIA) { return bgpq3_print_nokia_oaspath(f,b); + } else if(b->vendor==V_VYATTA) { + return bgpq3_print_vyatta_oaspath(f,b); } else { sx_report(SX_FATAL,"Unknown vendor %i\n", b->vendor); }; @@ -1002,6 +1009,141 @@ bgpq3_print_nokia_prefixlist(FILE* f, struct bgpq_expander* b) return 0; }; +int +bgpq3_print_vyatta_aspath(FILE* f, struct bgpq_expander* b) +{ + int nc=0, lineNo=1, i, j, k; + fprintf(f,"delete policy as-path-list %s\n", b->name?b->name:"NN"); + + if(b->asn32s[b->asnumber/65536] && + b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& + (0x80>>(b->asnumber%8))) { + fprintf(f,"set policy as-path-list %s rule %u action permit\n", + b->name?b->name:"NN",lineNo); + fprintf(f,"set policy as-path-list %s rule %u regex '^%u(_%u)*$'\n", + b->name?b->name:"NN",lineNo,b->asnumber,b->asnumber); + lineNo++; + }; + for(k=0;k<65536;k++) { + if(!b->asn32s[k]) continue; + for(i=0;i<8192;i++) { + for(j=0;j<8;j++) { + if(b->asn32s[k][i]&(0x80>>j)) { + if(k*65536+i*8+j==b->asnumber) continue; + if(!nc) { + fprintf(f,"set policy as-path-list %s rule %u action permit\n", + b->name?b->name:"NN",lineNo); + fprintf(f,"set policy as-path-list %s rule %u regex '^%u(_[0-9]+)*_(%u", + b->name?b->name:"NN",lineNo,b->asnumber,k*65536+i*8+j); + } else { + fprintf(f,"|%u",k*65536+i*8+j); + }; + nc++; + if(nc==b->aswidth) { + fprintf(f,")$'\n"); + nc=0; + lineNo++; + }; + }; + }; + }; + }; + if(nc) fprintf(f,")$'\n"); + return 0; +}; + +int +bgpq3_print_vyatta_oaspath(FILE* f, struct bgpq_expander* b) +{ + int nc=0, lineNo=1, i, j, k; + fprintf(f,"delete policy as-path-list %s\n", b->name?b->name:"NN"); + + if(b->asn32s[b->asnumber/65536] && + b->asn32s[b->asnumber/65535][(b->asnumber%65536)/8]& + (0x80>>(b->asnumber%8))) { + fprintf(f,"set policy as-path-list %s rule %u action permit\n", + b->name?b->name:"NN",lineNo); + fprintf(f,"set policy as-path-list %s rule %u regex '^(_%u)*$'\n", + b->name?b->name:"NN",lineNo,b->asnumber); + lineNo++; + }; + for(k=0;k<65536;k++) { + if(!b->asn32s[k]) continue; + for(i=0;i<8192;i++) { + for(j=0;j<8;j++) { + if(b->asn32s[k][i]&(0x80>>j)) { + if(k*65536+i*8+j==b->asnumber) continue; + if(!nc) { + fprintf(f,"set policy as-path-list %s rule %u action permit\n", + b->name?b->name:"NN",lineNo); + fprintf(f,"set policy as-path-list %s rule %u regex '^(_[0-9]+)*_(%u", + b->name?b->name:"NN",lineNo,k*65536+i*8+j); + } else { + fprintf(f,"|%u",k*65536+i*8+j); + }; + nc++; + if(nc==b->aswidth) { + fprintf(f,")$'\n"); + nc=0; + lineNo++; + }; + }; + }; + }; + }; + if(nc) fprintf(f,")$'\n"); + return 0; +}; + +void +bgpq3_print_vprefix(struct sx_radix_node* n, void* ff) +{ + char prefix[128]; + FILE* f=(FILE*)ff; + if(!f) f=stdout; + if(n->isGlue) goto checkSon; + sx_prefix_snprintf(&n->prefix,prefix,sizeof(prefix)); + seq++; + if(n->isAggregate) { + if(n->aggregateLow>n->prefix.masklen) { + fprintf(f,"set policy prefix-list%s %s rule %i action permit\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq); + fprintf(f,"set policy prefix-list%s %s rule %i prefix %s\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq,prefix); + fprintf(f,"set policy prefix-list%s %s rule %i ge %u\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq,n->aggregateLow); + fprintf(f,"set policy prefix-list%s %s rule %i le %u\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq,n->aggregateHi); + } else { + fprintf(f,"set policy prefix-list%s %s rule %i action permit\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq); + fprintf(f,"set policy prefix-list%s %s rule %i prefix %s\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq,prefix); + fprintf(f,"set policy prefix-list%s %s rule %i le %u\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq,n->aggregateHi); + }; + } else { + fprintf(f,"set policy prefix-list%s %s rule %i action permit\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq); + fprintf(f,"set policy prefix-list%s %s rule %i prefix %s\n", + n->prefix.family==AF_INET6?"6":"",bname?bname:"NN",seq,prefix); + }; +checkSon: + if(n->son) + bgpq3_print_vprefix(n->son,ff); +}; + +int +bgpq3_print_vyatta_prefixlist(FILE* f, struct bgpq_expander* b) +{ + bname=b->name ? b->name : "NN"; + seq=b->sequence; + fprintf(f,"delete policy prefix-list%s %s\n", + (b->family==AF_INET6)?"6":"",bname); + sx_radix_tree_foreach(b->tree,bgpq3_print_vprefix,f); + return 0; +}; + int bgpq3_print_cisco_eacl(FILE* f, struct bgpq_expander* b) { @@ -1045,6 +1187,7 @@ bgpq3_print_prefixlist(FILE* f, struct bgpq_expander* b) case V_OPENBGPD: return bgpq3_print_openbgpd_prefixlist(f,b); case V_FORMAT: return bgpq3_print_format_prefixlist(f,b); case V_NOKIA: return bgpq3_print_nokia_prefixlist(f,b); + case V_VYATTA: return bgpq3_print_vyatta_prefixlist(f,b); }; return 0; }; @@ -1061,6 +1204,7 @@ bgpq3_print_eacl(FILE* f, struct bgpq_expander* b) case V_OPENBGPD: return bgpq3_print_openbgpd_prefixlist(f,b); case V_FORMAT: sx_report(SX_FATAL, "unreachable point\n"); case V_NOKIA: return bgpq3_print_nokia_ipprefixlist(f,b); + case V_VYATTA: sx_report(SX_FATAL, "unreachable point\n"); }; return 0; };