]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Construction of BGP packets.
authorMartin Mares <mj@ucw.cz>
Tue, 21 Mar 2000 15:53:50 +0000 (15:53 +0000)
committerMartin Mares <mj@ucw.cz>
Tue, 21 Mar 2000 15:53:50 +0000 (15:53 +0000)
proto/bgp/Makefile
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c

index 0f0ba278f7b9b5e948053a18549bdbcb5436df63..a634cf0de166a080243475fe828a7dc7098c38ef 100644 (file)
@@ -1,4 +1,4 @@
-source=bgp.c attrs.c
+source=bgp.c attrs.c packets.c
 root-rel=../../
 dir-name=proto/bgp
 
index 40915a40871a6dc97c03c0d38f13fc29339cc8c8..c52e8bd0b144c6cbfa9dc3f5f336d9eb4f678ac0 100644 (file)
@@ -78,21 +78,13 @@ bgp_start_timer(timer *t, int value)
   tm_start(t, value);
 }
 
-static int
-bgp_rx(sock *sk, int size)
-{
-  DBG("BGP: Got %d bytes\n", size);
-
-  return 1;                            /* Start from the beginning */
-}
-
 static void
 bgp_send_open(struct bgp_conn *conn)
 {
   DBG("BGP: Sending open\n");
   conn->sk->rx_hook = bgp_rx;
   tm_stop(conn->connect_retry_timer);
-  /* FIXME */
+  bgp_schedule_packet(conn, PKT_OPEN);
   conn->state = BS_OPENSENT;
 }
 
@@ -174,14 +166,14 @@ bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
   s->data = conn;
   s->ttl = p->cf->multihop ? : 1;
   s->rbsize = BGP_RX_BUFFER_SIZE;
-#if 0
+  s->tbsize = BGP_TX_BUFFER_SIZE;
   s->tx_hook = bgp_tx;
-#endif
   s->err_hook = bgp_err;
   s->tos = IP_PREC_INTERNET_CONTROL;
 
   conn->bgp = p;
   conn->sk = s;
+  conn->packets_to_send = 0;
 
   t = conn->connect_retry_timer = tm_new(p->p.pool);
   t->hook = bgp_connect_timeout;
