コード例 #1
0
ファイル: vport.c プロジェクト: Sovietaced/ivs
indigo_error_t
indigo_port_stats_get(
    of_port_stats_request_t *port_stats_request,
    of_port_stats_reply_t **port_stats_reply_ptr)
{
    of_port_no_t req_of_port_num;
    of_port_stats_reply_t *port_stats_reply;
    indigo_error_t err = INDIGO_ERROR_NONE;

    port_stats_reply = of_port_stats_reply_new(port_stats_request->version);
    if (port_stats_reply == NULL) {
        err = INDIGO_ERROR_RESOURCE;
        goto out;
    }

    of_list_port_stats_entry_t list;
    of_port_stats_reply_entries_bind(port_stats_reply, &list);

    of_port_stats_request_port_no_get(port_stats_request, &req_of_port_num);
    int dump_all = req_of_port_num == OF_PORT_DEST_NONE_BY_VERSION(port_stats_request->version);

    /* Refresh statistics */
    nl_cache_refill(route_cache_sock, link_cache);

    struct nl_msg *msg = ind_ovs_create_nlmsg(ovs_vport_family, OVS_VPORT_CMD_GET);
    if (dump_all) {
        nlmsg_hdr(msg)->nlmsg_flags |= NLM_F_DUMP;
    } else {
        nla_put_u32(msg, OVS_VPORT_ATTR_PORT_NO, req_of_port_num);
    }

    /* Ask kernel to send us one or more OVS_VPORT_CMD_NEW messages */
    if (nl_send_auto(ind_ovs_socket, msg) < 0) {
        err = INDIGO_ERROR_UNKNOWN;
        goto out;
    }
    ind_ovs_nlmsg_freelist_free(msg);

    /* Handle OVS_VPORT_CMD_NEW messages */
    nl_cb_set(netlink_callbacks, NL_CB_VALID, NL_CB_CUSTOM,
              port_stats_iterator, &list);
    if (nl_recvmsgs(ind_ovs_socket, netlink_callbacks) < 0) {
        err = INDIGO_ERROR_UNKNOWN;
        goto out;
    }

out:
    if (err != INDIGO_ERROR_NONE) {
        of_port_stats_reply_delete(port_stats_reply);
        port_stats_reply = NULL;
    }

    *port_stats_reply_ptr = port_stats_reply;
    return err;
}
コード例 #2
0
ファイル: vport.c プロジェクト: Sovietaced/ivs
/*
 * ind_ovs_port_deleted will free the port struct.
 */
indigo_error_t indigo_port_interface_remove(
    indigo_port_name_t port_name)
{
    struct ind_ovs_port *port = ind_ovs_port_lookup_by_name(port_name);
    if (port == NULL) {
        return INDIGO_ERROR_NOT_FOUND;
    }

    struct nl_msg *msg = ind_ovs_create_nlmsg(ovs_vport_family, OVS_VPORT_CMD_DEL);
    nla_put_u32(msg, OVS_VPORT_ATTR_PORT_NO, port->dp_port_no);
    return ind_ovs_transact(msg);
}
コード例 #3
0
ファイル: vport.c プロジェクト: Sovietaced/ivs
/*
 * This function just asks the datapath to add the port. If that succeeds we'll
 * get a OVS_VPORT_CMD_NEW multicast message. At that point ind_ovs_port_added
 * will create our own representation of the port. This is to support using
 * ovs-dpctl to add and remove ports.
 */
indigo_error_t indigo_port_interface_add(
    indigo_port_name_t port_name,
    of_port_no_t of_port,
    indigo_port_config_t *config)
{
    assert(of_port < IND_OVS_MAX_PORTS);
    assert(strlen(port_name) < 256);

    struct nl_msg *msg = ind_ovs_create_nlmsg(ovs_vport_family, OVS_VPORT_CMD_NEW);
    nla_put_u32(msg, OVS_VPORT_ATTR_TYPE, OVS_VPORT_TYPE_NETDEV);
    nla_put_string(msg, OVS_VPORT_ATTR_NAME, port_name);
    nla_put_u32(msg, OVS_VPORT_ATTR_PORT_NO, of_port);
    nla_put_u32(msg, OVS_VPORT_ATTR_UPCALL_PID, 0);
    return ind_ovs_transact(msg);
}
コード例 #4
0
ファイル: upcall.c プロジェクト: iHiroakiKawai/ivs
/*
 * See the OF_PORT_DEST_USE_TABLE comment in ind_ovs_translate_actions.
 * This is mostly the same as ind_ovs_handle_packet_miss but does
 * not reuse the original message for the execute command since
 * the incoming message has a userdata attribute.
 * It also doesn't install a kflow or update flow stats.
 */
