Commit cc4eee62 authored by Pavel Tvrdík's avatar Pavel Tvrdík
Browse files

MRT Table Dump: draft-petrie-grow-mrt-add-paths

Add support for MRT Table Dump draft-petrie-grow-mrt-add-paths
parent a474f34c
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -219,14 +219,14 @@ mrt_rib_table_alloc(struct mrt_rib_table *state)
}

void
mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix)
mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix, uint is_addpath)
{
  mrt_rib_table_reset(state);

#ifdef IPV6
  state->subtype = MRT_RIB_IPV6_UNICAST;
  state->subtype = (is_addpath == MRT_RIB_ADDPATH) ? MRT_RIB_IPV6_UNICAST_ADDPATH : MRT_RIB_IPV6_UNICAST;
#else
  state->subtype = MRT_RIB_IPV4_UNICAST;
  state->subtype = (is_addpath == MRT_RIB_ADDPATH) ? MRT_RIB_IPV4_UNICAST_ADDPATH : MRT_RIB_IPV4_UNICAST;
#endif

  struct mrt_buffer *msg = &state->msg;
@@ -257,6 +257,16 @@ mrt_rib_table_add_entry(struct mrt_rib_table *state, const struct mrt_rib_entry

  mrt_buffer_put_var_autosize(msg, entry->peer_index);
  mrt_buffer_put_var_autosize(msg, entry->originated_time);

  switch (state->subtype)
  {
    case MRT_RIB_IPV4_UNICAST_ADDPATH:
    case MRT_RIB_IPV6_UNICAST_ADDPATH:
    case MRT_RIB_IPV4_MULTICAST_ADDPATH:
    case MRT_RIB_IPV6_MULTICAST_ADDPATH:
      mrt_buffer_put_var_autosize(msg, entry->path_id);
  }

  mrt_buffer_put_var_autosize(msg, entry->attributes_length);
  mrt_buffer_put_raw(msg, entry->attributes, entry->attributes_length);

+10 −1
Original line number Diff line number Diff line
@@ -37,6 +37,14 @@
#define MRT_RIB_IPV6_UNICAST	4
#define MRT_RIB_IPV6_MULTICAST 	5
#define MRT_RIB_GENERIC		6
#define MRT_RIB_IPV4_UNICAST_ADDPATH	8	/* Experimental draft-petrie-grow-mrt-add-paths */
#define MRT_RIB_IPV4_MULTICAST_ADDPATH	9	/* Experimental draft-petrie-grow-mrt-add-paths */
#define MRT_RIB_IPV6_UNICAST_ADDPATH	10	/* Experimental draft-petrie-grow-mrt-add-paths */
#define MRT_RIB_IPV6_MULTICAST_ADDPATH 	11	/* Experimental draft-petrie-grow-mrt-add-paths */
#define MRT_RIB_GENERIC_ADDPATH		12	/* Experimental draft-petrie-grow-mrt-add-paths */
#define MRT_RIB_NO_ADDPATH	0
#define MRT_RIB_ADDPATH		1


/* MRT BGP4MP Subtypes */
#define MRT_BGP4MP_MESSAGE	1
@@ -72,6 +80,7 @@ struct mrt_rib_entry
{
  u16 peer_index;
  u32 originated_time;
  u32 path_id;			/* draft-petrie-grow-mrt-add-paths */
  u16 attributes_length;
  byte *attributes;		/* encoded BGP attributes */
};
@@ -98,7 +107,7 @@ void mrt_peer_index_table_add_peer(struct mrt_peer_index_table *state, u32 peer_
void mrt_peer_index_table_dump(struct mrt_peer_index_table *state, int file_descriptor);

void mrt_rib_table_alloc(struct mrt_rib_table *state);
void mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix);
void mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix, uint is_addpath);
void mrt_rib_table_add_entry(struct mrt_rib_table *state, const struct mrt_rib_entry *entry);

/* implemented in sysdep */
+1 −1
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ t_rib_table(void)
  ip4_pton("12.34.56.78", &prefix);
#endif
  mrt_rib_table_alloc(&state);
  mrt_rib_table_header(&state, sequence_number, prefix_len, prefix);
  mrt_rib_table_header(&state, sequence_number, prefix_len, prefix, MRT_RIB_NO_ADDPATH);

  u32 i;
  for(i = 0; i < 5; i++)
+87 −53
Original line number Diff line number Diff line
@@ -52,36 +52,26 @@ bgp_mrt_rib_table_dump(struct mrt_table_dump_ctx *state)
  mrt_dump_message(fileno(state->rfile->f), MRT_TABLE_DUMP_V2, state->rib_table.subtype, msg, msg_length);
}

/*
 * Usage:
 * 	struct mrt_table_dump_ctx ctx;
 * 	bgp_mrt_table_dump_init(rtable, &ctx);
 * 	while (ctx.state != MRT_STATE_COMPLETED)
 * 	  bgp_mrt_table_dump_step(&ctx);
 */
