diff options
-rw-r--r-- | proto/bgp/Doc | 3 | ||||
-rw-r--r-- | proto/bgp/attrs.c | 23 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 101 | ||||
-rw-r--r-- | proto/bgp/packets.c | 36 |
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) { |