]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: exporting protocol-specific state information
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Fri, 11 Oct 2024 10:38:18 +0000 (12:38 +0200)
committerMaria Matejka <mq@ucw.cz>
Thu, 14 Nov 2024 10:41:37 +0000 (11:41 +0100)
proto/bgp/attrs.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c

index 3951b25f6907bfa2bfa5c46e58f6ac2c82505cb0..d293a71b2fcf063215679b4235497c7b8fe0cb97 100644 (file)
@@ -1215,6 +1215,79 @@ bgp_find_attr(ea_list *attrs, uint code)
   return ea_find(attrs, BGP_EA_ID(code));
 }
 
+struct ea_class ea_bgp_rem_id = {
+  .name = "proto_bgp_rem_id",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_rem_as = {
+  .name = "proto_bgp_rem_as",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_loc_as = {
+  .name = "proto_bgp_loc_as",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_rem_ip = {
+  .name = "proto_bgp_rem_ip",
+  .type = T_IP,
+};
+
+struct ea_class ea_bgp_afi = {
+  .name = "bgp_afi",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_peer_type = {
+  .name = "bgp_peer_type",
+  .type = T_INT,
+};
+
+/*
+ * Protocol connections information
+ */
+
+struct ea_class ea_bgp_in_conn_local_open_msg = {
+  .name = "bgp_in_conn_local_open_msg",
+  .type = T_BYTESTRING,
+};
+
+struct ea_class ea_bgp_in_conn_remote_open_msg = {
+  .name = "bgp_in_conn_remote_open_msg",
+  .type = T_BYTESTRING,
+};
+
+struct ea_class ea_bgp_out_conn_local_open_msg = {
+  .name = "bgp_out_conn_local_open_msg",
+  .type = T_BYTESTRING,
+};
+
+struct ea_class ea_bgp_out_conn_remote_open_msg = {
+  .name = "bgp_out_conn_remote_open_msg",
+  .type = T_BYTESTRING,
+};
+
+struct ea_class ea_bgp_in_conn_state = {
+  .name = "bgp_in_conn_state",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_out_conn_state = {
+  .name = "bgp_out_conn_state",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_in_conn_sk = {
+  .name = "bgp_in_conn_sk",
+  .type = T_OPAQUE,
+};
+
+struct ea_class ea_bgp_out_conn_sk = {
+  .name = "bgp_out_conn_sk",
+  .type = T_OPAQUE,
+};
 
 /*
  *     Protocol extended state information
@@ -1225,6 +1298,31 @@ struct ea_class ea_bgp_state_startup = {
   .type = T_INT,
 };
 
+struct ea_class ea_bgp_close_bmp = {
+  .name = "bgp_close_bmp",
+  .type = T_OPAQUE,
+};
+
+struct ea_class ea_bgp_close_bmp_set = {
+  .name = "bgp_close_bmp_set",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_as4_session = {
+  .name = "bgp_as4_session",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_as4_in_conn = {
+  .name = "bgp_as4_in_conn",
+  .type = T_INT,
+};
+
+struct ea_class ea_bgp_as4_out_conn = {
+  .name = "bgp_as4_out_conn",
+  .type = T_INT,
+};
+
 void
 bgp_register_attrs(void)
 {
@@ -1246,7 +1344,11 @@ bgp_register_attrs(void)
   }
 
   EA_REGISTER_ALL(
-      &ea_bgp_state_startup
+      &ea_bgp_rem_id, &ea_bgp_rem_as, &ea_bgp_loc_as, &ea_bgp_rem_ip, &ea_bgp_peer_type, &ea_bgp_afi,
+      &ea_bgp_in_conn_local_open_msg, &ea_bgp_out_conn_local_open_msg, &ea_bgp_in_conn_remote_open_msg,
+      &ea_bgp_out_conn_remote_open_msg, &ea_bgp_close_bmp, &ea_bgp_close_bmp_set, &ea_bgp_as4_session,
+      &ea_bgp_state_startup, &ea_bgp_in_conn_state, &ea_bgp_out_conn_state,
+      &ea_bgp_in_conn_sk, &ea_bgp_out_conn_sk, &ea_bgp_as4_in_conn, &ea_bgp_as4_out_conn
       );
 }
 
@@ -1892,7 +1994,7 @@ bgp_tx_resend(struct bgp_proto *p, struct bgp_channel *bc)
  */
 
 static void
-bgp_out_item_done(struct lfjour *j, struct lfjour_item *i)
+bgp_out_item_done(struct lfjour *j UNUSED, struct lfjour_item *i UNUSED)
 {}
 
 static struct rt_export_feed *
index be3f643fa268a47f37ea4fb91c1519f60d53a4ae..1a284df8eb48574567cb5d6065d57c6d3ce9b238 100644 (file)
@@ -486,6 +486,23 @@ bgp_close_conn(struct bgp_conn *conn)
   conn->local_open_length = 0;
   conn->remote_open_length = 0;
 
+  ea_list *attr = conn->bgp->p.ea_state;
+  if (conn == &conn->bgp->incoming_conn)
+  {
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_local_open_msg, 0, NULL, 0));
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_remote_open_msg, 0, NULL, 0));
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_sk, 0, NULL, 0));
+  }
+  else
+  {
+    ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_local_open_msg, 0, NULL, 0));
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_remote_open_msg, 0, NULL, 0));
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_sk, 0, NULL, 0));
+  }
+  conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&conn->bgp->p, attr);
+
   mb_free(conn->local_caps);
   conn->local_caps = NULL;
   mb_free(conn->remote_caps);
