Esempio n. 1
0
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;
}
Esempio n. 2
0
/*
 * 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);
}