X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fqos%2Fqos_record.c;h=ef9e587a8a67a33aa6781f7e67a1acf161920c8d;hb=609e1210c6339376dd6cdd0f79195b436d5614d2;hp=047bd25cda4cb3d34a747e9f055ebb1b9ea5e6e8;hpb=039cbfe254be998f7311bc4638bb262b44efac19;p=vpp.git diff --git a/src/vnet/qos/qos_record.c b/src/vnet/qos/qos_record.c index 047bd25cda4..ef9e587a8a6 100644 --- a/src/vnet/qos/qos_record.c +++ b/src/vnet/qos/qos_record.c @@ -18,11 +18,14 @@ #include #include #include +#include +#include /** * Per-interface, per-protocol vector of feature on/off configurations */ static u8 *qos_record_configs[QOS_N_SOURCES]; +static u32 l2_qos_input_next[QOS_N_SOURCES][32]; static void qos_record_feature_config (u32 sw_if_index, @@ -39,11 +42,27 @@ qos_record_feature_config (u32 sw_if_index, sw_if_index, enable, NULL, 0); vnet_feature_enable_disable ("ip4-multicast", "ip4-qos-record", sw_if_index, enable, NULL, 0); + l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_L2_IP_QOS_RECORD, + enable); break; case QOS_SOURCE_MPLS: + vnet_feature_enable_disable ("mpls-input", "mpls-qos-record", + sw_if_index, enable, NULL, 0); + break; case QOS_SOURCE_VLAN: + vnet_feature_enable_disable ("ip6-unicast", "vlan-ip6-qos-record", + sw_if_index, enable, NULL, 0); + vnet_feature_enable_disable ("ip6-multicast", "vlan-ip6-qos-record", + sw_if_index, enable, NULL, 0); + vnet_feature_enable_disable ("ip4-unicast", "vlan-ip4-qos-record", + sw_if_index, enable, NULL, 0); + vnet_feature_enable_disable ("ip4-multicast", "vlan-ip4-qos-record", + sw_if_index, enable, NULL, 0); + vnet_feature_enable_disable ("mpls-input", "vlan-mpls-qos-record", + sw_if_index, enable, NULL, 0); + break; case QOS_SOURCE_EXT: - // not implemented yet + /* not a valid option for recording */ break; } } @@ -65,7 +84,7 @@ qos_record_enable (u32 sw_if_index, qos_source_t input_source) int qos_record_disable (u32 sw_if_index, qos_source_t input_source) { - if (vec_len (qos_record_configs[input_source]) < sw_if_index) + if (vec_len (qos_record_configs[input_source]) <= sw_if_index) return VNET_API_ERROR_NO_MATCHING_INTERFACE; if (0 == qos_record_configs[input_source][sw_if_index]) @@ -82,7 +101,7 @@ qos_record_disable (u32 sw_if_index, qos_source_t input_source) } /* - * Disable recording feautre for all protocols when the interface + * Disable recording feature for all protocols when the interface * is deleted */ static clib_error_t * @@ -95,7 +114,7 @@ qos_record_ip_interface_add_del (vnet_main_t * vnm, FOR_EACH_QOS_SOURCE (qs) { - qos_record_disable (sw_if_index, qs); + while (qos_record_disable (sw_if_index, qs) == 0); } } @@ -116,7 +135,8 @@ typedef struct qos_record_trace_t_ static inline uword qos_record_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, int is_ip6) + vlib_frame_t * frame, + qos_source_t qos_src, dpo_proto_t dproto, int is_l2) { u32 n_left_from, *from, *to_next, next_index; @@ -135,8 +155,9 @@ qos_record_inline (vlib_main_t * vm, ip4_header_t *ip4_0; ip6_header_t *ip6_0; vlib_buffer_t *b0; - u32 sw_if_index0, next0, bi0; + u32 next0, bi0; qos_bits_t qos0; + u8 l2_len; next0 = 0; bi0 = from[0]; @@ -147,22 +168,58 @@ qos_record_inline (vlib_main_t * vm, n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); - if (is_ip6) + + if (is_l2) + { + l2_len = vnet_buffer (b0)->l2.l2_len; + u8 *l3h; + u16 ethertype; + + vlib_buffer_advance (b0, l2_len); + + l3h = vlib_buffer_get_current (b0); + ethertype = clib_net_to_host_u16 (*(u16 *) (l3h - 2)); + + if (ethertype == ETHERNET_TYPE_IP4) + dproto = DPO_PROTO_IP4; + else if (ethertype == ETHERNET_TYPE_IP6) + dproto = DPO_PROTO_IP6; + else if (ethertype == ETHERNET_TYPE_MPLS) + dproto = DPO_PROTO_MPLS; + else + goto non_ip; + } + + if (DPO_PROTO_IP6 == dproto) { ip6_0 = vlib_buffer_get_current (b0); qos0 = ip6_traffic_class_network_order (ip6_0); } - else + else if (DPO_PROTO_IP4 == dproto) { ip4_0 = vlib_buffer_get_current (b0); qos0 = ip4_0->tos; } + else if (DPO_PROTO_ETHERNET == dproto) + { + ethernet_vlan_header_t *vlan0; + + vlan0 = (vlib_buffer_get_current (b0) - + sizeof (ethernet_vlan_header_t)); + + qos0 = ethernet_vlan_header_get_priority_net_order (vlan0); + } + else if (DPO_PROTO_MPLS) + { + mpls_unicast_header_t *mh; + + mh = vlib_buffer_get_current (b0); + qos0 = vnet_mpls_uc_get_exp (mh->label_exp_s_ttl); + } + vnet_buffer2 (b0)->qos.bits = qos0; - vnet_buffer2 (b0)->qos.source = QOS_SOURCE_IP; + vnet_buffer2 (b0)->qos.source = qos_src; b0->flags |= VNET_BUFFER_F_QOS_DATA_VALID; - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - - vnet_feature_next (sw_if_index0, &next0, b0); if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED))) @@ -172,6 +229,17 @@ qos_record_inline (vlib_main_t * vm, t->bits = qos0; } + non_ip: + if (is_l2) + { + vlib_buffer_advance (b0, -l2_len); + next0 = vnet_l2_feature_next (b0, + l2_qos_input_next[qos_src], + L2INPUT_FEAT_L2_IP_QOS_RECORD); + } + else + vnet_feature_next (&next0, b0); + /* verify speculative enqueue, maybe switch current next frame */ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, @@ -201,14 +269,55 @@ static inline uword ip4_qos_record (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return (qos_record_inline (vm, node, frame, 0)); + return (qos_record_inline (vm, node, frame, QOS_SOURCE_IP, + DPO_PROTO_IP4, 0)); } static inline uword ip6_qos_record (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return (qos_record_inline (vm, node, frame, 1)); + return (qos_record_inline (vm, node, frame, QOS_SOURCE_IP, + DPO_PROTO_IP6, 0)); +} + +static inline uword +mpls_qos_record (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (qos_record_inline (vm, node, frame, QOS_SOURCE_MPLS, + DPO_PROTO_MPLS, 0)); +} + +static inline uword +vlan_ip4_qos_record (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN, + DPO_PROTO_ETHERNET, 0)); +} + +static inline uword +vlan_ip6_qos_record (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN, + DPO_PROTO_ETHERNET, 0)); +} + +static inline uword +vlan_mpls_qos_record (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN, + DPO_PROTO_ETHERNET, 0)); +} + +static inline uword +l2_ip_qos_record (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN, 0, 1)); } /* *INDENT-OFF* */ @@ -233,6 +342,10 @@ VNET_FEATURE_INIT (ip4_qos_record_node, static) = { .arc_name = "ip4-unicast", .node_name = "ip4-qos-record", }; +VNET_FEATURE_INIT (ip4m_qos_record_node, static) = { + .arc_name = "ip4-multicast", + .node_name = "ip4-qos-record", +}; VLIB_REGISTER_NODE (ip6_qos_record_node) = { .function = ip6_qos_record, @@ -255,8 +368,148 @@ VNET_FEATURE_INIT (ip6_qos_record_node, static) = { .arc_name = "ip6-unicast", .node_name = "ip6-qos-record", }; +VNET_FEATURE_INIT (ip6m_qos_record_node, static) = { + .arc_name = "ip6-multicast", + .node_name = "ip6-qos-record", +}; + +VLIB_REGISTER_NODE (mpls_qos_record_node) = { + .function = mpls_qos_record, + .name = "mpls-qos-record", + .vector_size = sizeof (u32), + .format_trace = format_qos_record_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = 0, + .n_next_nodes = 1, + + .next_nodes = { + [0] = "mpls-drop", + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (mpls_qos_record_node, mpls_qos_record); + +VNET_FEATURE_INIT (mpls_qos_record_node, static) = { + .arc_name = "mpls-input", + .node_name = "mpls-qos-record", +}; + +VLIB_REGISTER_NODE (vlan_mpls_qos_record_node) = { + .function = vlan_mpls_qos_record, + .name = "vlan-mpls-qos-record", + .vector_size = sizeof (u32), + .format_trace = format_qos_record_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = 0, + .n_next_nodes = 1, + + .next_nodes = { + [0] = "mpls-drop", + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (vlan_mpls_qos_record_node, vlan_mpls_qos_record); + +VNET_FEATURE_INIT (vlan_mpls_qos_record_node, static) = { + .arc_name = "mpls-input", + .node_name = "vlan-mpls-qos-record", + .runs_before = VNET_FEATURES ("mpls-qos-record"), +}; + +VLIB_REGISTER_NODE (vlan_ip4_qos_record_node) = { + .function = vlan_ip4_qos_record, + .name = "vlan-ip4-qos-record", + .vector_size = sizeof (u32), + .format_trace = format_qos_record_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = 0, + .n_next_nodes = 1, + + .next_nodes = { + [0] = "ip4-drop", + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (vlan_ip4_qos_record_node, vlan_ip4_qos_record); + +VNET_FEATURE_INIT (vlan_ip4_qos_record_node, static) = { + .arc_name = "ip4-unicast", + .node_name = "vlan-ip4-qos-record", + .runs_before = VNET_FEATURES ("ip4-qos-record"), +}; +VNET_FEATURE_INIT (vlan_ip4m_qos_record_node, static) = { + .arc_name = "ip4-multicast", + .node_name = "vlan-ip4-qos-record", + .runs_before = VNET_FEATURES ("ip4-qos-record"), +}; + +VLIB_REGISTER_NODE (vlan_ip6_qos_record_node) = { + .function = vlan_ip6_qos_record, + .name = "vlan-ip6-qos-record", + .vector_size = sizeof (u32), + .format_trace = format_qos_record_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = 0, + .n_next_nodes = 1, + + .next_nodes = { + [0] = "ip6-drop", + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (vlan_ip6_qos_record_node, vlan_ip6_qos_record); + +VNET_FEATURE_INIT (vlan_ip6_qos_record_node, static) = { + .arc_name = "ip6-unicast", + .node_name = "vlan-ip6-qos-record", + .runs_before = VNET_FEATURES ("ip6-qos-record"), +}; +VNET_FEATURE_INIT (vlan_ip6m_qos_record_node, static) = { + .arc_name = "ip6-multicast", + .node_name = "vlan-ip6-qos-record", + .runs_before = VNET_FEATURES ("ip6-qos-record"), +}; + +VLIB_REGISTER_NODE (l2_ip_qos_record_node, static) = { + .function = l2_ip_qos_record, + .name = "l2-ip-qos-record", + .vector_size = sizeof (u32), + .format_trace = format_qos_record_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = 0, + .n_next_nodes = 1, + + /* Consider adding error "no IP after L2, no recording" */ + .next_nodes = { + [0] = "error-drop", + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (l2_ip_qos_record_node, l2_ip_qos_record); + /* *INDENT-ON* */ +clib_error_t * +l2_ip_qos_init (vlib_main_t * vm) +{ + qos_source_t qs; + + /* Initialize the feature next-node indexes */ + FOR_EACH_QOS_SOURCE (qs) + feat_bitmap_init_next_nodes (vm, + l2_ip_qos_record_node.index, + L2INPUT_N_FEAT, + l2input_get_feat_names (), + l2_qos_input_next[qs]); + return 0; +} + +VLIB_INIT_FUNCTION (l2_ip_qos_init); static clib_error_t * qos_record_cli (vlib_main_t * vm, @@ -301,7 +554,7 @@ qos_record_cli (vlib_main_t * vm, /*? * Enable QoS bit recording on an interface using the packet's input DSCP bits * Which input QoS bits to use are either; IP, MPLS or VLAN. If more than - * one protocol is chosen (which is foolish) the higer layers override the + * one protocol is chosen (which is foolish) the higher layers override the * lower. * * @cliexpar