p->cf = cf;
p->debug = cf->debug;
+ log("cf->mrtdump %x cf->name %s", cf->mrtdump, cf->name);
p->mrtdump = cf->mrtdump;
p->name = cf->name;
p->proto = cf->protocol;
/* Call a pre-comparison hook */
/* Not really an efficient way to compute this */
const struct rte_context *ctx = rte_get_context(e);
+ log("nexthop update ctx %x, fc ptr %x", ctx, ctx->rte_recalculate);
if (ctx && ctx->rte_recalculate)
ctx->rte_recalculate(ctx, tab, n, new, e, NULL);
{
int as_length = s->as4_session ? 4 : 2;
int as_sets = s->allow_as_sets;
- struct bgp_proto_attributes *proto_attrs = s->proto_attrs;
+ struct bgp_route_ctx *proto_attrs = s->proto_attrs;
if (!proto_attrs)
return;
if (!s->as4_session)
bgp_process_as4_attrs(&attrs, s->pool);
+ if (!s->proto_attrs)
+ return attrs;
#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 */
return as;
/* If AS_PATH is not defined, we treat rte as locally originated */
- struct bgp_proto_attributes *p = (struct bgp_proto_attributes *) ea_find(r->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
+ struct bgp_route_ctx *p = (struct bgp_route_ctx *) ea_find(r->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
return p->confederation ?: p->local_as;
}
int
bgp_rte_better(const struct rte_context *ctx, rte *new, rte *old)
{
- const struct bgp_proto_attributes *new_bgp = SKIP_BACK(const struct bgp_proto_attributes, bgp_rte_ctx, ctx);
- const struct bgp_proto_attributes *old_bgp = bgp_get_route_context(old);
+ const struct bgp_route_ctx *new_bgp = SKIP_BACK(const struct bgp_route_ctx, bgp_rte_ctx, ctx);
+ const struct bgp_route_ctx *old_bgp = bgp_get_route_context(old);
ASSERT_DIE(old_bgp); /* This means that old is actually really a bgp route */
int
bgp_rte_mergable(rte *pri, rte *sec)
{
- struct bgp_proto_attributes *pri_bgp = (struct bgp_proto_attributes *) ea_find(pri->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
- struct bgp_proto_attributes *sec_bgp = (struct bgp_proto_attributes *) ea_find(sec->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
+ struct bgp_route_ctx *pri_bgp = (struct bgp_route_ctx *) ea_find(pri->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
+ struct bgp_route_ctx *sec_bgp = (struct bgp_route_ctx *) ea_find(sec->attrs->eattrs, EA_ROUTE_CONTEXT)->u.ptr;
eattr *x, *y;
u32 p, s;
static inline int
use_deterministic_med(const rte *r)
{
- const struct bgp_proto_attributes *pa = bgp_get_route_context(r);
+ const struct bgp_route_ctx *pa = bgp_get_route_context(r);
return pa && pa->deterministic_med;
}
return p->p.proto_state;
}
-static uint
+uint
bgp_format_rte_ctx(const struct rte_context *ctx, byte *buf)
{
- struct bgp_proto_attributes *pa = SKIP_BACK(struct bgp_proto_attributes, bgp_rte_ctx, ctx);
+ struct bgp_route_ctx *pa = SKIP_BACK(struct bgp_route_ctx, bgp_rte_ctx, ctx);
uint buf_shift;
buf_shift = bsprintf(buf, "loc=%I %u; ", pa->local_ip, pa->local_as);
buf_shift += bsprintf(buf + buf_shift, "loc ID %R; ", pa->local_id);
/* from conf */ \
BGP_ROUTE_ATTRIBUTES\
-struct bgp_proto_attributes { BGP_ROUTE_CONTEXT };
+struct bgp_route_ctx { BGP_ROUTE_CONTEXT };
struct bgp_proto {
struct proto p;
const struct bgp_config *cf; /* Shortcut to BGP configuration */
const char *hostname; /* Hostname for this BGP protocol */
union {
- struct bgp_proto_attributes proto_attrs;
+ struct bgp_route_ctx proto_attrs;
struct { BGP_ROUTE_CONTEXT; };
};
u32 public_as; /* Externally visible ASN (local_as or confederation id) */
struct bgp_parse_state {
// instead of struct bgp_proto *proto;
- struct bgp_proto_attributes *proto_attrs;
+ struct bgp_route_ctx *proto_attrs;
struct proto *p;
u32 public_as;
u8 is_mrt_parse;
/* attrs.c */
-static inline const struct bgp_proto_attributes *
+static inline const struct bgp_route_ctx *
bgp_get_route_context(const rte *r)
{
const struct rte_context *ctx = rte_get_context(r);
return (ctx && (ctx->proto_class == PROTOCOL_BGP)) ?
- SKIP_BACK(struct bgp_proto_attributes, bgp_rte_ctx, ctx) : NULL;
+ SKIP_BACK(struct bgp_route_ctx, bgp_rte_ctx, ctx) : NULL;
}
static inline eattr *
void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to);
byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf);
+uint bgp_format_rte_ctx(const struct rte_context *ctx, byte *buf);
/* Packet types */
static void
bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
{
- ASSERT_DIE(s->p);
- struct bgp_proto *p = (struct bgp_proto *) s->p;
+ log("bgp_apply_next_hop");
+
struct bgp_channel *c = SKIP_BACK(struct bgp_channel, c, s->channel);
if (c->cf->gw_mode == GW_DIRECT)
/* GW_DIRECT -> single_hop -> p->neigh != NULL */
if (ipa_nonzero2(gw))
- nbr = neigh_find(&p->p, gw, NULL, 0);
- else if (ipa_nonzero(ll))
- nbr = neigh_find(&p->p, ll, p->neigh->iface, 0);
+ nbr = neigh_find(s->p, gw, NULL, 0);
+ //else if (ipa_nonzero(ll)) //TODO
+ // nbr = neigh_find(&s->p, ll, p->neigh->iface, 0);
else
- WITHDRAW(BAD_NEXT_HOP " - zero address");
+ WITHDRAW(BAD_NEXT_HOP " - zero address FIX ME LINK LOCAL NEXTHOP ONLY");
if (!nbr)
WITHDRAW(BAD_NEXT_HOP " - address %I not directly reachable", ipa_nonzero(gw) ? gw : ll);
- if (nbr->scope == SCOPE_HOST)
+ if (nbr && nbr->scope == SCOPE_HOST)
WITHDRAW(BAD_NEXT_HOP " - address %I is local", nbr->addr);
a->dest = RTD_UNICAST;
/* With MPLS, hostentry is applied later in bgp_apply_mpls_labels() */
}
+ log("bgp_apply_next_hop end");
}
static void
if (s->mpls)
bgp_decode_mpls_labels(s, &pos, &len, &l, a);
- if (l > IP4_MAX_PREFIX_LENGTH)
- bgp_parse_error(s, 10);
+ if (l > IP4_MAX_PREFIX_LENGTH){
+ bug("parse error");
+ bgp_parse_error(s, 10);}
/* Decode prefix body */
ip4_addr addr = IP4_NONE;
static inline void
bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
{
+ log("bgp_decode_nlri");
if (!s->get_channel(s, afi))
DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi));
if (ea)
{
+ log("ea %x", ea);
a = allocz(RTA_MAX_SIZE);
a->source = RTS_BGP;
a = NULL;
}
+ log("jump %s %x (desc %x)", s->desc->name, s->desc->decode_nlri, s->desc);
+ log("true desc %x, name %s fce %x", &bgp_af_table[0], bgp_af_table[0].name, bgp_af_table[0].decode_nlri );
s->desc->decode_nlri(s, nlri, len, a);
+ log("jumped");
rta_free(s->cached_rta);
s->cached_rta = NULL;
+ log("bgp_decode_nlri end");
}
void
struct rte_ctx_adata *rcad = lp_allocz(s->pool, sizeof *rcad);
rcad->ad.length = sizeof *rcad - sizeof rcad->ad;
rcad->ctx = &s->proto_attrs->bgp_rte_ctx;
+ log("ctx %x, fc ptr %x (%s)", rcad->ctx, rcad->ctx->rte_recalculate, s->proto_name);
+ ASSERT_DIE(s->proto_name);
ea_set_attr_ptr(ea, s->pool, EA_ROUTE_CONTEXT, 0, EAF_TYPE_OPAQUE, &rcad->ad);
/* Check for End-of-RIB marker */
conn->bgp->stats.rx_messages++;
conn->bgp->stats.rx_bytes += len;
+ log("if (conn->bgp->p.mrtdump & MD_MESSAGES) %x %x", conn->bgp->p.mrtdump, MD_MESSAGES);
if (conn->bgp->p.mrtdump & MD_MESSAGES)
bgp_dump_message(conn, pkt, len);
put_u16(s->buf.start + s->peer_count_offset, s->peer_count);
mrt_dump_message(&s->buf, s->fd);
+ log("mrt_peer_table_dump ok");
}
static void
Figure 12: BGP4MP_MESSAGE Subtype
*/
-void
-mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4)
+int
+mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4, struct bgp_route_ctx *proto_attrs)
{
- log("mrt_parse_bgp_message");
u64 peer_as, local_as;
if (as4)
{
peer_as = mrtload_two_octet(fp, remains);
local_as = mrtload_two_octet(fp, remains);
}
+ proto_attrs->is_internal = peer_as == local_as;
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);
- log("peer as %lx local as %lx interface %x add fam %i peer %I loc %I", peer_as, local_as, interface_id, addr_fam, peer_addr, local_addr);
+ mrtload_ip(fp, remains, &proto_attrs->remote_ip, addr_fam == 2);
+ mrtload_ip(fp, remains, &proto_attrs->local_ip, addr_fam == 2);
+
+ log("peer as %lx local as %lx interface %x add fam %i peer %I loc %I", peer_as, local_as, interface_id, addr_fam, proto_attrs->remote_ip, proto_attrs->local_ip);
+ return addr_fam;
}
static void
static void
mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P)
{
- log("here");
- mrt_parse_bgp_message(fp, remains, as4);
+ struct mrtload_proto *p = (void *) P;
+ struct mrtload_route_ctx *proto_attrs = (struct mrtload_route_ctx *) mb_alloc(p->ctx_pool, sizeof(struct mrtload_route_ctx));
+ int addr_fam = mrt_parse_bgp_message(fp, remains, as4, &proto_attrs->ctx);
+ log("addr fam %x", addr_fam);
+ if (addr_fam != p->addr_fam)
+ return;
+ log("continue");
if (*remains < 19)
{
remains[0] = remains[0] - 16;
u64 length = mrtload_two_octet(fp, remains) - 16 - 2 -1; /* length without header (marker, length, type) */
+ log("length %i", length);
int type = mrtload_one(fp, remains);
+ log("type %i (pkt update %i)", type, PKT_UPDATE);
if (type != PKT_UPDATE)
return;
rt_lock_source(P->main_source);
struct bgp_parse_state s = {
+ .proto_name = P->name,
.pool = lp_new(P->pool),
.parse_error = mrt_parse_error,
.end_mark = mrt_rx_end_mark,
.p = P,
};
+ proto_attrs->ctx.bgp_rte_ctx.proto_class = PROTOCOL_BGP;
+ proto_attrs->ctx.bgp_rte_ctx.rte_better = bgp_rte_better;
+ proto_attrs->ctx.bgp_rte_ctx.rte_recalculate = NULL; //cf->deterministic_med ? bgp_rte_recalculate
+ proto_attrs->ctx.bgp_rte_ctx.format = bgp_format_rte_ctx;
+
+ // TODO: this is not the correct setting
+ proto_attrs->ctx.local_id = proto_get_router_id(P->cf);
+ proto_attrs->ctx.remote_id = 0;
+ proto_attrs->ctx.rr_client = 0;
+ proto_attrs->ctx.rs_client = 0;
+ proto_attrs->ctx.is_interior = proto_attrs->ctx.is_internal;
+
+ HASH_INSERT(p->ctx_hash, MRTLOAD_CTX, proto_attrs);
+
+ s.proto_attrs = &proto_attrs->ctx;
+
byte buf[length];
ASSERT_DIE(length <= remains[0]);
mrtload_n_octet(fp, remains, buf, length);
log("type %i subtype %i", type, subtype);
if (type == MRT_BGP4MP)
{
- log("yeah?");
switch (subtype)
{
case (MRT_BGP4MP_MESSAGE):
p->channel->desc = cf->channel_cf->desc;
p->channel->c.channel = &channel_mrtload;
p->channel->c.table = cf->table_cf->table;
+ p->addr_fam = cf->table_cf->table->addr_type;
+ p->ctx_pool = rp_new(P->pool, "Mrtload route ctx");
+ HASH_INIT(p->ctx_hash, p->ctx_pool, 10);
- if (cf->channel_cf->igp_table_ip4)
- p->channel->igp_table_ip4 = cf->channel_cf->igp_table_ip4->table;
+ ASSERT_DIE(cf->table_cf->table);
+ struct rtable_config **def_tables = cf->c.global->def_tables;
+ if (cf->table_cf->table->addr_type == NET_IP4)
+ {
+ p->channel->igp_table_ip4 = cf->table_cf->table;
+ p->channel->igp_table_ip6 = def_tables[NET_IP6]->table;
+ }
- if (cf->channel_cf->igp_table_ip6)
- p->channel->igp_table_ip6 = cf->channel_cf->igp_table_ip6->table;
+ if (cf->table_cf->table->addr_type == NET_IP6)
+ {
+ p->channel->igp_table_ip6 = cf->table_cf->table;
+ p->channel->igp_table_ip4 = def_tables[NET_IP4]->table;
+ }
+
+ ASSERT_DIE(p->channel->igp_table_ip6 || p->channel->igp_table_ip4);
mrtload(P);
mrtload_postconfig(struct proto_config *CF)
{
struct mrtload_config *cf = (void *) CF;
+
if (cf->channel_cf->c.in_filter != FILTER_ACCEPT)
cf_error("MRT load channel in filter must be set to accept");
if (cf->channel_cf->c.out_filter != FILTER_REJECT)
#include "filter/filter.h"
#include "proto/mrt/mrt.h"
+#define MRTLOAD_CTX_KEY(n) n->ctx.remote_as, n->ctx.local_as, \
+ n->ctx.is_internal
+#define MRTLOAD_CTX_NEXT(n) n->next
+#define MRTLOAD_CTX_EQ(p1,n1,p2,n2) p1 == p2 && n1 == n2
+#define MRTLOAD_CTX_FN(pas, las, iin) u64_hash(pas) + u64_hash(las) + iin
+#define MRTLOAD_CTX_REHASH mrtload_ctx_rehash
+#define MRTLOAD_CTX_PARAMS /2, *2, 1, 1, 8, 20
+#define MRTLOAD_CTX_INIT_ORDER 6
+
+
extern const struct channel_class channel_mrtload;
struct mrtload_config {
const struct bgp_af_desc *desc;
};
+struct mrtload_route_ctx {
+ struct bgp_route_ctx ctx;
+ struct mrtload_route_ctx *next;
+};
+
struct mrtload_proto {
struct proto p;
union {
struct { BGP_ROUTE_CONTEXT };
};
+ int addr_fam;
struct mrt_table_dump_state *table_dump;
struct bgp_channel *channel;
+ pool *ctx_pool;
+ HASH(struct mrtload_route_ctx) ctx_hash; // TODO : maybe it should be stored somewhere else
};