X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vnet%2Fvnet%2Fnsh-vxlan-gpe%2Fdecap.c;h=76003e6003fe87a80a08bd9f8ec620635d7b5446;hb=8f15e922f7f32c1beca5baa9a1a7f187ff5bdc4f;hp=62bb0f81dc744a124d9ff254bf1e49051710b6f2;hpb=cb9cadad578297ffd78fa8a33670bdf1ab669e7e;p=vpp.git diff --git a/vnet/vnet/nsh-vxlan-gpe/decap.c b/vnet/vnet/nsh-vxlan-gpe/decap.c index 62bb0f81dc7..76003e6003f 100644 --- a/vnet/vnet/nsh-vxlan-gpe/decap.c +++ b/vnet/vnet/nsh-vxlan-gpe/decap.c @@ -59,9 +59,13 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, { u32 n_left_from, next_index, * from, * to_next; nsh_vxlan_gpe_main_t * ngm = &nsh_vxlan_gpe_main; + vnet_main_t * vnm = ngm->vnet_main; + vnet_interface_main_t * im = &vnm->interface_main; u32 last_tunnel_index = ~0; nsh_vxlan_gpe_tunnel_key_t last_key; u32 pkts_decapsulated = 0; + u32 cpu_index = os_get_cpu_number(); + u32 stats_sw_if_index, stats_n_packets, stats_n_bytes; memset (&last_key, 0xff, sizeof (last_key)); @@ -69,6 +73,8 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, n_left_from = from_frame->n_vectors; next_index = node->cached_next_index; + stats_sw_if_index = node->runtime_data[0]; + stats_n_packets = stats_n_bytes = 0; while (n_left_from > 0) { @@ -88,6 +94,7 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, nsh_vxlan_gpe_tunnel_t * t0, * t1; nsh_vxlan_gpe_tunnel_key_t key0, key1; u32 error0, error1; + u32 sw_if_index0, sw_if_index1, len0, len1; /* Prefetch next iteration. */ { @@ -162,22 +169,73 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, t0 = pool_elt_at_index (ngm->tunnels, tunnel_index0); next0 = t0->decap_next_index; + sw_if_index0 = t0->sw_if_index; + len0 = vlib_buffer_length_in_chain(vm, b0); /* Required to make the l2 tag push / pop code work on l2 subifs */ vnet_update_l2_len (b0); - /* - * ip[46] lookup in the configured FIB - * nsh-vxlan-gpe-encap, here's the encap tunnel sw_if_index - */ - vnet_buffer(b0)->sw_if_index[VLIB_TX] = t0->decap_fib_index; + if (next0 == NSH_VXLAN_GPE_INPUT_NEXT_NSH_VXLAN_GPE_ENCAP) + { + /* + * Functioning as SFF (ie "half NSH tunnel mode") + * If ingress (we are in decap.c) with NSH header, and 'decap next nsh-vxlan-gpe' then "NSH switch" + * 1. Take DST, remap to SRC, remap other keys in place + * 2. Look up new t0 as per above + * 3. Set sw_if_index[VLIB_TX] to be t0->sw_if_index + */ + uword * next_p0; + nsh_vxlan_gpe_tunnel_t * next_t0; + nsh_vxlan_gpe_tunnel_key_t next_key0; + + next_key0.src = iuvn0->ip4.dst_address.as_u32; + next_key0.vni = iuvn0->vxlan.vni_res; + next_key0.spi_si = iuvn0->nsh.spi_si; + next_key0.pad = 0; + + next_p0 = hash_get_mem (ngm->nsh_vxlan_gpe_tunnel_by_key, &next_key0); + + if (next_p0 == 0) + { + error0 = NSH_VXLAN_GPE_ERROR_NO_SUCH_TUNNEL; + goto trace0; + } + next_t0 = pool_elt_at_index (ngm->tunnels, next_p0[0]); + vnet_buffer(b0)->sw_if_index[VLIB_TX] = next_t0->sw_if_index; + + } + else + { + /* + * ip[46] lookup in the configured FIB + * nsh-vxlan-gpe-encap, here's the encap tunnel sw_if_index + */ + vnet_buffer(b0)->sw_if_index[VLIB_TX] = t0->decap_fib_index; + } + + pkts_decapsulated++; + stats_n_packets += 1; + stats_n_bytes += len0; + + if (PREDICT_FALSE(sw_if_index0 != stats_sw_if_index)) + { + stats_n_packets -= 1; + stats_n_bytes -= len0; + if (stats_n_packets) + vlib_increment_combined_counter( + im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, + cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + stats_n_packets = 1; + stats_n_bytes = len0; + stats_sw_if_index = sw_if_index0; + } trace0: b0->error = error0 ? node->errors[error0] : 0; - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { - nsh_vxlan_gpe_rx_trace_t *tr + nsh_vxlan_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->next_index = next0; tr->error = error0; @@ -211,23 +269,75 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, t1 = pool_elt_at_index (ngm->tunnels, tunnel_index1); next1 = t1->decap_next_index; + sw_if_index1 = t1->sw_if_index; + len1 = vlib_buffer_length_in_chain(vm, b1); /* Required to make the l2 tag push / pop code work on l2 subifs */ vnet_update_l2_len (b1); - /* - * ip[46] lookup in the configured FIB - * nsh-vxlan-gpe-encap, here's the encap tunnel sw_if_index - */ + if (next1 == NSH_VXLAN_GPE_INPUT_NEXT_NSH_VXLAN_GPE_ENCAP) + { + /* + * Functioning as SFF (ie "half NSH tunnel mode") + * If ingress (we are in decap.c) with NSH header, and 'decap next nsh-vxlan-gpe' then "NSH switch" + * 1. Take DST, remap to SRC, remap other keys in place + * 2. Look up new t0 as per above + * 3. Set sw_if_index[VLIB_TX] to be t0->sw_if_index + */ + uword * next_p1; + nsh_vxlan_gpe_tunnel_t * next_t1; + nsh_vxlan_gpe_tunnel_key_t next_key1; + + next_key1.src = iuvn1->ip4.dst_address.as_u32; + next_key1.vni = iuvn1->vxlan.vni_res; + next_key1.spi_si = iuvn1->nsh.spi_si; + next_key1.pad = 0; + + next_p1 = hash_get_mem (ngm->nsh_vxlan_gpe_tunnel_by_key, &next_key1); + + if (next_p1 == 0) + { + error1 = NSH_VXLAN_GPE_ERROR_NO_SUCH_TUNNEL; + goto trace1; + } + next_t1 = pool_elt_at_index (ngm->tunnels, next_p1[0]); + vnet_buffer(b1)->sw_if_index[VLIB_TX] = next_t1->sw_if_index; + + } + else + { + /* + * ip[46] lookup in the configured FIB + * nsh-vxlan-gpe-encap, here's the encap tunnel sw_if_index + */ + vnet_buffer(b1)->sw_if_index[VLIB_TX] = t1->decap_fib_index; + } + + pkts_decapsulated++; + stats_n_packets += 1; + stats_n_bytes += len1; + /* Batch stats increment on the same vxlan tunnel so counter + is not incremented per packet */ + if (PREDICT_FALSE(sw_if_index1 != stats_sw_if_index)) + { + stats_n_packets -= 1; + stats_n_bytes -= len1; + if (stats_n_packets) + vlib_increment_combined_counter( + im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, + cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + stats_n_packets = 1; + stats_n_bytes = len1; + stats_sw_if_index = sw_if_index1; + } vnet_buffer(b1)->sw_if_index[VLIB_TX] = t1->decap_fib_index; - pkts_decapsulated += 2; trace1: b1->error = error1 ? node->errors[error1] : 0; - if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) { - nsh_vxlan_gpe_rx_trace_t *tr + nsh_vxlan_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b1, sizeof (*tr)); tr->next_index = next1; tr->error = error1; @@ -251,6 +361,7 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, nsh_vxlan_gpe_tunnel_t * t0; nsh_vxlan_gpe_tunnel_key_t key0; u32 error0; + u32 sw_if_index0, len0; bi0 = from[0]; to_next[0] = bi0; @@ -283,7 +394,7 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, || (key0.as_u64[1] != last_key.as_u64[1]))) { p0 = hash_get_mem (ngm->nsh_vxlan_gpe_tunnel_by_key, &key0); - + if (p0 == 0) { error0 = NSH_VXLAN_GPE_ERROR_NO_SUCH_TUNNEL; @@ -300,23 +411,76 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, t0 = pool_elt_at_index (ngm->tunnels, tunnel_index0); next0 = t0->decap_next_index; + sw_if_index0 = t0->sw_if_index; + len0 = vlib_buffer_length_in_chain(vm, b0); /* Required to make the l2 tag push / pop code work on l2 subifs */ vnet_update_l2_len (b0); - /* - * ip[46] lookup in the configured FIB - * nsh-vxlan-gpe-encap, here's the encap tunnel sw_if_index - */ - vnet_buffer(b0)->sw_if_index[VLIB_TX] = t0->decap_fib_index; + if (next0 == NSH_VXLAN_GPE_INPUT_NEXT_NSH_VXLAN_GPE_ENCAP) + { + /* + * Functioning as SFF (ie "half NSH tunnel mode") + * If ingress (we are in decap.c) with NSH header, and 'decap next nsh-vxlan-gpe' then "NSH switch" + * 1. Take DST, remap to SRC, remap other keys in place + * 2. Look up new t0 as per above + * 3. Set sw_if_index[VLIB_TX] to be t0->sw_if_index + */ + uword * next_p0; + nsh_vxlan_gpe_tunnel_t * next_t0; + nsh_vxlan_gpe_tunnel_key_t next_key0; + + next_key0.src = iuvn0->ip4.dst_address.as_u32; + next_key0.vni = iuvn0->vxlan.vni_res; + next_key0.spi_si = iuvn0->nsh.spi_si; + next_key0.pad = 0; + + next_p0 = hash_get_mem (ngm->nsh_vxlan_gpe_tunnel_by_key, &next_key0); + + if (next_p0 == 0) + { + error0 = NSH_VXLAN_GPE_ERROR_NO_SUCH_TUNNEL; + goto trace00; + } + next_t0 = pool_elt_at_index (ngm->tunnels, next_p0[0]); + vnet_buffer(b0)->sw_if_index[VLIB_TX] = next_t0->sw_if_index; + + } + else + { + /* + * ip[46] lookup in the configured FIB + * nsh-vxlan-gpe-encap, here's the encap tunnel sw_if_index + */ + vnet_buffer(b0)->sw_if_index[VLIB_TX] = t0->decap_fib_index; + } + pkts_decapsulated ++; + stats_n_packets += 1; + stats_n_bytes += len0; + + /* Batch stats increment on the same nsh-vxlan-gpe tunnel so counter + is not incremented per packet */ + if (PREDICT_FALSE(sw_if_index0 != stats_sw_if_index)) + { + stats_n_packets -= 1; + stats_n_bytes -= len0; + if (stats_n_packets) + vlib_increment_combined_counter( + im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, + cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); + stats_n_packets = 1; + stats_n_bytes = len0; + stats_sw_if_index = sw_if_index0; + } + trace00: b0->error = error0 ? node->errors[error0] : 0; - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { - nsh_vxlan_gpe_rx_trace_t *tr + nsh_vxlan_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->next_index = next0; tr->error = error0; @@ -331,8 +495,16 @@ nsh_vxlan_gpe_input (vlib_main_t * vm, vlib_put_next_frame (vm, node, next_index, n_left_to_next); } vlib_node_increment_counter (vm, nsh_vxlan_gpe_input_node.index, - NSH_VXLAN_GPE_ERROR_DECAPSULATED, + NSH_VXLAN_GPE_ERROR_DECAPSULATED, pkts_decapsulated); + /* Increment any remaining batch stats */ + if (stats_n_packets) + { + vlib_increment_combined_counter( + im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, cpu_index, + stats_sw_if_index, stats_n_packets, stats_n_bytes); + node->runtime_data[0] = stats_sw_if_index; + } return from_frame->n_vectors; }