Beispiel #1
0
WsResult ws_compile_file(WsCompilerPtr compiler, const char *input_name,
                         FILE *input, FILE *output)
{
    WsResult result;
    WsStream *stream;
    unsigned char *bc;
    size_t bc_len;

    /* Initialize the input stream. */
    stream = ws_stream_new_file(input, WS_FALSE, WS_FALSE);
    if (stream == NULL)
        return WS_ERROR_OUT_OF_MEMORY;

    result = compile_stream(compiler, input_name, stream, &bc, &bc_len);

    ws_stream_close(stream);

    if (result == WS_OK) {
        /* Store the result to the file. */
        if (fwrite(bc, 1, bc_len, output) != bc_len)
            result = WS_ERROR_IO;

        ws_bc_data_free(bc);
    }

    return result;
}
Beispiel #2
0
int CFlowStatRuleMgr::add_stream(TrexStream * stream) {
#ifdef __DEBUG_FUNC_ENTRY__
    std::cout << __METHOD_NAME__ << " user id:" << stream->m_rx_check.m_pg_id << std::endl;
    stream_dump(stream);
#endif

    if (! stream->m_rx_check.m_enabled) {
        return 0;
    }

    // Init everything here, and not in the constructor, since we relay on other objects
    // By the time a stream is added everything else is initialized.
    if (! m_api ) {
        create();
    }

    TrexPlatformApi::driver_stat_cap_e rule_type = (TrexPlatformApi::driver_stat_cap_e)stream->m_rx_check.m_rule_type;

    if ((m_cap & rule_type) == 0) {
        throw TrexFStatEx("Interface does not support given rule type", TrexException::T_FLOW_STAT_BAD_RULE_TYPE_FOR_IF);
    }

    // compile_stream throws exception if something goes wrong
    compile_stream(stream, m_parser);

    switch(rule_type) {
    case TrexPlatformApi::IF_STAT_IPV4_ID:
        uint8_t l4_proto;
        if (m_parser->get_l4_proto(l4_proto) < 0) {
            throw TrexFStatEx("Failed determining l4 proto for packet", TrexException::T_FLOW_STAT_FAILED_FIND_L4);
        }

        // throws exception if there is error
        m_user_id_map.add_stream(stream->m_rx_check.m_pg_id, l4_proto);
        break;
    case TrexPlatformApi::IF_STAT_PAYLOAD:
        uint16_t payload_len;
        if (m_parser->get_payload_len(stream->m_pkt.binary, stream->m_pkt.len, payload_len) < 0) {
            throw TrexFStatEx("Failed getting payload len", TrexException::T_FLOW_STAT_BAD_PKT_FORMAT);
        }
        if (payload_len < sizeof(struct flow_stat_payload_header)) {
            throw TrexFStatEx("Need at least " + std::to_string(sizeof(struct latency_header))
                              + " payload bytes for payload rules. Packet only has " + std::to_string(payload_len) + " bytes"
                              , TrexException::T_FLOW_STAT_PAYLOAD_TOO_SHORT);
        }
        m_user_id_map.add_stream(stream->m_rx_check.m_pg_id, PAYLOAD_RULE_PROTO);
        break;
    default:
        throw TrexFStatEx("Wrong rule_type", TrexException::T_FLOW_STAT_BAD_RULE_TYPE);
        break;
    }

    stream->m_rx_check.m_hw_id = HW_ID_FREE;
    return 0;
}
bool 
TrexStreamsCompiler::compile_internal(uint8_t                                port_id,
                                      const std::vector<TrexStream *>        &streams,
                                      std::vector<TrexStreamsCompiledObj *>  &objs,
                                      uint8_t                                dp_core_count,
                                      double                                 factor,
                                      std::string                            *fail_msg) {

#if 0
    for (auto stream : streams) {
        stream->Dump(stdout);
    }
    fprintf(stdout,"------------pre compile \n");
#endif

    GraphNodeMap nodes;


    /* compile checks */
    pre_compile_check(streams, nodes);

    /* check if all are cont. streams */
    bool all_continues = true;
    for (const auto stream : streams) {
        if (stream->get_type() != TrexStream::stCONTINUOUS) {
            all_continues = false;
            break;
        }
    }

    /* allocate objects for all DP cores */
    for (uint8_t i = 0; i < dp_core_count; i++) {
        TrexStreamsCompiledObj *obj = new TrexStreamsCompiledObj(port_id);
        obj->m_all_continues = all_continues;
        objs.push_back(obj);
    }

    /* compile all the streams */
    for (auto stream : streams) {

        /* skip non-enabled streams */
        if (!stream->m_enabled) {
            continue;
        }
     
        /* compile a single stream to all cores */
        compile_stream(stream, factor, dp_core_count, objs, nodes);
    }

    return true;
}
Beispiel #4
0
WsResult ws_compile_data(WsCompilerPtr compiler, const char *input_name,
                         const unsigned char *input, size_t input_len,
                         unsigned char **output_return,
                         size_t *output_len_return)
{
    WsResult result;
    WsStream *stream;

    /* Initialize the input stream. */
    stream = ws_stream_new_data_input(input, input_len);
    if (stream == NULL)
        return WS_ERROR_OUT_OF_MEMORY;

    result = compile_stream(compiler, input_name, stream, output_return,
                            output_len_return);

    ws_stream_close(stream);

    return result;
}
Beispiel #5
0
// called on all streams, when stream start to transmit
// If stream need flow stat counting, make sure the type of packet is supported, and
// embed needed info in packet.
// If stream does not need flow stat counting, make sure it does not interfere with
// other streams that do need stat counting.
// Might change the IP ID of the stream packet
int CFlowStatRuleMgr::start_stream(TrexStream * stream) {
#ifdef __DEBUG_FUNC_ENTRY__
    std::cout << __METHOD_NAME__ << " user id:" << stream->m_rx_check.m_pg_id << std::endl;
    stream_dump(stream);
#endif

    int ret;
    // Streams which does not need statistics might be started, before any stream that do
    // need statistcs, so start_stream might be called before add_stream
    if (! m_api ) {
        create();
    }

    // first handle streams that do not need rx stat
    if (! stream->m_rx_check.m_enabled) {
        try {
            compile_stream(stream, m_parser);
        } catch (TrexFStatEx) {
            // If no statistics needed, and we can't parse the stream, that's OK.
            return 0;
        }

        uint16_t ip_id;
        if (m_parser->get_ip_id(ip_id) < 0) {
            return 0; // if we could not find the ip id, no need to fix
        }
        // verify no reserved IP_ID used, and change if needed
        if (ip_id >= IP_ID_RESERVE_BASE) {
            if (m_parser->set_ip_id(ip_id & 0xefff) < 0) {
                throw TrexFStatEx("Stream IP ID in reserved range. Failed changing it"
                                  , TrexException::T_FLOW_STAT_FAILED_CHANGE_IP_ID);
            }
        }
        return 0;
    }

    // from here, we know the stream need rx stat

    // Starting a stream which was never added
    if (stream->m_rx_check.m_hw_id == HW_ID_INIT) {
        add_stream(stream);
    }

    if (stream->m_rx_check.m_hw_id < MAX_FLOW_STATS + MAX_FLOW_STATS_PAYLOAD) {
        throw TrexFStatEx("Starting a stream which was already started"
                          , TrexException::T_FLOW_STAT_ALREADY_STARTED);
    }

    TrexPlatformApi::driver_stat_cap_e rule_type = (TrexPlatformApi::driver_stat_cap_e)stream->m_rx_check.m_rule_type;

    if ((m_cap & rule_type) == 0) {
        throw TrexFStatEx("Interface does not support given rule type", TrexException::T_FLOW_STAT_BAD_RULE_TYPE_FOR_IF);
    }

    // compile_stream throws exception if something goes wrong
    if ((ret = compile_stream(stream, m_parser)) < 0)
        return ret;

    uint16_t hw_id;

    switch(rule_type) {
    case TrexPlatformApi::IF_STAT_IPV4_ID:
        break;
    case TrexPlatformApi::IF_STAT_PAYLOAD:
        break;
    default:
        throw TrexFStatEx("Wrong rule_type", TrexException::T_FLOW_STAT_BAD_RULE_TYPE);
        break;
    }

    if (m_user_id_map.is_started(stream->m_rx_check.m_pg_id)) {
        m_user_id_map.start_stream(stream->m_rx_check.m_pg_id); // just increase ref count;
        hw_id = m_user_id_map.get_hw_id(stream->m_rx_check.m_pg_id); // can't fail if we got here
    } else {
        if (rule_type == TrexPlatformApi::IF_STAT_IPV4_ID) {
            hw_id = m_hw_id_map.find_free_hw_id();
        } else {
            hw_id = m_hw_id_map_payload.find_free_hw_id();
        }
        if (hw_id == HW_ID_FREE) {
            throw TrexFStatEx("Failed allocating statistic counter. Probably all are used for this rule type."
                              , TrexException::T_FLOW_STAT_NO_FREE_HW_ID);
        } else {
            uint32_t user_id = stream->m_rx_check.m_pg_id;
            m_user_id_map.start_stream(user_id, hw_id);
            if (rule_type == TrexPlatformApi::IF_STAT_IPV4_ID) {
                if (hw_id > m_max_hw_id) {
                    m_max_hw_id = hw_id;
                }
                m_hw_id_map.map(hw_id, user_id);
                add_hw_rule(hw_id, m_user_id_map.l4_proto(user_id));
            } else {
                if (hw_id > m_max_hw_id_payload) {
                    m_max_hw_id_payload = hw_id;
                }
                m_hw_id_map_payload.map(hw_id, user_id);
            }
            // clear hardware counters. Just in case we have garbage from previous iteration
            rx_per_flow_t rx_cntr;
            tx_per_flow_t tx_cntr;
            rfc2544_info_t rfc2544_info;
            for (uint8_t port = 0; port < m_num_ports; port++) {
                m_api->get_flow_stats(port, &rx_cntr, (void *)&tx_cntr, hw_id, hw_id, true, rule_type);
            }
            if (rule_type == TrexPlatformApi::IF_STAT_PAYLOAD) {
                m_api->get_rfc2544_info(&rfc2544_info, hw_id, hw_id, true);
            }
        }
    }

    // saving given hw_id on stream for use by tx statistics count
    if (rule_type == TrexPlatformApi::IF_STAT_IPV4_ID) {
        m_parser->set_ip_id(IP_ID_RESERVE_BASE + hw_id);
        stream->m_rx_check.m_hw_id = hw_id;
    } else {
        struct flow_stat_payload_header *fsp_head = (struct flow_stat_payload_header *)
            (stream->m_pkt.binary + stream->m_pkt.len - sizeof(struct flow_stat_payload_header));
        fsp_head->hw_id = hw_id;
        fsp_head->magic = FLOW_STAT_PAYLOAD_MAGIC;
        m_parser->set_ip_id(FLOW_STAT_PAYLOAD_IP_ID);
        // for payload rules, we use the range right after ip id rules
        stream->m_rx_check.m_hw_id = hw_id + MAX_FLOW_STATS;
    }

#ifdef __DEBUG_FUNC_ENTRY__
    std::cout << "exit:" << __METHOD_NAME__ << " hw_id:" << hw_id << std::endl;
    stream_dump(stream);
#endif

    if (m_num_started_streams == 0) {
        send_start_stop_msg_to_rx(true); // First transmitting stream. Rx core should start reading packets;

        // wait to make sure that message is acknowledged. RX core might be in deep sleep mode, and we want to
        // start transmitting packets only after it is working, otherwise, packets will get lost.
        if (m_rx_core) { // in simulation, m_rx_core will be NULL
            int count = 0;
            while (!m_rx_core->is_working()) {
                delay(1);
                count++;
                if (count == 100) {
                    throw TrexFStatEx("Critical error!! - RX core failed to start", TrexException::T_FLOW_STAT_RX_CORE_START_FAIL);
                }
            }
        }
    } else {
        // make sure rx core is working. If not, we got really confused somehow.
        if (m_rx_core)
            assert(m_rx_core->is_working());
    }
    m_num_started_streams++;
    return 0;
}