int dpdk_netlink_receive(void *usockp, char *nl_buf, unsigned int nl_len) { int ret; struct vr_message request; memset(&request, 0, sizeof(request)); request.vr_message_buf = nl_buf + HDR_LEN; request.vr_message_len = nl_len - HDR_LEN; ret = vr_message_request(&request); if (ret < 0) vr_send_response(ret); dpdk_nl_process_response(usockp, (struct nlmsghdr *)nl_buf); return 0; }
static int uvrouter_agent_rx(void *arg) { int ret; struct sockaddr_in sock_addr; struct msghdr mhdr; struct iovec iov; struct vr_message request, *response; iov.iov_base = uvr_agent_buffer; iov.iov_len = UVR_AGENT_BUFFER_SIZE; bzero(&mhdr, sizeof(mhdr)); mhdr.msg_iov = &iov; mhdr.msg_iovlen = 1; mhdr.msg_name = &sock_addr; mhdr.msg_namelen = sizeof(sock_addr); ret = recvmsg(uvr_agent_fd, &mhdr, MSG_DONTWAIT); if (ret <= 0) return ret; request.vr_message_buf = uvr_agent_buffer; request.vr_message_len = ret; vr_message_request(&request); while ((response = vr_message_dequeue_response())) { iov.iov_base = response->vr_message_buf; iov.iov_len = response->vr_message_len; ret = sendmsg(uvr_agent_fd, &mhdr, 0); vr_message_free(response); if (ret <= 0) break; } return ret; }
int vr_message_make_request(unsigned int object_type, void *object) { char *buf = NULL; int ret; unsigned int len; struct vr_mproto *proto; struct vr_mtransport *trans; struct vr_message request; proto = message_h.vm_proto; trans = message_h.vm_trans; if (!proto || !trans) return 0; len = proto->mproto_buf_len(object_type, object); buf = trans->mtrans_alloc(len); if (!buf) return -ENOMEM; ret = proto->mproto_encode(buf, len, object_type, object, VR_MESSAGE_TYPE_REQUEST); if (ret < 0) goto request_fail; request.vr_message_buf = buf; request.vr_message_len = ret; vr_message_request(&request); request_fail: if (buf) trans->mtrans_free(buf); return ret; }
static int netlink_trans_request(struct sk_buff *in_skb, struct genl_info *info) { char *buf; unsigned int len; uint32_t multi_flag; struct nlmsghdr *rep, *nlh = info->nlhdr; struct genlmsghdr *genlh; struct nlattr **aap = info->attrs; struct nlattr *nla; struct vr_message request, *response; struct sk_buff *skb; uint32_t netlink_id; if (!aap || !(nla = aap[NL_ATTR_VR_MESSAGE_PROTOCOL])) return -EINVAL; request.vr_message_buf = nla_data(nla); request.vr_message_len = nla_len(nla); vr_message_request(&request); #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) netlink_id = NETLINK_CB(in_skb).pid; #else netlink_id = NETLINK_CB(in_skb).portid; #endif multi_flag = 0; while ((response = vr_message_dequeue_response())) { if ((multi_flag == 0) && (!vr_response_queue_empty())) multi_flag = NLM_F_MULTI; buf = response->vr_message_buf; skb = netlink_skb(buf); if (!skb) continue; len = response->vr_message_len; len += GENL_HDRLEN + NLA_HDRLEN; len = NLMSG_ALIGN(len); rep = __nlmsg_put(skb, netlink_id, nlh->nlmsg_seq, nlh->nlmsg_type, len, multi_flag); genlh = nlmsg_data(rep); memcpy(genlh, info->genlhdr, sizeof(*genlh)); nla = (struct nlattr *)((char *)genlh + GENL_HDRLEN); nla->nla_len = response->vr_message_len; nla->nla_type = NL_ATTR_VR_MESSAGE_PROTOCOL; netlink_unicast(in_skb->sk, skb, netlink_id, MSG_DONTWAIT); response->vr_message_buf = NULL; vr_message_free(response); } if (multi_flag) { skb = alloc_skb(NLMSG_HDRLEN, GFP_ATOMIC); if (!skb) return 0; __nlmsg_put(skb, netlink_id, nlh->nlmsg_seq, NLMSG_DONE, 0, 0); netlink_unicast(in_skb->sk, skb, netlink_id, MSG_DONTWAIT); } return 0; }
NTSTATUS KsyncHandleWrite(PKSYNC_DEVICE_CONTEXT ctx, uint8_t *buffer, size_t buffer_size) { struct vr_message request; struct vr_message *response; uint32_t multi_flag; int ret; /* Received buffer contains tightly packed Netlink headers, thus we can just increment appropriate headers */ struct nlmsghdr *nlh = (struct nlmsghdr *)(buffer); struct genlmsghdr *genlh = (struct genlmsghdr *)(nlh + 1); struct nlattr *nla = (struct nlattr *)(genlh + 1); request.vr_message_buf = NLA_DATA(nla); request.vr_message_len = NLA_LEN(nla); ret = vr_message_request(&request); if (ret) { if (vr_send_response(ret)) { return STATUS_INVALID_PARAMETER; } } multi_flag = 0; while ((response = vr_message_dequeue_response())) { if (!multi_flag && !vr_response_queue_empty()) multi_flag = NLM_F_MULTI; char *data = response->vr_message_buf - NETLINK_HEADER_LEN; size_t data_len = NLMSG_ALIGN(response->vr_message_len + NETLINK_HEADER_LEN); struct nlmsghdr *nlh_resp = (struct nlmsghdr *)(data); nlh_resp->nlmsg_len = data_len; nlh_resp->nlmsg_type = nlh->nlmsg_type; nlh_resp->nlmsg_flags = multi_flag; nlh_resp->nlmsg_seq = nlh->nlmsg_seq; nlh_resp->nlmsg_pid = 0; /* 'genlmsghdr' should be put directly after 'nlmsghdr', thus we can just increment previous header pointer */ struct genlmsghdr *genlh_resp = (struct genlmsghdr *)(nlh_resp + 1); WinRawMemCpy(genlh_resp, genlh, sizeof(*genlh_resp)); /* 'nlattr' should be put directly after 'genlmsghdr', thus we can just increment previous header pointer */ struct nlattr *nla_resp = (struct nlattr *)(genlh_resp + 1); nla_resp->nla_len = response->vr_message_len; nla_resp->nla_type = NL_ATTR_VR_MESSAGE_PROTOCOL; PKSYNC_RESPONSE ks_resp = KsyncResponseCreate(); if (ks_resp != NULL) { ks_resp->message_len = data_len; WinRawMemCpy(ks_resp->buffer, data, ks_resp->message_len); KsyncAppendResponse(ctx, ks_resp); } else { return STATUS_INSUFFICIENT_RESOURCES; } vr_message_free(response); } if (multi_flag) { PKSYNC_RESPONSE ks_resp = KsyncResponseCreate(); if (ks_resp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } struct nlmsghdr *nlh_done = (struct nlmsghdr *)ks_resp->buffer; nlh_done->nlmsg_len = NLMSG_HDRLEN; nlh_done->nlmsg_type = NLMSG_DONE; nlh_done->nlmsg_flags = 0; nlh_done->nlmsg_seq = nlh->nlmsg_seq; nlh_done->nlmsg_pid = 0; ks_resp->message_len = NLMSG_HDRLEN; KsyncAppendResponse(ctx, ks_resp); } return STATUS_SUCCESS; }