LCOV - code coverage report
Current view: top level - ksync - ksync_sock_uds.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 158 0.0 %
Date: 2026-11-09 02:10:49 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "ksync_sock.h"
       7             : 
       8             : #include <boost/asio.hpp>
       9             : #include <boost/bind/bind.hpp>
      10             : #include <errno.h>
      11             : 
      12             : class AgentParam;
      13             : 
      14             : using namespace boost::asio;
      15             : using namespace boost::placeholders;
      16             : 
      17             : /////////////////////////////////////////////////////////////////////////////
      18             : // KSyncSockUds routines
      19             : /////////////////////////////////////////////////////////////////////////////
      20             : //Unix domain socket class for interacting with dpdk vrouter
      21             : 
      22             : class KSyncSockUdsReadTask : public Task {
      23             : public:
      24           0 :     KSyncSockUdsReadTask(TaskScheduler *scheduler, KSyncSockUds *queue) :
      25           0 :         Task(scheduler->GetTaskId("Ksync::KSyncSockUdsRead"), 0), queue_(queue) {
      26           0 :     }
      27           0 :     ~KSyncSockUdsReadTask() {
      28           0 :     }
      29             : 
      30           0 :     bool Run() {
      31           0 :         queue_->Run();
      32           0 :         return true;
      33             :     }
      34           0 :     std::string Description() const { return "KSyncSockUdsRead"; }
      35             : private:
      36             :     KSyncSockUds *queue_;
      37             : 
      38             : };
      39             : 
      40             : 
      41             : 
      42             : string KSyncSockUds::sockpath_= KSYNC_AGENT_VROUTER_SOCK_PATH;
      43             : 
      44           0 : KSyncSockUds::KSyncSockUds(boost::asio::io_context &ios) :
      45           0 :     sock_(ios),
      46           0 :     server_ep_(sockpath_),
      47           0 :     rx_buff_(NULL),
      48           0 :     rx_buff_q_(NULL),
      49           0 :     remain_(0),
      50           0 :     socket_(0),
      51           0 :     connected_(false) {
      52           0 :     boost::system::error_code ec;
      53           0 :     reset_use_wait_tree();
      54           0 :     set_process_data_inline();
      55           0 : retry:;
      56           0 :     sock_.connect(server_ep_, ec);
      57           0 :     if (ec) {
      58           0 :         sleep(1);
      59           0 :         goto retry;
      60             :     }
      61           0 :     socket_ = sock_.native_handle();
      62           0 :     connected_ = true;
      63           0 :     rx_buff_   = new char[10*kBufLen];
      64           0 :     rx_buff_q_ = new char[10*kBufLen];
      65           0 : }
      66             : 
      67           0 : bool KSyncSockUds::Run() {
      68           0 :     AgentSandeshContext *ctxt = KSyncSock::GetAgentSandeshContext(0);
      69           0 :     char *ret_buff = new char[1024*kBufLen];
      70           0 :     boost::system::error_code ec;
      71             : 
      72             :     // Read data from the socket and append it to the existing
      73             :     // unprocessed data in the local buffer.
      74             :     while (1) {
      75           0 :         char *bufp = rx_buff_;
      76           0 :         struct nlmsghdr *nlh = NULL;
      77             :         struct nlmsghdr tnlh;
      78           0 :         size_t offset = 0;
      79             :         int ret_val;
      80           0 :         size_t bytes_transferred = 0;
      81           0 :         bytes_transferred = ret_val = recv(socket_, rx_buff_, 10*kBufLen, 0);
      82           0 :         if (ret_val == 0) {
      83             :             // connection reset by peer
      84             :             // close socket and exit
      85           0 :             sock_.close(ec);
      86           0 :             LOG(INFO, " dpdk vrouter is down, exiting.. errno:" << errno);
      87           0 :             exit(0);
      88             :         }
      89           0 :         if (ret_val < 0) {
      90           0 :             if (errno != EAGAIN) {
      91           0 :                 sock_.close(ec);
      92           0 :                 connected_ = false;
      93           0 : retry:;
      94           0 :                 sock_.connect(server_ep_, ec);
      95           0 :                 if (ec) {
      96           0 :                     sleep(1);
      97           0 :                     goto retry;
      98             :                 }
      99           0 :                 socket_ = sock_.native_handle();
     100           0 :                 connected_ = true;
     101             :             }
     102           0 :             continue;
     103             :         }
     104             : 
     105           0 :         if (remain_ != 0) {
     106           0 :             if (remain_ < sizeof(struct nlmsghdr)) {
     107           0 :                 memcpy((char *)&tnlh, rx_buff_q_, remain_);
     108           0 :                 memcpy(((char *)&tnlh) + remain_, rx_buff_,
     109           0 :                         (sizeof(struct nlmsghdr) - remain_));
     110           0 :                 nlh =  &tnlh;
     111             :             } else {
     112           0 :                 nlh =  (struct nlmsghdr *)rx_buff_q_;
     113             :             }
     114           0 :             if (remain_ > nlh->nlmsg_len)
     115           0 :                 assert(0);
     116           0 :             memcpy(ret_buff, rx_buff_q_, remain_);
     117           0 :             memcpy(ret_buff+remain_, rx_buff_, nlh->nlmsg_len - remain_);
     118           0 :             bufp += (nlh->nlmsg_len - remain_);
     119           0 :             ctxt->SetErrno(0);
     120           0 :             ProcessDataInline(ret_buff);
     121           0 :             offset = nlh->nlmsg_len - remain_;
     122             :         }
     123           0 :         while (offset < bytes_transferred) {
     124           0 :             if ((bytes_transferred - offset) >= (sizeof(struct nlmsghdr))) {
     125           0 :                 nlh =  (struct nlmsghdr *)(rx_buff_ + offset);
     126           0 :                 if ((bytes_transferred - offset) >= nlh->nlmsg_len) {
     127           0 :                     memcpy(ret_buff, rx_buff_ + offset, nlh->nlmsg_len);
     128           0 :                     ctxt->SetErrno(0);
     129           0 :                     ProcessDataInline(ret_buff);
     130           0 :                     offset += nlh->nlmsg_len;
     131             :                 } else {
     132           0 :                     break;
     133             :                 }
     134             :             } else {
     135           0 :                 break;
     136             :             }
     137             :         }
     138           0 :         memcpy(rx_buff_q_, rx_buff_ + offset, bytes_transferred - offset);
     139           0 :         remain_ = bytes_transferred - offset;
     140           0 :     }
     141             :     return true;
     142             : }
     143             : 
     144           0 : void KSyncSockUds::Init(io_service &ios, const std::string &cpu_pin_policy,
     145             :     const std::string &sockpathvr) {
     146           0 :     sockpath_ = sockpathvr;
     147           0 :     KSyncSock::SetSockTableEntry(new KSyncSockUds(ios));
     148           0 :     SetNetlinkFamilyId(10);
     149           0 :     KSyncSock::Init(false, cpu_pin_policy);
     150           0 : }
     151             : 
     152           0 : uint32_t KSyncSockUds::GetSeqno(char *data) {
     153           0 :     return GetNetlinkSeqno(data);
     154             : }
     155             : 
     156           0 : bool KSyncSockUds::IsMoreData(char *data) {
     157           0 :     return NetlinkMsgDone(data);
     158             : }
     159             : 
     160           0 : bool KSyncSockUds::Decoder(char *data, AgentSandeshContext *context) {
     161           0 :     KSyncSockNetlink::NetlinkDecoder(data, context);
     162           0 :     return true;
     163             : }
     164             : 
     165           0 : bool KSyncSockUds::BulkDecoder(char *data,
     166             :                                KSyncBulkSandeshContext *bulk_sandesh_context) {
     167             :     // Get sandesh buffer and buffer-length
     168           0 :     uint32_t buf_len = 0;
     169           0 :     char *buf = NULL;
     170           0 :     GetNetlinkPayload(data, &buf, &buf_len);
     171           0 :     return bulk_sandesh_context->Decoder(buf, buf_len, NLA_ALIGNTO, IsMoreData(data));
     172             : }
     173             : 
     174           0 : void KSyncSockUds::AsyncSendTo(KSyncBufferList *iovec, uint32_t seq_no,
     175             :                                HandlerCb cb) {
     176           0 :     if (connected_ == true)
     177           0 :         SendTo(iovec, seq_no);
     178           0 : }
     179             : 
     180           0 : size_t KSyncSockUds::SendTo(KSyncBufferList *iovec, uint32_t seq_no) {
     181           0 :     size_t len = 0, ret;
     182             :     struct msghdr msg;
     183           0 :     struct iovec iov[max_bulk_msg_count_*2];
     184             :     int i;
     185             : 
     186           0 :     memset(&msg, 0, sizeof(msg));
     187           0 :     msg.msg_iov = iov;
     188             : 
     189           0 :     ResetNetlink(nl_client_);
     190           0 :     int offset = nl_client_->cl_buf_offset;
     191           0 :     UpdateNetlink(nl_client_, bulk_buf_size_, seq_no);
     192             : 
     193           0 :     KSyncBufferList::iterator it = iovec->begin();
     194           0 :     iovec->insert(it, buffer((char *)nl_client_->cl_buf, offset));
     195             : 
     196           0 :     int count = iovec->size();
     197           0 :     for(i = 0; i < count; i++) {
     198           0 :         mutable_buffers_1 buf = iovec->at(i);
     199           0 :         size_t buf_size = boost::asio::buffer_size(buf);
     200           0 :         void* cbuf = boost::asio::buffer_cast<void*>(buf);
     201           0 :         len += buf_size;
     202           0 :         iov[i].iov_base = cbuf;
     203           0 :         iov[i].iov_len = buf_size;
     204             :     }
     205             : 
     206           0 :     msg.msg_iovlen = i;
     207           0 :     ret = sendmsg(socket_, &msg, 0);
     208           0 :     if (ret != len) {
     209           0 :         LOG(ERROR, "sendmsg failure " << ret << "len " << len);
     210             :     }
     211           0 :     return len;
     212           0 : }
     213             : 
     214           0 : bool KSyncSockUds::Validate(char *data) {
     215           0 :     return true;
     216             : }
     217             : 
     218           0 : void KSyncSockUds::AsyncReceive(mutable_buffers_1 buf, HandlerCb cb) {
     219             :     static int started = 0;
     220           0 :     if (!started) {
     221           0 :         TaskScheduler *scheduler = TaskScheduler::GetInstance();
     222             :         //Receive is handled in a separate Run() thread
     223           0 :         KSyncSockUdsReadTask *task = new KSyncSockUdsReadTask(scheduler, this);
     224           0 :         scheduler->Enqueue(task);
     225           0 :         started = 1;
     226             :     }
     227           0 : }
     228             : 
     229           0 : void KSyncSockUds::Receive(mutable_buffers_1 buf) {
     230           0 :     boost::system::error_code ec;
     231           0 :     uint32_t bytes_read = 0;
     232           0 :     const struct nlmsghdr *nlh = NULL;
     233             : 
     234           0 :     char *netlink_header(buffer_cast<char *>(buf));
     235             : 
     236           0 :     while (bytes_read < sizeof(struct nlmsghdr)) {
     237           0 :         char *buffer = netlink_header + bytes_read;
     238           0 :         bytes_read += recv(socket_, buffer, sizeof(struct nlmsghdr) - bytes_read, 0);
     239             :         //Data read is lesser than netlink header
     240             :         //continue reading
     241           0 :         if (bytes_read == sizeof(struct nlmsghdr)) {
     242           0 :             nlh =  buffer_cast<struct nlmsghdr *>(buf);
     243             :         }
     244             :     }
     245             : 
     246           0 :     if (nlh->nlmsg_type == NLMSG_ERROR) {
     247           0 :         LOG(ERROR, "Netlink error for seqno " << nlh->nlmsg_seq
     248             :                 << " len " << nlh->nlmsg_len);
     249           0 :         assert(0);
     250             :     }
     251             : 
     252           0 :     bytes_read = 0;
     253           0 :     uint32_t payload_size = nlh->nlmsg_len - sizeof(struct nlmsghdr);
     254           0 :     char *data(buffer_cast<char *>(buf + sizeof(struct nlmsghdr)));
     255             : 
     256           0 :     while (bytes_read < payload_size) {
     257           0 :         char *buffer = data + bytes_read;
     258           0 :         bytes_read += recv(socket_, buffer, payload_size - bytes_read, 0);
     259             :     }
     260           0 : }

Generated by: LCOV version 1.14