diff options
author | Dave Barach <dave@barachs.net> | 2018-10-30 10:24:17 -0400 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2018-10-30 19:21:51 +0000 |
commit | 5e36c3cd6b74d0b6adf483934eebbf50f5f570b2 (patch) | |
tree | 37ebbbfbc96c67c72eede70c8208ccd3c8873f9b | |
parent | 8f8994ad599fc556e2325a4f5f9ea33eeb3e25b4 (diff) |
DOC-ONLY: document packet intialization from scratch
Minor clean-up in the home gateway use-case documentation
Change-Id: I7d3aaea8cec62248daf7814b21a8acb574ac12a1
Signed-off-by: Dave Barach <dave@barachs.net>
-rw-r--r-- | docs/gettingstarted/developers/vnet.md | 121 | ||||
-rw-r--r-- | docs/usecases/homegateway.rst | 45 |
2 files changed, 126 insertions, 40 deletions
diff --git a/docs/gettingstarted/developers/vnet.md b/docs/gettingstarted/developers/vnet.md index ab081b08302..cd9e22f6428 100644 --- a/docs/gettingstarted/developers/vnet.md +++ b/docs/gettingstarted/developers/vnet.md @@ -125,6 +125,127 @@ looking for similar tasks, and think about using the same coding pattern. It is not uncommon to recode a given graph node dispatch function several times during performance optimization. +Creating Packets from Scratch +----------------------------- + +At times, it's necessary to create packets from scratch and send +them. Tasks like sending keepalives or actively opening connections +come to mind. Its not difficult, but accurate buffer metadata setup is +required. + +### Allocating Buffers + +Use vlib_buffer_alloc, which allocates a set of buffer indices. For +low-performance applications, it's OK to allocate one buffer at a +time. Note that vlib_buffer_alloc(...) does NOT initialize buffer +metadata. See below. + +In high-performance cases, allocate a vector of buffer indices, +and hand them out from the end of the vector; decrement _vec_len(..) +as buffer indices are allocated. See tcp_alloc_tx_buffers(...) and +tcp_get_free_buffer_index(...) for an example. + +### Buffer Initialization Example + +The following example shows the **main points**, but is not to be +blindly cut-'n-pasted. + +```c + u32 bi0; + vlib_buffer_t *b0; + ip4_header_t *ip; + udp_header_t *udp; + vlib_buffer_free_list_t *fl; + + /* Allocate a buffer */ + if (vlib_buffer_alloc (vm, &bi0, 1) != 1) + return -1; + + b0 = vlib_get_buffer (vm, bi0); + + /* Initialize the buffer */ + fl = vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); + vlib_buffer_init_for_free_list (b0, fl); + VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0); + + /* At this point b0->current_data = 0, b0->current_length = 0 */ + + /* + * Copy data into the buffer. This example ASSUMES that data will fit + * in a single buffer, and is e.g. an ip4 packet. + */ + if (have_packet_rewrite) + { + clib_memcpy (b0->data, data, vec_len (data)); + b0->current_length = vec_len (data); + } + else + { + /* OR, build a udp-ip packet (for example) */ + ip = vlib_buffer_get_current (b0); + udp = (udp_header_t *) (ip + 1); + data_dst = (u8 *) (udp + 1); + + ip->ip_version_and_header_length = 0x45; + ip->ttl = 254; + ip->protocol = IP_PROTOCOL_UDP; + ip->length = clib_host_to_net_u16 (sizeof (*ip) + sizeof (*udp) + + vec_len(udp_data)); + ip->src_address.as_u32 = src_address->as_u32; + ip->dst_address.as_u32 = dst_address->as_u32; + udp->src_port = clib_host_to_net_u16 (src_port); + udp->dst_port = clib_host_to_net_u16 (dst_port); + udp->length = clib_host_to_net_u16 (vec_len (udp_data)); + clib_memcpy (data_dst, udp_data, vec_len(udp_data)); + + if (compute_udp_checksum) + { + /* RFC 7011 section 10.3.2. */ + udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip); + if (udp->checksum == 0) + udp->checksum = 0xffff; + } + b0->current_length = vec_len (sizeof (*ip) + sizeof (*udp) + + vec_len (udp_data)); + + } + b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID; + + /* sw_if_index 0 is the "local" interface, which always exists */ + vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0; + + /* Use the default FIB index for tx lookup. Set non-zero to use another fib */ + vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0; + +``` + +If your use-case calls for large packet transmission, use +vlib_buffer_chain_append_data_with_alloc(...) to create the requisite +buffer chain. + +### Enqueueing packets for lookup and transmission + +The simplest way to send a set of packets is to use +vlib_get_frame_to_node(...) to allocate fresh frame(s) to +ip4_lookup_node or ip6_lookup_node, add the constructed buffer +indices, and dispatch the frame using vlib_put_frame_to_node(...). + +```c + vlib_frame_t *f; + f = vlib_get_frame_to_node (vm, ip4_lookup_node.index); + f->n_vectors = vec_len(buffer_indices_to_send); + to_next = vlib_frame_vector_args (f); + + for (i = 0; i < vec_len (buffer_indices_to_send); i++) + to_next[i] = buffer_indices_to_send[i]; + + vlib_put_frame_to_node (vm, ip4_lookup_node_index, f); +``` + +It is inefficient to allocate and schedule single packet frames. +That's typical in case you need to send one packet per second, but +should **not** occur in a for-loop! + Packet tracer ------------- diff --git a/docs/usecases/homegateway.rst b/docs/usecases/homegateway.rst index f6d7ec9a329..077d5a2a961 100644 --- a/docs/usecases/homegateway.rst +++ b/docs/usecases/homegateway.rst @@ -77,9 +77,9 @@ vpp configuration:: set int state GigabitEthernet0/14/0 up comment { dhcp server and host-stack access } - tap connect lstack address 192.168.1.2/24 - set int l2 bridge tapcli-0 1 - set int state tapcli-0 up + create tap host-if-name lstack host-ip4-addr 192.168.1.2/24 host-ip4-gw 192.168.1.1 + set int l2 bridge tap0 1 + set int state tap0 up comment { Configure NAT} nat44 add interface address GigabitEthernet3/0/0 @@ -96,13 +96,11 @@ vpp configuration:: comment { bin dns_enable_disable } comment { see patch below, which adds these commands } service restart isc-dhcp-server - add default linux route via 192.168.1.1 Patches ------- -You'll need this patch to add the "service restart" and "add default -linux route" commands:: +You'll need this patch to add the "service restart" command:: diff --git a/src/vpp/vnet/main.c b/src/vpp/vnet/main.c index 6e136e19..69189c93 100644 @@ -144,40 +142,7 @@ linux route" commands:: +}; +/* *INDENT-ON* */ + - +static clib_error_t * - +add_default_linux_route_command_fn (vlib_main_t * vm, - + unformat_input_t * input, - + vlib_cli_command_t * c) - +{ - + int rv __attribute__((unused)); - + ip4_address_t ip4_addr; - + u8 *cmd; - + - + if (!unformat (input, "%U", unformat_ip4_address, &ip4_addr)) - + return clib_error_return (0, "default gateway address required..."); - + - + cmd = format (0, "/sbin/route add -net 0.0.0.0/0 gw %U", - + format_ip4_address, &ip4_addr); - + vec_add1 (cmd, 0); - + - + rv = system (cmd); - + - + vlib_cli_output (vm, "%s", cmd); - + - + vec_free(cmd); - + - + return 0; - +} - + - +/* *INDENT-OFF* */ - +VLIB_CLI_COMMAND (add_default_linux_route_command, static) = { - + .path = "add default linux route via", - + .short_help = "Adds default linux route: 0.0.0.0/0 via <addr>", - + .function = add_default_linux_route_command_fn, - +}; - +/* *INDENT-ON* */ - + - + + Using the temporal mac filter plugin ------------------------------------ |