From: Katerina Kubecova Date: Mon, 16 Jun 2025 13:26:56 +0000 (+0200) Subject: bgp: structs refactoring - BGP_ROUTE_ATTRIBUTES and BGP_PROTO_ATTRIBUTES created X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2113243960ff32f85c94514cced91dc1e788013;p=thirdparty%2Fbird.git bgp: structs refactoring - BGP_ROUTE_ATTRIBUTES and BGP_PROTO_ATTRIBUTES created --- diff --git a/nest/route.h b/nest/route.h index 5a9e7fa16..41940fb92 100644 --- a/nest/route.h +++ b/nest/route.h @@ -561,6 +561,7 @@ const char *ea_custom_name(uint ea); #define EAF_TYPE_STRING 0x16 /* Text string */ #define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */ #define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */ +#define EAF_PROTO_ATTR_PTR 0x18 /* Pointer to bgp_proto_attributes */ typedef struct adata { uint length; /* Length of data */ diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 489405134..52c54ef2e 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -450,7 +450,8 @@ bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte { int as_length = s->as4_session ? 4 : 2; int as_sets = s->allow_as_sets; - int as_confed = s->confederation && s->is_interior; + struct bgp_proto_attributes *proto_attrs = s->proto_attrs; + int as_confed = proto_attrs->confederation && proto_attrs->is_interior; char err[128]; if (!as_path_valid(data, len, as_length, as_sets, as_confed, err, sizeof(err))) @@ -465,13 +466,13 @@ bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte } /* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */ - if (s->is_interior && !s->is_internal && + if (proto_attrs->is_interior && !proto_attrs->is_internal && ((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE))) WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE"); /* Reject routes with first AS in AS_PATH not matching neighbor AS; RFC 4271 6.3 */ - if (!s->is_internal && s->enforce_first_as && - !bgp_as_path_first_as_equal(data, len, s->remote_as)) + if (!proto_attrs->is_internal && s->enforce_first_as && + !bgp_as_path_first_as_equal(data, len, proto_attrs->remote_as)) WITHDRAW("Malformed AS_PATH attribute - %s", "First AS differs from neigbor AS"); bgp_set_attr_data(to, s->pool, BA_AS_PATH, flags, data, len); @@ -560,7 +561,7 @@ bgp_export_local_pref(struct bgp_export_state *s, eattr *a) static void bgp_decode_local_pref(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to) { - if (!s->is_interior && !s->allow_local_pref) + if (!s->proto_attrs->is_interior && !s->allow_local_pref) DISCARD(BAD_EBGP, "LOCAL_PREF"); if (len != 4) @@ -654,7 +655,7 @@ bgp_export_originator_id(struct bgp_export_state *s, eattr *a) static void bgp_decode_originator_id(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to) { - if (!s->is_internal) + if (!s->proto_attrs->is_internal) DISCARD(BAD_EBGP, "ORIGINATOR_ID"); if (len != 4) @@ -678,7 +679,7 @@ bgp_export_cluster_list(struct bgp_export_state *s UNUSED, eattr *a) static void bgp_decode_cluster_list(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to) { - if (!s->is_internal) + if (!s->proto_attrs->is_internal) DISCARD(BAD_EBGP, "CLUSTER_LIST"); if (!len || (len % 4)) @@ -958,6 +959,18 @@ bgp_encode_mpls_label_stack(struct bgp_write_state *s, eattr *a, byte *buf UNUSE return 0; } +static int +bgp_encode_proto_attrs(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte *buf UNUSED, uint size UNUSED) +{ + return 0; +} + +static void +bgp_decode_proto_attrs(struct bgp_parse_state *s UNUSED, uint code UNUSED, uint flags UNUSED, byte *data UNUSED, uint len UNUSED, ea_list **to UNUSED) +{ + return; +} + static void bgp_decode_mpls_label_stack(struct bgp_parse_state *s, uint code UNUSED, uint flags UNUSED, byte *data UNUSED, uint len UNUSED, ea_list **to UNUSED) { @@ -1138,6 +1151,13 @@ static const struct bgp_attr_desc bgp_attr_table[] = { .encode = bgp_encode_u32, .decode = bgp_decode_otc, }, + [BA_PROTO_ATTRS] = { + .name = "bgp proto attrs", + .type = EAF_PROTO_ATTR_PTR, + .flags = BAF_OPERATIONAL, + .encode = bgp_encode_proto_attrs, + .decode = bgp_decode_proto_attrs, + }, [BA_MPLS_LABEL_STACK] = { .name = "mpls_label_stack", .type = EAF_TYPE_INT_SET, @@ -1314,7 +1334,7 @@ static inline int bgp_originator_id_loopy(struct bgp_parse_state *s, ea_list *attrs) { eattr *e = bgp_find_attr(attrs, BA_ORIGINATOR_ID); - return (e && (e->u.data == s->local_id)); + return (e && (e->u.data == s->proto_attrs->local_id)); } static inline int @@ -1437,24 +1457,24 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len) #define IS_LOOP(msg, args...) { RTRACE("update is loop (" msg "), treating as withdraw", ##args); goto loop; } /* Reject routes with our ASN in AS_PATH attribute */ - if (bgp_as_path_loopy(s, attrs, s->local_as)) + if (bgp_as_path_loopy(s, attrs, s->proto_attrs->local_as)) goto loop; /* Reject routes with our Confederation ID in AS_PATH attribute; RFC 5065 4.0 */ - if ((s->public_as != s->local_as) && bgp_as_path_loopy(s, attrs, s->public_as)) + if ((s->public_as != s->proto_attrs->local_as) && bgp_as_path_loopy(s, attrs, s->public_as)) goto loop; /* Reject routes with our Router ID in ORIGINATOR_ID attribute; RFC 4456 8 */ - if (s->is_internal && bgp_originator_id_loopy(s, attrs)) + if (s->proto_attrs->is_internal && bgp_originator_id_loopy(s, attrs)) goto loop; /* Reject routes with our Cluster ID in CLUSTER_LIST attribute; RFC 4456 8 */ - if (s->rr_client && bgp_cluster_list_loopy(s->rr_cluster_id, attrs)) + if (s->rr_client && bgp_cluster_list_loopy(s->proto_attrs->rr_cluster_id, attrs)) goto loop; /* If there is no local preference, define one */ if (!BIT32_TEST(s->attrs_seen, BA_LOCAL_PREF)) - bgp_set_attr_u32(&attrs, s->pool, BA_LOCAL_PREF, 0, s->default_local_pref); + bgp_set_attr_u32(&attrs, s->pool, BA_LOCAL_PREF, 0, s->proto_attrs->default_local_pref); return attrs; @@ -1499,7 +1519,7 @@ bgp_finish_attrs(struct bgp_parse_state *s, rta *a) WITHDRAW("Route leak detected - OTC attribute from downstream"); /* Reject routes from peers if they are leaked */ - if (e && (s->local_role == BGP_ROLE_PEER) && (e->u.data != s->remote_as)) + if (e && (s->local_role == BGP_ROLE_PEER) && (e->u.data != s->proto_attrs->remote_as)) WITHDRAW("Route leak detected - OTC attribute with mismatched ASN (%u)", (uint) e->u.data); @@ -1507,7 +1527,7 @@ bgp_finish_attrs(struct bgp_parse_state *s, rta *a) if (!e && (s->local_role == BGP_ROLE_CUSTOMER || s->local_role == BGP_ROLE_PEER || s->local_role == BGP_ROLE_RS_CLIENT)) - bgp_set_attr_u32(&a->eattrs, s->pool, BA_ONLY_TO_CUSTOMER, 0, s->remote_as); + bgp_set_attr_u32(&a->eattrs, s->pool, BA_ONLY_TO_CUSTOMER, 0, s->proto_attrs->remote_as); } /* Apply MPLS policy for labeled SAFIs */ @@ -1987,8 +2007,8 @@ bgp_get_neighbor(rte *r) return as; /* If AS_PATH is not defined, we treat rte as locally originated */ - struct bgp_proto *p = (void *) r->src->proto; - return p->cf->confederation ?: p->local_as; + struct bgp_proto_attributes *p = (struct bgp_proto_attributes *) ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr; + return p->confederation ?: p->local_as; } static inline int @@ -2017,8 +2037,8 @@ rte_stale(rte *r) int bgp_rte_better(rte *new, rte *old) { - struct bgp_proto *new_bgp = (struct bgp_proto *) new->src->proto; - struct bgp_proto *old_bgp = (struct bgp_proto *) old->src->proto; + struct bgp_proto_attributes *new_bgp = (struct bgp_proto_attributes *) ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr; + struct bgp_proto_attributes *old_bgp = (struct bgp_proto_attributes *) ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr; eattr *x, *y; u32 n, o; @@ -2049,8 +2069,8 @@ bgp_rte_better(rte *new, rte *old) /* Start with local preferences */ x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); - n = x ? x->u.data : new_bgp->cf->default_local_pref; - o = y ? y->u.data : old_bgp->cf->default_local_pref; + n = x ? x->u.data : new_bgp->default_local_pref; + o = y ? y->u.data : old_bgp->default_local_pref; if (n > o) return 1; if (n < o) @@ -2065,7 +2085,7 @@ bgp_rte_better(rte *new, rte *old) return 0; /* RFC 4271 9.1.2.2. a) Use AS path lengths */ - if (new_bgp->cf->compare_path_lengths || old_bgp->cf->compare_path_lengths) + if (new_bgp->compare_path_lengths || old_bgp->compare_path_lengths) { x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); @@ -2098,13 +2118,13 @@ bgp_rte_better(rte *new, rte *old) * same behavior as used by default in Cisco routers, so it is * probably not a big issue. */ - if (new_bgp->cf->med_metric || old_bgp->cf->med_metric || + if (new_bgp->med_metric || old_bgp->med_metric || (bgp_get_neighbor(new) == bgp_get_neighbor(old))) { x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); - n = x ? x->u.data : new_bgp->cf->default_med; - o = y ? y->u.data : old_bgp->cf->default_med; + n = x ? x->u.data : new_bgp->default_med; + o = y ? y->u.data : old_bgp->default_med; if (n < o) return 1; if (n > o) @@ -2118,8 +2138,8 @@ bgp_rte_better(rte *new, rte *old) return 1; /* RFC 4271 9.1.2.2. e) Compare IGP metrics */ - n = new_bgp->cf->igp_metric ? new->attrs->igp_metric : 0; - o = old_bgp->cf->igp_metric ? old->attrs->igp_metric : 0; + n = new_bgp->igp_metric ? new->attrs->igp_metric : 0; + o = old_bgp->igp_metric ? old->attrs->igp_metric : 0; if (n < o) return 1; if (n > o) @@ -2134,7 +2154,7 @@ bgp_rte_better(rte *new, rte *old) /* RFC 5004 - prefer older routes */ /* (if both are external and from different peer) */ - if ((new_bgp->cf->prefer_older || old_bgp->cf->prefer_older) && + if ((new_bgp->prefer_older || old_bgp->prefer_older) && !new_bgp->is_internal && n != o) return 0; @@ -2162,8 +2182,8 @@ bgp_rte_better(rte *new, rte *old) int bgp_rte_mergable(rte *pri, rte *sec) { - struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->src->proto; - struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->src->proto; + struct bgp_proto_attributes *pri_bgp = (struct bgp_proto_attributes *) ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr; + struct bgp_proto_attributes *sec_bgp = (struct bgp_proto_attributes *) ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr; eattr *x, *y; u32 p, s; @@ -2182,13 +2202,13 @@ bgp_rte_mergable(rte *pri, rte *sec) /* Start with local preferences */ x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); - p = x ? x->u.data : pri_bgp->cf->default_local_pref; - s = y ? y->u.data : sec_bgp->cf->default_local_pref; + p = x ? x->u.data : pri_bgp->default_local_pref; + s = y ? y->u.data : sec_bgp->default_local_pref; if (p != s) return 0; /* RFC 4271 9.1.2.2. a) Use AS path lengths */ - if (pri_bgp->cf->compare_path_lengths || sec_bgp->cf->compare_path_lengths) + if (pri_bgp->compare_path_lengths || sec_bgp->compare_path_lengths) { x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); @@ -2211,13 +2231,13 @@ bgp_rte_mergable(rte *pri, rte *sec) return 0; /* RFC 4271 9.1.2.2. c) Compare MED's */ - if (pri_bgp->cf->med_metric || sec_bgp->cf->med_metric || + if (pri_bgp->med_metric || sec_bgp->med_metric || (bgp_get_neighbor(pri) == bgp_get_neighbor(sec))) { x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); - p = x ? x->u.data : pri_bgp->cf->default_med; - s = y ? y->u.data : sec_bgp->cf->default_med; + p = x ? x->u.data : pri_bgp->default_med; + s = y ? y->u.data : sec_bgp->default_med; if (p != s) return 0; } @@ -2227,8 +2247,8 @@ bgp_rte_mergable(rte *pri, rte *sec) return 0; /* RFC 4271 9.1.2.2. e) Compare IGP metrics */ - p = pri_bgp->cf->igp_metric ? pri->attrs->igp_metric : 0; - s = sec_bgp->cf->igp_metric ? sec->attrs->igp_metric : 0; + p = pri_bgp->igp_metric ? pri->attrs->igp_metric : 0; + s = sec_bgp->igp_metric ? sec->attrs->igp_metric : 0; if (p != s) return 0; @@ -2247,8 +2267,8 @@ same_group(rte *r, u32 lpref, u32 lasn) static inline int use_deterministic_med(rte *r) { - struct proto *P = r->src->proto; - return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med; + struct bgp_proto_attributes *pa = (struct bgp_proto_attributes *) ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr; + return (pa->routes_proto == BGP_ROUTE) && pa->deterministic_med; } int diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 1f3ae87ca..84c273f41 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -2064,6 +2064,14 @@ bgp_start(struct proto *P) p->remote_as = cf->remote_as; p->public_as = cf->local_as; + p->deterministic_med = cf->deterministic_med; + p->default_local_pref = cf->default_local_pref; + p->compare_path_lengths = cf->compare_path_lengths; + p->confederation = cf->confederation; + p->med_metric = cf->med_metric; + p->default_med = cf->default_med; + p->igp_metric = cf->igp_metric; + p->prefer_older = cf->prefer_older; /* For dynamic BGP childs, remote_ip is already set */ if (ipa_nonzero(cf->remote_ip)) p->remote_ip = cf->remote_ip; @@ -2251,6 +2259,7 @@ bgp_init(struct proto_config *CF) P->rte_igp_metric = bgp_rte_igp_metric; p->cf = cf; + p->routes_proto = BGP_ROUTE; p->is_internal = (cf->local_as == cf->remote_as); p->is_interior = p->is_internal || cf->confederation_member; p->rs_client = cf->rs_client; @@ -2744,6 +2753,19 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF) || (old->remote_range && new->remote_range && net_equal(old->remote_range, new->remote_range))) && !bstrcmp(old->dynamic_name, new->dynamic_name) && (old->dynamic_name_digits == new->dynamic_name_digits); + + /* Options influencing best route selection; for now, restarting, in future + * we should just recalculate the tables */ + same = same && p->deterministic_med == new->deterministic_med + && p->compare_path_lengths == new->compare_path_lengths + && p->med_metric == new->med_metric + && p->default_med == new->default_med + && p->igp_metric == new->igp_metric + && p->prefer_older == new->prefer_older; + + /* looks like this does not affect best route selection */ + p->default_local_pref = new->default_local_pref; + p->confederation = new->confederation; /* Reconfigure TCP-AP */ same = same && bgp_reconfigure_ao_keys(p, new); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index adc1e8359..14f9f8f3b 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -74,8 +74,24 @@ struct bgp_af_desc { }; +#define BGP_ROUTE_ATTRIBUTES \ + int deterministic_med; /* Use more complicated algo to have strict RFC 4271 MED comparison */ \ + u32 default_local_pref; /* Default value for LOCAL_PREF attribute */ \ + int compare_path_lengths; /* Use path lengths when selecting best route */ \ + u32 confederation; /* Confederation ID, or zero if confeds not active */ \ + int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */ \ + u32 default_med; /* Default value for MULTI_EXIT_DISC attribute */ \ + int igp_metric; /* Use IGP metrics when selecting best route */ \ + int prefer_older; /* Prefer older routes according to RFC 5004 */ \ + +struct rte_class_config { BGP_ROUTE_ATTRIBUTES }; + struct bgp_config { struct proto_config c; + union { + struct rte_class_config rte_class; + struct { BGP_ROUTE_ATTRIBUTES; }; + }; u32 local_as, remote_as; ip_addr local_ip; /* Source address to use */ ip_addr remote_ip; @@ -87,13 +103,6 @@ struct bgp_config { int strict_bind; /* Bind listening socket to local address */ int free_bind; /* Bind listening socket with SKF_FREEBIND */ int ttl_security; /* Enable TTL security [RFC 5082] */ - int compare_path_lengths; /* Use path lengths when selecting best route */ - int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */ - int igp_metric; /* Use IGP metrics when selecting best route */ - int prefer_older; /* Prefer older routes according to RFC 5004 */ - int deterministic_med; /* Use more complicated algo to have strict RFC 4271 MED comparison */ - u32 default_local_pref; /* Default value for LOCAL_PREF attribute */ - u32 default_med; /* Default value for MULTI_EXIT_DISC attribute */ int capabilities; /* Enable capability handshake [RFC 5492] */ int enable_refresh; /* Enable local support for route refresh [RFC 2918] */ int enable_enhanced_refresh; /* Enable local support for enhanced route refresh [RFC 7313] */ @@ -103,7 +112,6 @@ struct bgp_config { u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */ int rr_client; /* Whether neighbor is RR client of me */ int rs_client; /* Whether neighbor is RS client of me */ - u32 confederation; /* Confederation ID, or zero if confeds not active */ int confederation_member; /* Whether neighbor AS is member of our confederation */ int passive; /* Do not initiate outgoing connection */ int interpret_communities; /* Hardwired handling of well-known communities */ @@ -351,22 +359,38 @@ struct bgp_conn { uint hold_time, keepalive_time, send_hold_time; /* Times calculated from my and neighbor's requirements */ }; +enum route_proto { + BGP_ROUTE = 1, +}; + +#define BGP_PROTO_ATTRIBUTES \ + enum route_proto routes_proto; /* protocol enum (pointer to bgp_proto_attributes is given to route eattrs) */ \ + u32 local_as, remote_as; \ + ip_addr local_ip, remote_ip; \ + u32 local_id; /* BGP identifier of this router */ \ + u32 remote_id; /* BGP identifier of the neighbor */ \ + u32 rr_cluster_id; /* Route reflector cluster ID */ \ + u8 rr_client; /* Whether neighbor is RR client of me */ \ + u8 rs_client; /* Whether neighbor is RS client of me */ \ + u8 is_internal; /* Internal BGP session (local_as == remote_as) */ \ + u8 is_interior; /* Internal or intra-confederation BGP session */ \ + \ + /* from conf */ \ + BGP_ROUTE_ATTRIBUTES\ + +struct bgp_proto_attributes { BGP_PROTO_ATTRIBUTES }; + struct bgp_proto { struct proto p; const struct bgp_config *cf; /* Shortcut to BGP configuration */ const char *hostname; /* Hostname for this BGP protocol */ - ip_addr local_ip, remote_ip; - u32 local_as, remote_as; + union { + struct bgp_proto_attributes proto_attrs; + struct { BGP_PROTO_ATTRIBUTES; }; + }; u32 public_as; /* Externally visible ASN (local_as or confederation id) */ - u32 local_id; /* BGP identifier of this router */ - u32 remote_id; /* BGP identifier of the neighbor */ - u32 rr_cluster_id; /* Route reflector cluster ID */ u8 start_state; /* Substates that partitions BS_START */ - u8 is_internal; /* Internal BGP session (local_as == remote_as) */ - u8 is_interior; /* Internal or intra-confederation BGP session */ u8 as4_session; /* Session uses 4B AS numbers in AS_PATH (both sides support it) */ - u8 rr_client; /* Whether neighbor is RR client of me */ - u8 rs_client; /* Whether neighbor is RS client of me */ u8 ipv4; /* Use IPv4 connection, i.e. remote_ip is IPv4 */ u8 passive; /* Do not initiate outgoing connection */ u8 route_refresh; /* Route refresh allowed to send [RFC 2918] */ @@ -494,15 +518,10 @@ struct bgp_write_state { struct bgp_parse_state { // instead of struct bgp_proto *proto; + struct bgp_proto_attributes *proto_attrs; struct proto *p; - u32 local_as; u32 public_as; - u32 remote_as; - u32 rr_cluster_id; - u32 local_id; u8 is_mrt_parse; - u8 is_interior; - u8 is_internal; const char *proto_name; u32 debug; /* Debugging flags */ struct channel *mpls_channel; @@ -512,8 +531,6 @@ struct bgp_parse_state { int allow_local_pref; int allow_local_as; int enforce_first_as; - u32 default_local_pref; - u32 confederation; u8 local_role; int rr_client; ip_addr remote_ip; @@ -773,6 +790,7 @@ byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf); #define BAF_TRANSITIVE 0x40 #define BAF_PARTIAL 0x20 #define BAF_EXT_LEN 0x10 +#define BAF_OPERATIONAL 0x100 #define BAF_DECODE_FLAGS 0x0100 /* Private flag - attribute flags are handled by the decode hook */ @@ -794,6 +812,7 @@ byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf); #define BA_AIGP 0x1a /* RFC 7311 */ #define BA_LARGE_COMMUNITY 0x20 /* RFC 8092 */ #define BA_ONLY_TO_CUSTOMER 0x23 /* RFC 9234 */ +#define BA_PROTO_ATTRS 0x24 /* BGP_PROTO_ATTRIBUTES */ /* Bird's private internal BGP attributes */ #define BA_MPLS_LABEL_STACK 0xfe /* MPLS label stack transfer attribute */ diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 93df8f966..9c2eed300 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -14,10 +14,13 @@ CF_DEFINES #define BGP_CFG ((struct bgp_config *) this_proto) #define BGP_CC ((struct bgp_channel_config *) this_channel) +#define BGP_RT_CF BGP_CFG->route_attrs; static struct ao_config *this_ao_key; static struct ao_config **next_ao_key; +static struct rte_class_config *BGP_RT_CFG; + CF_DECLS CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE, @@ -55,6 +58,7 @@ proto: bgp_proto '}' ; bgp_proto_start: proto_start BGP { this_proto = proto_config_new(&proto_bgp, $1); + BGP_RT_CFG = &BGP_CFG->rte_class; BGP_CFG->local_port = BGP_PORT; BGP_CFG->remote_port = BGP_PORT; BGP_CFG->multihop = -1; /* undefined */ @@ -142,8 +146,19 @@ bgp_role_name: | RS_CLIENT { $$ = BGP_ROLE_RS_CLIENT; } ; +bgp_attr_for_route: + DETERMINISTIC MED bool ';' { BGP_RT_CFG->deterministic_med = $3; } + | DEFAULT BGP_LOCAL_PREF expr ';' { BGP_RT_CFG->default_local_pref = $3; } + | PATH METRIC bool ';' { BGP_RT_CFG->compare_path_lengths = $3; } + | CONFEDERATION expr ';' { BGP_RT_CFG->confederation = $2; } + | MED METRIC bool ';' { BGP_RT_CFG->med_metric = $3; } + | DEFAULT BGP_MED expr ';' { BGP_RT_CFG->default_med = $3; } + | IGP METRIC bool ';' { BGP_RT_CFG->igp_metric = $3; } + | PREFER OLDER bool ';' { BGP_RT_CFG->prefer_older = $3; } + bgp_proto: - bgp_proto_start proto_name '{' + bgp_proto bgp_attr_for_route + | bgp_proto_start proto_name '{' | bgp_proto proto_item ';' | bgp_proto bgp_proto_channel ';' | bgp_proto mpls_channel ';' @@ -170,7 +185,6 @@ bgp_proto: | bgp_proto RR CLUSTER ID idval ';' { BGP_CFG->rr_cluster_id = $5; } | bgp_proto RR CLIENT bool ';' { BGP_CFG->rr_client = $4; } | bgp_proto RS CLIENT bool ';' { BGP_CFG->rs_client = $4; } - | bgp_proto CONFEDERATION expr ';' { BGP_CFG->confederation = $3; } | bgp_proto CONFEDERATION MEMBER bool ';' { BGP_CFG->confederation_member = $4; } | bgp_proto HOLD TIME expr ';' { BGP_CFG->hold_time = $4; if (($4 && $4<3) || ($4>65535)) cf_error("Hold time must be in range 3-65535 or zero"); } | bgp_proto MIN HOLD TIME expr ';' { BGP_CFG->min_hold_time = $5; } @@ -186,13 +200,6 @@ bgp_proto: | bgp_proto DYNAMIC NAME DIGITS expr ';' { BGP_CFG->dynamic_name_digits = $5; if ($5>10) cf_error("Dynamic name digits must be at most 10"); } | bgp_proto STRICT BIND bool ';' { BGP_CFG->strict_bind = $4; } | bgp_proto FREE BIND bool ';' { BGP_CFG->free_bind = $4; } - | bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; } - | bgp_proto MED METRIC bool ';' { BGP_CFG->med_metric = $4; } - | bgp_proto IGP METRIC bool ';' { BGP_CFG->igp_metric = $4; } - | bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; } - | bgp_proto DETERMINISTIC MED bool ';' { BGP_CFG->deterministic_med = $4; } - | bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; } - | bgp_proto DEFAULT BGP_LOCAL_PREF expr ';' { BGP_CFG->default_local_pref = $4; } | bgp_proto SOURCE ADDRESS ipa ';' { BGP_CFG->local_ip = $4; } | bgp_proto START DELAY TIME expr ';' { BGP_CFG->connect_delay_time = $5; cf_warn("%s: Start delay time option is deprecated, use connect delay time", this_proto->name); } | bgp_proto CONNECT DELAY TIME expr ';' { BGP_CFG->connect_delay_time = $5; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 42af4c99b..5b4cda16b 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1177,7 +1177,7 @@ static void bgp_apply_flow_validation(struct bgp_parse_state *s, const net_addr *n, rta *a) { struct bgp_channel *c = SKIP_BACK(struct bgp_channel, c, s->channel); - int valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->is_interior); + int valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->proto_attrs->is_interior); a->dest = valid ? RTD_NONE : RTD_UNREACHABLE; /* Invalidate cached rta if dest changes */ @@ -2861,6 +2861,8 @@ bgp_parse_update(struct bgp_parse_state *s, byte *pkt, uint len, ea_list **ea) else *ea = NULL; + bgp_set_attr_ptr(ea, s->pool, BA_PROTO_ATTRS, 0, (adata*) s->proto_attrs); + /* Check for End-of-RIB marker */ if (!s->attr_len && !s->ip_unreach_len && !s->ip_reach_len) { s->end_mark(s, BGP_AF_IPV4); return; } @@ -2917,25 +2919,18 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) .get_channel = bgp_get_channel_to_parse, .apply_mpls_labels = bgp_apply_mpls_labels, - .local_as = p->local_as, + .proto_attrs = &p->proto_attrs, .remote_ip = p->remote_ip, .public_as = p->public_as, - .remote_as = p->remote_as, - .rr_cluster_id = p->rr_cluster_id, - .local_id = p->local_id, - .is_interior = p->is_interior, - .is_internal = p->is_internal, .proto_name = p->p.name, .is_mrt_parse = 0, .debug = p->p.debug, .mpls_channel = p->p.mpls_channel, // from config - .default_local_pref = p->cf->default_local_pref, .allow_local_pref = p->cf->allow_local_pref, .allow_as_sets = p->cf->allow_as_sets, .allow_local_as = p->cf->allow_local_as, - .confederation = p->cf->confederation, .enforce_first_as = p->cf->enforce_first_as, .local_role = p->cf->local_role, .rr_client = p->cf->rr_client, diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index 1336837a8..c460e6913 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -351,6 +351,7 @@ mrt_peer_table_entry(struct mrt_table_dump_state *s, u32 peer_id, u32 peer_as, i static void mrt_peer_table_dump(struct mrt_table_dump_state *s) { + log("mrt_peer_table_dump"); mrt_init_message(&s->buf, MRT_TABLE_DUMP_V2, MRT_PEER_INDEX_TABLE); mrt_peer_table_header(s, config->router_id, s->table->name); diff --git a/proto/mrt/mrt_load.c b/proto/mrt/mrt_load.c index 9ef35bde0..908eacadb 100644 --- a/proto/mrt/mrt_load.c +++ b/proto/mrt/mrt_load.c @@ -83,6 +83,7 @@ mrt_parse_error(struct bgp_parse_state * ps UNUSED, uint e UNUSED) void mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4) { + log("mrt_parse_bgp_message"); u64 peer_as, local_as; if (as4) { @@ -97,6 +98,7 @@ mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4) int interface_id = mrtload_two_octet(fp, remains); int addr_fam = mrtload_two_octet(fp, remains); + log("peer as %i", peer_as); ip_addr peer_addr, local_addr; mrtload_ip(fp, remains, &peer_addr, addr_fam == 2); mrtload_ip(fp, remains, &local_addr, addr_fam == 2); @@ -133,6 +135,7 @@ mrt_apply_mpls_labels(struct bgp_parse_state *s UNUSED, rta *a UNUSED, u32 *labe static void mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P) { + log("here"); mrt_parse_bgp_message(fp, remains, as4); if (*remains < 19) @@ -201,8 +204,10 @@ mrt_parse_general_header(FILE *fp, struct proto *P) u64 remains = length; /* We do not load MRT_TABLE_DUMP_V2 type and MRT_BGP4MP_STATE_CHANGE_AS4. */ + log("type %i subtype %i", type, subtype); if (type == MRT_BGP4MP) { + log("yeah?"); switch (subtype) { case (MRT_BGP4MP_MESSAGE): @@ -232,12 +237,12 @@ mrt_parse_general_header(FILE *fp, struct proto *P) void mrtload(struct proto *P) { - struct mrt_config *cf = SKIP_BACK(struct mrt_config, c, P->cf); + struct mrtload_config *cf = (void *) (P->cf); FILE *fp = fopen(cf->filename, "r"); if (fp == NULL) { - log(L_WARN "Can not open file %s", fp); + log(L_WARN "Can not open file %s", cf->filename); return; } @@ -255,6 +260,8 @@ mrtload_check_config(struct proto_config *CF, struct bgp_channel_config *CC) if (!cf->filename) cf_error("File not specified"); + else + log("%s", cf->filename); if (!CC->desc) cf_error("Afi not specified."); @@ -276,6 +283,14 @@ mrtload_start(struct proto *P) struct mrtload_proto *p = (void *) P; struct mrtload_config *cf = (void *) (P->cf); + p->deterministic_med = cf->deterministic_med; + p->default_local_pref = cf->default_local_pref; + p->compare_path_lengths = cf->compare_path_lengths; + p->confederation = cf->confederation; + p->med_metric = cf->med_metric; + p->default_med = cf->default_med; + p->igp_metric = cf->igp_metric; + p->prefer_older = cf->prefer_older; p->channel = (void *) proto_add_channel(P, &cf->channel_cf->c); p->channel->afi = cf->channel_cf->afi; diff --git a/proto/mrt/mrt_load.h b/proto/mrt/mrt_load.h index 6609d1c5b..64391cc4a 100644 --- a/proto/mrt/mrt_load.h +++ b/proto/mrt/mrt_load.h @@ -13,6 +13,10 @@ extern const struct channel_class channel_mrtload; struct mrtload_config { struct proto_config c; + union { + struct rte_class_config rte_class; + struct { BGP_ROUTE_ATTRIBUTES }; + }; struct rtable_config *table_cf; const char *table_expr; @@ -25,6 +29,10 @@ struct mrtload_config { struct mrtload_proto { struct proto p; + union { + struct rte_class_config rte_class; + struct { BGP_PROTO_ATTRIBUTES }; + }; struct mrt_table_dump_state *table_dump; struct bgp_channel *channel; diff --git a/proto/mrt/mrtload.Y b/proto/mrt/mrtload.Y index 51eba5740..3bd29fb22 100644 --- a/proto/mrt/mrtload.Y +++ b/proto/mrt/mrtload.Y @@ -21,6 +21,7 @@ proto: mrtload_proto; mrtload_proto_start: proto_start MRTLOAD { this_proto = proto_config_new(&proto_mrtload, $1); + BGP_RT_CFG = &MRTLOAD_CFG->rte_class; }; @@ -86,6 +87,7 @@ mrtload_proto_opts: /* empty */ | mrtload_proto_opts mrt_get_bgp_channel mrtload_tab ';' | mrtload_proto_opts mrtload_proto_item ';' + | mrtload_proto_opts bgp_attr_for_route ; diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index cc422ee1c..9387d3cfd 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -922,7 +922,7 @@ sk_set_icmp6_filter(sock *s, int p1, int p2) void sk_log_error(sock *s, const char *p) { - log(L_ERR "%s: Socket error: %s%#m", p, s->err); + bug("%s: Socket error: %s%#m", p, s->err); } @@ -1665,7 +1665,8 @@ sk_open(sock *s) log(L_WARN "Socket error: %s%#m", s->err); sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port); - if (bind(fd, &sa.sa, SA_LEN(sa)) < 0) + int i = bind(fd, &sa.sa, SA_LEN(sa)); + if (i < 0) ERR2("bind"); }