/* 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;
}
Exemple #2
0
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;
}
Exemple #5
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;
}