# Enums are translated to C initializers: use CF_ENUM(typename, prefix, values)
# For different prefix: CF_ENUM_PX(typename, external prefix, C prefix, values)
+ # The typename is converted to a keyword by removing T_ENUM_ prefix
m4_define(CF_enum, `m4_divert(1){ "CF_enum_prefix_ext[[]]$1", -((CF_enum_type<<16) | CF_enum_prefix_int[[]]$1) },
m4_divert(-1)')
- m4_define(CF_ENUM, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$2)CF_iterate([[CF_enum]], [[m4_shift(m4_shift($@))]])DNL')
- m4_define(CF_ENUM_PX, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$3)CF_iterate([[CF_enum]], [[m4_shift(m4_shift(m4_shift($@)))]])DNL')
+ m4_define(CF_ENUM, `CF_keywd(m4_substr($1, 7))m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$2)CF_iterate([[CF_enum]], [[m4_shift(m4_shift($@))]])DNL')
+ m4_define(CF_ENUM_PX, `CF_keywd(m4_substr($1, 7))m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$3)CF_iterate([[CF_enum]], [[m4_shift(m4_shift(m4_shift($@)))]])DNL')
-# After all configuration templates end, we generate the
+# After all configuration templates end, we generate the keyword list
m4_m4wrap(`
m4_divert(0)
static const struct keyword keyword_list[] = {
m4_define(CF_itera, `m4_ifelse($#, 1, [[CF_iter($1)]], [[CF_iter($1)[[]]CF_itera(m4_shift($@))]])')
m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)')
-# Keywords act as %token<s>
-m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)CF_append([[CF_kw_rule]],$1,[[ | ]])m4_define([[CF_toks]],CF_toks $1)]])')
+ m4_define(CF_append, `m4_define([[$1]], m4_ifdef([[$1]], m4_defn([[$1]])[[$3]])[[$2]])')
+
+# Keywords act as untyped %token
+m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_define([[CF_toks]],CF_toks $1)]])')
m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token<s>[[]]CF_toks
)DNL')
m4_define(CF_METHODS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token<s>[[]]CF_toks
m4_undivert(2)DNL
-%type <s> KEYWORD
+ %type <i> enum_type
+
%%
-KEYWORD: CF_kw_rule;
+ enum_type: CF_enum_type;
+
m4_undivert(3)DNL
%%
CF_DECLS
-CF_KEYWORDS_EXCLUSIVE(IN)
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR,
- INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC,
+ INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC, ENUM,
SET, STRING, BYTESTRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE,
- FOR, DO,
+ FOR, IN, DO,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
- FROM, GW, NET, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, GW_MPLS_STACK, ONLINK,
- PREFERENCE,
+ FROM, GW, NET, PROTO, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS,
ROA_CHECK, ASPA_CHECK,
DEFINED,
ADD, DELETE, RESET,
cf_error( "You can't create sets of this type." );
}
}
- | ENUM enum_type { $$ = $2; };
++ | ENUM
++ <i>{ $$ = cf_maybe_exit_filters(); }
++ enum_type
++ {
++ if ($2) cf_enter_filters();
++ $$ = $3;
++ }
;
function_argsn:
NUM { $$.type = T_INT; $$.val.i = $1; }
| fipa { $$ = $1; }
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
- | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
+ | ENUM_TOKEN { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| '(' term ')' {
- $$ = cf_eval($2, T_VOID);
+ $$ = cf_eval_tmp($2, T_VOID);
if (!f_valid_set_type($$.type))
cf_error("Set-incompatible type (%s)", f_type_name($$.type));
}
attribute bgppath mypath;
attribute lclist mylclist;
+/* Setting some custom attributes, enough to force BIRD to reallocate the attribute idmap */
+attribute int test_ca_int1;
+attribute int test_ca_int2;
+attribute int test_ca_int3;
+attribute int test_ca_int4;
+attribute int test_ca_int5;
+attribute int test_ca_int6;
+attribute int test_ca_int7;
+attribute int test_ca_int8;
+attribute int test_ca_int9;
+attribute int test_ca_int10;
+
+attribute ip test_ca_ip1;
+attribute ip test_ca_ip2;
+attribute ip test_ca_ip3;
+attribute ip test_ca_ip4;
+attribute ip test_ca_ip5;
+attribute ip test_ca_ip6;
+attribute ip test_ca_ip7;
+attribute ip test_ca_ip8;
+attribute ip test_ca_ip9;
+attribute ip test_ca_ip10;
+
+attribute quad test_ca_quad1;
+attribute quad test_ca_quad2;
+attribute quad test_ca_quad3;
+attribute quad test_ca_quad4;
+attribute quad test_ca_quad5;
+attribute quad test_ca_quad6;
+attribute quad test_ca_quad7;
+attribute quad test_ca_quad8;
+attribute quad test_ca_quad9;
+attribute quad test_ca_quad10;
+
+attribute bgppath test_ca_bgppath1;
+attribute bgppath test_ca_bgppath2;
+attribute bgppath test_ca_bgppath3;
+attribute bgppath test_ca_bgppath4;
+attribute bgppath test_ca_bgppath5;
+attribute bgppath test_ca_bgppath6;
+attribute bgppath test_ca_bgppath7;
+attribute bgppath test_ca_bgppath8;
+attribute bgppath test_ca_bgppath9;
+attribute bgppath test_ca_bgppath10;
+
+attribute clist test_ca_clist1;
+attribute clist test_ca_clist2;
+attribute clist test_ca_clist3;
+attribute clist test_ca_clist4;
+attribute clist test_ca_clist5;
+attribute clist test_ca_clist6;
+attribute clist test_ca_clist7;
+attribute clist test_ca_clist8;
+attribute clist test_ca_clist9;
+attribute clist test_ca_clist10;
+
+attribute eclist test_ca_eclist1;
+attribute eclist test_ca_eclist2;
+attribute eclist test_ca_eclist3;
+attribute eclist test_ca_eclist4;
+attribute eclist test_ca_eclist5;
+attribute eclist test_ca_eclist6;
+attribute eclist test_ca_eclist7;
+attribute eclist test_ca_eclist8;
+attribute eclist test_ca_eclist9;
+attribute eclist test_ca_eclist10;
+
+attribute lclist test_ca_lclist1;
+attribute lclist test_ca_lclist2;
+attribute lclist test_ca_lclist3;
+attribute lclist test_ca_lclist4;
+attribute lclist test_ca_lclist5;
+attribute lclist test_ca_lclist6;
+attribute lclist test_ca_lclist7;
+attribute lclist test_ca_lclist8;
+attribute lclist test_ca_lclist9;
+attribute lclist test_ca_lclist10;
+
+attribute lclist test_ca_lclist_max1;
+attribute lclist test_ca_lclist_max2;
+attribute lclist test_ca_lclist_max3;
+attribute lclist test_ca_lclist_max4;
+attribute lclist test_ca_lclist_max5;
+attribute lclist test_ca_lclist_max6;
+attribute lclist test_ca_lclist_max7;
+attribute lclist test_ca_lclist_max8;
+attribute lclist test_ca_lclist_max9;
+attribute lclist test_ca_lclist_max10;
+attribute lclist test_ca_lclist_max11;
+attribute lclist test_ca_lclist_max12;
+attribute lclist test_ca_lclist_max13;
+attribute lclist test_ca_lclist_max14;
+attribute lclist test_ca_lclist_max15;
+attribute lclist test_ca_lclist_max16;
+attribute lclist test_ca_lclist_max17;
+attribute lclist test_ca_lclist_max18;
+attribute lclist test_ca_lclist_max19;
+attribute lclist test_ca_lclist_max20;
+attribute lclist test_ca_lclist_max21;
+
++attribute enum rts test_ca_rts;
++attribute enum rtd test_ca_rtd;
++attribute enum scope test_ca_scope;
++attribute enum roa test_ca_roa;
++attribute enum aspa test_ca_aspa;
++attribute enum af test_ca_af;
++attribute enum nettype test_ca_nettype;
++attribute enum bgp_origin test_ca_bgp_origin;
++attribute enum ra_preference test_ca_ra_preference;
++attribute enum mpls_policy test_ca_mpls_policy;
++attribute enum nettype set test_ca_nettype_set;
+
+/* Uncomment this to get an error */
+#attribute int bgp_path;
/*
* Common definitions and functions
function t_enum()
{
- bt_assert(format(RTS_STATIC) = "(enum 30)1");
- bt_assert(format(NET_IP4) = "(enum 36)1");
- bt_assert(format(NET_VPN6) = "(enum 36)4");
- bt_assert(format(ev6) = "(enum 36)2");
+ enum rts ev0 = RTS_STATIC;
+ enum rtd ev1 = RTD_UNICAST;
+ enum scope ev2 = SCOPE_UNIVERSE;
+ enum roa ev3 = ROA_VALID;
+ enum aspa ev4 = ASPA_VALID;
+ enum af ev5 = AF_IPV6;
+ enum nettype ev6 = NET_IP6;
+ enum bgp_origin ev7 = ORIGIN_IGP;
+ enum ra_preference ev8 = RA_PREF_LOW;
+ enum mpls_policy ev9 = MPLS_POLICY_STATIC;
+
+ enum nettype set es = [NET_IP6, NET_VPN6];
+
+ bt_assert(format(RTS_STATIC) = "(enum 31)1");
+ bt_assert(format(NET_IP4) = "(enum 3b)1");
+ bt_assert(format(NET_VPN6) = "(enum 3b)4");
++ bt_assert(format(ev6) = "(enum 3b)2");
+
+ bt_assert(ev0 = RTS_STATIC);
+ bt_assert(ev6 = NET_IP6);
bt_assert(RTS_STATIC ~ [RTS_STATIC, RTS_DEVICE]);
bt_assert(RTS_BGP !~ [RTS_STATIC, RTS_DEVICE]);
FIRST, FREE, VALIDATE, BASE, ROLE, ROLES, PEER, PROVIDER, CUSTOMER,
RS_SERVER, RS_CLIENT, REQUIRE, BGP_OTC, GLOBAL, SEND)
++CF_ENUM(T_ENUM_BGP_ORIGIN, ORIGIN_, IGP, EGP, INCOMPLETE)
++
%type <i> bgp_nh
%type <i32> bgp_afi
bgp_proto_channel: bgp_channel_start bgp_channel_opt_list bgp_channel_end;
-
-dynamic_attr: BGP_ORIGIN
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_ENUM_BGP_ORIGIN, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); $$.flags = BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_PATH
- { $$ = f_new_dynamic_attr(EAF_TYPE_AS_PATH, T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); $$.flags = BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_NEXT_HOP
- { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_CODE(PROTOCOL_BGP, BA_NEXT_HOP)); $$.flags = BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_MED
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); $$.flags = BAF_OPTIONAL; } ;
-dynamic_attr: BGP_LOCAL_PREF
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); $$.flags = BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_ATOMIC_AGGR
- { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(PROTOCOL_BGP, BA_ATOMIC_AGGR)); $$.flags = BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_AGGREGATOR
- { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(PROTOCOL_BGP, BA_AGGREGATOR)); $$.flags = BAF_OPTIONAL | BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); $$.flags = BAF_OPTIONAL | BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_ORIGINATOR_ID
- { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID)); $$.flags = BAF_OPTIONAL; } ;
-dynamic_attr: BGP_CLUSTER_LIST
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST)); $$.flags = BAF_OPTIONAL; } ;
-dynamic_attr: BGP_EXT_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(PROTOCOL_BGP, BA_EXT_COMMUNITY)); $$.flags = BAF_OPTIONAL | BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_AIGP
- { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(PROTOCOL_BGP, BA_AIGP)); $$.flags = BAF_OPTIONAL; } ;
-dynamic_attr: BGP_LARGE_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(PROTOCOL_BGP, BA_LARGE_COMMUNITY)); $$.flags = BAF_OPTIONAL | BAF_TRANSITIVE; } ;
-dynamic_attr: BGP_OTC
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_ONLY_TO_CUSTOMER)); $$.flags = BAF_OPTIONAL | BAF_TRANSITIVE; } ;
-
-custom_attr: ATTRIBUTE BGP expr type symbol ';' {
+custom_attr: ATTRIBUTE BGP NUM type symbol ';' {
if ($3 > 255 || $3 < 1)
- cf_error("Invalid attribute number (Given %i, must be 1-255)", $3);
- if ($4 != T_BYTESTRING)
- cf_error("Attribute type must be bytestring, not %s", f_type_name($4));
- if (bgp_attr_name($3))
- cf_error("Attribute BGP.%d already known as %s", $3, bgp_attr_name($3));
-
- struct f_dynamic_attr *a = cfg_alloc(sizeof(struct f_dynamic_attr));
- *a = f_new_dynamic_attr(f_type_attr($4), T_BYTESTRING, EA_CODE(PROTOCOL_BGP, $3));
- a->flags = BAF_TRANSITIVE | BAF_OPTIONAL;
- cf_define_symbol(new_config, $5, SYM_ATTRIBUTE, attribute, a);
+ cf_error("Invalid attribute number. (Given %i, must be 1-255.)", $3);
+
+ struct ea_class *ac = bgp_find_ea_class_by_id($3);
+ ASSERT_DIE(ac);
+ if ($4 != ac->type)
+ cf_error("Attribute %d type must be %s, not %s.", $3, f_type_name(ac->type), f_type_name($4));
+
+ ea_ref_class(new_config->pool, ac);
+ cf_define_symbol(new_config, $5, SYM_ATTRIBUTE, attribute, ac);
};
--CF_ENUM(T_ENUM_BGP_ORIGIN, ORIGIN_, IGP, EGP, INCOMPLETE)
-
+CF_CLI(RELOAD BGP, proto_patt, [<name>], [[Send and request route refresh to/from neighbor]])
+{
+ proto_apply_cmd($3, bgp_reload_in, 1, 0);
+ proto_apply_cmd($3, bgp_reload_out, 1, 0);
+};
+
+CF_CLI(RELOAD BGP IN, proto_patt, [<name>], [[Request route refresh from neighbor]])
+{
+ proto_apply_cmd($4, bgp_reload_in, 1, 0);
+}
+
+CF_CLI(RELOAD BGP OUT, proto_patt, [<name>], [[Refresh routes to neighbor]])
+{
+ proto_apply_cmd($4, bgp_reload_out, 1, 0);
+}
CF_CODE