diff options
author | Martin Mares <mj@ucw.cz> | 2000-03-30 19:39:48 +0200 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 2000-03-30 19:39:48 +0200 |
commit | b552ecc4d7ddb1b960aa26b96ebea95a3af72043 (patch) | |
tree | 48d3c298290975dd6f41d9c41ef0acb1a90eef97 /proto/bgp/packets.c | |
parent | ce0603a6eda81b97d6db021c91b86cb4c920eb04 (diff) | |
download | bird-b552ecc4d7ddb1b960aa26b96ebea95a3af72043.tar bird-b552ecc4d7ddb1b960aa26b96ebea95a3af72043.zip |
Connection state machine works.
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r-- | proto/bgp/packets.c | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index d889671..e530f81 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -26,14 +26,11 @@ bgp_create_notification(struct bgp_conn *conn, byte *buf) buf[1] = conn->notify_subcode; switch (conn->notify_arg_size) { - case 1: - buf[2] = conn->notify_arg; return buf+3; - case 2: - put_u16(buf+2, conn->notify_arg); return buf+4; - case 4: - put_u32(buf+2, conn->notify_arg); return buf+6; - default: - bug("bgp_create_notification: unknown error code size"); + case 0: return buf + 1; + case 1: buf[2] = conn->notify_arg; return buf+3; + case 2: put_u16(buf+2, conn->notify_arg); return buf+4; + case 4: put_u32(buf+2, conn->notify_arg); return buf+6; + default: bug("bgp_create_notification: unknown error code size"); } } @@ -140,6 +137,7 @@ bgp_tx(sock *sk) static void bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) { + struct bgp_conn *other; struct bgp_proto *p = conn->bgp; struct bgp_config *cf = p->cf; unsigned as, hold; @@ -168,8 +166,39 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) if (!id || id == 0xffffffff || id == p->local_id) { bgp_error(conn, 2, 3, id, 0); return; } - /* FIXME: What to do with the other connection??? */ - ASSERT(conn == &p->conn); + /* Check the other connection */ + other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn; + switch (other->state) + { + case BS_IDLE: + break; + case BS_CONNECT: + case BS_ACTIVE: + case BS_OPENSENT: + DBG("BGP: Collision, closing the other connection\n"); + bgp_close_conn(other); + break; + case BS_OPENCONFIRM: + if ((p->local_id < id) == (conn == &p->incoming_conn)) + { + /* Should close the other connection */ + DBG("BGP: Collision, closing the other connection\n"); + bgp_error(other, 6, 0, 0, 0); + break; + } + /* Fall thru */ + case BS_ESTABLISHED: + /* Should close this connection */ + DBG("BGP: Collision, closing this connection\n"); + bgp_error(conn, 6, 0, 0, 0); + return; + default: + bug("bgp_rx_open: Unknown state"); + } + + /* Make this connection primary */ + conn->primary = 1; + p->conn = conn; /* Update our local variables */ if (hold < p->cf->hold_time) @@ -216,7 +245,8 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len) } DBG("BGP: NOTIFICATION %d.%d %08x\n", pkt[19], pkt[20], arg); /* FIXME: Better reporting */ conn->error_flag = 1; - proto_notify_state(&conn->bgp->p, PS_STOP); + if (conn->primary) + proto_notify_state(&conn->bgp->p, PS_STOP); bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE); } |