/* Sends the given 'command' to datapath 'dp', related to the local datapath * numbered 'dp_idx'. If 'arg' is nonnull, adds it to the command as the * datapath or port name attribute depending on the requested operation. * Returns 0 if successful, otherwise a positive errno value. */ static int send_mgmt_command(struct dpif *dp, int dp_idx, int command, const char *arg) { struct ofpbuf request, *reply; int retval; ofpbuf_init(&request, 0); nl_msg_put_genlmsghdr(&request, dp->sock, 32, openflow_family, NLM_F_REQUEST | NLM_F_ACK, command, 1); if (dp_idx != -1) { nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, dp_idx); } if (arg) { if ((command == DP_GENL_C_ADD_DP) || (command == DP_GENL_C_DEL_DP)) { nl_msg_put_string(&request, DP_GENL_A_DP_NAME, arg); } else { nl_msg_put_string(&request, DP_GENL_A_PORTNAME, arg); } } retval = nl_sock_transact(dp->sock, &request, &reply); ofpbuf_uninit(&request); ofpbuf_delete(reply); return retval; }
static int lookup_brc_multicast_group(int *multicast_group) { struct nl_sock *sock; struct ofpbuf request, *reply; struct nlattr *attrs[ARRAY_SIZE(brc_multicast_policy)]; int retval; retval = nl_sock_create(NETLINK_GENERIC, &sock); if (retval) { return retval; } ofpbuf_init(&request, 0); nl_msg_put_genlmsghdr(&request, 0, brc_family, NLM_F_REQUEST, BRC_GENL_C_QUERY_MC, 1); retval = nl_sock_transact(sock, &request, &reply); ofpbuf_uninit(&request); if (retval) { nl_sock_destroy(sock); return retval; } if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN, brc_multicast_policy, attrs, ARRAY_SIZE(brc_multicast_policy))) { nl_sock_destroy(sock); ofpbuf_delete(reply); return EPROTO; } *multicast_group = nl_attr_get_u32(attrs[BRC_GENL_A_MC_GROUP]); nl_sock_destroy(sock); ofpbuf_delete(reply); return 0; }
/* Encapsulates 'msg', which must contain an OpenFlow message, in a Netlink * message, and sends it to the OpenFlow local datapath numbered 'dp_idx' via * 'sock'. * * Returns 0 if successful, otherwise a positive errno value. Returns EAGAIN * if the 'sock' send buffer is full. * * If the send is successful, then the kernel module will receive it, but there * is no guarantee that any reply will not be dropped (see nl_sock_transact() * for details). */ int dpif_send_openflow(struct dpif *dp, int dp_idx, struct ofpbuf *buffer) { struct ofp_header *oh; unsigned int dump_flag; struct ofpbuf hdr; struct nlattr *nla; uint32_t fixed_buffer[64 / 4]; struct iovec iov[3]; int pad_bytes; int n_iov; int retval; /* The reply to OFPT_STATS_REQUEST may be multiple segments long, so we * need to specify NLM_F_DUMP in the request. */ oh = ofpbuf_at_assert(buffer, 0, sizeof *oh); dump_flag = oh->type == OFPT_STATS_REQUEST ? NLM_F_DUMP : 0; ofpbuf_use(&hdr, fixed_buffer, sizeof fixed_buffer); nl_msg_put_genlmsghdr(&hdr, dp->sock, 32, openflow_family, NLM_F_REQUEST | dump_flag, DP_GENL_C_OPENFLOW, 1); nl_msg_put_u32(&hdr, DP_GENL_A_DP_IDX, dp_idx); nla = ofpbuf_put_uninit(&hdr, sizeof *nla); nla->nla_len = sizeof *nla + buffer->size; nla->nla_type = DP_GENL_A_OPENFLOW; pad_bytes = NLA_ALIGN(nla->nla_len) - nla->nla_len; nl_msg_nlmsghdr(&hdr)->nlmsg_len = hdr.size + buffer->size + pad_bytes; n_iov = 2; iov[0].iov_base = hdr.data; iov[0].iov_len = hdr.size; iov[1].iov_base = buffer->data; iov[1].iov_len = buffer->size; if (pad_bytes) { static char zeros[NLA_ALIGNTO]; n_iov++; iov[2].iov_base = zeros; iov[2].iov_len = pad_bytes; } retval = nl_sock_sendv(dp->sock, iov, n_iov, false); if (retval && retval != EAGAIN) { VLOG_WARN_RL(&rl, "dpif_send_openflow: %s", strerror(retval)); } return retval; }
/* Looks up the Netlink multicast group and datapath index of a datapath * by either the datapath index or name. If 'dp_idx' points to a value * of '-1', then 'dp_name' is used to lookup the datapath. If successful, * stores the multicast group in '*multicast_group' and the index in * '*dp_idx' and returns 0. Otherwise, returns a positive errno value. */ static int query_datapath(int *dp_idx, int *multicast_group, const char *dp_name) { struct nl_sock *sock; struct ofpbuf request, *reply; struct nlattr *attrs[ARRAY_SIZE(openflow_multicast_policy)]; int retval; retval = nl_sock_create(NETLINK_GENERIC, 0, 0, 0, &sock); if (retval) { return retval; } ofpbuf_init(&request, 0); nl_msg_put_genlmsghdr(&request, sock, 0, openflow_family, NLM_F_REQUEST, DP_GENL_C_QUERY_DP, 1); if (*dp_idx != -1) { nl_msg_put_u32(&request, DP_GENL_A_DP_IDX, *dp_idx); } if (dp_name) { nl_msg_put_string(&request, DP_GENL_A_DP_NAME, dp_name); } retval = nl_sock_transact(sock, &request, &reply); ofpbuf_uninit(&request); if (retval) { nl_sock_destroy(sock); return retval; } if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN, openflow_multicast_policy, attrs, ARRAY_SIZE(openflow_multicast_policy))) { nl_sock_destroy(sock); ofpbuf_delete(reply); return EPROTO; } *dp_idx = nl_attr_get_u32(attrs[DP_GENL_A_DP_IDX]); *multicast_group = nl_attr_get_u32(attrs[DP_GENL_A_MC_GROUP]); nl_sock_destroy(sock); ofpbuf_delete(reply); return 0; }
static int netdev_windows_netdev_to_ofpbuf(struct netdev_windows_netdev_info *info, struct ofpbuf *buf) { struct ovs_header *ovs_header; int error = EINVAL; nl_msg_put_genlmsghdr(buf, 0, ovs_win_netdev_family, NLM_F_REQUEST | NLM_F_ECHO, info->cmd, OVS_WIN_NETDEV_VERSION); ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header); ovs_header->dp_ifindex = info->dp_ifindex; if (info->name) { nl_msg_put_string(buf, OVS_WIN_NETDEV_ATTR_NAME, info->name); error = 0; } return error; }