static int parse_ringnuma_config(const char *q_arg) { char s[256]; const char *p, *p0 = q_arg; char *end; uint8_t i,port_id,ring_flag,socket_id; unsigned size; enum fieldnames { FLD_PORT = 0, FLD_FLAG, FLD_SOCKET, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; #define RX_RING_ONLY 0x1 #define TX_RING_ONLY 0x2 #define RXTX_RING 0x3 /* reset from value set at definition */ while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; rte_snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } port_id = (uint8_t)int_fld[FLD_PORT]; if (port_id >= nb_ports) { printf("Invalid port, range is [0, %d]\n", nb_ports - 1); return -1; } socket_id = (uint8_t)int_fld[FLD_SOCKET]; if (socket_id >= MAX_SOCKET) { printf("Invalid socket id, range is [0, %d]\n", MAX_SOCKET - 1); return -1; } ring_flag = (uint8_t)int_fld[FLD_FLAG]; if ((ring_flag < RX_RING_ONLY) || (ring_flag > RXTX_RING)) { printf("Invalid ring-flag=%d config for port =%d\n", ring_flag,port_id); return -1; } switch (ring_flag & RXTX_RING) { case RX_RING_ONLY: rxring_numa[port_id] = socket_id; break; case TX_RING_ONLY: txring_numa[port_id] = socket_id; break; case RXTX_RING: rxring_numa[port_id] = socket_id; txring_numa[port_id] = socket_id; break; default: printf("Invalid ring-flag=%d config for port=%d\n", ring_flag,port_id); break; } } return 0; }
static int parse_queue_stats_mapping_config(const char *q_arg, int is_rx) { char s[256]; const char *p, *p0 = q_arg; char *end; enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_STATS_COUNTER, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; int i; unsigned size; /* reset from value set at definition */ is_rx ? (nb_rx_queue_stats_mappings = 0) : (nb_tx_queue_stats_mappings = 0); while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; rte_snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++){ errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } /* Check mapping field is in correct range (0..RTE_ETHDEV_QUEUE_STAT_CNTRS-1) */ if (int_fld[FLD_STATS_COUNTER] >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { printf("Stats counter not in the correct range 0..%d\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); return -1; } if (is_rx ? (nb_rx_queue_stats_mappings >= MAX_RX_QUEUE_STATS_MAPPINGS) : (nb_tx_queue_stats_mappings >= MAX_TX_QUEUE_STATS_MAPPINGS)) { printf("exceeded max number of %s queue statistics mappings: %hu\n", is_rx ? "RX" : "TX", is_rx ? nb_rx_queue_stats_mappings : nb_tx_queue_stats_mappings); return -1; } if (!is_rx) { tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].port_id = (uint8_t)int_fld[FLD_PORT]; tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].queue_id = (uint8_t)int_fld[FLD_QUEUE]; tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].stats_counter_id = (uint8_t)int_fld[FLD_STATS_COUNTER]; ++nb_tx_queue_stats_mappings; } else { rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].port_id = (uint8_t)int_fld[FLD_PORT]; rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].queue_id = (uint8_t)int_fld[FLD_QUEUE]; rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].stats_counter_id = (uint8_t)int_fld[FLD_STATS_COUNTER]; ++nb_rx_queue_stats_mappings; } } /* Reassign the rx/tx_queue_stats_mappings pointer to point to this newly populated array rather */ /* than to the default array (that was set at its definition) */ is_rx ? (rx_queue_stats_mappings = rx_queue_stats_mappings_array) : (tx_queue_stats_mappings = tx_queue_stats_mappings_array); return 0; }
static int test_rte_strsplit(void) { int i; do { /* ======================================================= * split a mac address correct number of splits requested * =======================================================*/ char test_string[] = "54:65:76:87:98:90"; char *splits[6]; LOG("Source string: '%s', to split on ':'\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 6, ':') != 6) { LOG("Error splitting mac address\n"); return -1; } for (i = 0; i < 6; i++) LOG("Token %d = %s\n", i + 1, splits[i]); } while (0); do { /* ======================================================= * split on spaces smaller number of splits requested * =======================================================*/ char test_string[] = "54 65 76 87 98 90"; char *splits[6]; LOG("Source string: '%s', to split on ' '\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 3, ' ') != 3) { LOG("Error splitting mac address for max 2 splits\n"); return -1; } for (i = 0; i < 3; i++) LOG("Token %d = %s\n", i + 1, splits[i]); } while (0); do { /* ======================================================= * split on commas - more splits than commas requested * =======================================================*/ char test_string[] = "a,b,c,d"; char *splits[6]; LOG("Source string: '%s', to split on ','\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 6, ',') != 4) { LOG("Error splitting %s on ','\n", test_string); return -1; } for (i = 0; i < 4; i++) LOG("Token %d = %s\n", i + 1, splits[i]); } while(0); do { /* ======================================================= * Try splitting on non-existent character. * =======================================================*/ char test_string[] = "a,b,c,d"; char *splits[6]; LOG("Source string: '%s', to split on ' '\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 6, ' ') != 1) { LOG("Error splitting %s on ' '\n", test_string); return -1; } LOG("String not split\n"); } while(0); do { /* ======================================================= * Invalid / edge case parameter checks * =======================================================*/ char test_string[] = "a,b,c,d"; char *splits[6]; if (rte_strsplit(NULL, 0, splits, 6, ',') >= 0 || errno != EINVAL){ LOG("Error: rte_strsplit accepted NULL string parameter\n"); return -1; } if (rte_strsplit(test_string, sizeof(test_string), NULL, 0, ',') >= 0 || errno != EINVAL){ LOG("Error: rte_strsplit accepted NULL array parameter\n"); return -1; } errno = 0; if (rte_strsplit(test_string, 0, splits, 6, ',') != 0 || errno != 0) { LOG("Error: rte_strsplit did not accept 0 length string\n"); return -1; } if (rte_strsplit(test_string, sizeof(test_string), splits, 0, ',') != 0 || errno != 0) { LOG("Error: rte_strsplit did not accept 0 length array\n"); return -1; } LOG("Parameter test cases passed\n"); } while(0); LOG("%s - PASSED\n", __func__); return 0; }
struct rte_cfgfile * rte_cfgfile_load(const char *filename, int flags) { int allocated_sections = CFG_ALLOC_SECTION_BATCH; int allocated_entries = 0; int curr_section = -1; int curr_entry = -1; char buffer[256]; int lineno = 0; struct rte_cfgfile *cfg = NULL; FILE *f = fopen(filename, "r"); if (f == NULL) return NULL; cfg = malloc(sizeof(*cfg) + sizeof(cfg->sections[0]) * allocated_sections); if (cfg == NULL) goto error2; memset(cfg->sections, 0, sizeof(cfg->sections[0]) * allocated_sections); while (fgets(buffer, sizeof(buffer), f) != NULL) { char *pos = NULL; size_t len = strnlen(buffer, sizeof(buffer)); lineno++; if ((len >= sizeof(buffer) - 1) && (buffer[len-1] != '\n')) { printf("Error line %d - no \\n found on string. " "Check if line too long\n", lineno); goto error1; } pos = memchr(buffer, ';', sizeof(buffer)); if (pos != NULL) { *pos = '\0'; len = pos - buffer; } len = _strip(buffer, len); if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL) continue; if (buffer[0] == '[') { /* section heading line */ char *end = memchr(buffer, ']', len); if (end == NULL) { printf("Error line %d - no terminating '['" "character found\n", lineno); goto error1; } *end = '\0'; _strip(&buffer[1], end - &buffer[1]); /* close off old section and add start new one */ if (curr_section >= 0) cfg->sections[curr_section]->num_entries = curr_entry + 1; curr_section++; /* resize overall struct if we don't have room for more sections */ if (curr_section == allocated_sections) { allocated_sections += CFG_ALLOC_SECTION_BATCH; struct rte_cfgfile *n_cfg = realloc(cfg, sizeof(*cfg) + sizeof(cfg->sections[0]) * allocated_sections); if (n_cfg == NULL) { printf("Error - no more memory\n"); goto error1; } cfg = n_cfg; } /* allocate space for new section */ allocated_entries = CFG_ALLOC_ENTRY_BATCH; curr_entry = -1; cfg->sections[curr_section] = malloc( sizeof(*cfg->sections[0]) + sizeof(cfg->sections[0]->entries[0]) * allocated_entries); if (cfg->sections[curr_section] == NULL) { printf("Error - no more memory\n"); goto error1; } snprintf(cfg->sections[curr_section]->name, sizeof(cfg->sections[0]->name), "%s", &buffer[1]); } else { /* value line */ if (curr_section < 0) { printf("Error line %d - value outside of" "section\n", lineno); goto error1; } struct rte_cfgfile_section *sect = cfg->sections[curr_section]; char *split[2]; if (rte_strsplit(buffer, sizeof(buffer), split, 2, '=') != 2) { printf("Error at line %d - cannot split " "string\n", lineno); goto error1; } curr_entry++; if (curr_entry == allocated_entries) { allocated_entries += CFG_ALLOC_ENTRY_BATCH; struct rte_cfgfile_section *n_sect = realloc( sect, sizeof(*sect) + sizeof(sect->entries[0]) * allocated_entries); if (n_sect == NULL) { printf("Error - no more memory\n"); goto error1; } sect = cfg->sections[curr_section] = n_sect; } sect->entries[curr_entry] = malloc( sizeof(*sect->entries[0])); if (sect->entries[curr_entry] == NULL) { printf("Error - no more memory\n"); goto error1; } struct rte_cfgfile_entry *entry = sect->entries[ curr_entry]; snprintf(entry->name, sizeof(entry->name), "%s", split[0]); snprintf(entry->value, sizeof(entry->value), "%s", split[1]); _strip(entry->name, strnlen(entry->name, sizeof(entry->name))); _strip(entry->value, strnlen(entry->value, sizeof(entry->value))); } } fclose(f); cfg->flags = flags; cfg->sections[curr_section]->num_entries = curr_entry + 1; cfg->num_sections = curr_section + 1; return cfg; error1: rte_cfgfile_close(cfg); error2: fclose(f); return NULL; }
/* * Parse a grant node. * @param domid * Guest domain id. * @param path * Full path string for a grant node, like for the following (key, val) pair * idx#_mempool_gref = "gref#, gref#, gref#" * path = 'local/domain/domid/control/dpdk/idx#_mempool_gref' * gref# is a shared page contain packed (gref,pfn) entries * @return * Returns the pointer to xen_gntnode */ static struct xen_gntnode * parse_gntnode(int dom_id, char *path) { char **gref_list = NULL; uint32_t i, len, gref_num; void *addr = NULL; char *buf = NULL; struct xen_gntnode *gntnode = NULL; struct xen_gnt *gnt = NULL; int pg_sz = getpagesize(); char *end; uint64_t index; if ((buf = xen_read_node(path, &len)) == NULL) goto err; gref_list = malloc(MAX_GREF_PER_NODE * sizeof(char *)); if (gref_list == NULL) goto err; gref_num = rte_strsplit(buf, len, gref_list, MAX_GREF_PER_NODE, XEN_GREF_SPLITTOKEN); if (gref_num == 0) { RTE_LOG(ERR, XENHOST, " %s: invalid grant node format\n", __func__); goto err; } gntnode = calloc(1, sizeof(struct xen_gntnode)); gnt = calloc(gref_num, sizeof(struct xen_gnt)); if (gnt == NULL || gntnode == NULL) goto err; for (i = 0; i < gref_num; i++) { errno = 0; gnt[i].gref = strtol(gref_list[i], &end, 0); if (errno != 0 || end == NULL || end == gref_list[i] || (*end != '\0' && *end != XEN_GREF_SPLITTOKEN)) { RTE_LOG(ERR, XENHOST, " %s: parse grant node item failed\n", __func__); goto err; } addr = xen_grant_mmap(NULL, dom_id, gnt[i].gref, &index); if (addr == NULL) { RTE_LOG(ERR, XENHOST, " %s: map gref %u failed\n", __func__, gnt[i].gref); goto err; } RTE_LOG(INFO, XENHOST, " %s: map gref %u to %p\n", __func__, gnt[i].gref, addr); memcpy(gnt[i].gref_pfn, addr, pg_sz); if (munmap(addr, pg_sz)) { RTE_LOG(INFO, XENHOST, " %s: unmap gref %u failed\n", __func__, gnt[i].gref); goto err; } if (xen_unmap_grant_ref(index)) { RTE_LOG(INFO, XENHOST, " %s: release gref %u failed\n", __func__, gnt[i].gref); goto err; } } gntnode->gnt_num = gref_num; gntnode->gnt_info = gnt; free(buf); free(gref_list); return gntnode; err: free(gnt); free(gntnode); free(gref_list); free(buf); return NULL; }