@@ -640,6 +657,16 @@ bgp_conn_set_state(struct bgp_conn *conn, uint new_state)
     bgp_dump_state_change(conn, conn->state, new_state);
 
   conn->state = new_state;
+
+  if (conn == &conn->bgp->incoming_conn)
+    ea_set_attr(&conn->bgp->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_in_conn_state, 0, new_state));
+  else
+  {
+    ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
+    ea_set_attr(&conn->bgp->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_out_conn_state, 0, new_state));
+  }
+  conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&conn->bgp->p, conn->bgp->p.ea_state);
 }
 
 void
@@ -680,6 +707,9 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
   p->last_error_code = 0;
 
   p->as4_session = conn->as4_session;
+  ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_as4_session, 0, conn->as4_session));
+  p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&conn->bgp->p, conn->bgp->p.ea_state);
 
   p->route_refresh = peer->route_refresh;
   p->enhanced_refresh = local->enhanced_refresh && peer->enhanced_refresh;
@@ -791,11 +821,6 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
 
   bgp_conn_set_state(conn, BS_ESTABLISHED);
   proto_notify_state(&p->p, PS_UP);
-
-#ifdef CONFIG_BMP
-  bmp_peer_up(p, conn->local_open_msg, conn->local_open_length,
-             conn->remote_open_msg, conn->remote_open_length);
-#endif
 }
 
 static void
@@ -809,9 +834,28 @@ bgp_conn_leave_established_state(struct bgp_conn *conn, struct bgp_proto *p)
     bgp_stop(p, 0, NULL, 0);
 
 #ifdef CONFIG_BMP
-  bmp_peer_down(p, p->last_error_class,
-               conn->notify_code, conn->notify_subcode,
-               conn->notify_data, conn->notify_size);
+  struct {
+    struct closing_bgp closing_struct;
+    byte data[conn->notify_size];
+  } to_ea;
+
+  to_ea.closing_struct = (struct closing_bgp) {
+    .err_class = p->last_error_class,
+    .err_code = conn->notify_code,
+    .err_subcode = conn->notify_subcode,
+    .length = conn->notify_size,
+  };
+  memcpy(to_ea.data, conn->notify_data, conn->notify_size);
+
+  ea_set_attr(&p->p.ea_state, EA_LITERAL_STORE_ADATA(&ea_bgp_close_bmp, 0, &to_ea.closing_struct, sizeof(to_ea)));
+  ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_close_bmp_set, 0, 1));
+  p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
+
+  proto_announce_state_later(&p->p, p->p.ea_state);
+
+  //bmp_peer_down(p, p->last_error_class,
+       //      conn->notify_code, conn->notify_subcode,
+       //      conn->notify_data, conn->notify_size);
 #endif
 }
 
@@ -1205,6 +1249,17 @@ bgp_setup_conn(struct bgp_proto *p, struct bgp_conn *conn)
   conn->hold_timer     = tm_new_init(p->p.pool, bgp_hold_timeout,       conn, 0, 0);
   conn->keepalive_timer        = tm_new_init(p->p.pool, bgp_keepalive_timeout, conn, 0, 0);
   conn->send_hold_timer = tm_new_init(p->p.pool, bgp_send_hold_timeout, conn, 0, 0);
+
+  ea_list *attr = conn->bgp->p.ea_state;
+  if (conn == &conn->bgp->incoming_conn)
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_sk, 0, NULL, 0));
+  else
+  {
+    ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_sk, 0, NULL, 0));
+  }
+  conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&p->p, attr);
 }
 
 static void
@@ -1214,6 +1269,24 @@ bgp_setup_sk(struct bgp_conn *conn, sock *s)
   s->err_hook = bgp_sock_err;
   s->fast_rx = 1;
   conn->sk = s;