index 8e2e8dfec646e94dae8ebf779e970bbdc956fa2d..3ddf6194f59fc21cfd33b63b55890932dfca5cd9 100644 (file)
@@ -22,10 +22,13 @@ struct bgp_config {
 struct bgp_conn {
   struct bgp_proto *bgp;
   struct birdsock *sk;
-  int state;                           /* State of connection state machine */
+  unsigned int state;                  /* State of connection state machine */
   struct timer *connect_retry_timer;
   struct timer *hold_timer;
   struct timer *keepalive_timer;
+  unsigned int packets_to_send;                /* Bitmap of packet types to be sent */
+  unsigned int notify_code, notify_subcode, notify_arg, notify_arg_size;
+  unsigned int error_flag;             /* Error state, ignore all input */
 };
 
 struct bgp_proto {
@@ -42,8 +45,12 @@ struct bgp_proto {
   struct object_lock *lock;            /* Lock for neighbor connection */
 };
 
-#define BGP_PORT 179
-#define BGP_RX_BUFFER_SIZE 4096
+#define BGP_PORT               179
+#define BGP_VERSION            4
+#define BGP_HEADER_LENGTH      19
+#define BGP_MAX_PACKET_LENGTH  4096
+#define BGP_RX_BUFFER_SIZE     4096
+#define BGP_TX_BUFFER_SIZE     BGP_MAX_PACKET_LENGTH
 
 void bgp_check(struct bgp_config *c);
 
@@ -51,12 +58,17 @@ void bgp_check(struct bgp_config *c);
 
 /* packets.c */
 
+void bgp_schedule_packet(struct bgp_conn *conn, int type);
+void bgp_tx(struct birdsock *sk);
+int bgp_rx(struct birdsock *sk, int size);
+
 /* Packet types */
 
 #define PKT_OPEN               0x01
 #define PKT_UPDATE             0x02
 #define PKT_NOTIFICATION       0x03
 #define PKT_KEEPALIVE          0x04
+#define PKT_SCHEDULE_CLOSE     0x1f    /* Used internally to schedule socket close */
 
 /* Attributes */
 
index a5f52b88045a218e924b6eb18e4acf73f2cff62e..b3b25f47ac77ff5c55337660d199e0db45179bf8 100644 (file)
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
+#define LOCAL_DEBUG
+
 #include "nest/bird.h"
 #include "nest/iface.h"
 #include "nest/protocol.h"
 #include "nest/route.h"
 #include "conf/conf.h"
+#include "lib/unaligned.h"
+#include "lib/socket.h"
 
 #include "bgp.h"
+
+static byte *
+bgp_create_notification(struct bgp_conn *conn, byte *buf)
+{
+  DBG("BGP: Sending notification: code=%d, sub=%d, arg=%d:%d\n", conn->notify_code, conn->notify_subcode, conn->notify_arg, conn->notify_arg_size);
+  buf[0] = conn->notify_code;
+  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");
+    }
+}
+
+static byte *
+bgp_create_open(struct bgp_conn *conn, byte *buf)
+{
+  DBG("BGP: Sending open\n");
+  buf[0] = BGP_VERSION;
+  put_u16(buf+1, conn->bgp->local_as);
+  put_u16(buf+3, conn->bgp->cf->hold_time);
+  put_u32(buf+5, conn->bgp->local_id);
+  buf[9] = 0;                          /* No optional parameters */
+  return buf+10;
+}
+
+static byte *
+bgp_create_update(struct bgp_conn *conn, byte *buf)
+{
+  DBG("BGP: Sending update\n");
+  bug("Don't know how to create updates");
+}
+
+static void
+bgp_create_header(byte *buf, unsigned int len, unsigned int type)
+{
+  memset(buf, 0xff, 16);               /* Marker */
+  put_u16(buf+16, len);
+  buf[18] = type;
+}
+
+static void
+bgp_fire_tx(struct bgp_conn *conn)
+{
+  unsigned int s = conn->packets_to_send;
+  sock *sk = conn->sk;
+  byte *buf = sk->tbuf;
+  byte *pkt = buf + BGP_HEADER_LENGTH;
+  byte *end;
+  int type;
+
+  if (s & (1 << PKT_SCHEDULE_CLOSE))
+    {
+      conn->packets_to_send = 0;
+      bug("Scheduled close");          /* FIXME */
+    }
+  if (s & (1 << PKT_NOTIFICATION))
+    {
+      s = 1 << PKT_SCHEDULE_CLOSE;
+      type = PKT_NOTIFICATION;
+      end = bgp_create_notification(conn, pkt);
+    }
+  else if (s & (1 << PKT_KEEPALIVE))
+    {
+      s &= ~(1 << PKT_KEEPALIVE);
+      type = PKT_KEEPALIVE;
+      end = pkt;                       /* Keepalives carry no data */
+      DBG("BGP: Sending keepalive\n");
+    }
+  else if (s & (1 << PKT_OPEN))
+    {
+      s &= ~(1 << PKT_OPEN);
+      type = PKT_OPEN;
+      end = bgp_create_open(conn, pkt);
+    }
+  else if (s & (1 << PKT_UPDATE))
+    {
+      end = bgp_create_update(conn, pkt);
+      type = PKT_UPDATE;
+      if (!end)
+       {
+         conn->packets_to_send = 0;
+         return;
+       }
+    }
+  else
+    return;
+  conn->packets_to_send = s;
+  bgp_create_header(buf, end - buf, type);
+  sk_send(sk, end - buf);
+}
+
+void
+bgp_schedule_packet(struct bgp_conn *conn, int type)
+{
+  DBG("BGP: Scheduling packet type %d\n", type);
+  conn->packets_to_send |= 1 << type;
+  if (conn->sk->tpos != conn->sk->tbuf)
+    bgp_fire_tx(conn);
+}
+
+void
+bgp_tx(sock *sk)
+{
+  struct bgp_conn *conn = sk->data;
+
+  DBG("BGP: TX hook\n");
+  bgp_fire_tx(conn);
+}
+
+int
+bgp_rx(sock *sk, int size)
+{
+  struct bgp_conn *conn = sk->data;
+  byte *pkt_start = sk->rbuf;
+  byte *end = pkt_start + size;
+
+  DBG("BGP: RX hook: Got %d bytes\n", size);
+  while (end >= pkt_start + BGP_HEADER_LENGTH)
+    {
+      if (conn->error_flag)
+       return 1;
+      bug("Incoming packets not handled"); /* FIXME */
+    }
+  if (pkt_start != sk->rbuf)
+    {
+      memmove(sk->rbuf, pkt_start, end - pkt_start);
+      sk->rpos = sk->rbuf + (end - pkt_start);
+    }
+  return 0;
+}