LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dpdk - vr_dpdk_usocket.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 349 644 54.2 %
Date: 2026-11-09 02:10:49 Functions: 23 32 71.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_dpdk_usocket.c -- library to deal with packet0 and netlink tcp/unix
       3             :  * sockets
       4             :  *
       5             :  * Copyright(c) 2014, Juniper Networks Inc.
       6             :  * Copyright Contributors to the OpenSDN project
       7             :  * All rights reserved
       8             :  */
       9             : 
      10             : #include <fcntl.h>
      11             : #include <poll.h>
      12             : #include <linux/netlink.h>
      13             : #include <sys/eventfd.h>
      14             : #include <sys/stat.h>
      15             : #include <sys/un.h>
      16             : #include <stdint.h>
      17             : #include <netinet/tcp.h>
      18             : 
      19             : #include "nl_util.h"
      20             : #include "vr_dpdk.h"
      21             : #include "vr_dpdk_usocket.h"
      22             : #include "vr_message.h"
      23             : 
      24             : #include <rte_byteorder.h>
      25             : #include <rte_errno.h>
      26             : #include <rte_hexdump.h>
      27             : #include <rte_timer.h>
      28             : 
      29             : #define INFINITE_TIMEOUT    -1
      30             : 
      31             : extern void dpdk_burst_rx(unsigned int, struct rte_mbuf *[],
      32             :                 struct vr_interface *, const char *, unsigned int);
      33             : extern struct nlmsghdr *dpdk_nl_message_hdr(struct vr_message *);
      34             : extern unsigned int dpdk_nl_message_len(struct vr_message *);
      35             : 
      36             : static int vr_usocket_accept(struct vr_usocket *);
      37             : static int vr_usocket_connect(struct vr_usocket *);
      38             : static int vr_usocket_bind(struct vr_usocket *);
      39             : static int usock_write(struct vr_usocket *);
      40             : static int usock_read_init(struct vr_usocket *);
      41             : 
      42             : static char vr_packet_unix_file[VR_UNIX_PATH_MAX];
      43             : char *vr_socket_dir = VR_DEF_SOCKET_DIR;
      44             : uint16_t vr_netlink_port = VR_DEF_NETLINK_PORT;
      45             : 
      46             : /*
      47             :  * mark the error in socket for somebody to process/see
      48             :  */
      49             : static void
      50           0 : usock_set_error(struct vr_usocket *usockp, int error)
      51             : {
      52             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d error %d\n", __func__, pthread_self(),
      53             :             usockp->usock_fd, error);
      54           0 :     usockp->usock_error = error;
      55           0 :     usockp->usock_errno = errno;
      56             : 
      57           0 :     return;
      58             : }
      59             : 
      60             : /*
      61             :  * free the poll descriptor array, if it was allocated
      62             :  */
      63             : static void
      64        3057 : usock_deinit_poll(struct vr_usocket *usockp)
      65             : {
      66        3057 :     if (!usockp)
      67           0 :         return;
      68             : 
      69             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(), usockp->usock_fd);
      70        3057 :     if (usockp->usock_pfds) {
      71          53 :         vr_free(usockp->usock_pfds, VR_USOCK_POLL_OBJECT);
      72          53 :         usockp->usock_pfds = NULL;
      73             :     }
      74             : 
      75        3057 :     return;
      76             : }
      77             : 
      78             : /*
      79             :  * for both netlink and packet protocol sockets, we will need to poll. in case
      80             :  * of netlink, the poll in on tcp sockets to accept a connection (from agent,
      81             :  * utilities etc.:). for packet socket, the poll is on unix socket to receive
      82             :  * packets from agent and to be passed to vrouter. packet sockets also will
      83             :  * have an event usocket to dequeue packets from the packet_mbuf_ring, where
      84             :  * packets to be trapped will be enqueued.
      85             :  *
      86             :  * alloc the poll array
      87             :  */
      88             : static int
      89        3057 : usock_init_poll(struct vr_usocket *usockp)
      90             : {
      91             :     unsigned int i;
      92             :     unsigned int proto;
      93             : 
      94        3057 :     if (!usockp)
      95           0 :         return -EINVAL;
      96             : 
      97             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(), usockp->usock_fd);
      98        3057 :     proto = usockp->usock_proto;
      99        3057 :     if ((proto != NETLINK) && (proto != PACKET)) {
     100           0 :         usock_set_error(usockp, -EINVAL);
     101           0 :         goto error_return;
     102             :     }
     103             : 
     104        3057 :     if (!usockp->usock_max_cfds) {
     105           0 :         usock_set_error(usockp, -EINVAL);
     106           0 :         goto error_return;
     107             :     }
     108             : 
     109        3057 :     if (!usockp->usock_pfds) {
     110         106 :         usockp->usock_pfds = vr_zalloc(sizeof(struct pollfd) *
     111          53 :                 usockp->usock_max_cfds + 1, VR_USOCK_POLL_OBJECT);
     112          53 :         if (!usockp->usock_pfds) {
     113           0 :             usock_set_error(usockp, -ENOMEM);
     114           0 :             goto error_return;
     115             :         }
     116             : 
     117        3445 :         for (i = 1; i <= usockp->usock_max_cfds; i++) {
     118        3392 :             usockp->usock_pfds[i].fd = -1;
     119             :         }
     120             :     }
     121             : 
     122        3057 :     return 0;
     123             : 
     124           0 : error_return:
     125           0 :     return usockp->usock_error;
     126             : }
     127             : 
     128             : /*
     129             :  * bind a child socket to the parent. binding in this context means adding
     130             :  * a child usocket to parent poll list. an example where this will be required
     131             :  * is when one has created an event usocket. An event usocket by itself cannot
     132             :  * do anything useful in the context of dpdk vrouter application. Hence it needs
     133             :  * to be bound to the parent socket that does something useful, in this case
     134             :  * the packet socket. Another example is that of netlink socket. when thexi
     135             :  * netlink socket accepts new connection and the new connected socket has to be
     136             :  * polled, in which case we will need to bind it to the parent socket poll list
     137             :  */
     138             : static int
     139        3004 : usock_bind_usockets(struct vr_usocket *parent, struct vr_usocket *child)
     140             : {
     141             :     unsigned int i;
     142             :     int ret;
     143             :     struct vr_usocket *child_pair;
     144             : 
     145        3004 :     if (parent->usock_state == LIMITED)
     146           0 :         return -ENOSPC;
     147             : 
     148             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: parent FD %d child FD %d\n", __func__,
     149             :             pthread_self(), parent->usock_fd, child->usock_fd);
     150             : 
     151        3004 :     if (child->usock_proto == EVENT) {
     152          53 :         child_pair = vr_usocket(EVENT, RAW);
     153          53 :         if (!child_pair)
     154           0 :             return -ENOMEM;
     155             : 
     156             :         RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: parent FD %d closing child FD %d\n",
     157             :                     __func__, pthread_self(), parent->usock_fd, child->usock_fd);
     158          53 :         close(child->usock_fd);
     159          53 :         child->usock_fd = child_pair->usock_fd;
     160          53 :         child = child_pair;
     161             :     }
     162             : 
     163        3004 :     ret = usock_init_poll(parent);
     164        3004 :     if (ret)
     165           0 :         return ret;
     166             : 
     167        3004 :     if (!parent->usock_children) {
     168          53 :         parent->usock_children = vr_zalloc(sizeof(struct vr_usocket *) *
     169             :                 USOCK_MAX_CHILD_FDS + 1, VR_USOCK_OBJECT);
     170          53 :         if (!parent->usock_children) {
     171           0 :             usock_set_error(parent, -ENOMEM);
     172           0 :             return -ENOMEM;
     173             :         }
     174             :     }
     175             : 
     176        3004 :     child->usock_parent = parent;
     177        3004 :     parent->usock_cfds++;
     178        3004 :     if (parent->usock_cfds >= USOCK_MAX_CHILD_FDS){
     179           0 :         parent->usock_state = LIMITED;
     180           0 :         RTE_LOG(ERR, USOCK, "%s:[%lx] Netlink socket reached max connection %d\n",
     181             :                 __func__, pthread_self(), USOCK_MAX_CHILD_FDS);
     182           0 :         RTE_LOG(ERR, USOCK, "Netlink state: %x\n", parent->usock_state);
     183             :     }
     184             : 
     185        5955 :     for (i = 1; i <= parent->usock_max_cfds; i++) {
     186        5955 :         if (!parent->usock_children[i]) {
     187        3004 :             parent->usock_children[i] = child;
     188        3004 :             parent->usock_pfds[i].fd = child->usock_fd;
     189        3004 :             parent->usock_pfds[i].events = POLLIN;
     190        3004 :             child->usock_child_index = i;
     191        3004 :             break;
     192             :         }
     193             :     }
     194             : 
     195        3004 :     if (child->usock_proto == EVENT)
     196          53 :         child->usock_state = READING_DATA;
     197             : 
     198        3004 :     usock_read_init(child);
     199             : 
     200        3004 :     return 0;
     201             : }
     202             : 
     203             : int
     204          53 : vr_usocket_bind_usockets(void *usock1, void *usock2)
     205             : {
     206          53 :     struct vr_usocket *parent = (struct vr_usocket *)usock1;
     207          53 :     struct vr_usocket *child = (struct vr_usocket *)usock2;
     208             : 
     209             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: usock1 FD %d usock2 FD %d\n", __func__,
     210             :             pthread_self(), parent->usock_fd, child->usock_fd);
     211          53 :     return usock_bind_usockets(parent, child);
     212             : }
     213             : 
     214             : static int
     215        2951 : usock_clone(struct vr_usocket *parent, int cfd)
     216             : {
     217             :     struct vr_usocket *child;
     218             : 
     219             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: parent FD %d cfd %d\n", __func__,
     220             :             pthread_self(), parent->usock_fd, cfd);
     221        2951 :     child = vr_zalloc(sizeof(struct vr_usocket), VR_USOCK_OBJECT);
     222        2951 :     if (!child) {
     223           0 :         usock_set_error(parent, -ENOMEM);
     224           0 :         goto error_return;
     225             :     }
     226             : 
     227        2951 :     child->usock_rx_buf = vr_malloc(USOCK_RX_BUF_LEN, VR_USOCK_BUF_OBJECT);
     228        2951 :     if (!child->usock_rx_buf) {
     229           0 :         usock_set_error(parent, -ENOMEM);
     230           0 :         goto error_return;
     231             :     }
     232        2951 :     child->usock_buf_len = USOCK_RX_BUF_LEN;
     233             : 
     234        2951 :     child->usock_type = parent->usock_type;
     235        2951 :     child->usock_proto = parent->usock_proto;
     236        2951 :     child->usock_fd = cfd;
     237             : 
     238        2951 :     if (usock_bind_usockets(parent, child))
     239           0 :         goto error_return;
     240             : 
     241        2951 :     return 0;
     242             : 
     243           0 : error_return:
     244           0 :     if (child) {
     245           0 :         if (child->usock_rx_buf)
     246           0 :             vr_free(child->usock_rx_buf, VR_USOCK_BUF_OBJECT);
     247           0 :         vr_free(child, VR_USOCK_OBJECT);
     248             :     }
     249             : 
     250           0 :     return parent->usock_error;
     251             : }
     252             : 
     253             : 
     254             : static void
     255        3004 : usock_unbind(struct vr_usocket *child)
     256             : {
     257             :     struct vr_usocket *parent;
     258             : 
     259        3004 :     if (!child)
     260           0 :         return;
     261             : 
     262        3004 :     parent = child->usock_parent;
     263             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: child FD %d parent %p\n", __func__,
     264             :             pthread_self(), child->usock_fd, parent);
     265        3004 :     if (!parent)
     266          53 :         return;
     267             : 
     268        2951 :     parent->usock_children[child->usock_child_index] = NULL;
     269        2951 :     if (parent->usock_pfds)
     270        2951 :         parent->usock_pfds[child->usock_child_index].fd = -1;
     271             : 
     272        2951 :     parent->usock_disconnects++;
     273        2951 :     parent->usock_cfds--;
     274        2951 :     if((parent->usock_state == LIMITED) &&
     275           0 :             (parent->usock_cfds < USOCK_MAX_CHILD_FDS))
     276           0 :         parent->usock_state = LISTENING;
     277             : 
     278        2951 :     child->usock_parent = NULL;
     279             : 
     280        2951 :     return;
     281             : }
     282             : 
     283             : static void
     284        6008 : usock_close(struct vr_usocket *usockp)
     285             : {
     286             :     int i;
     287             :     struct vr_usocket *parent;
     288             : 
     289             :     RTE_SET_USED(parent);
     290             : 
     291        6008 :     if (!usockp)
     292        3004 :         return;
     293             : 
     294             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(), usockp->usock_fd);
     295        3004 :     usock_unbind(usockp);
     296        3004 :     usock_deinit_poll(usockp);
     297             : 
     298        3057 :     for (i = 0; i < usockp->usock_cfds; i++) {
     299          53 :         usock_close(usockp->usock_children[i]);
     300             :     }
     301             : 
     302             :     RTE_LOG_DP(DEBUG, USOCK, "%s: closing FD %d\n", __func__, usockp->usock_fd);
     303        3004 :     close(usockp->usock_fd);
     304             : 
     305        3004 :     if (!usockp->usock_mbuf_pool && usockp->usock_rx_buf) {
     306        2951 :         vr_free(usockp->usock_rx_buf, VR_USOCK_BUF_OBJECT);
     307        2951 :         usockp->usock_rx_buf = NULL;
     308             :     }
     309             : 
     310        3004 :     if (usockp->usock_iovec) {
     311           0 :         vr_free(usockp->usock_iovec, VR_USOCK_IOVEC_OBJECT);
     312           0 :         usockp->usock_iovec = NULL;
     313             :     }
     314             : 
     315        3004 :     if (usockp->usock_mbuf_pool) {
     316             :         /* no api to destroy a pool */
     317             :     }
     318             : 
     319        3004 :     if (usockp->usock_proto == PACKET) {
     320             :         RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: unlinking %s\n", __func__,
     321             :             pthread_self(), vr_packet_unix_file);
     322           0 :         unlink(vr_packet_unix_file);
     323             :     }
     324             : 
     325        3004 :     usockp->usock_io_in_progress = 0;
     326             : 
     327        3004 :     vr_free(usockp, VR_USOCK_OBJECT);
     328             : 
     329        3004 :     return;
     330             : }
     331             : 
     332             : static int
     333        2863 : __usock_write(struct vr_usocket *usockp)
     334             : {
     335             :     int ret;
     336             :     unsigned int len;
     337             :     unsigned char *buf;
     338        2863 :     struct vr_usocket *parent = NULL;
     339             : 
     340        2863 :     if (usockp->usock_proto != EVENT) {
     341        2863 :         parent = usockp->usock_parent;
     342        2863 :         if (!parent)
     343           0 :             return -1;
     344             :     }
     345             : 
     346        2863 :     buf = usockp->usock_tx_buf;
     347        2863 :     if (!buf || !usockp->usock_write_len)
     348           0 :         return 0;
     349             : 
     350        2863 :     len = usockp->usock_write_len;
     351             : 
     352        2863 :     buf += usockp->usock_write_offset;
     353        2863 :     len -= usockp->usock_write_offset;
     354             : 
     355        2863 : retry_write:
     356             : #ifdef VR_DPDK_USOCK_DUMP
     357             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d writing %d bytes\n",
     358             :                 __func__, pthread_self(), usockp->usock_fd, len);
     359             :     rte_hexdump(stdout, "usock buffer dump:", buf, len);
     360             : #endif
     361        2863 :     if (usockp->usock_owner != pthread_self()) {
     362           0 :         if (usockp->usock_owner)
     363           0 :             RTE_LOG(WARNING, USOCK, "WARNING: thread %lx (lcore %u) is trying to write %u bytes"
     364             :                 " to usocket FD %d owned by thread %lx\n",
     365             :                 pthread_self(), rte_lcore_id(), len, usockp->usock_fd, usockp->usock_owner);
     366           0 :         usockp->usock_owner = pthread_self();
     367             :     }
     368        2863 :     ret = write(usockp->usock_fd, buf, len);
     369        2863 :     if (ret > 0) {
     370        2863 :         usockp->usock_write_offset += ret;
     371        2863 :         if (usockp->usock_write_offset == usockp->usock_write_len) {
     372             :             /* remove from output poll */
     373        2863 :             if (parent)
     374        2863 :                 parent->usock_pfds[usockp->usock_child_index].events = POLLIN;
     375        2863 :             usockp->usock_tx_buf = NULL;
     376             :         } else {
     377           0 :             if (parent)
     378           0 :                 parent->usock_pfds[usockp->usock_child_index].events = POLLOUT;
     379             :         }
     380           0 :     } else if (ret < 0) {
     381             :         RTE_LOG_DP(DEBUG, VROUTER, "%s[%lx]: write error FD %d\n", __func__, pthread_self(),
     382             :                 usockp->usock_fd);
     383           0 :         usock_set_error(usockp, ret);
     384             : 
     385           0 :         if (errno == EINTR)
     386           0 :             goto retry_write;
     387             : 
     388           0 :         if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
     389           0 :             if (parent) {
     390           0 :                 parent->usock_pfds[usockp->usock_child_index].events = POLLOUT;
     391           0 :                 return 0;
     392             :             }
     393             :         }
     394           0 :         usockp->usock_tx_buf = NULL;
     395             :     }
     396             : 
     397        2863 :     return ret;
     398             : }
     399             : 
     400             : static void
     401           0 : usock_netlink_write_responses(struct vr_usocket *usockp)
     402             : {
     403             :     int ret;
     404             :     struct vr_message *resp;
     405             : 
     406             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(), usockp->usock_fd);
     407           0 :     while ((resp =
     408           0 :                 (struct vr_message *)vr_queue_dequeue(&usockp->usock_nl_responses))) {
     409           0 :         usockp->usock_tx_buf = (unsigned char *)dpdk_nl_message_hdr(resp);
     410           0 :         usockp->usock_write_len = dpdk_nl_message_len(resp);
     411           0 :         usockp->usock_write_offset = 0;
     412           0 :         ret = __usock_write(usockp);
     413           0 :         if ((ret < 0) || (ret == usockp->usock_write_len)) {
     414           0 :             vr_message_free(resp);
     415             :         } else {
     416             :             break;
     417             :         }
     418             :     }
     419             : 
     420           0 :     return;
     421             : }
     422             : 
     423             : 
     424             : static int
     425           0 : usock_mbuf_write(struct vr_usocket *usockp, struct rte_mbuf *mbuf)
     426             : {
     427             :     unsigned int i, pkt_len;
     428             :     struct msghdr mhdr;
     429             :     struct rte_mbuf *m;
     430             :     struct iovec *iov;
     431             : 
     432           0 :     if (!mbuf)
     433           0 :         return 0;
     434             : 
     435           0 :     pkt_len = rte_pktmbuf_pkt_len(mbuf);
     436           0 :     if (!pkt_len)
     437           0 :         return 0;
     438             : 
     439           0 :     iov = usockp->usock_iovec;
     440             : 
     441           0 :     m = mbuf;
     442           0 :     for (i = 0; (m && (i < PKT0_MAX_IOV_LEN)); i++) {
     443           0 :         iov->iov_base = rte_pktmbuf_mtod(m, unsigned char *);
     444           0 :         iov->iov_len = rte_pktmbuf_data_len(m);
     445           0 :         m = m->next;
     446           0 :         iov++;
     447             :     }
     448             : 
     449           0 :     if ((i == PKT0_MAX_IOV_LEN) && m)
     450           0 :         usockp->usock_pkt_truncated++;
     451             : 
     452           0 :     mhdr.msg_name = NULL;
     453           0 :     mhdr.msg_namelen = 0;
     454           0 :     mhdr.msg_iov = usockp->usock_iovec;
     455           0 :     mhdr.msg_iovlen = i;
     456           0 :     mhdr.msg_control = NULL;
     457           0 :     mhdr.msg_controllen = 0;
     458           0 :     mhdr.msg_flags = 0;
     459             : 
     460             : #ifdef VR_DPDK_USOCK_DUMP
     461             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d sending message\n", __func__,
     462             :             pthread_self(), usockp->usock_fd);
     463             :     rte_hexdump(stdout, "usock message dump:", &mhdr, sizeof(mhdr));
     464             : #endif
     465           0 :     return sendmsg(usockp->usock_fd, &mhdr, MSG_DONTWAIT);
     466             : }
     467             : 
     468             : static void
     469           0 : vr_dpdk_packet_receive(struct vr_usocket *usockp)
     470             : {
     471           0 :     const unsigned lcore_id = rte_lcore_id();
     472           0 :     struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id];
     473             :     struct vr_interface_stats *stats;
     474             : 
     475             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
     476             :                 usockp->usock_fd);
     477             :     /**
     478             :      * Packets is read from the agent's socket here. On success, a counter for
     479             :      * packets dequeued from the interface is incremented.
     480             :      */
     481           0 :     stats = vif_get_stats(usockp->usock_vif, lcore_id);
     482           0 :     if (usockp->usock_vif) {
     483           0 :         stats->vis_port_ipackets++;
     484             :         /* buf_addr and data_off do not change */
     485           0 :         usockp->usock_mbuf->data_len = usockp->usock_read_len;
     486           0 :         usockp->usock_mbuf->pkt_len = usockp->usock_read_len;
     487             :         /* convert mbuf to vr_packet */
     488           0 :         vr_dpdk_packet_get(usockp->usock_mbuf, usockp->usock_vif);
     489             :         /* send the mbuf to vRouter */
     490           0 :         vr_dpdk_lcore_vroute(lcore, usockp->usock_vif, &usockp->usock_mbuf, 1);
     491             :         /* flush packet TX queues immediately */
     492           0 :         vr_dpdk_lcore_flush(lcore);
     493             :     } else {
     494             :         /**
     495             :          * If reading from socket failed, increment counter for interface
     496             :          * dequeue drops.
     497             :          */
     498           0 :         RTE_LOG(ERR, VROUTER, "Error receiving from packet socket: no vif attached\n");
     499           0 :         vr_dpdk_pfree(usockp->usock_mbuf, NULL, VP_DROP_INTERFACE_DROP);
     500           0 :         stats->vis_port_ierrors++;
     501             :     }
     502             : 
     503           0 :     usockp->usock_mbuf = NULL;
     504           0 :     usockp->usock_rx_buf = NULL;
     505           0 :     usockp->usock_buf_len = 0;
     506             : 
     507           0 :     return;
     508             : }
     509             : 
     510             : static void
     511          53 : vr_dpdk_packet_ring_drain(struct vr_usocket *usockp)
     512             : {
     513             :     int i;
     514             :     unsigned nb_pkts;
     515             :     struct rte_mbuf *mbuf_arr[VR_DPDK_RX_BURST_SZ];
     516          53 :     const unsigned lcore_id = rte_lcore_id();
     517             :     struct vr_interface_stats *stats;
     518             : 
     519             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: draining packet ring...\n", __func__,
     520             :             pthread_self());
     521             : 
     522          53 :     if (unlikely(usockp->usock_parent->usock_vif == NULL))
     523          53 :         return;
     524             : 
     525           0 :     rcu_thread_offline();
     526             : 
     527           0 :     stats = vif_get_stats(usockp->usock_parent->usock_vif, lcore_id);
     528             :     do {
     529           0 :         nb_pkts = rte_ring_sc_dequeue_burst(vr_dpdk.packet_ring,
     530             :             (void **)&mbuf_arr, VR_DPDK_RX_BURST_SZ, NULL);
     531           0 :         for (i = 0; i < nb_pkts; i++) {
     532           0 :             if (usock_mbuf_write(usockp->usock_parent, mbuf_arr[i]) >= 0)
     533           0 :                 stats->vis_port_opackets++;
     534             :             else {
     535           0 :                 stats->vis_port_oerrors++;
     536             :                 RTE_LOG_DP(DEBUG, USOCK,
     537             :                         "%s: Error writing mbuf to packet socket: %s (%d)\n",
     538             :                         __func__, rte_strerror(errno), errno);
     539             :             }
     540             : 
     541           0 :             rte_pktmbuf_free(mbuf_arr[i]);
     542             :         }
     543           0 :     } while (nb_pkts > 0);
     544             : 
     545           0 :     rcu_thread_online();
     546             : }
     547             : 
     548             : static int
     549        2915 : usock_read_done(struct vr_usocket *usockp)
     550             : {
     551        2915 :     if (usockp->usock_state == READING_FAULTY_DATA)
     552           0 :         return 0;
     553             : 
     554        2915 :     switch (usockp->usock_proto) {
     555           0 :     case PACKET:
     556           0 :         vr_dpdk_packet_receive(usockp);
     557           0 :         break;
     558             : 
     559          53 :     case EVENT:
     560          53 :         vr_dpdk_packet_ring_drain(usockp);
     561          53 :         break;
     562             : 
     563        2862 :     case NETLINK:
     564        2862 :         dpdk_netlink_receive(usockp, usockp->usock_rx_buf,
     565             :                 usockp->usock_read_len);
     566        2862 :         break;
     567             : 
     568           0 :     default:
     569           0 :         break;
     570             :     }
     571             : 
     572        2915 :     return 0;
     573             : }
     574             : 
     575             : static int
     576        6025 : usock_read_init(struct vr_usocket *usockp)
     577             : {
     578        6025 :     usockp->usock_read_offset = 0;
     579             : 
     580        6025 :     switch (usockp->usock_proto) {
     581        5813 :     case NETLINK:
     582        5813 :         if (usockp->usock_parent) {
     583        5813 :             usockp->usock_read_len = NLMSG_HDRLEN;
     584        5813 :             usockp->usock_state = READING_HEADER;
     585             :         }
     586        5813 :         break;
     587             : 
     588         212 :     case EVENT:
     589         212 :         usockp->usock_read_len = USOCK_EVENT_BUF_LEN;
     590         212 :         usockp->usock_state = READING_DATA;
     591         212 :         break;
     592             : 
     593           0 :     case PACKET:
     594           0 :         if (usockp->usock_mbuf) {
     595           0 :             RTE_LOG(ERR, VROUTER, "Error initing usock read: mbuf is already exist\n");
     596           0 :             return -EINVAL;
     597             :         }
     598             : 
     599           0 :         usockp->usock_mbuf = rte_pktmbuf_alloc(usockp->usock_mbuf_pool);
     600           0 :         if (!usockp->usock_mbuf) {
     601           0 :             RTE_LOG(ERR, VROUTER, "Error initing usock read: cannot allocate mbuf\n");
     602           0 :             return -ENOMEM;
     603             :         }
     604             : 
     605           0 :         usockp->usock_rx_buf = rte_pktmbuf_mtod(usockp->usock_mbuf, char *);
     606           0 :         usockp->usock_buf_len = usockp->usock_mbuf->buf_len
     607           0 :                                 - rte_pktmbuf_headroom(usockp->usock_mbuf);
     608           0 :         usockp->usock_read_len = usockp->usock_buf_len;
     609           0 :         usockp->usock_state = READING_DATA;
     610           0 :         break;
     611             : 
     612           0 :     default:
     613           0 :         break;
     614             :     }
     615             : 
     616        6025 :     return 0;
     617             : }
     618             : 
     619             : static int
     620        8728 : __usock_read(struct vr_usocket *usockp)
     621             : {
     622             :     int ret;
     623        8728 :     unsigned int offset = usockp->usock_read_offset;
     624        8728 :     unsigned int len = usockp->usock_read_len;
     625        8728 :     unsigned int toread = len - offset;
     626             : 
     627             :     struct nlmsghdr *nlh;
     628        8728 :     unsigned int proto = usockp->usock_proto;
     629        8728 :     char *buf = usockp->usock_rx_buf;
     630             : 
     631        8728 :     if (toread > usockp->usock_buf_len) {
     632           0 :         toread = usockp->usock_buf_len - offset;
     633             :     }
     634             : 
     635        8728 : retry_read:
     636        8728 :     if (usockp->usock_owner != pthread_self()) {
     637        3004 :         if (usockp->usock_owner)
     638           0 :             RTE_LOG(WARNING, USOCK, "WARNING: thread %lx is trying to read"
     639             :                 " usocket FD %d owned by thread %lx\n",
     640             :                 pthread_self(), usockp->usock_fd, usockp->usock_owner);
     641        3004 :         usockp->usock_owner = pthread_self();
     642             :     }
     643        8728 :     ret = read(usockp->usock_fd, buf + offset, toread);
     644             : #ifdef VR_DPDK_USOCK_DUMP
     645             :     if (ret > 0) {
     646             :         RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d read %d bytes\n", __func__,
     647             :             pthread_self(), usockp->usock_fd, ret);
     648             :         rte_hexdump(stdout, "usock buffer dump:", buf + offset, ret);
     649             :     } else if (ret < 0) {
     650             :         RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d read returned error %d: %s (%d)\n", __func__,
     651             :             pthread_self(), usockp->usock_fd, ret, rte_strerror(errno), errno);
     652             :     }
     653             : #endif
     654        8728 :     if (ret <= 0) {
     655        2951 :         if (!ret)
     656        2951 :             return -1;
     657             : 
     658           0 :         if (errno == EINTR)
     659           0 :             goto retry_read;
     660             : 
     661           0 :         if ((errno == EAGAIN) ||
     662           0 :                 (errno == EWOULDBLOCK))
     663           0 :             return 0;
     664             : 
     665           0 :         RTE_LOG(ERR, USOCK, "Error reading FD %d: %s (%d)\n",
     666             :                 usockp->usock_fd, rte_strerror(errno), errno);
     667           0 :         return ret;
     668             :     }
     669             : 
     670        5777 :     offset += ret;
     671        5777 :     usockp->usock_read_offset = offset;
     672             : 
     673        5777 :     if (proto == NETLINK) {
     674        5724 :         if (usockp->usock_state == READING_HEADER) {
     675        2862 :             if (usockp->usock_read_offset == usockp->usock_read_len) {
     676        2862 :                 usockp->usock_state = READING_DATA;
     677        2862 :                 nlh = (struct nlmsghdr *)(usockp->usock_rx_buf);
     678        2862 :                 usockp->usock_read_len = nlh->nlmsg_len;
     679             :             }
     680             :         }
     681             : 
     682        5724 :         if (usockp->usock_buf_len < usockp->usock_read_len) {
     683           0 :             usockp->usock_rx_buf = vr_malloc(usockp->usock_read_len,
     684             :                     VR_USOCK_BUF_OBJECT);
     685           0 :             if (!usockp->usock_rx_buf) {
     686             :                 /* bad, but let's recover */
     687           0 :                 usockp->usock_rx_buf = buf;
     688           0 :                 usockp->usock_read_len -= usockp->usock_read_offset;
     689           0 :                 usockp->usock_read_offset = 0;
     690           0 :                 usockp->usock_state = READING_FAULTY_DATA;
     691             :             } else {
     692           0 :                 memcpy(usockp->usock_rx_buf, buf, usockp->usock_read_offset);
     693           0 :                 vr_free(buf, VR_USOCK_BUF_OBJECT);
     694           0 :                 usockp->usock_buf_len = usockp->usock_read_len;
     695           0 :                 buf = usockp->usock_rx_buf;
     696             :             }
     697             :         }
     698          53 :     } else if (proto == PACKET) {
     699           0 :         usockp->usock_read_len = ret;
     700             :     }
     701             : 
     702        5777 :     return ret;
     703             : }
     704             : 
     705             : 
     706             : static struct vr_usocket *
     707         159 : usock_alloc(unsigned short proto, unsigned short type)
     708             : {
     709         159 :     unsigned int pkt0_mempool_sz = PKT0_MBUF_POOL_SIZE;
     710         159 :     int sock_fd = -1, domain, ret;
     711             :     /* socket TX buffer size = (hold flow table entries * size of jumbo frame) */
     712         159 :     int setsocksndbuff = vr_flow_hold_limit * vr_packet_sz;
     713             :     int getsocksndbuff;
     714         159 :     socklen_t getsocksndbufflen = sizeof(getsocksndbuff);
     715         159 :     int error = 0, flags;
     716             :     unsigned int buf_len;
     717         159 :     struct vr_usocket *usockp = NULL, *child;
     718         159 :     bool is_socket = true;
     719             :     unsigned short sock_type;
     720         159 :     int flag = 1;
     721             : 
     722             :     RTE_SET_USED(child);
     723             : 
     724             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: proto %u type %u\n", __func__,
     725             :                 pthread_self(), proto, type);
     726         159 :     switch (type) {
     727           0 :     case TCP:
     728           0 :         domain = AF_INET;
     729           0 :         sock_type = SOCK_STREAM;
     730           0 :         break;
     731             : 
     732          53 :     case UNIX:
     733          53 :         domain = AF_UNIX;
     734          53 :         sock_type = SOCK_STREAM;
     735          53 :         break;
     736             : 
     737         106 :     case RAW:
     738         106 :         domain = AF_UNIX;
     739         106 :         sock_type = SOCK_DGRAM;
     740         106 :         break;
     741             : 
     742           0 :     default:
     743           0 :         return NULL;
     744             :     }
     745             : 
     746         159 :     if (proto == EVENT) {
     747         106 :         is_socket = false;
     748         106 :         sock_fd = eventfd(0, 0);
     749             :         RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: new event FD %d\n", __func__,
     750             :                 pthread_self(), sock_fd);
     751         106 :         if (sock_fd < 0)
     752           0 :             return NULL;
     753             :     }
     754             : 
     755         159 :     if (is_socket) {
     756          53 :         sock_fd = socket(domain, sock_type, 0);
     757          53 :         RTE_LOG(INFO, USOCK, "%s[%lx]: new socket FD %d\n", __func__,
     758             :                 pthread_self(), sock_fd);
     759          53 :         if (sock_fd < 0)
     760           0 :             return NULL;
     761             : 
     762          53 :         if (type == TCP) {
     763           0 :             RTE_LOG(INFO, USOCK, "%s[%lx]: setting socket FD %d nodelay.\n"
     764             :                         , __func__, pthread_self(), sock_fd);
     765           0 :             ret = setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag,
     766             :                              sizeof(int));
     767           0 :             if (ret != 0) {
     768           0 :                 RTE_LOG(ERR, USOCK, "%s[%lx]: setting socket FD %d nodelay failed (%d).\n"
     769             :                         , __func__, pthread_self(), sock_fd, errno);
     770             :             }
     771             :         }
     772             : 
     773             :         /* set socket send buffer size */
     774          53 :         ret = setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &setsocksndbuff,
     775             :                          sizeof(setsocksndbuff));
     776          53 :         if (ret == 0) {
     777             :             /* check if setting buffer succeeded */
     778          53 :             ret = getsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &getsocksndbuff,
     779             :                              &getsocksndbufflen);
     780          53 :             if (ret == 0) {
     781          53 :                 if (getsocksndbuff >= setsocksndbuff) {
     782           0 :                     RTE_LOG(INFO, USOCK, "%s[%lx]: setting socket FD %d send buff size.\n"
     783             :                             "Buffer size set to %d (requested %d)\n", __func__,
     784             :                             pthread_self(), sock_fd, getsocksndbuff, setsocksndbuff);
     785             :                 } else { /* set other than requested */
     786          53 :                     RTE_LOG(ERR, USOCK, "%s[%lx]: setting socket FD %d send buff size failed.\n"
     787             :                             "Buffer size set to %d (requested %d)\n", __func__,
     788             :                             pthread_self(), sock_fd, getsocksndbuff, setsocksndbuff);
     789             :                 }
     790             :             } else { /* requesting buffer size failed */
     791           0 :                 RTE_LOG(ERR, USOCK, "%s[%lx]: getting socket FD %d send buff size failed (%d)\n",
     792             :                          __func__, pthread_self(), sock_fd, errno);
     793             :             }
     794             :         } else { /* setting buffer size failed */
     795           0 :             RTE_LOG(ERR, USOCK, "%s[%lx]: setting socket FD %d send buff size %d failed (%d)\n",
     796             :                      __func__, pthread_self(), sock_fd, setsocksndbuff, errno);
     797             :         }
     798             :     }
     799             : 
     800         159 :     usockp = vr_zalloc(sizeof(*usockp), VR_USOCK_OBJECT);
     801         159 :     if (!usockp)
     802           0 :         goto error_exit;
     803             : 
     804         159 :     usockp->usock_type = type;
     805         159 :     usockp->usock_proto = proto;
     806         159 :     usockp->usock_fd = sock_fd;
     807         159 :     usockp->usock_state = INITED;
     808             : 
     809         159 :     if (is_socket) {
     810          53 :         error = vr_usocket_bind(usockp);
     811          53 :         if (error < 0)
     812           0 :             goto error_exit;
     813             : 
     814          53 :         if (usockp->usock_proto == PACKET) {
     815           0 :             error = vr_usocket_connect(usockp);
     816           0 :             if (error < 0)
     817           0 :                 goto error_exit;
     818             :         }
     819             :     }
     820             : 
     821         159 :     switch (proto) {
     822          53 :     case NETLINK:
     823          53 :         usockp->usock_max_cfds = USOCK_MAX_CHILD_FDS;
     824          53 :         buf_len = 0;
     825          53 :         break;
     826             : 
     827           0 :     case PACKET:
     828           0 :         usockp->usock_max_cfds = USOCK_MAX_CHILD_FDS;
     829           0 :         buf_len = 0;
     830           0 :         break;
     831             : 
     832         106 :     case EVENT:
     833             :         /* TODO: we don't need the buf since we use stack to send an event */
     834         106 :         buf_len = USOCK_EVENT_BUF_LEN;
     835         106 :         break;
     836             : 
     837           0 :     default:
     838           0 :         buf_len = 0;
     839           0 :         break;
     840             :     }
     841             : 
     842         159 :     if (buf_len) {
     843         106 :         usockp->usock_rx_buf = vr_zalloc(buf_len, VR_USOCK_BUF_OBJECT);
     844         106 :         if (!usockp->usock_rx_buf)
     845           0 :             goto error_exit;
     846             : 
     847         106 :         usockp->usock_buf_len = buf_len;
     848         106 :         usock_read_init(usockp);
     849             :     }
     850             : 
     851         159 :     if (proto == PACKET) {
     852           0 :         usockp->usock_mbuf_pool = rte_mempool_lookup("packet_mbuf_pool");
     853           0 :         if (!usockp->usock_mbuf_pool) {
     854           0 :             usockp->usock_mbuf_pool = rte_mempool_create("packet_mbuf_pool",
     855             :                     pkt0_mempool_sz, PKT0_MBUF_PACKET_SIZE,
     856             :                     PKT0_MBUF_POOL_CACHE_SZ, sizeof(struct rte_pktmbuf_pool_private),
     857             :                     vr_dpdk_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL,
     858           0 :                     rte_socket_id(), 0);
     859           0 :             if (!usockp->usock_mbuf_pool)
     860           0 :                 goto error_exit;
     861             :         }
     862             : 
     863           0 :         usockp->usock_iovec = vr_zalloc(sizeof(struct iovec) *
     864             :                 PKT0_MAX_IOV_LEN, VR_USOCK_IOVEC_OBJECT);
     865           0 :         if (!usockp->usock_iovec)
     866           0 :             goto error_exit;
     867             : 
     868           0 :         usock_read_init(usockp);
     869             :     }
     870             : 
     871             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d F_GETFL\n", __func__, pthread_self(),
     872             :                 usockp->usock_fd);
     873         159 :     flags = fcntl(usockp->usock_fd, F_GETFL);
     874         159 :     if (flags == -1)
     875           0 :         goto error_exit;
     876             : 
     877             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d F_SETFL\n", __func__, pthread_self(),
     878             :                 usockp->usock_fd);
     879         159 :     error = fcntl(usockp->usock_fd, F_SETFL, flags | O_NONBLOCK);
     880         159 :     if (error == -1)
     881           0 :         goto error_exit;
     882             : 
     883         159 :     usockp->usock_poll_block = 1;
     884             : 
     885         159 :     return usockp;
     886             : 
     887           0 : error_exit:
     888             : 
     889           0 :     error = errno;
     890           0 :     if (sock_fd >= 0) {
     891           0 :         close(sock_fd);
     892           0 :         sock_fd = -1;
     893             :     }
     894             : 
     895           0 :     usock_close(usockp);
     896           0 :     usockp = NULL;
     897           0 :     errno = error;
     898             : 
     899           0 :     return usockp;
     900             : }
     901             : 
     902             : /*
     903             :  * currently defined protocols are netlink and packet.
     904             :  * for packet, only raw socket type is accepted
     905             :  * for netlink, both tcp and unix socket types are accepted
     906             :  */
     907             : static bool
     908         159 : valid_usock(int proto, int type)
     909             : {
     910             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: proto %u type %u\n", __func__,
     911             :             pthread_self(), proto, type);
     912         159 :     if ((proto != PACKET) &&
     913         106 :             (proto != NETLINK) &&
     914             :             (proto != EVENT))
     915           0 :         return -EINVAL;
     916             : 
     917         159 :     if (((proto == PACKET) || (proto == EVENT)) && (type != RAW)) {
     918           0 :         return -EINVAL;
     919             :     } else {
     920         159 :         if (type != TCP && type != UNIX)
     921         106 :             return -EINVAL;
     922             :     }
     923             : 
     924          53 :     return true;
     925             : }
     926             : 
     927             : void
     928           0 : vr_usocket_detach_vif(void *usockp)
     929             : {
     930             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
     931             :                         ((struct vr_usocket *)usockp)->usock_fd);
     932           0 :     ((struct vr_usocket *)usockp)->usock_vif = NULL;
     933           0 :     return;
     934             : }
     935             : 
     936             : void
     937           0 : vr_usocket_attach_vif(void *usockp, struct vr_interface *vif)
     938             : {
     939           0 :     if (!vif)
     940           0 :         return;
     941             : 
     942             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
     943             :                         ((struct vr_usocket *)usockp)->usock_fd);
     944           0 :     ((struct vr_usocket *)usockp)->usock_vif = vif;
     945           0 :     return;
     946             : }
     947             : 
     948             : void
     949           0 : vr_usocket_non_blocking(struct vr_usocket *usockp)
     950             : {
     951             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
     952             :                 usockp->usock_fd);
     953           0 :     usockp->usock_poll_block = 0;
     954           0 :     return;
     955             : }
     956             : 
     957             : int
     958        2863 : vr_usocket_write(struct vr_usocket *usockp, unsigned char *buf,
     959             :         unsigned int len)
     960             : {
     961        2863 :     if (usockp->usock_tx_buf)
     962           0 :         return -1;
     963             : 
     964        2863 :     usockp->usock_tx_buf = buf;
     965        2863 :     usockp->usock_write_offset = 0;
     966        2863 :     usockp->usock_write_len = len;
     967             : 
     968        2863 :     return __usock_write(usockp);
     969             : }
     970             : 
     971             : int
     972          53 : vr_usocket_eventfd_write(struct vr_usocket *usockp)
     973             : {
     974          53 :     if (usockp->usock_proto != EVENT)
     975           0 :         return -1;
     976             : 
     977          53 :     return eventfd_write(usockp->usock_fd, 1);
     978             : }
     979             : 
     980             : int
     981        2863 : vr_usocket_message_write(struct vr_usocket *usockp,
     982             :         struct vr_message *message)
     983             : {
     984             :     int ret;
     985             :     unsigned int len;
     986             :     unsigned char *buf;
     987             : 
     988             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
     989             :                 usockp->usock_fd);
     990        2863 :     if ((usockp->usock_proto != NETLINK) && (usockp->usock_type != TCP))
     991           0 :         return -EINVAL;
     992             : 
     993        2863 :     if (usockp->usock_tx_buf || !vr_queue_empty(&usockp->usock_nl_responses)) {
     994           0 :         vr_queue_enqueue(&usockp->usock_nl_responses,
     995             :                 &message->vr_message_queue);
     996           0 :         return 0;
     997             :     }
     998             : 
     999        2863 :     buf = (unsigned char *)dpdk_nl_message_hdr(message);
    1000        2863 :     len = dpdk_nl_message_len(message);
    1001        2863 :     ret = vr_usocket_write(usockp, buf, len);
    1002        2863 :     if (ret == len) {
    1003        2863 :         vr_message_free(message);
    1004             :     }
    1005             : 
    1006        2863 :     return ret;
    1007             : }
    1008             : 
    1009             : static int
    1010       11679 : vr_usocket_read(struct vr_usocket *usockp)
    1011             : {
    1012             :     int ret;
    1013             : 
    1014       11679 :     if (!usockp || usockp->usock_fd < 0)
    1015           0 :         return -1;
    1016             : 
    1017       11679 :     switch (usockp->usock_state) {
    1018        2951 :     case LISTENING:
    1019             :     case LIMITED:
    1020        2951 :         ret = vr_usocket_accept(usockp);
    1021        2951 :         if (ret < 0)
    1022           0 :             return ret;
    1023             : 
    1024        2951 :         break;
    1025             : 
    1026        8728 :     case READING_HEADER:
    1027             :     case READING_DATA:
    1028             :     case READING_FAULTY_DATA:
    1029        8728 :         ret = __usock_read(usockp);
    1030        8728 :         if (ret < 0) {
    1031             :             RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: read error FD %d\n", __func__, pthread_self(),
    1032             :                         usockp->usock_fd);
    1033        2951 :             usock_close(usockp);
    1034        2951 :             return ret;
    1035             :         }
    1036             : 
    1037        5777 :         if (usockp->usock_read_offset == usockp->usock_read_len) {
    1038        2915 :             usock_read_done(usockp);
    1039             :             /* we have the complete message */
    1040        2915 :             usock_read_init(usockp);
    1041             :         }
    1042             : 
    1043        5777 :         break;
    1044             : 
    1045           0 :     default:
    1046           0 :         return -1;
    1047             :     }
    1048             : 
    1049        8728 :     return ret;
    1050             : }
    1051             : 
    1052             : static int
    1053           0 : vr_usocket_connect(struct vr_usocket *usockp)
    1054             : {
    1055             :     struct sockaddr_un sun;
    1056             : 
    1057             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
    1058             :                 usockp->usock_fd);
    1059           0 :     if (usockp->usock_proto != PACKET)
    1060           0 :         return -EINVAL;
    1061             : 
    1062           0 :     sun.sun_family = AF_UNIX;
    1063           0 :     memset(sun.sun_path, 0, sizeof(sun.sun_path));
    1064           0 :     strncpy(sun.sun_path, vr_socket_dir, sizeof(sun.sun_path) - 1);
    1065           0 :     strncat(sun.sun_path, "/"VR_PACKET_AGENT_UNIX_NAME, sizeof(sun.sun_path)
    1066           0 :         - strlen(sun.sun_path) - 1);
    1067             : 
    1068             : #ifdef VR_DPDK_USOCK_DUMP
    1069             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d retry connecting\n", __func__,
    1070             :             pthread_self(), usockp->usock_fd);
    1071             :     rte_hexdump(stdout, "usock address dump:", &sun, sizeof(sun));
    1072             : #endif
    1073           0 :     return vr_dpdk_retry_connect(usockp->usock_fd, (struct sockaddr *)&sun,
    1074             :                                         sizeof(sun));
    1075             : }
    1076             : 
    1077             : static int
    1078        2951 : vr_usocket_accept(struct vr_usocket *usockp)
    1079             : {
    1080             :     int ret;
    1081             : 
    1082             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
    1083             :                 usockp->usock_fd);
    1084        2951 :     ret = accept(usockp->usock_fd, NULL, NULL);
    1085             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d accepted %d\n", __func__, pthread_self(),
    1086             :                     usockp->usock_fd, ret);
    1087        2951 :     if (ret < 0) {
    1088           0 :         usock_set_error(usockp, ret);
    1089           0 :         return ret;
    1090             :     }
    1091             : 
    1092        5902 :     if ((usockp->usock_state == LIMITED) ||
    1093        2951 :             (usock_clone(usockp, ret)))
    1094           0 :         close(ret);
    1095             : 
    1096        2951 :     return 0;
    1097             : }
    1098             : 
    1099             : static int
    1100          53 : vr_usocket_bind(struct vr_usocket *usockp)
    1101             : {
    1102          53 :     int error = 0;
    1103             :     struct sockaddr_in sin;
    1104             :     struct sockaddr_un sun;
    1105          53 :     struct sockaddr *addr = NULL;
    1106          53 :     socklen_t addrlen = 0;
    1107             :     int optval;
    1108             :     bool server;
    1109             : 
    1110          53 :     optval = 1;
    1111             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d setting option\n", __func__,
    1112             :             pthread_self(), usockp->usock_fd);
    1113          53 :     if (setsockopt(usockp->usock_fd, SOL_SOCKET, SO_REUSEADDR, &optval,
    1114             :                 sizeof(optval)))
    1115           0 :         return -errno;
    1116             : 
    1117          53 :     switch (usockp->usock_type) {
    1118           0 :     case TCP:
    1119           0 :         sin.sin_family = AF_INET;
    1120           0 :         sin.sin_port = rte_cpu_to_be_16(vr_netlink_port);
    1121           0 :         sin.sin_addr.s_addr = INADDR_ANY;
    1122           0 :         addr = (struct sockaddr *)&sin;
    1123           0 :         addrlen = sizeof(sin);
    1124           0 :         server = true;
    1125             : 
    1126           0 :         break;
    1127             : 
    1128          53 :     case UNIX:
    1129          53 :         sun.sun_family = AF_UNIX;
    1130          53 :         memset(sun.sun_path, 0, sizeof(sun.sun_path));
    1131          53 :         strncpy(sun.sun_path, vr_socket_dir, sizeof(sun.sun_path) - 1);
    1132          53 :         strncat(sun.sun_path, "/"VR_NETLINK_UNIX_NAME, sizeof(sun.sun_path)
    1133          53 :             - strlen(sun.sun_path) - 1);
    1134             : 
    1135          53 :         addr = (struct sockaddr *)&sun;
    1136          53 :         addrlen = sizeof(sun);
    1137          53 :         server = true;
    1138          53 :         mkdir(vr_socket_dir, VR_DEF_SOCKET_DIR_MODE);
    1139          53 :         unlink(sun.sun_path);
    1140             : 
    1141          53 :         break;
    1142             : 
    1143           0 :     case RAW:
    1144           0 :         sun.sun_family = AF_UNIX;
    1145           0 :         strncpy(vr_packet_unix_file, vr_socket_dir, sizeof(vr_packet_unix_file)
    1146             :             - 1);
    1147           0 :         strncat(vr_packet_unix_file, "/"VR_PACKET_UNIX_NAME,
    1148           0 :             sizeof(vr_packet_unix_file) - strlen(vr_packet_unix_file) - 1);
    1149           0 :         memset(sun.sun_path, 0, sizeof(sun.sun_path));
    1150           0 :         memcpy(sun.sun_path, vr_packet_unix_file, sizeof(sun.sun_path) - 1);
    1151             : 
    1152           0 :         addr = (struct sockaddr *)&sun;
    1153           0 :         addrlen = sizeof(sun);
    1154           0 :         server = false;
    1155           0 :         mkdir(vr_socket_dir, VR_DEF_SOCKET_DIR_MODE);
    1156           0 :         unlink(sun.sun_path);
    1157             : 
    1158           0 :         break;
    1159             : 
    1160           0 :     default:
    1161           0 :         return -EINVAL;
    1162             :     }
    1163             : 
    1164             : #ifdef VR_DPDK_USOCK_DUMP
    1165             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d binding\n", __func__, pthread_self(),
    1166             :             usockp->usock_fd);
    1167             :     rte_hexdump(stdout, "usock address dump:", addr, addrlen);
    1168             : #endif
    1169          53 :     error = bind(usockp->usock_fd, addr, addrlen);
    1170          53 :     if (error < 0)
    1171           0 :         return error;
    1172             : 
    1173          53 :     if (server) {
    1174             :         RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d listening\n", __func__,
    1175             :                 pthread_self(),  usockp->usock_fd);
    1176          53 :         error = listen(usockp->usock_fd, 1);
    1177          53 :         if (error < 0)
    1178           0 :             return error;
    1179          53 :         usockp->usock_state = LISTENING;
    1180             :     }
    1181             : 
    1182          53 :     return 0;
    1183             : }
    1184             : 
    1185             : void
    1186          53 : vr_usocket_close(void *sock)
    1187             : {
    1188          53 :     struct vr_usocket *usockp = (struct vr_usocket *)sock;
    1189             : 
    1190          53 :     if (usockp == NULL)
    1191           0 :         return;
    1192             : 
    1193             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
    1194             :                 usockp->usock_fd);
    1195          53 :     if (usockp->usock_io_in_progress) {
    1196           0 :         usockp->usock_should_close = 1;
    1197           0 :         return;
    1198             :     }
    1199             : 
    1200          53 :     usock_close(usockp);
    1201          53 :     return;
    1202             : }
    1203             : 
    1204             : /*
    1205             :  * create a usocket which is of type (TCP/UNIX/RAW). the messages
    1206             :  * read in those sockets will follow protocol 'proto'. protocol is
    1207             :  * netlink, packet or event
    1208             :  */
    1209             : void *
    1210         159 : vr_usocket(int proto, int type)
    1211             : {
    1212             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: proto %u type %u\n", __func__,
    1213             :                 pthread_self(), proto, type);
    1214             : 
    1215         159 :     if (!valid_usock(proto, type))
    1216           0 :         return NULL;
    1217             : 
    1218         159 :     return (void *)usock_alloc(proto, type);
    1219             : }
    1220             : 
    1221             : static int
    1222           0 : usock_write(struct vr_usocket *usockp)
    1223             : {
    1224             :     int ret;
    1225             : 
    1226           0 :     if (!usockp || usockp->usock_fd < 0)
    1227           0 :         return 0;
    1228             : 
    1229           0 :     ret = __usock_write(usockp);
    1230           0 :     if (ret < 0) {
    1231           0 :         usock_close(usockp);
    1232           0 :         return ret;
    1233             :     }
    1234             : 
    1235           0 :     if (usockp->usock_proto == NETLINK) {
    1236           0 :         if (usockp->usock_write_offset == usockp->usock_write_len) {
    1237           0 :             usock_netlink_write_responses(usockp);
    1238             :         }
    1239             :     }
    1240             : 
    1241           0 :     return 0;
    1242             : }
    1243             : 
    1244             : 
    1245             : /*
    1246             :  * start io on socket
    1247             :  */
    1248             : int
    1249          53 : vr_usocket_io(void *transport)
    1250             : {
    1251             :     int ret, i, processed;
    1252             :     int timeout;
    1253             :     struct pollfd *pfd;
    1254          53 :     struct vr_usocket *usockp = (struct vr_usocket *)transport;
    1255          53 :     unsigned lcore_id = rte_lcore_id();
    1256          53 :     struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id];
    1257             : 
    1258          53 :     if (!usockp)
    1259           0 :         return -1;
    1260             : 
    1261             :     RTE_LOG_DP(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(),
    1262             :                 usockp->usock_fd);
    1263          53 :     if ((ret = usock_init_poll(usockp)))
    1264           0 :         goto return_from_io;
    1265             : 
    1266          53 :     pfd = &usockp->usock_pfds[0];
    1267          53 :     pfd->fd = usockp->usock_fd;
    1268          53 :     pfd->events = POLLIN;
    1269             : 
    1270          53 :     usockp->usock_io_in_progress = 1;
    1271             : 
    1272          53 :     timeout = usockp->usock_poll_block ? INFINITE_TIMEOUT : 0;
    1273             :     while (1) {
    1274       11732 :         if (usockp->usock_should_close) {
    1275           0 :             usock_close(usockp);
    1276           0 :             return -1;
    1277             :         }
    1278             : 
    1279             :         /*
    1280             :          * Handle an IPC commands for IO_LCORE_ID up
    1281             :          * and just check the stop flag for the rest.
    1282             :          */
    1283       11732 :         if (lcore_id >= VR_DPDK_IO_LCORE_ID) {
    1284       11732 :             if (unlikely(vr_dpdk_lcore_cmd_handle(lcore)))
    1285          53 :                 break;
    1286             :         } else {
    1287           0 :             if (unlikely(vr_dpdk_is_stop_flag_set()))
    1288           0 :                 break;
    1289             :         }
    1290             : 
    1291       11679 :         rcu_thread_offline();
    1292       11679 :         ret = poll(usockp->usock_pfds, usockp->usock_max_cfds,
    1293             :                 timeout);
    1294       11679 :         if (ret < 0) {
    1295           0 :             usock_set_error(usockp, ret);
    1296             :             /* all other errors are fatal */
    1297           0 :             if (errno != EINTR)
    1298           0 :                 goto return_from_io;
    1299             :         }
    1300             : 
    1301       11679 :         rcu_thread_online();
    1302             : 
    1303       11679 :         processed = 0;
    1304       11679 :         pfd = usockp->usock_pfds;
    1305       40761 :         for (i = 0; (i < usockp->usock_max_cfds) && (processed < ret);
    1306       29082 :                 i++, pfd++) {
    1307       29082 :             if ((pfd->fd >= 0)) {
    1308       29082 :                 if (pfd->revents & POLLIN) {
    1309       11679 :                     if (i == 0) {
    1310        2951 :                         ret = vr_usocket_read(usockp);
    1311        2951 :                         if (ret < 0)
    1312           0 :                             return ret;
    1313             :                     } else {
    1314        8728 :                         vr_usocket_read(usockp->usock_children[i]);
    1315             :                     }
    1316             :                 }
    1317             : 
    1318       29082 :                 if (pfd->revents & POLLOUT) {
    1319           0 :                     usock_write(usockp->usock_children[i]);
    1320             :                 }
    1321             : 
    1322       29082 :                 if (pfd->revents & POLLHUP) {
    1323        2951 :                     if (i) {
    1324        2951 :                         usock_close(usockp->usock_children[i]);
    1325             :                     } else {
    1326           0 :                         break;
    1327             :                     }
    1328             :                 }
    1329             : 
    1330       29082 :                 if (pfd->revents)
    1331       11679 :                     processed++;
    1332             :             }
    1333             :         }
    1334             : 
    1335       11679 :         if (!timeout)
    1336           0 :             return 0;
    1337             :     }
    1338             : 
    1339          53 : return_from_io:
    1340          53 :     usockp->usock_io_in_progress = 0;
    1341          53 :     usock_deinit_poll(usockp);
    1342             : 
    1343          53 :     return ret;
    1344             : }
    1345             : 

Generated by: LCOV version 1.14