+
+  struct bgp_conn_sk_ea sk_ea = {
+    .saddr = s->saddr,
+    .daddr = s->daddr,
+    .sport = s->sport,
+    .dport = s->dport
+  };
+
+  ea_list *attr = conn->bgp->p.ea_state;
+  if (conn == &conn->bgp->incoming_conn)
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_sk, 0, (byte*)(&sk_ea), sizeof(sk_ea)));
+  else
+  {
+    ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_sk, 0, (byte*)(&sk_ea), sizeof(sk_ea)));
+  }
+  conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&conn->bgp->p, attr);
 }
 
 static void
@@ -1734,6 +1807,17 @@ bgp_start(struct proto *P)
   p->remote_id = 0;
   p->link_addr = IPA_NONE;
 
+  ea_list *eal = p->p.ea_state;
+  ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id));
+  ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_loc_as, 0, p->local_as));
+  ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_rem_as, 0, p->remote_as));
+  ea_set_attr(&eal, EA_LITERAL_STORE_ADATA(&ea_bgp_rem_ip, 0, &p->remote_ip, sizeof(ip_addr)));
+
+  ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_out_conn_state, 0, BS_IDLE));
+  ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_in_conn_state, 0, BS_IDLE));
+
+  proto_announce_state(&p->p, eal);
+
   /* Lock all channels when in GR recovery mode */
   if (p->p.gr_recovery && p->cf->gr_mode)
   {
@@ -1905,6 +1989,9 @@ bgp_init(struct proto_config *CF)
   /* Add MPLS channel */
   proto_configure_mpls_channel(P, CF, RTS_BGP);
 
+  PST_LOCKED(ts)
+    bgp_state_to_eattr(P, ts->states[P->id]);
+
   return P;
 }
 
@@ -1926,6 +2013,14 @@ bgp_channel_init(struct channel *C, struct channel_config *CF)
 
   if (cf->base_table)
     c->base_table = cf->base_table->table;
+
+  PST_LOCKED(ts)
+  {
+    ea_list *eal = ea_free_later(ts->channels[c->c.id]);
+    ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_afi, 0, c->afi));
+    ts->channels[c->c.id] = ea_lookup_slow(eal, 0, EALS_IN_TABLE);
+  }
+
 }
 
 static int
@@ -2363,6 +2458,11 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
   /* We should update our copy of configuration ptr as old configuration will be freed */
   p->cf = new;
 
+  ea_list *eal = proto_get_state(p->p.id);
+  ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_peer_type, 0, p->cf->peer_type));
+  p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&p->p, eal);
+
   /* Check whether existing connections are compatible with required capabilities */
   struct bgp_conn *ci = &p->incoming_conn;
   if (((ci->state == BS_OPENCONFIRM) || (ci->state == BS_ESTABLISHED)) && !bgp_check_capabilities(ci))
@@ -2566,6 +2666,27 @@ bgp_get_status(struct proto *P, byte *buf)
     bsprintf(buf, "%-14s%s%s", bgp_state_dsc(p), err1, err2);
 }
 
