/*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_flow_classification.h" #include "hash_func.h" /* * Key conversion */ struct pkt_key_qinq { uint16_t ethertype_svlan; uint16_t svlan; uint16_t ethertype_cvlan; uint16_t cvlan; } __attribute__((__packed__)); struct pkt_key_ipv4_5tuple { uint8_t ttl; uint8_t proto; uint16_t checksum; uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; } __attribute__((__packed__)); struct pkt_key_ipv6_5tuple { uint16_t payload_length; uint8_t proto; uint8_t hop_limit; uint8_t ip_src[16]; uint8_t ip_dst[16]; uint16_t port_src; uint16_t port_dst; } __attribute__((__packed__)); static int app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in, uint8_t *key_out, uint32_t *signature) { uint8_t buffer[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; void *key_buffer = (key_out) ? key_out : buffer; switch (key_in->type) { case FLOW_KEY_QINQ: { struct pkt_key_qinq *qinq = key_buffer; qinq->ethertype_svlan = 0; qinq->svlan = rte_bswap16(key_in->key.qinq.svlan); qinq->ethertype_cvlan = 0; qinq->cvlan = rte_bswap16(key_in->key.qinq.cvlan); if (signature) *signature = (uint32_t) hash_default_key8(qinq, 8, 0); return 0; } case FLOW_KEY_IPV4_5TUPLE: { struct pkt_key_ipv4_5tuple *ipv4 = key_buffer; ipv4->ttl = 0; ipv4->proto = key_in->key.ipv4_5tuple.proto; ipv4->checksum = 0; ipv4->ip_src = rte_bswap32(key_in->key.ipv4_5tuple.ip_src); ipv4->ip_dst = rte_bswap32(key_in->key.ipv4_5tuple.ip_dst); ipv4->port_src = rte_bswap16(key_in->key.ipv4_5tuple.port_src); ipv4->port_dst = rte_bswap16(key_in->key.ipv4_5tuple.port_dst); if (signature) *signature = (uint32_t) hash_default_key16(ipv4, 16, 0); return 0; } case FLOW_KEY_IPV6_5TUPLE: { struct pkt_key_ipv6_5tuple *ipv6 = key_buffer; memset(ipv6, 0, 64); ipv6->payload_length = 0; ipv6->proto = key_in->key.ipv6_5tuple.proto; ipv6->hop_limit = 0; memcpy(&ipv6->ip_src, &key_in->key.ipv6_5tuple.ip_src, 16); memcpy(&ipv6->ip_dst, &key_in->key.ipv6_5tuple.ip_dst, 16); ipv6->port_src = rte_bswap16(key_in->key.ipv6_5tuple.port_src); ipv6->port_dst = rte_bswap16(key_in->key.ipv6_5tuple.port_dst); if (signature) *signature = (uint32_t) hash_default_key64(ipv6, 64, 0); return 0; } default: return -1; } } /* * Flow classification pipeline */ struct app_pipeline_fc_flow { struct pipeline_fc_key key; uint32_t port_id; uint32_t flow_id; uint32_t signature; void *entry_ptr; TAILQ_ENTRY(app_pipeline_fc_flow) node; }; #define N_BUCKETS 65536 struct app_pipeline_fc { /* Parameters */ uint32_t n_ports_in; uint32_t n_ports_out; /* Flows */ TAILQ_HEAD(, app_pipeline_fc_flow) flows[N_BUCKETS]; uint32_t n_flows; /* Default flow */ uint32_t default_flow_present; uint32_t default_flow_port_id; void *default_flow_entry_ptr; }; static struct app_pipeline_fc_flow * app_pipeline_fc_flow_find(struct app_pipeline_fc *p, struct pipeline_fc_key *key) { struct app_pipeline_fc_flow *f; uint32_t signature, bucket_id; app_pipeline_fc_key_convert(key, NULL, &signature); bucket_id = signature & (N_BUCKETS - 1); TAILQ_FOREACH(f, &p->flows[bucket_id], node) if ((signature == f->signature) && (memcmp(key, &f->key, sizeof(struct pipeline_fc_key)) == 0)) return f; return NULL; } static void* app_pipeline_fc_init(struct pipeline_params *params, __rte_unused void *arg) { struct app_pipeline_fc *p; uint32_t size, i; /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || (params->n_ports_out == 0)) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fc)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (p == NULL) return NULL; /* Initialization */ p->n_ports_in = params->n_ports_in; p->n_ports_out = params->n_ports_out; for (i = 0; i < N_BUCKETS; i++) TAILQ_INIT(&p->flows[i]); p->n_flows = 0; return (void *) p; } static int app_pipeline_fc_free(void *pipeline) { struct app_pipeline_fc *p = pipeline; uint32_t i; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ for (i = 0; i < N_BUCKETS; i++) while (!TAILQ_EMPTY(&p->flows[i])) { struct app_pipeline_fc_flow *flow; flow = TAILQ_FIRST(&p->flows[i]); TAILQ_REMOVE(&p->flows[i], flow, node); rte_free(flow); } rte_free(p); return 0; } static int app_pipeline_fc_key_check(struct pipeline_fc_key *key) { switch (key->type) { case FLOW_KEY_QINQ: { uint16_t svlan = key->key.qinq.svlan; uint16_t cvlan = key->key.qinq.cvlan; if ((svlan & 0xF000) || (cvlan & 0xF000)) return -1; return 0; } case FLOW_KEY_IPV4_5TUPLE: return 0; case FLOW_KEY_IPV6_5TUPLE: return 0; default: return -1; } } int app_pipeline_fc_add(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key, uint32_t port_id, uint32_t flow_id) { struct app_pipeline_fc *p; struct app_pipeline_fc_flow *flow; struct pipeline_fc_add_msg_req *req; struct pipeline_fc_add_msg_rsp *rsp; uint32_t signature; int new_flow; /* Check input arguments */ if ((app == NULL) || (key == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; if (app_pipeline_fc_key_check(key) != 0) return -1; /* Find existing flow or allocate new flow */ flow = app_pipeline_fc_flow_find(p, key); new_flow = (flow == NULL); if (flow == NULL) { flow = rte_malloc(NULL, sizeof(*flow), RTE_CACHE_LINE_SIZE); if (flow == NULL) return -1; } /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD; app_pipeline_fc_key_convert(key, req->key, &signature); req->port_id = port_id; req->flow_id = flow_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) { if (new_flow) rte_free(flow); return -1; } /* Read response and write flow */ if (rsp->status || (rsp->entry_ptr == NULL) || ((new_flow == 0) && (rsp->key_found == 0)) || ((new_flow == 1) && (rsp->key_found == 1))) { app_msg_free(app, rsp); if (new_flow) rte_free(flow); return -1; } memset(&flow->key, 0, sizeof(flow->key)); memcpy(&flow->key, key, sizeof(flow->key)); flow->port_id = port_id; flow->flow_id = flow_id; flow->signature = signature; flow->entry_ptr = rsp->entry_ptr; /* Commit rule */ if (new_flow) { uint32_t bucket_id = signature & (N_BUCKETS - 1); TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow, node); p->n_flows++; } /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_fc_add_bulk(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key, uint32_t *port_id, uint32_t *flow_id, uint32_t n_keys) { struct app_pipeline_fc *p; struct pipeline_fc_add_bulk_msg_req *req; struct pipeline_fc_add_bulk_msg_rsp *rsp; struct app_pipeline_fc_flow **flow; uint32_t *signature; int *new_flow; struct pipeline_fc_add_bulk_flow_req *flow_req; struct pipeline_fc_add_bulk_flow_rsp *flow_rsp; uint32_t i; int status; /* Check input arguments */ if ((app == NULL) || (key == NULL) || (port_id == NULL) || (flow_id == NULL) || (n_keys == 0)) return -1; p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); if (p == NULL) return -1; for (i = 0; i < n_keys; i++) if (port_id[i] >= p->n_ports_out) return -1; for (i = 0; i < n_keys; i++) if (app_pipeline_fc_key_check(&key[i]) != 0) return -1; /* Memory allocation */ flow = rte_malloc(NULL, n_keys * sizeof(struct app_pipeline_fc_flow *), RTE_CACHE_LINE_SIZE); if (flow == NULL) return -1; signature = rte_malloc(NULL, n_keys * sizeof(uint32_t), RTE_CACHE_LINE_SIZE); if (signature == NULL) { rte_free(flow); return -1; } new_flow = rte_malloc( NULL, n_keys * sizeof(int), RTE_CACHE_LINE_SIZE); if (new_flow == NULL) { rte_free(signature); rte_free(flow); return -1; } flow_req = rte_malloc(NULL, n_keys * sizeof(struct pipeline_fc_add_bulk_flow_req), RTE_CACHE_LINE_SIZE); if (flow_req == NULL) { rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } flow_rsp = rte_malloc(NULL, n_keys * sizeof(struct pipeline_fc_add_bulk_flow_rsp), RTE_CACHE_LINE_SIZE); if (flow_rsp == NULL) { rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } /* Find existing flow or allocate new flow */ for (i = 0; i < n_keys; i++) { flow[i] = app_pipeline_fc_flow_find(p, &key[i]); new_flow[i] = (flow[i] == NULL); if (flow[i] == NULL) { flow[i] = rte_zmalloc(NULL, sizeof(struct app_pipeline_fc_flow), RTE_CACHE_LINE_SIZE); if (flow[i] == NULL) { uint32_t j; for (j = 0; j < i; j++) if (new_flow[j]) rte_free(flow[j]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } } } /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) { for (i = 0; i < n_keys; i++) if (new_flow[i]) rte_free(flow[i]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } for (i = 0; i < n_keys; i++) { app_pipeline_fc_key_convert(&key[i], flow_req[i].key, &signature[i]); flow_req[i].port_id = port_id[i]; flow_req[i].flow_id = flow_id[i]; } req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK; req->req = flow_req; req->rsp = flow_rsp; req->n_keys = n_keys; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, 10000); if (rsp == NULL) { for (i = 0; i < n_keys; i++) if (new_flow[i]) rte_free(flow[i]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } /* Read response */ status = 0; for (i = 0; i < rsp->n_keys; i++) if ((flow_rsp[i].entry_ptr == NULL) || ((new_flow[i] == 0) && (flow_rsp[i].key_found == 0)) || ((new_flow[i] == 1) && (flow_rsp[i].key_found == 1))) status = -1; if (rsp->n_keys < n_keys) status = -1; /* Commit flows */ for (i = 0; i < rsp->n_keys; i++) { memcpy(&flow[i]->key, &key[i], sizeof(flow[i]->key)); flow[i]->port_id = port_id[i]; flow[i]->flow_id = flow_id[i]; flow[i]->signature = signature[i]; flow[i]->entry_ptr = flow_rsp[i].entry_ptr; if (new_flow[i]) { uint32_t bucket_id = signature[i] & (N_BUCKETS - 1); TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow[i], node); p->n_flows++; } } /* Free resources */ app_msg_free(app, rsp); for (i = rsp->n_keys; i < n_keys; i++) if (new_flow[i]) rte_free(flow[i]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return status; } int app_pipeline_fc_del(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key) { struct app_pipeline_fc *p; struct app_pipeline_fc_flow *flow; struct pipeline_fc_del_msg_req *req; struct pipeline_fc_del_msg_rsp *rsp; uint32_t signature, bucket_id; /* Check input arguments */ if ((app == NULL) || (key == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); if (p == NULL) return -1; if (app_pipeline_fc_key_check(key) != 0) return -1; /* Find rule */ flow = app_pipeline_fc_flow_find(p, key); if (flow == NULL) return 0; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL; app_pipeline_fc_key_convert(key, req->key, &signature); /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response */ if (rsp->status || !rsp->key_found) { app_msg_free(app, rsp); return -1; } /* Remove rule */ bucket_id = signature & (N_BUCKETS - 1); TAILQ_REMOVE(&p->flows[bucket_id], flow, node); p->n_flows--; rte_free(flow); /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_fc_add_default(struct app_params *app, uint32_t pipeline_id, uint32_t port_id) { struct app_pipeline_fc *p; struct pipeline_fc_add_default_msg_req *req; struct pipeline_fc_add_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response and write flow */ if (rsp->status || (rsp->entry_ptr == NULL)) { app_msg_free(app, rsp); return -1; } p->default_flow_port_id = port_id; p->default_flow_entry_ptr = rsp->entry_ptr; /* Commit route */ p->default_flow_present = 1; /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_fc_del_default(struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_fc *p; struct pipeline_fc_del_default_msg_req *req; struct pipeline_fc_del_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); if (p == NULL) return -EINVAL; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response */ if (rsp->status) { app_msg_free(app, rsp); return -1; } /* Commit route */ p->default_flow_present = 0; /* Free response */ app_msg_free(app, rsp); return 0; } /* * Flow ls */ static void print_fc_qinq_flow(struct app_pipeline_fc_flow *flow) { printf("(SVLAN = %" PRIu32 ", " "CVLAN = %" PRIu32 ") => " "Port = %" PRIu32 ", " "Flow ID = %" PRIu32 ", " "(signature = 0x%08" PRIx32 ", " "entry_ptr = %p)\n", flow->key.key.qinq.svlan, flow->key.key.qinq.cvlan, flow->port_id, flow->flow_id, flow->signature, flow->entry_ptr); } static void print_fc_ipv4_5tuple_flow(struct app_pipeline_fc_flow *flow) { printf("(SA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", " "DA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", " "SP = %" PRIu32 ", " "DP = %" PRIu32 ", " "Proto = %" PRIu32 ") => " "Port = %" PRIu32 ", " "Flow ID = %" PRIu32 " " "(signature = 0x%08" PRIx32 ", " "entry_ptr = %p)\n", (flow->key.key.ipv4_5tuple.ip_src >> 24) & 0xFF, (flow->key.key.ipv4_5tuple.ip_src >> 16) & 0xFF, (flow->key.key.ipv4_5tuple.ip_src >> 8) & 0xFF, flow->key.key.ipv4_5tuple.ip_src & 0xFF, (flow->key.key.ipv4_5tuple.ip_dst >> 24) & 0xFF, (flow->key.key.ipv4_5tuple.ip_dst >> 16) & 0xFF, (flow->key.key.ipv4_5tuple.ip_dst >> 8) & 0xFF, flow->key.key.ipv4_5tuple.ip_dst & 0xFF, flow->key.key.ipv4_5tuple.port_src, flow->key.key.ipv4_5tuple.port_dst, flow->key.key.ipv4_5tuple.proto, flow->port_id, flow->flow_id, flow->signature, flow->entry_ptr); } static void print_fc_ipv6_5tuple_flow(struct app_pipeline_fc_flow *flow) { printf("(SA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", " "DA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", " "SP = %" PRIu32 ", " "DP = %" PRIu32 " " "Proto = %" PRIu32 " " "=> Port = %" PRIu32 ", " "Flow ID = %" PRIu32 " " "(signature = 0x%08" PRIx32 ", " "entry_ptr = %p)\n", flow->key.key.ipv6_5tuple.ip_src[0], flow->key.key.ipv6_5tuple.ip_src[1], flow->key.key.ipv6_5tuple.ip_src[2], flow->key.key.ipv6_5tuple.ip_src[3], flow->key.key.ipv6_5tuple.ip_src[4], flow->key.key.ipv6_5tuple.ip_src[5], flow->key.key.ipv6_5tuple.ip_src[6], flow->key.key.ipv6_5tuple.ip_src[7], flow->key.key.ipv6_5tuple.ip_src[8], flow->key.key.ipv6_5tuple.ip_src[9], flow->key.key.ipv6_5tuple.ip_src[10], flow->key.key.ipv6_5tuple.ip_src[11], flow->key.key.ipv6_5tuple.ip_src[12], flow->key.key.ipv6_5tuple.ip_src[13], flow->key.key.ipv6_5tuple.ip_src[14], flow->key.key.ipv6_5tuple.ip_src[15], flow->key.key.ipv6_5tuple.ip_dst[0], flow->key.key.ipv6_5tuple.ip_dst[1], flow->key.key.ipv6_5tuple.ip_dst[2], flow->key.key.ipv6_5tuple.ip_dst[3], flow->key.key.ipv6_5tuple.ip_dst[4], flow->key.key.ipv6_5tuple.ip_dst[5], flow->key.key.ipv6_5tuple.ip_dst[6], flow->key.key.ipv6_5tuple.ip_dst[7], flow->key.key.ipv6_5tuple.ip_dst[8], flow->key.key.ipv6_5tuple.ip_dst[9], flow->key.key.ipv6_5tuple.ip_dst[10], flow->key.key.ipv6_5tuple.ip_dst[11], flow->key.key.ipv6_5tuple.ip_dst[12], flow->key.key.ipv6_5tuple.ip_dst[13], flow->key.key.ipv6_5tuple.ip_dst[14], flow->key.key.ipv6_5tuple.ip_dst[15], flow->key.key.ipv6_5tuple.port_src, flow->key.key.ipv6_5tuple.port_dst, flow->key.key.ipv6_5tuple.proto, flow->port_id, flow->flow_id, flow->signature, flow->entry_ptr); } static void print_fc_flow(struct app_pipeline_fc_flow *flow) { switch (flow->key.type) { case FLOW_KEY_QINQ: print_fc_qinq_flow(flow); break; case FLOW_KEY_IPV4_5TUPLE: print_fc_ipv4_5tuple_flow(flow); break; case FLOW_KEY_IPV6_5TUPLE: print_fc_ipv6_5tuple_flow(flow); break; } } static int app_pipeline_fc_ls(struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_fc *p; struct app_pipeline_fc_flow *flow; uint32_t i; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification); if (p == NULL) return -1; for (i = 0; i < N_BUCKETS; i++) TAILQ_FOREACH(flow, &p->flows[i], node) print_fc_flow(flow); if (p->default_flow_present) printf("Default flow: port %" PRIu32 " (entry ptr = %p)\n", p->default_flow_port_id, p->default_flow_entry_ptr); else printf("Default: DROP\n"); return 0; } /* * flow add qinq */ struct cmd_fc_add_qinq_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t qinq_string; uint16_t svlan; uint16_t cvlan; cmdline_fixed_string_t port_string; uint32_t port; cmdline_fixed_string_t flowid_string; uint32_t flow_id; }; static void cmd_fc_add_qinq_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_qinq_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_QINQ; key.key.qinq.svlan = params->svlan; key.key.qinq.cvlan = params->cvlan; status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port, params->flow_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_qinq_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_qinq_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_qinq_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_qinq_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_qinq_qinq_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, qinq_string, "qinq"); cmdline_parse_token_num_t cmd_fc_add_qinq_svlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, svlan, UINT16); cmdline_parse_token_num_t cmd_fc_add_qinq_cvlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, cvlan, UINT16); cmdline_parse_token_string_t cmd_fc_add_qinq_port_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, port_string, "port"); cmdline_parse_token_num_t cmd_fc_add_qinq_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, port, UINT32); cmdline_parse_token_string_t cmd_fc_add_qinq_flowid_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flowid_string, "flowid"); cmdline_parse_token_num_t cmd_fc_add_qinq_flow_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, flow_id, UINT32); cmdline_parse_inst_t cmd_fc_add_qinq = { .f = cmd_fc_add_qinq_parsed, .data = NULL, .help_str = "Flow add (Q-in-Q)", .tokens = { (void *) &cmd_fc_add_qinq_p_string, (void *) &cmd_fc_add_qinq_pipeline_id, (void *) &cmd_fc_add_qinq_flow_string, (void *) &cmd_fc_add_qinq_add_string, (void *) &cmd_fc_add_qinq_qinq_string, (void *) &cmd_fc_add_qinq_svlan, (void *) &cmd_fc_add_qinq_cvlan, (void *) &cmd_fc_add_qinq_port_string, (void *) &cmd_fc_add_qinq_port, (void *) &cmd_fc_add_qinq_flowid_string, (void *) &cmd_fc_add_qinq_flow_id, NULL, }, }; /* * flow add qinq all */ struct cmd_fc_add_qinq_all_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t qinq_string; cmdline_fixed_string_t all_string; uint32_t n_flows; uint32_t n_ports; }; #ifndef N_FLOWS_BULK #define N_FLOWS_BULK 4096 #endif static void cmd_fc_add_qinq_all_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_qinq_all_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key *key; uint32_t *port_id; uint32_t *flow_id; uint32_t id; /* Check input arguments */ if (params->n_flows == 0) { printf("Invalid number of flows\n"); return; } if (params->n_ports == 0) { printf("Invalid number of output ports\n"); return; } /* Memory allocation */ key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE); if (key == NULL) { printf("Memory allocation failed\n"); return; } port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE); if (port_id == NULL) { rte_free(key); printf("Memory allocation failed\n"); return; } flow_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*flow_id), RTE_CACHE_LINE_SIZE); if (flow_id == NULL) { rte_free(port_id); rte_free(key); printf("Memory allocation failed\n"); return; } /* Flow add */ for (id = 0; id < params->n_flows; id++) { uint32_t pos = id & (N_FLOWS_BULK - 1); key[pos].type = FLOW_KEY_QINQ; key[pos].key.qinq.svlan = id >> 12; key[pos].key.qinq.cvlan = id & 0xFFF; port_id[pos] = id % params->n_ports; flow_id[pos] = id; if ((pos == N_FLOWS_BULK - 1) || (id == params->n_flows - 1)) { int status; status = app_pipeline_fc_add_bulk(app, params->pipeline_id, key, port_id, flow_id, pos + 1); if (status != 0) { printf("Command failed\n"); break; } } } /* Memory free */ rte_free(flow_id); rte_free(port_id); rte_free(key); } cmdline_parse_token_string_t cmd_fc_add_qinq_all_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_qinq_all_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_qinq_all_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_qinq_all_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_qinq_all_qinq_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, qinq_string, "qinq"); cmdline_parse_token_string_t cmd_fc_add_qinq_all_all_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, all_string, "all"); cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_flows = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_flows, UINT32); cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_ports = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_ports, UINT32); cmdline_parse_inst_t cmd_fc_add_qinq_all = { .f = cmd_fc_add_qinq_all_parsed, .data = NULL, .help_str = "Flow add all (Q-in-Q)", .tokens = { (void *) &cmd_fc_add_qinq_all_p_string, (void *) &cmd_fc_add_qinq_all_pipeline_id, (void *) &cmd_fc_add_qinq_all_flow_string, (void *) &cmd_fc_add_qinq_all_add_string, (void *) &cmd_fc_add_qinq_all_qinq_string, (void *) &cmd_fc_add_qinq_all_all_string, (void *) &cmd_fc_add_qinq_all_n_flows, (void *) &cmd_fc_add_qinq_all_n_ports, NULL, }, }; /* * flow add ipv4_5tuple */ struct cmd_fc_add_ipv4_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv4_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; cmdline_fixed_string_t port_string; uint32_t port; cmdline_fixed_string_t flowid_string; uint32_t flow_id; }; static void cmd_fc_add_ipv4_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv4_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV4_5TUPLE; key.key.ipv4_5tuple.ip_src = rte_bswap32( params->ip_src.addr.ipv4.s_addr); key.key.ipv4_5tuple.ip_dst = rte_bswap32( params->ip_dst.addr.ipv4.s_addr); key.key.ipv4_5tuple.port_src = params->port_src; key.key.ipv4_5tuple.port_dst = params->port_dst; key.key.ipv4_5tuple.proto = params->proto; status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port, params->flow_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_src = TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_dst = TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, proto, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_port_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_string, "port"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flowid_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flowid_string, "flowid"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_flow_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flow_id, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple = { .f = cmd_fc_add_ipv4_5tuple_parsed, .data = NULL, .help_str = "Flow add (IPv4 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv4_5tuple_p_string, (void *) &cmd_fc_add_ipv4_5tuple_pipeline_id, (void *) &cmd_fc_add_ipv4_5tuple_flow_string, (void *) &cmd_fc_add_ipv4_5tuple_add_string, (void *) &cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string, (void *) &cmd_fc_add_ipv4_5tuple_ip_src, (void *) &cmd_fc_add_ipv4_5tuple_ip_dst, (void *) &cmd_fc_add_ipv4_5tuple_port_src, (void *) &cmd_fc_add_ipv4_5tuple_port_dst, (void *) &cmd_fc_add_ipv4_5tuple_proto, (void *) &cmd_fc_add_ipv4_5tuple_port_string, (void *) &cmd_fc_add_ipv4_5tuple_port, (void *) &cmd_fc_add_ipv4_5tuple_flowid_string, (void *) &cmd_fc_add_ipv4_5tuple_flow_id, NULL, }, }; /* * flow add ipv4_5tuple all */ struct cmd_fc_add_ipv4_5tuple_all_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv4_5tuple_string; cmdline_fixed_string_t all_string; uint32_t n_flows; uint32_t n_ports; }; static void cmd_fc_add_ipv4_5tuple_all_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv4_5tuple_all_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key *key; uint32_t *port_id; uint32_t *flow_id; uint32_t id; /* Check input parameters */ if (params->n_flows == 0) { printf("Invalid number of flows\n"); return; } if (params->n_ports == 0) { printf("Invalid number of ports\n"); return; } /* Memory allocation */ key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE); if (key == NULL) { printf("Memory allocation failed\n"); return; } port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE); if (port_id == NULL) { rte_free(key); printf("Memory allocation failed\n"); return; } flow_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*flow_id), RTE_CACHE_LINE_SIZE); if (flow_id == NULL) { rte_free(port_id); rte_free(key); printf("Memory allocation failed\n"); return; } /* Flow add */ for (id = 0; id < params->n_flows; id++) { uint32_t pos = id & (N_FLOWS_BULK - 1); key[pos].type = FLOW_KEY_IPV4_5TUPLE; key[pos].key.ipv4_5tuple.ip_src = 0; key[pos].key.ipv4_5tuple.ip_dst = id; key[pos].key.ipv4_5tuple.port_src = 0; key[pos].key.ipv4_5tuple.port_dst = 0; key[pos].key.ipv4_5tuple.proto = 6; port_id[pos] = id % params->n_ports; flow_id[pos] = id; if ((pos == N_FLOWS_BULK - 1) || (id == params->n_flows - 1)) { int status; status = app_pipeline_fc_add_bulk(app, params->pipeline_id, key, port_id, flow_id, pos + 1); if (status != 0) { printf("Command failed\n"); break; } } } /* Memory free */ rte_free(flow_id); rte_free(port_id); rte_free(key); } cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, ipv4_5tuple_string, "ipv4_5tuple"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_all_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, all_string, "all"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_flows = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, n_flows, UINT32); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_ports = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, n_ports, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple_all = { .f = cmd_fc_add_ipv4_5tuple_all_parsed, .data = NULL, .help_str = "Flow add all (IPv4 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv4_5tuple_all_p_string, (void *) &cmd_fc_add_ipv4_5tuple_all_pipeline_id, (void *) &cmd_fc_add_ipv4_5tuple_all_flow_string, (void *) &cmd_fc_add_ipv4_5tuple_all_add_string, (void *) &cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string, (void *) &cmd_fc_add_ipv4_5tuple_all_all_string, (void *) &cmd_fc_add_ipv4_5tuple_all_n_flows, (void *) &cmd_fc_add_ipv4_5tuple_all_n_ports, NULL, }, }; /* * flow add ipv6_5tuple */ struct cmd_fc_add_ipv6_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv6_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; cmdline_fixed_string_t port_string; uint32_t port; cmdline_fixed_string_t flowid_string; uint32_t flow_id; }; static void cmd_fc_add_ipv6_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv6_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV6_5TUPLE; memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16); memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16); key.key.ipv6_5tuple.port_src = params->port_src; key.key.ipv6_5tuple.port_dst = params->port_dst; key.key.ipv6_5tuple.proto = params->proto; status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port, params->flow_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_src = TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_dst = TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, proto, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_port_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_string, "port"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flowid_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flowid_string, "flowid"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_flow_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flow_id, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple = { .f = cmd_fc_add_ipv6_5tuple_parsed, .data = NULL, .help_str = "Flow add (IPv6 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv6_5tuple_p_string, (void *) &cmd_fc_add_ipv6_5tuple_pipeline_id, (void *) &cmd_fc_add_ipv6_5tuple_flow_string, (void *) &cmd_fc_add_ipv6_5tuple_add_string, (void *) &cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string, (void *) &cmd_fc_add_ipv6_5tuple_ip_src, (void *) &cmd_fc_add_ipv6_5tuple_ip_dst, (void *) &cmd_fc_add_ipv6_5tuple_port_src, (void *) &cmd_fc_add_ipv6_5tuple_port_dst, (void *) &cmd_fc_add_ipv6_5tuple_proto, (void *) &cmd_fc_add_ipv6_5tuple_port_string, (void *) &cmd_fc_add_ipv6_5tuple_port, (void *) &cmd_fc_add_ipv6_5tuple_flowid_string, (void *) &cmd_fc_add_ipv6_5tuple_flow_id, NULL, }, }; /* * flow add ipv6_5tuple all */ struct cmd_fc_add_ipv6_5tuple_all_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv6_5tuple_string; cmdline_fixed_string_t all_string; uint32_t n_flows; uint32_t n_ports; }; static void cmd_fc_add_ipv6_5tuple_all_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv6_5tuple_all_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key *key; uint32_t *port_id; uint32_t *flow_id; uint32_t id; /* Check input parameters */ if (params->n_flows == 0) { printf("Invalid number of flows\n"); return; } if (params->n_ports == 0) { printf("Invalid number of ports\n"); return; } /* Memory allocation */ key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE); if (key == NULL) { printf("Memory allocation failed\n"); return; } port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE); if (port_id == NULL) { rte_free(key); printf("Memory allocation failed\n"); return; } flow_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*flow_id), RTE_CACHE_LINE_SIZE); if (flow_id == NULL) { rte_free(port_id); rte_free(key); printf("Memory allocation failed\n"); return; } /* Flow add */ for (id = 0; id < params->n_flows; id++) { uint32_t pos = id & (N_FLOWS_BULK - 1); uint32_t *x; key[pos].type = FLOW_KEY_IPV6_5TUPLE; x = (uint32_t *) key[pos].key.ipv6_5tuple.ip_dst; *x = rte_bswap32(id); key[pos].key.ipv6_5tuple.proto = 6; port_id[pos] = id % params->n_ports; flow_id[pos] = id; if ((pos == N_FLOWS_BULK - 1) || (id == params->n_flows - 1)) { int status; status = app_pipeline_fc_add_bulk(app, params->pipeline_id, key, port_id, flow_id, pos + 1); if (status != 0) { printf("Command failed\n"); break; } } } /* Memory free */ rte_free(flow_id); rte_free(port_id); rte_free(key); } cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, ipv6_5tuple_string, "ipv6_5tuple"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_all_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, all_string, "all"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_flows = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, n_flows, UINT32); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_ports = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, n_ports, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple_all = { .f = cmd_fc_add_ipv6_5tuple_all_parsed, .data = NULL, .help_str = "Flow add all (ipv6 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv6_5tuple_all_p_string, (void *) &cmd_fc_add_ipv6_5tuple_all_pipeline_id, (void *) &cmd_fc_add_ipv6_5tuple_all_flow_string, (void *) &cmd_fc_add_ipv6_5tuple_all_add_string, (void *) &cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string, (void *) &cmd_fc_add_ipv6_5tuple_all_all_string, (void *) &cmd_fc_add_ipv6_5tuple_all_n_flows, (void *) &cmd_fc_add_ipv6_5tuple_all_n_ports, NULL, }, }; /* * flow del qinq */ struct cmd_fc_del_qinq_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t qinq_string; uint16_t svlan; uint16_t cvlan; }; static void cmd_fc_del_qinq_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_qinq_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_QINQ; key.key.qinq.svlan = params->svlan; key.key.qinq.cvlan = params->cvlan; status = app_pipeline_fc_del(app, params->pipeline_id, &key); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_qinq_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_qinq_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_qinq_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_qinq_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_qinq_qinq_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, qinq_string, "qinq"); cmdline_parse_token_num_t cmd_fc_del_qinq_svlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, svlan, UINT16); cmdline_parse_token_num_t cmd_fc_del_qinq_cvlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, cvlan, UINT16); cmdline_parse_inst_t cmd_fc_del_qinq = { .f = cmd_fc_del_qinq_parsed, .data = NULL, .help_str = "Flow delete (Q-in-Q)", .tokens = { (void *) &cmd_fc_del_qinq_p_string, (void *) &cmd_fc_del_qinq_pipeline_id, (void *) &cmd_fc_del_qinq_flow_string, (void *) &cmd_fc_del_qinq_del_string, (void *) &cmd_fc_del_qinq_qinq_string, (void *) &cmd_fc_del_qinq_svlan, (void *) &cmd_fc_del_qinq_cvlan, NULL, }, }; /* * flow del ipv4_5tuple */ struct cmd_fc_del_ipv4_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t ipv4_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; }; static void cmd_fc_del_ipv4_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_ipv4_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV4_5TUPLE; key.key.ipv4_5tuple.ip_src = rte_bswap32( params->ip_src.addr.ipv4.s_addr); key.key.ipv4_5tuple.ip_dst = rte_bswap32( params->ip_dst.addr.ipv4.s_addr); key.key.ipv4_5tuple.port_src = params->port_src; key.key.ipv4_5tuple.port_dst = params->port_dst; key.key.ipv4_5tuple.proto = params->proto; status = app_pipeline_fc_del(app, params->pipeline_id, &key); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_src = TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_dst = TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, proto, UINT32); cmdline_parse_inst_t cmd_fc_del_ipv4_5tuple = { .f = cmd_fc_del_ipv4_5tuple_parsed, .data = NULL, .help_str = "Flow delete (IPv4 5-tuple)", .tokens = { (void *) &cmd_fc_del_ipv4_5tuple_p_string, (void *) &cmd_fc_del_ipv4_5tuple_pipeline_id, (void *) &cmd_fc_del_ipv4_5tuple_flow_string, (void *) &cmd_fc_del_ipv4_5tuple_del_string, (void *) &cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string, (void *) &cmd_fc_del_ipv4_5tuple_ip_src, (void *) &cmd_fc_del_ipv4_5tuple_ip_dst, (void *) &cmd_fc_del_ipv4_5tuple_port_src, (void *) &cmd_fc_del_ipv4_5tuple_port_dst, (void *) &cmd_fc_del_ipv4_5tuple_proto, NULL, }, }; /* * flow del ipv6_5tuple */ struct cmd_fc_del_ipv6_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t ipv6_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; }; static void cmd_fc_del_ipv6_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_ipv6_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV6_5TUPLE; memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16); memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16); key.key.ipv6_5tuple.port_src = params->port_src; key.key.ipv6_5tuple.port_dst = params->port_dst; key.key.ipv6_5tuple.proto = params->proto; status = app_pipeline_fc_del(app, params->pipeline_id, &key); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_src = TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_dst = TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, proto, UINT32); cmdline_parse_inst_t cmd_fc_del_ipv6_5tuple = { .f = cmd_fc_del_ipv6_5tuple_parsed, .data = NULL, .help_str = "Flow delete (IPv6 5-tuple)", .tokens = { (void *) &cmd_fc_del_ipv6_5tuple_p_string, (void *) &cmd_fc_del_ipv6_5tuple_pipeline_id, (void *) &cmd_fc_del_ipv6_5tuple_flow_string, (void *) &cmd_fc_del_ipv6_5tuple_del_string, (void *) &cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string, (void *) &cmd_fc_del_ipv6_5tuple_ip_src, (void *) &cmd_fc_del_ipv6_5tuple_ip_dst, (void *) &cmd_fc_del_ipv6_5tuple_port_src, (void *) &cmd_fc_del_ipv6_5tuple_port_dst, (void *) &cmd_fc_del_ipv6_5tuple_proto, NULL, }, }; /* * flow add default */ struct cmd_fc_add_default_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t default_string; uint32_t port; }; static void cmd_fc_add_default_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_fc_add_default(app, params->pipeline_id, params->port); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_default_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_default_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_default_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, default_string, "default"); cmdline_parse_token_num_t cmd_fc_add_default_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, port, UINT32); cmdline_parse_inst_t cmd_fc_add_default = { .f = cmd_fc_add_default_parsed, .data = NULL, .help_str = "Flow add default", .tokens = { (void *) &cmd_fc_add_default_p_string, (void *) &cmd_fc_add_default_pipeline_id, (void *) &cmd_fc_add_default_flow_string, (void *) &cmd_fc_add_default_add_string, (void *) &cmd_fc_add_default_default_string, (void *) &cmd_fc_add_default_port, NULL, }, }; /* * flow del default */ struct cmd_fc_del_default_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t default_string; }; static void cmd_fc_del_default_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_fc_del_default(app, params->pipeline_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_default_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_default_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_default_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, default_string, "default"); cmdline_parse_inst_t cmd_fc_del_default = { .f = cmd_fc_del_default_parsed, .data = NULL, .help_str = "Flow delete default", .tokens = { (void *) &cmd_fc_del_default_p_string, (void *) &cmd_fc_del_default_pipeline_id, (void *) &cmd_fc_del_default_flow_string, (void *) &cmd_fc_del_default_del_string, (void *) &cmd_fc_del_default_default_string, NULL, }, }; /* * flow ls */ struct cmd_fc_ls_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t ls_string; }; static void cmd_fc_ls_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_fc_ls_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_fc_ls(app, params->pipeline_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_ls_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_ls_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_ls_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_ls_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_ls_ls_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, ls_string, "ls"); cmdline_parse_inst_t cmd_fc_ls = { .f = cmd_fc_ls_parsed, .data = NULL, .help_str = "Flow list", .tokens = { (void *) &cmd_fc_ls_p_string, (void *) &cmd_fc_ls_pipeline_id, (void *) &cmd_fc_ls_flow_string, (void *) &cmd_fc_ls_ls_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { (cmdline_parse_inst_t *) &cmd_fc_add_qinq, (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple, (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple, (cmdline_parse_inst_t *) &cmd_fc_del_qinq, (cmdline_parse_inst_t *) &cmd_fc_del_ipv4_5tuple, (cmdline_parse_inst_t *) &cmd_fc_del_ipv6_5tuple, (cmdline_parse_inst_t *) &cmd_fc_add_default, (cmdline_parse_inst_t *) &cmd_fc_del_default, (cmdline_parse_inst_t *) &cmd_fc_add_qinq_all, (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple_all, (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple_all, (cmdline_parse_inst_t *) &cmd_fc_ls, NULL, }; static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = { .f_init = app_pipeline_fc_init, .f_free = app_pipeline_fc_free, .cmds = pipeline_cmds, }; struct pipeline_type pipeline_flow_classification = { .name = "FLOW_CLASSIFICATION", .be_ops = &pipeline_flow_classification_be_ops, .fe_ops = &pipeline_flow_classification_fe_ops, };