Exemple #1
0
static ucli_status_t
ppe_ucli_utm__format__(ucli_context_t* uc)
{
    ppe_header_t header; 

    UCLI_COMMAND_INFO(uc, 
                      "format", 1, 
                      "Change the format of the current packet.");

    UCLI_ARGPARSE_OR_RETURN(uc, "{ppe_header}", &header); 
    if(header == PPE_HEADER_8021Q || header == PPE_HEADER_ETHERII) {
        int rv; 
        rv = ppe_packet_format_set(&ppec->ppep, header); 
        if(rv < 0) {
            return ucli_error(uc, "packet format conversion failed."); 
        }
        if(rv == 1) { 
            aim_free(ppec->ppep._data); 
        }
    }
    else {
        return ucli_error(uc, "%{ppe_header} is not a valid conversion.", 
                          header); 
    }
    return UCLI_STATUS_OK; 
}
Exemple #2
0
static ucli_status_t
ppe_ucli_utm__checkw__(ucli_context_t* uc)
{
    ppe_field_info_t* fi; 
    uint8_t* cvalue; 
    uint8_t pvalue[128];
    unsigned int csize; 

    aim_datatype_map_t* operation; 
    aim_datatype_map_t operation_map[] = { 
        { "==", 'e' }, { "!=", 'n' }, { NULL } 
    }; 

    UCLI_COMMAND_INFO(uc, 
                      "checkw", 3, 
                      "Check wide packet field values and status.");
    
    UCLI_ARGPARSE_OR_RETURN(uc, "{ppe_field_info}{map}{data}", &fi, 
                            &operation, operation_map, "operation", 
                            &cvalue, &csize); 

    PPE_FIELD_EXISTS_OR_RETURN(uc, fi->field); 
    
    if(fi->size_bits/8 != csize) { 
        return ucli_error(uc, 
                          "field %{ppe_field} is %d bytes wide.", fi->field, 
                          fi->size_bits/8);
    }

    PPE_WIDE_FIELD_GET_OR_RETURN(uc, &ppec->ppep, fi->field, pvalue); 
    
    switch(operation->i) 
        {
        case 'e':
            {
                if(PPE_MEMCMP(pvalue, cvalue, csize)) { 
                    return ucli_error(uc, 
                                      "field %{ppe_field} is %{data} (should be %{data}", 
                                      fi->field, pvalue, csize, cvalue, csize); 
                }
                return UCLI_STATUS_OK; 
                break; 
            }
        case 'n':
            {
                if(!PPE_MEMCMP(pvalue, cvalue, csize)) { 
                    return ucli_error(uc, 
                                      "field %{ppe_field} is %{data}", 
                                      fi->field, pvalue, csize); 
                }
                return UCLI_STATUS_OK; 
                break; 
            }
        default:
            return ucli_e_internal(uc, "unknown operation."); 
        }
}
Exemple #3
0
static ucli_status_t
ppe_ucli_utm__check__(ucli_context_t* uc)
{
    ppe_field_info_t* fi; 
    uint32_t cvalue; 
    uint32_t pvalue; 

    aim_datatype_map_t* operation; 
    aim_datatype_map_t operation_map[] = { 
        { "==", 'e' }, { "!=", 'n' }, { NULL } 
    }; 

    UCLI_COMMAND_INFO(uc, 
                      "check", 3, 
                      "Check packet field values and status.");
    
    UCLI_ARGPARSE_OR_RETURN(uc, "{ppe_field_info}{map}i", &fi, 
                            &operation, operation_map, "operation", 
                            &cvalue); 

    PPE_FIELD_EXISTS_OR_RETURN(uc, fi->field); 
    PPE_FIELD32_OR_RETURN(uc, fi->size_bits); 
    PPE_FIELD_GET_OR_RETURN(uc, &ppec->ppep, fi->field, &pvalue); 
    
    switch(operation->i) 
        {
        case 'e':
            {
                if(pvalue != cvalue) {
                    return ucli_error(uc, 
                                      "field %{ppe_field} is 0x%x (%d) (should be 0x%x (%d)", 
                                      fi->field, pvalue, pvalue, cvalue, cvalue); 
                }
                return UCLI_STATUS_OK; 
                break; 
            }
        case 'n':
            {
                if(pvalue == cvalue) {
                    return ucli_error(uc, 
                                      "field %{ppe_field} is 0x%x (%d)", 
                                      fi->field, pvalue, pvalue); 
                }
                return UCLI_STATUS_OK; 
                break; 
            }
        default:
            return ucli_e_internal(uc, "unknown operation."); 
        }
}
Exemple #4
0
static ucli_status_t
fme_ucli_utm__key__(ucli_context_t* uc)
{
    uint32_t keymask;
    uint8_t* value = NULL;
    int value_size = 0;
    uint8_t* mask = NULL;
    int mask_size = 0;
    int rv = UCLI_STATUS_OK;
    fme_key_t key;

    UCLI_COMMAND_INFO(uc,
                      "key",  3,
                      "Set the match key for the current entry.");


    UCLI_ARGPARSE_OR_RETURN(uc, "i{data}{data}", &keymask, &value, &value_size,
                            &mask, &mask_size);

    if(value_size != mask_size) {
        rv = ucli_error(uc, "value size (%d) and mask size (%d) must be equal.",
                        value_size, mask_size);
        goto __key__error;
    }
    if(value_size % 4 != 0) {
        rv = ucli_error(uc, "values and masks must be 32bit aligned (size=%d)",
                        value_size);
        goto __key__error;
    }


    FME_MEMSET(&key, 0, sizeof(key));
    key.keymask = keymask;
    key.size = value_size;
    FME_MEMCPY(key.values, value, value_size);
    FME_MEMCPY(key.masks, mask, mask_size);
    aim_free(value);
    aim_free(mask);
    fme_entry_key_set(fmec->entries[fmec->eid], &key);

    return rv;

 __key__error:

    aim_free(value);
    aim_free(mask);

    return rv;
}
Exemple #5
0
ucli_status_t
vt_ucli_module__echo__(ucli_context_t* uc)
{
    UCLI_COMMAND_INFO(uc,
                      "echo", 2,
                      "$summary#Send a VPI echo request."
                      "$args#<vpi_spec> <data>");


    UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{idata}",
                            &vtc->vpi, vtc->data, &vtc->size);
    ucli_printf(uc, "sending echo request.\n");
    if(vpi_ioctl(vtc->vpi, VPI_PROTOCOL_OPCODE_ECHO, vtc->data, vtc->size) < 0) {
        return ucli_error(uc, "vpi_ioctl() failed.");
    }

    ucli_printf(uc, "waiting for response.\n");
    memset(vtc->data, 0, sizeof(vtc->data));
    if(vpi_recv__(uc, vtc) > 0) {
        ucli_printf(uc, "recv(%{vpi}):\n%{data}",
                    vtc->vpi, vtc->data, vtc->size);
        return UCLI_STATUS_OK;
    }
    else {
        return UCLI_STATUS_E_ERROR;
    }
}
Exemple #6
0
static int
ucli_vargparse_type__(ucli_context_t* uc,
                      char c, char* type, const char* arg,
                      aim_va_list_t* vargs)
{
    int rv;
    aim_datatype_t* dt;

    if(arg == NULL) {
        return UCLI_STATUS_E_ARG;
    }

    if(type && type[0] == '%') {
        /* Immediate string specified. The argument must be that string. */
        if(type[1] == 0) {
            /* No string */
            return UCLI_STATUS_E_INTERNAL;
        }
        if(!UCLI_STRCMP(type+1, arg)) {
            return UCLI_STATUS_OK;
        }
        ucli_error(uc, "expected '%s', not '%s'", type+1, arg);
        return UCLI_STATUS_E_ARG;
    }

    dt = aim_datatype_find(c, type);
    if(dt == NULL) {
        /* Unrecognized type */
        ucli_error(uc, "<bug: no handler for type '%c:%s'>", (c) ? c : '.', (type) ? type : "[NULL]");
        AIM_LOG_ERROR("bug: no handler for type '%c:%s'", (c) ? c : '.', (type) ? type : "[NULL]");
        return UCLI_STATUS_E_INTERNAL;
    }

    {
        aim_datatype_context_t dtc;
        dtc.dt = dt;
        dtc.epvs = &uc->pvs;
        rv = dt->from_str(&dtc, arg, vargs);
    }


    if( (rv < 0) && dt->desc) {
        ucli_e_arg(uc, arg, dt->desc);
    }
    return rv;
}
Exemple #7
0
static ucli_status_t
ppe_ucli_utm__chm__(ucli_context_t* uc)
{
    ppe_header_t header; 
    int bool; 

    UCLI_COMMAND_INFO(uc, 
                      "chm", 2, 
                      "Check the header mask."); 

    UCLI_ARGPARSE_OR_RETURN(uc, "{ppe_header}{bool}", &header, &bool); 
    if(bool && !(ppec->ppep.header_mask & (1 << header))) {
        return ucli_error(uc, "header bit %{ppe_header} is 0.", header); 
    }
    if(!bool && (ppec->ppep.header_mask & (1 << header))) { 
        return ucli_error(uc, "header bit %{ppe_header} is 1.", header); 
    }
    return UCLI_STATUS_OK; 
}
Exemple #8
0
ucli_status_t
vt_ucli_module__send__(ucli_context_t* uc)
{
    UCLI_COMMAND_INFO(uc,
                      "send", 2,
                      "$summary#Send a single packet on the given VPI."
                      "$args#<vpi_spec> <packet_data>");

    UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{idata}", &vtc->vpi, vtc->data, &vtc->size);
    if(vpi_send(vtc->vpi, vtc->data, vtc->size) < 0) {
        return ucli_error(uc, "vpi_send() failed.");
    }
    return UCLI_STATUS_OK;
}
Exemple #9
0
ucli_status_t
vt_ucli_module__bridge__(ucli_context_t* uc)
{
    vpi_t v1, v2;
    vpi_bridge_t vbridge;

    UCLI_COMMAND_INFO(uc,
                      "bridge", 2,
                      "$summary#Forward all packets between two VPI interfaces."
                      "$args#<vpi_spec_1> <vpi_spec_2>");

    UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{vpi}", &v1, &v2);
    vbridge = vpi_bridge_create(v1, v2);
    if(vbridge == NULL) {
        return ucli_error(uc, "vpi_bridge_create(%{vpi},%{vpi}) failed.",
                          v1, v2);
    }
    if(vpi_bridge_start(vbridge) < 0) {
        return ucli_error(uc, "vpi_bridge_start() failed.");
    }
    vtc->bridges++;
    ucli_printf(uc, "bridging %s <-> %s\n", vpi_name_get(v1), vpi_name_get(v2));
    return UCLI_STATUS_OK;
}
Exemple #10
0
static inline int
field_required__(ucli_context_t* uc, ppe_field_t f)
{
    AIM_VAR_PCAST_SAFE(ppe_utm_ctrl_t*, ppec, uc, uc->cookie); 

    int e = ppe_field_exists(&ppec->ppep, f); 
    if(e == 1) {
        return 0; 
    }
    else if(e == 0) {
        return ucli_error(uc, "field %{ppe_field} does not exist in the packet.", 
                          f); 
    }
    else {
        return ucli_e_internal(uc, "ppe_field_exists() failed internally."); 
    }
}
Exemple #11
0
static ucli_status_t
ppe_ucli_utm__checkf__(ucli_context_t* uc)
{
    ppe_header_t cheader; 
    ppe_header_t pheader; 

    UCLI_COMMAND_INFO(uc, 
                      "checkf", 1, 
                      "Check the packet format."); 

    UCLI_ARGPARSE_OR_RETURN(uc, "{ppe_header}", &cheader); 
    ppe_packet_format_get(&ppec->ppep, &pheader); 
    if(pheader != cheader) { 
        return ucli_error(uc, "packet format is currently %{ppe_header}.", 
                          pheader); 
    }
    return UCLI_STATUS_OK; 
}
Exemple #12
0
ucli_status_t
vt_ucli_module__sendrecv__(ucli_context_t* uc)
{
    UCLI_COMMAND_INFO(uc,
                      "sendrecv", 2,
                      "$summary#Send a single packet on the given VPI and wait for a response."
                      "$args#<vpi_spec> <packet_data>");

    vtc->size = sizeof(vtc->data);
    UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{idata}", &vtc->vpi, vtc->data, &vtc->size);
    if(vpi_send(vtc->vpi, vtc->data, vtc->size) < 0) {
        return ucli_error(uc, "vpi_send() failed.");
    }
    if(vpi_recv__(uc, vtc) > 0) {
        ucli_printf(uc, "recv(%{vpi}):\n%{data}", vtc->vpi, vtc->data, vtc->size);
        return UCLI_STATUS_OK;
    }
    else {
        return UCLI_STATUS_E_ERROR;
    }
}
Exemple #13
0
ucli_status_t
vt_ucli_module__spam__(ucli_context_t* uc)
{
    aim_ratelimiter_t counter_rl;
    aim_ratelimiter_t send_rl;
    int count = 0;
    int last = 0;
    int pps = -1;

    UCLI_COMMAND_INFO(uc,
                      "spam", 3,
                      "$summary#Spam packet data on the given VPI."
                      "$args#<vpi_spec> <packet_data> <pps>");

    UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}{idata}i",
                            &vtc->vpi, vtc->data, &vtc->size, &pps);

    aim_ratelimiter_init(&counter_rl, 1000000, 0, NULL);
    aim_ratelimiter_init(&send_rl, 1000000/pps, 0, NULL);

    for(;;) {
        uint64_t now = os_time_monotonic();
        if(aim_ratelimiter_limit(&counter_rl, now) == 0) {
            ucli_printf(uc, "Sent %d packets - %d pps\n", count,
                        (count - last));
            last = count;

        }
        if(aim_ratelimiter_limit(&send_rl, now) == 0) {
            if(vpi_send(vtc->vpi, vtc->data, vtc->size) < 0) {
                return ucli_error(uc, "vpi_send() failed.");
            }
            count++;
        }
        else {
            os_sleep_usecs(1);
        }
    }
    return UCLI_STATUS_OK;
}
Exemple #14
0
static ucli_status_t
ppe_ucli_utm__missing__(ucli_context_t* uc)
{
    ppe_field_t f; 
    int rv; 
    
    UCLI_COMMAND_INFO(uc, 
                      "missing", 1, 
                      "Check that a field is missing in the packet."); 

    UCLI_ARGPARSE_OR_RETURN(uc, "{ppe_field}", &f);    
    rv = ppe_field_exists(&ppec->ppep, f); 
    if(rv == 0) { 
        return UCLI_STATUS_OK; 
    }
    else if(rv == 1) {
        return ucli_error(uc, "field %{ppe_field} exists in the packet.", 
                          f); 
    }
    else {
        return ucli_e_internal(uc, "ppe_field_exists()"); 
    }
}
Exemple #15
0
static ucli_status_t
ppe_ucli_utm__dfk__(ucli_context_t* uc)
{
    ppe_dfk_t dfk; 
    ppe_field_t fields[4]; 
    uint8_t* verify_data;
    unsigned int verify_data_size; 
    int rv = UCLI_STATUS_OK; 
    unsigned int i; 

    UCLI_COMMAND_INFO(uc, 
                      "dfk", AIM_ARRAYSIZE(fields)+1, 
                      "Generate and verify a dynamic field key."); 
    UCLI_ARGPARSE_OR_RETURN(uc, 
                            "{ppe_field}{ppe_field}{ppe_field}{ppe_field}{data}", 
                            fields+0, fields+1, fields+2, fields+3, 
                            &verify_data, &verify_data_size); 

    ppe_dfk_init(&dfk, fields, AIM_ARRAYSIZE(fields)); 
    i = ppe_packet_dfk(&ppec->ppep, &dfk); 

    if(i != verify_data_size) { 
        rv = ucli_error(uc, "dfk size is %d, verify data size is %d", 
                        i, verify_data_size); 
        goto dfk_error;
    }

    for(i = 0; i < AIM_ARRAYSIZE(fields); i++) {
        const ppe_field_info_t* fi = ppe_field_info_get(fields[i]); 
        int exists = ppe_field_exists(&ppec->ppep, fi->field); 
        if(exists && ( (dfk.mask & (1<<i)) == 0)) { 
            /* Should be in the field key but isn't.*/
            rv = ucli_error(uc, "%{ppe_field} exists in packet but not in field key.", 
                            fi->field);
            goto dfk_error; 
        }
        if(!(exists) && (dfk.mask & (1<<i))) { 
            /* Should not be in the field key but is. */
            rv = ucli_error(uc, "%{ppe_field} is in the key but not the packet.", 
                            fi->field); 
            goto dfk_error; 
        }
        
    }
    for(i = 0; i < verify_data_size; i++) { 
        if(verify_data[i] != dfk.data[i]) { 
            rv = ucli_error(uc, "key data mismatch at byte %d.\nkey=%{data}, verify=%{data}", 
                            i, dfk.data, verify_data_size, verify_data, verify_data_size);         
            goto dfk_error; 
        }
    }
    for(i = 0; i < AIM_ARRAYSIZE(fields); i++) {
        if(dfk.mask & (1<<i)) {         
            const ppe_field_info_t* fi = ppe_field_info_get(fields[i]); 
            if(fi->size_bits <= 32) { 
                uint32_t pdata;
                uint32_t kdata; 
                ppe_field_get(&ppec->ppep, fi->field, &pdata); 
                ppe_dfk_field_get(&dfk, fi->field, &kdata); 
                if(pdata != kdata) { 
                    rv = ucli_error(uc, "field_get mismatch: p=0x%x, k=0x%x"); 
                    goto dfk_error; 
                }
            }
            else { 
                unsigned int i; 
                uint8_t pdata[128]; 
                uint8_t kdata[128]; 
                
                ppe_wide_field_get(&ppec->ppep, fi->field, pdata); 
                ppe_dfk_wide_field_get(&dfk, fi->field, kdata); 
                for(i = 0; i < fi->size_bits/8; i++) { 
                    if(pdata[i] != kdata[i]) { 
                        rv = ucli_error(uc, "wide_field_get mismatch @ %d: p=0x%x k=0x%x", 
                                        i, pdata[i], kdata[i]); 
                        goto dfk_error; 
                    }
                }
            }
        }
    }

    aim_free(verify_data); 
    ppe_dfk_destroy(&dfk); 
    return UCLI_STATUS_OK; 

 dfk_error:
    ucli_printf(uc, "key: "); 
    ppe_dfk_show(&dfk, &uc->pvs); 
    ppe_dfk_destroy(&dfk); 
    aim_free(verify_data); 
    ucli_printf(uc, "\n"); 
    return rv; 
}
Exemple #16
0
static ucli_status_t
fme_ucli_utm__match__(ucli_context_t* uc)
{
    int rv;
    int i;

    uint32_t keymask;
    uint8_t* value;
    int value_size;
    int _now;
    fme_timeval_t now;
    unsigned int size;
    fme_entry_t* fe = NULL;
    fme_key_t key;

    UCLI_COMMAND_INFO(uc,
                      "match", 4,
                      "Run the key and data.");

    UCLI_ARGPARSE_OR_RETURN(uc, "i{data}ii", &keymask, &value, &value_size,
                            &size, &_now);
    now = _now;
    FME_MEMSET(&key, 0, sizeof(key));
    key.keymask = keymask;
    FME_MEMCPY(key.values, value, value_size);
    key.size = value_size;
    FME_MEMSET(key.masks, 0, sizeof(key.masks));
    aim_free(value);

    rv = fme_match(fmec->fme, &key, now, size, NULL, NULL, &fe);

    if(rv == 1) {
        if(fmec->expects[fe->prio] == 0) {
            /* Unexpected match */
            ucli_error(uc, "unexpected match: ");
            fme_entry_dump(fe, &uc->pvs);
            goto __match__error;
        }

        /* match is expected -- check counter values */
        if(fe->counters.matches != 1) {
            ucli_error(uc, "match counter was not incremented.");
            goto __match__error;
        }
        if(fe->counters.bytes != size) {
            ucli_error(uc, "byte counter is incorrect.");
            goto __match__error;
        }
        if(fe->timestamp != now) {
            ucli_error(uc, "timestamp was not updated.");
            goto __match__error;
        }

        /* all good */
    }
    else if(rv == 0) {
        /* Make sure we have to entries expected to match */
        for(i = 0; i < FME_CONFIG_UTM_ENTRIES; i++) {
            if(fmec->expects[i]) {
                ucli_error(uc, "expected match was not received: ");
                fme_entry_dump(fmec->entries[i], &uc->pvs);
                goto __match__error;
            }
        }
        /* all good */
    }
    else {
        ucli_e_internal(uc, "fme_match() returned %d", rv);
        goto __match__error;
    }

    /* all good - reset */
    fme_destroy_all(fmec->fme);
    FME_MEMSET(fmec, 0, sizeof(*fmec));
    fme_create(&fmec->fme, "fme_utm", FME_CONFIG_UTM_ENTRIES);
    return UCLI_STATUS_OK;

 __match__error:

    ucli_error(uc, "fme: ");
    fme_dump(fmec->fme, &uc->pvs);
    return UCLI_STATUS_E_ERROR;
}
Exemple #17
0
static ucli_status_t
ppe_ucli_utm__rwall__(ucli_context_t* uc)
{
    ppe_packet_t ppep;  
    ppe_header_t header; 
    ppe_field_t f; 
    int rv = UCLI_STATUS_OK; 

    UCLI_COMMAND_INFO(uc, 
                      "rwall", 0, 
                      "Read and write all packet fields in all headers."); 

    ppe_packet_init(&ppep, NULL, 0);

    /**
     * Allocate and assign a header pointer for every header type. 
     * All bits will be initialized to 1. 
     */
    for(header = 0; header < PPE_HEADER_COUNT; header++) {
        uint8_t* hp = aim_zmalloc(1000); 
        PPE_MEMSET(hp, 0xFF, 1000); 
        ppe_header_set(&ppep, header, hp); 
    }

    /**
     * Check that every field reads back as all 1's, with the correct width
     */
    for(f = 0; f < PPE_FIELD_COUNT; f++) {
        const ppe_field_info_t* fi = ppe_field_info_get(f); 
        if(fi->size_bits == 0) { 
            continue; 
        }
        if(fi->size_bits <= 32) {
            uint32_t v;
            ppe_field_get(&ppep, f, &v); 
            if(fi->size_bits == 32) {
                if(v != 0xFFFFFFFF)  {
                    rv = ucli_error(uc, "first read: field %{ppe_field} is 0x%x, should be 0x%x", 
                                    f, v, -1); 
                }
            }
            else {
                if(v != ( (1U << fi->size_bits) - 1)) { 
                    rv = ucli_error(uc, "first read: field %{ppe_field} is 0x%x, should be 0x%x (%d bits)", 
                                    f, v, (1<<fi->size_bits) - 1, fi->size_bits); 
                }
            }
            /** clear field and re-read */
            ppe_field_set(&ppep, f, 0); 
            ppe_field_get(&ppep, f, &v); 
            if(v != 0) {
                rv = ucli_error(uc, "second read: field %{ppe_field} is 0x%x when it should be 0.", 
                                f, v); 
            }            
        }
        else {
            uint8_t vb[64];    
            int bytes = ppe_wide_field_get(&ppep, f, vb); 
            int i; 
            for(i = 0; i < bytes; i++) {
                if(vb[i] != 0xFF) { 
                    rv = ucli_error(uc, "first read: field %{ppe_field}[%d] is 0x%.2x, should be 0x%.2x", 
                                    f, i, vb[i], 0xFF); 
                }
            }
            PPE_MEMSET(vb, 0, sizeof(vb)); 
            /** clear field and re-read */
            ppe_wide_field_set(&ppep, f, vb); 
            PPE_MEMSET(vb, 0xFF, sizeof(vb)); 
            ppe_wide_field_get(&ppep, f, vb); 
            for(i = 0; i < bytes; i++) {
                if(vb[i] != 0) {
                    rv = ucli_error(uc, "second read: field %{ppe_field}[%d] is 0x%.2x, should be 0.", 
                                    f, i, vb[i]); 
                }
            }
        }

        /** continue reading other fields, making sure the field we just cleared
         * does not change the value of fields we have not yet visited. */

    }

    for(header = 0; header < PPE_HEADER_COUNT; header++) {
        aim_free(ppe_header_get(&ppep, header)); 
    }
    return rv; 
}
Exemple #18
0
int
ucli_e_arg(ucli_context_t* uc, const char* arg, const char* desc)
{
    ucli_error(uc, "argument '%s' is not a valid %s", arg, desc); 
    return UCLI_STATUS_E_ARG; 
}