diff options
Diffstat (limited to 'src/vnet/dpo/mpls_disposition.c')
-rw-r--r-- | src/vnet/dpo/mpls_disposition.c | 316 |
1 files changed, 235 insertions, 81 deletions
diff --git a/src/vnet/dpo/mpls_disposition.c b/src/vnet/dpo/mpls_disposition.c index 77429de4116..2956e541d57 100644 --- a/src/vnet/dpo/mpls_disposition.c +++ b/src/vnet/dpo/mpls_disposition.c @@ -42,38 +42,55 @@ mpls_disp_dpo_get_index (mpls_disp_dpo_t *mdd) return (mdd - mpls_disp_dpo_pool); } -index_t +void mpls_disp_dpo_create (dpo_proto_t payload_proto, fib_rpf_id_t rpf_id, - const dpo_id_t *dpo) + fib_mpls_lsp_mode_t mode, + const dpo_id_t *parent, + dpo_id_t *dpo) { mpls_disp_dpo_t *mdd; + dpo_type_t dtype; mdd = mpls_disp_dpo_alloc(); mdd->mdd_payload_proto = payload_proto; mdd->mdd_rpf_id = rpf_id; - - dpo_stack(DPO_MPLS_DISPOSITION, + mdd->mdd_mode = mode; + dtype = (FIB_MPLS_LSP_MODE_PIPE == mode ? + DPO_MPLS_DISPOSITION_PIPE : + DPO_MPLS_DISPOSITION_UNIFORM); + + /* + * stack this disposition object on the parent given + */ + dpo_stack(dtype, mdd->mdd_payload_proto, &mdd->mdd_dpo, - dpo); - - return (mpls_disp_dpo_get_index(mdd)); + parent); + + /* + * set up the return DPO to refer to this object + */ + dpo_set(dpo, + dtype, + payload_proto, + mpls_disp_dpo_get_index(mdd)); } u8* format_mpls_disp_dpo (u8 *s, va_list *args) { - index_t index = va_arg (*args, index_t); - u32 indent = va_arg (*args, u32); + index_t index = va_arg(*args, index_t); + u32 indent = va_arg(*args, u32); mpls_disp_dpo_t *mdd; mdd = mpls_disp_dpo_get(index); - s = format(s, "mpls-disposition:[%d]:[%U]", + s = format(s, "mpls-disposition:[%d]:[%U, %U]", index, - format_dpo_proto, mdd->mdd_payload_proto); + format_dpo_proto, mdd->mdd_payload_proto, + format_fib_mpls_lsp_mode, mdd->mdd_mode); s = format(s, "\n%U", format_white_space, indent); s = format(s, "%U", format_dpo_id, &mdd->mdd_dpo, indent+2); @@ -116,25 +133,41 @@ typedef struct mpls_label_disposition_trace_t_ index_t mdd; } mpls_label_disposition_trace_t; -extern vlib_node_registration_t ip4_mpls_label_disposition_node; -extern vlib_node_registration_t ip6_mpls_label_disposition_node; +extern vlib_node_registration_t ip4_mpls_label_disposition_pipe_node; +extern vlib_node_registration_t ip6_mpls_label_disposition_pipe_node; +extern vlib_node_registration_t ip4_mpls_label_disposition_uniform_node; +extern vlib_node_registration_t ip6_mpls_label_disposition_uniform_node; always_inline uword mpls_label_disposition_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame, - u8 payload_is_ip4, - u8 payload_is_ip6) + vlib_node_runtime_t * node, + vlib_frame_t * from_frame, + u8 payload_is_ip4, + u8 payload_is_ip6, + fib_mpls_lsp_mode_t mode) { u32 n_left_from, next_index, * from, * to_next; vlib_node_runtime_t *error_node; if (payload_is_ip4) - error_node = vlib_node_get_runtime (vm, ip4_mpls_label_disposition_node.index); + { + if (FIB_MPLS_LSP_MODE_PIPE == mode) + error_node = + vlib_node_get_runtime(vm, ip4_mpls_label_disposition_pipe_node.index); + else + error_node = + vlib_node_get_runtime(vm, ip4_mpls_label_disposition_uniform_node.index); + } else - error_node = vlib_node_get_runtime (vm, ip6_mpls_label_disposition_node.index); - - from = vlib_frame_vector_args (from_frame); + { + if (FIB_MPLS_LSP_MODE_PIPE == mode) + error_node = + vlib_node_get_runtime(vm, ip6_mpls_label_disposition_uniform_node.index); + else + error_node = + vlib_node_get_runtime(vm, ip6_mpls_label_disposition_uniform_node.index); + } + from = vlib_frame_vector_args(from_frame); n_left_from = from_frame->n_vectors; next_index = node->cached_next_index; @@ -159,14 +192,14 @@ mpls_label_disposition_inline (vlib_main_t * vm, { vlib_buffer_t * p2, * p3; - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); + p2 = vlib_get_buffer(vm, from[2]); + p3 = vlib_get_buffer(vm, from[3]); - vlib_prefetch_buffer_header (p2, STORE); - vlib_prefetch_buffer_header (p3, STORE); + vlib_prefetch_buffer_header(p2, STORE); + vlib_prefetch_buffer_header(p3, STORE); - CLIB_PREFETCH (p2->data, sizeof (ip6_header_t), STORE); - CLIB_PREFETCH (p3->data, sizeof (ip6_header_t), STORE); + CLIB_PREFETCH(p2->data, sizeof(ip6_header_t), STORE); + CLIB_PREFETCH(p3->data, sizeof(ip6_header_t), STORE); } from += 2; @@ -174,8 +207,8 @@ mpls_label_disposition_inline (vlib_main_t * vm, n_left_from -= 2; n_left_to_next -= 2; - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); + b0 = vlib_get_buffer(vm, bi0); + b1 = vlib_get_buffer(vm, bi1); /* dst lookup was done by ip4 lookup */ mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; @@ -190,30 +223,62 @@ mpls_label_disposition_inline (vlib_main_t * vm, { ip4_header_t *ip0, *ip1; - ip0 = vlib_buffer_get_current (b0); - ip1 = vlib_buffer_get_current (b1); + ip0 = vlib_buffer_get_current(b0); + ip1 = vlib_buffer_get_current(b1); /* * IPv4 input checks on the exposed IP header * including checksum */ - ip4_input_check_x2 (vm, error_node, - b0, b1, ip0, ip1, - &next0, &next1, 1); + ip4_input_check_x2(vm, error_node, + b0, b1, ip0, ip1, + &next0, &next1, 1); + + if (FIB_MPLS_LSP_MODE_UNIFORM == mode) + { + /* + * Copy the TTL from the MPLS packet into the + * exposed IP. recalc the chksum + */ + ip0->ttl = vnet_buffer(b0)->mpls.ttl; + ip1->ttl = vnet_buffer(b1)->mpls.ttl; + ip0->tos = mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp); + ip1->tos = mpls_exp_to_ip_dscp(vnet_buffer(b1)->mpls.exp); + + ip0->checksum = ip4_header_checksum(ip0); + ip1->checksum = ip4_header_checksum(ip1); + } } else if (payload_is_ip6) { ip6_header_t *ip0, *ip1; - ip0 = vlib_buffer_get_current (b0); - ip1 = vlib_buffer_get_current (b1); + ip0 = vlib_buffer_get_current(b0); + ip1 = vlib_buffer_get_current(b1); /* * IPv6 input checks on the exposed IP header */ - ip6_input_check_x2 (vm, error_node, - b0, b1, ip0, ip1, - &next0, &next1); + ip6_input_check_x2(vm, error_node, + b0, b1, ip0, ip1, + &next0, &next1); + + if (FIB_MPLS_LSP_MODE_UNIFORM == mode) + { + /* + * Copy the TTL from the MPLS packet into the + * exposed IP + */ + ip0->hop_limit = vnet_buffer(b0)->mpls.ttl; + ip1->hop_limit = vnet_buffer(b1)->mpls.ttl; + + ip6_set_traffic_class_network_order( + ip0, + mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp)); + ip6_set_traffic_class_network_order( + ip1, + mpls_exp_to_ip_dscp(vnet_buffer(b1)->mpls.exp)); + } } vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index; @@ -224,14 +289,14 @@ mpls_label_disposition_inline (vlib_main_t * vm, if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { mpls_label_disposition_trace_t *tr = - vlib_add_trace (vm, node, b0, sizeof (*tr)); + vlib_add_trace(vm, node, b0, sizeof(*tr)); tr->mdd = mddi0; } if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) { mpls_label_disposition_trace_t *tr = - vlib_add_trace (vm, node, b1, sizeof (*tr)); + vlib_add_trace(vm, node, b1, sizeof(*tr)); tr->mdd = mddi1; } @@ -254,7 +319,7 @@ mpls_label_disposition_inline (vlib_main_t * vm, n_left_from -= 1; n_left_to_next -= 1; - b0 = vlib_get_buffer (vm, bi0); + b0 = vlib_get_buffer(vm, bi0); /* dst lookup was done by ip4 lookup */ mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; @@ -265,24 +330,48 @@ mpls_label_disposition_inline (vlib_main_t * vm, { ip4_header_t *ip0; - ip0 = vlib_buffer_get_current (b0); + ip0 = vlib_buffer_get_current(b0); /* * IPv4 input checks on the exposed IP header * including checksum */ - ip4_input_check_x1 (vm, error_node, b0, ip0, &next0, 1); + ip4_input_check_x1(vm, error_node, b0, ip0, &next0, 1); + + if (FIB_MPLS_LSP_MODE_UNIFORM == mode) + { + /* + * Copy the TTL from the MPLS packet into the + * exposed IP. recalc the chksum + */ + ip0->ttl = vnet_buffer(b0)->mpls.ttl; + ip0->tos = mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp); + ip0->checksum = ip4_header_checksum(ip0); + } } else if (payload_is_ip6) { ip6_header_t *ip0; - ip0 = vlib_buffer_get_current (b0); + ip0 = vlib_buffer_get_current(b0); /* * IPv6 input checks on the exposed IP header */ - ip6_input_check_x1 (vm, error_node, b0, ip0, &next0); + ip6_input_check_x1(vm, error_node, b0, ip0, &next0); + + if (FIB_MPLS_LSP_MODE_UNIFORM == mode) + { + /* + * Copy the TTL from the MPLS packet into the + * exposed IP + */ + ip0->hop_limit = vnet_buffer(b0)->mpls.ttl; + + ip6_set_traffic_class_network_order( + ip0, + mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp)); + } } vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index; @@ -291,14 +380,14 @@ mpls_label_disposition_inline (vlib_main_t * vm, if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { mpls_label_disposition_trace_t *tr = - vlib_add_trace (vm, node, b0, sizeof (*tr)); + vlib_add_trace(vm, node, b0, sizeof(*tr)); tr->mdd = mddi0; } vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0); } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); + vlib_put_next_frame(vm, node, next_index, n_left_to_next); } return from_frame->n_vectors; } @@ -306,57 +395,103 @@ mpls_label_disposition_inline (vlib_main_t * vm, static u8 * format_mpls_label_disposition_trace (u8 * s, va_list * args) { - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - CLIB_UNUSED (mpls_label_disposition_trace_t * t); + CLIB_UNUSED(vlib_main_t * vm) = va_arg(*args, vlib_main_t *); + CLIB_UNUSED(vlib_node_t * node) = va_arg(*args, vlib_node_t *); + CLIB_UNUSED(mpls_label_disposition_trace_t * t); - t = va_arg (*args, mpls_label_disposition_trace_t *); + t = va_arg(*args, mpls_label_disposition_trace_t *); s = format(s, "disp:%d", t->mdd); return (s); } static uword -ip4_mpls_label_disposition (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +ip4_mpls_label_disposition_pipe (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) { - return (mpls_label_disposition_inline(vm, node, frame, 1, 0)); + return (mpls_label_disposition_inline(vm, node, frame, 1, 0, + FIB_MPLS_LSP_MODE_PIPE)); } -VLIB_REGISTER_NODE (ip4_mpls_label_disposition_node) = { - .function = ip4_mpls_label_disposition, - .name = "ip4-mpls-label-disposition", - .vector_size = sizeof (u32), +VLIB_REGISTER_NODE(ip4_mpls_label_disposition_pipe_node) = { + .function = ip4_mpls_label_disposition_pipe, + .name = "ip4-mpls-label-disposition-pipe", + .vector_size = sizeof(u32), .format_trace = format_mpls_label_disposition_trace, .sibling_of = "ip4-input", .n_errors = IP4_N_ERROR, .error_strings = ip4_error_strings, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_mpls_label_disposition_node, - ip4_mpls_label_disposition) +VLIB_NODE_FUNCTION_MULTIARCH(ip4_mpls_label_disposition_pipe_node, + ip4_mpls_label_disposition_pipe) static uword -ip6_mpls_label_disposition (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +ip6_mpls_label_disposition_pipe (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) { - return (mpls_label_disposition_inline(vm, node, frame, 0, 1)); + return (mpls_label_disposition_inline(vm, node, frame, 0, 1, + FIB_MPLS_LSP_MODE_PIPE)); } -VLIB_REGISTER_NODE (ip6_mpls_label_disposition_node) = { - .function = ip6_mpls_label_disposition, - .name = "ip6-mpls-label-disposition", - .vector_size = sizeof (u32), +VLIB_REGISTER_NODE(ip6_mpls_label_disposition_pipe_node) = { + .function = ip6_mpls_label_disposition_pipe, + .name = "ip6-mpls-label-disposition-pipe", + .vector_size = sizeof(u32), .format_trace = format_mpls_label_disposition_trace, .sibling_of = "ip6-input", .n_errors = IP6_N_ERROR, .error_strings = ip6_error_strings, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_mpls_label_disposition_node, - ip6_mpls_label_disposition) +VLIB_NODE_FUNCTION_MULTIARCH(ip6_mpls_label_disposition_pipe_node, + ip6_mpls_label_disposition_pipe) + +static uword +ip4_mpls_label_disposition_uniform (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (mpls_label_disposition_inline(vm, node, frame, 1, 0, + FIB_MPLS_LSP_MODE_UNIFORM)); +} + +VLIB_REGISTER_NODE(ip4_mpls_label_disposition_uniform_node) = { + .function = ip4_mpls_label_disposition_uniform, + .name = "ip4-mpls-label-disposition-uniform", + .vector_size = sizeof(u32), + + .format_trace = format_mpls_label_disposition_trace, + .sibling_of = "ip4-input", + .n_errors = IP4_N_ERROR, + .error_strings = ip4_error_strings, +}; +VLIB_NODE_FUNCTION_MULTIARCH(ip4_mpls_label_disposition_uniform_node, + ip4_mpls_label_disposition_uniform) + +static uword +ip6_mpls_label_disposition_uniform (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (mpls_label_disposition_inline(vm, node, frame, 0, 1, + FIB_MPLS_LSP_MODE_UNIFORM)); +} + +VLIB_REGISTER_NODE(ip6_mpls_label_disposition_uniform_node) = { + .function = ip6_mpls_label_disposition_uniform, + .name = "ip6-mpls-label-disposition-uniform", + .vector_size = sizeof(u32), + + .format_trace = format_mpls_label_disposition_trace, + .sibling_of = "ip6-input", + .n_errors = IP6_N_ERROR, + .error_strings = ip6_error_strings, +}; +VLIB_NODE_FUNCTION_MULTIARCH(ip6_mpls_label_disposition_uniform_node, + ip6_mpls_label_disposition_uniform) static void mpls_disp_dpo_mem_show (void) @@ -374,25 +509,44 @@ const static dpo_vft_t mdd_vft = { .dv_mem_show = mpls_disp_dpo_mem_show, }; -const static char* const mpls_label_disp_ip4_nodes[] = +const static char* const mpls_label_disp_pipe_ip4_nodes[] = +{ + "ip4-mpls-label-disposition-pipe", + NULL, +}; +const static char* const mpls_label_disp_pipe_ip6_nodes[] = +{ + "ip6-mpls-label-disposition-pipe", + NULL, +}; +const static char* const * const mpls_label_disp_pipe_nodes[DPO_PROTO_NUM] = +{ + [DPO_PROTO_IP4] = mpls_label_disp_pipe_ip4_nodes, + [DPO_PROTO_IP6] = mpls_label_disp_pipe_ip6_nodes, +}; + +const static char* const mpls_label_disp_uniform_ip4_nodes[] = { - "ip4-mpls-label-disposition", + "ip4-mpls-label-disposition-uniform", NULL, }; -const static char* const mpls_label_disp_ip6_nodes[] = +const static char* const mpls_label_disp_uniform_ip6_nodes[] = { - "ip6-mpls-label-disposition", + "ip6-mpls-label-disposition-uniform", NULL, }; -const static char* const * const mpls_label_disp_nodes[DPO_PROTO_NUM] = +const static char* const * const mpls_label_disp_uniform_nodes[DPO_PROTO_NUM] = { - [DPO_PROTO_IP4] = mpls_label_disp_ip4_nodes, - [DPO_PROTO_IP6] = mpls_label_disp_ip6_nodes, + [DPO_PROTO_IP4] = mpls_label_disp_uniform_ip4_nodes, + [DPO_PROTO_IP6] = mpls_label_disp_uniform_ip6_nodes, }; void -mpls_disp_dpo_module_init (void) +mpls_disp_dpo_module_init(void) { - dpo_register(DPO_MPLS_DISPOSITION, &mdd_vft, mpls_label_disp_nodes); + dpo_register(DPO_MPLS_DISPOSITION_PIPE, &mdd_vft, + mpls_label_disp_pipe_nodes); + dpo_register(DPO_MPLS_DISPOSITION_UNIFORM, &mdd_vft, + mpls_label_disp_uniform_nodes); } |