summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--proto/bgp/Doc3
-rw-r--r--proto/bgp/attrs.c23
-rw-r--r--proto/bgp/bgp.c101
-rw-r--r--proto/bgp/packets.c36
4 files changed, 163 insertions, 0 deletions
diff --git a/proto/bgp/Doc b/proto/bgp/Doc
index e69de29..6432d1a 100644
--- a/proto/bgp/Doc
+++ b/proto/bgp/Doc
@@ -0,0 +1,3 @@
+S bgp.c
+S packets.c
+S attrs.c
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index b074eb2..82a180a 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -170,6 +170,17 @@ bgp_attach_attr(ea_list **to, struct linpool *pool, unsigned attr, unsigned val)
return bgp_set_attr(a->attrs, pool, attr, val);
}
+/**
+ * bgp_encode_attrs - encode BGP attributes
+ * @w: buffer
+ * @attrs: a list of extended attributes
+ * @remains: remaining space in the buffer
+ *
+ * The bgp_encode_attrs() function takes a list of extended attributes
+ * and converts it to its BGP representation (a part of an Update message).
+ *
+ * Result: Length of the attribute block generated.
+ */
unsigned int
bgp_encode_attrs(byte *w, ea_list *attrs, int remains)
{
@@ -715,6 +726,18 @@ bgp_path_loopy(struct bgp_proto *p, eattr *a)
return 0;
}
+/**
+ * bgp_decode_attrs - check and decode BGP attributes
+ * @conn: connection
+ * @attr: start of attribute block
+ * @len: length of attribute block
+ * @pool: linear pool to make all the allocations in
+ * @mandatory: 1 iff presence of mandatory attributes has to be checked
+ *
+ * This function takes a BGP attribute block (a part of an Update message), checks
+ * its consistency and converts it to a list of BIRD route attributes represented
+ * by a &rta.
+ */
struct rta *
bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct linpool *pool, int mandatory)
{
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 610436f..243942f 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -6,6 +6,53 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
+/**
+ * DOC: Border Gateway Protocol
+ *
+ * The BGP protocol is implemented in three parts: |bgp.c| which takes care of the
+ * connection and most of the interface with BIRD core, |packets.c| handling
+ * both incoming and outgoing BGP packets and |attrs.c| containing functions for
+ * manipulation with BGP attribute lists.
+ *
+ * As opposed to the other existing routing daemons, BIRD has a sophisticated core
+ * architecture which is able to keep all the information needed by BGP in the
+ * primary routing table, therefore no complex data structures like a central
+ * BGP table are needed. This increases memory footprint of a BGP router with
+ * many connections, but not too much and, which is more important, it makes
+ * BGP much easier to implement.
+ *
+ * Each instance of BGP (corresponding to one BGP peer) is described by a &bgp_proto
+ * structure to which are attached individual connections represented by &bgp_connection
+ * (usually, there exists only one connection, but during BGP session setup, there
+ * can be more of them). The connections are handled according to the BGP state machine
+ * defined in the RFC with all the timers and all the parameters configurable.
+ *
+ * In incoming direction, we listen on the connection's socket and each time we receive
+ * some input, we pass it to bgp_rx(). It decodes packet headers and the markers and
+ * passes complete packets to bgp_rx_packet() which distributes the packet according
+ * to its type.
+ *
+ * In outgoing direction, we gather all the routing updates and sort them to buckets
+ * (&bgp_bucket) according to their attributes (we keep a hash table for fast comparison
+ * of &rta's and a &fib which helps us to find if we already have another route for
+ * the same destination queued for sending, so that we can replace it with the new one
+ * immediately instead of sending both updates). There also exists a special bucket holding
+ * all the route withdrawals which cannot be queued anywhere else as they don't have any
+ * attributes. If we have any packet to send (due to either new routes or the connection
+ * tracking code wanting to send a Open, KeepAlive or Notification message), we call
+ * bgp_schedule_packet() which sets the corresponding bit in a @packet_to_send
+ * bit field in &bgp_conn and as soon as the transmit socket buffer becomes empty,
+ * we call bgp_fire_tx(). It inspects state of all the packet type bits and calls
+ * the corresponding bgp_create_xx() functions, eventually rescheduling the same packet
+ * type if we have more data of the same type to send.
+ *
+ * The processing of attributes consists of two functions: bgp_decode_attrs() for checking
+ * of the attribute blocks and translating them to the language of BIRD's extended attributes
+ * and bgp_encode_attrs() which does the converse. Both functions are built around a
+ * @bgp_attr_table array describing all important characteristics of all known attributes.
+ * Unknown transitive attributes are attached to the route as %EAF_TYPE_OPAQUE byte streams.
+ */
+
#undef LOCAL_DEBUG
#include "nest/bird.h"
@@ -42,6 +89,15 @@ bgp_close(struct bgp_proto *p)
}
}
+/**
+ * bgp_start_timer - start a BGP timer
+ * @t: timer
+ * @value: time to fire (0 to disable the timer)
+ *
+ * This functions calls tm_start() on @t with time @value and the
+ * amount of randomization suggested by the BGP standard. Please use
+ * it for all BGP timers.
+ */
void
bgp_start_timer(timer *t, int value)
{
@@ -55,6 +111,19 @@ bgp_start_timer(timer *t, int value)
tm_stop(t);
}
+/**
+ * bgp_close_conn - close a BGP connection
+ * @conn: connection to close
+ *
+ * This function takes a connection described by the &bgp_conn structure,
+ * closes its socket and frees all resources associated with it.
+ *
+ * If the connection is being closed due to a protocol error, adjust
+ * the connection restart timer as well according to the error recovery
+ * policy set in the configuration.
+ *
+ * If the connection was marked as primary, it shuts down the protocol as well.
+ */
void
bgp_close_conn(struct bgp_conn *conn)
{
@@ -231,6 +300,14 @@ bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
conn->sk = s;
}
+/**
+ * bgp_connect - initiate an outgoing connection
+ * @p: BGP instance
+ *
+ * The bgp_connect() function creates a new &bgp_conn and initiates
+ * a TCP connection to the peer. The rest of connection setup is governed
+ * by the BGP state machine as described in the standard.
+ */
static void
bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing connection */
{
@@ -279,6 +356,18 @@ bgp_initiate(struct bgp_proto *p)
bgp_connect(p);
}
+/**
+ * bgp_incoming_connection - handle an incoming connection
+ * @sk: TCP socket
+ * @dummy: unused
+ *
+ * This function serves as a socket hook for accepting of new BGP
+ * connections. It searches a BGP instance corresponding to the peer
+ * which has connected and if such an instance exists, it creates a
+ * &bgp_conn structure, attaches it to the instance and either sends
+ * an Open message or (if there already is an active connection) it
+ * closes the new connection by sending a Notification message.
+ */
static int
bgp_incoming_connection(sock *sk, int dummy)
{
@@ -473,6 +562,18 @@ bgp_init(struct proto_config *C)
return P;
}
+/**
+ * bgp_error - report a protocol error
+ * @c: connection
+ * @code: error code (according to the RFC)
+ * @subcode: error subcode
+ * @data: data to be passed in the Notification message
+ * @len: length of the data
+ *
+ * bgp_error() sends a notification packet to tell the other side that a protocol
+ * error has occured (including the data considered erroneous if possible) and
+ * closes the connection.
+ */
void
bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len)
{
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 820d8d3..ffee9f7 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -236,6 +236,16 @@ bgp_create_header(byte *buf, unsigned int len, unsigned int type)
buf[18] = type;
}
+/**
+ * bgp_fire_tx - transmit packets
+ * @conn: connection
+ *
+ * Whenever the transmit buffers of the underlying TCP connection
+ * are free and we have any packets queued for sending, the socket functions
+ * call bgp_fire_tx() which takes care of selecting the highest priority packet
+ * queued (Notification > Keepalive > Open > Update), assembling its header
+ * and body and sending it to the connection.
+ */
static int
bgp_fire_tx(struct bgp_conn *conn)
{
@@ -295,6 +305,13 @@ bgp_fire_tx(struct bgp_conn *conn)
return sk_send(sk, end - buf);
}
+/**
+ * bgp_schedule_packet - schedule a packet for transmission
+ * @conn: connection
+ * @type: packet type
+ *
+ * Schedule a packet of type @type to be sent as soon as possible.
+ */
void
bgp_schedule_packet(struct bgp_conn *conn, int type)
{
@@ -770,6 +787,15 @@ bgp_rx_keepalive(struct bgp_conn *conn, byte *pkt, unsigned len)
}
}
+/**
+ * bgp_rx_packet - handle a received packet
+ * @conn: BGP connection
+ * @pkt: start of the packet
+ * @len: packet size
+ *
+ * bgp_rx_packet() takes a newly received packet and calls the corresponding
+ * packet handler according to the packet type.
+ */
static void
bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
{
@@ -784,6 +810,16 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
}
}
+/**
+ * bgp_rx - handle received data
+ * @sk: socket
+ * @size: amount of data received
+ *
+ * bgp_rx() is called by the socket layer whenever new data arrive from
+ * the underlying TCP connection. It assembles the data fragments to packets,
+ * checks their headers and framing and passes complete packets to
+ * bgp_rx_packet().
+ */
int
bgp_rx(sock *sk, int size)
{