Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature to generate IP filters with statistics to count traffic to/from given AS, based on prefix list matches #98

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ It's options are as follows:

> generate output in BIRD format (default: Cisco).

**-c**

> generate IP prefix ingress/egress filters for counting traffic, based on dst/src IP matches to a per-AS prefix list (Nokia MD-CLI only)

**-d**

> enable some debugging output.
Expand Down
4 changes: 3 additions & 1 deletion extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ typedef enum {
T_ASSET,
T_PREFIXLIST,
T_EACL,
T_ROUTE_FILTER_LIST
T_ROUTE_FILTER_LIST,
T_TRAFFIC_COUNTING_FILTER,
} bgpq_gen_t;

struct bgpq_expander;
Expand Down Expand Up @@ -143,6 +144,7 @@ void bgpq4_print_asset(FILE *f, struct bgpq_expander *b);
void bgpq4_print_oaspath(FILE *f, struct bgpq_expander *b);
void bgpq4_print_aslist(FILE *f, struct bgpq_expander *b);
void bgpq4_print_route_filter_list(FILE *f, struct bgpq_expander *b);
void bgpq4_print_counting_filter(FILE *f, struct bgpq_expander *b);

void sx_radix_node_freeall(struct sx_radix_node *n);
void sx_radix_tree_freeall(struct sx_radix_tree *t);
Expand Down
18 changes: 16 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ usage(int ecode)
printf(" -t : generate as-sets for OpenBGPD (OpenBGPD 6.4+), BIRD "
"and JSON formats\n");
printf(" -z : generate route-filter-list (Junos only)\n");
printf(" -c : generate counting IP filters for ingress/egress (Nokia only)\n");
printf(" -W len : specify max-entries on as-path/as-list line (use 0 for "
"infinity)\n");

Expand Down Expand Up @@ -199,7 +200,7 @@ main(int argc, char* argv[])
expander.sources=getenv("IRRD_SOURCES");

while ((c = getopt(argc, argv,
"23467a:AbBdDEeF:S:jJKf:l:L:m:M:NnpW:r:R:G:H:tTh:UuwXsvz")) != EOF) {
"23467a:AbBcdDEeF:S:jJKf:l:L:m:M:NnpW:r:R:G:H:tTh:UuwXsvz")) != EOF) {
switch (c) {
case '2':
if (expander.vendor != V_NOKIA_MD) {
Expand Down Expand Up @@ -255,6 +256,11 @@ main(int argc, char* argv[])
vendor_exclusive();
expander.vendor = V_OPENBGPD;
break;
case 'c':
if (expander.generation)
exclusive();
expander.generation = T_TRAFFIC_COUNTING_FILTER;
break;
case 'd':
debug_expander++;
break;
Expand Down Expand Up @@ -310,7 +316,7 @@ main(int argc, char* argv[])
break;
case 'j':
if (expander.vendor)
vendor_exclusive();
vendor_exclusive();
expander.vendor = V_JSON;
break;
case 'K':
Expand Down Expand Up @@ -556,6 +562,11 @@ main(int argc, char* argv[])
sx_report(SX_FATAL, "Route-filter-lists (-z) supported for Juniper (-J)"
" output only\n");

if (expander.generation == T_TRAFFIC_COUNTING_FILTER
&& expander.vendor != V_NOKIA_MD)
sx_report(SX_FATAL, "Packet counting IP ingress/egress filters based on "
"prefix lists (-c) supported for Nokia MD (-n) output only\n");

if (expander.generation == T_ASSET
&& expander.vendor != V_JSON
&& expander.vendor != V_OPENBGPD
Expand Down Expand Up @@ -799,6 +810,9 @@ main(int argc, char* argv[])
case T_ROUTE_FILTER_LIST:
bgpq4_print_route_filter_list(stdout, &expander);
break;
case T_TRAFFIC_COUNTING_FILTER:
bgpq4_print_counting_filter(stdout, &expander);
break;
}

expander_freeall(&expander);
Expand Down
59 changes: 58 additions & 1 deletion printer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,6 @@ bgpq4_print_nokia_md_prefix(struct sx_radix_node *n, void *ff)
checkSon:
if (n->son)
bgpq4_print_nokia_md_prefix(n->son, ff);

}

static void
Expand Down Expand Up @@ -1760,6 +1759,45 @@ bgpq4_print_nokia_md_prefixlist(FILE *f, struct bgpq_expander *b)
fprintf(f,"}\n");
}

static void
bgpq4_print_nokia_md_counting_filter(FILE *f, struct bgpq_expander *b)
{
struct asn_entry *asne;
char namebuf[32];
char asbuf[16];

strncpy( namebuf, b->name ? b->name : "NN", sizeof(namebuf) );
namebuf[ sizeof(namebuf) - 1 ] = 0;

// Generate prefix list for all prefixes in each AS
RB_FOREACH(asne, asn_tree, &b->asnlist) {

uint32_t entry = max( asne->asn % 2097152, (uint32_t)1); // entry based on AS, max 2097151

sprintf(asbuf, "AS%u", entry);
b->name = asbuf;
bgpq4_print_nokia_md_prefixlist(f,b);

// Enable auto-id for filters
fprintf(f,"/configure filter md-auto-id { filter-id-range { start 1 end 65535 } }\n");

// Add an entry to match the prefix list to the named IP filters for ingress/egress based on dst/src IP
for (int i=0; i<2; ++i) {
// Do not delete, to allow for multiple filter entries for different AS
// fprintf(f,"/configure filter delete %s-filter \"%s-%s\"\n",
// b->tree->family == AF_INET ? "ip" : "ipv6", namebuf, i==0 ? "in" : "out");
fprintf(f,"/configure filter %s-filter \"%s-%s\" {\n",
b->tree->family == AF_INET ? "ip" : "ipv6", namebuf, i==0 ? "in" : "out");
fprintf(f,"default-action accept\n");
// Note: could add a port number or list of ports to match (say) only web traffic, DNS, etc.
fprintf(f,"entry %u { match { %s-ip { ip-prefix-list \"%s\" } }\naction accept }\n",
entry, i==0 ? "src" : "dst", asbuf );

fprintf(f,"}\n");
}
}
}

static void
bgpq4_print_nokia_md_ipprefixlist(FILE *f, struct bgpq_expander *b)
{
Expand Down Expand Up @@ -2002,3 +2040,22 @@ bgpq4_print_route_filter_list(FILE *f, struct bgpq_expander *b)
sx_report(SX_FATAL, "unreachable point\n");
}
}

/*
* Creates IP ingress/egress filters each with an entry to match all prefixes
* for the given AS. This can be used to collect fine grained statistics about
* peering traffic ( i.e. how many packets/bytes are sent to/received from a given AS)
*
* Entries for different AS are not cleared, to allow multiple runs for different AS numbers
*/
void
bgpq4_print_counting_filter(FILE *f, struct bgpq_expander *b)
{
switch(b->vendor) {
case V_NOKIA_MD:
bgpq4_print_nokia_md_counting_filter(f, b);
break;
default:
sx_report(SX_FATAL, "unreachable point\n");
}
}