From 07203afe6fc5f1573135189329e41f125da1f558 Mon Sep 17 00:00:00 2001 From: "Keith Burns (alagalah)" Date: Thu, 25 Aug 2016 13:37:37 -0700 Subject: [PATCH] VPP-305: Documentation for vnet/vnet/unix Change-Id: I3f1a225033ecebe0cedfc3466b552176461b76ab Signed-off-by: Keith Burns (alagalah) --- vnet/vnet/unix/gdb_funcs.c | 60 ++++++++- vnet/vnet/unix/pcap.c | 59 +++++--- vnet/vnet/unix/pcap.h | 84 +++++++++--- vnet/vnet/unix/pcap2pg.c | 41 +++++- vnet/vnet/unix/tapcli.c | 330 ++++++++++++++++++++++++++++++++++++++------- vnet/vnet/unix/tapcli.h | 8 +- vnet/vnet/unix/tuntap.c | 214 ++++++++++++++++++++++------- vnet/vnet/unix/tuntap.h | 9 +- 8 files changed, 647 insertions(+), 158 deletions(-) diff --git a/vnet/vnet/unix/gdb_funcs.c b/vnet/vnet/unix/gdb_funcs.c index 9a2e4599a2b..cfb4b247800 100644 --- a/vnet/vnet/unix/gdb_funcs.c +++ b/vnet/vnet/unix/gdb_funcs.c @@ -12,33 +12,73 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/** + * @file + * @brief Host utility functions + */ #include #include #include -/* Functions to call from gdb */ + +/** + * @brief GDB callable function: vl - Return vector length of vector + * + * @param *p - void - address of vector + * + * @return length - u32 + * + */ u32 vl(void *p) { return vec_len (p); } +/** + * @brief GDB callable function: pe - call pool_elts - number of elements in a pool + * + * @param *v - void - address of pool + * + * @return number - uword + * + */ uword pe (void *v) { return (pool_elts(v)); } +/** + * @brief GDB callable function: pifi - call pool_is_free_index - is passed index free? + * + * @param *p - void - address of pool + * @param *index - u32 + * + * @return 0|1 - int + * + */ int pifi (void *p, u32 index) { return pool_is_free_index (p, index); } +/** + * @brief GDB callable function: debug_hex_bytes - return formatted hex string + * + * @param *s - u8 + * @param n - u32 - number of bytes to format + * + */ void debug_hex_bytes (u8 *s, u32 n) { fformat (stderr, "%U\n", format_hex_bytes, s, n); } +/** + * @brief GDB callable function: vlib_dump_frame_ownership + * + */ void vlib_dump_frame_ownership (void) { vlib_main_t * vm = vlib_get_main(); @@ -47,7 +87,7 @@ void vlib_dump_frame_ownership (void) vlib_next_frame_t * nf; u32 first_nf_index; u32 index; - + vec_foreach(this_node_runtime, nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]) { first_nf_index = this_node_runtime->next_frame_index; @@ -74,11 +114,18 @@ void vlib_dump_frame_ownership (void) } } +/** + * @brief GDB callable function: vlib_runtime_index_to_node_name + * + * Takes node index and will return the node name. + * + * @param index - u32 + */ void vlib_runtime_index_to_node_name (u32 index) { vlib_main_t * vm = vlib_get_main(); vlib_node_main_t * nm = &vm->node_main; - + if (index > vec_len (nm->nodes)) { fformat(stderr, "%d out of range, max %d\n", vec_len(nm->nodes)); @@ -89,6 +136,13 @@ void vlib_runtime_index_to_node_name (u32 index) } +/** + * @brief GDB callable function: show_gdb_command_fn - show gdb + * + * Shows list of functions for VPP available in GDB + * + * @return error - clib_error_t + */ static clib_error_t * show_gdb_command_fn (vlib_main_t * vm, unformat_input_t * input, diff --git a/vnet/vnet/unix/pcap.c b/vnet/vnet/unix/pcap.c index 1c5f033ea1f..5c8a14bd29c 100644 --- a/vnet/vnet/unix/pcap.c +++ b/vnet/vnet/unix/pcap.c @@ -40,24 +40,33 @@ #include #include -/* Usage - -#include - -static pcap_main_t pcap = { - .file_name = "/tmp/ip4", - .n_packets_to_capture = 2, - .packet_type = PCAP_PACKET_TYPE_ip, -}; - -To add a buffer: - - pcap_add_buffer (&pcap, vm, pi0, 128); - -file will be written after n_packets_to_capture or call to pcap_write (&pcap). - +/** + * @file + * @brief PCAP function. + * Usage + * + * #include + * + * static pcap_main_t pcap = { + * .file_name = "/tmp/ip4", + * .n_packets_to_capture = 2, + * .packet_type = PCAP_PACKET_TYPE_ip, + * }; + * + * To add a buffer: + * + * pcap_add_buffer (&pcap, vm, pi0, 128); + * + * File will be written after n_packets_to_capture or call to pcap_write (&pcap). + * */ +/** + * @brief Close PCAP file + * + * @return rc - clib_error_t + * + */ clib_error_t * pcap_close (pcap_main_t * pm) { @@ -67,6 +76,12 @@ pcap_close (pcap_main_t * pm) return 0; } +/** + * @brief Write PCAP file + * + * @return rc - clib_error_t + * + */ clib_error_t * pcap_write (pcap_main_t * pm) { @@ -143,6 +158,12 @@ pcap_write (pcap_main_t * pm) return error; } +/** + * @brief Read PCAP file + * + * @return rc - clib_error_t + * + */ clib_error_t * pcap_read (pcap_main_t * pm) { clib_error_t * error = 0; @@ -197,7 +218,7 @@ clib_error_t * pcap_read (pcap_main_t * pm) error = clib_error_return (0, "short read `%s'", pm->file_name); goto done; } - + if (vec_len (pm->packets_read) == 0) pm->min_packet_bytes = pm->max_packet_bytes = ph.n_bytes_in_packet; else @@ -205,7 +226,7 @@ clib_error_t * pcap_read (pcap_main_t * pm) pm->min_packet_bytes = clib_min (pm->min_packet_bytes, ph.n_bytes_in_packet); pm->max_packet_bytes = clib_max (pm->max_packet_bytes, ph.n_bytes_in_packet); } - + vec_add1 (pm->packets_read, data); } @@ -213,5 +234,5 @@ clib_error_t * pcap_read (pcap_main_t * pm) if (fd >= 0) close (fd); return error; - + } diff --git a/vnet/vnet/unix/pcap.h b/vnet/vnet/unix/pcap.h index 89eca031185..6aaf32bef7e 100644 --- a/vnet/vnet/unix/pcap.h +++ b/vnet/vnet/unix/pcap.h @@ -36,13 +36,25 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - +/** + * @file + * @brief PCAP utility definitions + */ #ifndef included_vnet_pcap_h #define included_vnet_pcap_h #include -#define foreach_vnet_pcap_packet_type \ +/** + * @brief Packet types supported by PCAP + * + * null 0 + * ethernet 1 + * ppp 9 + * ip 12 + * hdlc 104 + */ +#define foreach_vnet_pcap_packet_type \ _ (null, 0) \ _ (ethernet, 1) \ _ (ppp, 9) \ @@ -56,27 +68,27 @@ typedef enum { } pcap_packet_type_t; #define foreach_pcap_file_header \ - /* 0xa1b2c3d4 host byte order. \ + /** 0xa1b2c3d4 host byte order. \ 0xd4c3b2a1 => need to byte swap everything. */ \ _ (u32, magic) \ \ - /* Currently major 2 minor 4. */ \ + /** Currently major 2 minor 4. */ \ _ (u16, major_version) \ _ (u16, minor_version) \ \ - /* 0 for GMT. */ \ + /** 0 for GMT. */ \ _ (u32, time_zone) \ \ - /* Accuracy of timestamps. Typically set to 0. */ \ + /** Accuracy of timestamps. Typically set to 0. */ \ _ (u32, sigfigs) \ \ - /* Size of largest packet in file. */ \ + /** Size of largest packet in file. */ \ _ (u32, max_packet_size_in_bytes) \ \ - /* One of vnet_pcap_packet_type_t. */ \ + /** One of vnet_pcap_packet_type_t. */ \ _ (u32, packet_type) -/* File header. */ +/** File header struct */ typedef struct { #define _(t, f) t f; foreach_pcap_file_header @@ -84,58 +96,79 @@ typedef struct { } pcap_file_header_t; #define foreach_pcap_packet_header \ - /* Time stamp in seconds and microseconds. */ \ + /** Time stamp in seconds */ \ _ (u32, time_in_sec) \ + /** Time stamp in microseconds. */ \ _ (u32, time_in_usec) \ \ - /* Number of bytes stored in file and size of actual packet. */ \ + /** Number of bytes stored in file. */ \ _ (u32, n_packet_bytes_stored_in_file) \ + /** Number of bytes in actual packet. */ \ _ (u32, n_bytes_in_packet) -/* Packet header. */ +/** Packet header. */ typedef struct { #define _(t, f) t f; foreach_pcap_packet_header #undef _ - /* Packet data follows. */ + /** Packet data follows. */ u8 data[0]; } pcap_packet_header_t; +/** + * @brief PCAP main state data structure + */ typedef struct { - /* File name of pcap output. */ + /** File name of pcap output. */ char * file_name; - /* Number of packets to capture. */ + /** Number of packets to capture. */ u32 n_packets_to_capture; + /** Packet type */ pcap_packet_type_t packet_type; - /* Number of packets currently captured. */ + /** Number of packets currently captured. */ u32 n_packets_captured; + /** flags */ u32 flags; #define PCAP_MAIN_INIT_DONE (1 << 0) - /* File descriptor for reading/writing. */ + /** File descriptor for reading/writing. */ int file_descriptor; + /** Bytes written */ u32 n_pcap_data_written; - /* Vector of pcap data. */ + /** Vector of pcap data. */ u8 * pcap_data; - /* Packets read from file. */ + /** Packets read from file. */ u8 ** packets_read; + /** Min/Max Packet bytes */ u32 min_packet_bytes, max_packet_bytes; } pcap_main_t; -/* Write out data to output file. */ +/** Write out data to output file. */ clib_error_t * pcap_write (pcap_main_t * pm); +/** Read data from file. */ clib_error_t * pcap_read (pcap_main_t * pm); +/** + * @brief Add packet + * + * @param *pm - pcap_main_t + * @param time_now - f64 + * @param n_bytes_in_trace - u32 + * @param n_bytes_in_packet - u32 + * + * @return Packet Data + * + */ static inline void * pcap_add_packet (pcap_main_t * pm, f64 time_now, @@ -155,6 +188,15 @@ pcap_add_packet (pcap_main_t * pm, return h->data; } +/** + * @brief Add buffer (vlib_buffer_t) to the trace + * + * @param *pm - pcap_main_t + * @param *vm - vlib_main_t + * @param buffer_index - u32 + * @param n_bytes_in_trace - u32 + * + */ static inline void pcap_add_buffer (pcap_main_t * pm, vlib_main_t * vm, u32 buffer_index, @@ -179,7 +221,7 @@ pcap_add_buffer (pcap_main_t * pm, b = vlib_get_buffer (vm, b->next_buffer); } - /* Flush output vector. */ + /** Flush output vector. */ if (vec_len (pm->pcap_data) >= 64*1024 || pm->n_packets_captured >= pm->n_packets_to_capture) pcap_write (pm); diff --git a/vnet/vnet/unix/pcap2pg.c b/vnet/vnet/unix/pcap2pg.c index 10b47c976dc..217a61f4cb4 100644 --- a/vnet/vnet/unix/pcap2pg.c +++ b/vnet/vnet/unix/pcap2pg.c @@ -14,14 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/** + * @file + * @brief Functions to convert PCAP file format to VPP PG (Packet Generator) + * + */ #include #include #include pcap_main_t pcap_main; -static char * pg_fmt = +/** + * @brief char * to seed a PG file + */ +static char * pg_fmt = "packet-generator new {\n" " name s%d\n" " limit 1\n" @@ -29,16 +36,32 @@ static char * pg_fmt = " node ethernet-input\n"; +/** + * @brief Packet Generator Stream boilerplate + * + * @param *ofp - FILE + * @param i - int + * @param *pkt - u8 + */ void stream_boilerplate (FILE *ofp, int i, u8 * pkt) { fformat(ofp, pg_fmt, i, vec_len(pkt), vec_len(pkt)); } +/** + * @brief Conversion of PCAP file to PG file format + * + * @param *pm - pcap_main_t + * @param *ofp - FILE + * + * @return rc - int + * + */ int pcap2pg (pcap_main_t * pm, FILE *ofp) { int i, j; u8 *pkt; - + for (i = 0; i < vec_len (pm->packets_read); i++) { int offset; @@ -51,13 +74,13 @@ int pcap2pg (pcap_main_t * pm, FILE *ofp) stream_boilerplate (ofp, i, pkt); fformat (ofp, " data {\n"); - + ethertype = clib_net_to_host_u16 (h->type); - /* + /** * In vnet terms, packet generator interfaces are not ethernets. * They don't have vlan tables. - * This dance transforms captured 802.1q VLAN packets into + * This transforms captured 802.1q VLAN packets into * regular Ethernet packets. */ if (ethertype == 0x8100 /* 802.1q vlan */) @@ -69,7 +92,7 @@ int pcap2pg (pcap_main_t * pm, FILE *ofp) else offset = 14; - fformat (ofp, + fformat (ofp, " 0x%04x: %02x%02x.%02x%02x.%02x%02x" " -> %02x%02x.%02x%02x.%02x%02x\n", ethertype, @@ -97,6 +120,10 @@ int pcap2pg (pcap_main_t * pm, FILE *ofp) return 0; } +/** + * @brief pcap2pg. + * usage: pcap2pg -i [-o ] + */ int main (int argc, char **argv) { unformat_input_t input; diff --git a/vnet/vnet/unix/tapcli.c b/vnet/vnet/unix/tapcli.c index 7e2ee06330a..608b22098b1 100644 --- a/vnet/vnet/unix/tapcli.c +++ b/vnet/vnet/unix/tapcli.c @@ -1,4 +1,4 @@ -/* +/* *------------------------------------------------------------------ * tapcli.c - dynamic tap interface hookup * @@ -16,12 +16,16 @@ * limitations under the License. *------------------------------------------------------------------ */ +/** + * @file + * @brief dynamic tap interface hookup + */ #include /* for open */ #include #include #include -#include +#include #include /* for iovec */ #include @@ -48,22 +52,39 @@ static vlib_node_registration_t tapcli_rx_node; static void tapcli_nopunt_frame (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame); +/** + * @brief Struct for the tapcli interface + */ typedef struct { u32 unix_fd; u32 unix_file_index; u32 provision_fd; - u32 sw_if_index; /* for counters */ + /** For counters */ + u32 sw_if_index; u32 hw_if_index; u32 is_promisc; struct ifreq ifr; u32 per_interface_next_index; - u8 active; /* for delete */ + /** for delete */ + u8 active; } tapcli_interface_t; +/** + * @brief Struct for RX trace + */ typedef struct { u16 sw_if_index; } tapcli_rx_trace_t; +/** + * @brief Function to format TAP CLI trace + * + * @param *s - u8 - formatting string + * @param *va - va_list + * + * @return *s - u8 - formatted string + * + */ u8 * format_tapcli_rx_trace (u8 * s, va_list * va) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); @@ -75,54 +96,67 @@ u8 * format_tapcli_rx_trace (u8 * s, va_list * va) return s; } +/** + * @brief TAPCLI main state struct + */ typedef struct { - /* Vector of iovecs for readv/writev calls. */ + /** Vector of iovecs for readv/writev calls. */ struct iovec * iovecs; - /* Vector of VLIB rx buffers to use. We allocate them in blocks + /** Vector of VLIB rx buffers to use. We allocate them in blocks of VLIB_FRAME_SIZE (256). */ u32 * rx_buffers; - /* tap device destination MAC address. Required, or Linux drops pkts */ + /** tap device destination MAC address. Required, or Linux drops pkts */ u8 ether_dst_mac[6]; - /* Interface MTU in bytes and # of default sized buffers. */ + /** Interface MTU in bytes and # of default sized buffers. */ u32 mtu_bytes, mtu_buffers; - /* Vector of tap interfaces */ + /** Vector of tap interfaces */ tapcli_interface_t * tapcli_interfaces; - /* Vector of deleted tap interfaces */ + /** Vector of deleted tap interfaces */ u32 * tapcli_inactive_interfaces; - /* Bitmap of tap interfaces with pending reads */ + /** Bitmap of tap interfaces with pending reads */ uword * pending_read_bitmap; - /* Hash table to find tapcli interface given hw_if_index */ + /** Hash table to find tapcli interface given hw_if_index */ uword * tapcli_interface_index_by_sw_if_index; - - /* Hash table to find tapcli interface given unix fd */ + + /** Hash table to find tapcli interface given unix fd */ uword * tapcli_interface_index_by_unix_fd; - /* renumbering table */ + /** renumbering table */ u32 * show_dev_instance_by_real_dev_instance; - /* 1 => disable CLI */ + /** 1 => disable CLI */ int is_disabled; - /* convenience */ + /** convenience - vlib_main_t */ vlib_main_t * vlib_main; + /** convenience - vnet_main_t */ vnet_main_t * vnet_main; + /** convenience - unix_main_t */ unix_main_t * unix_main; } tapcli_main_t; static tapcli_main_t tapcli_main; -/* - * tapcli_tx - * Output node, writes the buffers comprising the incoming frame +/** + * @brief tapcli TX node function + * @node tap-cli-tx + * + * Output node, writes the buffers comprising the incoming frame * to the tun/tap device, aka hands them to the Linux kernel stack. - * + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + * @return n_packets - uword + * */ static uword tapcli_tx (vlib_main_t * vm, @@ -192,9 +226,9 @@ tapcli_tx (vlib_main_t * vm, if (writev (ti->unix_fd, tm->iovecs, vec_len (tm->iovecs)) < l) clib_unix_warning ("writev"); } - + vlib_buffer_free(vm, vlib_frame_vector_args(frame), frame->n_vectors); - + return n_packets; } @@ -206,8 +240,8 @@ VLIB_REGISTER_NODE (tapcli_tx_node,static) = { }; enum { - TAPCLI_RX_NEXT_IP4_INPUT, - TAPCLI_RX_NEXT_IP6_INPUT, + TAPCLI_RX_NEXT_IP4_INPUT, + TAPCLI_RX_NEXT_IP6_INPUT, TAPCLI_RX_NEXT_ETHERNET_INPUT, TAPCLI_RX_NEXT_DROP, TAPCLI_RX_N_NEXT, @@ -215,6 +249,17 @@ enum { +/** + * @brief Dispatch tapcli RX node function for node tap_cli_rx + * + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *ti - tapcli_interface_t + * + * @return n_packets - uword + * + */ static uword tapcli_rx_iface(vlib_main_t * vm, vlib_node_runtime_t * node, tapcli_interface_t * ti) @@ -352,6 +397,19 @@ static uword tapcli_rx_iface(vlib_main_t * vm, return VLIB_FRAME_SIZE - n_left_to_next; } +/** + * @brief tapcli RX node function + * @node tap-cli-rx + * + * Input node from the Kernel tun/tap device + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + * @return n_packets - uword + * + */ static uword tapcli_rx (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -384,6 +442,7 @@ tapcli_rx (vlib_main_t * vm, return total_count; //This might return more than 256. } +/** TAPCLI error strings */ static char * tapcli_rx_error_strings[] = { #define _(sym,string) string, foreach_tapcli_error @@ -409,19 +468,27 @@ VLIB_REGISTER_NODE (tapcli_rx_node, static) = { }, }; -/* Gets called when file descriptor is ready from epoll. */ + +/** + * @brief Gets called when file descriptor is ready from epoll. + * + * @param *uf - unix_file_t + * + * @return error - clib_error_t + * + */ static clib_error_t * tapcli_read_ready (unix_file_t * uf) { vlib_main_t * vm = vlib_get_main(); tapcli_main_t * tm = &tapcli_main; uword * p; - - /* Schedule the rx node */ + + /** Schedule the rx node */ vlib_node_set_interrupt_pending (vm, tapcli_rx_node.index); p = hash_get (tm->tapcli_interface_index_by_unix_fd, uf->file_descriptor); - /* Mark the specific tap interface ready-to-read */ + /** Mark the specific tap interface ready-to-read */ if (p) tm->pending_read_bitmap = clib_bitmap_set (tm->pending_read_bitmap, p[0], 1); @@ -431,6 +498,15 @@ static clib_error_t * tapcli_read_ready (unix_file_t * uf) return 0; } +/** + * @brief CLI function for TAPCLI configuration + * + * @param *vm - vlib_main_t + * @param *input - unformat_input_t + * + * @return error - clib_error_t + * + */ static clib_error_t * tapcli_config (vlib_main_t * vm, unformat_input_t * input) { @@ -451,18 +527,27 @@ tapcli_config (vlib_main_t * vm, unformat_input_t * input) if (tm->is_disabled) return 0; - if (geteuid()) + if (geteuid()) { clib_warning ("tapcli disabled: must be superuser"); tm->is_disabled = 1; return 0; - } + } tm->mtu_buffers = (tm->mtu_bytes + (buffer_size - 1)) / buffer_size; - + return 0; } +/** + * @brief Renumber TAPCLI interface + * + * @param *hi - vnet_hw_interface_t + * @param new_dev_instance - u32 + * + * @return rc - int + * + */ static int tap_name_renumber (vnet_hw_interface_t * hi, u32 new_dev_instance) { @@ -479,6 +564,14 @@ static int tap_name_renumber (vnet_hw_interface_t * hi, VLIB_CONFIG_FUNCTION (tapcli_config, "tapcli"); +/** + * @brief Free "no punt" frame + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + */ static void tapcli_nopunt_frame (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -494,6 +587,15 @@ VNET_HW_INTERFACE_CLASS (tapcli_interface_class,static) = { .name = "tapcli", }; +/** + * @brief Formatter for TAPCLI interface name + * + * @param *s - formatter string + * @param *args - va_list + * + * @return *s - formatted string + * + */ static u8 * format_tapcli_interface_name (u8 * s, va_list * args) { u32 i = va_arg (*args, u32); @@ -510,7 +612,17 @@ static u8 * format_tapcli_interface_name (u8 * s, va_list * args) return s; } -static u32 tapcli_flag_change (vnet_main_t * vnm, +/** + * @brief Modify interface flags for TAPCLI interface + * + * @param *vnm - vnet_main_t + * @param *hw - vnet_hw_interface_t + * @param flags - u32 + * + * @return rc - u32 + * + */ +static u32 tapcli_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags) { @@ -562,7 +674,15 @@ static u32 tapcli_flag_change (vnet_main_t * vnm, return 0; } -static void tapcli_set_interface_next_node (vnet_main_t *vnm, +/** + * @brief Setting the TAP interface's next processing node + * + * @param *vnm - vnet_main_t + * @param hw_if_index - u32 + * @param node_index - u32 + * + */ +static void tapcli_set_interface_next_node (vnet_main_t *vnm, u32 hw_if_index, u32 node_index) { @@ -571,35 +691,40 @@ static void tapcli_set_interface_next_node (vnet_main_t *vnm, vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); ti = vec_elt_at_index (tm->tapcli_interfaces, hw->dev_instance); - - /* Shut off redirection */ + + /** Shut off redirection */ if (node_index == ~0) { ti->per_interface_next_index = node_index; return; } - - ti->per_interface_next_index = + + ti->per_interface_next_index = vlib_node_add_next (tm->vlib_main, tapcli_rx_node.index, node_index); } -/* - * Mainly exists to set link_state == admin_state - * otherwise, e.g. ip6 neighbor discovery breaks +/** + * @brief Set link_state == admin_state otherwise things like ip6 neighbor discovery breaks + * + * @param *vnm - vnet_main_t + * @param hw_if_index - u32 + * @param flags - u32 + * + * @return error - clib_error_t */ -static clib_error_t * +static clib_error_t * tapcli_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) { uword is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0; u32 hw_flags; - u32 speed_duplex = VNET_HW_INTERFACE_FLAG_FULL_DUPLEX + u32 speed_duplex = VNET_HW_INTERFACE_FLAG_FULL_DUPLEX | VNET_HW_INTERFACE_FLAG_SPEED_1G; - + if (is_admin_up) hw_flags = VNET_HW_INTERFACE_FLAG_LINK_UP | speed_duplex; else hw_flags = speed_duplex; - + vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags); return 0; } @@ -614,6 +739,14 @@ VNET_DEVICE_CLASS (tapcli_dev_class,static) = { .no_flatten_output_chains = 1, }; +/** + * @brief Dump TAP interfaces + * + * @param **out_tapids - tapcli_interface_details_t + * + * @return rc - int + * + */ int vnet_tap_dump_ifs (tapcli_interface_details_t **out_tapids) { tapcli_main_t * tm = &tapcli_main; @@ -635,7 +768,12 @@ int vnet_tap_dump_ifs (tapcli_interface_details_t **out_tapids) return 0; } -/* get tap interface from inactive interfaces or create new */ +/** + * @brief Get tap interface from inactive interfaces or create new + * + * @return interface - tapcli_interface_t + * + */ static tapcli_interface_t *tapcli_get_new_tapif() { tapcli_main_t * tm = &tapcli_main; @@ -661,6 +799,17 @@ static tapcli_interface_t *tapcli_get_new_tapif() return ti; } +/** + * @brief Connect a TAP interface + * + * @param *vm - vlib_main_t + * @param *intfc_name - u8 + * @param *hwaddr_arg - u8 + * @param *sw_if_index - u32 + * + * @return rc - int + * + */ int vnet_tap_connect (vlib_main_t * vm, u8 * intfc_name, u8 *hwaddr_arg, u32 * sw_if_indexp) { @@ -683,7 +832,7 @@ int vnet_tap_connect (vlib_main_t * vm, u8 * intfc_name, u8 *hwaddr_arg, if ((dev_net_tun_fd = open ("/dev/net/tun", O_RDWR)) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; - + memset (&ifr, 0, sizeof (ifr)); strncpy(ifr.ifr_name, (char *) intfc_name, sizeof (ifr.ifr_name)-1); ifr.ifr_flags = flags; @@ -829,6 +978,19 @@ int vnet_tap_connect (vlib_main_t * vm, u8 * intfc_name, u8 *hwaddr_arg, return rv; } +/** + * @brief Renumber a TAP interface + * + * @param *vm - vlib_main_t + * @param *intfc_name - u8 + * @param *hwaddr_arg - u8 + * @param *sw_if_indexp - u32 + * @param renumber - u8 + * @param custom_dev_instance - u32 + * + * @return rc - int + * + */ int vnet_tap_connect_renumber (vlib_main_t * vm, u8 * intfc_name, u8 *hwaddr_arg, u32 * sw_if_indexp, u8 renumber, u32 custom_dev_instance) @@ -841,6 +1003,14 @@ int vnet_tap_connect_renumber (vlib_main_t * vm, u8 * intfc_name, return rv; } +/** + * @brief Disconnect TAP CLI interface + * + * @param *ti - tapcli_interface_t + * + * @return rc - int + * + */ static int tapcli_tap_disconnect (tapcli_interface_t *ti) { int rv = 0; @@ -866,6 +1036,15 @@ static int tapcli_tap_disconnect (tapcli_interface_t *ti) return rv; } +/** + * @brief Delete TAP interface + * + * @param *vm - vlib_main_t + * @param sw_if_index - u32 + * + * @return rc - int + * + */ int vnet_tap_delete(vlib_main_t *vm, u32 sw_if_index) { int rv = 0; @@ -895,6 +1074,16 @@ int vnet_tap_delete(vlib_main_t *vm, u32 sw_if_index) return rv; } +/** + * @brief CLI function to delete TAP interface + * + * @param *vm - vlib_main_t + * @param *input - unformat_input_t + * @param *cmd - vlib_cli_command_t + * + * @return error - clib_error_t + * + */ static clib_error_t * tap_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -933,7 +1122,20 @@ VLIB_CLI_COMMAND (tap_delete_command, static) = { .function = tap_delete_command_fn, }; -/* modifies tap interface - can result in new interface being created */ +/** + * @brief Modifies tap interface - can result in new interface being created + * + * @param *vm - vlib_main_t + * @param orig_sw_if_index - u32 + * @param *intfc_name - u8 + * @param *hwaddr_arg - u8 + * @param *sw_if_indexp - u32 + * @param renumber - u8 + * @param custom_dev_instance - u32 + * + * @return rc - int + * + */ int vnet_tap_modify (vlib_main_t * vm, u32 orig_sw_if_index, u8 * intfc_name, u8 *hwaddr_arg, u32 * sw_if_indexp, @@ -950,6 +1152,16 @@ int vnet_tap_modify (vlib_main_t * vm, u32 orig_sw_if_index, return rv; } +/** + * @brief CLI function to modify TAP interface + * + * @param *vm - vlib_main_t + * @param *input - unformat_input_t + * @param *cmd - vlib_cli_command_t + * + * @return error - clib_error_t + * + */ static clib_error_t * tap_modify_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -961,7 +1173,7 @@ tap_modify_command_fn (vlib_main_t * vm, u32 new_sw_if_index = ~0; int user_hwaddr = 0; u8 hwaddr[6]; - + if (tm->is_disabled) { return clib_error_return (0, "device disabled..."); @@ -979,7 +1191,7 @@ tap_modify_command_fn (vlib_main_t * vm, else return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); - + if (unformat(input, "hwaddr %U", unformat_ethernet_address, &hwaddr)) user_hwaddr = 1; @@ -1006,6 +1218,16 @@ VLIB_CLI_COMMAND (tap_modify_command, static) = { .function = tap_modify_command_fn, }; +/** + * @brief CLI function to connect TAP interface + * + * @param *vm - vlib_main_t + * @param *input - unformat_input_t + * @param *cmd - vlib_cli_command_t + * + * @return error - clib_error_t + * + */ static clib_error_t * tap_connect_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -1095,6 +1317,14 @@ VLIB_CLI_COMMAND (tap_connect_command, static) = { .function = tap_connect_command_fn, }; +/** + * @brief TAPCLI main init + * + * @param *vm - vlib_main_t + * + * @return error - clib_error_t + * + */ clib_error_t * tapcli_init (vlib_main_t * vm) { diff --git a/vnet/vnet/unix/tapcli.h b/vnet/vnet/unix/tapcli.h index e9228d7cb0e..fcd82dbf25d 100644 --- a/vnet/vnet/unix/tapcli.h +++ b/vnet/vnet/unix/tapcli.h @@ -14,11 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/** + * @file + * @brief TAPCLI definitions + */ #ifndef __included_tapcli_h__ #define __included_tapcli_h__ -#define foreach_tapcli_error \ +/** TAP CLI errors */ +#define foreach_tapcli_error \ /* Must be first. */ \ _(NONE, "no error") \ _(READ, "read error") \ @@ -32,6 +37,7 @@ typedef enum { TAPCLI_N_ERROR, } tapcli_error_t; +/** TAP CLI interface details struct */ typedef struct { u32 sw_if_index; u8 dev_name[64]; diff --git a/vnet/vnet/unix/tuntap.c b/vnet/vnet/unix/tuntap.c index 01da1730e6c..83e7ec4f590 100644 --- a/vnet/vnet/unix/tuntap.c +++ b/vnet/vnet/unix/tuntap.c @@ -16,12 +16,25 @@ * limitations under the License. *------------------------------------------------------------------ */ +/** + * @file + * @brief TunTap Kernel stack (reverse) punt/inject path. + * + * This driver runs in one of two distinct modes: + * - "punt/inject" mode, where we send pkts not otherwise processed + * by the forwarding to the Linux kernel stack, and + * + * - "normal interface" mode, where we treat the Linux kernel stack + * as a peer. + * + * By default, we select punt/inject mode. + */ #include /* for open */ #include #include #include -#include +#include #include /* for iovec */ #include @@ -49,58 +62,52 @@ static void tuntap_nopunt_frame (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame); -/* - * This driver runs in one of two distinct modes: - * "punt/inject" mode, where we send pkts not otherwise processed - * by the forwarding to the Linux kernel stack, and - * "normal interface" mode, where we treat the Linux kernel stack - * as a peer. - * - * By default, we select punt/inject mode. - */ - typedef struct { u32 sw_if_index; u8 is_v6; u8 addr[16]; } subif_address_t; +/** + * @brief TUNTAP node main state + */ typedef struct { - /* Vector of iovecs for readv/writev calls. */ + /** Vector of iovecs for readv/writev calls. */ struct iovec * iovecs; - /* Vector of VLIB rx buffers to use. We allocate them in blocks + /** Vector of VLIB rx buffers to use. We allocate them in blocks of VLIB_FRAME_SIZE (256). */ u32 * rx_buffers; - /* File descriptors for /dev/net/tun and provisioning socket. */ + /** File descriptors for /dev/net/tun and provisioning socket. */ int dev_net_tun_fd, dev_tap_fd; - /* Create a "tap" [ethernet] encaps device */ + /** Create a "tap" [ethernet] encaps device */ int is_ether; - /* 1 if a "normal" routed intfc, 0 if a punt/inject interface */ + /** 1 if a "normal" routed intfc, 0 if a punt/inject interface */ int have_normal_interface; - /* tap device destination MAC address. Required, or Linux drops pkts */ + /** tap device destination MAC address. Required, or Linux drops pkts */ u8 ether_dst_mac[6]; - /* Interface MTU in bytes and # of default sized buffers. */ + /** Interface MTU in bytes and # of default sized buffers. */ u32 mtu_bytes, mtu_buffers; - /* Linux interface name for tun device. */ + /** Linux interface name for tun device. */ char * tun_name; - /* Pool of subinterface addresses */ + /** Pool of subinterface addresses */ subif_address_t *subifs; - /* Hash for subif addresses */ + /** Hash for subif addresses */ mhash_t subif_mhash; + /** Unix file index */ u32 unix_file_index; - /* For the "normal" interface, if configured */ + /** For the "normal" interface, if configured */ u32 hw_if_index, sw_if_index; } tuntap_main_t; @@ -108,15 +115,23 @@ typedef struct { static tuntap_main_t tuntap_main = { .tun_name = "vnet", - /* Suitable defaults for an Ethernet-like tun/tap device */ + /** Suitable defaults for an Ethernet-like tun/tap device */ .mtu_bytes = 4096 + 256, }; -/* - * tuntap_tx - * Output node, writes the buffers comprising the incoming frame +/** + * @brief tuntap_tx + * @node tuntap-tx + * + * Output node, writes the buffers comprising the incoming frame * to the tun/tap device, aka hands them to the Linux kernel stack. - * + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + * @return rc - uword + * */ static uword tuntap_tx (vlib_main_t * vm, @@ -146,7 +161,7 @@ tuntap_tx (vlib_main_t * vm, if (tm->iovecs) _vec_len (tm->iovecs) = 0; - /* VLIB buffer chain -> Unix iovec(s). */ + /** VLIB buffer chain -> Unix iovec(s). */ vec_add2 (tm->iovecs, iov, 1); iov->iov_base = b->data + b->current_data; iov->iov_len = l = b->current_length; @@ -167,13 +182,13 @@ tuntap_tx (vlib_main_t * vm, if (writev (tm->dev_net_tun_fd, tm->iovecs, vec_len (tm->iovecs)) < l) clib_unix_warning ("writev"); } - - /* The normal interface path flattens the buffer chain */ + + /** The normal interface path flattens the buffer chain */ if (tm->have_normal_interface) vlib_buffer_free_no_next (vm, buffers, n_packets); else vlib_buffer_free (vm, buffers, n_packets); - + return n_packets; } @@ -185,13 +200,24 @@ VLIB_REGISTER_NODE (tuntap_tx_node,static) = { }; enum { - TUNTAP_RX_NEXT_IP4_INPUT, - TUNTAP_RX_NEXT_IP6_INPUT, + TUNTAP_RX_NEXT_IP4_INPUT, + TUNTAP_RX_NEXT_IP6_INPUT, TUNTAP_RX_NEXT_ETHERNET_INPUT, TUNTAP_RX_NEXT_DROP, TUNTAP_RX_N_NEXT, }; +/** + * @brief TUNTAP receive node + * @node tuntap-rx + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + * @return rc - uword + * + */ static uword tuntap_rx (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -209,7 +235,7 @@ tuntap_rx (vlib_main_t * vm, struct rte_mbuf *first_mb = NULL, *prev_mb = NULL; #endif - /* Make sure we have some RX buffers. */ + /** Make sure we have some RX buffers. */ { uword n_left = vec_len (tm->rx_buffers); uword n_alloc; @@ -226,14 +252,14 @@ tuntap_rx (vlib_main_t * vm, } } - /* Allocate RX buffers from end of rx_buffers. + /** Allocate RX buffers from end of rx_buffers. Turn them into iovecs to pass to readv. */ { uword i_rx = vec_len (tm->rx_buffers) - 1; vlib_buffer_t * b; word i, n_bytes_left, n_bytes_in_packet; - /* We should have enough buffers left for an MTU sized packet. */ + /** We should have enough buffers left for an MTU sized packet. */ ASSERT (vec_len (tm->rx_buffers) >= tm->mtu_buffers); vec_validate (tm->iovecs, tm->mtu_buffers - 1); @@ -299,14 +325,14 @@ tuntap_rx (vlib_main_t * vm, #endif } - /* Interface counters for tuntap interface. */ - vlib_increment_combined_counter + /** Interface counters for tuntap interface. */ + vlib_increment_combined_counter (vnet_main.interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, os_get_cpu_number(), tm->sw_if_index, 1, n_bytes_in_packet); - + _vec_len (tm->rx_buffers) = i_rx; } @@ -370,6 +396,9 @@ tuntap_rx (vlib_main_t * vm, return 1; } +/** + * @brief TUNTAP_RX error strings + */ static char * tuntap_rx_error_strings[] = { "unknown packet type", }; @@ -392,7 +421,13 @@ VLIB_REGISTER_NODE (tuntap_rx_node,static) = { }, }; -/* Gets called when file descriptor is ready from epoll. */ +/** + * @brief Gets called when file descriptor is ready from epoll. + * + * @param *uf - unix_file_t + * + * @return error - clib_error_t + */ static clib_error_t * tuntap_read_ready (unix_file_t * uf) { vlib_main_t * vm = vlib_get_main(); @@ -400,11 +435,14 @@ static clib_error_t * tuntap_read_ready (unix_file_t * uf) return 0; } -/* - * tuntap_exit - * Clean up the tun/tap device +/** + * @brief Clean up the tun/tap device + * + * @param *vm - vlib_main_t + * + * @return error - clib_error_t + * */ - static clib_error_t * tuntap_exit (vlib_main_t * vm) { @@ -446,6 +484,15 @@ tuntap_exit (vlib_main_t * vm) VLIB_MAIN_LOOP_EXIT_FUNCTION (tuntap_exit); +/** + * @brief CLI function for tun/tap config + * + * @param *vm - vlib_main_t + * @param *input - unformat_input_t + * + * @return error - clib_error_t + * + */ static clib_error_t * tuntap_config (vlib_main_t * vm, unformat_input_t * input) { @@ -654,6 +701,16 @@ tuntap_config (vlib_main_t * vm, unformat_input_t * input) VLIB_CONFIG_FUNCTION (tuntap_config, "tuntap"); +/** + * @brief Add or Del IP4 address to tun/tap interface + * + * @param *im - ip4_main_t + * @param opaque - uword + * @param sw_if_index - u32 + * @param *address - ip4_address_t + * @param is_delete - u32 + * + */ void tuntap_ip4_add_del_interface_address (ip4_main_t * im, uword opaque, @@ -668,15 +725,15 @@ tuntap_ip4_add_del_interface_address (ip4_main_t * im, subif_address_t subif_addr, * ap; uword * p; - /* Tuntap disabled, or using a "normal" interface. */ + /** Tuntap disabled, or using a "normal" interface. */ if (tm->have_normal_interface || tm->dev_tap_fd < 0) return; - /* See if we already know about this subif */ + /** See if we already know about this subif */ memset (&subif_addr, 0, sizeof (subif_addr)); subif_addr.sw_if_index = sw_if_index; clib_memcpy (&subif_addr.addr, address, sizeof (*address)); - + p = mhash_get (&tm->subif_mhash, &subif_addr); if (p) @@ -728,21 +785,31 @@ tuntap_ip4_add_del_interface_address (ip4_main_t * im, clib_unix_warning ("ioctl SIOCSIFFLAGS"); } -/* - * $$$$ gross workaround for a known #include bug +/** + * @brief workaround for a known #include bug * #include causes multiple definitions if * netinet/in.h is also included. */ struct in6_ifreq { struct in6_addr ifr6_addr; u32 ifr6_prefixlen; - int ifr6_ifindex; + int ifr6_ifindex; }; -/* +/** + * @brief Add or Del tun/tap interface address + * * Both the v6 interface address API and the way ifconfig * displays subinterfaces differ from their v4 couterparts. * The code given here seems to work but YMMV. + * + * @param *im - ip6_main_t + * @param opaque - uword + * @param sw_if_index - u32 + * @param *address - ip6_address_t + * @param address_length - u32 + * @param if_address_index - u32 + * @param is_delete - u32 */ void tuntap_ip6_add_del_interface_address (ip6_main_t * im, @@ -768,7 +835,7 @@ tuntap_ip6_add_del_interface_address (ip6_main_t * im, subif_addr.sw_if_index = sw_if_index; subif_addr.is_v6 = 1; clib_memcpy (&subif_addr.addr, address, sizeof (*address)); - + p = mhash_get (&tm->subif_mhash, &subif_addr); if (p) @@ -829,6 +896,14 @@ tuntap_ip6_add_del_interface_address (ip6_main_t * im, } } +/** + * @brief TX the tun/tap frame + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + */ static void tuntap_punt_frame (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -838,6 +913,14 @@ tuntap_punt_frame (vlib_main_t * vm, vlib_frame_free (vm, node, frame); } +/** + * @brief Free the tun/tap frame + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + */ static void tuntap_nopunt_frame (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -853,6 +936,15 @@ VNET_HW_INTERFACE_CLASS (tuntap_interface_class,static) = { .name = "tuntap", }; +/** + * @brief Format tun/tap interface name + * + * @param *s - u8 - formatter string + * @param *args - va_list + * + * @return *s - u8 - formatted string + * + */ static u8 * format_tuntap_interface_name (u8 * s, va_list * args) { u32 i = va_arg (*args, u32); @@ -861,6 +953,16 @@ static u8 * format_tuntap_interface_name (u8 * s, va_list * args) return s; } +/** + * @brief TX packet out tun/tap + * + * @param *vm - vlib_main_t + * @param *node - vlib_node_runtime_t + * @param *frame - vlib_frame_t + * + * @return n_buffers - uword - Packets transmitted + * + */ static uword tuntap_intfc_tx (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -884,6 +986,14 @@ VNET_DEVICE_CLASS (tuntap_dev_class,static) = { .format_device_name = format_tuntap_interface_name, }; +/** + * @brief tun/tap node init + * + * @param *vm - vlib_main_t + * + * @return error - clib_error_t + * + */ static clib_error_t * tuntap_init (vlib_main_t * vm) { diff --git a/vnet/vnet/unix/tuntap.h b/vnet/vnet/unix/tuntap.h index ba0b77938e8..d7f96caeaf0 100644 --- a/vnet/vnet/unix/tuntap.h +++ b/vnet/vnet/unix/tuntap.h @@ -1,4 +1,4 @@ -/* +/* *------------------------------------------------------------------ * tuntap.h - kernel stack (reverse) punt/inject path * @@ -16,10 +16,9 @@ * limitations under the License. *------------------------------------------------------------------ */ - -/* - * Call from some VLIB_INIT_FUNCTION to set the Linux kernel - * inject node name. +/** + * @file + * @brief Call from VLIB_INIT_FUNCTION to set the Linux kernel inject node name. */ void register_tuntap_inject_node_name (char *name); -- 2.16.6