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-11-09 02:10:49 Functions: 7 44 15.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14