summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-01-03 12:17:52 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2010-01-03 12:17:52 +0100
commitcf31112f0d7618464097f71228f84bd534f1bc0f (patch)
tree68f7fa93bd2154a16169b4db3dc9c16e51c2e84f /proto
parent610bb3cff05f6d5b09c77724bc97295b809d15e2 (diff)
Implements MRTdump feature.
Diffstat (limited to 'proto')
-rw-r--r--proto/bgp/bgp.c29
-rw-r--r--proto/bgp/bgp.h8
-rw-r--r--proto/bgp/packets.c105
-rw-r--r--proto/ospf/iface.c9
-rw-r--r--proto/ospf/neighbor.c6
-rw-r--r--proto/ospf/ospf.c4
-rw-r--r--proto/ospf/topology.c6
7 files changed, 139 insertions, 28 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 3cbcb6d7..215dc817 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -313,6 +313,22 @@ bgp_stop(struct bgp_proto *p, unsigned subcode)
ev_schedule(p->event);
}
+static inline void
+bgp_conn_set_state(struct bgp_conn *conn, unsigned new_state)
+{
+ if (conn->bgp->p.mrtdump & MD_STATES)
+ mrt_dump_bgp_state_change(conn, conn->state, new_state);
+
+ conn->state = new_state;
+}
+
+void
+bgp_conn_enter_openconfirm_state(struct bgp_conn *conn)
+{
+ /* Really, most of the work is done in bgp_rx_open(). */
+ bgp_conn_set_state(conn, BS_OPENCONFIRM);
+}
+
void
bgp_conn_enter_established_state(struct bgp_conn *conn)
{
@@ -325,7 +341,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
p->last_error_class = 0;
p->last_error_code = 0;
bgp_attr_init(conn->bgp);
- conn->state = BS_ESTABLISHED;
+ bgp_conn_set_state(conn, BS_ESTABLISHED);
proto_notify_state(&p->p, PS_UP);
}
@@ -345,7 +361,7 @@ bgp_conn_enter_close_state(struct bgp_conn *conn)
struct bgp_proto *p = conn->bgp;
int os = conn->state;
- conn->state = BS_CLOSE;
+ bgp_conn_set_state(conn, BS_CLOSE);
tm_stop(conn->hold_timer);
tm_stop(conn->keepalive_timer);
conn->sk->rx_hook = NULL;
@@ -361,7 +377,7 @@ bgp_conn_enter_idle_state(struct bgp_conn *conn)
int os = conn->state;
bgp_close_conn(conn);
- conn->state = BS_IDLE;
+ bgp_conn_set_state(conn, BS_IDLE);
ev_schedule(p->event);
if (os == BS_ESTABLISHED)
@@ -374,13 +390,14 @@ bgp_send_open(struct bgp_conn *conn)
conn->start_state = conn->bgp->start_state;
conn->want_as4_support = conn->bgp->cf->enable_as4 && (conn->start_state != BSS_CONNECT_NOCAP);
conn->peer_as4_support = 0; // Default value, possibly changed by receiving capability.
+ conn->advertised_as = 0;
DBG("BGP: Sending open\n");
conn->sk->rx_hook = bgp_rx;
conn->sk->tx_hook = bgp_tx;
tm_stop(conn->connect_retry_timer);
bgp_schedule_packet(conn, PKT_OPEN);
- conn->state = BS_OPENSENT;
+ bgp_conn_set_state(conn, BS_OPENSENT);
bgp_start_timer(conn->hold_timer, conn->bgp->cf->initial_hold_time);
}
@@ -490,7 +507,7 @@ bgp_active(struct bgp_proto *p)
BGP_TRACE(D_EVENTS, "Connect delayed by %d seconds", delay);
bgp_setup_conn(p, conn);
- conn->state = BS_ACTIVE;
+ bgp_conn_set_state(conn, BS_ACTIVE);
bgp_start_timer(conn->connect_retry_timer, delay);
}
@@ -539,7 +556,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
BGP_TRACE(D_EVENTS, "Connecting to %I from local address %I", s->daddr, s->saddr);
bgp_setup_conn(p, conn);
bgp_setup_sk(p, conn, s);
- conn->state = BS_CONNECT;
+ bgp_conn_set_state(conn, BS_CONNECT);
if (sk_open(s))
{
bgp_sock_err(s, 0);
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 7cbd6557..24d69741 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -138,6 +138,7 @@ void bgp_check(struct bgp_config *c);
void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
void bgp_close_conn(struct bgp_conn *c);
void bgp_update_startup_delay(struct bgp_proto *p);
+void bgp_conn_enter_openconfirm_state(struct bgp_conn *conn);
void bgp_conn_enter_established_state(struct bgp_conn *conn);
void bgp_conn_enter_close_state(struct bgp_conn *conn);
void bgp_conn_enter_idle_state(struct bgp_conn *conn);
@@ -189,6 +190,7 @@ inline static void bgp_attach_attr_ip(struct ea_list **to, struct linpool *pool,
/* packets.c */
+void mrt_dump_bgp_state_change(struct bgp_conn *conn, unsigned old, unsigned new);
void bgp_schedule_packet(struct bgp_conn *conn, int type);
void bgp_kick_tx(void *vconn);
void bgp_tx(struct birdsock *sk);
@@ -294,4 +296,10 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
#define BGP_AF_IPV4 1
#define BGP_AF_IPV6 2
+#ifdef IPV6
+#define BGP_AF BGP_AF_IPV6
+#else
+#define BGP_AF BGP_AF_IPV4
+#endif
+
#endif
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 91b47927..03cc4ee0 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -13,6 +13,7 @@
#include "nest/protocol.h"
#include "nest/route.h"
#include "nest/attrs.h"
+#include "nest/mrtdump.h"
#include "conf/conf.h"
#include "lib/unaligned.h"
#include "lib/socket.h"
@@ -23,6 +24,84 @@
static struct rate_limit rl_rcv_update, rl_snd_update;
+/*
+ * MRT Dump format is not semantically specified.
+ * We will use these values in appropriate fields:
+ *
+ * Local AS, Remote AS - configured AS numbers for given BGP instance.
+ * Local IP, Remote IP - IP addresses of the TCP connection (0 if no connection)
+ *
+ * We dump two kinds of MRT messages: STATE_CHANGE (for BGP state
+ * changes) and MESSAGE (for received BGP messages).
+ *
+ * STATE_CHANGE uses always AS4 variant, but MESSAGE uses AS4 variant
+ * only when AS4 session is established and even in that case MESSAGE
+ * does not use AS4 variant for initial OPEN message. This strange
+ * behavior is here for compatibility with Quagga and Bgpdump,
+ */
+
+static byte *
+mrt_put_bgp4_hdr(byte *buf, struct bgp_conn *conn, int as4)
+{
+ struct bgp_proto *p = conn->bgp;
+ ip_addr local_addr;
+
+ if (as4)
+ {
+ put_u32(buf+0, p->remote_as);
+ put_u32(buf+4, p->local_as);
+ buf+=8;
+ }
+ else
+ {
+ put_u16(buf+0, (p->remote_as <= 0xFFFF) ? p->remote_as : AS_TRANS);
+ put_u16(buf+2, (p->local_as <= 0xFFFF) ? p->local_as : AS_TRANS);
+ buf+=4;
+ }
+
+ put_u16(buf+0, p->neigh->iface->index);
+ put_u16(buf+2, BGP_AF);
+ buf+=4;
+ buf = ipa_put_addr(buf, conn->sk ? conn->sk->daddr : IPA_NONE);
+ buf = ipa_put_addr(buf, conn->sk ? conn->sk->saddr : IPA_NONE);
+
+ return buf;
+}
+
+static void
+mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
+{
+ byte buf[BGP_MAX_PACKET_LENGTH + 128];
+ byte *bp = buf + MRTDUMP_HDR_LENGTH;
+ int as4 = conn->bgp->as4_session;
+
+ bp = mrt_put_bgp4_hdr(bp, conn, as4);
+ memcpy(bp, pkt, len);
+ bp += len;
+ mrt_dump_message(&conn->bgp->p, BGP4MP, as4 ? BGP4MP_MESSAGE_AS4 : BGP4MP_MESSAGE,
+ buf, bp-buf);
+}
+
+static inline u16
+convert_state(unsigned state)
+{
+ /* Convert state from our BS_* values to values used in MRTDump */
+ return (state == BS_CLOSE) ? 1 : state + 1;
+}
+
+void
+mrt_dump_bgp_state_change(struct bgp_conn *conn, unsigned old, unsigned new)
+{
+ byte buf[128];
+ byte *bp = buf + MRTDUMP_HDR_LENGTH;
+
+ bp = mrt_put_bgp4_hdr(bp, conn, 1);
+ put_u16(bp+0, convert_state(old));
+ put_u16(bp+2, convert_state(new));
+ bp += 4;
+ mrt_dump_message(&conn->bgp->p, BGP4MP, BGP4MP_STATE_CHANGE_AS4, buf, bp-buf);
+}
+
static byte *
bgp_create_notification(struct bgp_conn *conn, byte *buf)
{
@@ -403,13 +482,8 @@ bgp_create_route_refresh(struct bgp_conn *conn, byte *buf)
struct bgp_proto *p = conn->bgp;
BGP_TRACE(D_PACKETS, "Sending ROUTE-REFRESH");
-#ifdef IPV6
- *buf++ = 0; /* AFI IPv6 */
- *buf++ = BGP_AF_IPV6;
-#else
- *buf++ = 0; /* AFI IPv4 */
- *buf++ = BGP_AF_IPV4;
-#endif
+ *buf++ = 0;
+ *buf++ = BGP_AF;
*buf++ = 0; /* RFU */
*buf++ = 1; /* and SAFI 1 */
return buf;
@@ -552,12 +626,13 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
switch (opt[0])
{
- case 2:
+ case 2: /* Route refresh capability, RFC 2918 */
if (cl != 0)
goto err;
conn->peer_refresh_support = 1;
break;
- case 65:
+
+ case 65: /* AS4 capability, RFC 4893 */
if (cl != 4)
goto err;
conn->peer_as4_support = 1;
@@ -709,7 +784,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
bgp_schedule_packet(conn, PKT_KEEPALIVE);
bgp_start_timer(conn->hold_timer, conn->hold_time);
- conn->state = BS_OPENCONFIRM;
+ bgp_conn_enter_openconfirm_state(conn);
}
#define DECODE_PREFIX(pp, ll) do { \
@@ -1160,8 +1235,14 @@ bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len)
static void
bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
{
- DBG("BGP: Got packet %02x (%d bytes)\n", pkt[18], len);
- switch (pkt[18])
+ byte type = pkt[18];
+
+ DBG("BGP: Got packet %02x (%d bytes)\n", type, len);
+
+ if (conn->bgp->p.mrtdump & MD_MESSAGES)
+ mrt_dump_bgp_packet(conn, pkt, len);
+
+ switch (type)
{
case PKT_OPEN: return bgp_rx_open(conn, pkt, len);
case PKT_UPDATE: return bgp_rx_update(conn, pkt, len);
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 8db086ec..e514a5d5 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -152,9 +152,12 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) &&
((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)))
{
- /* FIXME some error handing ? */
- sk_join_group(ifa->sk, AllDRouters);
- ifa->dr_up = 1;
+ if (!ifa->dr_up == 0)
+ {
+ /* FIXME some error handing ? */
+ sk_join_group(ifa->sk, AllDRouters);
+ ifa->dr_up = 1;
+ }
}
else if (ifa->dr_up)
{
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index ba8d7b98..0411d48e 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -623,9 +623,9 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
pos = "ptp ";
- cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s", n->rid, n->priority,
- ospf_ns[n->state], pos, etime, n->ip,
- (ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name));
+ cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
+ ospf_ns[n->state], pos, etime,
+ (ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name), n->ip);
}
static void
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index 9ebef6b7..232803d7 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -917,8 +917,8 @@ ospf_sh_neigh(struct proto *p, char *iff)
}
cli_msg(-1013, "%s:", p->name);
- cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-12s\t%-10s", "Router ID", "Pri",
- " State", "DTime", "Router IP", "Interface");
+ cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %-12s", "Router ID", "Pri",
+ " State", "DTime", "Interface", "Router IP");
WALK_LIST(ifa, po->iface_list)
if ((iff == NULL) || patmatch(iff, ifa->iface->name))
WALK_LIST(n, ifa->neigh_list)
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 3ca5e774..870c0bc2 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -433,9 +433,11 @@ originate_rt_lsa(struct ospf_area *oa)
#ifdef OSPFv2
lsa.options = oa->options;
-#endif
-
lsa.id = po->router_id;
+#else /* OSPFv3 */
+ lsa.id = 0;
+#endif
+
lsa.rt = po->router_id;
lsa.sn = oa->rt ? (oa->rt->lsa.sn + 1) : LSA_INITSEQNO;
u32 dom = oa->areaid;