static void
ind_ovs_handle_packet_table(struct ind_ovs_upcall_thread *thread,
                            struct ind_ovs_port *port,
                            struct nl_msg *msg, struct nlattr **attrs)
{
    struct nlattr *key = attrs[OVS_PACKET_ATTR_KEY];
    struct nlattr *packet = attrs[OVS_PACKET_ATTR_PACKET];
    assert(key && packet);

    struct ind_ovs_parsed_key pkey;
    ind_ovs_parse_key(key, &pkey);

    /* Lookup the flow in the userspace flowtable. */
    struct ind_ovs_flow *flow;
    if (ind_ovs_lookup_flow(&pkey, &flow) != 0) {
        ind_ovs_upcall_request_pktin(pkey.in_port, port, packet, key, OF_PACKET_IN_REASON_NO_MATCH);
        return;
    }

    /* Send OVS_PACKET_CMD_EXECUTE. */
    /* TODO ensure the message is large enough */
    struct nl_msg *reply = ind_ovs_create_nlmsg(ovs_packet_family,
                                                OVS_PACKET_CMD_EXECUTE);

    ind_ovs_translate_actions(&pkey, flow->of_list_action,
                              reply, OVS_PACKET_ATTR_ACTIONS);

    nla_put(reply, OVS_PACKET_ATTR_KEY, nla_len(key), nla_data(key));
    nla_put(reply, OVS_PACKET_ATTR_PACKET, nla_len(packet), nla_data(packet));

    struct nlattr *actions = nlmsg_find_attr(nlmsg_hdr(reply),
        sizeof(struct genlmsghdr) + sizeof(struct ovs_header),
        OVS_PACKET_ATTR_ACTIONS);

    /* Don't send the packet back out if it would be dropped. */
    if (nla_len(actions) > 0) {
        nl_send_auto(port->notify_socket, reply);
    }

    ind_ovs_nlmsg_freelist_free(reply);
}
コード例 #5
0
ファイル: vport.c プロジェクト: Sovietaced/ivs
void
ind_ovs_port_added(uint32_t port_no, const char *ifname, of_mac_addr_t mac_addr)
{
    indigo_error_t err;

    if (ind_ovs_ports[port_no]) {
        return;
    }

    struct ind_ovs_port *port = calloc(1, sizeof(*port));
    if (port == NULL) {
        LOG_ERROR("failed to allocate port");
        return;
    }

    strncpy(port->ifname, ifname, sizeof(port->ifname));
    port->dp_port_no = port_no;
    port->mac_addr = mac_addr;
    aim_ratelimiter_init(&port->upcall_log_limiter, 1000*1000, 5, NULL);
    aim_ratelimiter_init(&port->pktin_limiter, PORT_PKTIN_INTERVAL, PORT_PKTIN_BURST_SIZE, NULL);
    pthread_mutex_init(&port->quiesce_lock, NULL);
    pthread_cond_init(&port->quiesce_cvar, NULL);

    port->notify_socket = ind_ovs_create_nlsock();
    if (port->notify_socket == NULL) {
        goto cleanup_port;
    }

    if (nl_socket_set_nonblocking(port->notify_socket) < 0) {
        LOG_ERROR("failed to set netlink socket nonblocking");
        goto cleanup_port;
    }

    struct nl_msg *msg = ind_ovs_create_nlmsg(ovs_vport_family, OVS_VPORT_CMD_SET);
    nla_put_u32(msg, OVS_VPORT_ATTR_PORT_NO, port_no);
    nla_put_u32(msg, OVS_VPORT_ATTR_UPCALL_PID,
                nl_socket_get_local_port(port->notify_socket));
    err = ind_ovs_transact(msg);
    if (err < 0) {
        LOG_ERROR("datapath failed to configure port %s", ifname);
        goto cleanup_port;
    }

    if (!ind_ovs_get_interface_flags(ifname, &port->ifflags)) {
        /* Bring interface up if not already */
        if (!(port->ifflags & IFF_UP)) {
            port->ifflags |= IFF_UP;
            (void) ind_ovs_set_interface_flags(ifname, port->ifflags);
        }
    } else {
        /* Not a netdev, fake the interface flags */
        port->ifflags = IFF_UP;
    }

    /* Ensure port is fully populated before publishing it. */
    __sync_synchronize();

    ind_ovs_ports[port_no] = port;

    if ((err = port_status_notify(port_no, OF_PORT_CHANGE_REASON_ADD)) < 0) {
        LOG_WARN("failed to notify controller of port addition");
        /* Can't cleanup the port because it's already visible to other
         * threads. */
    }

    ind_ovs_upcall_register(port);
    LOG_INFO("Added port %s", port->ifname);
    ind_ovs_kflow_invalidate_all();
    return;

cleanup_port:
    assert(ind_ovs_ports[port_no] == NULL);
    if (port->notify_socket) {
        nl_socket_free(port->notify_socket);
    }
    free(port);
}