From 0332b951ceff2f991bd9fe87d169dc5e6fe93e02 Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Thu, 28 Jul 2011 23:22:51 +0200 Subject: Added reliability layer documentation Signed-off-by: Adriaan de Jong Acked-by: James Yonan Signed-off-by: David Sommerseth --- doc_reliable.h | 49 +++++++ reliable.h | 445 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 430 insertions(+), 64 deletions(-) create mode 100644 doc_reliable.h diff --git a/doc_reliable.h b/doc_reliable.h new file mode 100644 index 0000000..5264906 --- /dev/null +++ b/doc_reliable.h @@ -0,0 +1,49 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2010 Fox Crypto B.V. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file + * Reliability Layer module documentation file. + */ + +/** + * @defgroup reliable Reliability Layer module + * + * The Reliability Layer is part of OpenVPN's control channel. It + * provides a reliable and sequential transport mechanism for control + * channel messages between OpenVPN peers. This module forms the + * interface between the \link external_multiplexer External + * Multiplexer\endlink and the \link control_tls Control Channel TLS + * module\endlink. + * + * @par UDP or TCP as VPN tunnel transport + * + * This is especially important when OpenVPN is configured to communicate + * over UDP, because UDP does not offer a reliable and sequential + * transport. OpenVPN endpoints can also communicate over TCP which does + * provide a reliable and sequential transport. In both cases, using UDP + * or TCP as an external transport, the internal Reliability Layer is + * active. + */ diff --git a/reliable.h b/reliable.h index 9cf8eec..086761f 100644 --- a/reliable.h +++ b/reliable.h @@ -22,11 +22,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - * This routines implement a reliability layer on top of UDP, - * so that TLS can be run over UDP. + +/** + * @file + * Reliability Layer module header file. */ + #if defined(USE_CRYPTO) && defined(USE_SSL) #ifndef RELIABLE_H @@ -38,48 +40,35 @@ #include "session_id.h" #include "mtu.h" +/** @addtogroup reliable + * @{ */ + + #define EXPONENTIAL_BACKOFF -#define RELIABLE_ACK_SIZE 8 +#define RELIABLE_ACK_SIZE 8 /**< The maximum number of packet IDs + * waiting to be acknowledged which can + * be stored in one \c reliable_ack + * structure. */ + +#define RELIABLE_CAPACITY 8 /**< The maximum number of packets that + * the reliability layer for one VPN + * tunnel in one direction can store. */ +/** + * The acknowledgment structure in which packet IDs are stored for later + * acknowledgment. + */ struct reliable_ack { int len; packet_id_type packet_id[RELIABLE_ACK_SIZE]; }; -/* no active buffers? */ -static inline bool -reliable_ack_empty (struct reliable_ack *ack) -{ - return !ack->len; -} - -/* get a packet_id from buf */ -bool reliable_ack_read_packet_id (struct buffer *buf, packet_id_type *pid); - -/* acknowledge a packet_id by adding it to a struct reliable_ack */ -bool reliable_ack_acknowledge_packet_id (struct reliable_ack *ack, packet_id_type pid); - -/* read a packet ID acknowledgement record from buf */ -bool reliable_ack_read (struct reliable_ack *ack, - struct buffer *buf, const struct session_id *sid); - -/* write a packet ID acknowledgement record to buf */ -bool reliable_ack_write (struct reliable_ack *ack, - struct buffer *buf, - const struct session_id *sid, int max, bool prepend); - -/* print a reliable ACK record coming off the wire */ -const char *reliable_ack_print (struct buffer *buf, bool verbose, struct gc_arena *gc); - -/* add to extra_frame the maximum number of bytes we will need for reliable_ack_write */ -void reliable_ack_adjust_frame_parameters (struct frame* frame, int max); - -void reliable_ack_debug_print (const struct reliable_ack *ack, char *desc); - -#define RELIABLE_CAPACITY 8 - +/** + * The structure in which the reliability layer stores a single incoming + * or outgoing packet. + */ struct reliable_entry { bool active; @@ -90,6 +79,10 @@ struct reliable_entry struct buffer buf; }; +/** + * The reliability layer storage structure for one VPN tunnel's control + * channel in one direction. + */ struct reliable { int size; @@ -100,64 +93,388 @@ struct reliable struct reliable_entry array[RELIABLE_CAPACITY]; }; -void reliable_debug_print (const struct reliable *rel, char *desc); -/* set sending timeout (after this time we send again until ACK) */ -static inline void -reliable_set_timeout (struct reliable *rel, interval_t timeout) +/**************************************************************************/ +/** @name Functions for processing incoming acknowledgments + * @{ */ + +/** + * Read an acknowledgment record from a received packet. + * + * This function reads the packet ID acknowledgment record from the packet + * contained in \a buf. If the record contains acknowledgments, these are + * stored in \a ack. This function also compares the packet's session ID + * with the expected session ID \a sid, which should be equal. + * + * @param ack The acknowledgment structure in which received + * acknowledgments are to be stored. + * @param buf The buffer containing the packet. + * @param sid The expected session ID to compare to the session ID in + * the packet. + * + * @return + * @li True, if processing was successful. + * @li False, if an error occurs during processing. + */ +bool reliable_ack_read (struct reliable_ack *ack, + struct buffer *buf, const struct session_id *sid); + +/** + * Remove acknowledged packets from a reliable structure. + * + * @param rel The reliable structure storing sent packets. + * @param ack The acknowledgment structure containing received + * acknowledgments. + */ +void reliable_send_purge (struct reliable *rel, struct reliable_ack *ack); + +/** @} name Functions for processing incoming acknowledgments */ + + +/**************************************************************************/ +/** @name Functions for processing outgoing acknowledgments + * @{ */ + +/** + * Check whether an acknowledgment structure contains any + * packet IDs to be acknowledged. + * + * @param ack The acknowledgment structure to check. + * + * @return + * @li True, if the acknowledgment structure is empty. + * @li False, if there are packet IDs to be acknowledged. + */ +static inline bool +reliable_ack_empty (struct reliable_ack *ack) { - rel->initial_timeout = timeout; + return !ack->len; } +/** + * Write a packet ID acknowledgment record to a buffer. + * + * @param ack The acknowledgment structure containing packet IDs to be + * acknowledged. + * @param buf The buffer into which the acknowledgment record will be + * written. + * @param sid The session ID of the VPN tunnel associated with the + * packet IDs to be acknowledged. + * @param max The maximum number of acknowledgments to be written in + * the record. + * @param prepend If true, prepend the acknowledgment record in the + * buffer; if false, write into the buffer's current position. + * + * @return + * @li True, if processing was successful. + * @li False, if an error occurs during processing. + */ +bool reliable_ack_write (struct reliable_ack *ack, + struct buffer *buf, + const struct session_id *sid, int max, bool prepend); + +/** @} name Functions for processing outgoing acknowledgments */ + + +/**************************************************************************/ +/** @name Functions for initialization and cleanup + * @{ */ + +/** + * Initialize a reliable structure. + * + * @param rel The reliable structure to initialize. + * @param buf_size The size of the buffers in which packets will be + * stored. + * @param offset The size of reserved space at the beginning of the + * buffers to allow efficient header prepending. + * @param array_size The number of packets that this reliable + * structure can store simultaneously. + * @param hold description + */ void reliable_init (struct reliable *rel, int buf_size, int offset, int array_size, bool hold); +/** + * Free allocated memory associated with a reliable structure. + * + * @param rel The reliable structured to clean up. + */ void reliable_free (struct reliable *rel); -/* no active buffers? */ -bool reliable_empty (const struct reliable *rel); +/* add to extra_frame the maximum number of bytes we will need for reliable_ack_write */ +void reliable_ack_adjust_frame_parameters (struct frame* frame, int max); -/* in how many seconds should we wake up to check for timeout */ -interval_t reliable_send_timeout (const struct reliable *rel); +/** @} name Functions for initialization and cleanup */ -/* del acknowledged items from send buf */ -void reliable_send_purge (struct reliable *rel, struct reliable_ack *ack); -/* true if at least one free buffer available */ +/**************************************************************************/ +/** @name Functions for inserting incoming packets + * @{ */ + +/** + * Check whether a reliable structure has any free buffers + * available for use. + * + * @param rel The reliable structure to check. + * + * @return + * @li True, if at least one buffer is available for use. + * @li False, if all the buffers are active. + */ bool reliable_can_get (const struct reliable *rel); -/* make sure that incoming packet ID isn't a replay */ +/** + * Check that a received packet's ID is not a replay. + * + * @param rel The reliable structure for handling this VPN tunnel's + * received packets. + * @param id The packet ID of the received packet. + * + * @return + * @li True, if the packet ID is not a replay. + * @li False, if the packet ID is a replay. + */ bool reliable_not_replay (const struct reliable *rel, packet_id_type id); -/* make sure that incoming packet ID won't deadlock the receive buffer */ +/** + * Check that a received packet's ID can safely be stored in + * the reliable structure's processing window. + * + * This function checks the difference between the received packet's ID + * and the lowest non-acknowledged packet ID in the given reliable + * structure. If that difference is larger than the total number of + * packets which can be stored, then this packet cannot be stored safely, + * because the reliable structure could possibly fill up without leaving + * room for all intervening packets. In that case, this received packet + * could break the reliable structure's sequentiality, and must therefore + * be discarded. + * + * @param rel The reliable structure for handling this VPN tunnel's + * received packets. + * @param id The packet ID of the received packet. + * + * @return + * @li True, if the packet can safely be stored. + * @li False, if the packet does not fit safely in the reliable + * structure's processing window. + */ bool reliable_wont_break_sequentiality (const struct reliable *rel, packet_id_type id); -/* grab a free buffer */ +/** + * Read the packet ID of a received packet. + * + * @param buf The buffer containing the received packet. + * @param pid A pointer where the packet's packet ID will be written. + * + * @return + * @li True, if processing was successful. + * @li False, if an error occurs during processing. + */ +bool reliable_ack_read_packet_id (struct buffer *buf, packet_id_type *pid); + +/** + * Get the buffer of a free %reliable entry in which to store a + * packet. + * + * @param rel The reliable structure in which to search for a free + * entry. + * + * @return A pointer to a buffer of a free entry in the \a rel + * reliable structure. If there are no free entries available, this + * function returns NULL. + */ struct buffer *reliable_get_buf (struct reliable *rel); -/* grab a free buffer, fail if buffer clogged by unacknowledged low packet IDs */ -struct buffer *reliable_get_buf_output_sequenced (struct reliable *rel); +/** + * Mark the %reliable entry associated with the given buffer as active + * incoming. + * + * @param rel The reliable structure associated with this packet. + * @param buf The buffer into which the packet has been copied. + * @param pid The packet's packet ID. + * @param opcode The packet's opcode. + */ +void reliable_mark_active_incoming (struct reliable *rel, struct buffer *buf, + packet_id_type pid, int opcode); + +/** + * Record a packet ID for later acknowledgment. + * + * @param ack The acknowledgment structure which stores this VPN + * tunnel's packet IDs for later acknowledgment. + * @param pid The packet ID of the received packet which should be + * acknowledged. + * + * @return + * @li True, if the packet ID was added to \a ack. + * @li False, if the packet ID was already present in \a ack or \a ack + * has no free space to store any more packet IDs. + */ +bool reliable_ack_acknowledge_packet_id (struct reliable_ack *ack, packet_id_type pid); + +/** @} name Functions for inserting incoming packets */ -/* get active buffer for next sequentially increasing key ID */ + +/**************************************************************************/ +/** @name Functions for extracting incoming packets + * @{ */ + +/** + * Get the buffer of the next sequential and active entry. + * + * @param rel The reliable structure from which to retrieve the + * buffer. + * + * @return A pointer to the buffer of the entry with the next + * sequential key ID. If no such entry is present, this function + * returns NULL. + */ struct buffer *reliable_get_buf_sequenced (struct reliable *rel); -/* return true if reliable_send would return a non-NULL result */ +/** + * Remove an entry from a reliable structure. + * + * @param rel The reliable structure associated with the given buffer. + * @param buf The buffer of the reliable entry which is to be removed. + * @param inc_pid If true, the reliable structure's packet ID counter + * will be incremented. + */ +void reliable_mark_deleted (struct reliable *rel, struct buffer *buf, bool inc_pid); + +/** @} name Functions for extracting incoming packets */ + + +/**************************************************************************/ +/** @name Functions for inserting outgoing packets + * @{ */ + +/** + * Get the buffer of free reliable entry and check whether the + * outgoing acknowledgment sequence is still okay. + * + * @param rel The reliable structure in which to search for a free + * entry. + * + * @return A pointer to a buffer of a free entry in the \a rel + * reliable structure. If there are no free entries available, this + * function returns NULL. If the outgoing acknowledgment sequence is + * broken, this function also returns NULL. + */ +struct buffer *reliable_get_buf_output_sequenced (struct reliable *rel); + +/** + * Mark the reliable entry associated with the given buffer as + * active outgoing. + * + * @param rel The reliable structure for handling this VPN tunnel's + * outgoing packets. + * @param buf The buffer previously returned by \c + * reliable_get_buf_output_sequenced() into which the packet has been + * copied. + * @param opcode The packet's opcode. + */ +void reliable_mark_active_outgoing (struct reliable *rel, struct buffer *buf, int opcode); + +/** @} name Functions for inserting outgoing packets */ + + +/**************************************************************************/ +/** @name Functions for extracting outgoing packets + * @{ */ + +/** + * Check whether a reliable structure has any active entries + * ready to be (re)sent. + * + * @param rel The reliable structure to check. + * + * @return + * @li True, if there are active entries ready to be (re)sent + * president. + * @li False, if there are no active entries, or the active entries + * are not yet ready for resending. + */ bool reliable_can_send (const struct reliable *rel); -/* return next buffer to send to remote */ +/** + * Get the next packet to send to the remote peer. + * + * This function looks for the active entry ready for (re)sending with the + * lowest packet ID, and returns the buffer associated with it. This + * function also resets the timeout after which that entry will become + * ready for resending again. + * + * @param rel The reliable structure to check. + * @param opcode A pointer to an integer in which this function will + * store the opcode of the next packet to be sent. + * + * @return A pointer to the buffer of the next entry to be sent, or + * NULL if there are no entries ready for (re)sending present in the + * reliable structure. If a valid pointer is returned, then \a opcode + * will point to the opcode of that packet. + */ struct buffer *reliable_send (struct reliable *rel, int *opcode); -/* schedule all pending packets for immediate retransmit */ +/** @} name Functions for extracting outgoing packets */ + + +/**************************************************************************/ +/** @name Miscellaneous functions + * @{ */ + +/** + * Check whether a reliable structure is empty. + * + * @param rel The reliable structure to check. + * + * @return + * @li True, if there are no active entries in the given reliable + * structure. + * @li False, if there is at least one active entry present. + */ +bool reliable_empty (const struct reliable *rel); + +/** + * Determined how many seconds until the earliest resend should + * be attempted. + * + * @param rel The reliable structured to check. + * + * @return The interval in seconds until the earliest resend attempt + * of the outgoing packets stored in the \a rel reliable structure. If + * the next time for attempting resending of one or more packets has + * already passed, this function will return 0. + */ +interval_t reliable_send_timeout (const struct reliable *rel); + +/** + * Reschedule all entries of a reliable structure to be ready + * for (re)sending immediately. + * + * @param rel The reliable structure of which the entries should be + * modified. + */ void reliable_schedule_now (struct reliable *rel); -/* enable an incoming buffer previously returned by a get function as active */ -void reliable_mark_active_incoming (struct reliable *rel, struct buffer *buf, - packet_id_type pid, int opcode); +void reliable_debug_print (const struct reliable *rel, char *desc); -/* enable an outgoing buffer previously returned by a get function as active. */ -void reliable_mark_active_outgoing (struct reliable *rel, struct buffer *buf, int opcode); +/* set sending timeout (after this time we send again until ACK) */ +static inline void +reliable_set_timeout (struct reliable *rel, interval_t timeout) +{ + rel->initial_timeout = timeout; +} + +/* print a reliable ACK record coming off the wire */ +const char *reliable_ack_print (struct buffer *buf, bool verbose, struct gc_arena *gc); + +void reliable_ack_debug_print (const struct reliable_ack *ack, char *desc); + +/** @} name Miscellaneous functions */ + + +/** @} addtogroup reliable */ -/* delete a buffer previously activated by reliable_mark_active() */ -void reliable_mark_deleted (struct reliable *rel, struct buffer *buf, bool inc_pid); #endif /* RELIABLE_H */ #endif /* USE_CRYPTO && USE_SSL */ -- cgit v1.2.3