From: Barry Spinney <[email protected]> This patch adds a new marking_colors_supported and marking_colors_needed arrays. Also splits the TOS marking function - which previously could specify ECN or DSCP marking into two separate calls. Also improved the documentation.
This patch also updates the TM implementation to match the latest changes to the header file. In addition a few bugs were fixed in the marking implementations. Signed-off-by: Barry Spinney <[email protected]> Signed-off-by: Bill Fischofer <[email protected]> --- include/odp/api/spec/traffic_mngr.h | 135 ++++++++++++++++----- .../include/odp_traffic_mngr_internal.h | 11 +- platform/linux-generic/odp_traffic_mngr.c | 127 +++++++++++++------ 3 files changed, 206 insertions(+), 67 deletions(-) diff --git a/include/odp/api/spec/traffic_mngr.h b/include/odp/api/spec/traffic_mngr.h index c5b9d24..83b89e7 100644 --- a/include/odp/api/spec/traffic_mngr.h +++ b/include/odp/api/spec/traffic_mngr.h @@ -293,19 +293,35 @@ typedef struct { * form of VLAN egress marking using the odp_tm_vlan_marking() * function. This being true does not imply that all colors and * subfield values and changes are supported. Unsupported features - * can be detected by the marking function returning an error code.*/ + * can be detected by the marking function returning an error code. */ odp_bool_t vlan_marking_supported; - /** ip_tos_marking_supported indicates that this TM system supports + /** ecn_marking_supported indicates that this TM system supports + * Explicit Congestion Notification egress marking by using the + * odp_tm_ip_ecn_marking() function. Note that the ECN is the bottom + * two bits of the IPv4 TOS field or the analogous IPv6 Traffic Class + * (TC) field. Note that the ecn_marking_supported boolean being + * true does not imply that all colors are supported. */ + odp_bool_t ecn_marking_supported; + + /** drop_prec_marking_supported indicates that this TM system supports * SOME form of IPv4/IPv6 egress marking by using the - * odp_tm_ip_tos_marking() function. Note that the actually field + * odp_tm_drop_prec_marking() function. Note that the actually field * modified for IPv4 pkts is called TOS, whereas the field modified * for IPv6 pkts is called Traffic Class (TC) - but they are analogous - * fields. Note that the ip_tos_marking_supported boolean being true + * fields. Note that the drop_prec_marking_supported boolean being true * does not imply that all colors and subfield values and changes are * supported. Unsupported features can be detected by the marking * function returning an error code.*/ - odp_bool_t ip_tos_marking_supported; + odp_bool_t drop_prec_marking_supported; + + /** The marking_colors_supported array is used to indicate which colors + * can be used for marking. A value of FALSE means that this color + * should not be enabled for either vlan marking, ecn marking or + * drop precedence marking. A value of TRUE means that this color is + * supported for at least one of (and ideally all of) vlan marking, + * ecn marking or drop precedence marking. */ + odp_bool_t marking_colors_supported[ODP_NUM_PACKET_COLORS]; /** The per_level array specifies the TM system capabilities that * can vary based upon the tm_node level. */ @@ -379,7 +395,7 @@ typedef struct { uint32_t max_tm_queues; /** num_levels specifies that number of levels of hierarchical - * scheduling that will b used. This is a count of the tm_node + * scheduling that will be used. This is a count of the tm_node * stages and does not include tm_queues or tm_egress objects. */ uint8_t num_levels; @@ -402,11 +418,25 @@ typedef struct { * vlan_marking_supported. */ odp_bool_t vlan_marking_needed; - /** ip_tos_marking_needed indicates that the ODP application expects + /** ecn_marking_needed indicates that the ODP application expects + * to use some form of IPv4 TOS or IPv6 TC field egress marking by + * using the odp_tm_ecn_marking() function. See also comments for + * ecn_marking_supported. */ + odp_bool_t ecn_marking_needed; + + /** drop_prec_marking_needed indicates that the ODP application expects * to use some form of IPv4 TOS or IPv6 TC field egress marking by - * using the odp_tm_ip_tos_marking() function. See also comments for - * ip_tos_marking_supported. */ - odp_bool_t ip_tos_marking_needed; + * using the odp_tm_drop_prec_marking() function. See also comments for + * drop_prec_marking_supported. */ + odp_bool_t drop_prec_marking_needed; + + /** The marking_colors_needed array is used to indicate which colors + * are expected to be used for marking. A value of FALSE means that + * the application will not enable this color for vlan marking, + * ecn marking nor drop precedence marking. A value of TRUE means that + * the application expects to use this color in conjunction with one or + * more of the marking API's. */ + odp_bool_t marking_colors_needed[ODP_NUM_PACKET_COLORS]; /** The per_level array specifies the TM system requirements that * can vary based upon the tm_node level. */ @@ -598,7 +628,11 @@ int odp_tm_destroy(odp_tm_t odp_tm); * field (but only for pkts that already carry a VLAN tag) of a pkt based upon * the final pkt (or shaper?) color assigned to the pkt when it reaches the * egress node. When drop_eligible_enabled is false, then the given color has - * no effect on the VLAN fields. + * no effect on the VLAN fields. See IEEE 802.1q for more details. + * + * Note that ALL ODP implementations are required to SUCCESSFULLY handle all + * calls to this function with drop_eligible_enabled == FALSE - i.e. must + * always return 0 when disabling this feature. * * @param[in] odp_tm Odp_tm is used to identify the TM system * whose egress behavior is being changed. @@ -612,39 +646,76 @@ int odp_tm_vlan_marking(odp_tm_t odp_tm, odp_packet_color_t color, odp_bool_t drop_eligible_enabled); -/** IP Tos Marking. +/** Explicit Congestion Notification Marking. + * + * The odp_tm_ecn_marking() function allows one to configure the TM + * egress so that the two bit ECN subfield of the eight bit TOS field of an + * IPv4 pkt OR the eight bit Traffic Class (TC) field of an IPv6 pkt can be + * selectively modified based upon the final color assigned to the pkt when it + * reaches the egress. Note that the IPv4 header checksum will be updated - + * but only if the IPv4 TOS field actually changes as a result of this + * setting or the odp_tm_drop_prec_marking setting. For IPv6, since there is + * no header checksum, nothing needs to be done. Note that this marking API + * will only ever cause both ECN bits to be set to 1 - but only for TCP pkts + * whose incoming ECN bits are not both 0. See RFC 3168 for more details. * - * The odp_tm_ip_tos_marking() function allows one to configure the TM - * egress so that the eight bit TOS field of an IPv4 pkt OR the analogous - * eight bit Traffic Class (TC) field of an IPv6 pkt can be selectively - * modified based upon the final color assigned to the pkt when it reaches the - * egress. Note that both the TOS/TC field and the VLAN header of a VLAN tagged - * IP pkt could be independently modified. Also note that this function - * will update the IPv4 header checksum - but only if the TOS field actually - * changes. For IPv6, since there is no header checksum, nothing needs to - * be done. + * Note that ALL ODP implementations are required to SUCCESSFULLY handle all + * calls to this function with ecn_ce_enabled == FALSE - i.e. must always + * return 0 when disabling this feature. * * @param[in] odp_tm Odp_tm is used to identify the TM system whose * egress behavior is being changed. * @param[in] color The packet color whose egress marking is * being changed. - * @param[in] dscp_enabled If true then egressed IPv4/IPv6 pkts with this - * color will have the pkt's DSCP subfield set to the - * new_dscp parameter (see below). - * @param[in] new_dscp The Differentiated Services Code Point value. - * Must be in the range 0..63. * @param[in] ecn_ce_enabled If true then egressed IPv4/IPv6 pkts whose * protocol field is TCP AND whose ECN subfield has - * one of the two values 1 or 2, will set this + * either one of the two values 1 or 2, will set this * subfield to the value ECN_CE - i.e. Congestion * Experienced (whose value is 3). * @return 0 upon success, < 0 upon failure. */ -int odp_tm_ip_tos_marking(odp_tm_t odp_tm, - odp_packet_color_t color, - odp_bool_t dscp_enabled, - uint8_t new_dscp, - odp_bool_t ecn_ce_enabled); +int odp_tm_ecn_marking(odp_tm_t odp_tm, + odp_packet_color_t color, + odp_bool_t ecn_ce_enabled); + +/** Drop Precedence Marking. + * + * The odp_tm_drop_prec_marking() function allows one to configure the TM + * egress so that the two RFC 2597 Drop Precedence bits can be modified + * based upon the final color assigned to the pkt when it reaches the egress. + * The Drop Precedence bits are contained within the six bit Differentiated + * Services Code Point subfield of the IPv4 TOS field or the IPv6 Traffic + * Class (TC) field. Specifically the Drop Precedence sub-subfield can be + * accessed with a DSCP bit mask of 0x06. When enabled for a given color, + * these two bits will be set to Medium Drop Precedence (value 0x4) if the + * color is ODP_PACKET_YELLOW, set to High Drop Precedence (value 0x6) if + * the color is ODP_PACKET_RED, otherwise set to Low Drop Precedence for any + * other color. Of course an implementation can restrict the set of colors + * which can be enabled via the marking_colors_supported array in the + * odp_tm_capabilities_t record. + * + * Note that the IPv4 header checksum will be updated - but only if the + * IPv4 TOS field actually changes as a result of this setting or the + * odp_tm_ecn_marking setting. For IPv6, since there is no header checksum, + * nothing else needs to be done. + * + * Note that ALL ODP implementations are required to SUCCESSFULLY handle all + * calls to this function with drop_prec_enabled == FALSE - i.e. must always + * return 0 when disabling this feature. + * + * @param[in] odp_tm Odp_tm is used to identify the TM system whose + * egress behavior is being changed. + * @param[in] color The packet color whose egress marking is + * being changed. + * @param[in] drop_prec_enabled If true then egressed IPv4/IPv6 pkts with this + * color will have the pkt's Drop Precedence + * sub-subfield of the DSCP subfield set to + * LOW, MEDIUM or HIGH drop precedence. + * @return 0 upon success, < 0 upon failure. + */ +int odp_tm_drop_prec_marking(odp_tm_t odp_tm, + odp_packet_color_t color, + odp_bool_t drop_prec_enabled); /** Shaper profile types and functions */ diff --git a/platform/linux-generic/include/odp_traffic_mngr_internal.h b/platform/linux-generic/include/odp_traffic_mngr_internal.h index a0853eb..90036de 100644 --- a/platform/linux-generic/include/odp_traffic_mngr_internal.h +++ b/platform/linux-generic/include/odp_traffic_mngr_internal.h @@ -67,6 +67,15 @@ typedef struct stat file_stat_t; typedef uint64_t tm_handle_t; +#define LOW_DROP_PRECEDENCE 0x02 +#define MEDIUM_DROP_PRECEDENCE 0x04 +#define HIGH_DROP_PRECEDENCE 0x06 +#define DROP_PRECEDENCE_MASK 0x06 +#define DSCP_CLASS1 0x08 +#define DSCP_CLASS2 0x10 +#define DSCP_CLASS3 0x18 +#define DSCP_CLASS4 0x20 + #define PF_RM_CURRENT_BEST 0x01 #define PF_NEW_PKT_IN 0x02 #define PF_SHAPER_DELAYED 0x10 @@ -327,7 +336,7 @@ typedef struct { typedef struct { odp_bool_t marking_enabled; - odp_bool_t dscp_enabled; + odp_bool_t drop_prec_enabled; uint8_t shifted_dscp; uint8_t inverted_dscp_mask; odp_bool_t ecn_ce_enabled; diff --git a/platform/linux-generic/odp_traffic_mngr.c b/platform/linux-generic/odp_traffic_mngr.c index 27530ff..1cc5e9b 100644 --- a/platform/linux-generic/odp_traffic_mngr.c +++ b/platform/linux-generic/odp_traffic_mngr.c @@ -1924,7 +1924,7 @@ static void egress_ipv4_tos_marking(tm_tos_marking_t *tos_marking, old_tos = ipv4_hdr_ptr->tos; new_tos = old_tos; - if (tos_marking->dscp_enabled) + if (tos_marking->drop_prec_enabled) new_tos = (new_tos & tos_marking->inverted_dscp_mask) | tos_marking->shifted_dscp; @@ -1989,10 +1989,11 @@ static void egress_ipv6_tc_marking(tm_tos_marking_t *tos_marking, } old_ver_tc_flow = odp_be_to_cpu_32(ipv6_hdr_ptr->ver_tc_flow); - old_tc = old_ver_tc_flow >> ODPH_IPV6HDR_TC_SHIFT; + old_tc = (old_ver_tc_flow & ODPH_IPV6HDR_TC_MASK) + >> ODPH_IPV6HDR_TC_SHIFT; new_tc = old_tc; - if (tos_marking->dscp_enabled) + if (tos_marking->drop_prec_enabled) new_tc = (new_tc & tos_marking->inverted_dscp_mask) | tos_marking->shifted_dscp; @@ -2006,7 +2007,7 @@ static void egress_ipv6_tc_marking(tm_tos_marking_t *tos_marking, if (new_tc == old_tc) return; - new_ver_tc_flow = (old_ver_tc_flow & ODPH_IPV6HDR_TC_MASK) | + new_ver_tc_flow = (old_ver_tc_flow & ~ODPH_IPV6HDR_TC_MASK) | (new_tc << ODPH_IPV6HDR_TC_SHIFT); ipv6_hdr_ptr->ver_tc_flow = odp_cpu_to_be_32(new_ver_tc_flow); @@ -2345,12 +2346,12 @@ int odp_tm_capabilities(odp_tm_capabilities_t capabilities[] ODP_UNUSED, { odp_tm_level_capabilities_t *per_level_cap; odp_tm_capabilities_t *cap_ptr; + odp_packet_color_t color; uint32_t level_idx; if (capabilities_size == 0) return -1; - /* TBD */ cap_ptr = &capabilities[0]; memset(cap_ptr, 0, sizeof(odp_tm_capabilities_t)); @@ -2360,7 +2361,11 @@ int odp_tm_capabilities(odp_tm_capabilities_t capabilities[] ODP_UNUSED, cap_ptr->tm_queue_wred_supported = true; cap_ptr->tm_queue_dual_slope_supported = true; cap_ptr->vlan_marking_supported = true; - cap_ptr->ip_tos_marking_supported = true; + cap_ptr->ecn_marking_supported = true; + cap_ptr->drop_prec_marking_supported = true; + + for (color = 0; color < ODP_NUM_PACKET_COLORS; color++) + cap_ptr->marking_colors_supported[color] = true; for (level_idx = 0; level_idx < cap_ptr->max_levels; level_idx++) { per_level_cap = &cap_ptr->per_level[level_idx]; @@ -2378,7 +2383,7 @@ int odp_tm_capabilities(odp_tm_capabilities_t capabilities[] ODP_UNUSED, per_level_cap->weights_supported = true; } - return 0; + return 1; } static void tm_system_capabilities_set(odp_tm_capabilities_t *cap_ptr, @@ -2386,6 +2391,7 @@ static void tm_system_capabilities_set(odp_tm_capabilities_t *cap_ptr, { odp_tm_level_requirements_t *per_level_req; odp_tm_level_capabilities_t *per_level_cap; + odp_packet_color_t color; odp_bool_t shaper_supported, wred_supported; odp_bool_t dual_slope; uint32_t num_levels, level_idx, max_nodes; @@ -2407,7 +2413,13 @@ static void tm_system_capabilities_set(odp_tm_capabilities_t *cap_ptr, cap_ptr->tm_queue_wred_supported = wred_supported; cap_ptr->tm_queue_dual_slope_supported = dual_slope; cap_ptr->vlan_marking_supported = req_ptr->vlan_marking_needed; - cap_ptr->ip_tos_marking_supported = req_ptr->ip_tos_marking_needed; + cap_ptr->ecn_marking_supported = req_ptr->ecn_marking_needed; + cap_ptr->drop_prec_marking_supported = + req_ptr->drop_prec_marking_needed; + + for (color = 0; color < ODP_NUM_PACKET_COLORS; color++) + cap_ptr->marking_colors_supported[color] = + req_ptr->marking_colors_needed[color]; for (level_idx = 0; level_idx < num_levels; level_idx++) { per_level_cap = &cap_ptr->per_level[level_idx]; @@ -2635,6 +2647,11 @@ int odp_tm_vlan_marking(odp_tm_t odp_tm, if ((tm_system == NULL) || (ODP_NUM_PACKET_COLORS < color)) return -1; + if (drop_eligible_enabled) + if ((!tm_system->requirements.vlan_marking_needed) || + (!tm_system->requirements.marking_colors_needed[color])) + return -2; + vlan_marking = &tm_system->marking.vlan_marking[color]; vlan_marking->marking_enabled = drop_eligible_enabled; vlan_marking->drop_eligible_enabled = drop_eligible_enabled; @@ -2646,37 +2663,79 @@ int odp_tm_vlan_marking(odp_tm_t odp_tm, return 0; } -static void tm_tos_marking(tm_tos_marking_t *tos_marking, - odp_bool_t dscp_enabled, - uint8_t new_dscp, - odp_bool_t ecn_ce_enabled) - +int odp_tm_ecn_marking(odp_tm_t odp_tm, + odp_packet_color_t color, + odp_bool_t ecn_ce_enabled) { - tos_marking->marking_enabled = dscp_enabled | ecn_ce_enabled; - tos_marking->dscp_enabled = dscp_enabled; - tos_marking->shifted_dscp = (new_dscp & ~ODPH_IP_TOS_DSCP_MASK) - << ODPH_IP_TOS_DSCP_SHIFT; - tos_marking->inverted_dscp_mask = (uint8_t)~ODPH_IP_TOS_DSCP_MASK; - tos_marking->ecn_ce_enabled = ecn_ce_enabled; + tm_tos_marking_t *tos_marking; + tm_system_t *tm_system; + + tm_system = GET_TM_SYSTEM(odp_tm); + if ((tm_system == NULL) || (ODP_NUM_PACKET_COLORS <= color)) + return -1; + + if (ecn_ce_enabled) + if ((!tm_system->requirements.ecn_marking_needed) || + (!tm_system->requirements.marking_colors_needed[color])) + return -2; + + tos_marking = &tm_system->marking.ip_tos_marking[color]; + tos_marking->marking_enabled = tos_marking->drop_prec_enabled | + ecn_ce_enabled; + tos_marking->ecn_ce_enabled = ecn_ce_enabled; + + if (ecn_ce_enabled) + tm_system->marking_enabled = true; + else + tm_system->marking_enabled = tm_marking_enabled(tm_system); + + return 0; } -int odp_tm_ip_tos_marking(odp_tm_t odp_tm, - odp_packet_color_t color, - odp_bool_t dscp_enabled, - uint8_t new_dscp, - odp_bool_t ecn_ce_enabled) +int odp_tm_drop_prec_marking(odp_tm_t odp_tm, + odp_packet_color_t color, + odp_bool_t drop_prec_enabled) { - tm_tos_marking_t *ip_marking; + tm_tos_marking_t *tos_marking; tm_system_t *tm_system; + uint8_t dscp_mask, new_dscp, inverted_mask, tos_mask; + uint8_t shifted_dscp; tm_system = GET_TM_SYSTEM(odp_tm); - if ((tm_system == NULL) || (ODP_NUM_PACKET_COLORS <= color) || - (ODPH_IP_TOS_MAX_DSCP < new_dscp)) + if ((tm_system == NULL) || (ODP_NUM_PACKET_COLORS <= color)) return -1; - ip_marking = &tm_system->marking.ip_tos_marking[color]; - tm_tos_marking(ip_marking, dscp_enabled, new_dscp, ecn_ce_enabled); - if (dscp_enabled | ecn_ce_enabled) + if (drop_prec_enabled) + if ((!tm_system->requirements.drop_prec_marking_needed) || + (!tm_system->requirements.marking_colors_needed[color])) + return -2; + + dscp_mask = DROP_PRECEDENCE_MASK; + if (color == ODP_PACKET_YELLOW) + new_dscp = MEDIUM_DROP_PRECEDENCE; + else if (color == ODP_PACKET_RED) + new_dscp = HIGH_DROP_PRECEDENCE; + else + new_dscp = LOW_DROP_PRECEDENCE; + + if (drop_prec_enabled) { + new_dscp = new_dscp & dscp_mask; + inverted_mask = (uint8_t)~dscp_mask; + tos_mask = (inverted_mask << ODPH_IP_TOS_DSCP_SHIFT) | + ODPH_IP_TOS_ECN_MASK; + shifted_dscp = new_dscp << ODPH_IP_TOS_DSCP_SHIFT; + } else { + tos_mask = 0xFF; /* Note that this is an inverted mask */ + shifted_dscp = 0; + } + + tos_marking = &tm_system->marking.ip_tos_marking[color]; + tos_marking->marking_enabled = drop_prec_enabled | + tos_marking->ecn_ce_enabled; + tos_marking->drop_prec_enabled = drop_prec_enabled; + tos_marking->shifted_dscp = shifted_dscp; + tos_marking->inverted_dscp_mask = tos_mask; + if (drop_prec_enabled) tm_system->marking_enabled = true; else tm_system->marking_enabled = tm_marking_enabled(tm_system); @@ -4012,18 +4071,18 @@ int odp_tm_node_fanin_info(odp_tm_node_t tm_node, return -5; info->is_last = next_shaper_obj->fanin_list_next == NULL; - if (shaper_obj->in_tm_node_obj) { - fanin_tm_node_obj = shaper_obj->enclosing_entity; + if (next_shaper_obj->in_tm_node_obj) { + fanin_tm_node_obj = next_shaper_obj->enclosing_entity; info->tm_node = MAKE_ODP_TM_NODE(fanin_tm_node_obj); info->tm_queue = ODP_TM_INVALID; } else { - fanin_tm_queue_obj = shaper_obj->enclosing_entity; + fanin_tm_queue_obj = next_shaper_obj->enclosing_entity; info->tm_queue = MAKE_ODP_TM_QUEUE(fanin_tm_queue_obj); info->tm_node = ODP_TM_INVALID; } info->sched_profile = ODP_TM_INVALID; - sched_params = shaper_obj->sched_params; + sched_params = next_shaper_obj->sched_params; if (sched_params != NULL) info->sched_profile = sched_params->sched_profile; -- 2.5.0 _______________________________________________ lng-odp mailing list [email protected] https://lists.linaro.org/mailman/listinfo/lng-odp
