From: Fan Zhang Date: Tue, 1 Mar 2016 10:35:52 +0000 (+0000) Subject: examples/ip_pipeline: add link identification X-Git-Tag: spdx-start~7545 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=377cd98e0ab6;p=dpdk.git examples/ip_pipeline: add link identification This patch adds link identification feature to packet framework. To identify a link, user can use both existing port-mask option, or specify PCI device in every LINK section in the configuration file. Signed-off-by: Fan Zhang Acked-by: Cristian Dumitrescu --- diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h index 2c9125634a..f55aef8510 100644 --- a/examples/ip_pipeline/app.h +++ b/examples/ip_pipeline/app.h @@ -49,7 +49,7 @@ #include "pipeline.h" #define APP_PARAM_NAME_SIZE PIPELINE_NAME_SIZE - +#define APP_LINK_PCI_BDF_SIZE 16 struct app_mempool_params { char *name; uint32_t parsed; @@ -64,7 +64,7 @@ struct app_link_params { uint32_t parsed; uint32_t pmd_id; /* Generated based on port mask */ uint32_t arp_q; /* 0 = Disabled (packets go to default queue 0) */ - uint32_t tcp_syn_local_q; /* 0 = Disabled (pkts go to default queue) */ + uint32_t tcp_syn_q; /* 0 = Disabled (pkts go to default queue) */ uint32_t ip_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t tcp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t udp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ @@ -73,6 +73,7 @@ struct app_link_params { uint32_t ip; /* 0 = Invalid */ uint32_t depth; /* Valid only when IP is valid */ uint64_t mac_addr; /* Read from HW */ + char pci_bdf[APP_LINK_PCI_BDF_SIZE]; struct rte_eth_conf conf; uint8_t promisc; @@ -269,6 +270,10 @@ struct app_thread_data { double headroom_ratio; }; +#ifndef APP_MAX_LINKS +#define APP_MAX_LINKS 16 +#endif + struct app_eal_params { /* Map lcore set to physical cpu set */ char *coremap; @@ -290,13 +295,13 @@ struct app_eal_params { uint32_t ranks; /* Add a PCI device in black list. */ - char *pci_blacklist; + char *pci_blacklist[APP_MAX_LINKS]; /* Add a PCI device in white list. */ - char *pci_whitelist; + char *pci_whitelist[APP_MAX_LINKS]; /* Add a virtual device. */ - char *vdev; + char *vdev[APP_MAX_LINKS]; /* Use VMware TSC map instead of native RDTSC */ uint32_t vmware_tsc_map_present; @@ -371,10 +376,6 @@ struct app_eal_params { #define APP_MAX_MEMPOOLS 8 #endif -#ifndef APP_MAX_LINKS -#define APP_MAX_LINKS 16 -#endif - #ifndef APP_LINK_MAX_HWQ_IN #define APP_LINK_MAX_HWQ_IN 64 #endif diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c index 1ff5763723..fd9ff49569 100644 --- a/examples/ip_pipeline/config_check.c +++ b/examples/ip_pipeline/config_check.c @@ -59,12 +59,16 @@ check_mempools(struct app_params *app) static void check_links(struct app_params *app) { - uint32_t n_links_port_mask = __builtin_popcountll(app->port_mask); uint32_t i; /* Check that number of links matches the port mask */ - APP_CHECK((app->n_links == n_links_port_mask), - "Not enough links provided in the PORT_MASK\n"); + if (app->port_mask) { + uint32_t n_links_port_mask = + __builtin_popcountll(app->port_mask); + + APP_CHECK((app->n_links == n_links_port_mask), + "Not enough links provided in the PORT_MASK\n"); + } for (i = 0; i < app->n_links; i++) { struct app_link_params *link = &app->link_params[i]; @@ -76,8 +80,8 @@ check_links(struct app_params *app) rxq_max = 0; if (link->arp_q > rxq_max) rxq_max = link->arp_q; - if (link->tcp_syn_local_q > rxq_max) - rxq_max = link->tcp_syn_local_q; + if (link->tcp_syn_q > rxq_max) + rxq_max = link->tcp_syn_q; if (link->ip_local_q > rxq_max) rxq_max = link->ip_local_q; if (link->tcp_local_q > rxq_max) @@ -89,7 +93,7 @@ check_links(struct app_params *app) for (i = 1; i <= rxq_max; i++) APP_CHECK(((link->arp_q == i) || - (link->tcp_syn_local_q == i) || + (link->tcp_syn_q == i) || (link->ip_local_q == i) || (link->tcp_local_q == i) || (link->udp_local_q == i) || diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c index 5f72af9cd9..4695ac1595 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -56,6 +56,7 @@ static struct app_params app_params_default = { .config_file = "./config/ip_pipeline.cfg", .log_level = APP_LOG_LEVEL_HIGH, + .port_mask = 0, .eal_params = { .channels = 4, @@ -74,7 +75,7 @@ static const struct app_link_params link_params_default = { .parsed = 0, .pmd_id = 0, .arp_q = 0, - .tcp_syn_local_q = 0, + .tcp_syn_q = 0, .ip_local_q = 0, .tcp_local_q = 0, .udp_local_q = 0, @@ -83,6 +84,7 @@ static const struct app_link_params link_params_default = { .ip = 0, .depth = 0, .mac_addr = 0, + .pci_bdf = {0}, .conf = { .link_speed = 0, @@ -205,12 +207,13 @@ struct app_pipeline_params default_pipeline_params = { }; static const char app_usage[] = - "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK " + "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] [-p PORT_MASK] " "[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\n" "\n" "Arguments:\n" "\t-f CONFIG_FILE: Default config file is %s\n" - "\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\n" + "\t-p PORT_MASK: Mask of NIC port IDs in hex format (generated from " + "config file when not provided)\n" "\t-s SCRIPT_FILE: No CLI script file is run when not specified\n" "\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n" "\t--preproc PREPROCESSOR: Configuration file pre-processor\n" @@ -283,6 +286,11 @@ parser_read_arg_bool(const char *p) #define PARSE_ERROR(exp, section, entry) \ APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"\n", section, entry) +#define PARSE_ERROR_MESSAGE(exp, section, entry, message) \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s\n", \ + section, entry, message) + + #define PARSE_ERROR_MALLOC(exp) \ APP_CHECK(exp, "Parse error: no free memory\n") @@ -657,29 +665,62 @@ parse_eal(struct app_params *app, /* pci_blacklist */ if ((strcmp(entry->name, "pci_blacklist") == 0) || (strcmp(entry->name, "b") == 0)) { - PARSE_ERROR_DUPLICATE((p->pci_blacklist == NULL), - section_name, - entry->name); - p->pci_blacklist = strdup(entry->value); + uint32_t i; + + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->pci_blacklist[i]) + continue; + + p->pci_blacklist[i] = + strdup(entry->value); + PARSE_ERROR_MALLOC(p->pci_blacklist[i]); + } + + PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS), + section_name, entry->name, + "too many elements"); continue; } /* pci_whitelist */ if ((strcmp(entry->name, "pci_whitelist") == 0) || (strcmp(entry->name, "w") == 0)) { - PARSE_ERROR_DUPLICATE((p->pci_whitelist == NULL), - section_name, - entry->name); - p->pci_whitelist = strdup(entry->value); + uint32_t i; + + PARSE_ERROR_MESSAGE((app->port_mask != 0), + section_name, entry->name, "entry to be " + "generated by the application (port_mask " + "not provided)"); + + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->pci_whitelist[i]) + continue; + + p->pci_whitelist[i] = strdup(entry->value); + PARSE_ERROR_MALLOC(p->pci_whitelist[i]); + } + + PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS), + section_name, entry->name, + "too many elements"); continue; } /* vdev */ if (strcmp(entry->name, "vdev") == 0) { - PARSE_ERROR_DUPLICATE((p->vdev == NULL), - section_name, - entry->name); - p->vdev = strdup(entry->value); + uint32_t i; + + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->vdev[i]) + continue; + + p->vdev[i] = strdup(entry->value); + PARSE_ERROR_MALLOC(p->vdev[i]); + } + + PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS), + section_name, entry->name, + "too many elements"); continue; } @@ -1395,6 +1436,7 @@ parse_link(struct app_params *app, struct app_link_params *param; struct rte_cfgfile_entry *entries; int n_entries, i; + int pci_bdf_present = 0; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1433,7 +1475,7 @@ parse_link(struct app_params *app, if (strcmp(ent->name, "tcp_syn_q") == 0) { int status = parser_read_uint32( - ¶m->tcp_syn_local_q, ent->value); + ¶m->tcp_syn_q, ent->value); PARSE_ERROR((status == 0), section_name, ent->name); continue; @@ -1476,10 +1518,31 @@ parse_link(struct app_params *app, continue; } + if (strcmp(ent->name, "pci_bdf") == 0) { + PARSE_ERROR_DUPLICATE((pci_bdf_present == 0), + section_name, ent->name); + + snprintf(param->pci_bdf, APP_LINK_PCI_BDF_SIZE, + "%s", ent->value); + pci_bdf_present = 1; + continue; + } + /* unrecognized */ PARSE_ERROR_INVALID(0, section_name, ent->name); } + /* Check for mandatory fields */ + if (app->port_mask) + PARSE_ERROR_MESSAGE((pci_bdf_present == 0), + section_name, "pci_bdf", + "entry not allowed (port_mask is provided)"); + else + PARSE_ERROR_MESSAGE((pci_bdf_present), + section_name, "pci_bdf", + "this entry is mandatory (port_mask is not " + "provided)"); + param->parsed = 1; free(entries); @@ -2121,7 +2184,8 @@ create_implicit_mempools(struct app_params *app) } static void -parse_port_mask(struct app_params *app, uint64_t port_mask) +create_implicit_links_from_port_mask(struct app_params *app, + uint64_t port_mask) { uint32_t pmd_id, link_id; @@ -2142,6 +2206,18 @@ parse_port_mask(struct app_params *app, uint64_t port_mask) } } +static void +assign_link_pmd_id_from_pci_bdf(struct app_params *app) +{ + uint32_t i; + + for (i = 0; i < app->n_links; i++) { + struct app_link_params *link = &app->link_params[i]; + + link->pmd_id = i; + } +} + int app_config_parse(struct app_params *app, const char *file_name) { @@ -2153,7 +2229,8 @@ app_config_parse(struct app_params *app, const char *file_name) create_implicit_mempools(app); /* Port mask */ - parse_port_mask(app, app->port_mask); + if (app->port_mask) + create_implicit_links_from_port_mask(app, app->port_mask); /* Load application configuration file */ cfg = rte_cfgfile_load(file_name, 0); @@ -2232,6 +2309,9 @@ app_config_parse(struct app_params *app, const char *file_name) APP_PARAM_COUNT(app->msgq_params, app->n_msgq); APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines); + if (app->port_mask == 0) + assign_link_pmd_id_from_pci_bdf(app); + /* Save configuration to output file */ app_config_save(app, app->output_file); @@ -2245,6 +2325,7 @@ static void save_eal_params(struct app_params *app, FILE *f) { struct app_eal_params *p = &app->eal_params; + uint32_t i; fprintf(f, "[EAL]\n"); @@ -2263,14 +2344,29 @@ save_eal_params(struct app_params *app, FILE *f) if (p->ranks_present) fprintf(f, "%s = %" PRIu32 "\n", "r", p->ranks); - if (p->pci_blacklist) - fprintf(f, "%s = %s\n", "pci_blacklist", p->pci_blacklist); + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->pci_blacklist[i] == NULL) + break; + + fprintf(f, "%s = %s\n", "pci_blacklist", + p->pci_blacklist[i]); + } - if (p->pci_whitelist) - fprintf(f, "%s = %s\n", "pci_whitelist", p->pci_whitelist); + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->pci_whitelist[i] == NULL) + break; - if (p->vdev) - fprintf(f, "%s = %s\n", "vdev", p->vdev); + fprintf(f, "%s = %s\n", "pci_whitelist", + p->pci_whitelist[i]); + } + + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->vdev[i] == NULL) + break; + + fprintf(f, "%s = %s\n", "vdev", + p->vdev[i]); + } if (p->vmware_tsc_map_present) fprintf(f, "%s = %s\n", "vmware_tsc_map", @@ -2371,14 +2467,17 @@ save_links_params(struct app_params *app, FILE *f) fprintf(f, "; %s = %" PRIu32 "\n", "pmd_id", p->pmd_id); fprintf(f, "%s = %s\n", "promisc", p->promisc ? "yes" : "no"); fprintf(f, "%s = %" PRIu32 "\n", "arp_q", p->arp_q); - fprintf(f, "%s = %" PRIu32 "\n", "tcp_syn_local_q", - p->tcp_syn_local_q); + fprintf(f, "%s = %" PRIu32 "\n", "tcp_syn_q", + p->tcp_syn_q); fprintf(f, "%s = %" PRIu32 "\n", "ip_local_q", p->ip_local_q); fprintf(f, "%s = %" PRIu32 "\n", "tcp_local_q", p->tcp_local_q); fprintf(f, "%s = %" PRIu32 "\n", "udp_local_q", p->udp_local_q); fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q", p->sctp_local_q); + if (strlen(p->pci_bdf)) + fprintf(f, "%s = %s\n", "pci_bdf", p->pci_bdf); + fputc('\n', f); } } @@ -2891,10 +2990,6 @@ app_config_args(struct app_params *app, int argc, char **argv) optind = 0; /* reset getopt lib */ - /* Check that mandatory args have been provided */ - if (!p_present) - rte_panic("Error: PORT_MASK is not provided\n"); - /* Check dependencies between args */ if (preproc_params_present && (preproc_present == 0)) rte_panic("Error: Preprocessor args specified while " diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c index af47835d6a..2d9fae4217 100644 --- a/examples/ip_pipeline/init.c +++ b/examples/ip_pipeline/init.c @@ -96,9 +96,10 @@ app_init_core_mask(struct app_params *app) static void app_init_eal(struct app_params *app) { - char buffer[32]; + char buffer[256]; struct app_eal_params *p = &app->eal_params; uint32_t n_args = 0; + uint32_t i; int status; app->eal_argv[n_args++] = strdup(app->app_name); @@ -132,24 +133,47 @@ app_init_eal(struct app_params *app) app->eal_argv[n_args++] = strdup(buffer); } - if (p->pci_blacklist) { + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->pci_blacklist[i] == NULL) + break; + snprintf(buffer, sizeof(buffer), "--pci-blacklist=%s", - p->pci_blacklist); + p->pci_blacklist[i]); app->eal_argv[n_args++] = strdup(buffer); } - if (p->pci_whitelist) { + if (app->port_mask != 0) + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->pci_whitelist[i] == NULL) + break; + + snprintf(buffer, + sizeof(buffer), + "--pci-whitelist=%s", + p->pci_whitelist[i]); + app->eal_argv[n_args++] = strdup(buffer); + } + else + for (i = 0; i < app->n_links; i++) { + char *pci_bdf = app->link_params[i].pci_bdf; + + snprintf(buffer, + sizeof(buffer), + "--pci-whitelist=%s", + pci_bdf); + app->eal_argv[n_args++] = strdup(buffer); + } + + for (i = 0; i < APP_MAX_LINKS; i++) { + if (p->vdev[i] == NULL) + break; + snprintf(buffer, sizeof(buffer), - "--pci-whitelist=%s", - p->pci_whitelist); - app->eal_argv[n_args++] = strdup(buffer); - } - - if (p->vdev) { - snprintf(buffer, sizeof(buffer), "--vdev=%s", p->vdev); + "--vdev=%s", + p->vdev[i]); app->eal_argv[n_args++] = strdup(buffer); } @@ -267,6 +291,15 @@ app_init_eal(struct app_params *app) app->eal_argc = n_args; APP_LOG(app, HIGH, "Initializing EAL ..."); + if (app->log_level >= APP_LOG_LEVEL_LOW) { + int i; + + fprintf(stdout, "[APP] EAL arguments: \""); + for (i = 1; i < app->eal_argc; i++) + fprintf(stdout, "%s ", app->eal_argv[i]); + fprintf(stdout, "\"\n"); + } + status = rte_eal_init(app->eal_argc, app->eal_argv); if (status < 0) rte_panic("EAL init error\n"); @@ -317,7 +350,7 @@ app_link_filter_tcp_syn_add(struct app_link_params *link) { struct rte_eth_syn_filter filter = { .hig_pri = 1, - .queue = link->tcp_syn_local_q, + .queue = link->tcp_syn_q, }; return rte_eth_dev_filter_ctrl(link->pmd_id, @@ -555,28 +588,45 @@ app_link_set_arp_filter(struct app_params *app, struct app_link_params *cp) static void app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp) { - if (cp->tcp_syn_local_q != 0) { + if (cp->tcp_syn_q != 0) { int status = app_link_filter_tcp_syn_add(cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): " "Adding TCP SYN filter (queue = %" PRIu32 ")", - cp->name, cp->pmd_id, cp->tcp_syn_local_q); + cp->name, cp->pmd_id, cp->tcp_syn_q); if (status) rte_panic("%s (%" PRIu32 "): " "Error adding TCP SYN filter " "(queue = %" PRIu32 ") (%" PRId32 ")\n", - cp->name, cp->pmd_id, cp->tcp_syn_local_q, + cp->name, cp->pmd_id, cp->tcp_syn_q, status); } } +static int +app_link_is_virtual(struct app_link_params *p) +{ + uint32_t pmd_id = p->pmd_id; + struct rte_eth_dev *dev = &rte_eth_devices[pmd_id]; + + if (dev->dev_type == RTE_ETH_DEV_VIRTUAL) + return 1; + + return 0; +} + void app_link_up_internal(struct app_params *app, struct app_link_params *cp) { uint32_t i; int status; + if (app_link_is_virtual(cp)) { + cp->state = 1; + return; + } + /* For each link, add filters for IP of current link */ if (cp->ip != 0) { for (i = 0; i < app->n_links; i++) { @@ -671,8 +721,8 @@ app_link_up_internal(struct app_params *app, struct app_link_params *cp) /* PMD link up */ status = rte_eth_dev_set_link_up(cp->pmd_id); if (status < 0) - rte_panic("%s (%" PRIu32 "): PMD set up error %" PRId32 "\n", - cp->name, cp->pmd_id, status); + rte_panic("%s (%" PRIu32 "): PMD set link up error %" + PRId32 "\n", cp->name, cp->pmd_id, status); /* Mark link as UP */ cp->state = 1; @@ -682,9 +732,18 @@ void app_link_down_internal(struct app_params *app, struct app_link_params *cp) { uint32_t i; + int status; + + if (app_link_is_virtual(cp)) { + cp->state = 0; + return; + } /* PMD link down */ - rte_eth_dev_set_link_down(cp->pmd_id); + status = rte_eth_dev_set_link_down(cp->pmd_id); + if (status < 0) + rte_panic("%s (%" PRIu32 "): PMD set link down error %" + PRId32 "\n", cp->name, cp->pmd_id, status); /* Mark link as DOWN */ cp->state = 0; diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c index 1e16ad6f21..bffc9a4add 100644 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c +++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c @@ -898,9 +898,15 @@ print_link_info(struct app_link_params *p) mac_addr = (struct ether_addr *) &p->mac_addr; - printf("%s: flags=<%s>\n", - p->name, - (p->state) ? "UP" : "DOWN"); + if (strlen(p->pci_bdf)) + printf("%s(%s): flags=<%s>\n", + p->name, + p->pci_bdf, + (p->state) ? "UP" : "DOWN"); + else + printf("%s: flags=<%s>\n", + p->name, + (p->state) ? "UP" : "DOWN"); if (p->ip) printf("\tinet %" PRIu32 ".%" PRIu32