[PATCH v4 0/2] net/mlx5: add random item support
Add support for matching random value using the "rte_flow_item_random" structure. Depends-on: series-30553 ("ethdev: add random item support") v2: - Rebase. - Move release notes to the new release file. v3: - Fix typos in commit message and release notes. - Update limitations. v4: - Fix using same value for both "MLX5_FLOW_ITEM_NSH" and "MLX5_FLOW_ITEM_RANDOM". - Add "Acked-by" from v3. Erez Shitrit (1): net/mlx5/hws: add support for random number match Michael Baum (1): net/mlx5: add random item support doc/guides/nics/features/mlx5.ini | 1 + doc/guides/nics/mlx5.rst | 9 +++ doc/guides/rel_notes/release_24_03.rst | 3 +++ drivers/net/mlx5/hws/mlx5dr_definer.c | 33 ++ drivers/net/mlx5/hws/mlx5dr_definer.h | 8 ++- drivers/net/mlx5/mlx5_flow.h | 3 +++ drivers/net/mlx5/mlx5_flow_dv.c| 5 drivers/net/mlx5/mlx5_flow_hw.c| 5 8 files changed, 66 insertions(+), 1 deletion(-) -- 2.25.1
[PATCH v4 1/2] net/mlx5/hws: add support for random number match
From: Erez Shitrit The HW adds a random number per each hash, this value can be used for statistic calculation over the packets, for example by setting one bit in the mask of that field we will get half of the traffic in the flow, and so on with the rest of the mask. Signed-off-by: Erez Shitrit --- drivers/net/mlx5/hws/mlx5dr_definer.c | 33 +++ drivers/net/mlx5/hws/mlx5dr_definer.h | 8 ++- drivers/net/mlx5/mlx5_flow.h | 3 +++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hws/mlx5dr_definer.c index 0b60479406..005733372a 100644 --- a/drivers/net/mlx5/hws/mlx5dr_definer.c +++ b/drivers/net/mlx5/hws/mlx5dr_definer.c @@ -182,6 +182,7 @@ struct mlx5dr_definer_conv_data { X(SET_BE32, ipsec_sequence_number, v->hdr.seq, rte_flow_item_esp) \ X(SET, ib_l4_udp_port, UDP_ROCEV2_PORT, rte_flow_item_ib_bth) \ X(SET, ib_l4_opcode, v->hdr.opcode, rte_flow_item_ib_bth) \ + X(SET, random_number, v->value, rte_flow_item_random) \ X(SET, ib_l4_bth_a,v->hdr.a, rte_flow_item_ib_bth) \ /* Item set function format */ @@ -2173,6 +2174,33 @@ mlx5dr_definer_conv_item_ipv6_routing_ext(struct mlx5dr_definer_conv_data *cd, return 0; } +static int +mlx5dr_definer_conv_item_random(struct mlx5dr_definer_conv_data *cd, + struct rte_flow_item *item, + int item_idx) +{ + const struct rte_flow_item_random *m = item->mask; + const struct rte_flow_item_random *l = item->last; + struct mlx5dr_definer_fc *fc; + + if (!m) + return 0; + + if (m->value != (m->value & UINT16_MAX)) { + DR_LOG(ERR, "Random value is 16 bits only"); + rte_errno = EINVAL; + return rte_errno; + } + + fc = &cd->fc[MLX5DR_DEFINER_FNAME_RANDOM_NUM]; + fc->item_idx = item_idx; + fc->tag_set = &mlx5dr_definer_random_number_set; + fc->is_range = l && l->value; + DR_CALC_SET_HDR(fc, random_number, random_number); + + return 0; +} + static int mlx5dr_definer_mt_set_fc(struct mlx5dr_match_template *mt, struct mlx5dr_definer_fc *fc, @@ -2224,6 +2252,7 @@ mlx5dr_definer_check_item_range_supp(struct rte_flow_item *item) case RTE_FLOW_ITEM_TYPE_TAG: case RTE_FLOW_ITEM_TYPE_META: case MLX5_RTE_FLOW_ITEM_TYPE_TAG: + case RTE_FLOW_ITEM_TYPE_RANDOM: return 0; default: DR_LOG(ERR, "Range not supported over item type %d", item->type); @@ -2537,6 +2566,10 @@ mlx5dr_definer_conv_items_to_hl(struct mlx5dr_context *ctx, ret = mlx5dr_definer_conv_item_ptype(&cd, items, i); item_flags |= MLX5_FLOW_ITEM_PTYPE; break; + case RTE_FLOW_ITEM_TYPE_RANDOM: + ret = mlx5dr_definer_conv_item_random(&cd, items, i); + item_flags |= MLX5_FLOW_ITEM_RANDOM; + break; default: DR_LOG(ERR, "Unsupported item type %d", items->type); rte_errno = ENOTSUP; diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.h b/drivers/net/mlx5/hws/mlx5dr_definer.h index 6f1c99e37a..18591ef853 100644 --- a/drivers/net/mlx5/hws/mlx5dr_definer.h +++ b/drivers/net/mlx5/hws/mlx5dr_definer.h @@ -150,6 +150,7 @@ enum mlx5dr_definer_fname { MLX5DR_DEFINER_FNAME_PTYPE_TUNNEL, MLX5DR_DEFINER_FNAME_PTYPE_FRAG_O, MLX5DR_DEFINER_FNAME_PTYPE_FRAG_I, + MLX5DR_DEFINER_FNAME_RANDOM_NUM, MLX5DR_DEFINER_FNAME_MAX, }; @@ -407,6 +408,11 @@ struct mlx5_ifc_definer_hl_ipv4_src_dst_bits { u8 destination_address[0x20]; }; +struct mlx5_ifc_definer_hl_random_number_bits { + u8 random_number[0x10]; + u8 reserved[0x10]; +}; + struct mlx5_ifc_definer_hl_ipv6_addr_bits { u8 ipv6_address_127_96[0x20]; u8 ipv6_address_95_64[0x20]; @@ -516,7 +522,7 @@ struct mlx5_ifc_definer_hl_bits { struct mlx5_ifc_definer_hl_mpls_bits mpls_inner; u8 unsupported_config_headers_outer[0x80]; u8 unsupported_config_headers_inner[0x80]; - u8 unsupported_random_number[0x20]; + struct mlx5_ifc_definer_hl_random_number_bits random_number; struct mlx5_ifc_definer_hl_ipsec_bits ipsec; struct mlx5_ifc_definer_hl_metadata_bits metadata; u8 unsupported_utc_timestamp[0x40]; diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 6dde9de688..0a83c7f384 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -277,6 +277,9 @@ enum mlx5_feature_name { /* NSH ITEM */ #define MLX5_FLOW_ITEM_NSH (1ull << 53) +/* R
[PATCH v4 2/2] net/mlx5: add random item support
Add support for random item in HWS mode. Signed-off-by: Michael Baum Acked-by: Dariusz Sosnowski --- doc/guides/nics/features/mlx5.ini | 1 + doc/guides/nics/mlx5.rst | 9 + doc/guides/rel_notes/release_24_03.rst | 3 +++ drivers/net/mlx5/mlx5_flow_dv.c| 5 + drivers/net/mlx5/mlx5_flow_hw.c| 5 + 5 files changed, 23 insertions(+) diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini index 0739fe9d63..6261b7d657 100644 --- a/doc/guides/nics/features/mlx5.ini +++ b/doc/guides/nics/features/mlx5.ini @@ -88,6 +88,7 @@ port_id = Y port_representor = Y ptype= Y quota= Y +random = Y tag = Y tcp = Y udp = Y diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index 6b52fb93c5..971c229850 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -167,6 +167,7 @@ Features - Sub-Function. - Matching on represented port. - Matching on aggregated affinity. +- Matching on random value. Limitations @@ -564,6 +565,7 @@ Limitations - Modification of the MPLS header is supported only in HWS and only to copy from, the encapsulation level is always 0. - Modification of the 802.1Q Tag, VXLAN Network or GENEVE Network ID's is not supported. + - Modify field action using ``RTE_FLOW_FIELD_RANDOM`` is not supported. - Encapsulation levels are not supported, can modify outermost header fields only. - Offsets cannot skip past the boundary of a field. - If the field type is ``RTE_FLOW_FIELD_MAC_TYPE`` @@ -770,6 +772,13 @@ Limitations - In HW steering (``dv_flow_en`` = 2): - not supported on guest port. +- Match on random value: + + - Supported only with HW Steering enabled (``dv_flow_en`` = 2). + - Supported only in table with ``nb_flows=1``. + - NIC ingress/egress flow in group 0 is not supported. + - Supports matching only 16 bits (LSB). + - During live migration to a new process set its flow engine as standby mode, the user should only program flow rules in group 0 (``fdb_def_rule_en=0``). Live migration is only supported under SWS (``dv_flow_en=1``). diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst index 819cef7f20..93e58b55ca 100644 --- a/doc/guides/rel_notes/release_24_03.rst +++ b/doc/guides/rel_notes/release_24_03.rst @@ -60,6 +60,9 @@ New Features * Added ``RTE_FLOW_ITEM_TYPE_RANDOM`` to match random value. * Added ``RTE_FLOW_FIELD_RANDOM`` to represent it in field API. +* **Updated NVIDIA mlx5 net driver.** + + * Added support for ``RTE_FLOW_ITEM_TYPE_RANDOM`` flow item. Removed Items - diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 115d730317..67a44095d7 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -5396,6 +5396,11 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION, action, "modifications of the MPLS header " "is not supported"); + if (dst_data->field == RTE_FLOW_FIELD_RANDOM || + src_data->field == RTE_FLOW_FIELD_RANDOM) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "modifications of random value is not supported"); if (dst_data->field == RTE_FLOW_FIELD_MARK || src_data->field == RTE_FLOW_FIELD_MARK) if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c index da873ae2e2..af4e9abd89 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -5047,6 +5047,10 @@ flow_hw_validate_action_modify_field(struct rte_eth_dev *dev, return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, "modifying vlan_type is not supported"); + if (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_RANDOM)) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "modifying random value is not supported"); if (flow_hw_modify_field_is_used(action_conf, RTE_FLOW_FIELD_GENEVE_VNI)) return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, @@ -6807,6 +6811,7 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev, case RTE_FLOW_ITEM_TYPE_FLEX: case RTE_FLOW_ITEM_TYPE_IB_BTH: case RTE_FLOW_ITEM_TYPE_PTYPE: + case RTE_FLOW_ITEM_TYPE_RANDOM: break; c
[PATCH v1 2/2] net/mlx5: add support to compare random value
Add support to use "RTE_FLOW_ITEM_TYPE_COMPARE" with "RTE_FLOW_FIELD_RAMDOM" as an argument. The random field is supported only when base is an immediate value, random field cannot be compared with enother field. Signed-off-by: Michael Baum --- drivers/net/mlx5/mlx5_flow_hw.c | 70 - 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c index a944a9b5b0..d472f83909 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -6643,18 +6643,55 @@ flow_hw_prepend_item(const struct rte_flow_item *items, return copied_items; } -static inline bool -flow_hw_item_compare_field_supported(enum rte_flow_field_id field) +static int +flow_hw_item_compare_field_validate(enum rte_flow_field_id arg_field, + enum rte_flow_field_id base_field, + struct rte_flow_error *error) { - switch (field) { + switch (arg_field) { + case RTE_FLOW_FIELD_TAG: + case RTE_FLOW_FIELD_META: + break; + case RTE_FLOW_FIELD_RANDOM: + if (base_field == RTE_FLOW_FIELD_VALUE) + return 0; + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "compare random is supported only with immediate value"); + default: + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "compare item argument field is not supported"); + } + switch (base_field) { case RTE_FLOW_FIELD_TAG: case RTE_FLOW_FIELD_META: case RTE_FLOW_FIELD_VALUE: - return true; + break; + default: + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "compare item base field is not supported"); + } + return 0; +} + +static inline uint32_t +flow_hw_item_compare_width_supported(enum rte_flow_field_id field) +{ + switch (field) { + case RTE_FLOW_FIELD_TAG: + case RTE_FLOW_FIELD_META: + return 32; + case RTE_FLOW_FIELD_RANDOM: + return 16; default: break; } - return false; + return 0; } static int @@ -6663,6 +6700,7 @@ flow_hw_validate_item_compare(const struct rte_flow_item *item, { const struct rte_flow_item_compare *comp_m = item->mask; const struct rte_flow_item_compare *comp_v = item->spec; + int ret; if (unlikely(!comp_m)) return rte_flow_error_set(error, EINVAL, @@ -6674,19 +6712,13 @@ flow_hw_validate_item_compare(const struct rte_flow_item *item, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "compare item only support full mask"); - if (!flow_hw_item_compare_field_supported(comp_m->a.field) || - !flow_hw_item_compare_field_supported(comp_m->b.field)) - return rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, - "compare item field not support"); - if (comp_m->a.field == RTE_FLOW_FIELD_VALUE && - comp_m->b.field == RTE_FLOW_FIELD_VALUE) - return rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, - "compare between value is not valid"); + ret = flow_hw_item_compare_field_validate(comp_m->a.field, + comp_m->b.field, error); + if (ret < 0) + return ret; if (comp_v) { + uint32_t width; + if (comp_v->operation != comp_m->operation || comp_v->a.field != comp_m->a.field || comp_v->b.field != comp_m->b.field) @@ -6694,7 +6726,9 @@ flow_hw_validate_item_compare(const struct rte_flow_item *item, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "compare item spec/mask not matching"); - if ((comp_v->width & comp_m->width) != 32) + width = flow_hw_item_compare_width_supported(comp_v->a.field); + MLX5_ASSERT(width > 0); + if ((comp_v->width & comp_m->width) !=
[PATCH v1 0/2] net/mlx5: add random compare support
Add support for compare item with "RTE_FLOW_FIELD_RANDOM". Depends-on: series-30553 ("ethdev: add random item support") Depends-on: series-30606 ("ethdev: add RTE_FLOW_ITEM_TYPE_COMPARE") Depends-on: series-30665 ("net/mlx5: add random item support") Hamdan Igbaria (1): net/mlx5/hws: add support for compare matcher Michael Baum (1): net/mlx5: add support to compare random value drivers/common/mlx5/mlx5_prm.h| 16 ++ drivers/net/mlx5/hws/mlx5dr_cmd.c | 9 +- drivers/net/mlx5/hws/mlx5dr_cmd.h | 1 + drivers/net/mlx5/hws/mlx5dr_debug.c | 4 +- drivers/net/mlx5/hws/mlx5dr_debug.h | 1 + drivers/net/mlx5/hws/mlx5dr_definer.c | 220 +- drivers/net/mlx5/hws/mlx5dr_definer.h | 33 drivers/net/mlx5/hws/mlx5dr_matcher.c | 48 ++ drivers/net/mlx5/hws/mlx5dr_matcher.h | 12 +- drivers/net/mlx5/mlx5_flow_hw.c | 70 +--- 10 files changed, 387 insertions(+), 27 deletions(-) -- 2.25.1
[PATCH v1 1/2] net/mlx5/hws: add support for compare matcher
From: Hamdan Igbaria Add support for compare matcher, this matcher will allow direct comparison between two packet fields, or a packet field and a value, with fully masked DW. For now this matcher hash table is limited to size 1x1, thus it supports only 1 rule STE. Signed-off-by: Hamdan Igbaria --- drivers/common/mlx5/mlx5_prm.h| 16 ++ drivers/net/mlx5/hws/mlx5dr_cmd.c | 9 +- drivers/net/mlx5/hws/mlx5dr_cmd.h | 1 + drivers/net/mlx5/hws/mlx5dr_debug.c | 4 +- drivers/net/mlx5/hws/mlx5dr_debug.h | 1 + drivers/net/mlx5/hws/mlx5dr_definer.c | 220 +- drivers/net/mlx5/hws/mlx5dr_definer.h | 33 drivers/net/mlx5/hws/mlx5dr_matcher.c | 48 ++ drivers/net/mlx5/hws/mlx5dr_matcher.h | 12 +- 9 files changed, 335 insertions(+), 9 deletions(-) diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h index 9e22dce6da..3033b4d3cd 100644 --- a/drivers/common/mlx5/mlx5_prm.h +++ b/drivers/common/mlx5/mlx5_prm.h @@ -3440,6 +3440,7 @@ enum mlx5_ifc_rtc_ste_format { MLX5_IFC_RTC_STE_FORMAT_8DW = 0x4, MLX5_IFC_RTC_STE_FORMAT_11DW = 0x5, MLX5_IFC_RTC_STE_FORMAT_RANGE = 0x7, + MLX5_IFC_RTC_STE_FORMAT_4DW_RANGE = 0x8, }; enum mlx5_ifc_rtc_reparse_mode { @@ -3478,6 +3479,21 @@ struct mlx5_ifc_rtc_bits { u8 reserved_at_1a0[0x260]; }; +struct mlx5_ifc_ste_match_4dw_range_ctrl_dw_bits { + u8 match[0x1]; + u8 reserved_at_1[0x2]; + u8 base1[0x1]; + u8 inverse1[0x1]; + u8 reserved_at_5[0x1]; + u8 operator1[0x2]; + u8 reserved_at_8[0x3]; + u8 base0[0x1]; + u8 inverse0[0x1]; + u8 reserved_at_a[0x1]; + u8 operator0[0x2]; + u8 compare_delta[0x10]; +}; + struct mlx5_ifc_alias_context_bits { u8 vhca_id_to_be_accessed[0x10]; u8 reserved_at_10[0xd]; diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.c b/drivers/net/mlx5/hws/mlx5dr_cmd.c index 876a47147d..702d6fadac 100644 --- a/drivers/net/mlx5/hws/mlx5dr_cmd.c +++ b/drivers/net/mlx5/hws/mlx5dr_cmd.c @@ -370,9 +370,12 @@ mlx5dr_cmd_rtc_create(struct ibv_context *ctx, attr, obj_type, MLX5_GENERAL_OBJ_TYPE_RTC); attr = MLX5_ADDR_OF(create_rtc_in, in, rtc); - MLX5_SET(rtc, attr, ste_format_0, rtc_attr->is_frst_jumbo ? - MLX5_IFC_RTC_STE_FORMAT_11DW : - MLX5_IFC_RTC_STE_FORMAT_8DW); + if (rtc_attr->is_compare) { + MLX5_SET(rtc, attr, ste_format_0, MLX5_IFC_RTC_STE_FORMAT_4DW_RANGE); + } else { + MLX5_SET(rtc, attr, ste_format_0, rtc_attr->is_frst_jumbo ? +MLX5_IFC_RTC_STE_FORMAT_11DW : MLX5_IFC_RTC_STE_FORMAT_8DW); + } if (rtc_attr->is_scnd_range) { MLX5_SET(rtc, attr, ste_format_1, MLX5_IFC_RTC_STE_FORMAT_RANGE); diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.h b/drivers/net/mlx5/hws/mlx5dr_cmd.h index 18c2b07fc8..073ffd9633 100644 --- a/drivers/net/mlx5/hws/mlx5dr_cmd.h +++ b/drivers/net/mlx5/hws/mlx5dr_cmd.h @@ -82,6 +82,7 @@ struct mlx5dr_cmd_rtc_create_attr { uint8_t reparse_mode; bool is_frst_jumbo; bool is_scnd_range; + bool is_compare; }; struct mlx5dr_cmd_alias_obj_create_attr { diff --git a/drivers/net/mlx5/hws/mlx5dr_debug.c b/drivers/net/mlx5/hws/mlx5dr_debug.c index 11557bcab8..a9094cd35b 100644 --- a/drivers/net/mlx5/hws/mlx5dr_debug.c +++ b/drivers/net/mlx5/hws/mlx5dr_debug.c @@ -99,6 +99,7 @@ static int mlx5dr_debug_dump_matcher_match_template(FILE *f, struct mlx5dr_matcher *matcher) { bool is_root = matcher->tbl->level == MLX5DR_ROOT_LEVEL; + bool is_compare = mlx5dr_matcher_is_compare(matcher); enum mlx5dr_debug_res_type type; int i, ret; @@ -117,7 +118,8 @@ mlx5dr_debug_dump_matcher_match_template(FILE *f, struct mlx5dr_matcher *matcher return rte_errno; } - type = MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_MATCH_DEFINER; + type = is_compare ? MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_COMPARE_MATCH_DEFINER : + MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_MATCH_DEFINER; ret = mlx5dr_debug_dump_matcher_template_definer(f, mt, mt->definer, type); if (ret) return ret; diff --git a/drivers/net/mlx5/hws/mlx5dr_debug.h b/drivers/net/mlx5/hws/mlx5dr_debug.h index 5cffdb10b5..a89a6a0b1d 100644 --- a/drivers/net/mlx5/hws/mlx5dr_debug.h +++ b/drivers/net/mlx5/hws/mlx5dr_debug.h @@ -24,6 +24,7 @@ enum mlx5dr_debug_res_type { MLX5DR_DEBUG_RES_TYPE_MATCHER_ACTION_TEMPLATE = 4204, MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_HASH_DEFINER = 4205, MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_RANGE_DEFINER = 4206, + MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_COMPARE_MATCH_DEFINER = 4207, }; static inline uint64_t diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hw
[PATCH v5 00/14] Enhance the bond framework to support offload
This patch series try to enhance the bond framework to support the offload feature better: * Add new API to make the member port can access some information of the bond port which belongs. * Add new API to get the result of whether bond port is created by the member port. * Add two command line argument to control if enable member port notification and dedicated queue features. * Add logic to support add ports which share the same PCI address into bond port. * Also modify the testpmd application to test the new APIs and logics added by this patch series. --- v2: * Fix compile error on github-robot by removing the redundancy function declaration in the header file. v3: * Use the hole in the structure for the new added flag data field. v4: * Drop two commits not necessary for this series. * Modify some logic as the review comments from reviewers. v5: * Add a new 'rte_eth_bond_flow.h' header file. * Add the patches of NFP PMD as the example of support bond flow offload. --- Long Wu (14): ethdev: add member notification for bonding port ethdev: add API to get firmware creation of bonding port net/bonding: add bonding port arguments net/bonding: support add port by data name net/bonding: support checking valid bonding port ID net/bonding: add commands for bonding port notification net/bonding: create new rte flow header file net/nfp: add bond firmware creation initialization net/nfp: reset bond configuration of firmware net/nfp: handle link event of bond firmware creation net/nfp: support bond member notification net/nfp: handle bond packets from firmware net/nfp: support getting bond firmware creation net/nfp: support offloading bond-flow .../link_bonding_poll_mode_drv_lib.rst| 18 + drivers/net/bonding/bonding_testpmd.c | 128 drivers/net/bonding/eth_bond_private.h| 24 +- drivers/net/bonding/rte_eth_bond.h| 88 +++ drivers/net/bonding/rte_eth_bond_api.c| 122 drivers/net/bonding/rte_eth_bond_args.c | 47 ++ drivers/net/bonding/rte_eth_bond_flow.c | 1 + drivers/net/bonding/rte_eth_bond_flow.h | 22 + drivers/net/bonding/rte_eth_bond_pmd.c| 94 ++- drivers/net/bonding/version.map | 5 + drivers/net/nfp/flower/nfp_flower.c | 87 ++- drivers/net/nfp/flower/nfp_flower.h | 13 + drivers/net/nfp/flower/nfp_flower_bond.c | 691 ++ drivers/net/nfp/flower/nfp_flower_bond.h | 165 + drivers/net/nfp/flower/nfp_flower_cmsg.c | 35 + drivers/net/nfp/flower/nfp_flower_cmsg.h | 12 + drivers/net/nfp/flower/nfp_flower_ctrl.c | 106 ++- drivers/net/nfp/flower/nfp_flower_flow.c | 232 +- .../net/nfp/flower/nfp_flower_representor.c | 35 + .../net/nfp/flower/nfp_flower_representor.h | 2 + drivers/net/nfp/meson.build | 3 +- drivers/net/nfp/nfp_net_common.c | 25 + drivers/net/nfp/nfp_net_common.h | 1 - lib/ethdev/ethdev_driver.h| 38 + 24 files changed, 1951 insertions(+), 43 deletions(-) create mode 100644 drivers/net/bonding/rte_eth_bond_flow.h create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.c create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.h -- 2.39.1
[PATCH v5 01/14] ethdev: add member notification for bonding port
From: Long Wu Bonding PMD does not let member ports know the bonding port's information, like how many member ports the bonding port has, what mode the bonding port is in and so on. Add the notification interface for bonding port to let member port know it is added to a bonding port and what the bonding port's configuration is. If so the member ports have chance to offload bond-flow that its destination port is a bonding port. Signed-off-by: Long Wu Reviewed-by: James Hershaw Reviewed-by: Chaoyong He Reviewed-by: Peng Zhang --- drivers/net/bonding/eth_bond_private.h | 1 + drivers/net/bonding/rte_eth_bond.h | 46 drivers/net/bonding/rte_eth_bond_api.c | 72 ++ drivers/net/bonding/rte_eth_bond_pmd.c | 32 ++-- drivers/net/bonding/version.map| 3 ++ lib/ethdev/ethdev_driver.h | 18 +++ 6 files changed, 169 insertions(+), 3 deletions(-) diff --git a/drivers/net/bonding/eth_bond_private.h b/drivers/net/bonding/eth_bond_private.h index e688894210..f69e85c199 100644 --- a/drivers/net/bonding/eth_bond_private.h +++ b/drivers/net/bonding/eth_bond_private.h @@ -180,6 +180,7 @@ struct bond_dev_private { uint8_t member_update_idx; bool kvargs_processing_is_done; + bool notify_member; /**< Enable member notification of bonding port. */ uint32_t candidate_max_rx_pktlen; uint32_t max_rx_pktlen; diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index f10165f2c6..f6c773615c 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -351,6 +351,52 @@ rte_eth_bond_link_up_prop_delay_set(uint16_t bonding_port_id, int rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id); +/** + * Set the flag of whether bonding port notifies member ports. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param notify + * Flag of whether bonding port notifies member ports. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_notify_member_flag_set(uint16_t bonding_port_id, bool notify); + +/** + * Get the flag of whether bonding port notifies member ports. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param notify + * Flag of whether bonding port notifies member ports. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_notify_member_flag_get(uint16_t bonding_port_id, bool *notify); + +/** + * Notify the member ports of bonding port's information. + * + * This interface is called in the following functions: + * - bond_ethdev_lsc_event_callback() + * - bond_ethdev_configure() + * + * @param bonding_port_id + * Port ID of bonding device. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_notify_members(uint16_t bonding_port_id); #ifdef __cplusplus } diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 99e496556a..239f86ee92 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -627,6 +627,17 @@ __eth_bond_member_add_lock_free(uint16_t bonding_port_id, uint16_t member_port_i member_vlan_filter_set(bonding_port_id, member_port_id); + if (internals->notify_member && + *member_eth_dev->dev_ops->bond_notify_member != NULL) { + ret = member_eth_dev->dev_ops->bond_notify_member(member_eth_dev, + bonding_eth_dev); + if (ret < 0) { + RTE_BOND_LOG(ERR, "Add member (port %u) notify failed!", + member_port_id); + return -1; + } + } + return 0; } @@ -733,6 +744,10 @@ __eth_bond_member_remove_lock_free(uint16_t bonding_port_id, member_eth_dev = &rte_eth_devices[member_port_id]; member_remove(internals, member_eth_dev); member_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDING_MEMBER); + if (internals->notify_member && + *member_eth_dev->dev_ops->bond_notify_member != NULL) + member_eth_dev->dev_ops->bond_notify_member(member_eth_dev, + bonding_eth_dev); /* first member in the active list will be the primary by default, * otherwise use first device in list */ @@ -1098,3 +1113,60 @@ rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id) return internals->link_up_delay_ms; } + +int +rte_eth_bond_notify_member_flag_set(uint16_t bonding_port_id, bool notify) +{ + struct bond_dev_private *internals; + + if (valid_bonding_port_id(bonding_port_id) != 0) + return -EINVAL; + + internals = rte_eth_devices[bonding_port_id].data->dev_private; + + internals->notify_member = notify;
[PATCH v5 02/14] ethdev: add API to get firmware creation of bonding port
From: Long Wu After bonding port notification, member port firmware may create the bonding port. We want to get the result of creatition, so we add this API to do the getting action. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/rte_eth_bond.h | 15 ++ drivers/net/bonding/rte_eth_bond_api.c | 28 ++ drivers/net/bonding/version.map| 1 + lib/ethdev/ethdev_driver.h | 20 ++ 4 files changed, 64 insertions(+) diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index f6c773615c..9a8bed0346 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -398,6 +398,21 @@ __rte_experimental int rte_eth_bond_notify_members(uint16_t bonding_port_id); +/** + * Get the status of specified bonding port created by member port firmware. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param member_port_id + * Port ID of member device. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id); + #ifdef __cplusplus } #endif diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 239f86ee92..83957830a9 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -1170,3 +1170,31 @@ rte_eth_bond_notify_members(uint16_t bonding_port_id) return 0; } + +int +rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id) +{ + uint32_t i; + struct rte_eth_dev *bonding_dev; + struct rte_eth_dev *member_dev; + struct bond_dev_private *internals; + + if (valid_bonding_port_id(bonding_port_id) != 0) + return -EINVAL; + + bonding_dev = &rte_eth_devices[bonding_port_id]; + internals = bonding_dev->data->dev_private; + for (i = 0; i < internals->member_count; i++) { + if (internals->members[i].port_id == member_port_id) + break; + } + + if (i == internals->member_count) + return -EINVAL; + + member_dev = &rte_eth_devices[member_port_id]; + if (*member_dev->dev_ops->bond_fw_create_get == NULL) + return -ENOTSUP; + + return member_dev->dev_ops->bond_fw_create_get(member_dev, bonding_dev); +} diff --git a/drivers/net/bonding/version.map b/drivers/net/bonding/version.map index 3bd5e8ad11..12589f61b0 100644 --- a/drivers/net/bonding/version.map +++ b/drivers/net/bonding/version.map @@ -32,6 +32,7 @@ EXPERIMENTAL { global: rte_eth_bond_8023ad_member_info; rte_eth_bond_active_members_get; + rte_eth_bond_fw_create_get; rte_eth_bond_member_add; rte_eth_bond_member_remove; rte_eth_bond_members_get; diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h index 39316a7a29..09d85ad101 100644 --- a/lib/ethdev/ethdev_driver.h +++ b/lib/ethdev/ethdev_driver.h @@ -1231,6 +1231,21 @@ typedef int (*eth_map_aggr_tx_affinity_t)(struct rte_eth_dev *dev, uint16_t tx_q typedef int (*eth_bond_notify_member)(struct rte_eth_dev *dev, struct rte_eth_dev *bonding_dev); +/** + * @internal + * Get the status of specified bonding port created by member port firmware. + * + * @param dev + * Member port (ethdev) handle. + * @param bonding_dev + * Bonding port (ethdev) handle. + * + * @return + * Negative on error, 0 on success. + */ +typedef int (*eth_bond_fw_create_get)(struct rte_eth_dev *dev, + struct rte_eth_dev *bonding_dev); + /** * @internal A structure containing the functions exported by an Ethernet driver. */ @@ -1473,6 +1488,11 @@ struct eth_dev_ops { /** Notify the member port of bonding port information */ eth_bond_notify_member bond_notify_member; + /** +* Get the status of whether bonding port is successfully created by +* the member port firmware. +*/ + eth_bond_fw_create_get bond_fw_create_get; }; /** -- 2.39.1
[PATCH v5 03/14] net/bonding: add bonding port arguments
From: Long Wu Include the following new arguments for bonding ports: - "notify_member" to enable/disable member notification. - "dedicated_queue" to enable/disable dedicated queue. Add these two arguments in initial argument. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/eth_bond_private.h | 10 drivers/net/bonding/rte_eth_bond.h | 14 ++ drivers/net/bonding/rte_eth_bond_api.c | 14 ++ drivers/net/bonding/rte_eth_bond_args.c | 44 ++ drivers/net/bonding/rte_eth_bond_pmd.c | 61 - 5 files changed, 142 insertions(+), 1 deletion(-) diff --git a/drivers/net/bonding/eth_bond_private.h b/drivers/net/bonding/eth_bond_private.h index f69e85c199..f9603a0f6b 100644 --- a/drivers/net/bonding/eth_bond_private.h +++ b/drivers/net/bonding/eth_bond_private.h @@ -28,6 +28,8 @@ #define PMD_BOND_LSC_POLL_PERIOD_KVARG ("lsc_poll_period_ms") #define PMD_BOND_LINK_UP_PROP_DELAY_KVARG ("up_delay") #define PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG("down_delay") +#define PMD_BOND_NOTIFY_MEMBER_KVARG ("notify_member") +#define PMD_BOND_DEDICATED_QUEUE_KVARG ("dedicated_queue") #define PMD_BOND_XMIT_POLICY_LAYER2_KVARG ("l2") #define PMD_BOND_XMIT_POLICY_LAYER23_KVARG ("l23") @@ -319,6 +321,14 @@ int bond_ethdev_parse_time_ms_kvarg(const char *key, const char *value, void *extra_args); +int +bond_ethdev_parse_notify_member_kvarg(const char *key __rte_unused, + const char *value, void *extra_args); + +int +bond_ethdev_parse_dedicated_queue_kvarg(const char *key __rte_unused, + const char *value, void *extra_args); + void bond_tlb_disable(struct bond_dev_private *internals); diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index 9a8bed0346..84dd39b12f 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -351,6 +351,20 @@ rte_eth_bond_link_up_prop_delay_set(uint16_t bonding_port_id, int rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id); +/** + * Set the flag that whether bonding device enable dedicated queue. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param queue_flag + * The flag of enable bond dedicated queue + * + * @return + * 0 on success, negative value otherwise. + */ +int +rte_eth_bond_dedicated_queue_flag_set(uint16_t bonding_port_id, bool queue_flag); + /** * Set the flag of whether bonding port notifies member ports. * diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 83957830a9..32fa761baf 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -1114,6 +1114,20 @@ rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id) return internals->link_up_delay_ms; } +int +rte_eth_bond_dedicated_queue_flag_set(uint16_t bonding_port_id, bool queue_flag) +{ + struct bond_dev_private *internals; + + if (valid_bonding_port_id(bonding_port_id) != 0) + return -1; + + internals = rte_eth_devices[bonding_port_id].data->dev_private; + internals->mode4.dedicated_queues.enabled = queue_flag; + + return 0; +} + int rte_eth_bond_notify_member_flag_set(uint16_t bonding_port_id, bool notify) { diff --git a/drivers/net/bonding/rte_eth_bond_args.c b/drivers/net/bonding/rte_eth_bond_args.c index bdec5d61d4..8a3e4656ef 100644 --- a/drivers/net/bonding/rte_eth_bond_args.c +++ b/drivers/net/bonding/rte_eth_bond_args.c @@ -20,6 +20,8 @@ const char *pmd_bond_init_valid_arguments[] = { PMD_BOND_MAC_ADDR_KVARG, PMD_BOND_AGG_MODE_KVARG, RTE_DEVARGS_KEY_DRIVER, + PMD_BOND_NOTIFY_MEMBER_KVARG, + PMD_BOND_DEDICATED_QUEUE_KVARG, NULL }; @@ -297,3 +299,45 @@ bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused, return 0; } + +int +bond_ethdev_parse_notify_member_kvarg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + bool *notify_member; + + if (value == NULL || extra_args == NULL) + return -1; + + notify_member = extra_args; + + if (strcmp("enable", value) == 0) + *notify_member = true; + else if (strcmp("disable", value) == 0) + *notify_member = false; + else + return -1; + + return 0; +} + +int +bond_ethdev_parse_dedicated_queue_kvarg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + bool *dedicated_queue; + + if (value == NULL || extra_args == NULL) + return -1; + + dedicated_queue = extra_args; + + if (strcmp("enable", value) == 0) + *dedicated_queue = true; + else if (strcmp("disable", value) == 0) + *dedicated_queue = false;
[PATCH v5 04/14] net/bonding: support add port by data name
From: Long Wu Several ports may share the same PCI address, like NFP representor port. So users cannot add this type of ports to bonding port by "--vdev" argument in dpdk-testpmd. But the port's data name is unique between them, include an option to add such ports to the bonding port. After adding this feature, users can create a bonding port that member port is this type of port by "--vdev" in dpdk-testpmd start command. For example: dpdk-testpmd -l 2-10 -s 0x8 -a ca:00.0,representor=[0-2] --vdev 'net_bonding0,member=flower_repr_p0,member=flower_repr_p1, mode=4,socket_id=1,xmit_policy=l34' -- -i Note: 1. "ca:00.0" is NFP 4000 card. 2. "flower_repr_p0" and "flower_repr_p1" are NFP phy representor port's data name. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/rte_eth_bond_args.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/bonding/rte_eth_bond_args.c b/drivers/net/bonding/rte_eth_bond_args.c index 8a3e4656ef..b320eb3038 100644 --- a/drivers/net/bonding/rte_eth_bond_args.c +++ b/drivers/net/bonding/rte_eth_bond_args.c @@ -70,6 +70,9 @@ find_port_id_by_dev_name(const char *name) if (strcmp(rte_eth_devices[i].device->name, name) == 0) return i; + + if (strcmp(rte_eth_devices[i].data->name, name) == 0) + return i; } return -1; } -- 2.39.1
[PATCH v5 05/14] net/bonding: support checking valid bonding port ID
From: Long Wu Add API to support checking if the port id is a bonding port id. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/rte_eth_bond.h | 13 + drivers/net/bonding/rte_eth_bond_api.c | 7 +++ drivers/net/bonding/version.map| 1 + 3 files changed, 21 insertions(+) diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index 84dd39b12f..62af9bbd99 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -427,6 +427,19 @@ __rte_experimental int rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id); +/** + * Check whether bonding port id is valid. + * + * @param port_id + * Port ID of bonding device. + * + * @return + * true means the port is a bonding device, false means not. + */ +__rte_experimental +bool +rte_eth_bond_is_valid_port(uint16_t port_id); + #ifdef __cplusplus } #endif diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 32fa761baf..5e9437c786 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -1212,3 +1212,10 @@ rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id) return member_dev->dev_ops->bond_fw_create_get(member_dev, bonding_dev); } + + +bool +rte_eth_bond_is_valid_port(uint16_t port_id) +{ + return (valid_bonding_port_id(port_id) == 0); +} diff --git a/drivers/net/bonding/version.map b/drivers/net/bonding/version.map index 12589f61b0..cd27c43092 100644 --- a/drivers/net/bonding/version.map +++ b/drivers/net/bonding/version.map @@ -33,6 +33,7 @@ EXPERIMENTAL { rte_eth_bond_8023ad_member_info; rte_eth_bond_active_members_get; rte_eth_bond_fw_create_get; + rte_eth_bond_is_valid_port; rte_eth_bond_member_add; rte_eth_bond_member_remove; rte_eth_bond_members_get; -- 2.39.1
[PATCH v5 06/14] net/bonding: add commands for bonding port notification
From: Long Wu Add some commands to support bonding port notification in dpdk-testpmd. 1. Users can enable the notification by command: "set bonding notify_member (port_id) (enable|disable)" 2. If member port firmware try to create the bonding port after notification users can get the status by command: "get bonding member firmware create (member_port_id) (bonding_port_id)" Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- .../link_bonding_poll_mode_drv_lib.rst| 18 +++ drivers/net/bonding/bonding_testpmd.c | 128 ++ 2 files changed, 146 insertions(+) diff --git a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst index 60717a3587..653d2f850d 100644 --- a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst +++ b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst @@ -637,3 +637,21 @@ in balance mode with a transmission policy of layer 2+3:: Members (3): [1 3 4] Active Members (3): [1 3 4] Primary: [3] + +set bonding notify_member +~ + +Set the notify member flag of bonding port:: + + testpmd> set bonding notify_member (port_id) (enable|disable) + +This command just set the flag of notification. +If we enable it, bonding PMD will notify member ports when its some +configurations changed. + +get bonding member firmware create +~~ + +Get the status of member port hardware creating the bonding port:: + + testpmd> get bonding member firmware create (member_port_id) (bonding_port_id) diff --git a/drivers/net/bonding/bonding_testpmd.c b/drivers/net/bonding/bonding_testpmd.c index 8fcd6cadd0..48f71da3a7 100644 --- a/drivers/net/bonding/bonding_testpmd.c +++ b/drivers/net/bonding/bonding_testpmd.c @@ -692,6 +692,124 @@ static cmdline_parse_inst_t cmd_set_bonding_agg_mode_policy = { } }; +struct cmd_set_bonding_notify_member_result { + cmdline_fixed_string_t set; + cmdline_fixed_string_t bonding; + cmdline_fixed_string_t notify_member; + uint16_t port_num; + cmdline_fixed_string_t mode; +}; + +static void +cmd_set_bonding_notify_member_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, __rte_unused void *data) +{ + struct cmd_set_bonding_notify_member_result *res = parsed_result; + bool notify_member = false; + + if (strcmp(res->notify_member, "enable") == 0) + notify_member = true; + else if (strcmp(res->notify_member, "disable") == 0) + notify_member = false; + + rte_eth_bond_notify_member_flag_set(res->port_num, notify_member); +} + +static cmdline_parse_token_string_t cmd_set_bonding_notify_member_set = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + set, "set"); +static cmdline_parse_token_string_t cmd_set_bonding_notify_member_bonding = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + bonding, "bonding"); +static cmdline_parse_token_string_t cmd_set_bonding_notify_member = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + notify_member, "notify_member"); +static cmdline_parse_token_num_t cmd_set_bonding_notify_member_portnum = + TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_notify_member_result, + port_num, RTE_UINT16); +static cmdline_parse_token_string_t cmd_set_bonding_notify_member_mode_string = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + mode, "enable#disable"); + +static cmdline_parse_inst_t cmd_set_bonding_notify_member_ports = { + .f = cmd_set_bonding_notify_member_parsed, + .data = NULL, + .help_str = "set bonding notify_member (port_id) (enable|disable)", + .tokens = { + (void *)&cmd_set_bonding_notify_member_set, + (void *)&cmd_set_bonding_notify_member_bonding, + (void *)&cmd_set_bonding_notify_member, + (void *)&cmd_set_bonding_notify_member_portnum, + (void *)&cmd_set_bonding_notify_member_mode_string, + NULL + } +}; + +struct cmd_get_bonding_member_hw_create_result { + cmdline_fixed_string_t get; + cmdline_fixed_string_t bonding; + cmdline_fixed_string_t member; + cmdline_fixed_string_t firmware; + cmdline_fixed_string_t create; + uint16_t member_port_id; + uint16_t bonding_port_id; +}; + +static void +cmd_get_bonding_member_hw_create_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, __rte_unused void *data) +{ + struct cmd_get_bonding_member_hw_create_result *res = parsed_result; + int ret; + + ret = rte_eth_bond_fw_create_get(res->bonding_port_id, res->member_port_id); + if (ret == 0) + printf("Member port %u fi
[PATCH v5 07/14] net/bonding: create new rte flow header file
From: Long Wu Move the flow code to a new head file to make flow related code more clean and make the code architecture more reasonable in the future. There is no functional change, just moving verbatim code around. Signed-off-by: Long Wu Reviewed-by: James Hershaw Reviewed-by: Chaoyong He Reviewed-by: Peng Zhang --- drivers/net/bonding/eth_bond_private.h | 13 - drivers/net/bonding/rte_eth_bond_api.c | 1 + drivers/net/bonding/rte_eth_bond_flow.c | 1 + drivers/net/bonding/rte_eth_bond_flow.h | 22 ++ drivers/net/bonding/rte_eth_bond_pmd.c | 1 + 5 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 drivers/net/bonding/rte_eth_bond_flow.h diff --git a/drivers/net/bonding/eth_bond_private.h b/drivers/net/bonding/eth_bond_private.h index f9603a0f6b..4373465d8d 100644 --- a/drivers/net/bonding/eth_bond_private.h +++ b/drivers/net/bonding/eth_bond_private.h @@ -9,10 +9,8 @@ #include #include -#include #include #include -#include #include "rte_eth_bond.h" #include "eth_bond_8023ad_private.h" @@ -47,8 +45,6 @@ extern const char *pmd_bond_init_valid_arguments[]; extern struct rte_vdev_driver pmd_bond_drv; -extern const struct rte_flow_ops bond_flow_ops; - /** Port Queue Mapping Structure */ struct bond_rx_queue { uint16_t queue_id; @@ -94,15 +90,6 @@ struct bond_member_details { uint16_t reta_size; }; -struct rte_flow { - TAILQ_ENTRY(rte_flow) next; - /* Members flows */ - struct rte_flow *flows[RTE_MAX_ETHPORTS]; - /* Flow description for synchronization */ - struct rte_flow_conv_rule rule; - uint8_t rule_data[]; -}; - typedef void (*burst_xmit_hash_t)(struct rte_mbuf **buf, uint16_t nb_pkts, uint16_t member_count, uint16_t *members); diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 5e9437c786..0a296d3894 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -12,6 +12,7 @@ #include #include "rte_eth_bond.h" +#include "rte_eth_bond_flow.h" #include "eth_bond_private.h" #include "eth_bond_8023ad_private.h" diff --git a/drivers/net/bonding/rte_eth_bond_flow.c b/drivers/net/bonding/rte_eth_bond_flow.c index 71a91675f7..e6c7ce5362 100644 --- a/drivers/net/bonding/rte_eth_bond_flow.c +++ b/drivers/net/bonding/rte_eth_bond_flow.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright 2018 Mellanox Technologies, Ltd */ +#include "rte_eth_bond_flow.h" #include #include diff --git a/drivers/net/bonding/rte_eth_bond_flow.h b/drivers/net/bonding/rte_eth_bond_flow.h new file mode 100644 index 00..7394e0e2e1 --- /dev/null +++ b/drivers/net/bonding/rte_eth_bond_flow.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2023 Corigine, Inc. + */ + +#ifndef _RTE_ETH_BOND_FLOW_H_ +#define _RTE_ETH_BOND_FLOW_H_ + +#include +#include + +extern const struct rte_flow_ops bond_flow_ops; + +struct rte_flow { + TAILQ_ENTRY(rte_flow) next; + struct rte_flow *flows[RTE_MAX_ETHPORTS]; + /**< Member ports flows */ + struct rte_flow_conv_rule rule; + /**< Flow description for synchronization */ + uint8_t rule_data[]; +}; + +#endif /* _RTE_ETH_BOND_FLOW_H_ */ diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c index b3a37a36c8..650f8061a2 100644 --- a/drivers/net/bonding/rte_eth_bond_pmd.c +++ b/drivers/net/bonding/rte_eth_bond_pmd.c @@ -21,6 +21,7 @@ #include #include "rte_eth_bond.h" +#include "rte_eth_bond_flow.h" #include "eth_bond_private.h" #include "eth_bond_8023ad_private.h" -- 2.39.1
[PATCH v5 08/14] net/nfp: add bond firmware creation initialization
From: Long Wu Firmware supports several features and bond firmware creation is one of the features. Driver notifies firmware that driver supports bond firmware creation feature by CPP bus write. If write successfully, initialize driver configuration. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower.c | 64 ++- drivers/net/nfp/flower/nfp_flower.h | 13 + drivers/net/nfp/flower/nfp_flower_bond.c | 59 + drivers/net/nfp/flower/nfp_flower_bond.h | 65 drivers/net/nfp/meson.build | 1 + 5 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.c create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.h diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c index 94b50611f0..195960e00d 100644 --- a/drivers/net/nfp/flower/nfp_flower.c +++ b/drivers/net/nfp/flower/nfp_flower.c @@ -16,6 +16,7 @@ #include "../nfp_cpp_bridge.h" #include "../nfp_logs.h" #include "../nfp_mtr.h" +#include "nfp_flower_bond.h" #include "nfp_flower_ctrl.h" #include "nfp_flower_representor.h" @@ -228,6 +229,42 @@ nfp_flower_init_vnic_common(struct nfp_net_hw *hw, return 0; } +static int +nfp_flower_bond_feature_init(struct nfp_app_fw_flower *app_fw_flower) +{ + int ret; + + /* Notify hardware that driver supports hardware creation of bonding port */ + ret = nfp_rtsym_write_le(app_fw_flower->pf_hw->pf_dev->sym_tbl, + "_abi_flower_balance_sync_enable", 1); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Enable bonding port hardware creation failed."); + return ret; + } + + ret = nfp_flower_bond_init(app_fw_flower); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Initialize bonding structure failed."); + return ret; + } + + app_fw_flower->flower_en_feats |= NFP_FL_ENABLE_BOND; + + return 0; +} + +static int +nfp_flower_sync_feature_bits(struct nfp_app_fw_flower *app_fw_flower) +{ + int ret; + + ret = nfp_flower_bond_feature_init(app_fw_flower); + if (ret != 0) + return ret; + + return 0; +} + static int nfp_flower_init_ctrl_vnic(struct nfp_net_hw *hw) { @@ -538,6 +575,20 @@ nfp_flower_cleanup_ctrl_vnic(struct nfp_net_hw *hw) rte_free(eth_dev); } +static void +nfp_flower_bond_feature_cleanup(struct nfp_app_fw_flower *app_fw_flower) +{ + nfp_flower_bond_cleanup(app_fw_flower); + app_fw_flower->flower_en_feats &= ~NFP_FL_ENABLE_BOND; +} + +static void +nfp_flower_sync_feature_cleanup(struct nfp_app_fw_flower *app_fw_flower) +{ + if (nfp_flower_support_bond_offload(app_fw_flower)) + nfp_flower_bond_feature_cleanup(app_fw_flower); +} + static int nfp_flower_start_ctrl_vnic(struct nfp_net_hw *net_hw) { @@ -768,22 +819,31 @@ nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev, goto ctrl_vnic_cleanup; } + /* Synchronize the features of driver and hardware */ + ret = nfp_flower_sync_feature_bits(app_fw_flower); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Sync feature bits failed"); + goto ctrl_vnic_cleanup; + } + /* Start up flower services */ ret = nfp_flower_enable_services(app_fw_flower); if (ret != 0) { PMD_INIT_LOG(ERR, "Could not enable flower services"); ret = -ESRCH; - goto ctrl_vnic_cleanup; + goto sync_feature_cleanup; } ret = nfp_flower_repr_create(app_fw_flower); if (ret != 0) { PMD_INIT_LOG(ERR, "Could not create representor ports"); - goto ctrl_vnic_cleanup; + goto sync_feature_cleanup; } return 0; +sync_feature_cleanup: + nfp_flower_sync_feature_cleanup(app_fw_flower); ctrl_vnic_cleanup: nfp_flower_cleanup_ctrl_vnic(app_fw_flower->ctrl_hw); ctrl_cpp_area_cleanup: diff --git a/drivers/net/nfp/flower/nfp_flower.h b/drivers/net/nfp/flower/nfp_flower.h index 8393de66c5..30443cd568 100644 --- a/drivers/net/nfp/flower/nfp_flower.h +++ b/drivers/net/nfp/flower/nfp_flower.h @@ -7,6 +7,7 @@ #define __NFP_FLOWER_H__ #include "../nfp_net_common.h" +#include "nfp_flower_bond.h" /* Extra features bitmap. */ #define NFP_FL_FEATS_GENEVE RTE_BIT64(0) @@ -61,6 +62,9 @@ struct nfp_app_fw_flower { /** Number of phyport representors */ uint8_t num_phyport_reprs; + /** Bitmap of features enabled by HW */ + uint8_t flower_en_feats; + /** Pointer to the PF vNIC */ struct nfp_net_hw *pf_hw; @@ -96,6 +100,9 @@ struct nfp_app_fw_flower { /** Function pointers for different NFD version */ struct nfp_flower_nfd_func nfd_func; + + /** Link bond data bl
[PATCH v5 09/14] net/nfp: reset bond configuration of firmware
From: Long Wu Driver sends control message to reset the bond firmware configuration in flower NIC initialization. Firmware should reset bond configuration to avoid strange problems caused by residues. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower.c | 23 ++ drivers/net/nfp/flower/nfp_flower_bond.c | 90 drivers/net/nfp/flower/nfp_flower_bond.h | 54 ++ drivers/net/nfp/flower/nfp_flower_cmsg.c | 35 + drivers/net/nfp/flower/nfp_flower_cmsg.h | 3 + 5 files changed, 205 insertions(+) diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c index 195960e00d..fc3ea84828 100644 --- a/drivers/net/nfp/flower/nfp_flower.c +++ b/drivers/net/nfp/flower/nfp_flower.c @@ -589,6 +589,22 @@ nfp_flower_sync_feature_cleanup(struct nfp_app_fw_flower *app_fw_flower) nfp_flower_bond_feature_cleanup(app_fw_flower); } +static int +nfp_flower_start_features(struct nfp_app_fw_flower *app_flower) +{ + int ret; + + if (nfp_flower_support_bond_offload(app_flower)) { + ret = nfp_flower_bond_reset(app_flower->nfp_bond); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Reset bond feature failed"); + return ret; + } + } + + return 0; +} + static int nfp_flower_start_ctrl_vnic(struct nfp_net_hw *net_hw) { @@ -826,6 +842,13 @@ nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev, goto ctrl_vnic_cleanup; } + /* Start up some features */ + ret = nfp_flower_start_features(app_fw_flower); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Failed to start features"); + goto sync_feature_cleanup; + } + /* Start up flower services */ ret = nfp_flower_enable_services(app_fw_flower); if (ret != 0) { diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index bbd2818e68..4ac27f117c 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -6,8 +6,31 @@ #include +#include "nfp_flower_cmsg.h" #include "nfp_flower_representor.h" +static void +nfp_fl_bond_cmsg_args_init(struct nfp_flower_bond_cmsg_args *cmsg_args, + struct nfp_bond_group *group, + struct rte_eth_dev **active_members, + uint32_t member_cnt, + enum nfp_flower_bond_batch batch) +{ + cmsg_args->group = group; + cmsg_args->active_members = active_members; + cmsg_args->member_cnt = member_cnt; + cmsg_args->batch = batch; +} + +static uint32_t +nfp_fl_get_next_pkt_number(struct nfp_flower_bond *nfp_bond) +{ + nfp_bond->pkt_num++; + nfp_bond->pkt_num &= NFP_FL_BOND_PKT_NUMBER_MASK; + + return nfp_bond->pkt_num; +} + static void nfp_flower_bond_increment_version(struct nfp_flower_bond *nfp_bond) { @@ -57,3 +80,70 @@ nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) rte_free(nfp_bond); app_fw_flower->nfp_bond = NULL; } + +int +nfp_flower_bond_reset(struct nfp_flower_bond *nfp_bond) +{ + struct nfp_app_fw_flower *app_flower; + enum nfp_flower_bond_batch batch = NFP_FLOWER_BOND_BATCH_FIRST; + struct nfp_flower_bond_cmsg_args init_args; + + app_flower = nfp_bond->app_fw_flower; + app_flower->nfp_bond->rst_cfg = true; + + nfp_fl_bond_cmsg_args_init(&init_args, NULL, NULL, 0, batch); + + return nfp_flower_cmsg_bond_config_group(app_flower, &init_args, &batch); +} + +enum nfp_flower_bond_batch +nfp_flower_bond_cmsg_payload(struct nfp_flower_bond *nfp_bond, + struct nfp_flower_cmsg_bond_config *msg, + struct nfp_flower_bond_cmsg_args *init_args) +{ + uint32_t i; + uint8_t flags = 0; + struct nfp_flower_representor *repr; + enum nfp_flower_bond_batch batch = init_args->batch; + + /* Increment batch version for each new batch of config messages. */ + if (batch == NFP_FLOWER_BOND_BATCH_FIRST) { + flags |= NFP_FL_BOND_FIRST; + nfp_flower_bond_increment_version(nfp_bond); + batch = NFP_FLOWER_BOND_BATCH_MEMBER; + } + + /* If it is a reset msg then it is also the end of the batch. */ + if (nfp_bond->rst_cfg) { + flags |= NFP_FL_BOND_RESET; + batch = NFP_FLOWER_BOND_BATCH_FINISHED; + } + + /* +* To signal the end of a batch, both the switch and last flags are set +* and the reserved SYNC group ID is used. +*/ + if (batch == NFP_FLOWER_BOND_BATCH_FINISHED) { + flags |= NFP_FL_BOND_SWITCH | NFP_FL_BOND_LAST; + nfp_bond->rst_cfg = false; + msg->group_id = rte_cpu_to_be_32(NFP_FL_BOND_SYNC_ID); + msg->group_inst = 0; + } else { +
[PATCH v5 10/14] net/nfp: handle link event of bond firmware creation
From: Long Wu If NFP physical representor port is a member port of bonding port, its link status changed and firmware has created the bonding port, driver will record the link status and send control message to notify firmware. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 259 ++ drivers/net/nfp/flower/nfp_flower_bond.h | 22 ++ .../net/nfp/flower/nfp_flower_representor.c | 13 + .../net/nfp/flower/nfp_flower_representor.h | 2 + drivers/net/nfp/meson.build | 2 +- drivers/net/nfp/nfp_net_common.c | 25 ++ drivers/net/nfp/nfp_net_common.h | 1 - 7 files changed, 322 insertions(+), 2 deletions(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index 4ac27f117c..c814c0d4ea 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -4,8 +4,11 @@ */ #include "nfp_flower_bond.h" +#include +#include #include +#include "../nfp_logs.h" #include "nfp_flower_cmsg.h" #include "nfp_flower_representor.h" @@ -43,6 +46,72 @@ nfp_flower_bond_increment_version(struct nfp_flower_bond *nfp_bond) nfp_bond->batch_ver += 2; } +static enum nfp_flower_bond_batch +nfp_flower_bond_remove_node(struct nfp_flower_bond *nfp_bond, + struct nfp_bond_group *entry, + enum nfp_flower_bond_batch batch) +{ + enum nfp_flower_bond_batch batch_out; + struct nfp_flower_bond_cmsg_args cmsg_args; + struct nfp_app_fw_flower *app_flower = nfp_bond->app_fw_flower; + + nfp_fl_bond_cmsg_args_init(&cmsg_args, entry, NULL, 0, batch); + if (nfp_flower_cmsg_bond_config_group(app_flower, &cmsg_args, &batch_out) != 0) { + PMD_DRV_LOG(ERR, "group remove failed."); + return batch_out; + } + + entry->to_remove = false; + entry->offloaded = false; + + if (entry->to_destroy) { + LIST_REMOVE(entry, next); + rte_free(entry); + } + + return batch_out; +} + +static void +nfp_flower_bond_member_work_status(struct nfp_bond_group *entry, + struct rte_eth_dev **active_eth_devs, + uint32_t *active) +{ + uint32_t i; + uint32_t *flags; + uint32_t active_count; + uint16_t member_port_id; + struct rte_eth_dev *eth_dev; + struct bond_dev_private *internals; + struct nfp_flower_representor *repr; + + active_count = 0; + + internals = entry->main_dev->data->dev_private; + for (i = 0; i < internals->member_count; i++) { + member_port_id = internals->members[i].port_id; + if (internals->current_primary_port == member_port_id || + internals->mode != BONDING_MODE_ACTIVE_BACKUP) { + eth_dev = &rte_eth_devices[member_port_id]; + repr = eth_dev->data->dev_private; + flags = &repr->bond_port_flags; + + if ((*flags & NFP_FL_BOND_PORT_CHANGED) != 0) { + *flags &= ~NFP_FL_BOND_PORT_CHANGED; + entry->dirty = true; + } + + if ((*flags & NFP_FL_BOND_PORT_TX_ENABLED) != 0 && + (*flags & NFP_FL_BOND_PORT_LINK_UP) != 0) { + active_eth_devs[active_count] = eth_dev; + active_count++; + } + } + } + + *active = active_count; +} + int nfp_flower_bond_init(struct nfp_app_fw_flower *app_fw_flower) { @@ -96,6 +165,132 @@ nfp_flower_bond_reset(struct nfp_flower_bond *nfp_bond) return nfp_flower_cmsg_bond_config_group(app_flower, &init_args, &batch); } +struct nfp_bond_group * +nfp_flower_bond_find_group(struct nfp_flower_bond *nfp_bond, + const struct rte_eth_dev *bond_dev) +{ + struct nfp_bond_group *group; + + LIST_FOREACH(group, &nfp_bond->group_list, next) { + if (group->main_dev == bond_dev) + return group; + } + + return NULL; +} + +void +nfp_flower_bond_do_work(struct nfp_flower_bond *nfp_bond) +{ + int ret; + uint32_t active_count; + struct nfp_bond_group *entry; + struct nfp_app_fw_flower *app_flower; + struct nfp_flower_bond_cmsg_args cmsg_args; + struct rte_eth_dev *active_eth_devs[RTE_MAX_ETHPORTS]; + enum nfp_flower_bond_batch batch = NFP_FLOWER_BOND_BATCH_FIRST; + + app_flower = nfp_bond->app_fw_flower; + + pthread_mutex_lock(&nfp_bond->mutex); + + LIST_FOREACH(entry, &nfp_bond->group_list, next) { + if (entry->to_remove) { + batch = nfp_flower_bond_remove_node(nfp_bond, entry, batch); +
[PATCH v5 11/14] net/nfp: support bond member notification
From: Long Wu A NFP representor port can receive a bond notification. Then driver will parse this notification into one of these two events: 1. Bonding port configuration may have changed. This includes creation of a bonding port, removal/addition of a member port, changing the bond mode, etc. 2. Bonding port is deleted. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 183 +- drivers/net/nfp/flower/nfp_flower_bond.h | 2 + .../net/nfp/flower/nfp_flower_representor.c | 21 ++ 3 files changed, 205 insertions(+), 1 deletion(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index c814c0d4ea..523e0025ad 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -46,6 +46,39 @@ nfp_flower_bond_increment_version(struct nfp_flower_bond *nfp_bond) nfp_bond->batch_ver += 2; } +static void +nfp_flower_bond_group_id_clear(struct nfp_flower_bond *nfp_bond, + uint32_t id_clear) +{ + bool *group_id_map = nfp_bond->group_id_map; + + if (id_clear >= NFP_FL_BOND_GROUP_MAX || id_clear < NFP_FL_BOND_GROUP_MIN) { + PMD_DRV_LOG(ERR, "Try to clear invalid group id %u.", id_clear); + return; + } + + if (group_id_map[id_clear]) + group_id_map[id_clear] = false; +} + +static int +nfp_flower_bond_group_id_get(struct nfp_flower_bond *nfp_bond, + uint32_t *id_ret) +{ + uint32_t id; + bool *group_id_map = nfp_bond->group_id_map; + + for (id = NFP_FL_BOND_GROUP_MIN; id < NFP_FL_BOND_GROUP_MAX; id++) { + if (!group_id_map[id]) { + group_id_map[id] = true; + *id_ret = id; + return 0; + } + } + + return -ENOSPC; +} + static enum nfp_flower_bond_batch nfp_flower_bond_remove_node(struct nfp_flower_bond *nfp_bond, struct nfp_bond_group *entry, @@ -65,6 +98,7 @@ nfp_flower_bond_remove_node(struct nfp_flower_bond *nfp_bond, entry->offloaded = false; if (entry->to_destroy) { + nfp_flower_bond_group_id_clear(nfp_bond, entry->group_id); LIST_REMOVE(entry, next); rte_free(entry); } @@ -139,6 +173,7 @@ nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) pthread_mutex_lock(&nfp_bond->mutex); LIST_FOREACH(entry, &nfp_bond->group_list, next) { + nfp_flower_bond_group_id_clear(nfp_bond, entry->group_id); LIST_REMOVE(entry, next); rte_free(entry); } @@ -271,16 +306,162 @@ nfp_flower_bond_change_linkstatus_event(struct nfp_flower_bond *nfp_bond, *bond_port_flags |= NFP_FL_BOND_PORT_CHANGED; } +static struct nfp_bond_group * +nfp_flower_bond_group_create(struct nfp_flower_bond *nfp_bond, + struct rte_eth_dev *bond_dev) +{ + uint32_t id; + unsigned int numa_node; + struct nfp_bond_group *group = NULL; + + if (nfp_flower_bond_group_id_get(nfp_bond, &id) < 0) + return NULL; + + numa_node = rte_socket_id(); + + group = rte_zmalloc_socket(NULL, sizeof(struct nfp_bond_group), + RTE_CACHE_LINE_SIZE, numa_node); + if (group == NULL) { + PMD_DRV_LOG(ERR, "Unable malloc memory for nfp bond group"); + nfp_flower_bond_group_id_clear(nfp_bond, id); + return NULL; + } + + group->group_id = id; + group->main_dev = bond_dev; + group->dirty = true; + group->offloaded = false; + group->to_remove = false; + group->to_destroy = false; + group->member_cnt = 0; + group->group_inst = ++nfp_bond->global_inst; + LIST_INSERT_HEAD(&nfp_bond->group_list, group, next); + + return group; +} + +static int +nfp_flower_bond_changeupper_event(struct nfp_flower_bond *nfp_bond, + struct rte_eth_dev *bond_dev) +{ + uint32_t i; + uint16_t port_id; + bool can_offload = true; + uint16_t nfp_member_count; + struct rte_eth_dev *eth_dev; + struct nfp_bond_group *group; + struct bond_dev_private *internals; + struct nfp_flower_representor *repr; + struct nfp_app_fw_flower *app_flower; + + internals = bond_dev->data->dev_private; + app_flower = nfp_bond->app_fw_flower; + nfp_member_count = 0; + + for (i = 0; i < internals->member_count; i++) { + port_id = internals->members[i].port_id; + eth_dev = &rte_eth_devices[port_id]; + if (!nfp_flower_is_phy_repr(eth_dev)) { + can_offload = false; + break; + } + + repr = eth_dev->data->dev_private; + + if (repr->app_fw_flower !
[PATCH v5 12/14] net/nfp: handle bond packets from firmware
From: Long Wu Firmware sends bond firmware creation packets to driver, driver needs to handle it in ctrl VNIC service. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 53 drivers/net/nfp/flower/nfp_flower_bond.h | 14 +++ drivers/net/nfp/flower/nfp_flower_ctrl.c | 106 +-- 3 files changed, 168 insertions(+), 5 deletions(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index 523e0025ad..73b616360a 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -161,6 +161,8 @@ nfp_flower_bond_init(struct nfp_app_fw_flower *app_fw_flower) LIST_INIT(&nfp_bond->group_list); nfp_flower_bond_increment_version(nfp_bond); nfp_bond->app_fw_flower = app_fw_flower; + nfp_bond->retrans.head = 0; + nfp_bond->retrans.rear = 0; return 0; } @@ -168,6 +170,7 @@ nfp_flower_bond_init(struct nfp_app_fw_flower *app_fw_flower) void nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) { + struct rte_mbuf *mbuf_tmp; struct nfp_bond_group *entry; struct nfp_flower_bond *nfp_bond = app_fw_flower->nfp_bond; @@ -177,6 +180,12 @@ nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) LIST_REMOVE(entry, next); rte_free(entry); } + + mbuf_tmp = nfp_fl_bond_get_unprocessed(nfp_bond); + for (; mbuf_tmp != NULL; + mbuf_tmp = nfp_fl_bond_get_unprocessed(nfp_bond)) + rte_pktmbuf_free(mbuf_tmp); + pthread_mutex_unlock(&nfp_bond->mutex); pthread_mutex_destroy(&nfp_bond->mutex); @@ -587,3 +596,47 @@ nfp_flower_bond_all_member_are_phyrepr(struct rte_eth_dev *bond_dev) return true; } + +int +nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, + struct rte_mbuf *mbuf) +{ + uint16_t rear_real; + struct nfp_flower_bond_retrans *retrans; + struct nfp_flower_cmsg_bond_config *cmsg_payload; + + cmsg_payload = rte_pktmbuf_mtod_offset(mbuf, + struct nfp_flower_cmsg_bond_config *, + NFP_FLOWER_CMSG_HLEN); + + if (rte_be_to_cpu_32(cmsg_payload->group_id) >= NFP_FL_BOND_GROUP_MAX) + return -EINVAL; + + retrans = &nfp_bond->retrans; + rear_real = (retrans->rear + 1) % NFP_FL_BOND_RETRANS_LIMIT; + if (rear_real == retrans->head) + return -ENOSPC; + + retrans->mbufs[retrans->rear] = mbuf; + + retrans->rear = rear_real; + + return 0; +} + +struct rte_mbuf * +nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond) +{ + struct rte_mbuf *mbuf; + struct nfp_flower_bond_retrans *retrans; + + retrans = &nfp_bond->retrans; + if (retrans->rear == retrans->head) + return NULL; + + mbuf = retrans->mbufs[retrans->head]; + + retrans->head = (retrans->head + 1) % NFP_FL_BOND_RETRANS_LIMIT; + + return mbuf; +} diff --git a/drivers/net/nfp/flower/nfp_flower_bond.h b/drivers/net/nfp/flower/nfp_flower_bond.h index f73589265f..59d1c211f2 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.h +++ b/drivers/net/nfp/flower/nfp_flower_bond.h @@ -41,6 +41,9 @@ #define NFP_FL_BOND_PORT_TX_ENABLEDRTE_BIT32(1) #define NFP_FL_BOND_PORT_CHANGED RTE_BIT32(2) +/** We store 100(101-1) mbufs but queue needs 101 */ +#define NFP_FL_BOND_RETRANS_LIMIT 101 + enum nfp_flower_bond_batch { NFP_FLOWER_BOND_BATCH_FIRST, NFP_FLOWER_BOND_BATCH_MEMBER, @@ -53,6 +56,12 @@ enum nfp_flower_bond_event { NFP_FLOWER_UNREGISTER }; +struct nfp_flower_bond_retrans { + struct rte_mbuf *mbufs[NFP_FL_BOND_RETRANS_LIMIT]; + uint16_t head; + uint16_t rear; +}; + /* Control message payload for bond config */ struct nfp_flower_cmsg_bond_config { /** Configuration flags */ @@ -113,6 +122,8 @@ struct nfp_flower_bond { bool group_id_map[NFP_FL_BOND_GROUP_MAX]; /** Pointer to the flower app */ struct nfp_app_fw_flower *app_fw_flower; + /** Store bond offload packets from firmware */ + struct nfp_flower_bond_retrans retrans; }; struct nfp_flower_bond_cmsg_args { @@ -139,5 +150,8 @@ int nfp_flower_bond_event_handle(struct nfp_flower_bond *nfp_bond, enum nfp_flower_bond_event event); void nfp_flower_bond_do_work(struct nfp_flower_bond *nfp_bond); bool nfp_flower_bond_all_member_are_phyrepr(struct rte_eth_dev *bond_dev); +struct rte_mbuf *nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond); +int nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, + struct rte_mbuf *mbuf); #endif /* __NFP_FLOWER_BOND_H__ */ diff --git a/drivers/net/nfp/flower/nfp_flower_ctrl.c b/drivers/net/nfp/flower/nfp_flower_ctrl.c index c25487c277..75c8c
[PATCH v5 14/14] net/nfp: support offloading bond-flow
From: Long Wu After bonding port notification and firmware created the bonding port, NFP rte_flow rule adds support for destination port to bonding port. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 22 +++ drivers/net/nfp/flower/nfp_flower_bond.h | 6 + drivers/net/nfp/flower/nfp_flower_cmsg.h | 9 + drivers/net/nfp/flower/nfp_flower_flow.c | 232 +-- 4 files changed, 252 insertions(+), 17 deletions(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index c809465ffc..6e4d60659a 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -667,3 +667,25 @@ nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, return ret; } + +int +nfp_flower_bond_get_output_id(struct nfp_flower_bond *nfp_bond, + const struct rte_eth_dev *bond_dev, + uint32_t *group_id) +{ + struct nfp_bond_group *group; + + pthread_mutex_lock(&nfp_bond->mutex); + + group = nfp_flower_bond_find_group(nfp_bond, bond_dev); + if (group == NULL) { + pthread_mutex_unlock(&nfp_bond->mutex); + return -ENOENT; + } + + *group_id = group->group_id; + + pthread_mutex_unlock(&nfp_bond->mutex); + + return 0; +} diff --git a/drivers/net/nfp/flower/nfp_flower_bond.h b/drivers/net/nfp/flower/nfp_flower_bond.h index 91d7d88b8c..6debe32549 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.h +++ b/drivers/net/nfp/flower/nfp_flower_bond.h @@ -44,6 +44,9 @@ /** We store 100(101-1) mbufs but queue needs 101 */ #define NFP_FL_BOND_RETRANS_LIMIT 101 +/* Flow output action of bonding port */ +#define NFP_FL_BOND_OUT0xC0DE + enum nfp_flower_bond_batch { NFP_FLOWER_BOND_BATCH_FIRST, NFP_FLOWER_BOND_BATCH_MEMBER, @@ -155,5 +158,8 @@ int nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, struct rte_mbuf *mbuf); int nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, struct rte_eth_dev *nfp_dev); +int nfp_flower_bond_get_output_id(struct nfp_flower_bond *nfp_bond, + const struct rte_eth_dev *bond_dev, + uint32_t *group_id); #endif /* __NFP_FLOWER_BOND_H__ */ diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h index 60ab58a3b1..17ef943855 100644 --- a/drivers/net/nfp/flower/nfp_flower_cmsg.h +++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h @@ -712,6 +712,15 @@ struct nfp_fl_act_head { uint8_t len_lw; }; +#define NFP_FL_PRE_BOND_VER_OFF 8 + +struct nfp_fl_pre_bond { + struct nfp_fl_act_head head; + rte_be16_t group_id; + uint8_t lag_version[3]; + uint8_t instance; +}; + struct nfp_fl_act_output { struct nfp_fl_act_head head; rte_be16_t flags; diff --git a/drivers/net/nfp/flower/nfp_flower_flow.c b/drivers/net/nfp/flower/nfp_flower_flow.c index e26be30d18..6e21ad8c26 100644 --- a/drivers/net/nfp/flower/nfp_flower_flow.c +++ b/drivers/net/nfp/flower/nfp_flower_flow.c @@ -5,12 +5,14 @@ #include "nfp_flower_flow.h" +#include #include #include #include #include #include "flower/nfp_conntrack.h" +#include "flower/nfp_flower_bond.h" #include "flower/nfp_flower_representor.h" #include "nfpcore/nfp_rtsym.h" #include "nfp_logs.h" @@ -969,9 +971,23 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[], return 0; } +static bool +nfp_flow_check_bond_action(struct nfp_flower_representor *representor, + uint32_t port_id) +{ + struct rte_eth_dev *bond_dev = &rte_eth_devices[port_id]; + + if (nfp_flower_support_bond_offload(representor->app_fw_flower) || + !nfp_flower_bond_all_member_are_phyrepr(bond_dev)) + return false; + + return true; +} + static int nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], - struct nfp_fl_key_ls *key_ls) + struct nfp_fl_key_ls *key_ls, + struct nfp_flower_representor *representor) { int ret = 0; bool meter_flag = false; @@ -981,6 +997,8 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], bool mac_set_flag = false; bool ttl_tos_flag = false; const struct rte_flow_action *action; + const struct rte_flow_action_port_id *port_id; + const struct rte_flow_action_ethdev *action_ethdev; for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) { /* Make sure actions length no longer than NFP_FL_MAX_A_SIZ */ @@ -1006,10 +1024,36 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], case RTE_FLOW_ACTION_TYPE_PORT_ID: PMD_DRV_LOG(DEBUG, "RTE_FLOW_AC
[PATCH v5 13/14] net/nfp: support getting bond firmware creation
From: Long Wu Support getting the status that whether the bonding port is created by the nfp firmware. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 27 +++ drivers/net/nfp/flower/nfp_flower_bond.h | 2 ++ .../net/nfp/flower/nfp_flower_representor.c | 1 + 3 files changed, 30 insertions(+) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index 73b616360a..c809465ffc 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -640,3 +640,30 @@ nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond) return mbuf; } + +int +nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, + struct rte_eth_dev *nfp_dev) +{ + int ret = -EINVAL; + struct nfp_bond_group *group; + struct nfp_flower_bond *nfp_bond; + struct nfp_flower_representor *repr; + + if (!nfp_flower_bond_is_member_port(bond_dev, nfp_dev)) + return ret; + + repr = nfp_dev->data->dev_private; + nfp_bond = repr->app_fw_flower->nfp_bond; + + pthread_mutex_lock(&nfp_bond->mutex); + LIST_FOREACH(group, &nfp_bond->group_list, next) { + if (group->main_dev == bond_dev && group->offloaded == true) { + ret = 0; + break; + } + } + pthread_mutex_unlock(&nfp_bond->mutex); + + return ret; +} diff --git a/drivers/net/nfp/flower/nfp_flower_bond.h b/drivers/net/nfp/flower/nfp_flower_bond.h index 59d1c211f2..91d7d88b8c 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.h +++ b/drivers/net/nfp/flower/nfp_flower_bond.h @@ -153,5 +153,7 @@ bool nfp_flower_bond_all_member_are_phyrepr(struct rte_eth_dev *bond_dev); struct rte_mbuf *nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond); int nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, struct rte_mbuf *mbuf); +int nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, + struct rte_eth_dev *nfp_dev); #endif /* __NFP_FLOWER_BOND_H__ */ diff --git a/drivers/net/nfp/flower/nfp_flower_representor.c b/drivers/net/nfp/flower/nfp_flower_representor.c index 43106da90e..8a1b2eff66 100644 --- a/drivers/net/nfp/flower/nfp_flower_representor.c +++ b/drivers/net/nfp/flower/nfp_flower_representor.c @@ -458,6 +458,7 @@ static const struct eth_dev_ops nfp_flower_repr_dev_ops = { .mtr_ops_get = nfp_net_mtr_ops_get, .bond_notify_member = nfp_flower_repr_bond_notify_member, + .bond_fw_create_get = nfp_flower_bond_fw_create_get, }; static uint32_t -- 2.39.1
Re: [PATCH v6 12/20] crypto/armv8: do not use PMD logtype
On 2023/12/23 1:42 AM, Stephen Hemminger wrote: On Fri, 22 Dec 2023 09:11:45 -0800 Stephen Hemminger wrote: - RTE_LOG(INFO, PMD, - "Closing ARMv8 crypto device %s on numa socket %u\n", + ARVM8_CRYTPO_LOG_INFO( + "Closing ARMv8 crypto device %s on numa socket %u", name, rte_socket_id Typo here will fix in next version Thanks for the effort. With change ARVM8_CRYTPO_LOG_INFO -> ARMV8_CRYPTO_LOG_INFO, Acked-by: Ruifeng Wang
[PATCH v6 00/14] Enhance the bond framework to support offload
This patch series try to enhance the bond framework to support the offload feature better: * Add new API to make the member port can access some information of the bond port which belongs. * Add new API to get the result of whether bond port is created by the member port. * Add two command line argument to control if enable member port notification and dedicated queue features. * Add logic to support add ports which share the same PCI address into bond port. * Also modify the testpmd application to test the new APIs and logics added by this patch series. --- v2: * Fix compile error on github-robot by removing the redundancy function declaration in the header file. v3: * Use the hole in the structure for the new added flag data field. v4: * Drop two commits not necessary for this series. * Modify some logic as the review comments from reviewers. v5: * Add a new 'rte_eth_bond_flow.h' header file. * Add the patches of NFP PMD as the example of support bond flow offload. v6: * Try to solve the CI build error. --- Long Wu (14): ethdev: add member notification for bonding port ethdev: add API to get firmware creation of bonding port net/bonding: add bonding port arguments net/bonding: support add port by data name net/bonding: support checking valid bonding port ID net/bonding: add commands for bonding port notification net/bonding: create new rte flow header file net/nfp: add bond firmware creation initialization net/nfp: reset bond configuration of firmware net/nfp: handle link event of bond firmware creation net/nfp: support bond member notification net/nfp: handle bond packets from firmware net/nfp: support getting bond firmware creation net/nfp: support offloading bond-flow .../link_bonding_poll_mode_drv_lib.rst| 18 + drivers/net/bonding/bonding_testpmd.c | 128 drivers/net/bonding/eth_bond_private.h| 24 +- drivers/net/bonding/rte_eth_bond.h| 88 +++ drivers/net/bonding/rte_eth_bond_api.c| 122 drivers/net/bonding/rte_eth_bond_args.c | 47 ++ drivers/net/bonding/rte_eth_bond_flow.c | 1 + drivers/net/bonding/rte_eth_bond_flow.h | 22 + drivers/net/bonding/rte_eth_bond_pmd.c| 94 ++- drivers/net/bonding/version.map | 5 + drivers/net/nfp/flower/nfp_flower.c | 87 ++- drivers/net/nfp/flower/nfp_flower.h | 13 + drivers/net/nfp/flower/nfp_flower_bond.c | 691 ++ drivers/net/nfp/flower/nfp_flower_bond.h | 165 + drivers/net/nfp/flower/nfp_flower_cmsg.c | 35 + drivers/net/nfp/flower/nfp_flower_cmsg.h | 12 + drivers/net/nfp/flower/nfp_flower_ctrl.c | 106 ++- drivers/net/nfp/flower/nfp_flower_flow.c | 232 +- .../net/nfp/flower/nfp_flower_representor.c | 35 + .../net/nfp/flower/nfp_flower_representor.h | 2 + drivers/net/nfp/meson.build | 3 +- drivers/net/nfp/nfp_net_common.c | 25 + drivers/net/nfp/nfp_net_common.h | 1 - lib/ethdev/ethdev_driver.h| 38 + 24 files changed, 1951 insertions(+), 43 deletions(-) create mode 100644 drivers/net/bonding/rte_eth_bond_flow.h create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.c create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.h -- 2.39.1
[PATCH v6 01/14] ethdev: add member notification for bonding port
From: Long Wu Bonding PMD does not let member ports know the bonding port's information, like how many member ports the bonding port has, what mode the bonding port is in and so on. Add the notification interface for bonding port to let member port know it is added to a bonding port and what the bonding port's configuration is. If so the member ports have chance to offload bond-flow that its destination port is a bonding port. Signed-off-by: Long Wu Reviewed-by: James Hershaw Reviewed-by: Chaoyong He Reviewed-by: Peng Zhang --- drivers/net/bonding/eth_bond_private.h | 1 + drivers/net/bonding/rte_eth_bond.h | 46 drivers/net/bonding/rte_eth_bond_api.c | 72 ++ drivers/net/bonding/rte_eth_bond_pmd.c | 32 ++-- drivers/net/bonding/version.map| 3 ++ lib/ethdev/ethdev_driver.h | 18 +++ 6 files changed, 169 insertions(+), 3 deletions(-) diff --git a/drivers/net/bonding/eth_bond_private.h b/drivers/net/bonding/eth_bond_private.h index e688894210..f69e85c199 100644 --- a/drivers/net/bonding/eth_bond_private.h +++ b/drivers/net/bonding/eth_bond_private.h @@ -180,6 +180,7 @@ struct bond_dev_private { uint8_t member_update_idx; bool kvargs_processing_is_done; + bool notify_member; /**< Enable member notification of bonding port. */ uint32_t candidate_max_rx_pktlen; uint32_t max_rx_pktlen; diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index f10165f2c6..f6c773615c 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -351,6 +351,52 @@ rte_eth_bond_link_up_prop_delay_set(uint16_t bonding_port_id, int rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id); +/** + * Set the flag of whether bonding port notifies member ports. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param notify + * Flag of whether bonding port notifies member ports. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_notify_member_flag_set(uint16_t bonding_port_id, bool notify); + +/** + * Get the flag of whether bonding port notifies member ports. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param notify + * Flag of whether bonding port notifies member ports. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_notify_member_flag_get(uint16_t bonding_port_id, bool *notify); + +/** + * Notify the member ports of bonding port's information. + * + * This interface is called in the following functions: + * - bond_ethdev_lsc_event_callback() + * - bond_ethdev_configure() + * + * @param bonding_port_id + * Port ID of bonding device. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_notify_members(uint16_t bonding_port_id); #ifdef __cplusplus } diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 99e496556a..239f86ee92 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -627,6 +627,17 @@ __eth_bond_member_add_lock_free(uint16_t bonding_port_id, uint16_t member_port_i member_vlan_filter_set(bonding_port_id, member_port_id); + if (internals->notify_member && + *member_eth_dev->dev_ops->bond_notify_member != NULL) { + ret = member_eth_dev->dev_ops->bond_notify_member(member_eth_dev, + bonding_eth_dev); + if (ret < 0) { + RTE_BOND_LOG(ERR, "Add member (port %u) notify failed!", + member_port_id); + return -1; + } + } + return 0; } @@ -733,6 +744,10 @@ __eth_bond_member_remove_lock_free(uint16_t bonding_port_id, member_eth_dev = &rte_eth_devices[member_port_id]; member_remove(internals, member_eth_dev); member_eth_dev->data->dev_flags &= (~RTE_ETH_DEV_BONDING_MEMBER); + if (internals->notify_member && + *member_eth_dev->dev_ops->bond_notify_member != NULL) + member_eth_dev->dev_ops->bond_notify_member(member_eth_dev, + bonding_eth_dev); /* first member in the active list will be the primary by default, * otherwise use first device in list */ @@ -1098,3 +1113,60 @@ rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id) return internals->link_up_delay_ms; } + +int +rte_eth_bond_notify_member_flag_set(uint16_t bonding_port_id, bool notify) +{ + struct bond_dev_private *internals; + + if (valid_bonding_port_id(bonding_port_id) != 0) + return -EINVAL; + + internals = rte_eth_devices[bonding_port_id].data->dev_private; + + internals->notify_member = notify;
[PATCH v6 02/14] ethdev: add API to get firmware creation of bonding port
From: Long Wu After bonding port notification, member port firmware may create the bonding port. We want to get the result of creatition, so we add this API to do the getting action. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/rte_eth_bond.h | 15 ++ drivers/net/bonding/rte_eth_bond_api.c | 28 ++ drivers/net/bonding/version.map| 1 + lib/ethdev/ethdev_driver.h | 20 ++ 4 files changed, 64 insertions(+) diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index f6c773615c..9a8bed0346 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -398,6 +398,21 @@ __rte_experimental int rte_eth_bond_notify_members(uint16_t bonding_port_id); +/** + * Get the status of specified bonding port created by member port firmware. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param member_port_id + * Port ID of member device. + * + * @return + * 0 on success, negative value otherwise. + */ +__rte_experimental +int +rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id); + #ifdef __cplusplus } #endif diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 239f86ee92..83957830a9 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -1170,3 +1170,31 @@ rte_eth_bond_notify_members(uint16_t bonding_port_id) return 0; } + +int +rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id) +{ + uint32_t i; + struct rte_eth_dev *bonding_dev; + struct rte_eth_dev *member_dev; + struct bond_dev_private *internals; + + if (valid_bonding_port_id(bonding_port_id) != 0) + return -EINVAL; + + bonding_dev = &rte_eth_devices[bonding_port_id]; + internals = bonding_dev->data->dev_private; + for (i = 0; i < internals->member_count; i++) { + if (internals->members[i].port_id == member_port_id) + break; + } + + if (i == internals->member_count) + return -EINVAL; + + member_dev = &rte_eth_devices[member_port_id]; + if (*member_dev->dev_ops->bond_fw_create_get == NULL) + return -ENOTSUP; + + return member_dev->dev_ops->bond_fw_create_get(member_dev, bonding_dev); +} diff --git a/drivers/net/bonding/version.map b/drivers/net/bonding/version.map index 3bd5e8ad11..12589f61b0 100644 --- a/drivers/net/bonding/version.map +++ b/drivers/net/bonding/version.map @@ -32,6 +32,7 @@ EXPERIMENTAL { global: rte_eth_bond_8023ad_member_info; rte_eth_bond_active_members_get; + rte_eth_bond_fw_create_get; rte_eth_bond_member_add; rte_eth_bond_member_remove; rte_eth_bond_members_get; diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h index 39316a7a29..09d85ad101 100644 --- a/lib/ethdev/ethdev_driver.h +++ b/lib/ethdev/ethdev_driver.h @@ -1231,6 +1231,21 @@ typedef int (*eth_map_aggr_tx_affinity_t)(struct rte_eth_dev *dev, uint16_t tx_q typedef int (*eth_bond_notify_member)(struct rte_eth_dev *dev, struct rte_eth_dev *bonding_dev); +/** + * @internal + * Get the status of specified bonding port created by member port firmware. + * + * @param dev + * Member port (ethdev) handle. + * @param bonding_dev + * Bonding port (ethdev) handle. + * + * @return + * Negative on error, 0 on success. + */ +typedef int (*eth_bond_fw_create_get)(struct rte_eth_dev *dev, + struct rte_eth_dev *bonding_dev); + /** * @internal A structure containing the functions exported by an Ethernet driver. */ @@ -1473,6 +1488,11 @@ struct eth_dev_ops { /** Notify the member port of bonding port information */ eth_bond_notify_member bond_notify_member; + /** +* Get the status of whether bonding port is successfully created by +* the member port firmware. +*/ + eth_bond_fw_create_get bond_fw_create_get; }; /** -- 2.39.1
[PATCH v6 03/14] net/bonding: add bonding port arguments
From: Long Wu Include the following new arguments for bonding ports: - "notify_member" to enable/disable member notification. - "dedicated_queue" to enable/disable dedicated queue. Add these two arguments in initial argument. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/eth_bond_private.h | 10 drivers/net/bonding/rte_eth_bond.h | 14 ++ drivers/net/bonding/rte_eth_bond_api.c | 14 ++ drivers/net/bonding/rte_eth_bond_args.c | 44 ++ drivers/net/bonding/rte_eth_bond_pmd.c | 61 - 5 files changed, 142 insertions(+), 1 deletion(-) diff --git a/drivers/net/bonding/eth_bond_private.h b/drivers/net/bonding/eth_bond_private.h index f69e85c199..f9603a0f6b 100644 --- a/drivers/net/bonding/eth_bond_private.h +++ b/drivers/net/bonding/eth_bond_private.h @@ -28,6 +28,8 @@ #define PMD_BOND_LSC_POLL_PERIOD_KVARG ("lsc_poll_period_ms") #define PMD_BOND_LINK_UP_PROP_DELAY_KVARG ("up_delay") #define PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG("down_delay") +#define PMD_BOND_NOTIFY_MEMBER_KVARG ("notify_member") +#define PMD_BOND_DEDICATED_QUEUE_KVARG ("dedicated_queue") #define PMD_BOND_XMIT_POLICY_LAYER2_KVARG ("l2") #define PMD_BOND_XMIT_POLICY_LAYER23_KVARG ("l23") @@ -319,6 +321,14 @@ int bond_ethdev_parse_time_ms_kvarg(const char *key, const char *value, void *extra_args); +int +bond_ethdev_parse_notify_member_kvarg(const char *key __rte_unused, + const char *value, void *extra_args); + +int +bond_ethdev_parse_dedicated_queue_kvarg(const char *key __rte_unused, + const char *value, void *extra_args); + void bond_tlb_disable(struct bond_dev_private *internals); diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index 9a8bed0346..84dd39b12f 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -351,6 +351,20 @@ rte_eth_bond_link_up_prop_delay_set(uint16_t bonding_port_id, int rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id); +/** + * Set the flag that whether bonding device enable dedicated queue. + * + * @param bonding_port_id + * Port ID of bonding device. + * @param queue_flag + * The flag of enable bond dedicated queue + * + * @return + * 0 on success, negative value otherwise. + */ +int +rte_eth_bond_dedicated_queue_flag_set(uint16_t bonding_port_id, bool queue_flag); + /** * Set the flag of whether bonding port notifies member ports. * diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 83957830a9..32fa761baf 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -1114,6 +1114,20 @@ rte_eth_bond_link_up_prop_delay_get(uint16_t bonding_port_id) return internals->link_up_delay_ms; } +int +rte_eth_bond_dedicated_queue_flag_set(uint16_t bonding_port_id, bool queue_flag) +{ + struct bond_dev_private *internals; + + if (valid_bonding_port_id(bonding_port_id) != 0) + return -1; + + internals = rte_eth_devices[bonding_port_id].data->dev_private; + internals->mode4.dedicated_queues.enabled = queue_flag; + + return 0; +} + int rte_eth_bond_notify_member_flag_set(uint16_t bonding_port_id, bool notify) { diff --git a/drivers/net/bonding/rte_eth_bond_args.c b/drivers/net/bonding/rte_eth_bond_args.c index bdec5d61d4..8a3e4656ef 100644 --- a/drivers/net/bonding/rte_eth_bond_args.c +++ b/drivers/net/bonding/rte_eth_bond_args.c @@ -20,6 +20,8 @@ const char *pmd_bond_init_valid_arguments[] = { PMD_BOND_MAC_ADDR_KVARG, PMD_BOND_AGG_MODE_KVARG, RTE_DEVARGS_KEY_DRIVER, + PMD_BOND_NOTIFY_MEMBER_KVARG, + PMD_BOND_DEDICATED_QUEUE_KVARG, NULL }; @@ -297,3 +299,45 @@ bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused, return 0; } + +int +bond_ethdev_parse_notify_member_kvarg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + bool *notify_member; + + if (value == NULL || extra_args == NULL) + return -1; + + notify_member = extra_args; + + if (strcmp("enable", value) == 0) + *notify_member = true; + else if (strcmp("disable", value) == 0) + *notify_member = false; + else + return -1; + + return 0; +} + +int +bond_ethdev_parse_dedicated_queue_kvarg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + bool *dedicated_queue; + + if (value == NULL || extra_args == NULL) + return -1; + + dedicated_queue = extra_args; + + if (strcmp("enable", value) == 0) + *dedicated_queue = true; + else if (strcmp("disable", value) == 0) + *dedicated_queue = false;
[PATCH v6 04/14] net/bonding: support add port by data name
From: Long Wu Several ports may share the same PCI address, like NFP representor port. So users cannot add this type of ports to bonding port by "--vdev" argument in dpdk-testpmd. But the port's data name is unique between them, include an option to add such ports to the bonding port. After adding this feature, users can create a bonding port that member port is this type of port by "--vdev" in dpdk-testpmd start command. For example: dpdk-testpmd -l 2-10 -s 0x8 -a ca:00.0,representor=[0-2] --vdev 'net_bonding0,member=flower_repr_p0,member=flower_repr_p1, mode=4,socket_id=1,xmit_policy=l34' -- -i Note: 1. "ca:00.0" is NFP 4000 card. 2. "flower_repr_p0" and "flower_repr_p1" are NFP phy representor port's data name. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/rte_eth_bond_args.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/bonding/rte_eth_bond_args.c b/drivers/net/bonding/rte_eth_bond_args.c index 8a3e4656ef..b320eb3038 100644 --- a/drivers/net/bonding/rte_eth_bond_args.c +++ b/drivers/net/bonding/rte_eth_bond_args.c @@ -70,6 +70,9 @@ find_port_id_by_dev_name(const char *name) if (strcmp(rte_eth_devices[i].device->name, name) == 0) return i; + + if (strcmp(rte_eth_devices[i].data->name, name) == 0) + return i; } return -1; } -- 2.39.1
[PATCH v6 05/14] net/bonding: support checking valid bonding port ID
From: Long Wu Add API to support checking if the port id is a bonding port id. Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- drivers/net/bonding/rte_eth_bond.h | 13 + drivers/net/bonding/rte_eth_bond_api.c | 7 +++ drivers/net/bonding/version.map| 1 + 3 files changed, 21 insertions(+) diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h index 84dd39b12f..62af9bbd99 100644 --- a/drivers/net/bonding/rte_eth_bond.h +++ b/drivers/net/bonding/rte_eth_bond.h @@ -427,6 +427,19 @@ __rte_experimental int rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id); +/** + * Check whether bonding port id is valid. + * + * @param port_id + * Port ID of bonding device. + * + * @return + * true means the port is a bonding device, false means not. + */ +__rte_experimental +bool +rte_eth_bond_is_valid_port(uint16_t port_id); + #ifdef __cplusplus } #endif diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 32fa761baf..5e9437c786 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -1212,3 +1212,10 @@ rte_eth_bond_fw_create_get(uint16_t bonding_port_id, uint16_t member_port_id) return member_dev->dev_ops->bond_fw_create_get(member_dev, bonding_dev); } + + +bool +rte_eth_bond_is_valid_port(uint16_t port_id) +{ + return (valid_bonding_port_id(port_id) == 0); +} diff --git a/drivers/net/bonding/version.map b/drivers/net/bonding/version.map index 12589f61b0..cd27c43092 100644 --- a/drivers/net/bonding/version.map +++ b/drivers/net/bonding/version.map @@ -33,6 +33,7 @@ EXPERIMENTAL { rte_eth_bond_8023ad_member_info; rte_eth_bond_active_members_get; rte_eth_bond_fw_create_get; + rte_eth_bond_is_valid_port; rte_eth_bond_member_add; rte_eth_bond_member_remove; rte_eth_bond_members_get; -- 2.39.1
[PATCH v6 06/14] net/bonding: add commands for bonding port notification
From: Long Wu Add some commands to support bonding port notification in dpdk-testpmd. 1. Users can enable the notification by command: "set bonding notify_member (port_id) (enable|disable)" 2. If member port firmware try to create the bonding port after notification users can get the status by command: "get bonding member firmware create (member_port_id) (bonding_port_id)" Signed-off-by: Long Wu Reviewed-by: Chaoyong He Reviewed-by: James Hershaw Reviewed-by: Peng Zhang --- .../link_bonding_poll_mode_drv_lib.rst| 18 +++ drivers/net/bonding/bonding_testpmd.c | 128 ++ 2 files changed, 146 insertions(+) diff --git a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst index 60717a3587..653d2f850d 100644 --- a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst +++ b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst @@ -637,3 +637,21 @@ in balance mode with a transmission policy of layer 2+3:: Members (3): [1 3 4] Active Members (3): [1 3 4] Primary: [3] + +set bonding notify_member +~ + +Set the notify member flag of bonding port:: + + testpmd> set bonding notify_member (port_id) (enable|disable) + +This command just set the flag of notification. +If we enable it, bonding PMD will notify member ports when its some +configurations changed. + +get bonding member firmware create +~~ + +Get the status of member port hardware creating the bonding port:: + + testpmd> get bonding member firmware create (member_port_id) (bonding_port_id) diff --git a/drivers/net/bonding/bonding_testpmd.c b/drivers/net/bonding/bonding_testpmd.c index 8fcd6cadd0..48f71da3a7 100644 --- a/drivers/net/bonding/bonding_testpmd.c +++ b/drivers/net/bonding/bonding_testpmd.c @@ -692,6 +692,124 @@ static cmdline_parse_inst_t cmd_set_bonding_agg_mode_policy = { } }; +struct cmd_set_bonding_notify_member_result { + cmdline_fixed_string_t set; + cmdline_fixed_string_t bonding; + cmdline_fixed_string_t notify_member; + uint16_t port_num; + cmdline_fixed_string_t mode; +}; + +static void +cmd_set_bonding_notify_member_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, __rte_unused void *data) +{ + struct cmd_set_bonding_notify_member_result *res = parsed_result; + bool notify_member = false; + + if (strcmp(res->notify_member, "enable") == 0) + notify_member = true; + else if (strcmp(res->notify_member, "disable") == 0) + notify_member = false; + + rte_eth_bond_notify_member_flag_set(res->port_num, notify_member); +} + +static cmdline_parse_token_string_t cmd_set_bonding_notify_member_set = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + set, "set"); +static cmdline_parse_token_string_t cmd_set_bonding_notify_member_bonding = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + bonding, "bonding"); +static cmdline_parse_token_string_t cmd_set_bonding_notify_member = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + notify_member, "notify_member"); +static cmdline_parse_token_num_t cmd_set_bonding_notify_member_portnum = + TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_notify_member_result, + port_num, RTE_UINT16); +static cmdline_parse_token_string_t cmd_set_bonding_notify_member_mode_string = + TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_notify_member_result, + mode, "enable#disable"); + +static cmdline_parse_inst_t cmd_set_bonding_notify_member_ports = { + .f = cmd_set_bonding_notify_member_parsed, + .data = NULL, + .help_str = "set bonding notify_member (port_id) (enable|disable)", + .tokens = { + (void *)&cmd_set_bonding_notify_member_set, + (void *)&cmd_set_bonding_notify_member_bonding, + (void *)&cmd_set_bonding_notify_member, + (void *)&cmd_set_bonding_notify_member_portnum, + (void *)&cmd_set_bonding_notify_member_mode_string, + NULL + } +}; + +struct cmd_get_bonding_member_hw_create_result { + cmdline_fixed_string_t get; + cmdline_fixed_string_t bonding; + cmdline_fixed_string_t member; + cmdline_fixed_string_t firmware; + cmdline_fixed_string_t create; + uint16_t member_port_id; + uint16_t bonding_port_id; +}; + +static void +cmd_get_bonding_member_hw_create_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, __rte_unused void *data) +{ + struct cmd_get_bonding_member_hw_create_result *res = parsed_result; + int ret; + + ret = rte_eth_bond_fw_create_get(res->bonding_port_id, res->member_port_id); + if (ret == 0) + printf("Member port %u fi
[PATCH v6 07/14] net/bonding: create new rte flow header file
From: Long Wu Move the flow code to a new head file to make flow related code more clean and make the code architecture more reasonable in the future. There is no functional change, just moving verbatim code around. Signed-off-by: Long Wu Reviewed-by: James Hershaw Reviewed-by: Chaoyong He Reviewed-by: Peng Zhang --- drivers/net/bonding/eth_bond_private.h | 13 - drivers/net/bonding/rte_eth_bond_api.c | 1 + drivers/net/bonding/rte_eth_bond_flow.c | 1 + drivers/net/bonding/rte_eth_bond_flow.h | 22 ++ drivers/net/bonding/rte_eth_bond_pmd.c | 1 + 5 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 drivers/net/bonding/rte_eth_bond_flow.h diff --git a/drivers/net/bonding/eth_bond_private.h b/drivers/net/bonding/eth_bond_private.h index f9603a0f6b..4373465d8d 100644 --- a/drivers/net/bonding/eth_bond_private.h +++ b/drivers/net/bonding/eth_bond_private.h @@ -9,10 +9,8 @@ #include #include -#include #include #include -#include #include "rte_eth_bond.h" #include "eth_bond_8023ad_private.h" @@ -47,8 +45,6 @@ extern const char *pmd_bond_init_valid_arguments[]; extern struct rte_vdev_driver pmd_bond_drv; -extern const struct rte_flow_ops bond_flow_ops; - /** Port Queue Mapping Structure */ struct bond_rx_queue { uint16_t queue_id; @@ -94,15 +90,6 @@ struct bond_member_details { uint16_t reta_size; }; -struct rte_flow { - TAILQ_ENTRY(rte_flow) next; - /* Members flows */ - struct rte_flow *flows[RTE_MAX_ETHPORTS]; - /* Flow description for synchronization */ - struct rte_flow_conv_rule rule; - uint8_t rule_data[]; -}; - typedef void (*burst_xmit_hash_t)(struct rte_mbuf **buf, uint16_t nb_pkts, uint16_t member_count, uint16_t *members); diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c index 5e9437c786..0a296d3894 100644 --- a/drivers/net/bonding/rte_eth_bond_api.c +++ b/drivers/net/bonding/rte_eth_bond_api.c @@ -12,6 +12,7 @@ #include #include "rte_eth_bond.h" +#include "rte_eth_bond_flow.h" #include "eth_bond_private.h" #include "eth_bond_8023ad_private.h" diff --git a/drivers/net/bonding/rte_eth_bond_flow.c b/drivers/net/bonding/rte_eth_bond_flow.c index 71a91675f7..e6c7ce5362 100644 --- a/drivers/net/bonding/rte_eth_bond_flow.c +++ b/drivers/net/bonding/rte_eth_bond_flow.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright 2018 Mellanox Technologies, Ltd */ +#include "rte_eth_bond_flow.h" #include #include diff --git a/drivers/net/bonding/rte_eth_bond_flow.h b/drivers/net/bonding/rte_eth_bond_flow.h new file mode 100644 index 00..7394e0e2e1 --- /dev/null +++ b/drivers/net/bonding/rte_eth_bond_flow.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2023 Corigine, Inc. + */ + +#ifndef _RTE_ETH_BOND_FLOW_H_ +#define _RTE_ETH_BOND_FLOW_H_ + +#include +#include + +extern const struct rte_flow_ops bond_flow_ops; + +struct rte_flow { + TAILQ_ENTRY(rte_flow) next; + struct rte_flow *flows[RTE_MAX_ETHPORTS]; + /**< Member ports flows */ + struct rte_flow_conv_rule rule; + /**< Flow description for synchronization */ + uint8_t rule_data[]; +}; + +#endif /* _RTE_ETH_BOND_FLOW_H_ */ diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c index b3a37a36c8..650f8061a2 100644 --- a/drivers/net/bonding/rte_eth_bond_pmd.c +++ b/drivers/net/bonding/rte_eth_bond_pmd.c @@ -21,6 +21,7 @@ #include #include "rte_eth_bond.h" +#include "rte_eth_bond_flow.h" #include "eth_bond_private.h" #include "eth_bond_8023ad_private.h" -- 2.39.1
[PATCH v6 09/14] net/nfp: reset bond configuration of firmware
From: Long Wu Driver sends control message to reset the bond firmware configuration in flower NIC initialization. Firmware should reset bond configuration to avoid strange problems caused by residues. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower.c | 23 ++ drivers/net/nfp/flower/nfp_flower_bond.c | 90 drivers/net/nfp/flower/nfp_flower_bond.h | 54 ++ drivers/net/nfp/flower/nfp_flower_cmsg.c | 35 + drivers/net/nfp/flower/nfp_flower_cmsg.h | 3 + 5 files changed, 205 insertions(+) diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c index 195960e00d..fc3ea84828 100644 --- a/drivers/net/nfp/flower/nfp_flower.c +++ b/drivers/net/nfp/flower/nfp_flower.c @@ -589,6 +589,22 @@ nfp_flower_sync_feature_cleanup(struct nfp_app_fw_flower *app_fw_flower) nfp_flower_bond_feature_cleanup(app_fw_flower); } +static int +nfp_flower_start_features(struct nfp_app_fw_flower *app_flower) +{ + int ret; + + if (nfp_flower_support_bond_offload(app_flower)) { + ret = nfp_flower_bond_reset(app_flower->nfp_bond); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Reset bond feature failed"); + return ret; + } + } + + return 0; +} + static int nfp_flower_start_ctrl_vnic(struct nfp_net_hw *net_hw) { @@ -826,6 +842,13 @@ nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev, goto ctrl_vnic_cleanup; } + /* Start up some features */ + ret = nfp_flower_start_features(app_fw_flower); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Failed to start features"); + goto sync_feature_cleanup; + } + /* Start up flower services */ ret = nfp_flower_enable_services(app_fw_flower); if (ret != 0) { diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index bbd2818e68..4ac27f117c 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -6,8 +6,31 @@ #include +#include "nfp_flower_cmsg.h" #include "nfp_flower_representor.h" +static void +nfp_fl_bond_cmsg_args_init(struct nfp_flower_bond_cmsg_args *cmsg_args, + struct nfp_bond_group *group, + struct rte_eth_dev **active_members, + uint32_t member_cnt, + enum nfp_flower_bond_batch batch) +{ + cmsg_args->group = group; + cmsg_args->active_members = active_members; + cmsg_args->member_cnt = member_cnt; + cmsg_args->batch = batch; +} + +static uint32_t +nfp_fl_get_next_pkt_number(struct nfp_flower_bond *nfp_bond) +{ + nfp_bond->pkt_num++; + nfp_bond->pkt_num &= NFP_FL_BOND_PKT_NUMBER_MASK; + + return nfp_bond->pkt_num; +} + static void nfp_flower_bond_increment_version(struct nfp_flower_bond *nfp_bond) { @@ -57,3 +80,70 @@ nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) rte_free(nfp_bond); app_fw_flower->nfp_bond = NULL; } + +int +nfp_flower_bond_reset(struct nfp_flower_bond *nfp_bond) +{ + struct nfp_app_fw_flower *app_flower; + enum nfp_flower_bond_batch batch = NFP_FLOWER_BOND_BATCH_FIRST; + struct nfp_flower_bond_cmsg_args init_args; + + app_flower = nfp_bond->app_fw_flower; + app_flower->nfp_bond->rst_cfg = true; + + nfp_fl_bond_cmsg_args_init(&init_args, NULL, NULL, 0, batch); + + return nfp_flower_cmsg_bond_config_group(app_flower, &init_args, &batch); +} + +enum nfp_flower_bond_batch +nfp_flower_bond_cmsg_payload(struct nfp_flower_bond *nfp_bond, + struct nfp_flower_cmsg_bond_config *msg, + struct nfp_flower_bond_cmsg_args *init_args) +{ + uint32_t i; + uint8_t flags = 0; + struct nfp_flower_representor *repr; + enum nfp_flower_bond_batch batch = init_args->batch; + + /* Increment batch version for each new batch of config messages. */ + if (batch == NFP_FLOWER_BOND_BATCH_FIRST) { + flags |= NFP_FL_BOND_FIRST; + nfp_flower_bond_increment_version(nfp_bond); + batch = NFP_FLOWER_BOND_BATCH_MEMBER; + } + + /* If it is a reset msg then it is also the end of the batch. */ + if (nfp_bond->rst_cfg) { + flags |= NFP_FL_BOND_RESET; + batch = NFP_FLOWER_BOND_BATCH_FINISHED; + } + + /* +* To signal the end of a batch, both the switch and last flags are set +* and the reserved SYNC group ID is used. +*/ + if (batch == NFP_FLOWER_BOND_BATCH_FINISHED) { + flags |= NFP_FL_BOND_SWITCH | NFP_FL_BOND_LAST; + nfp_bond->rst_cfg = false; + msg->group_id = rte_cpu_to_be_32(NFP_FL_BOND_SYNC_ID); + msg->group_inst = 0; + } else { +
[PATCH v6 08/14] net/nfp: add bond firmware creation initialization
From: Long Wu Firmware supports several features and bond firmware creation is one of the features. Driver notifies firmware that driver supports bond firmware creation feature by CPP bus write. If write successfully, initialize driver configuration. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower.c | 64 ++- drivers/net/nfp/flower/nfp_flower.h | 13 + drivers/net/nfp/flower/nfp_flower_bond.c | 59 + drivers/net/nfp/flower/nfp_flower_bond.h | 65 drivers/net/nfp/meson.build | 1 + 5 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.c create mode 100644 drivers/net/nfp/flower/nfp_flower_bond.h diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c index 94b50611f0..195960e00d 100644 --- a/drivers/net/nfp/flower/nfp_flower.c +++ b/drivers/net/nfp/flower/nfp_flower.c @@ -16,6 +16,7 @@ #include "../nfp_cpp_bridge.h" #include "../nfp_logs.h" #include "../nfp_mtr.h" +#include "nfp_flower_bond.h" #include "nfp_flower_ctrl.h" #include "nfp_flower_representor.h" @@ -228,6 +229,42 @@ nfp_flower_init_vnic_common(struct nfp_net_hw *hw, return 0; } +static int +nfp_flower_bond_feature_init(struct nfp_app_fw_flower *app_fw_flower) +{ + int ret; + + /* Notify hardware that driver supports hardware creation of bonding port */ + ret = nfp_rtsym_write_le(app_fw_flower->pf_hw->pf_dev->sym_tbl, + "_abi_flower_balance_sync_enable", 1); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Enable bonding port hardware creation failed."); + return ret; + } + + ret = nfp_flower_bond_init(app_fw_flower); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Initialize bonding structure failed."); + return ret; + } + + app_fw_flower->flower_en_feats |= NFP_FL_ENABLE_BOND; + + return 0; +} + +static int +nfp_flower_sync_feature_bits(struct nfp_app_fw_flower *app_fw_flower) +{ + int ret; + + ret = nfp_flower_bond_feature_init(app_fw_flower); + if (ret != 0) + return ret; + + return 0; +} + static int nfp_flower_init_ctrl_vnic(struct nfp_net_hw *hw) { @@ -538,6 +575,20 @@ nfp_flower_cleanup_ctrl_vnic(struct nfp_net_hw *hw) rte_free(eth_dev); } +static void +nfp_flower_bond_feature_cleanup(struct nfp_app_fw_flower *app_fw_flower) +{ + nfp_flower_bond_cleanup(app_fw_flower); + app_fw_flower->flower_en_feats &= ~NFP_FL_ENABLE_BOND; +} + +static void +nfp_flower_sync_feature_cleanup(struct nfp_app_fw_flower *app_fw_flower) +{ + if (nfp_flower_support_bond_offload(app_fw_flower)) + nfp_flower_bond_feature_cleanup(app_fw_flower); +} + static int nfp_flower_start_ctrl_vnic(struct nfp_net_hw *net_hw) { @@ -768,22 +819,31 @@ nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev, goto ctrl_vnic_cleanup; } + /* Synchronize the features of driver and hardware */ + ret = nfp_flower_sync_feature_bits(app_fw_flower); + if (ret != 0) { + PMD_INIT_LOG(ERR, "Sync feature bits failed"); + goto ctrl_vnic_cleanup; + } + /* Start up flower services */ ret = nfp_flower_enable_services(app_fw_flower); if (ret != 0) { PMD_INIT_LOG(ERR, "Could not enable flower services"); ret = -ESRCH; - goto ctrl_vnic_cleanup; + goto sync_feature_cleanup; } ret = nfp_flower_repr_create(app_fw_flower); if (ret != 0) { PMD_INIT_LOG(ERR, "Could not create representor ports"); - goto ctrl_vnic_cleanup; + goto sync_feature_cleanup; } return 0; +sync_feature_cleanup: + nfp_flower_sync_feature_cleanup(app_fw_flower); ctrl_vnic_cleanup: nfp_flower_cleanup_ctrl_vnic(app_fw_flower->ctrl_hw); ctrl_cpp_area_cleanup: diff --git a/drivers/net/nfp/flower/nfp_flower.h b/drivers/net/nfp/flower/nfp_flower.h index 8393de66c5..30443cd568 100644 --- a/drivers/net/nfp/flower/nfp_flower.h +++ b/drivers/net/nfp/flower/nfp_flower.h @@ -7,6 +7,7 @@ #define __NFP_FLOWER_H__ #include "../nfp_net_common.h" +#include "nfp_flower_bond.h" /* Extra features bitmap. */ #define NFP_FL_FEATS_GENEVE RTE_BIT64(0) @@ -61,6 +62,9 @@ struct nfp_app_fw_flower { /** Number of phyport representors */ uint8_t num_phyport_reprs; + /** Bitmap of features enabled by HW */ + uint8_t flower_en_feats; + /** Pointer to the PF vNIC */ struct nfp_net_hw *pf_hw; @@ -96,6 +100,9 @@ struct nfp_app_fw_flower { /** Function pointers for different NFD version */ struct nfp_flower_nfd_func nfd_func; + + /** Link bond data bl
[PATCH v6 10/14] net/nfp: handle link event of bond firmware creation
From: Long Wu If NFP physical representor port is a member port of bonding port, its link status changed and firmware has created the bonding port, driver will record the link status and send control message to notify firmware. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 259 ++ drivers/net/nfp/flower/nfp_flower_bond.h | 22 ++ .../net/nfp/flower/nfp_flower_representor.c | 13 + .../net/nfp/flower/nfp_flower_representor.h | 2 + drivers/net/nfp/meson.build | 2 +- drivers/net/nfp/nfp_net_common.c | 25 ++ drivers/net/nfp/nfp_net_common.h | 1 - 7 files changed, 322 insertions(+), 2 deletions(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index 4ac27f117c..c814c0d4ea 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -4,8 +4,11 @@ */ #include "nfp_flower_bond.h" +#include +#include #include +#include "../nfp_logs.h" #include "nfp_flower_cmsg.h" #include "nfp_flower_representor.h" @@ -43,6 +46,72 @@ nfp_flower_bond_increment_version(struct nfp_flower_bond *nfp_bond) nfp_bond->batch_ver += 2; } +static enum nfp_flower_bond_batch +nfp_flower_bond_remove_node(struct nfp_flower_bond *nfp_bond, + struct nfp_bond_group *entry, + enum nfp_flower_bond_batch batch) +{ + enum nfp_flower_bond_batch batch_out; + struct nfp_flower_bond_cmsg_args cmsg_args; + struct nfp_app_fw_flower *app_flower = nfp_bond->app_fw_flower; + + nfp_fl_bond_cmsg_args_init(&cmsg_args, entry, NULL, 0, batch); + if (nfp_flower_cmsg_bond_config_group(app_flower, &cmsg_args, &batch_out) != 0) { + PMD_DRV_LOG(ERR, "group remove failed."); + return batch_out; + } + + entry->to_remove = false; + entry->offloaded = false; + + if (entry->to_destroy) { + LIST_REMOVE(entry, next); + rte_free(entry); + } + + return batch_out; +} + +static void +nfp_flower_bond_member_work_status(struct nfp_bond_group *entry, + struct rte_eth_dev **active_eth_devs, + uint32_t *active) +{ + uint32_t i; + uint32_t *flags; + uint32_t active_count; + uint16_t member_port_id; + struct rte_eth_dev *eth_dev; + struct bond_dev_private *internals; + struct nfp_flower_representor *repr; + + active_count = 0; + + internals = entry->main_dev->data->dev_private; + for (i = 0; i < internals->member_count; i++) { + member_port_id = internals->members[i].port_id; + if (internals->current_primary_port == member_port_id || + internals->mode != BONDING_MODE_ACTIVE_BACKUP) { + eth_dev = &rte_eth_devices[member_port_id]; + repr = eth_dev->data->dev_private; + flags = &repr->bond_port_flags; + + if ((*flags & NFP_FL_BOND_PORT_CHANGED) != 0) { + *flags &= ~NFP_FL_BOND_PORT_CHANGED; + entry->dirty = true; + } + + if ((*flags & NFP_FL_BOND_PORT_TX_ENABLED) != 0 && + (*flags & NFP_FL_BOND_PORT_LINK_UP) != 0) { + active_eth_devs[active_count] = eth_dev; + active_count++; + } + } + } + + *active = active_count; +} + int nfp_flower_bond_init(struct nfp_app_fw_flower *app_fw_flower) { @@ -96,6 +165,132 @@ nfp_flower_bond_reset(struct nfp_flower_bond *nfp_bond) return nfp_flower_cmsg_bond_config_group(app_flower, &init_args, &batch); } +struct nfp_bond_group * +nfp_flower_bond_find_group(struct nfp_flower_bond *nfp_bond, + const struct rte_eth_dev *bond_dev) +{ + struct nfp_bond_group *group; + + LIST_FOREACH(group, &nfp_bond->group_list, next) { + if (group->main_dev == bond_dev) + return group; + } + + return NULL; +} + +void +nfp_flower_bond_do_work(struct nfp_flower_bond *nfp_bond) +{ + int ret; + uint32_t active_count; + struct nfp_bond_group *entry; + struct nfp_app_fw_flower *app_flower; + struct nfp_flower_bond_cmsg_args cmsg_args; + struct rte_eth_dev *active_eth_devs[RTE_MAX_ETHPORTS]; + enum nfp_flower_bond_batch batch = NFP_FLOWER_BOND_BATCH_FIRST; + + app_flower = nfp_bond->app_fw_flower; + + pthread_mutex_lock(&nfp_bond->mutex); + + LIST_FOREACH(entry, &nfp_bond->group_list, next) { + if (entry->to_remove) { + batch = nfp_flower_bond_remove_node(nfp_bond, entry, batch); +
[PATCH v6 11/14] net/nfp: support bond member notification
From: Long Wu A NFP representor port can receive a bond notification. Then driver will parse this notification into one of these two events: 1. Bonding port configuration may have changed. This includes creation of a bonding port, removal/addition of a member port, changing the bond mode, etc. 2. Bonding port is deleted. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 183 +- drivers/net/nfp/flower/nfp_flower_bond.h | 2 + .../net/nfp/flower/nfp_flower_representor.c | 21 ++ 3 files changed, 205 insertions(+), 1 deletion(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index c814c0d4ea..523e0025ad 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -46,6 +46,39 @@ nfp_flower_bond_increment_version(struct nfp_flower_bond *nfp_bond) nfp_bond->batch_ver += 2; } +static void +nfp_flower_bond_group_id_clear(struct nfp_flower_bond *nfp_bond, + uint32_t id_clear) +{ + bool *group_id_map = nfp_bond->group_id_map; + + if (id_clear >= NFP_FL_BOND_GROUP_MAX || id_clear < NFP_FL_BOND_GROUP_MIN) { + PMD_DRV_LOG(ERR, "Try to clear invalid group id %u.", id_clear); + return; + } + + if (group_id_map[id_clear]) + group_id_map[id_clear] = false; +} + +static int +nfp_flower_bond_group_id_get(struct nfp_flower_bond *nfp_bond, + uint32_t *id_ret) +{ + uint32_t id; + bool *group_id_map = nfp_bond->group_id_map; + + for (id = NFP_FL_BOND_GROUP_MIN; id < NFP_FL_BOND_GROUP_MAX; id++) { + if (!group_id_map[id]) { + group_id_map[id] = true; + *id_ret = id; + return 0; + } + } + + return -ENOSPC; +} + static enum nfp_flower_bond_batch nfp_flower_bond_remove_node(struct nfp_flower_bond *nfp_bond, struct nfp_bond_group *entry, @@ -65,6 +98,7 @@ nfp_flower_bond_remove_node(struct nfp_flower_bond *nfp_bond, entry->offloaded = false; if (entry->to_destroy) { + nfp_flower_bond_group_id_clear(nfp_bond, entry->group_id); LIST_REMOVE(entry, next); rte_free(entry); } @@ -139,6 +173,7 @@ nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) pthread_mutex_lock(&nfp_bond->mutex); LIST_FOREACH(entry, &nfp_bond->group_list, next) { + nfp_flower_bond_group_id_clear(nfp_bond, entry->group_id); LIST_REMOVE(entry, next); rte_free(entry); } @@ -271,16 +306,162 @@ nfp_flower_bond_change_linkstatus_event(struct nfp_flower_bond *nfp_bond, *bond_port_flags |= NFP_FL_BOND_PORT_CHANGED; } +static struct nfp_bond_group * +nfp_flower_bond_group_create(struct nfp_flower_bond *nfp_bond, + struct rte_eth_dev *bond_dev) +{ + uint32_t id; + unsigned int numa_node; + struct nfp_bond_group *group = NULL; + + if (nfp_flower_bond_group_id_get(nfp_bond, &id) < 0) + return NULL; + + numa_node = rte_socket_id(); + + group = rte_zmalloc_socket(NULL, sizeof(struct nfp_bond_group), + RTE_CACHE_LINE_SIZE, numa_node); + if (group == NULL) { + PMD_DRV_LOG(ERR, "Unable malloc memory for nfp bond group"); + nfp_flower_bond_group_id_clear(nfp_bond, id); + return NULL; + } + + group->group_id = id; + group->main_dev = bond_dev; + group->dirty = true; + group->offloaded = false; + group->to_remove = false; + group->to_destroy = false; + group->member_cnt = 0; + group->group_inst = ++nfp_bond->global_inst; + LIST_INSERT_HEAD(&nfp_bond->group_list, group, next); + + return group; +} + +static int +nfp_flower_bond_changeupper_event(struct nfp_flower_bond *nfp_bond, + struct rte_eth_dev *bond_dev) +{ + uint32_t i; + uint16_t port_id; + bool can_offload = true; + uint16_t nfp_member_count; + struct rte_eth_dev *eth_dev; + struct nfp_bond_group *group; + struct bond_dev_private *internals; + struct nfp_flower_representor *repr; + struct nfp_app_fw_flower *app_flower; + + internals = bond_dev->data->dev_private; + app_flower = nfp_bond->app_fw_flower; + nfp_member_count = 0; + + for (i = 0; i < internals->member_count; i++) { + port_id = internals->members[i].port_id; + eth_dev = &rte_eth_devices[port_id]; + if (!nfp_flower_is_phy_repr(eth_dev)) { + can_offload = false; + break; + } + + repr = eth_dev->data->dev_private; + + if (repr->app_fw_flower !
[PATCH v6 12/14] net/nfp: handle bond packets from firmware
From: Long Wu Firmware sends bond firmware creation packets to driver, driver needs to handle it in ctrl VNIC service. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 53 drivers/net/nfp/flower/nfp_flower_bond.h | 14 +++ drivers/net/nfp/flower/nfp_flower_ctrl.c | 106 +-- 3 files changed, 168 insertions(+), 5 deletions(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index 523e0025ad..73b616360a 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -161,6 +161,8 @@ nfp_flower_bond_init(struct nfp_app_fw_flower *app_fw_flower) LIST_INIT(&nfp_bond->group_list); nfp_flower_bond_increment_version(nfp_bond); nfp_bond->app_fw_flower = app_fw_flower; + nfp_bond->retrans.head = 0; + nfp_bond->retrans.rear = 0; return 0; } @@ -168,6 +170,7 @@ nfp_flower_bond_init(struct nfp_app_fw_flower *app_fw_flower) void nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) { + struct rte_mbuf *mbuf_tmp; struct nfp_bond_group *entry; struct nfp_flower_bond *nfp_bond = app_fw_flower->nfp_bond; @@ -177,6 +180,12 @@ nfp_flower_bond_cleanup(struct nfp_app_fw_flower *app_fw_flower) LIST_REMOVE(entry, next); rte_free(entry); } + + mbuf_tmp = nfp_fl_bond_get_unprocessed(nfp_bond); + for (; mbuf_tmp != NULL; + mbuf_tmp = nfp_fl_bond_get_unprocessed(nfp_bond)) + rte_pktmbuf_free(mbuf_tmp); + pthread_mutex_unlock(&nfp_bond->mutex); pthread_mutex_destroy(&nfp_bond->mutex); @@ -587,3 +596,47 @@ nfp_flower_bond_all_member_are_phyrepr(struct rte_eth_dev *bond_dev) return true; } + +int +nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, + struct rte_mbuf *mbuf) +{ + uint16_t rear_real; + struct nfp_flower_bond_retrans *retrans; + struct nfp_flower_cmsg_bond_config *cmsg_payload; + + cmsg_payload = rte_pktmbuf_mtod_offset(mbuf, + struct nfp_flower_cmsg_bond_config *, + NFP_FLOWER_CMSG_HLEN); + + if (rte_be_to_cpu_32(cmsg_payload->group_id) >= NFP_FL_BOND_GROUP_MAX) + return -EINVAL; + + retrans = &nfp_bond->retrans; + rear_real = (retrans->rear + 1) % NFP_FL_BOND_RETRANS_LIMIT; + if (rear_real == retrans->head) + return -ENOSPC; + + retrans->mbufs[retrans->rear] = mbuf; + + retrans->rear = rear_real; + + return 0; +} + +struct rte_mbuf * +nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond) +{ + struct rte_mbuf *mbuf; + struct nfp_flower_bond_retrans *retrans; + + retrans = &nfp_bond->retrans; + if (retrans->rear == retrans->head) + return NULL; + + mbuf = retrans->mbufs[retrans->head]; + + retrans->head = (retrans->head + 1) % NFP_FL_BOND_RETRANS_LIMIT; + + return mbuf; +} diff --git a/drivers/net/nfp/flower/nfp_flower_bond.h b/drivers/net/nfp/flower/nfp_flower_bond.h index 12e61ff1ce..e88d72899f 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.h +++ b/drivers/net/nfp/flower/nfp_flower_bond.h @@ -41,6 +41,9 @@ #define NFP_FL_BOND_PORT_TX_ENABLEDRTE_BIT32(1) #define NFP_FL_BOND_PORT_CHANGED RTE_BIT32(2) +/** We store 100(101-1) mbufs but queue needs 101 */ +#define NFP_FL_BOND_RETRANS_LIMIT 101 + enum nfp_flower_bond_batch { NFP_FLOWER_BOND_BATCH_FIRST, NFP_FLOWER_BOND_BATCH_MEMBER, @@ -53,6 +56,12 @@ enum nfp_flower_bond_event { NFP_FLOWER_UNREGISTER }; +struct nfp_flower_bond_retrans { + struct rte_mbuf *mbufs[NFP_FL_BOND_RETRANS_LIMIT]; + uint16_t head; + uint16_t rear; +}; + /* Control message payload for bond config */ struct nfp_flower_cmsg_bond_config { /** Configuration flags */ @@ -113,6 +122,8 @@ struct nfp_flower_bond { bool group_id_map[NFP_FL_BOND_GROUP_MAX]; /** Pointer to the flower app */ struct nfp_app_fw_flower *app_fw_flower; + /** Store bond offload packets from firmware */ + struct nfp_flower_bond_retrans retrans; }; struct nfp_flower_bond_cmsg_args { @@ -139,5 +150,8 @@ int nfp_flower_bond_event_handle(struct nfp_flower_bond *nfp_bond, enum nfp_flower_bond_event event); void nfp_flower_bond_do_work(struct nfp_flower_bond *nfp_bond); bool nfp_flower_bond_all_member_are_phyrepr(struct rte_eth_dev *bond_dev); +struct rte_mbuf *nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond); +int nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, + struct rte_mbuf *mbuf); #endif /* __NFP_FLOWER_BOND_H__ */ diff --git a/drivers/net/nfp/flower/nfp_flower_ctrl.c b/drivers/net/nfp/flower/nfp_flower_ctrl.c index c25487c277..75c8c
[PATCH v6 13/14] net/nfp: support getting bond firmware creation
From: Long Wu Support getting the status that whether the bonding port is created by the nfp firmware. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 27 +++ drivers/net/nfp/flower/nfp_flower_bond.h | 2 ++ .../net/nfp/flower/nfp_flower_representor.c | 1 + 3 files changed, 30 insertions(+) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index 73b616360a..c809465ffc 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -640,3 +640,30 @@ nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond) return mbuf; } + +int +nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, + struct rte_eth_dev *nfp_dev) +{ + int ret = -EINVAL; + struct nfp_bond_group *group; + struct nfp_flower_bond *nfp_bond; + struct nfp_flower_representor *repr; + + if (!nfp_flower_bond_is_member_port(bond_dev, nfp_dev)) + return ret; + + repr = nfp_dev->data->dev_private; + nfp_bond = repr->app_fw_flower->nfp_bond; + + pthread_mutex_lock(&nfp_bond->mutex); + LIST_FOREACH(group, &nfp_bond->group_list, next) { + if (group->main_dev == bond_dev && group->offloaded == true) { + ret = 0; + break; + } + } + pthread_mutex_unlock(&nfp_bond->mutex); + + return ret; +} diff --git a/drivers/net/nfp/flower/nfp_flower_bond.h b/drivers/net/nfp/flower/nfp_flower_bond.h index e88d72899f..41cd64d9eb 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.h +++ b/drivers/net/nfp/flower/nfp_flower_bond.h @@ -153,5 +153,7 @@ bool nfp_flower_bond_all_member_are_phyrepr(struct rte_eth_dev *bond_dev); struct rte_mbuf *nfp_fl_bond_get_unprocessed(struct nfp_flower_bond *nfp_bond); int nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, struct rte_mbuf *mbuf); +int nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, + struct rte_eth_dev *nfp_dev); #endif /* __NFP_FLOWER_BOND_H__ */ diff --git a/drivers/net/nfp/flower/nfp_flower_representor.c b/drivers/net/nfp/flower/nfp_flower_representor.c index 43106da90e..8a1b2eff66 100644 --- a/drivers/net/nfp/flower/nfp_flower_representor.c +++ b/drivers/net/nfp/flower/nfp_flower_representor.c @@ -458,6 +458,7 @@ static const struct eth_dev_ops nfp_flower_repr_dev_ops = { .mtr_ops_get = nfp_net_mtr_ops_get, .bond_notify_member = nfp_flower_repr_bond_notify_member, + .bond_fw_create_get = nfp_flower_bond_fw_create_get, }; static uint32_t -- 2.39.1
[PATCH v6 14/14] net/nfp: support offloading bond-flow
From: Long Wu After bonding port notification and firmware created the bonding port, NFP rte_flow rule adds support for destination port to bonding port. Signed-off-by: Long Wu Reviewed-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/flower/nfp_flower_bond.c | 22 +++ drivers/net/nfp/flower/nfp_flower_bond.h | 6 + drivers/net/nfp/flower/nfp_flower_cmsg.h | 9 + drivers/net/nfp/flower/nfp_flower_flow.c | 232 +-- 4 files changed, 252 insertions(+), 17 deletions(-) diff --git a/drivers/net/nfp/flower/nfp_flower_bond.c b/drivers/net/nfp/flower/nfp_flower_bond.c index c809465ffc..6e4d60659a 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.c +++ b/drivers/net/nfp/flower/nfp_flower_bond.c @@ -667,3 +667,25 @@ nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, return ret; } + +int +nfp_flower_bond_get_output_id(struct nfp_flower_bond *nfp_bond, + const struct rte_eth_dev *bond_dev, + uint32_t *group_id) +{ + struct nfp_bond_group *group; + + pthread_mutex_lock(&nfp_bond->mutex); + + group = nfp_flower_bond_find_group(nfp_bond, bond_dev); + if (group == NULL) { + pthread_mutex_unlock(&nfp_bond->mutex); + return -ENOENT; + } + + *group_id = group->group_id; + + pthread_mutex_unlock(&nfp_bond->mutex); + + return 0; +} diff --git a/drivers/net/nfp/flower/nfp_flower_bond.h b/drivers/net/nfp/flower/nfp_flower_bond.h index 41cd64d9eb..7e451c58f1 100644 --- a/drivers/net/nfp/flower/nfp_flower_bond.h +++ b/drivers/net/nfp/flower/nfp_flower_bond.h @@ -44,6 +44,9 @@ /** We store 100(101-1) mbufs but queue needs 101 */ #define NFP_FL_BOND_RETRANS_LIMIT 101 +/* Flow output action of bonding port */ +#define NFP_FL_BOND_OUT0xC0DE + enum nfp_flower_bond_batch { NFP_FLOWER_BOND_BATCH_FIRST, NFP_FLOWER_BOND_BATCH_MEMBER, @@ -155,5 +158,8 @@ int nfp_fl_bond_put_unprocessed(struct nfp_flower_bond *nfp_bond, struct rte_mbuf *mbuf); int nfp_flower_bond_fw_create_get(struct rte_eth_dev *bond_dev, struct rte_eth_dev *nfp_dev); +int nfp_flower_bond_get_output_id(struct nfp_flower_bond *nfp_bond, + const struct rte_eth_dev *bond_dev, + uint32_t *group_id); #endif /* __NFP_FLOWER_BOND_H__ */ diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h index 60ab58a3b1..17ef943855 100644 --- a/drivers/net/nfp/flower/nfp_flower_cmsg.h +++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h @@ -712,6 +712,15 @@ struct nfp_fl_act_head { uint8_t len_lw; }; +#define NFP_FL_PRE_BOND_VER_OFF 8 + +struct nfp_fl_pre_bond { + struct nfp_fl_act_head head; + rte_be16_t group_id; + uint8_t lag_version[3]; + uint8_t instance; +}; + struct nfp_fl_act_output { struct nfp_fl_act_head head; rte_be16_t flags; diff --git a/drivers/net/nfp/flower/nfp_flower_flow.c b/drivers/net/nfp/flower/nfp_flower_flow.c index e26be30d18..6e21ad8c26 100644 --- a/drivers/net/nfp/flower/nfp_flower_flow.c +++ b/drivers/net/nfp/flower/nfp_flower_flow.c @@ -5,12 +5,14 @@ #include "nfp_flower_flow.h" +#include #include #include #include #include #include "flower/nfp_conntrack.h" +#include "flower/nfp_flower_bond.h" #include "flower/nfp_flower_representor.h" #include "nfpcore/nfp_rtsym.h" #include "nfp_logs.h" @@ -969,9 +971,23 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[], return 0; } +static bool +nfp_flow_check_bond_action(struct nfp_flower_representor *representor, + uint32_t port_id) +{ + struct rte_eth_dev *bond_dev = &rte_eth_devices[port_id]; + + if (nfp_flower_support_bond_offload(representor->app_fw_flower) || + !nfp_flower_bond_all_member_are_phyrepr(bond_dev)) + return false; + + return true; +} + static int nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], - struct nfp_fl_key_ls *key_ls) + struct nfp_fl_key_ls *key_ls, + struct nfp_flower_representor *representor) { int ret = 0; bool meter_flag = false; @@ -981,6 +997,8 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], bool mac_set_flag = false; bool ttl_tos_flag = false; const struct rte_flow_action *action; + const struct rte_flow_action_port_id *port_id; + const struct rte_flow_action_ethdev *action_ethdev; for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) { /* Make sure actions length no longer than NFP_FL_MAX_A_SIZ */ @@ -1006,10 +1024,36 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[], case RTE_FLOW_ACTION_TYPE_PORT_ID: PMD_DRV_LOG(DEBUG, "RTE_FLOW_AC
DTS testpmd and SCAPY integration
Hello, Consider an option to describe DTS test with testpmd and SCAPY plain text commands. For example: Scenario: - Configure UDP packet in SCAPY and a flow in testpmd. - Send UDP packet and validate testpmd output triggered by that packet. ```yaml phase_0: name: CONFIGURATION tg: | udp_pkt = Ether()/IP()/UDP(sport=31)/Raw('== TEST ==') print('packet is ready') dut: | start set verbose 1 flow create 0 ingress pattern eth / ipv4 / udp src is 31 / end actions queue index 1 / end result: dut: 'Flow rule #0 created' tg: 'packet is ready' phase_1: name: SEND and VALIDATE tg: sendp(udp_pkt, iface=pf0) result: dut: '- RSS queue=0x1 -' ``` Test described as a sequence of phases. Phase definition: ``` : # unique phase ID name:# phase name : # application APP1 commands ... : # application APPy commands ... : # application APPx commands result:# optional phase results verification section : # APPx expected output ... : # APPy expected output ``` - Application commands in a phase executed sequentially, in order of application IDs: commands executed before commands. - Application results in a phase validated sequentially, in order of application IDs: result validated before APPy result. - Application result is a regular expression. Test application definition: ~~~ ``` : # unique application ID agent:# mandatory application type identifier: {testpmd|scapy} cmd: # optional application command template ``` Example: ```yaml dut: agent: testpmd cmd: 'dpdk-testpmd -a pci0 -- -i --rxq=4 --txq=4' tg: agent: scapy ``` Test commands do not bound to a specific setup. Therefore, testpmd commad line and SCAPY sendp() function use encoding to describe relative interface position in a tested HBA. PCI encoding scheme for testpmd: - PF PCI: `pciX` Example: `pci0: ':08:00.0'` - PCI SR-IOV: `pciXvfY` Example: `pci0vf0: ':08:00.2'` Network devices encoding scheme for SCAPY: - PF: `pfX` Example: `pf0: enp8s0f0np0` - PCI SR-IOV: `pfXvfY` Example: `pf0vf0: enp5s0f0v0` - Network device representor: `pfXrfY` Example: `pf0rf0: enp5s0f0npf0vf0` Test execution requires an additional file to describe tested setup. Setup file format: ~ ``` : # unique application ID host: # hostname or IPvX address path: # optional application path hba: # optional HBA description pmd: # PMD hw: # HW type ``` Example: ```yaml dut: host: 1.2.3.4 path: /opt/dpdk.org/build/app hba: pmd: mlx5 hw: mt4125 tg: host: ::1234 ``` ```yaml dut: agent: testpmd cmd: 'dpdk-testpmd -a pci0 -- -i --rxq=4 --txq=4' tg: agent: scapy test: - phases: [ *ref_phase0 ] repeat: 1 - phases: [ *ref_phase1 ] repeat: 3 phase_0: &ref_phase0 name: CONFIGURATION tg: | udp_pkt = Ether()/IP()/UDP(sport=31)/Raw('== TEST ==') print('packet is ready') dut: | start set verbose 1 flow create 0 ingress pattern eth / ipv4 / udp src is 31 / end actions queue index 1 / end result: dut: 'Flow rule #0 created' tg: 'packet is ready' phase_1: &ref_phase1 name: SEND and VALIDATE tg: sendp(udp_pkt, iface=pf0) result: dut: '- RSS queue=0x1 -' ``` The plain text format provides minimalistic and intuitive framework for DTS tests. DTS can use plan text testpmd/scapy command format in addition to Python framework. Regards, Gregory