X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Finterface_output.c;h=89ce274a6cc094eb213c9b908ef0eecdbbe83648;hb=75b9f45;hp=cdf18738193b5bc54241ca893ccf3b228897e84a;hpb=10ae76627b19f26d857bdeffae9e2c2fac6e38a8;p=vpp.git diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c index cdf18738193..89ce274a6cc 100644 --- a/src/vnet/interface_output.c +++ b/src/vnet/interface_output.c @@ -38,6 +38,10 @@ */ #include +#include +#include +#include +#include #include typedef struct @@ -55,7 +59,7 @@ format_vnet_interface_output_trace (u8 * s, va_list * va) interface_output_trace_t *t = va_arg (*va, interface_output_trace_t *); vnet_main_t *vnm = vnet_get_main (); vnet_sw_interface_t *si; - uword indent; + u32 indent; if (t->sw_if_index != (u32) ~ 0) { @@ -153,14 +157,57 @@ vnet_interface_output_trace (vlib_main_t * vm, } } -uword -vnet_interface_output_node (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) +static_always_inline void +calc_checksums (vlib_main_t * vm, vlib_buffer_t * b) +{ + ip4_header_t *ip4; + ip6_header_t *ip6; + tcp_header_t *th; + udp_header_t *uh; + + int is_ip4 = (b->flags & VNET_BUFFER_F_IS_IP4) != 0; + int is_ip6 = (b->flags & VNET_BUFFER_F_IS_IP6) != 0; + + ASSERT (!(is_ip4 && is_ip6)); + + ip4 = (ip4_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset); + ip6 = (ip6_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset); + th = (tcp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset); + uh = (udp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset); + + if (is_ip4) + { + ip4 = (ip4_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset); + if (b->flags & VNET_BUFFER_F_OFFLOAD_IP_CKSUM) + ip4->checksum = ip4_header_checksum (ip4); + if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM) + th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ip4); + if (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM) + uh->checksum = ip4_tcp_udp_compute_checksum (vm, b, ip4); + } + if (is_ip6) + { + int bogus; + if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM) + th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus); + if (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM) + uh->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus); + } + + b->flags &= ~VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; + b->flags &= ~VNET_BUFFER_F_OFFLOAD_UDP_CKSUM; + b->flags &= ~VNET_BUFFER_F_OFFLOAD_IP_CKSUM; +} + +static_always_inline uword +vnet_interface_output_node_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame, vnet_main_t * vnm, + vnet_hw_interface_t * hi, + int do_tx_offloads) { - vnet_main_t *vnm = vnet_get_main (); vnet_interface_output_runtime_t *rt = (void *) node->runtime_data; vnet_sw_interface_t *si; - vnet_hw_interface_t *hi; u32 n_left_to_tx, *from, *from_end, *to_tx; u32 n_bytes, n_buffers, n_packets; u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3; @@ -234,6 +281,7 @@ vnet_interface_output_node (vlib_main_t * vm, u32 bi0, bi1, bi2, bi3; vlib_buffer_t *b0, *b1, *b2, *b3; u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3; + u32 or_flags; /* Prefetch next iteration. */ vlib_prefetch_buffer_with_index (vm, from[4], LOAD); @@ -280,10 +328,10 @@ vnet_interface_output_node (vlib_main_t * vm, if (PREDICT_FALSE (current_config_index != ~0)) { - b0->feature_arc_index = arc; - b1->feature_arc_index = arc; - b2->feature_arc_index = arc; - b3->feature_arc_index = arc; + vnet_buffer (b0)->feature_arc_index = arc; + vnet_buffer (b1)->feature_arc_index = arc; + vnet_buffer (b2)->feature_arc_index = arc; + vnet_buffer (b3)->feature_arc_index = arc; b0->current_config_index = current_config_index; b1->current_config_index = current_config_index; b2->current_config_index = current_config_index; @@ -324,6 +372,22 @@ vnet_interface_output_node (vlib_main_t * vm, thread_index, tx_swif3, 1, n_bytes_b3); } + + or_flags = b0->flags | b1->flags | b2->flags | b3->flags; + + if (do_tx_offloads) + { + if (or_flags & + (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM | + VNET_BUFFER_F_OFFLOAD_UDP_CKSUM | + VNET_BUFFER_F_OFFLOAD_IP_CKSUM)) + { + calc_checksums (vm, b0); + calc_checksums (vm, b1); + calc_checksums (vm, b2); + calc_checksums (vm, b3); + } + } } while (from + 1 <= from_end && n_left_to_tx >= 1) @@ -351,7 +415,7 @@ vnet_interface_output_node (vlib_main_t * vm, if (PREDICT_FALSE (current_config_index != ~0)) { - b0->feature_arc_index = arc; + vnet_buffer (b0)->feature_arc_index = arc; b0->current_config_index = current_config_index; } @@ -363,6 +427,9 @@ vnet_interface_output_node (vlib_main_t * vm, thread_index, tx_swif0, 1, n_bytes_b0); } + + if (do_tx_offloads) + calc_checksums (vm, b0); } vlib_put_next_frame (vm, node, next_index, n_left_to_tx); @@ -376,6 +443,23 @@ vnet_interface_output_node (vlib_main_t * vm, return n_buffers; } +static uword +vnet_interface_output_node (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + vnet_main_t *vnm = vnet_get_main (); + vnet_hw_interface_t *hi; + vnet_interface_output_runtime_t *rt = (void *) node->runtime_data; + hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index); + + if (hi->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD) + return vnet_interface_output_node_inline (vm, node, frame, vnm, hi, + /* do_tx_offloads */ 0); + else + return vnet_interface_output_node_inline (vm, node, frame, vnm, hi, + /* do_tx_offloads */ 1); +} + VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node); CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node); @@ -429,8 +513,8 @@ vnet_per_buffer_interface_output (vlib_main_t * vm, vnet_buffer (b1)->sw_if_index [VLIB_TX]); - next0 = hi0->hw_if_index; - next1 = hi1->hw_if_index; + next0 = hi0->output_node_next_index; + next1 = hi1->output_node_next_index; vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, @@ -457,7 +541,7 @@ vnet_per_buffer_interface_output (vlib_main_t * vm, vnet_buffer (b0)->sw_if_index [VLIB_TX]); - next0 = hi0->hw_if_index; + next0 = hi0->output_node_next_index; vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); @@ -1005,6 +1089,12 @@ VNET_FEATURE_INIT (span_tx, static) = { .runs_before = VNET_FEATURES ("interface-tx"), }; +VNET_FEATURE_INIT (ipsec_if_tx, static) = { + .arc_name = "interface-output", + .node_name = "ipsec-if-output", + .runs_before = VNET_FEATURES ("interface-tx"), +}; + VNET_FEATURE_INIT (interface_tx, static) = { .arc_name = "interface-output", .node_name = "interface-tx", @@ -1020,12 +1110,13 @@ vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm, vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); u32 next_index; - next_index = vlib_node_add_next_with_slot - (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, - hi->output_node_index, - /* next_index */ hw_if_index); + if (hi->output_node_index == 0) + return 0; - ASSERT (next_index == hw_if_index); + next_index = vlib_node_add_next + (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, + hi->output_node_index); + hi->output_node_next_index = next_index; return 0; } @@ -1033,6 +1124,18 @@ vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm, VNET_HW_INTERFACE_ADD_DEL_FUNCTION (vnet_per_buffer_interface_output_hw_interface_add_del); +void +vnet_set_interface_output_node (vnet_main_t * vnm, + u32 hw_if_index, u32 node_index) +{ + ASSERT (node_index); + vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); + u32 next_index = vlib_node_add_next + (vnm->vlib_main, vnet_per_buffer_interface_output_node.index, node_index); + hi->output_node_next_index = next_index; + hi->output_node_index = node_index; +} + static clib_error_t * pcap_drop_trace_command_fn (vlib_main_t * vm, unformat_input_t * input,