-/* $OpenBSD: rde.c,v 1.602 2023/04/19 07:12:22 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.603 2023/04/19 13:23:33 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
- flowspec_add(curflow, &state, &parent_set);
+ if (flowspec_valid(curflow->data, curflow->len,
+ curflow->aid == AID_FLOWSPECv6) == -1)
+ log_warnx("invalid flowspec update received "
+ "from parent");
+ else
+ flowspec_add(curflow, &state, &parent_set);
+
rde_filterstate_clean(&state);
filterset_free(&parent_set);
free(curflow);
log_warnx("rde_dispatch: wrong flowspec len");
break;
}
- flowspec_delete(curflow);
+ if (flowspec_valid(curflow->data, curflow->len,
+ curflow->aid == AID_FLOWSPECv6) == -1)
+ log_warnx("invalid flowspec withdraw received "
+ "from parent");
+ else
+ flowspec_delete(curflow);
free(curflow);
curflow = NULL;
break;
flowspec_add(struct flowspec *f, struct filterstate *state,
struct filter_set_head *attrset)
{
+ struct pt_entry *pte;
+ uint32_t path_id_tx;
+
+ rde_apply_set(attrset, peerself, peerself, state, f->aid);
+ rde_filterstate_set_vstate(state, ROA_NOTFOUND, ASPA_NEVER_KNOWN);
+ path_id_tx = peerself->path_id_tx; /* XXX should use pathid_assign() */
+
+ pte = pt_get_flow(f);
+ if (pte == NULL)
+ pte = pt_add_flow(f);
+
+ if (prefix_flowspec_update(peerself, state, pte, path_id_tx) == 1)
+ peerself->stats.prefix_cnt++;
}
void
flowspec_delete(struct flowspec *f)
{
+ struct pt_entry *pte;
+
+ pte = pt_get_flow(f);
+ if (pte == NULL)
+ return;
+
+ if (prefix_flowspec_withdraw(peerself, pte) == 1)
+ peerself->stats.prefix_cnt--;
}
/* clean up */
-/* $OpenBSD: rde.h,v 1.292 2023/04/19 07:09:47 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.293 2023/04/19 13:23:33 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
int (*)(void *));
void rib_dump_terminate(void *);
+extern struct rib flowrib;
+
static inline struct rib *
re_rib(struct rib_entry *re)
{
+ if (re->prefix->aid == AID_FLOWSPECv4 ||
+ re->prefix->aid == AID_FLOWSPECv6)
+ return &flowrib;
return rib_byid(re->rib_id);
}
uint32_t, struct filterstate *, struct bgpd_addr *, int);
int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
+int prefix_flowspec_update(struct rde_peer *, struct filterstate *,
+ struct pt_entry *, uint32_t);
+int prefix_flowspec_withdraw(struct rde_peer *, struct pt_entry *);
+void prefix_flowspec_dump(uint8_t, void *,
+ void (*)(struct rib_entry *, void *),
+ void (*)(void *, uint8_t));
void prefix_add_eor(struct rde_peer *, uint8_t);
void prefix_adjout_update(struct prefix *, struct rde_peer *,
struct filterstate *, struct pt_entry *, uint32_t);
-/* $OpenBSD: rde_filter.c,v 1.134 2023/03/10 07:57:15 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.135 2023/04/19 13:23:33 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
if (rules == NULL)
return (action);
+ if (prefix->aid == AID_FLOWSPECv4 || prefix->aid == AID_FLOWSPECv6)
+ return (ACTION_ALLOW);
+
f = TAILQ_FIRST(rules);
while (f != NULL) {
RDE_FILTER_TEST_ATTRIB(
-/* $OpenBSD: rde_peer.c,v 1.31 2023/03/10 07:57:16 claudio Exp $ */
+/* $OpenBSD: rde_peer.c,v 1.32 2023/04/19 13:23:33 claudio Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
} else if (peer->export_type == EXPORT_DEFAULT_ROUTE) {
up_generate_default(peer, aid);
rde_up_dump_done(peer, aid);
+ } else if (aid == AID_FLOWSPECv4 || aid == AID_FLOWSPECv6) {
+ prefix_flowspec_dump(aid, peer, rde_up_dump_upcall,
+ rde_up_dump_done);
} else {
if (rib_dump_new(peer->loc_rib_id, aid, RDE_RUNNER_ROUNDS, peer,
rde_up_dump_upcall, rde_up_dump_done, NULL) == -1)
-/* $OpenBSD: rde_rib.c,v 1.258 2023/04/07 13:49:03 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.259 2023/04/19 13:23:33 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
*/
uint16_t rib_size;
struct rib **ribs;
+struct rib flowrib = { .id = 1, .tree = RB_INITIALIZER(&flowrib.tree) };
struct rib_entry *rib_add(struct rib *, struct pt_entry *);
static inline int rib_compare(const struct rib_entry *,
return (1);
}
+/*
+ * Special functions for flowspec until full integration is available.
+ * This just directly feeds the prefixes into the Adj-RIB-Out bypassing
+ * Adj-RIB-In and Loc-RIB for now.
+ */
+int
+prefix_flowspec_update(struct rde_peer *peer, struct filterstate *state,
+ struct pt_entry *pte, uint32_t path_id_tx)
+{
+ struct rde_aspath *asp, *nasp;
+ struct rde_community *comm, *ncomm;
+ struct rib_entry *re;
+ struct prefix *new, *old;
+
+ re = rib_get(&flowrib, pte);
+ if (re == NULL)
+ re = rib_add(&flowrib, pte);
+
+ old = prefix_bypeer(re, peer, 0);
+ new = prefix_alloc();
+
+ nasp = &state->aspath;
+ ncomm = &state->communities;
+ if ((asp = path_lookup(nasp)) == NULL) {
+ /* Path not available, create and link a new one. */
+ asp = path_copy(path_get(), nasp);
+ path_link(asp);
+ }
+ if ((comm = communities_lookup(ncomm)) == NULL) {
+ /* Communities not available, create and link a new one. */
+ comm = communities_link(ncomm);
+ }
+
+ prefix_link(new, re, re->prefix, peer, 0, path_id_tx, asp, comm,
+ NULL, 0, 0);
+ TAILQ_INSERT_HEAD(&re->prefix_h, new, entry.list.rib);
+
+ rde_generate_updates(re, new, old, EVAL_DEFAULT);
+
+ if (old != NULL) {
+ TAILQ_REMOVE(&re->prefix_h, old, entry.list.rib);
+ prefix_unlink(old);
+ prefix_free(old);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Remove a possible flowspec prefix from all Adj-RIB-Outs.
+ */
+int
+prefix_flowspec_withdraw(struct rde_peer *peer, struct pt_entry *pte)
+{
+ struct rib_entry *re;
+ struct prefix *p;
+
+ re = rib_get(&flowrib, pte);
+ if (re == NULL)
+ return 0;
+ p = prefix_bypeer(re, peer, 0);
+ if (p == NULL)
+ return 0;
+ rde_generate_updates(re, NULL, p, EVAL_DEFAULT);
+ TAILQ_REMOVE(&re->prefix_h, p, entry.list.rib);
+ prefix_unlink(p);
+ prefix_free(p);
+ return 1;
+}
+
+/*
+ * Push all flowspec rules into a newly available Adj-RIB-Out.
+ */
+void
+prefix_flowspec_dump(uint8_t aid, void *arg,
+ void (*call)(struct rib_entry *, void *), void (*done)(void *, uint8_t))
+{
+ struct rib_entry *re, *next;
+
+ RB_FOREACH_SAFE(re, rib_tree, rib_tree(&flowrib), next)
+ call(re, arg);
+ if (done != NULL)
+ done(arg, aid);
+}
+
/*
* Insert an End-of-RIB marker into the update queue.
*/