X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fsrv6-ad%2Fnode.c;h=776d283dbe759c2ddedc41468041272d5db450b8;hb=f5fa5ae2b021f946fbb8ec56e692459cd34bc7fb;hp=73957f55ab6fcef25f6031f42cd75623765df21a;hpb=b4d43d7901b49bdda4345adb86b4d15a5d72f7ff;p=vpp.git diff --git a/src/plugins/srv6-ad/node.c b/src/plugins/srv6-ad/node.c index 73957f55ab6..776d283dbe7 100644 --- a/src/plugins/srv6-ad/node.c +++ b/src/plugins/srv6-ad/node.c @@ -27,6 +27,7 @@ typedef struct typedef struct { + u8 error; ip6_address_t src, dst; } srv6_ad_rewrite_trace_t; @@ -47,6 +48,11 @@ format_srv6_ad_rewrite_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); srv6_ad_rewrite_trace_t *t = va_arg (*args, srv6_ad_rewrite_trace_t *); + if (PREDICT_FALSE (t->error != 0)) + { + return format (s, "SRv6-AD-rewrite: cache is empty"); + } + return format (s, "SRv6-AD-rewrite: src %U dst %U", format_ip6_address, &t->src, format_ip6_address, &t->dst); } @@ -86,6 +92,7 @@ typedef enum SRV6_AD_LOCALSID_NEXT_ERROR, SRV6_AD_LOCALSID_NEXT_REWRITE4, SRV6_AD_LOCALSID_NEXT_REWRITE6, + SRV6_AD_LOCALSID_NEXT_INTERFACE, SRV6_AD_LOCALSID_N_NEXT, } srv6_ad_localsid_next_t; @@ -143,9 +150,10 @@ end_ad_processing (vlib_buffer_t * b0, next_ext_header = ip6_ext_next_header (next_ext_header); } - /* Make sure next header is IP */ - if (PREDICT_FALSE - (next_hdr != IP_PROTOCOL_IPV6 && next_hdr != IP_PROTOCOL_IP_IN_IP)) + /* Make sure next header is valid */ + if (PREDICT_FALSE (next_hdr != IP_PROTOCOL_IPV6 && + next_hdr != IP_PROTOCOL_IP_IN_IP && + next_hdr != IP_PROTOCOL_IP6_NONXT)) { return; } @@ -154,19 +162,33 @@ end_ad_processing (vlib_buffer_t * b0, ls0_mem = ls0->plugin_mem; /* Cache IP header and extensions */ - vec_validate (ls0_mem->rewrite, total_size - 1); + if (PREDICT_FALSE (total_size > ls0_mem->rw_len)) + { + vec_validate (ls0_mem->rewrite, total_size - 1); + } clib_memcpy (ls0_mem->rewrite, ip0, total_size); + ls0_mem->rw_len = total_size; /* Remove IP header and extensions */ vlib_buffer_advance (b0, total_size); - /* Set Xconnect adjacency to VNF */ - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0_mem->nh_adj; + if (next_hdr == IP_PROTOCOL_IP6_NONXT) + { + /* Set output interface */ + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0_mem->sw_if_index_out; + + /* Set next node to interface-output */ + *next0 = SRV6_AD_LOCALSID_NEXT_INTERFACE; + } + else + { + /* Set Xconnect adjacency to VNF */ + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0_mem->nh_adj; - if (ls0_mem->ip_version == DA_IP4) - *next0 = SRV6_AD_LOCALSID_NEXT_REWRITE4; - else if (ls0_mem->ip_version == DA_IP6) - *next0 = SRV6_AD_LOCALSID_NEXT_REWRITE6; + /* Set next node to ip-rewrite */ + *next0 = (next_hdr == IP_PROTOCOL_IPV6) ? + SRV6_AD_LOCALSID_NEXT_REWRITE6 : SRV6_AD_LOCALSID_NEXT_REWRITE4; + } } /** @@ -184,8 +206,6 @@ srv6_ad_localsid_fn (vlib_main_t * vm, n_left_from = frame->n_vectors; next_index = node->cached_next_index; - u32 thread_index = vlib_get_thread_index (); - while (n_left_from > 0) { u32 n_left_to_next; @@ -233,9 +253,10 @@ srv6_ad_localsid_fn (vlib_main_t * vm, SRV6_AD_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) : &(sm->sr_ls_valid_counters)), - thread_index, ls0 - sm->localsids, - 1, vlib_buffer_length_in_chain (vm, - b0)); + vm->thread_index, + ls0 - sm->localsids, 1, + vlib_buffer_length_in_chain (vm, + b0)); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); @@ -260,6 +281,7 @@ VLIB_REGISTER_NODE (srv6_ad_localsid_node) = { .next_nodes = { [SRV6_AD_LOCALSID_NEXT_REWRITE4] = "ip4-rewrite", [SRV6_AD_LOCALSID_NEXT_REWRITE6] = "ip6-rewrite", + [SRV6_AD_LOCALSID_NEXT_INTERFACE] = "interface-output", [SRV6_AD_LOCALSID_NEXT_ERROR] = "error-drop", }, }; @@ -268,6 +290,140 @@ VLIB_REGISTER_NODE (srv6_ad_localsid_node) = { /******************************* Rewriting node *******************************/ +/** + * @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation + */ +static uword +srv6_ad2_rewrite_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + ip6_sr_main_t *srm = &sr_main; + srv6_ad_main_t *sm = &srv6_ad_main; + u32 n_left_from, next_index, *from, *to_next; + u32 cnt_packets = 0; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + /* TODO: Dual/quad loop */ + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t *b0; + ethernet_header_t *en0; + ip6_header_t *ip0 = 0; + ip6_sr_localsid_t *ls0; + srv6_ad_localsid_t *ls0_mem; + u32 next0 = SRV6_AD_REWRITE_NEXT_LOOKUP; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + en0 = vlib_buffer_get_current (b0); + ls0 = pool_elt_at_index (srm->localsids, + sm->sw_iface_localsid2[vnet_buffer + (b0)->sw_if_index + [VLIB_RX]]); + ls0_mem = ls0->plugin_mem; + + if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL)) + { + next0 = SRV6_AD_REWRITE_NEXT_ERROR; + b0->error = node->errors[SRV6_AD_REWRITE_COUNTER_NO_RW]; + } + else + { + ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >= + (ls0_mem->rw_len + b0->current_data)); + + clib_memcpy (((u8 *) en0) - ls0_mem->rw_len, + ls0_mem->rewrite, ls0_mem->rw_len); + vlib_buffer_advance (b0, -(word) ls0_mem->rw_len); + + ip0 = vlib_buffer_get_current (b0); + + ip0->payload_length = + clib_host_to_net_u16 (b0->current_length - + sizeof (ip6_header_t)); + } + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + srv6_ad_rewrite_trace_t *tr = + vlib_add_trace (vm, node, b0, sizeof *tr); + tr->error = 0; + + if (next0 == SRV6_AD_REWRITE_NEXT_ERROR) + { + tr->error = 1; + } + else + { + clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, + sizeof tr->src.as_u8); + clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8, + sizeof tr->dst.as_u8); + } + } + + /* Increment per-SID AD rewrite counters */ + vlib_increment_combined_counter (((next0 == + SRV6_AD_LOCALSID_NEXT_ERROR) ? + &(sm->invalid_counters) : + &(sm->valid_counters)), + vm->thread_index, ls0_mem->index, + 1, vlib_buffer_length_in_chain (vm, + b0)); + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + + cnt_packets++; + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + /* Update counters */ + vlib_node_increment_counter (vm, srv6_ad4_rewrite_node.index, + SRV6_AD_REWRITE_COUNTER_PROCESSED, + cnt_packets); + + return frame->n_vectors; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (srv6_ad2_rewrite_node) = { + .function = srv6_ad2_rewrite_fn, + .name = "srv6-ad2-rewrite", + .vector_size = sizeof (u32), + .format_trace = format_srv6_ad_rewrite_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = SRV6_AD_REWRITE_N_COUNTERS, + .error_strings = srv6_ad_rewrite_counter_strings, + .n_next_nodes = SRV6_AD_REWRITE_N_NEXT, + .next_nodes = { + [SRV6_AD_REWRITE_NEXT_LOOKUP] = "ip6-lookup", + [SRV6_AD_REWRITE_NEXT_ERROR] = "error-drop", + }, +}; +/* *INDENT-ON* */ + + /** * @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation */ @@ -326,11 +482,11 @@ srv6_ad4_rewrite_fn (vlib_main_t * vm, else { ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >= - (vec_len (ls0_mem->rewrite) + b0->current_data)); + (ls0_mem->rw_len + b0->current_data)); - clib_memcpy (((u8 *) ip0_encap) - vec_len (ls0_mem->rewrite), - ls0_mem->rewrite, vec_len (ls0_mem->rewrite)); - vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite)); + clib_memcpy (((u8 *) ip0_encap) - ls0_mem->rw_len, + ls0_mem->rewrite, ls0_mem->rw_len); + vlib_buffer_advance (b0, -(word) ls0_mem->rw_len); ip0 = vlib_buffer_get_current (b0); @@ -342,7 +498,7 @@ srv6_ad4_rewrite_fn (vlib_main_t * vm, ip0_encap->checksum = checksum0; /* Update outer IPv6 length (in case it has changed) */ - new_l0 = vec_len (ls0_mem->rewrite) - sizeof (ip6_header_t) + + new_l0 = ls0_mem->rw_len - sizeof (ip6_header_t) + clib_net_to_host_u16 (ip0_encap->length); ip0->payload_length = clib_host_to_net_u16 (new_l0); } @@ -352,12 +508,30 @@ srv6_ad4_rewrite_fn (vlib_main_t * vm, { srv6_ad_rewrite_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof *tr); - clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, - sizeof tr->src.as_u8); - clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8, - sizeof tr->dst.as_u8); + tr->error = 0; + + if (next0 == SRV6_AD_REWRITE_NEXT_ERROR) + { + tr->error = 1; + } + else + { + clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, + sizeof tr->src.as_u8); + clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8, + sizeof tr->dst.as_u8); + } } + /* Increment per-SID AD rewrite counters */ + vlib_increment_combined_counter (((next0 == + SRV6_AD_LOCALSID_NEXT_ERROR) ? + &(sm->invalid_counters) : + &(sm->valid_counters)), + vm->thread_index, ls0_mem->index, + 1, vlib_buffer_length_in_chain (vm, + b0)); + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); @@ -450,11 +624,11 @@ srv6_ad6_rewrite_fn (vlib_main_t * vm, else { ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >= - (vec_len (ls0_mem->rewrite) + b0->current_data)); + (ls0_mem->rw_len + b0->current_data)); - clib_memcpy (((u8 *) ip0_encap) - vec_len (ls0_mem->rewrite), - ls0_mem->rewrite, vec_len (ls0_mem->rewrite)); - vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite)); + clib_memcpy (((u8 *) ip0_encap) - ls0_mem->rw_len, + ls0_mem->rewrite, ls0_mem->rw_len); + vlib_buffer_advance (b0, -(word) ls0_mem->rw_len); ip0 = vlib_buffer_get_current (b0); @@ -462,7 +636,7 @@ srv6_ad6_rewrite_fn (vlib_main_t * vm, ip0_encap->hop_limit -= 1; /* Update outer IPv6 length (in case it has changed) */ - new_l0 = vec_len (ls0_mem->rewrite) + + new_l0 = ls0_mem->rw_len + clib_net_to_host_u16 (ip0_encap->payload_length); ip0->payload_length = clib_host_to_net_u16 (new_l0); } @@ -472,12 +646,30 @@ srv6_ad6_rewrite_fn (vlib_main_t * vm, { srv6_ad_rewrite_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof *tr); - clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, - sizeof tr->src.as_u8); - clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8, - sizeof tr->dst.as_u8); + tr->error = 0; + + if (next0 == SRV6_AD_REWRITE_NEXT_ERROR) + { + tr->error = 1; + } + else + { + clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, + sizeof tr->src.as_u8); + clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8, + sizeof tr->dst.as_u8); + } } + /* Increment per-SID AD rewrite counters */ + vlib_increment_combined_counter (((next0 == + SRV6_AD_LOCALSID_NEXT_ERROR) ? + &(sm->invalid_counters) : + &(sm->valid_counters)), + vm->thread_index, ls0_mem->index, + 1, vlib_buffer_length_in_chain (vm, + b0)); + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0);