LCOV - code coverage report
Current view: top level - root/contrail/vrouter/utils - unix_util.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 74 663 11.2 %
Date: 2026-08-03 02:19:58 Functions: 7 44 15.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include <stdint.h>
       2             : #include <stdio.h>
       3             : #include <string.h>
       4             : 
       5             : #include <fcntl.h>
       6             : #include <sys/types.h>
       7             : #include <sys/stat.h>
       8             : #include <sys/mman.h>
       9             : #include <sys/sysmacros.h>
      10             : #include <sys/socket.h>
      11             : 
      12             : #if defined(__linux__)
      13             : #include <linux/netlink.h>
      14             : #include <linux/rtnetlink.h>
      15             : #include <linux/genetlink.h>
      16             : #include <linux/if_ether.h>
      17             : #include <linux/sockios.h>
      18             : #include <linux/dcbnl.h>
      19             : #include <linux/socket.h>
      20             : #endif
      21             : #include <netinet/tcp.h>
      22             : #include <sys/un.h>
      23             : 
      24             : #include <vr_mem.h>
      25             : #include <nl_util.h>
      26             : #include <ini_parser.h>
      27             : 
      28             : /* This is defined in linux kernel headers (linux/socket.h) */
      29             : #if !defined(SOL_NETLINK)
      30             : #define SOL_NETLINK 270
      31             : #endif
      32             : 
      33             : #define VROUTER_GENETLINK_VROUTER_GROUP_ID 0x4
      34             : #define VROUTER_GENETLINK_FAMILY_NAME      "vrouter"
      35             : #define GENL_ID_VROUTER                    (NLMSG_MIN_TYPE + 0x10)
      36             : 
      37             : const char *
      38          13 : vr_table_map(int major, unsigned int table, const char *table_path, size_t size, void **mem)
      39             : {
      40             :     enum { ERROR_LEN = 1024 };
      41             :     static char error_msg[ERROR_LEN];
      42             : 
      43             :     int fd, ret;
      44             :     uint16_t dev;
      45             : 
      46             :     const char *path;
      47          13 :     const int platform = get_platform();
      48             : 
      49          13 :     if (major < 0) {
      50           0 :         snprintf(error_msg, ERROR_LEN, "Error: Invalid 'major' value: %d", major);
      51           0 :         return error_msg;
      52             :     }
      53             : 
      54          13 :     if (table_path) {
      55          13 :         path = table_path;
      56             :     } else {
      57           0 :         switch (table) {
      58           0 :         case VR_MEM_BRIDGE_TABLE_OBJECT:
      59           0 :             path = BRIDGE_TABLE_DEV;
      60           0 :             break;
      61             : 
      62           0 :         case VR_MEM_FLOW_TABLE_OBJECT:
      63           0 :             path = FLOW_TABLE_DEV;
      64           0 :             break;
      65             : 
      66           0 :         default:
      67           0 :             snprintf(error_msg, ERROR_LEN, "Error: Invalid 'table' value: %u", table);
      68           0 :             return error_msg;
      69             :         }
      70             : 
      71           0 :         ret = mknod(path, S_IFCHR | O_RDWR, makedev(major, table));
      72           0 :         if (ret && errno != EEXIST) {
      73           0 :             goto fail;
      74             :         }
      75             :     }
      76             : 
      77          13 :     fd = open(path, O_RDONLY | O_SYNC);
      78          13 :     if (fd < 0) {
      79           0 :         goto fail;
      80             :     }
      81             : 
      82          13 :     *mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
      83          13 :     close(fd);
      84             : 
      85          13 :     if (*mem == MAP_FAILED) {
      86           0 :         goto fail;
      87             :     }
      88             : 
      89          13 :     return NULL;
      90             : 
      91           0 : fail:
      92           0 :     snprintf(error_msg, ERROR_LEN, "%s: %s", path, strerror(errno));
      93           0 :     return error_msg;
      94             : }
      95             : 
      96             : const char *
      97           0 : vr_table_unlink(const char *path)
      98             : {
      99             :     enum { ERROR_LEN = 1024 };
     100             :     static char error_msg[ERROR_LEN];
     101             : 
     102           0 :     if (unlink(path) != 0) {
     103           0 :         if (errno != ENOENT) {
     104           0 :             snprintf(error_msg, ERROR_LEN,
     105           0 :                      "Error deleting %s. Error <%d>: %s", path, errno, strerror(errno));
     106           0 :             return error_msg;
     107             :         }
     108             :     }
     109             : 
     110           0 :     return NULL;
     111             : }
     112             : 
     113             : int
     114        2951 : nl_socket(struct nl_client *cl, int domain, int type, int protocol)
     115             : {
     116        2951 :     if (cl->cl_sock >= 0)
     117           0 :         return -EEXIST;
     118             : 
     119        2951 :     cl->cl_sock = socket(domain, type, protocol);
     120        2951 :     if (cl->cl_sock < 0)
     121           0 :         return cl->cl_sock;
     122             : 
     123        2951 :     cl->cl_socket_domain = domain;
     124             : 
     125        2951 :     if (type == SOCK_STREAM) {
     126        2951 :         cl->cl_recvmsg = nl_client_stream_recvmsg;
     127             :     }
     128             :     else {
     129           0 :         cl->cl_recvmsg = nl_client_datagram_recvmsg;
     130             :     }
     131             : 
     132        2951 :     return cl->cl_sock;
     133             : }
     134             : 
     135             : int
     136        2951 : nl_connect(struct nl_client *cl, uint32_t ip, uint16_t port, int group_id)
     137             : {
     138        2951 :     int group = (group_id == 0) ? VROUTER_GENETLINK_VROUTER_GROUP_ID : group_id;
     139             :     int ret;
     140             : 
     141        2951 :     if (cl->cl_socket_domain == AF_NETLINK) {
     142           0 :         struct sockaddr_nl *sa = malloc(sizeof(struct sockaddr_nl));
     143             : 
     144           0 :         if (!sa)
     145           0 :             return -1;
     146             : 
     147           0 :         memset(sa, 0, sizeof(*sa));
     148           0 :         sa->nl_family = cl->cl_socket_domain;
     149           0 :         sa->nl_pid = cl->cl_id;
     150           0 :         cl->cl_sa = (struct sockaddr *)sa;
     151           0 :         cl->cl_sa_len = sizeof(*sa);
     152             : 
     153           0 :         ret = bind(cl->cl_sock, cl->cl_sa, cl->cl_sa_len);
     154           0 :         if (ret < 0) {
     155           0 :             return ret;
     156             :         }
     157             : 
     158             :         /* We join the vrouter netlink broadcast group */
     159           0 :         ret = setsockopt(cl->cl_sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));
     160           0 :         if (ret < 0) {
     161           0 :             return ret;
     162             :         }
     163             : 
     164           0 :         return 0;
     165             :     }
     166             : 
     167        2951 :     if (cl->cl_socket_domain == AF_INET) {
     168             :         struct in_addr address;
     169           0 :         struct sockaddr_in *sa = malloc(sizeof(struct sockaddr_in));
     170           0 :         if (!sa)
     171           0 :             return -1;
     172             : 
     173           0 :         memset(sa, 0, sizeof(*sa));
     174           0 :         address.s_addr = htonl(ip);
     175           0 :         sa->sin_family = cl->cl_socket_domain;
     176           0 :         sa->sin_addr = address;
     177           0 :         sa->sin_port = htons(port);
     178           0 :         cl->cl_sa = (struct sockaddr *)sa;
     179           0 :         cl->cl_sa_len = sizeof(*sa);
     180             : 
     181           0 :         return connect(cl->cl_sock, cl->cl_sa, cl->cl_sa_len);
     182             :     }
     183        2951 :     if (cl->cl_socket_domain == AF_UNIX) {
     184        2951 :         struct sockaddr_un *sa = malloc(sizeof(struct sockaddr_un));
     185        2951 :         if (!sa)
     186           0 :             return -1;
     187             : 
     188        2951 :         memset(sa, 0, sizeof(*sa));
     189        2951 :         sa->sun_family = cl->cl_socket_domain;
     190        2951 :         snprintf(sa->sun_path, sizeof(sa->sun_path), "%s/dpdk_netlink", vr_socket_dir);
     191        2951 :         cl->cl_sa = (struct sockaddr *)sa;
     192        2951 :         cl->cl_sa_len = sizeof(*sa);
     193             : 
     194        2951 :         return connect(cl->cl_sock, cl->cl_sa, cl->cl_sa_len);
     195             :     }
     196           0 :     return 0;
     197             : }
     198             : 
     199             : int
     200           0 : nl_client_datagram_recvmsg(struct nl_client *cl, bool msg_wait)
     201             : {
     202             :     int ret;
     203             :     struct msghdr msg;
     204             :     struct iovec iov;
     205             : 
     206           0 :     memset(&msg, 0, sizeof(msg));
     207           0 :     msg.msg_name = cl->cl_sa;
     208           0 :     msg.msg_namelen = cl->cl_sa_len;
     209             : 
     210           0 :     iov.iov_base = (void *)(cl->cl_buf);
     211           0 :     iov.iov_len = cl->cl_buf_len;
     212           0 :     msg.msg_iov = &iov;
     213           0 :     msg.msg_iovlen = 1;
     214             : 
     215           0 :     cl->cl_buf_offset = 0;
     216             : 
     217           0 :     if (msg_wait)
     218           0 :         ret = recvmsg(cl->cl_sock, &msg, MSG_WAITALL);
     219             :     else
     220           0 :         ret = recvmsg(cl->cl_sock, &msg, MSG_DONTWAIT);
     221           0 :     if (ret < 0) {
     222           0 :         return ret;
     223             :     }
     224             : 
     225           0 :     cl->cl_recv_len = ret;
     226           0 :     if (cl->cl_recv_len > cl->cl_buf_len)
     227           0 :         return -EOPNOTSUPP;
     228             : 
     229           0 :     return ret;
     230             : }
     231             : 
     232             : int
     233        2863 : nl_client_stream_recvmsg(struct nl_client *cl, bool msg_wait) {
     234             :     int ret;
     235             :     struct msghdr msg;
     236             :     struct iovec iov;
     237             : 
     238        2863 :     memset(&msg, 0, sizeof(msg));
     239             : 
     240        2863 :     if (cl->cl_socket_domain != AF_UNIX) {
     241           0 :         msg.msg_name = cl->cl_sa;
     242           0 :         msg.msg_namelen = sizeof(cl->cl_sa_len);
     243             :     }
     244             : 
     245        2863 :     iov.iov_base = (void *)(cl->cl_buf);
     246        2863 :     iov.iov_len = NLMSG_HDRLEN;
     247        2863 :     msg.msg_iov = &iov;
     248        2863 :     msg.msg_iovlen = 1;
     249             : 
     250        2863 :     cl->cl_buf_offset = 0;
     251             : 
     252             :     /* read netlink header and get the lenght of sandesh message */
     253        2863 :     ret = recvmsg(cl->cl_sock, &msg, 0);
     254        2863 :     if (ret < 0) {
     255           0 :         return ret;
     256             :     }
     257        2863 :     struct nlmsghdr *nlh = (struct nlmsghdr *)(cl->cl_buf + cl->cl_buf_offset);
     258        2863 :     uint32_t pending_length = nlh->nlmsg_len - NLMSG_HDRLEN;
     259             : 
     260             :     /* read sandesh message */
     261        2863 :     iov.iov_base = (void *)(cl->cl_buf + NLMSG_HDRLEN);
     262        2863 :     iov.iov_len = pending_length;
     263        2863 :     msg.msg_iov = &iov;
     264        2863 :     msg.msg_iovlen = 1;
     265        2863 :     ret = recvmsg(cl->cl_sock, &msg, 0);
     266        2863 :     if (ret < 0) {
     267           0 :         return ret;
     268             :     }
     269             : 
     270        2863 :     cl->cl_recv_len = nlh->nlmsg_len;
     271        2863 :     if (cl->cl_recv_len > cl->cl_buf_len)
     272           0 :         return -EOPNOTSUPP;
     273             : 
     274        2863 :     return ret;
     275             : }
     276             : 
     277             : int
     278        2862 : nl_sendmsg(struct nl_client *cl)
     279             : {
     280             :     struct msghdr msg;
     281             :     struct iovec iov;
     282             : 
     283        2862 :     memset(&msg, 0, sizeof(msg));
     284             : #if defined (__linux__)
     285        2862 :     if (cl->cl_socket_domain != AF_UNIX) {
     286           0 :         msg.msg_name = cl->cl_sa;
     287           0 :         msg.msg_namelen = cl->cl_sa_len;
     288             :     }
     289             : #endif
     290             : 
     291        2862 :     iov.iov_base = (void *)(cl->cl_buf);
     292        2862 :     iov.iov_len = cl->cl_buf_offset;
     293             : 
     294        2862 :     cl->cl_buf_offset = 0;
     295             : 
     296        2862 :     msg.msg_iov = &iov;
     297        2862 :     msg.msg_iovlen = 1;
     298             : 
     299        2862 :     return sendmsg(cl->cl_sock, &msg, 0);
     300             : }
     301             : 
     302             : void
     303      303133 : nl_free_os_specific(struct nl_client *cl)
     304             : {
     305      303133 :     if (cl->cl_sock >= 0) {
     306        2920 :         close(cl->cl_sock);
     307        2920 :         cl->cl_sock = -1;
     308             :     }
     309             : 
     310      303133 :     cl->cl_sa_len = 0;
     311      303133 :     if (cl->cl_sa) {
     312        2920 :         free(cl->cl_sa);
     313        2920 :         cl->cl_sa = NULL;
     314             :     }
     315      303133 : }
     316             : 
     317             : void
     318      303332 : nl_reset_cl_sock(struct nl_client *cl)
     319             : {
     320      303332 :     cl->cl_sock = -1;
     321      303332 : }
     322             : 
     323             : struct nl_response *
     324           0 : nl_parse_reply_os_specific(struct nl_client *cl)
     325             : {
     326           0 :     struct nlmsghdr *nlh = (struct nlmsghdr *)(cl->cl_buf +
     327           0 :             cl->cl_buf_offset - NLMSG_HDRLEN);
     328           0 :     struct nl_response *resp = &cl->resp;
     329             : 
     330           0 :     if ((nlh->nlmsg_type == RTM_SETDCB) || (nlh->nlmsg_type == RTM_GETDCB)) {
     331           0 :         resp->nl_type = nlh->nlmsg_type;
     332           0 :         resp->nl_data = nl_get_buf_ptr(cl);
     333           0 :         return resp;
     334             :     }
     335             : 
     336           0 :     return NULL;
     337             : }
     338             : 
     339             : #if defined(__linux__)
     340             : int
     341           0 : nl_build_attr_linkinfo(struct nl_client *cl, struct vn_if *ifp)
     342             : {
     343             :     char *link_info_buf;
     344             :     int len;
     345           0 :     struct nlattr *nla = (struct nlattr *)
     346           0 :         ((char *)cl->cl_buf + cl->cl_buf_offset);
     347             : 
     348           0 :     len = NLA_HDRLEN + NLA_HDRLEN +
     349           0 :         NLA_ALIGN(strlen(ifp->if_kind) + 1);
     350             : 
     351           0 :     if (cl->cl_buf_offset + len > cl->cl_buf_len)
     352           0 :         return -ENOMEM;
     353             : 
     354           0 :     nla->nla_len = len;
     355           0 :     nla->nla_type = IFLA_LINKINFO;
     356             : 
     357           0 :     link_info_buf = (char *)nla + NLA_HDRLEN;
     358           0 :     nla = (struct nlattr *)link_info_buf;
     359           0 :     nla->nla_len = len - NLA_HDRLEN;
     360           0 :     nla->nla_type = IFLA_INFO_KIND;
     361             : 
     362           0 :     link_info_buf += NLA_HDRLEN;
     363           0 :     strcpy(link_info_buf, ifp->if_kind);
     364             : 
     365           0 :     cl->cl_buf_offset += len;
     366             : 
     367           0 :     return 0;
     368             : }
     369             : 
     370             : int
     371           0 : nl_build_attr_ifname(struct nl_client *cl, struct vn_if *ifp)
     372             : {
     373             :     char *if_name_buf;
     374             :     int len;
     375           0 :     struct nlattr *nla = (struct nlattr *)
     376           0 :         ((char *)cl->cl_buf + cl->cl_buf_offset);
     377             : 
     378           0 :     len = NLA_HDRLEN + NLA_ALIGN(strlen(ifp->if_name) + 1);
     379           0 :     if (cl->cl_buf_offset + len > cl->cl_buf_len)
     380           0 :         return -ENOMEM;
     381             : 
     382           0 :     nla->nla_len = len;
     383           0 :     nla->nla_type = IFLA_IFNAME;
     384             : 
     385           0 :     if_name_buf = (char *)nla + NLA_HDRLEN;
     386           0 :     strcpy(if_name_buf, ifp->if_name);
     387             : 
     388           0 :     cl->cl_buf_offset += nla->nla_len;
     389             : 
     390           0 :     return 0;
     391             : }
     392             : 
     393             : int
     394           0 : nl_build_mac_address(struct nl_client *cl, struct vn_if *ifp)
     395             : {
     396             :     int len;
     397             :     char *mac_buf;
     398           0 :     struct nlattr *nla = (struct nlattr *)
     399           0 :         ((char *)cl->cl_buf + cl->cl_buf_offset);
     400             : 
     401           0 :     len = NLA_HDRLEN + NLA_ALIGN(6);
     402           0 :     if (cl->cl_buf_offset + len > cl->cl_buf_len)
     403           0 :         return -ENOMEM;
     404             : 
     405           0 :     nla->nla_len = len;
     406           0 :     nla->nla_type = IFLA_ADDRESS;
     407             : 
     408           0 :     mac_buf = (char *)nla + NLA_HDRLEN;
     409           0 :     memcpy(mac_buf, ifp->if_mac, sizeof(ifp->if_mac));
     410             : 
     411           0 :     cl->cl_buf_offset += nla->nla_len;
     412             : 
     413           0 :     return 0;
     414             : }
     415             : 
     416             : 
     417             : int
     418           0 : nl_build_ifinfo(struct nl_client *cl, struct vn_if *ifp)
     419             : {
     420           0 :     struct ifinfomsg *ifi_msg = (struct ifinfomsg *)
     421           0 :         (cl->cl_buf + cl->cl_buf_offset);
     422             : 
     423           0 :     if (cl->cl_buf_offset + NLMSG_ALIGN(sizeof(*ifi_msg)) >
     424           0 :         cl->cl_buf_len)
     425           0 :         return -ENOMEM;
     426             : 
     427           0 :     memset(ifi_msg, 0, sizeof(struct ifinfomsg));
     428           0 :     cl->cl_buf_offset += NLMSG_ALIGN(sizeof(struct ifinfomsg));
     429             : 
     430           0 :     return 0;
     431             : }
     432             : 
     433             : int
     434           0 : nl_build_if_create_msg(struct nl_client *cl, struct vn_if *ifp, uint8_t ack)
     435             : {
     436             :     int ret;
     437             :     uint32_t flags;
     438             : 
     439           0 :     if (!cl->cl_buf || cl->cl_buf_offset || !ifp)
     440           0 :         return -EINVAL;
     441             : 
     442           0 :     flags = NLM_F_REQUEST | NLM_F_CREATE;
     443           0 :     if (ack) {
     444           0 :         flags |= NLM_F_ACK;
     445             :     }
     446           0 :     ret = nl_build_nlh(cl, RTM_NEWLINK, flags);
     447           0 :     if (ret)
     448           0 :         return ret;
     449             : 
     450           0 :     ret = nl_build_ifinfo(cl, ifp);
     451           0 :     if (ret)
     452           0 :         return ret;
     453             : 
     454           0 :     ret = nl_build_mac_address(cl, ifp);
     455           0 :     if (ret)
     456           0 :         return ret;
     457             : 
     458           0 :     ret = nl_build_attr_ifname(cl, ifp);
     459           0 :     if (ret)
     460           0 :         return ret;
     461             : 
     462           0 :     ret = nl_build_attr_linkinfo(cl, ifp);
     463           0 :     if (ret)
     464           0 :         return ret;
     465             : 
     466           0 :     cl->cl_msg_len = cl->cl_buf_offset;
     467           0 :     nl_update_nlh(cl);
     468             : 
     469           0 :     return 0;
     470             : }
     471             : 
     472             : static int
     473           0 : nl_build_attr_dcb_set_all(struct nl_client *cl)
     474             : {
     475             :     uint8_t *dst;
     476           0 :     struct nlattr *nla = (struct nlattr *)nl_get_buf_ptr(cl);
     477             : 
     478           0 :     nla->nla_type = DCB_ATTR_SET_ALL;
     479           0 :     nla->nla_len = NLA_HDRLEN + sizeof(uint8_t);
     480           0 :     dst = (uint8_t *)nla + NLA_HDRLEN;
     481           0 :     *dst = 1;
     482             : 
     483           0 :     cl->cl_buf_offset += NLA_ALIGN(nla->nla_len);
     484             : 
     485           0 :     return 0;
     486             : }
     487             : 
     488             : static int
     489           0 : nl_build_attr_dcb_state(struct nl_client *cl, uint8_t state)
     490             : {
     491             :     uint8_t *dst;
     492           0 :     struct nlattr *attr = (struct nlattr *)nl_get_buf_ptr(cl);
     493             : 
     494           0 :     attr->nla_len = NLA_HDRLEN + NLA_ALIGN(sizeof(state));
     495           0 :     attr->nla_type = DCB_ATTR_STATE;
     496             : 
     497           0 :     dst = nl_get_buf_ptr(cl) + NLA_HDRLEN;
     498           0 :     memcpy(dst, &state, sizeof(state));
     499             : 
     500           0 :     cl->cl_buf_offset += attr->nla_len;
     501           0 :     return 0;
     502             : }
     503             : 
     504             : static int
     505           0 : nl_build_attr_dcb_ifname(struct nl_client *cl, uint8_t *ifname)
     506             : {
     507             :     uint8_t *dst;
     508           0 :     struct nlattr *attr = (struct nlattr *)nl_get_buf_ptr(cl);
     509             : 
     510           0 :     attr->nla_len = NLA_HDRLEN + strlen(ifname) + 1;
     511           0 :     attr->nla_type = DCB_ATTR_IFNAME;
     512             : 
     513           0 :     dst = nl_get_buf_ptr(cl) + NLA_HDRLEN;
     514           0 :     memcpy(dst, ifname, strlen(ifname));
     515           0 :     *(dst + strlen(ifname)) = '\0';
     516             : 
     517           0 :     cl->cl_buf_offset += NLA_ALIGN(attr->nla_len);
     518           0 :     return 0;
     519             : }
     520             : 
     521             : static int
     522           0 : nl_build_attr_set_dcbx(struct nl_client *cl, uint8_t dcbx)
     523             : {
     524             :     uint8_t *dst;
     525           0 :     struct nlattr *nla = (struct nlattr *)nl_get_buf_ptr(cl);
     526             : 
     527           0 :     nla->nla_len = NLA_HDRLEN + NLA_ALIGN(sizeof(uint8_t));
     528           0 :     nla->nla_type = DCB_ATTR_DCBX;
     529             : 
     530           0 :     dst = nl_get_buf_ptr(cl) + NLA_HDRLEN;
     531           0 :     *dst = dcbx;
     532             : 
     533           0 :     cl->cl_buf_offset += nla->nla_len;
     534           0 :     return 0;
     535             : }
     536             : 
     537             : static int
     538           0 : nl_build_attr_dcb_get_pgtx(struct nl_client *cl)
     539             : {
     540           0 :     unsigned int len = 0;
     541           0 :     struct nlattr *nla_p, *nla = (struct nlattr *)nl_get_buf_ptr(cl);
     542             : 
     543           0 :     nla_p = nla;
     544           0 :     nla->nla_len = len = NLA_HDRLEN;
     545           0 :     nla->nla_type = DCB_ATTR_PG_CFG;
     546           0 :     len += nla_p->nla_len;
     547             : 
     548           0 :     nla_p = (struct nlattr *)((uint8_t *)nla_p + nla_p->nla_len);
     549           0 :     nla_p->nla_type = DCB_PG_ATTR_TC_ALL;
     550           0 :     nla_p->nla_len = 2 * NLA_HDRLEN;
     551           0 :     len += nla_p->nla_len;
     552             : 
     553           0 :     nla_p = (struct nlattr *)((uint8_t *)nla_p + NLA_HDRLEN);
     554           0 :     nla_p->nla_type = DCB_TC_ATTR_PARAM_ALL;
     555           0 :     nla_p->nla_len = NLA_HDRLEN;
     556           0 :     len += nla_p->nla_len;
     557             : 
     558           0 :     nla_p = (struct nlattr *)((uint8_t *)nla_p + nla_p->nla_len);
     559           0 :     nla_p->nla_type = DCB_PG_ATTR_BW_ID_ALL;
     560           0 :     nla_p->nla_len = NLA_HDRLEN;
     561           0 :     len += nla_p->nla_len;
     562             : 
     563           0 :     nla->nla_len = len;
     564           0 :     cl->cl_buf_offset += len;
     565             : 
     566           0 :     return 0;
     567             : }
     568             : 
     569             : static int
     570           0 : nl_build_attr_dcb_pgtx(struct nl_client *cl, struct priority *p)
     571             : {
     572             :     uint8_t i, j, map, *dst;
     573           0 :     unsigned int len = 0, tc_attr_len;
     574           0 :     struct nlattr *nla_p, *tcattr, *nla = (struct nlattr *)nl_get_buf_ptr(cl);
     575             : 
     576           0 :     nla_p = nla;
     577           0 :     nla->nla_len = len = NLA_HDRLEN;
     578           0 :     nla->nla_type = DCB_ATTR_PG_CFG;
     579             : 
     580           0 :     nla_p += 1;
     581           0 :     for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
     582           0 :         tcattr = nla_p;
     583           0 :         tcattr->nla_type = i;
     584           0 :         tcattr->nla_len = NLA_HDRLEN;
     585             : 
     586           0 :         tc_attr_len = 0;
     587             : 
     588           0 :         nla_p += 1;
     589           0 :         nla_p->nla_type = DCB_TC_ATTR_PARAM_STRICT_PRIO;
     590           0 :         nla_p->nla_len = NLA_HDRLEN + sizeof(uint8_t);
     591           0 :         dst = (uint8_t *)nla_p + NLA_HDRLEN;
     592           0 :         *dst = (p->tc_strictness & (1 << (i - DCB_PG_ATTR_TC_0)) ? 1 : 0);
     593           0 :         tc_attr_len += NLA_ALIGN(nla_p->nla_len);
     594             : 
     595           0 :         nla_p = (struct nlattr *)((uint8_t *)nla_p + NLA_ALIGN(nla_p->nla_len));
     596           0 :         nla_p->nla_len = NLA_HDRLEN + sizeof(uint8_t);
     597           0 :         nla_p->nla_type = DCB_TC_ATTR_PARAM_PGID;
     598           0 :         dst = (uint8_t *)nla_p + NLA_HDRLEN;
     599           0 :         *dst = p->tc_to_group[i - DCB_PG_ATTR_TC_0];
     600           0 :         tc_attr_len += NLA_ALIGN(nla_p->nla_len);
     601             : 
     602           0 :         if (p->tc_bw_pct[i - DCB_PG_ATTR_TC_0]) {
     603           0 :             nla_p = (struct nlattr *)((uint8_t *)nla_p +
     604           0 :                     NLA_ALIGN(nla_p->nla_len));
     605           0 :             nla_p->nla_len = NLA_HDRLEN + sizeof(uint8_t);
     606           0 :             nla_p->nla_type = DCB_TC_ATTR_PARAM_BW_PCT;
     607           0 :             dst = (uint8_t *)nla_p + NLA_HDRLEN;
     608           0 :             *dst = p->tc_bw_pct[i - DCB_PG_ATTR_TC_0];
     609           0 :             tc_attr_len += NLA_ALIGN(nla_p->nla_len);
     610             :         }
     611             : 
     612           0 :         map = 0;
     613           0 :         for (j = 0; j < sizeof(p->prio_to_tc); j++) {
     614           0 :             if (p->prio_to_tc[j] == (i - DCB_PG_ATTR_TC_0))
     615           0 :                 map |= (1 << j);
     616             :         }
     617             : 
     618           0 :         nla_p = (struct nlattr *)((uint8_t *)nla_p +
     619           0 :                 NLA_ALIGN(nla_p->nla_len));
     620           0 :         nla_p->nla_len = NLA_HDRLEN + sizeof(uint8_t);
     621           0 :         nla_p->nla_type = DCB_TC_ATTR_PARAM_UP_MAPPING;
     622           0 :         dst = (uint8_t *)nla_p + NLA_HDRLEN;
     623           0 :         *dst = map;
     624           0 :         tc_attr_len += NLA_ALIGN(nla_p->nla_len);
     625             : 
     626           0 :         tcattr->nla_len += tc_attr_len;
     627           0 :         len += tcattr->nla_len;
     628           0 :         nla_p = (struct nlattr *)((uint8_t *)nla_p + NLA_ALIGN(nla_p->nla_len));
     629             :     }
     630             : 
     631           0 :     for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
     632           0 :         nla_p->nla_type = i;
     633           0 :         nla_p->nla_len = NLA_HDRLEN + sizeof(uint8_t);
     634           0 :         dst = (uint8_t *)nla_p + NLA_HDRLEN;
     635           0 :         *dst = p->prio_group_bw[i - DCB_PG_ATTR_BW_ID_0];
     636           0 :         len += NLA_ALIGN(nla_p->nla_len);
     637             : 
     638           0 :         nla_p = (struct nlattr *)((uint8_t *)nla_p + NLA_ALIGN(nla_p->nla_len));
     639             :     }
     640             : 
     641           0 :     nla->nla_len = len;
     642           0 :     cl->cl_buf_offset += len;
     643             : 
     644           0 :     return 0;
     645             : }
     646             : 
     647             : static int
     648           0 : nl_build_dcb_msg(struct nl_client *cl, uint8_t cmd)
     649             : {
     650           0 :     struct dcbmsg *dcb = (struct dcbmsg *)nl_get_buf_ptr(cl);
     651             : 
     652           0 :     dcb->cmd = cmd;
     653           0 :     dcb->dcb_family = AF_UNSPEC;
     654           0 :     dcb->dcb_pad = 0;
     655             : 
     656           0 :     cl->cl_buf_offset += sizeof(*dcb);
     657             : 
     658           0 :     return 0;
     659             : }
     660             : 
     661             : static bool
     662           0 : nl_dcb_set_cmd(uint8_t cmd)
     663             : {
     664           0 :     switch (cmd) {
     665           0 :     case DCB_CMD_SSTATE:
     666             :     case DCB_CMD_PGTX_SCFG:
     667             :     case DCB_CMD_SET_ALL:
     668             :     case DCB_CMD_SDCBX:
     669             :     case DCB_CMD_IEEE_SET:
     670           0 :         return true;
     671             : 
     672           0 :     default:
     673           0 :         break;
     674             :     }
     675             : 
     676           0 :     return false;
     677             : }
     678             : 
     679             : static int
     680           0 : nl_build_dcb_nl_msg(struct nl_client *cl, uint8_t *ifname,
     681             :         uint8_t cmd, uint8_t ack)
     682             : {
     683             :     int ret, msgtype;
     684             :     uint32_t flags;
     685             : 
     686           0 :     if (!cl->cl_buf || cl->cl_buf_offset)
     687           0 :         return -EINVAL;
     688             : 
     689           0 :     flags = NLM_F_REQUEST | NLM_F_CREATE;
     690           0 :     if (ack) {
     691           0 :         flags |= NLM_F_ACK;
     692             :     }
     693             : 
     694           0 :     if (nl_dcb_set_cmd(cmd)) {
     695           0 :         msgtype = RTM_SETDCB;
     696             :     } else {
     697           0 :         msgtype = RTM_GETDCB;
     698             :     }
     699             : 
     700           0 :     ret = nl_build_nlh(cl, msgtype, flags);
     701           0 :     if (ret)
     702           0 :         return ret;
     703             : 
     704           0 :     ret = nl_build_dcb_msg(cl, cmd);
     705           0 :     if (ret)
     706           0 :         return ret;
     707             : 
     708           0 :     ret = nl_build_attr_dcb_ifname(cl, ifname);
     709           0 :     if (ret)
     710           0 :         return ret;
     711             : 
     712           0 :     return ret;
     713             : }
     714             : 
     715             : static int
     716           0 : nl_parse_dcb_tc_attr(struct nlattr *nla, void *buf, uint8_t parent_attr_type)
     717             : {
     718             :     int ret;
     719             :     uint8_t byte, j;
     720           0 :     unsigned int processed = 0, nla_len;
     721             : 
     722             :     struct nlattr *nla_p;
     723           0 :     struct priority *p = (struct priority *)buf;
     724             : 
     725           0 :     switch (nla->nla_type) {
     726           0 :     case DCB_TC_ATTR_PARAM_PGID:
     727           0 :         byte = *(uint8_t *)(nla + 1);
     728           0 :         p->tc_to_group[parent_attr_type - DCB_PG_ATTR_TC_0] = byte;
     729           0 :         processed = NLA_ALIGN(NLA_HDRLEN + sizeof(uint8_t));
     730           0 :         break;
     731             : 
     732           0 :     case DCB_TC_ATTR_PARAM_UP_MAPPING:
     733           0 :         byte = *(uint8_t *)(nla + 1);
     734           0 :         if (byte) {
     735           0 :             for (j = 0; j < 8; j++) {
     736           0 :                 if (byte & (1 << j)) {
     737           0 :                     p->prio_to_tc[j] = parent_attr_type - DCB_PG_ATTR_TC_0;
     738             :                 }
     739             :             }
     740             :         }
     741           0 :         processed = NLA_ALIGN(NLA_HDRLEN + sizeof(uint8_t));
     742           0 :         break;
     743             : 
     744           0 :     case DCB_TC_ATTR_PARAM_STRICT_PRIO:
     745           0 :         byte = *(uint8_t *)(nla + 1);
     746           0 :         if (byte)
     747           0 :             p->tc_strictness |= (1 << (parent_attr_type - DCB_PG_ATTR_TC_0));
     748           0 :         processed = NLA_ALIGN(NLA_HDRLEN + sizeof(uint8_t));
     749           0 :         break;
     750             : 
     751           0 :     case DCB_TC_ATTR_PARAM_BW_PCT:
     752           0 :         processed = NLA_ALIGN(NLA_HDRLEN + sizeof(uint8_t));
     753           0 :         break;
     754             : 
     755           0 :     default:
     756           0 :         return -EINVAL;
     757             :     }
     758             : 
     759           0 :     return processed;
     760             : }
     761             : 
     762             : 
     763             : static int
     764           0 : nl_parse_dcb_pg_attr(struct nlattr *nla, void *buf)
     765             : {
     766             :     int ret;
     767             :     uint8_t byte;
     768           0 :     unsigned int processed = 0, nla_len;
     769             : 
     770             :     struct nlattr *nla_p;
     771           0 :     struct priority *p = (struct priority *)buf;
     772             : 
     773           0 :     nla_len = NLA_ALIGN(nla->nla_len);
     774             : 
     775           0 :     switch (nla->nla_type) {
     776           0 :     case DCB_PG_ATTR_TC_0:
     777             :     case DCB_PG_ATTR_TC_1:
     778             :     case DCB_PG_ATTR_TC_2:
     779             :     case DCB_PG_ATTR_TC_3:
     780             :     case DCB_PG_ATTR_TC_4:
     781             :     case DCB_PG_ATTR_TC_5:
     782             :     case DCB_PG_ATTR_TC_6:
     783             :     case DCB_PG_ATTR_TC_7:
     784           0 :         processed = NLA_HDRLEN;
     785           0 :         break;
     786             : 
     787           0 :     case DCB_PG_ATTR_BW_ID_0:
     788             :     case DCB_PG_ATTR_BW_ID_1:
     789             :     case DCB_PG_ATTR_BW_ID_2:
     790             :     case DCB_PG_ATTR_BW_ID_3:
     791             :     case DCB_PG_ATTR_BW_ID_4:
     792             :     case DCB_PG_ATTR_BW_ID_5:
     793             :     case DCB_PG_ATTR_BW_ID_6:
     794             :     case DCB_PG_ATTR_BW_ID_7:
     795           0 :         byte = *(uint8_t *)(nla + 1);
     796           0 :         p->prio_group_bw[nla->nla_type - DCB_PG_ATTR_BW_ID_0] = byte;
     797           0 :         processed = NLA_ALIGN(NLA_HDRLEN + sizeof(uint8_t));
     798           0 :         break;
     799             : 
     800           0 :     default:
     801           0 :         return -EINVAL;
     802             :     }
     803             : 
     804           0 :     nla_len -= NLA_ALIGN(processed);
     805           0 :     while (nla_len) {
     806           0 :         nla_p = (struct nlattr *)((uint8_t *)nla + NLA_ALIGN(processed));
     807           0 :         ret = nl_parse_dcb_tc_attr(nla_p, buf, nla->nla_type);
     808           0 :         if (ret < 0)
     809           0 :             return ret;
     810             : 
     811           0 :         processed += ret;
     812           0 :         nla_len -= NLA_ALIGN(ret);
     813             :     }
     814             : 
     815           0 :     return processed;
     816             : }
     817             : 
     818             : static int
     819           0 : nl_parse_dcb_ieee_attr_ets(struct nlattr *nla, void *buf)
     820             : {
     821             :     uint8_t i;
     822             : 
     823           0 :     struct priority *p = (struct priority *)buf;
     824             :     struct ieee_ets *ets;
     825             : 
     826           0 :     ets = (struct ieee_ets *)(nla + 1);
     827           0 :     memcpy(p->prio_group_bw, ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
     828           0 :     p->tc_strictness = 0;
     829           0 :     for (i = 0; i < 8; i++) {
     830           0 :         if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) {
     831           0 :             p->tc_strictness |= (1 << i);
     832             :         }
     833             :     }
     834             : 
     835           0 :     memcpy(p->prio_to_tc, ets->prio_tc, sizeof(ets->tc_tx_bw));
     836           0 :     for (i = 0; i < 8; i++) {
     837           0 :         p->tc_to_group[i] = i;
     838             :     }
     839             : 
     840           0 :     return nla->nla_len;
     841             : }
     842             : 
     843             : static int
     844           0 : nl_parse_dcb_ieee_attr(struct nlattr *nla, void *buf)
     845             : {
     846             :     int ret;
     847             : 
     848           0 :     switch (nla->nla_type) {
     849           0 :     case DCB_ATTR_IEEE_ETS:
     850           0 :         ret = nl_parse_dcb_ieee_attr_ets(nla, buf);
     851           0 :         break;
     852             : 
     853           0 :     default:
     854           0 :         ret = nla->nla_len;
     855           0 :         break;
     856             :     }
     857             : 
     858           0 :     return ret;
     859             : }
     860             : 
     861             : static int
     862           0 : nla_parse_dcb_ieee_response(struct nlattr *nla, void *buf)
     863             : {
     864             :     int ret;
     865           0 :     unsigned int processed = 0, nla_len;
     866             :     struct nlattr *nla_p;
     867             : 
     868           0 :     if (nla->nla_type != DCB_ATTR_IFNAME)
     869           0 :         return -EINVAL;
     870           0 :     nla_len = NLA_ALIGN(nla->nla_len);
     871             : 
     872           0 :     nla = (struct nlattr *)((uint8_t *)nla + nla_len);
     873           0 :     if (nla->nla_type != DCB_ATTR_IEEE)
     874           0 :         return -EINVAL;
     875           0 :     nla_len = NLA_ALIGN(nla->nla_len);
     876           0 :     processed += NLA_HDRLEN;
     877           0 :     nla_len -= NLA_HDRLEN;
     878             : 
     879           0 :     while (nla_len) {
     880           0 :         nla_p = (struct nlattr *)((uint8_t *)nla + NLA_ALIGN(processed));
     881           0 :         ret = nl_parse_dcb_ieee_attr(nla_p, buf);
     882           0 :         if (ret < 0)
     883           0 :             return ret;
     884             : 
     885           0 :         processed += NLA_ALIGN(ret);
     886           0 :         nla_len -= NLA_ALIGN(ret);
     887             :     }
     888             : 
     889           0 :     return processed;
     890             : }
     891             : 
     892             : static int
     893           0 : nla_parse_dcb_pg_response(struct nlattr *nla, void *buf)
     894             : {
     895             :     int ret;
     896           0 :     unsigned int processed = 0, nla_len;
     897             :     struct nlattr *nla_p;
     898             : 
     899           0 :     nla_len = NLA_ALIGN(nla->nla_len);
     900           0 :     if (!nla_len || (nla->nla_type != DCB_ATTR_PG_CFG))
     901           0 :         return -EINVAL;
     902             : 
     903           0 :     processed = NLA_HDRLEN;
     904           0 :     nla_len -= NLA_ALIGN(processed);
     905             : 
     906           0 :     while (nla_len) {
     907           0 :         nla_p = (struct nlattr *)((uint8_t *)nla + NLA_ALIGN(processed));
     908           0 :         ret = nl_parse_dcb_pg_attr(nla_p, buf);
     909           0 :         if (ret < 0)
     910           0 :             return ret;
     911             : 
     912           0 :         processed += ret;
     913           0 :         nla_len -= NLA_ALIGN(ret);
     914             :     }
     915             : 
     916           0 :     return processed;
     917             : }
     918             : 
     919             : static int
     920           0 : nl_parse_dcb_response(uint8_t *dcbm, uint8_t cmd, uint8_t attr, void *buf)
     921             : {
     922             :     int ret;
     923             :     struct nlattr *nla;
     924           0 :     struct dcbmsg *dcb = (struct dcbmsg *)dcbm;
     925             : 
     926           0 :     if (dcb->cmd != cmd) {
     927           0 :         return -EINVAL;
     928             :     }
     929             : 
     930           0 :     nla = (struct nlattr *)(dcb + 1);
     931           0 :     if (nla->nla_type != attr)
     932           0 :         return -EINVAL;
     933             : 
     934           0 :     if ((nla->nla_type == DCB_ATTR_PG_CFG) &&
     935             :             (cmd == DCB_CMD_PGTX_GCFG)) {
     936           0 :         return nla_parse_dcb_pg_response(nla, buf);
     937           0 :     } else if (cmd == DCB_CMD_IEEE_GET) {
     938           0 :         return nla_parse_dcb_ieee_response(nla, buf);
     939             :     }
     940             : 
     941           0 :     return *((uint8_t *)((uint8_t *)nla + NLA_HDRLEN));
     942             : }
     943             : 
     944             : int
     945           0 : nl_build_set_dcb_state_msg(struct nl_client *cl,
     946             :         uint8_t *ifname, uint8_t state)
     947             : {
     948             :     int ret;
     949             : 
     950           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_SSTATE, 0);
     951           0 :     if (ret)
     952           0 :         return ret;
     953             : 
     954           0 :     ret = nl_build_attr_dcb_state(cl, state);
     955           0 :     if (ret)
     956           0 :         return ret;
     957             : 
     958           0 :     cl->cl_msg_len = cl->cl_buf_offset;
     959           0 :     nl_update_nlh(cl);
     960             : 
     961           0 :     return ret;
     962             : }
     963             : 
     964             : int
     965           0 : nl_build_get_dcb_state_msg(struct nl_client *cl, uint8_t *ifname)
     966             : {
     967             :     int ret;
     968             : 
     969           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_GSTATE, 0);
     970           0 :     if (ret)
     971           0 :         return ret;
     972             : 
     973           0 :     cl->cl_msg_len = cl->cl_buf_offset;
     974           0 :     nl_update_nlh(cl);
     975             : 
     976           0 :     return 0;
     977             : }
     978             : 
     979             : int
     980           0 : nl_build_set_priority_config_msg(struct nl_client *cl, uint8_t *ifname,
     981             :         struct priority *p)
     982             : {
     983             :     int ret;
     984             : 
     985           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_PGTX_SCFG, 0);
     986           0 :     if (ret)
     987           0 :         return ret;
     988             : 
     989           0 :     ret = nl_build_attr_dcb_pgtx(cl, p);
     990           0 :     if (ret)
     991           0 :         return ret;
     992             : 
     993           0 :     cl->cl_msg_len = cl->cl_buf_offset;
     994           0 :     nl_update_nlh(cl);
     995             : 
     996           0 :     return 0;
     997             : }
     998             : 
     999             : int
    1000           0 : nl_build_get_priority_config_msg(struct nl_client *cl, uint8_t *ifname)
    1001             : {
    1002             :     int ret;
    1003             : 
    1004           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_PGTX_GCFG, 0);
    1005           0 :     if (ret)
    1006           0 :         return ret;
    1007             : 
    1008           0 :     ret = nl_build_attr_dcb_get_pgtx(cl);
    1009           0 :     if (ret)
    1010           0 :         return ret;
    1011             : 
    1012           0 :     cl->cl_msg_len = cl->cl_buf_offset;
    1013           0 :     nl_update_nlh(cl);
    1014             : 
    1015           0 :     return 0;
    1016             : }
    1017             : 
    1018             : int
    1019           0 : nl_build_set_dcb_all(struct nl_client *cl, uint8_t *ifname)
    1020             : {
    1021             :     int ret;
    1022             : 
    1023           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_SET_ALL, 0);
    1024           0 :     if (ret)
    1025           0 :         return ret;
    1026             : 
    1027           0 :     ret = nl_build_attr_dcb_set_all(cl);
    1028           0 :     if (ret)
    1029           0 :         return ret;
    1030             : 
    1031           0 :     cl->cl_msg_len = cl->cl_buf_offset;
    1032           0 :     nl_update_nlh(cl);
    1033             : 
    1034           0 :     return 0;
    1035             : }
    1036             : 
    1037             : int
    1038           0 : nl_build_set_dcbx(struct nl_client *cl, uint8_t *ifname,  uint8_t dcbx)
    1039             : {
    1040             :     int ret;
    1041             : 
    1042           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_SDCBX, 0);
    1043           0 :     if (ret)
    1044           0 :         return ret;
    1045             : 
    1046           0 :     ret = nl_build_attr_set_dcbx(cl, dcbx);
    1047           0 :     if (ret)
    1048           0 :         return ret;
    1049             : 
    1050           0 :     cl->cl_msg_len = cl->cl_buf_offset;
    1051           0 :     nl_update_nlh(cl);
    1052             : 
    1053           0 :     return 0;
    1054             : }
    1055             : 
    1056             : int
    1057           0 : nl_build_get_dcbx(struct nl_client *cl, uint8_t *ifname)
    1058             : {
    1059             :     int ret;
    1060             : 
    1061           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_GDCBX, 0);
    1062           0 :     if (ret)
    1063           0 :         return ret;
    1064             : 
    1065           0 :     cl->cl_msg_len = cl->cl_buf_offset;
    1066           0 :     nl_update_nlh(cl);
    1067             : 
    1068           0 :     return 0;
    1069             : }
    1070             : 
    1071             : int
    1072           0 : nl_dcb_parse_reply(struct nl_client *cl, uint8_t cmd, void *resp_buf)
    1073             : {
    1074           0 :     int ret = 0;
    1075           0 :     uint8_t attr = DCB_ATTR_UNDEFINED;
    1076             :     struct nl_response *resp;
    1077             : 
    1078           0 :     resp = nl_parse_reply(cl);
    1079           0 :     if (resp) {
    1080           0 :         if (resp->nl_type == NL_MSG_TYPE_ERROR) {
    1081           0 :             printf("vRouter: DCB %d failed with error %d\n",
    1082             :                     cmd, resp->nl_op);
    1083           0 :             return resp->nl_op;
    1084             :         }
    1085             : 
    1086           0 :         switch (cmd) {
    1087           0 :         case DCB_CMD_SSTATE:
    1088             :         case DCB_CMD_GSTATE:
    1089           0 :             attr = DCB_ATTR_STATE;
    1090           0 :             break;
    1091             : 
    1092           0 :         case DCB_CMD_SDCBX:
    1093             :         case DCB_CMD_GDCBX:
    1094           0 :             attr = DCB_ATTR_DCBX;
    1095           0 :             break;
    1096             : 
    1097           0 :         case DCB_CMD_PGTX_SCFG:
    1098             :         case DCB_CMD_PGTX_GCFG:
    1099           0 :             attr = DCB_ATTR_PG_CFG;
    1100           0 :             break;
    1101             : 
    1102           0 :         case DCB_CMD_IEEE_SET:
    1103           0 :             attr = DCB_ATTR_IEEE;
    1104           0 :             break;
    1105             : 
    1106           0 :         case DCB_CMD_IEEE_GET:
    1107           0 :             attr = DCB_ATTR_IFNAME;
    1108           0 :             break;
    1109             : 
    1110           0 :         default:
    1111           0 :             break;
    1112             :         }
    1113             : 
    1114           0 :         ret = nl_parse_dcb_response((uint8_t *)resp->nl_data, cmd,
    1115             :                 attr, resp_buf);
    1116             :     }
    1117             : 
    1118           0 :     cl->cl_buf_offset = 0;
    1119           0 :     return ret;
    1120             : }
    1121             : 
    1122             : static int
    1123           0 : nl_build_attr_ieee_ets(struct nl_client *cl, struct priority *p)
    1124             : {
    1125             :     unsigned int i;
    1126             : 
    1127             :     struct ieee_ets *ets;
    1128           0 :     struct nlattr *nla_p, *nla = (struct nlattr *)nl_get_buf_ptr(cl);
    1129             : 
    1130           0 :     nla->nla_type = DCB_ATTR_IEEE;
    1131           0 :     nla->nla_len = NLA_HDRLEN;
    1132             : 
    1133           0 :     nla_p = (struct nlattr *)(nla + 1);
    1134           0 :     nla_p->nla_type = DCB_ATTR_IEEE_ETS;
    1135           0 :     nla_p->nla_len = NLA_HDRLEN + sizeof(*ets);
    1136             : 
    1137           0 :     ets = (struct ieee_ets *)(nla_p + 1);
    1138           0 :     memset(ets, 0, sizeof(*ets));
    1139             : 
    1140           0 :     ets->willing = 0;
    1141           0 :     ets->ets_cap = 8;
    1142           0 :     ets->cbs = 0;
    1143             : 
    1144           0 :     memcpy(&ets->tc_tx_bw, &p->prio_group_bw, sizeof(p->prio_group_bw));
    1145           0 :     memcpy(&ets->prio_tc, &p->prio_to_tc, sizeof(p->prio_to_tc));
    1146             : 
    1147           0 :     for (i = 0; i < 8; i++) {
    1148           0 :         if (p->tc_strictness & (1 << i)) {
    1149           0 :             ets->tc_tsa[i] = IEEE_8021QAZ_TSA_STRICT;
    1150             :         } else {
    1151           0 :             ets->tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
    1152             :         }
    1153             :     }
    1154             : 
    1155           0 :     nla->nla_len += NLA_ALIGN(nla_p->nla_len);
    1156           0 :     cl->cl_buf_offset += NLA_ALIGN(nla->nla_len);
    1157             : 
    1158           0 :     return 0;
    1159             : }
    1160             : 
    1161             : int
    1162           0 : nl_build_get_ieee_ets(struct nl_client *cl, uint8_t *ifname,
    1163             :         struct priority *p)
    1164             : {
    1165             :     int ret;
    1166             : 
    1167           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_IEEE_GET, 0);
    1168           0 :     if (ret)
    1169           0 :         return ret;
    1170             : 
    1171           0 :     cl->cl_msg_len = cl->cl_buf_offset;
    1172           0 :     nl_update_nlh(cl);
    1173             : 
    1174           0 :     return 0;
    1175             : }
    1176             : 
    1177             : int
    1178           0 : nl_build_set_ieee_ets(struct nl_client *cl, uint8_t *ifname,
    1179             :         struct priority *p)
    1180             : {
    1181             :     int ret;
    1182             : 
    1183           0 :     ret = nl_build_dcb_nl_msg(cl, ifname, DCB_CMD_IEEE_SET, 0);
    1184           0 :     if (ret)
    1185           0 :         return ret;
    1186             : 
    1187           0 :     ret = nl_build_attr_ieee_ets(cl, p);
    1188           0 :     if (ret < 0)
    1189           0 :         return ret;
    1190             : 
    1191           0 :     cl->cl_msg_len = cl->cl_buf_offset;
    1192           0 :     nl_update_nlh(cl);
    1193             : 
    1194           0 :     return 0;
    1195             : }
    1196             : 
    1197             : 
    1198             : int
    1199           0 : nl_dcb_sendmsg(struct nl_client *cl, uint8_t cmd, void *resp_buf)
    1200             : {
    1201             :     int ret;
    1202             : 
    1203           0 :     ret = nl_sendmsg(cl);
    1204           0 :     if (ret <= 0)
    1205           0 :         return -1;
    1206             : 
    1207           0 :     if ((ret = nl_recvmsg(cl)) > 0) {
    1208           0 :         return nl_dcb_parse_reply(cl, cmd, resp_buf);
    1209             :     }
    1210             : 
    1211           0 :     return ret;
    1212             : }
    1213             : 
    1214             : int
    1215           0 : vrouter_obtain_family_id(struct nl_client *cl)
    1216             : {
    1217             :     int ret;
    1218             :     struct nl_response *resp;
    1219             :     struct genl_ctrl_message *msg;
    1220             : 
    1221           0 :     if (cl->cl_socket_domain != AF_NETLINK) {
    1222           0 :         nl_set_genl_family_id(cl, GENL_ID_VROUTER);
    1223           0 :         return GENL_ID_VROUTER;
    1224             :     }
    1225             : 
    1226           0 :     if ((ret = nl_build_get_family_id(cl, VROUTER_GENETLINK_FAMILY_NAME)))
    1227           0 :         return ret;
    1228             : 
    1229           0 :     if (nl_sendmsg(cl) <= 0)
    1230           0 :         return -errno;
    1231             : 
    1232             :     while (1) {
    1233           0 :         ret = nl_recvmsg(cl);
    1234           0 :         if (ret == EAGAIN)
    1235           0 :             continue;
    1236           0 :         else if (ret > 0)
    1237           0 :             break;
    1238             : 
    1239           0 :         return -errno;
    1240             :     }
    1241             : 
    1242           0 :     resp = nl_parse_reply(cl);
    1243           0 :     if (!resp || resp->nl_type != NL_MSG_TYPE_GEN_CTRL ||
    1244           0 :             resp->nl_op != CTRL_CMD_NEWFAMILY)
    1245           0 :         return -EINVAL;
    1246             : 
    1247           0 :     msg = (struct genl_ctrl_message *)resp->nl_data;
    1248           0 :     nl_set_genl_family_id(cl, msg->family_id);
    1249             : 
    1250           0 :     return cl->cl_genl_family_id;
    1251             : }
    1252             : #endif  /* __linux__ */

Generated by: LCOV version 1.14