0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Filter: Add route attribute gw_mpls_stack

Add route attribute gw_mpls_stack to make MPLS stack of route nexthop
accessible from filters. Its type is T_CLIST, which is really not correct
(as it is a list, while T_CLIST is a set). Therefore, we keep this
attribute *undocumented* and it will be *changed* without further notice.

Based on a patch from Trisha Biswas <tbiswas@fastly.com>, thanks!
This commit is contained in:
Ondrej Zajicek 2024-03-05 16:38:24 +01:00
parent 26dd61ee7f
commit 114be2af28
5 changed files with 61 additions and 2 deletions

View File

@ -362,7 +362,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
IF, THEN, ELSE, CASE, IF, THEN, ELSE, CASE,
FOR, DO, FOR, DO,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
FROM, GW, NET, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, ONLINK, FROM, GW, NET, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, GW_MPLS_STACK, ONLINK,
PREFERENCE, PREFERENCE,
ROA_CHECK, ROA_CHECK,
DEFINED, DEFINED,
@ -879,6 +879,7 @@ static_attr:
| WEIGHT { $$ = f_new_static_attr(T_INT, SA_WEIGHT, 0); } | WEIGHT { $$ = f_new_static_attr(T_INT, SA_WEIGHT, 0); }
| PREFERENCE { $$ = f_new_static_attr(T_INT, SA_PREF, 0); } | PREFERENCE { $$ = f_new_static_attr(T_INT, SA_PREF, 0); }
| GW_MPLS { $$ = f_new_static_attr(T_INT, SA_GW_MPLS, 0); } | GW_MPLS { $$ = f_new_static_attr(T_INT, SA_GW_MPLS, 0); }
| GW_MPLS_STACK { $$ = f_new_static_attr(T_CLIST, SA_GW_MPLS_STACK, 0); }
| ONLINK { $$ = f_new_static_attr(T_BOOL, SA_ONLINK, 0); } | ONLINK { $$ = f_new_static_attr(T_BOOL, SA_ONLINK, 0); }
; ;

View File

@ -120,6 +120,7 @@ enum f_sa_code {
SA_WEIGHT, SA_WEIGHT,
SA_PREF, SA_PREF,
SA_GW_MPLS, SA_GW_MPLS,
SA_GW_MPLS_STACK,
SA_ONLINK, SA_ONLINK,
} PACKED; } PACKED;

View File

@ -692,6 +692,16 @@
case SA_WEIGHT: RESULT(sa.f_type, i, rta->nh.weight + 1); break; case SA_WEIGHT: RESULT(sa.f_type, i, rta->nh.weight + 1); break;
case SA_PREF: RESULT(sa.f_type, i, rta->pref); break; case SA_PREF: RESULT(sa.f_type, i, rta->pref); break;
case SA_GW_MPLS: RESULT(sa.f_type, i, rta->nh.labels ? rta->nh.label[0] : MPLS_NULL); break; case SA_GW_MPLS: RESULT(sa.f_type, i, rta->nh.labels ? rta->nh.label[0] : MPLS_NULL); break;
case SA_GW_MPLS_STACK:
{
uint len = rta->nh.labels * sizeof(u32);
struct adata *list = falloc(sizeof(struct adata) + len);
list->length = len;
memcpy(list->data, rta->nh.label, len);
RESULT(sa.f_type, ad, list);
break;
}
case SA_ONLINK: RESULT(sa.f_type, i, rta->nh.flags & RNF_ONLINK ? 1 : 0); break; case SA_ONLINK: RESULT(sa.f_type, i, rta->nh.flags & RNF_ONLINK ? 1 : 0); break;
default: default:
@ -779,6 +789,36 @@
} }
else else
rta->nh.labels = 0; rta->nh.labels = 0;
rta->nh.labels_orig = rta->hostentry ? rta->nh.labels : 0;
}
break;
case SA_GW_MPLS_STACK:
{
int len = int_set_get_size(v1.val.ad);
u32 *l = int_set_get_data(v1.val.ad);
if (len > MPLS_MAX_LABEL_STACK)
runtime("Too many MPLS labels in stack (%d)", len);
int i;
for (i = 0; i < len; i++)
{
u32 label = l[i];
if (label >= 0x100000)
runtime("Invalid MPLS label (%u)", label);
/* Ignore rest of label stack if implicit-NULL label (3) is set */
if (label == MPLS_NULL)
break;
rta->nh.label[i] = label;
}
rta->nh.labels = i;
rta->nh.labels_orig = rta->hostentry ? i : 0;
} }
break; break;
@ -1262,6 +1302,14 @@
RESULT(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, v2.val.i) ]]); RESULT(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, v2.val.i) ]]);
} }
/* Hack for gw_mpls_list */
INST(FI_CLIST_ADD_INT, 2, 1) {
ARG(1, T_CLIST);
ARG(2, T_INT);
METHOD_CONSTRUCTOR("add");
RESULT(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, v2.val.i) ]]);
}
INST(FI_CLIST_ADD_IP, 2, 1) { INST(FI_CLIST_ADD_IP, 2, 1) {
ARG(1, T_CLIST); ARG(1, T_CLIST);
ARG(2, T_IP); ARG(2, T_IP);
@ -1344,6 +1392,14 @@
RESULT(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, v2.val.i) ]]); RESULT(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, v2.val.i) ]]);
} }
/* Hack for gw_mpls_list */
INST(FI_CLIST_DELETE_INT, 2, 1) {
ARG(1, T_CLIST);
ARG(2, T_INT);
METHOD_CONSTRUCTOR("delete");
RESULT(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, v2.val.i) ]]);
}
INST(FI_CLIST_DELETE_IP, 2, 1) { INST(FI_CLIST_DELETE_IP, 2, 1) {
ARG(1, T_CLIST); ARG(1, T_CLIST);
ARG(2, T_IP); ARG(2, T_IP);

View File

@ -392,6 +392,7 @@ static inline ip6_addr ip6_ntoh(ip6_addr a)
#define MPLS_MAX_LABEL 0x100000 #define MPLS_MAX_LABEL 0x100000
#define MPLS_MAX_LABEL_STACK 8 #define MPLS_MAX_LABEL_STACK 8
#define MPLS_MAX_LABEL_STRING MPLS_MAX_LABEL_STACK*12 + 5
typedef struct mpls_label_stack { typedef struct mpls_label_stack {
uint len; uint len;
u32 stack[MPLS_MAX_LABEL_STACK]; u32 stack[MPLS_MAX_LABEL_STACK];

View File

@ -72,7 +72,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
if (a->dest == RTD_UNICAST) if (a->dest == RTD_UNICAST)
for (nh = &(a->nh); nh; nh = nh->next) for (nh = &(a->nh); nh; nh = nh->next)
{ {
char mpls[MPLS_MAX_LABEL_STACK*12 + 5], *lsp = mpls; char mpls[MPLS_MAX_LABEL_STRING], *lsp = mpls;
char *onlink = (nh->flags & RNF_ONLINK) ? " onlink" : ""; char *onlink = (nh->flags & RNF_ONLINK) ? " onlink" : "";
char weight[16] = ""; char weight[16] = "";