#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 */
{
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)))
}
/* 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);
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)
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)
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))
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)
{
.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,
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
#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;
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);
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 */
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
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;
/* 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)
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));
* 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)
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)
/* 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;
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;
/* 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));
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;
}
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;
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
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;
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;
|| (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);
};
+#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;
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] */
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 */
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] */
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;
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;
#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 */
#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 */
#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,
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 */
| 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 ';'
| 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; }
| 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; }
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 */
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; }
.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,
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);
void
mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4)
{
+ log("mrt_parse_bgp_message");
u64 peer_as, local_as;
if (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);
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)
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):
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;
}
if (!cf->filename)
cf_error("File not specified");
+ else
+ log("%s", cf->filename);
if (!CC->desc)
cf_error("Afi not specified.");
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;
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;
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;
mrtload_proto_start: proto_start MRTLOAD
{
this_proto = proto_config_new(&proto_mrtload, $1);
+ BGP_RT_CFG = &MRTLOAD_CFG->rte_class;
};
/* empty */
| mrtload_proto_opts mrt_get_bgp_channel mrtload_tab ';'
| mrtload_proto_opts mrtload_proto_item ';'
+ | mrtload_proto_opts bgp_attr_for_route
;
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);
}
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");
}