Hello, BIRD developers! Currently there is no way in filter rules to match routes by interface name and interface index.
However string comparison (=,!=,>,<,... operations), and pattern matching (using ~ operator) already implemented in filters, so expressions like: if "eth0" ~ "eth*" || "eth1" = "eth1" then print "This pattern matches!"; already works. Only one thing that is really needed is exposing attribute with name to filter which references route outgoing interface name and index. Of course all of these variables must be readonly. Interface indexes are taken from kernel (at least on Linux, and FreeBSD) and represents interface number in system. Matching to indexes is not such reliable as matching with interface names, as indexes might change on interface addition/removal. Currently only sink (blackhole, unreachable and prohibit) routes in BIRD have no interface associated. Return an empty string and index equal to zero (no real index in kernel) for such routes. -- SP5474-RIPE Sergey Popovich
diff -purN a/doc/bird.sgml b/doc/bird.sgml --- a/doc/bird.sgml 2013-09-25 12:35:37.805081155 +0300 +++ b/doc/bird.sgml 2013-09-25 12:56:20.725342862 +0300 @@ -1238,6 +1238,21 @@ undefined value is regarded as empty cli only to <cf/RTD_BLACKHOLE/, <cf/RTD_UNREACHABLE/ or <cf/RTD_PROHIBIT/. + <tag><m/string/ ifname</tag> + Name of the outgoing interface. Standard string comparison operations + (e.g. <cf/=, !=, <, >, <=, >=/) also applicable to this attribute. + Additionaly matching <cf/˜/ operator could be used to match value + against shell pattern like in <cf/interface/ directive. Sink routes + (like blackhole, unreachable or prohibit) has no interface associated + with it, so <cf/ifname/ returns an empty string for such routes. Read-only. + + <tag><m/int/ ifindex</tag> + Index of the outgoing interface. System wide index of the interface. + May be used for interface matching, however indexes might change on + interface creation/removal. Same notes about sink routes as described + for <cf/ifname/ also applicable to this attribute and <cf/ifindex/ returns + zero for such routes. Read-only. + <tag><m/int/ igp_metric</tag> The optional attribute that can be used to specify a distance to the network for routes that do not have a native protocol diff -purN a/filter/config.Y b/filter/config.Y --- a/filter/config.Y 2013-09-25 12:35:37.805081155 +0300 +++ b/filter/config.Y 2013-09-25 12:34:55.975324066 +0300 @@ -259,7 +259,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNS SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, IF, THEN, ELSE, CASE, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, - FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, PREFERENCE, + FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX, + PREFERENCE, LEN, DEFINED, ADD, DELETE, CONTAINS, RESET, @@ -687,6 +688,8 @@ static_attr: | SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope); $$->a1.i = 1; } | CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = OFFSETOF(struct rta, cast); } | DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = OFFSETOF(struct rta, dest); $$->a1.i = 1; } + | IFNAME { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = OFFSETOF(struct iface, name); } + | IFINDEX { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = OFFSETOF(struct iface, index); } ; term: diff -purN a/filter/filter.c b/filter/filter.c --- a/filter/filter.c 2013-09-25 12:35:37.805081155 +0300 +++ b/filter/filter.c 2013-09-25 12:47:48.703794821 +0300 @@ -915,14 +915,24 @@ interpret(struct f_inst *what) res.type = f_inst_aux_f_type(what->aux); switch(res.type) { + case T_INT: + if (what->a2.i == OFFSETOF(struct iface, index)) + res.val.i = rta->iface ? rta->iface->index : 0; + else + res.val.i = 0; + break; case T_IP: res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i); break; case T_ENUM: res.val.i = * ((char *) rta + what->a2.i); break; - case T_STRING: /* Warning: this is a special case for proto attribute */ - res.val.s = rta->proto->name; + case T_STRING: + if (what->a2.i == OFFSETOF(struct iface, name)) + res.val.s = rta->iface ? rta->iface->name : ""; + else + /* Warning: this is a special case for proto attribute */ + res.val.s = rta->proto->name; break; case T_PREFIX: /* Warning: this works only for prefix of network */ {