summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-05-15 18:09:30 +0200
committerMaria Matejka <mq@ucw.cz>2022-05-30 14:39:09 +0200
commit950775f6fa3d569a9d7cd05e33538d35e895d688 (patch)
tree81b4b23d5695e209301b252d0d282b05a0d67ac1 /proto/bgp
parent4fe9881d625f10e44109a649e369a413bd98de71 (diff)
Route destination field merged with nexthop attribute; splitting flowspec validation result out.
As there is either a nexthop or another destination specification (or othing in case of ROAs and Flowspec), it may be merged together. This code is somehow quirky and should be replaced in future by better implementation of nexthop. Also flowspec validation result has its own attribute now as it doesn't have anything to do with route nexthop.
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/attrs.c17
-rw-r--r--proto/bgp/bgp.h4
-rw-r--r--proto/bgp/packets.c25
3 files changed, 30 insertions, 16 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 1efc26ce..6a9e4026 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -1711,9 +1711,20 @@ bgp_preexport(struct proto *P, rte *e)
if (src == NULL)
return 0;
- /* Reject flowspec that failed validation */
- if ((e->attrs->dest == RTD_UNREACHABLE) && net_is_flow(e->net->n.addr))
- return -1;
+ /* Reject flowspec that failed or are pending validation */
+ if (net_is_flow(e->net->n.addr))
+ switch (rt_get_flowspec_valid(e))
+ {
+ case FLOWSPEC_VALID:
+ break;
+ case FLOWSPEC_INVALID:
+ return -1;
+ case FLOWSPEC_UNKNOWN:
+ if ((rt_get_source_attr(e) == RTS_BGP) &&
+ ((struct bgp_channel *) e->sender)->base_table)
+ return -1;
+ break;
+ }
/* IBGP route reflection, RFC 4456 */
if (p->is_internal && src->is_internal && (p->local_as == src->local_as))
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 6abb7870..2f98dc1b 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -519,7 +519,9 @@ struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
static inline int
rte_resolvable(rte *rt)
{
- return rt->attrs->dest != RTD_UNREACHABLE;
+ eattr *nhea = ea_find(rt->attrs->eattrs, &ea_gen_nexthop);
+ struct nexthop_adata *nhad = (void *) nhea->u.ptr;
+ return NEXTHOP_IS_REACHABLE(nhad) || (nhad->dest != RTD_UNREACHABLE);
}
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index b07320aa..4c46c60e 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -968,7 +968,6 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
ea_set_attr_u32(&a->eattrs, &ea_gen_igp_metric, 0, c->cf->cost);
- a->dest = RTD_UNICAST;
struct nexthop_adata nhad = {
.nh = {
.gw = nbr->addr,
@@ -1003,8 +1002,7 @@ bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 lnum, u32 labels[ln
{
REPORT("Too many MPLS labels ($u)", lnum);
- a->dest = RTD_UNREACHABLE;
- ea_unset_attr(&a->eattrs, 0, &ea_gen_nexthop);
+ ea_set_dest(&a->eattrs, 0, RTD_UNREACHABLE);
return;
}
@@ -1039,15 +1037,21 @@ static void
bgp_apply_flow_validation(struct bgp_parse_state *s, const net_addr *n, rta *a)
{
struct bgp_channel *c = s->channel;
- int valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->proto->is_interior);
- a->dest = valid ? RTD_NONE : RTD_UNREACHABLE;
+ uint valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->proto->is_interior);
- /* Invalidate cached rta if dest changes */
- if (s->cached_rta && (s->cached_rta->dest != a->dest))
+ /* Invalidate cached rta */
+ if (s->cached_rta)
{
+ /* Has't changed */
+ if (valid == ea_get_int(s->cached_rta->eattrs, &ea_gen_flowspec_valid, FLOWSPEC_UNKNOWN))
+ return;
+
rta_free(s->cached_rta);
s->cached_rta = NULL;
}
+
+ /* Set the value */
+ ea_set_attr_u32(&a->eattrs, &ea_gen_flowspec_valid, 0, valid);
}
static int
@@ -1107,17 +1111,14 @@ bgp_use_gateway(struct bgp_export_state *s)
if (c->cf->next_hop_self && bgp_match_src(s, c->cf->next_hop_self))
return NULL;
- /* Unreachable */
- if (ra->dest != RTD_UNICAST)
- return NULL;
-
eattr *nhea = ea_find(ra->eattrs, &ea_gen_nexthop);
if (!nhea)
return NULL;
/* We need one valid global gateway */
struct nexthop_adata *nhad = (struct nexthop_adata *) nhea->u.ptr;
- if (!NEXTHOP_ONE(nhad) || ipa_zero(nhad->nh.gw) ||
+ if (!NEXTHOP_IS_REACHABLE(nhad) ||
+ !NEXTHOP_ONE(nhad) || ipa_zero(nhad->nh.gw) ||
ipa_is_link_local(nhad->nh.gw))
return NULL;