From aee7adb69848d59ec5404698a24059be0a1d495b Mon Sep 17 00:00:00 2001 From: J vanBemmel Date: Thu, 25 May 2023 11:47:09 -0500 Subject: [PATCH] Add support for Nokia SR Linux IP prefix lists / ACL filters (#91) * Add support for Nokia SR Linux prefix sets * Update tests * Update docs * Fix ACL prefix filter --- bgpq4.8 | 2 + extern.h | 3 +- main.c | 17 ++++-- printer.c | 106 +++++++++++++++++++++++++++++++++ tests/generate_outputs.sh | 2 + tests/reference/srlinux--4.txt | 6 ++ tests/reference/srlinux--6.txt | 6 ++ 7 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 tests/reference/srlinux--4.txt create mode 100644 tests/reference/srlinux--6.txt diff --git a/bgpq4.8 b/bgpq4.8 index 2c282ee..6d4a692 100644 --- a/bgpq4.8 +++ b/bgpq4.8 @@ -109,6 +109,8 @@ maximum prefix-length of accepted prefixes (default: 32 for IPv4 and extra match conditions for Juniper route-filters. .It Fl n generate config for Nokia SR OS MD-CLI (Cisco IOS by default) +.It Fl n2 +generate config for Nokia SR Linux (Cisco IOS by default) .It Fl N generate config for Nokia SR OS classic CLI (Cisco IOS by default). .It Fl p diff --git a/extern.h b/extern.h index c64e755..0b07fcf 100644 --- a/extern.h +++ b/extern.h @@ -62,7 +62,8 @@ typedef enum { V_MIKROTIK6, V_MIKROTIK7, V_NOKIA_MD, - V_ARISTA + V_ARISTA, + V_NOKIA_SRL, } bgpq_vendor_t; typedef enum { diff --git a/main.c b/main.c index 6f71b51..bdfdf28 100644 --- a/main.c +++ b/main.c @@ -199,8 +199,15 @@ main(int argc, char* argv[]) expander.sources=getenv("IRRD_SOURCES"); while ((c = getopt(argc, argv, - "3467a:AbBdDEeF:S:jJKf:l:L:m:M:NnpW:r:R:G:H:tTh:UuwXsvz")) != EOF) { + "23467a:AbBdDEeF:S:jJKf:l:L:m:M:NnpW:r:R:G:H:tTh:UuwXsvz")) != EOF) { switch (c) { + case '2': + if (expander.vendor != V_NOKIA_MD) { + sx_report(SX_FATAL, "'2' can only be used after -n\n"); + exit(1); + } + expander.vendor = V_NOKIA_SRL; + break; case '3': /* do nothing, 32-bit ASN support is assumed */ break; @@ -473,6 +480,7 @@ main(int argc, char* argv[]) case V_JUNIPER: case V_NOKIA: case V_NOKIA_MD: + case V_NOKIA_SRL: expander.aswidth = 8; break; case V_BIRD: @@ -492,6 +500,7 @@ main(int argc, char* argv[]) case V_JUNIPER: case V_NOKIA: case V_NOKIA_MD: + case V_NOKIA_SRL: expander.aswidth = 8; break; } @@ -564,7 +573,7 @@ main(int argc, char* argv[]) } if (aggregate - && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA) + && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA || expander.vendor == V_NOKIA_SRL) && expander.generation != T_PREFIXLIST) { sx_report(SX_FATAL, "Sorry, aggregation (-A) is not supported with " "ip-prefix-lists (-E) on Nokia.\n"); @@ -572,7 +581,7 @@ main(int argc, char* argv[]) } if (refine - && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA) + && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA || expander.vendor == V_NOKIA_SRL) && expander.generation != T_PREFIXLIST) { sx_report(SX_FATAL, "Sorry, more-specifics (-R) is not supported with " "ip-prefix-lists (-E) on Nokia.\n"); @@ -580,7 +589,7 @@ main(int argc, char* argv[]) } if (refineLow - && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA) + && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA || expander.vendor == V_NOKIA_SRL) && expander.generation != T_PREFIXLIST) { sx_report(SX_FATAL, "Sorry, more-specifics (-r) is not supported with " "ip-prefix-lists (-E) on Nokia.\n"); diff --git a/printer.c b/printer.c index 93fed63..d97cb71 100644 --- a/printer.c +++ b/printer.c @@ -40,6 +40,13 @@ extern int debug_expander; +#define max(a,b) \ +({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; \ +}) + static void bgpq4_print_cisco_aspath(FILE *f, struct bgpq_expander *b) { @@ -1370,6 +1377,60 @@ checkSon: } +static void +bgpq4_print_nokia_srl_prefix(struct sx_radix_node *n, void *ff) +{ + char prefix[128]; + FILE *f = (FILE*)ff; + + if (n->isGlue) + goto checkSon; + + if (!f) + f = stdout; + + sx_prefix_snprintf(n->prefix, prefix, sizeof(prefix)); + + if (!n->isAggregate) { + fprintf(f, " prefix %s mask-length-range exact { }\n", prefix); + } else { + fprintf(f, " prefix %s mask-length-range %u..%u { }\n", prefix, + max(n->aggregateLow,n->prefix->masklen), n->aggregateHi); + } + +checkSon: + if (n->son) + bgpq4_print_nokia_srl_prefix(n->son, ff); +} + +typedef struct { + FILE *f; + int seq; +} NOKIA_SRL_IPFILTER_PARAMS; + +static void +bgpq4_print_nokia_srl_ipfilter(struct sx_radix_node *n, void *ff) +{ + char prefix[128]; + NOKIA_SRL_IPFILTER_PARAMS *params = (NOKIA_SRL_IPFILTER_PARAMS*) ff; + + if (n->isGlue) + goto checkSon; + + if (!params->f) + params->f = stdout; + + sx_prefix_snprintf(n->prefix, prefix, sizeof(prefix)); + + fprintf(params->f, " entry %d {\n action { accept { } }\n match { source-ip { prefix %s } } }\n", params->seq, prefix); + params->seq += 10; + +checkSon: + if (n->son) { + bgpq4_print_nokia_srl_ipfilter(n->son, ff); + } +} + static void bgpq4_print_juniper_prefixlist(FILE *f, struct bgpq_expander *b) { @@ -1716,6 +1777,45 @@ bgpq4_print_nokia_md_ipprefixlist(FILE *f, struct bgpq_expander *b) fprintf(f,"}\n"); } +static void +bgpq4_print_nokia_srl_prefixset(FILE *f, struct bgpq_expander *b) +{ + bname = b->name ? b->name : "NN"; + + fprintf(f, "/routing-policy\ndelete prefix-set \"%s\"\n", + bname); + + fprintf(f, "prefix-set \"%s\" {\n", bname); + + if (!sx_radix_tree_empty(b->tree)) { + sx_radix_tree_foreach(b->tree, bgpq4_print_nokia_srl_prefix, f); + } + + fprintf(f,"}\n"); +} + +static void +bgpq4_print_nokia_srl_aclipfilter(FILE *f, struct bgpq_expander *b) +{ + bname = b->name ? b->name : "NN"; + + fprintf(f,"/acl \ndelete ipv%c-filter \"%s\"\n", + b->tree->family == AF_INET ? '4' : '6', bname); + + fprintf(f,"ipv%c-filter \"%s\" {\n", + b->tree->family == AF_INET ? '4' : '6', bname); + + if (!sx_radix_tree_empty(b->tree)) { + NOKIA_SRL_IPFILTER_PARAMS params = { f, 10 }; + sx_radix_tree_foreach(b->tree, bgpq4_print_nokia_srl_ipfilter, ¶ms); + } else { + fprintf(f,"# generated ipv%c-filter '%s' is empty\n", + b->tree->family == AF_INET ? '4' : '6', bname); + } + + fprintf(f,"}\n"); +} + static void bgpq4_print_k6prefix(struct sx_radix_node *n, void *ff) { @@ -1827,6 +1927,9 @@ bgpq4_print_prefixlist(FILE *f, struct bgpq_expander *b) case V_NOKIA_MD: bgpq4_print_nokia_md_ipprefixlist(f, b); break; + case V_NOKIA_SRL: + bgpq4_print_nokia_srl_prefixset(f, b); + break; case V_HUAWEI: bgpq4_print_huawei_prefixlist(f, b); break; @@ -1863,6 +1966,9 @@ bgpq4_print_eacl(FILE *f, struct bgpq_expander *b) case V_NOKIA_MD: bgpq4_print_nokia_md_prefixlist(f, b); break; + case V_NOKIA_SRL: + bgpq4_print_nokia_srl_aclipfilter(f, b); + break; default: sx_report(SX_FATAL, "unreachable point\n"); } diff --git a/tests/generate_outputs.sh b/tests/generate_outputs.sh index 7c3ef47..ed54b47 100755 --- a/tests/generate_outputs.sh +++ b/tests/generate_outputs.sh @@ -45,6 +45,7 @@ fi "${BGPQ4_PATH}" -4 -K7 "AS${TEST_ASN}" > "${OUT_DIR}/routeros7--4.txt" "${BGPQ4_PATH}" -4 -N "AS${TEST_ASN}" > "${OUT_DIR}/sros--4.txt" "${BGPQ4_PATH}" -4 -n "AS${TEST_ASN}" > "${OUT_DIR}/sros-mdcli--4.txt" +"${BGPQ4_PATH}" -4 -n2 "AS${TEST_ASN}" > "${OUT_DIR}/srlinux--4.txt" # Test the IPv6 prefix-list output formatting for each supported NOS: "${BGPQ4_PATH}" -6 -b "AS${TEST_ASN}" > "${OUT_DIR}/bird--6.txt" @@ -61,6 +62,7 @@ fi "${BGPQ4_PATH}" -6 -K7 "AS${TEST_ASN}" > "${OUT_DIR}/routeros7--6.txt" "${BGPQ4_PATH}" -6 -N "AS${TEST_ASN}" > "${OUT_DIR}/sros--6.txt" "${BGPQ4_PATH}" -6 -n "AS${TEST_ASN}" > "${OUT_DIR}/sros-mdcli--6.txt" +"${BGPQ4_PATH}" -6 -n2 "AS${TEST_ASN}" > "${OUT_DIR}/srlinux--6.txt" # Test the AS path list output formatting for each supported NOS: "${BGPQ4_PATH}" "${TEST_AS_SET}" -f "${TEST_ASN}" -b > "${OUT_DIR}/bird--asp.txt" diff --git a/tests/reference/srlinux--4.txt b/tests/reference/srlinux--4.txt new file mode 100644 index 0000000..aae5548 --- /dev/null +++ b/tests/reference/srlinux--4.txt @@ -0,0 +1,6 @@ +/routing-policy +delete prefix-set "NN" +prefix-set "NN" { + prefix 192.31.196.0/24 mask-length-range exact { } + prefix 192.175.48.0/24 mask-length-range exact { } +} diff --git a/tests/reference/srlinux--6.txt b/tests/reference/srlinux--6.txt new file mode 100644 index 0000000..02d12e8 --- /dev/null +++ b/tests/reference/srlinux--6.txt @@ -0,0 +1,6 @@ +/routing-policy +delete prefix-set "NN" +prefix-set "NN" { + prefix 2001:4:112::/48 mask-length-range exact { } + prefix 2620:4f:8000::/48 mask-length-range exact { } +}