+int
+bgp_state_to_eattr(struct proto *P, struct ea_list *state)
+{
+  struct bgp_proto *p = (struct bgp_proto *) P;
+  ea_set_attr(&state, EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id));
+  ea_set_attr(&state, EA_LITERAL_STORE_ADATA(&ea_bgp_rem_ip, 0, &p->remote_ip, sizeof(ip_addr)));
+  ea_set_attr(&state, EA_LITERAL_EMBEDDED(&ea_bgp_peer_type, 0, p->cf->peer_type));
+  ea_set_attr(&state, EA_LITERAL_EMBEDDED(&ea_bgp_loc_as, 0, p->local_as));
+  ea_set_attr(&state, EA_LITERAL_EMBEDDED(&ea_bgp_rem_as, 0, p->remote_as));
+  ea_set_attr(&state, EA_LITERAL_EMBEDDED(&ea_bgp_as4_session, 0, p->as4_session));
+
+  ea_set_attr(&state, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_local_open_msg, 0, NULL, 0));
+  ea_set_attr(&state, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_remote_open_msg, 0, NULL, 0));
+  ea_set_attr(&state, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_local_open_msg, 0, NULL, 0));
+  ea_set_attr(&state, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_remote_open_msg, 0, NULL, 0));
+
+  ea_set_attr(&state, EA_LITERAL_STORE_ADATA(&ea_bgp_close_bmp, 0, NULL, 0));
+  ea_set_attr(&state, EA_LITERAL_EMBEDDED(&ea_bgp_close_bmp_set, 0, 0));
+  return 1;
+}
+
 static void
 bgp_show_afis(int code, char *s, u32 *afis, uint count)
 {
index 41c6840aa47db507aef7f1257892322d71522750..e6db1114f62eb0256be1caa33a70c2822062d680 100644 (file)
@@ -293,7 +293,7 @@ struct bgp_stats {
 struct bgp_conn {
   struct bgp_proto *bgp;
   struct birdsock *sk;
-  u8 state;                            /* State of connection state machine */
+  u8 state;                            /* State of connection state machine */
   u8 as4_session;                      /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
   u8 ext_messages;                     /* Session uses extended message length */
   u32 received_as;                     /* ASN received in OPEN message */
@@ -319,6 +319,21 @@ struct bgp_conn {
   uint hold_time, keepalive_time, send_hold_time;      /* Times calculated from my and neighbor's requirements */
 };
 
+struct bgp_conn_sk_ea {
+  ip_addr saddr;
+  ip_addr daddr;
+  int sport;
+  int dport;
+};
+
+struct closing_bgp {
+  int err_class;
+  int err_code;
+  int err_subcode;
+  int length;
+  byte data[0];
+};
+
 struct bgp_listen_request {
   node n;                              /* Node in bgp_socket / pending list */
   struct bgp_socket *sock;             /* Assigned socket */
@@ -644,6 +659,7 @@ extern struct rte_owner_class bgp_rte_owner_class;
 eattr *
 bgp_find_attr(ea_list *attrs, uint code);
 
+int bgp_state_to_eattr(struct proto *P, struct ea_list *state);
 void bgp_set_attr_u32(ea_list **to, uint code, uint flags, u32 val);
 void bgp_set_attr_ptr(ea_list **to, uint code, uint flags, const struct adata *ad);
 void bgp_set_attr_data(ea_list **to, uint code, uint flags, void *data, uint len);
@@ -698,6 +714,13 @@ bgp_total_aigp_metric(const rte *e)
   return metric;
 }
 
+/* bgp protocol journal attributes */
+extern struct ea_class ea_bgp_rem_id, ea_bgp_rem_as, ea_bgp_loc_as, ea_bgp_rem_ip, ea_bgp_peer_type, ea_bgp_afi,
+      ea_bgp_in_conn_local_open_msg, ea_bgp_out_conn_local_open_msg, ea_bgp_in_conn_remote_open_msg,
+      ea_bgp_out_conn_remote_open_msg, ea_bgp_close_bmp, ea_bgp_close_bmp_set, ea_bgp_as4_session,
+      ea_bgp_state_startup, ea_bgp_in_conn_state, ea_bgp_out_conn_state,
+      ea_bgp_in_conn_sk, ea_bgp_out_conn_sk, ea_bgp_as4_out_conn, ea_bgp_as4_in_conn;
+
 /* Extended state attributes */
 extern struct ea_class
              ea_bgp_state_startup;
index 10ee4bc0395cc4a39e80c3fcfae57a0b284f62ab..401e2814f66b1cb17a943f056d39b79e11b73188 100644 (file)
@@ -918,6 +918,17 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
   conn->remote_open_msg = bgp_copy_open(p, pkt, len);
   conn->remote_open_length = len - BGP_HEADER_LENGTH;
 
+  ea_list *attr = p->p.ea_state;
+  if (conn == &conn->bgp->incoming_conn)
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_remote_open_msg, 0, conn->remote_open_msg, conn->remote_open_length));
+  else
+  {
+    ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
+    ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_remote_open_msg, 0, conn->remote_open_msg, conn->remote_open_length));
+  }
+  p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&p->p, attr);
+
   if (bgp_read_options(conn, pkt+29, pkt[28], len-29) < 0)
     return;
 
@@ -1048,6 +1059,19 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
   conn->ext_messages = conn->local_caps->ext_messages && caps->ext_messages;
   p->remote_id = id;
 
+  ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id));
+
+  if (conn == &p->incoming_conn)
+    ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_as4_in_conn, 0, conn->as4_session));
+  else
+  {
+    ASSERT_DIE(conn == &p->outgoing_conn);
+    ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_as4_out_conn, 0, conn->as4_session));
+  }
+
+  p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
+  proto_announce_state_later(&p->p, p->p.ea_state);
+
   DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x, AS4 session to %d\n",
       conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, conn->as4_session);
 
@@ -3084,6 +3108,17 @@ bgp_fire_tx(struct bgp_conn *conn)
     conn->local_open_msg = bgp_copy_open(p, buf, end - buf);
     conn->local_open_length = end - buf - BGP_HEADER_LENGTH;
 
+    ea_list *attr = p->p.ea_state;
+    if (conn == &conn->bgp->incoming_conn)
+      ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_local_open_msg, 0, conn->local_open_msg, conn->local_open_length));
+    else
+    {
+      ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
+      ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_local_open_msg, 0, conn->local_open_msg, conn->local_open_length));
+    }
+    p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
+    proto_announce_state_later(&p->p, attr);
+
     return bgp_send(conn, PKT_OPEN, end - buf);
   }
   else if (s & (1 << PKT_KEEPALIVE))