void
bgp_mrt_table_dump_step(struct mrt_table_dump_ctx *state)
static void
bgp_mrt_rib_table_entry(struct mrt_table_dump_ctx *state, net *n, uint is_addpath)
{
  if (state->state == MRT_STATE_COMPLETED)
    return;

  uint max_work_size = 1;
  u32 original_rib_sequence_number = state->rib_sequence_number;

  FIB_ITERATE_START(&state->rtable->fib, &state->fit, f)
  {
    if (!max_work_size--)
    {
      FIB_ITERATE_PUT(&state->fit, f);
      return;
    }

    net *n = (net *) f;
    mrt_rib_table_header(&state->rib_table, state->rib_sequence_number++, n->n.pxlen, n->n.prefix);
  mrt_rib_table_header(&state->rib_table, state->rib_sequence_number++, n->n.pxlen, n->n.prefix, is_addpath);

  rte *e;
  for (e = n->routes; e; e = e->next)
  {
    u32 path_id = 0;

    if (is_addpath == MRT_RIB_ADDPATH)
      if (e->attrs->src->private_id == 0)
	continue;

    if (is_addpath == MRT_RIB_NO_ADDPATH)
      if (e->attrs->src->private_id != 0)
	continue;

    struct proto *P = e->attrs->src->proto;

    if (!is_route_good_for_table_dump(state, e))
@@ -101,22 +91,27 @@ bgp_mrt_table_dump_step(struct mrt_table_dump_ctx *state)
	continue;
      }

	struct bgp_proto tmp_bgp_proto = {
	    .as4_session = 1, /* to force build AS_PATH as 32bit AS in bgp_encode_attrs() */
	};
      /* Set as4_session=1 to force build AS_PATH as 32bit AS in bgp_encode_attrs() */
      struct bgp_proto bgp_proto_shallow_copy;
      memcpy(&bgp_proto_shallow_copy, p, sizeof(bgp_proto_shallow_copy));
      bgp_proto_shallow_copy.as4_session = 1;

	attributes_length = bgp_encode_attrs(&tmp_bgp_proto, attributes_buffer, e->attrs->eattrs, BGP_ATTR_BUFFER_SIZE);
      attributes_length = bgp_encode_attrs(&bgp_proto_shallow_copy, attributes_buffer, e->attrs->eattrs, BGP_ATTR_BUFFER_SIZE);
      if (attributes_length == -1)
      {
	log(L_WARN "%s: MRT Table Dump for %I/%u: Attribute list too long, let it blank", p->p.name, n->n.prefix, n->n.pxlen);
	attributes_length = 0;
      }
      peer_index = p->mrt_peer_index;

      if (is_addpath)
        path_id = e->attrs->src->private_id;
    }

    struct mrt_rib_entry entry = {
	.peer_index = peer_index,
	.originated_time = (u32) bird_clock_to_unix_timestamp(e->lastmod),
	.path_id = path_id,
	.attributes_length = attributes_length,
	.attributes = attributes_buffer
    };
@@ -128,6 +123,45 @@ bgp_mrt_table_dump_step(struct mrt_table_dump_ctx *state)
    bgp_mrt_rib_table_dump(state);
  else
    state->rib_sequence_number = original_rib_sequence_number;
}

static void
mrt_rib_table_without_addpath(struct mrt_table_dump_ctx *state, net *n)
{
  bgp_mrt_rib_table_entry(state, n, MRT_RIB_NO_ADDPATH);
}

static void
mrt_rib_table_with_addpath(struct mrt_table_dump_ctx *state, net *n)
{
  bgp_mrt_rib_table_entry(state, n, MRT_RIB_ADDPATH);
}

/*
 * Usage:
 * 	struct mrt_table_dump_ctx ctx;
 * 	bgp_mrt_table_dump_init(rtable, &ctx);
 * 	while (ctx.state != MRT_STATE_COMPLETED)
 * 	  bgp_mrt_table_dump_step(&ctx);
 */
void
bgp_mrt_table_dump_step(struct mrt_table_dump_ctx *state)
{
  if (state->state == MRT_STATE_COMPLETED)
    return;

  uint max_work_size = 1;

  FIB_ITERATE_START(&state->rtable->fib, &state->fit, f)
  {
    if (!max_work_size--)
    {
      FIB_ITERATE_PUT(&state->fit, f);
      return;
    }

    mrt_rib_table_without_addpath(state, (net *) f);
    mrt_rib_table_with_addpath(state, (net *) f);
  } FIB_ITERATE_END(f);

  fit_get(&state->rtable->fib, &state->fit);
+1 −1
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
  memcpy(bp, pkt, len);
  bp += len;

  mrt_dump_message(&conn->bgp->p, MRT_BGP4MP, subtype, buf, bp-buf);
  mrt_dump_message_proto(&conn->bgp->p, MRT_BGP4MP, subtype, buf, bp-buf);
}

static inline u16