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

BGP: Improve custom BGP attributes

- Implement EA_GET for custom BGP attributes
 - Forbid EA_SET on existing opaque attributes
 - Forbid redefining existing attributes
 - Document possible compatibility problems
This commit is contained in:
Ondrej Zajicek 2023-10-05 21:29:04 +02:00
parent ba01a6f2e6
commit 57aa077227
5 changed files with 32 additions and 9 deletions

View File

@ -3561,10 +3561,14 @@ some of them (marked with `<tt/O/') are optional.
name="local role"> is configured it set automatically. name="local role"> is configured it set automatically.
</descrip> </descrip>
<p>For attributes unknown by BIRD, the user can assign a name (on top level) <p>For attributes unknown by BIRD, the user can assign a name (on top level) to
to an attribute by its number. This defined name can be used then to both set an attribute by its number. This defined name can be used then to get, set (as a
(by a bytestring literal, transitive) or unset the given attribute even though bytestring, transitive) or unset the given attribute even though BIRD knows
BIRD knows nothing about it: nothing about it.
<p>Note that it is not possible to define an attribute with the same number
as one known by BIRD, therefore use of this statement carries a risk of
incompatibility with future BIRD versions.
<tt><label id="bgp-attribute-custom">attribute bgp <m/number/ bytestring <m/name/;</tt> <tt><label id="bgp-attribute-custom">attribute bgp <m/number/ bytestring <m/name/;</tt>

View File

@ -838,7 +838,10 @@
RESULT_(T_QUAD, i, e->u.data); RESULT_(T_QUAD, i, e->u.data);
break; break;
case EAF_TYPE_OPAQUE: case EAF_TYPE_OPAQUE:
RESULT_(T_ENUM_EMPTY, i, 0); if (da.f_type == T_ENUM_EMPTY)
RESULT_(T_ENUM_EMPTY, i, 0);
else
RESULT_(T_BYTESTRING, ad, e->u.ptr);
break; break;
case EAF_TYPE_IP_ADDRESS: case EAF_TYPE_IP_ADDRESS:
RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data)); RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data));
@ -870,6 +873,12 @@
ARG_ANY(1); ARG_ANY(1);
DYNAMIC_ATTR; DYNAMIC_ATTR;
ARG_TYPE(1, da.f_type); ARG_TYPE(1, da.f_type);
FID_NEW_BODY;
if (da.f_type == T_ENUM_EMPTY)
cf_error("Setting opaque attribute is not allowed");
FID_INTERPRET_BODY;
{ {
struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr)); struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr));

View File

@ -1152,6 +1152,12 @@ bgp_attr_known(uint code)
return (code < ARRAY_SIZE(bgp_attr_table)) && bgp_attr_table[code].name; return (code < ARRAY_SIZE(bgp_attr_table)) && bgp_attr_table[code].name;
} }
const char *
bgp_attr_name(uint code)
{
return (code < ARRAY_SIZE(bgp_attr_table)) ? bgp_attr_table[code].name : NULL;
}
void bgp_fix_attr_flags(ea_list *attrs) void bgp_fix_attr_flags(ea_list *attrs)
{ {
for (u8 i = 0; i < attrs->count; i++) for (u8 i = 0; i < attrs->count; i++)

View File

@ -611,6 +611,7 @@ bgp_unset_attr(ea_list **to, struct linpool *pool, uint code)
int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size); int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
const char * bgp_attr_name(uint code);
int bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end); int bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end);
ea_list * bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len); ea_list * bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len);
void bgp_finish_attrs(struct bgp_parse_state *s, rta *a); void bgp_finish_attrs(struct bgp_parse_state *s, rta *a);

View File

@ -365,11 +365,14 @@ dynamic_attr: BGP_LARGE_COMMUNITY
dynamic_attr: BGP_OTC dynamic_attr: BGP_OTC
{ $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_ONLY_TO_CUSTOMER)); } ; { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_ONLY_TO_CUSTOMER)); } ;
custom_attr: ATTRIBUTE BGP NUM type symbol ';' { custom_attr: ATTRIBUTE BGP expr type symbol ';' {
if($3 > 255 || $3 < 1) if ($3 > 255 || $3 < 1)
cf_error("Invalid attribute number. (Given %i, must be 1-255.)", $3); cf_error("Invalid attribute number (Given %i, must be 1-255)", $3);
if($4 != T_BYTESTRING) if ($4 != T_BYTESTRING)
cf_error("Attribute type must be bytestring, not %s", f_type_name($4)); 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)); 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 = f_new_dynamic_attr(f_type_attr($4), T_BYTESTRING, EA_CODE(PROTOCOL_BGP, $3));
a->flags = BAF_TRANSITIVE | BAF_OPTIONAL; a->flags = BAF_TRANSITIVE | BAF_OPTIONAL;