* Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
* ubs-hcom is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "ubsocket_data_tx.h"
#include "ubsocket_socket.h"
namespace ock {
namespace ubs {
DataTx::DataTx(const SocketPtr &sock, DataTxOps *ops) : fd_(sock->raw_socket_), event_fd_(sock->event_fd_), tx_ops_(ops)
{
}
ssize_t DataTx::WriteV(const SocketPtr &sock, const struct iovec *iov, int iovcnt)
{
PROF_START(CORE_WRITE);
if (sock->State() == SOCK_STAT_RAW_ESTABLISHED) {
ssize_t size = LibcApi::writev(fd_, iov, iovcnt);
return size;
}
if (iov == nullptr || iovcnt == 0) {
errno = EINVAL;
UBS_VLOG_ERR("WriteV invalid argument, fd: %d, ret: %d, errno: %d, errmsg: %s\n", fd_, -1, errno,
Func::Error2Str(errno));
PROF_END(CORE_WRITE, false);
return UBS_ERROR;
}
if (sock->State() == SOCK_STAT_CLOSE) {
errno = EPIPE;
UBS_VLOG_ERR("WriteV socket is closed, fd: %d, ret: %d, errno: %d, errmsg: %s\n", fd_, -1, errno,
Func::Error2Str(errno));
PROF_END(CORE_WRITE, false);
return UBS_ERROR;
}
if (tx_ops_->PollTx(sock) < 0) {
PROF_END(CORE_WRITE, false);
return UBS_ERROR;
}
ConverterPtr converterPtr = tx_ops_->BuildIovConverter(iov, iovcnt);
uint32_t input_total_len = 0;
uint32_t batch = 0;
uint32_t post_batch_max = tx_ops_->tx_queue_avail_num_ > TX_POST_BATCH_MAX ? TX_POST_BATCH_MAX :
tx_ops_->tx_queue_avail_num_;
uint32_t buf_cnt = 0;
uint32_t cut_total_len = 0;
do {
cut_total_len = 0;
uint32_t cut_len = 0;
uint32_t wr_left_len = tx_ops_->IOBufSize();
uint32_t sge_idx = 0;
while (sge_idx++ < TX_SGE_MAX && cut_total_len < tx_ops_->IOBufSize() &&
((cut_len = converterPtr->IndexMove(wr_left_len)) != 0)) {
++buf_cnt;
wr_left_len -= cut_len;
cut_total_len += cut_len;
}
input_total_len += cut_total_len;
} while (cut_total_len != 0 && ++batch < post_batch_max);
uintptr_t txBuf = tx_ops_->AllocTxBuf(0, buf_cnt);
uint32_t tx_total_len;
int64_t ret = tx_ops_->PostSend(sock, txBuf, batch, converterPtr);
if (ret < 0) {
PROF_END(CORE_WRITE, false);
return ret;
}
tx_total_len = ret;
if (GlobalSetting::UBS_TRACE_ENABLED) {
SocketBasePtr sockptr = RefConvert<Socket, SocketBase>(sock);
sockptr->GetStatsMgr()->UpdateTraceStats(Statistics::StatsMgr::TX_BYTE_COUNT, tx_total_len);
}
PROF_END(CORE_WRITE, true);
return tx_total_len;
}
}
}