/** * Copyright (C) Mellanox Technologies Ltd. 2001-2017. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #ifndef UCT_RC_TEST_H_ #define UCT_RC_TEST_H_ #include #include extern "C" { #include #include #include } class test_rc : public uct_test { public: typedef struct pending_send_request { uct_pending_req_t uct; int cb_count; int purge_count; uct_ep_h ep; } pending_send_request_t; virtual void init(); virtual void connect(); uct_rc_iface_t* rc_iface(entity *e) { return ucs_derived_of(e->iface(), uct_rc_iface_t); } uct_rc_ep_t* rc_ep(entity *e, int ep_idx = 0) { return ucs_derived_of(e->ep(ep_idx), uct_rc_ep_t); } void send_am_messages(entity *e, int wnd, ucs_status_t expected, uint8_t am_id = 0, int ep_idx = 0) { for (int i = 0; i < wnd; i++) { EXPECT_EQ(expected, send_am_message(e, am_id, ep_idx)); } } void progress_loop(double delta_ms=10.0) { uct_test::short_progress_loop(delta_ms); } void test_iface_ops(int cq_len); static ucs_status_t am_dummy_handler(void *arg, void *data, size_t length, unsigned flags) { return UCS_OK; } protected: entity *m_e1, *m_e2; }; class test_rc_flow_control : public test_rc { public: typedef struct pending_send_request { uct_pending_req_t uct; int cb_count; int purge_count; } pending_send_request_t; void init(); void cleanup(); virtual uct_rc_fc_t* get_fc_ptr(entity *e, int ep_idx = 0) { return &rc_ep(e, ep_idx)->fc; } virtual void disable_entity(entity *e) { rc_iface(e)->tx.cq_available = 0; } virtual void enable_entity(entity *e, unsigned cq_num = 128) { rc_iface(e)->tx.cq_available = cq_num; } virtual void set_tx_moderation(entity *e, int val) { rc_iface(e)->config.tx_moderation = val; } void set_fc_attributes(entity *e, bool enabled, int wnd, int s_thresh, int h_thresh) { rc_iface(e)->config.fc_enabled = enabled; rc_iface(e)->config.fc_wnd_size = get_fc_ptr(e)->fc_wnd = wnd; rc_iface(e)->config.fc_soft_thresh = s_thresh; rc_iface(e)->config.fc_hard_thresh = h_thresh; } void set_fc_disabled(entity *e) { /* same as default settings in rc_iface_init */ set_fc_attributes(e, false, std::numeric_limits::max(), 0, 0); } void send_am_and_flush(entity *e, int num_msg); void progress_loop(double delta_ms=10.0) { uct_test::short_progress_loop(delta_ms); } static ucs_status_t am_dummy_handler(void *arg, void *data, size_t length, void *desc) { return UCS_OK; } static ucs_status_t am_handler(void *arg, void *data, size_t length, unsigned flags) { ++m_am_rx_count; return UCS_OK; } static void purge_cb(uct_pending_req_t *self, void *arg) { pending_send_request_t *req = ucs_container_of(self, pending_send_request_t, uct); ++req->purge_count; } static ucs_status_t pending_cb(uct_pending_req_t *self) { pending_send_request_t *req = ucs_container_of(self, pending_send_request_t, uct); ++req->cb_count; return UCS_OK; } void validate_grant(entity *e); void test_general(int wnd, int s_thresh, int h_thresh, bool is_fc_enabled); void test_pending_grant(int wnd); void test_pending_purge(int wnd, int num_pend_sends); void test_flush_fc_disabled(); protected: static const uint8_t FLUSH_AM_ID = 1; static uint32_t m_am_rx_count; }; #ifdef ENABLE_STATS class test_rc_flow_control_stats : public test_rc_flow_control { public: void init() { stats_activate(); test_rc_flow_control::init(); } void cleanup() { test_rc_flow_control::cleanup(); stats_restore(); } void test_general(int wnd, int s_thresh, int h_thresh); }; #endif class test_rc_iface_attrs : public test_uct_iface_attrs { public: test_rc_iface_attrs() { ucs_status_t status = uct_config_modify(m_iface_config, "RC_TM_ENABLE", "y"); EXPECT_TRUE((status == UCS_OK) || (status == UCS_ERR_NO_ELEM)); } attr_map_t get_num_iov_mlx5_common(size_t av_size); attr_map_t get_num_iov(); }; #endif