1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
8 #include <netinet/in.h>
11 #include <rte_common.h>
12 #include <rte_hexdump.h>
13 #include <rte_malloc.h>
14 #include <cmdline_rdline.h>
15 #include <cmdline_parse.h>
16 #include <cmdline_parse_num.h>
17 #include <cmdline_parse_string.h>
20 #include "pipeline_common_fe.h"
21 #include "pipeline_flow_classification.h"
22 #include "hash_func.h"
30 uint16_t ethertype_svlan;
32 uint16_t ethertype_cvlan;
34 } __attribute__((__packed__));
36 struct pkt_key_ipv4_5tuple {
44 } __attribute__((__packed__));
46 struct pkt_key_ipv6_5tuple {
47 uint16_t payload_length;
54 } __attribute__((__packed__));
57 app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in,
61 uint8_t buffer[PIPELINE_FC_FLOW_KEY_MAX_SIZE];
62 uint8_t m[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; /* key mask */
63 void *key_buffer = (key_out) ? key_out : buffer;
65 memset(m, 0xFF, sizeof(m));
66 switch (key_in->type) {
69 struct pkt_key_qinq *qinq = key_buffer;
71 qinq->ethertype_svlan = 0;
72 qinq->svlan = rte_cpu_to_be_16(key_in->key.qinq.svlan);
73 qinq->ethertype_cvlan = 0;
74 qinq->cvlan = rte_cpu_to_be_16(key_in->key.qinq.cvlan);
77 *signature = (uint32_t) hash_default_key8(qinq, m, 8, 0);
81 case FLOW_KEY_IPV4_5TUPLE:
83 struct pkt_key_ipv4_5tuple *ipv4 = key_buffer;
86 ipv4->proto = key_in->key.ipv4_5tuple.proto;
88 ipv4->ip_src = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_src);
89 ipv4->ip_dst = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_dst);
90 ipv4->port_src = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_src);
91 ipv4->port_dst = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_dst);
94 *signature = (uint32_t) hash_default_key16(ipv4, m, 16, 0);
98 case FLOW_KEY_IPV6_5TUPLE:
100 struct pkt_key_ipv6_5tuple *ipv6 = key_buffer;
103 ipv6->payload_length = 0;
104 ipv6->proto = key_in->key.ipv6_5tuple.proto;
106 memcpy(&ipv6->ip_src, &key_in->key.ipv6_5tuple.ip_src, 16);
107 memcpy(&ipv6->ip_dst, &key_in->key.ipv6_5tuple.ip_dst, 16);
108 ipv6->port_src = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_src);
109 ipv6->port_dst = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_dst);
112 *signature = (uint32_t) hash_default_key64(ipv6, m, 64, 0);
122 * Flow classification pipeline
125 struct app_pipeline_fc_flow {
126 struct pipeline_fc_key key;
132 TAILQ_ENTRY(app_pipeline_fc_flow) node;
135 #define N_BUCKETS 65536
137 struct app_pipeline_fc {
140 uint32_t n_ports_out;
143 TAILQ_HEAD(, app_pipeline_fc_flow) flows[N_BUCKETS];
147 uint32_t default_flow_present;
148 uint32_t default_flow_port_id;
149 void *default_flow_entry_ptr;
152 static struct app_pipeline_fc_flow *
153 app_pipeline_fc_flow_find(struct app_pipeline_fc *p,
154 struct pipeline_fc_key *key)
156 struct app_pipeline_fc_flow *f;
157 uint32_t signature, bucket_id;
159 app_pipeline_fc_key_convert(key, NULL, &signature);
160 bucket_id = signature & (N_BUCKETS - 1);
162 TAILQ_FOREACH(f, &p->flows[bucket_id], node)
163 if ((signature == f->signature) &&
166 sizeof(struct pipeline_fc_key)) == 0))
173 app_pipeline_fc_init(struct pipeline_params *params,
174 __rte_unused void *arg)
176 struct app_pipeline_fc *p;
179 /* Check input arguments */
180 if ((params == NULL) ||
181 (params->n_ports_in == 0) ||
182 (params->n_ports_out == 0))
185 /* Memory allocation */
186 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fc));
187 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
192 p->n_ports_in = params->n_ports_in;
193 p->n_ports_out = params->n_ports_out;
195 for (i = 0; i < N_BUCKETS; i++)
196 TAILQ_INIT(&p->flows[i]);
203 app_pipeline_fc_free(void *pipeline)
205 struct app_pipeline_fc *p = pipeline;
208 /* Check input arguments */
213 for (i = 0; i < N_BUCKETS; i++)
214 while (!TAILQ_EMPTY(&p->flows[i])) {
215 struct app_pipeline_fc_flow *flow;
217 flow = TAILQ_FIRST(&p->flows[i]);
218 TAILQ_REMOVE(&p->flows[i], flow, node);
227 app_pipeline_fc_key_check(struct pipeline_fc_key *key)
232 uint16_t svlan = key->key.qinq.svlan;
233 uint16_t cvlan = key->key.qinq.cvlan;
235 if ((svlan & 0xF000) ||
242 case FLOW_KEY_IPV4_5TUPLE:
245 case FLOW_KEY_IPV6_5TUPLE:
254 app_pipeline_fc_load_file_qinq(char *filename,
255 struct pipeline_fc_key *keys,
265 /* Check input arguments */
266 if ((filename == NULL) ||
268 (port_ids == NULL) ||
269 (flow_ids == NULL) ||
278 /* Open input file */
279 f = fopen(filename, "r");
286 for (i = 0, l = 1; i < *n_keys; l++) {
288 uint32_t n_tokens = RTE_DIM(tokens);
290 uint16_t svlan, cvlan;
291 uint32_t portid, flowid;
294 if (fgets(file_buf, sizeof(file_buf), f) == NULL)
297 status = parse_tokenize_string(file_buf, tokens, &n_tokens);
301 if ((n_tokens == 0) || (tokens[0][0] == '#'))
304 if ((n_tokens != 7) ||
305 strcmp(tokens[0], "qinq") ||
306 parser_read_uint16(&svlan, tokens[1]) ||
307 parser_read_uint16(&cvlan, tokens[2]) ||
308 strcmp(tokens[3], "port") ||
309 parser_read_uint32(&portid, tokens[4]) ||
310 strcmp(tokens[5], "id") ||
311 parser_read_uint32(&flowid, tokens[6]))
314 keys[i].type = FLOW_KEY_QINQ;
315 keys[i].key.qinq.svlan = svlan;
316 keys[i].key.qinq.cvlan = cvlan;
318 port_ids[i] = portid;
319 flow_ids[i] = flowid;
321 if (app_pipeline_fc_key_check(&keys[i]))
339 app_pipeline_fc_load_file_ipv4(char *filename,
340 struct pipeline_fc_key *keys,
350 /* Check input arguments */
351 if ((filename == NULL) ||
353 (port_ids == NULL) ||
354 (flow_ids == NULL) ||
363 /* Open input file */
364 f = fopen(filename, "r");
371 for (i = 0, l = 1; i < *n_keys; l++) {
373 uint32_t n_tokens = RTE_DIM(tokens);
375 struct in_addr sipaddr, dipaddr;
376 uint16_t sport, dport;
378 uint32_t portid, flowid;
381 if (fgets(file_buf, sizeof(file_buf), f) == NULL)
384 status = parse_tokenize_string(file_buf, tokens, &n_tokens);
388 if ((n_tokens == 0) || (tokens[0][0] == '#'))
391 if ((n_tokens != 10) ||
392 strcmp(tokens[0], "ipv4") ||
393 parse_ipv4_addr(tokens[1], &sipaddr) ||
394 parse_ipv4_addr(tokens[2], &dipaddr) ||
395 parser_read_uint16(&sport, tokens[3]) ||
396 parser_read_uint16(&dport, tokens[4]) ||
397 parser_read_uint8(&proto, tokens[5]) ||
398 strcmp(tokens[6], "port") ||
399 parser_read_uint32(&portid, tokens[7]) ||
400 strcmp(tokens[8], "id") ||
401 parser_read_uint32(&flowid, tokens[9]))
404 keys[i].type = FLOW_KEY_IPV4_5TUPLE;
405 keys[i].key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr);
406 keys[i].key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr);
407 keys[i].key.ipv4_5tuple.port_src = sport;
408 keys[i].key.ipv4_5tuple.port_dst = dport;
409 keys[i].key.ipv4_5tuple.proto = proto;
411 port_ids[i] = portid;
412 flow_ids[i] = flowid;
414 if (app_pipeline_fc_key_check(&keys[i]))
432 app_pipeline_fc_load_file_ipv6(char *filename,
433 struct pipeline_fc_key *keys,
443 /* Check input arguments */
444 if ((filename == NULL) ||
446 (port_ids == NULL) ||
447 (flow_ids == NULL) ||
456 /* Open input file */
457 f = fopen(filename, "r");
464 for (i = 0, l = 1; i < *n_keys; l++) {
466 uint32_t n_tokens = RTE_DIM(tokens);
468 struct in6_addr sipaddr, dipaddr;
469 uint16_t sport, dport;
471 uint32_t portid, flowid;
474 if (fgets(file_buf, sizeof(file_buf), f) == NULL)
477 status = parse_tokenize_string(file_buf, tokens, &n_tokens);
481 if ((n_tokens == 0) || (tokens[0][0] == '#'))
484 if ((n_tokens != 10) ||
485 strcmp(tokens[0], "ipv6") ||
486 parse_ipv6_addr(tokens[1], &sipaddr) ||
487 parse_ipv6_addr(tokens[2], &dipaddr) ||
488 parser_read_uint16(&sport, tokens[3]) ||
489 parser_read_uint16(&dport, tokens[4]) ||
490 parser_read_uint8(&proto, tokens[5]) ||
491 strcmp(tokens[6], "port") ||
492 parser_read_uint32(&portid, tokens[7]) ||
493 strcmp(tokens[8], "id") ||
494 parser_read_uint32(&flowid, tokens[9]))
497 keys[i].type = FLOW_KEY_IPV6_5TUPLE;
498 memcpy(keys[i].key.ipv6_5tuple.ip_src,
500 sizeof(sipaddr.s6_addr));
501 memcpy(keys[i].key.ipv6_5tuple.ip_dst,
503 sizeof(dipaddr.s6_addr));
504 keys[i].key.ipv6_5tuple.port_src = sport;
505 keys[i].key.ipv6_5tuple.port_dst = dport;
506 keys[i].key.ipv6_5tuple.proto = proto;
508 port_ids[i] = portid;
509 flow_ids[i] = flowid;
511 if (app_pipeline_fc_key_check(&keys[i]))
531 app_pipeline_fc_add(struct app_params *app,
532 uint32_t pipeline_id,
533 struct pipeline_fc_key *key,
537 struct app_pipeline_fc *p;
538 struct app_pipeline_fc_flow *flow;
540 struct pipeline_fc_add_msg_req *req;
541 struct pipeline_fc_add_msg_rsp *rsp;
546 /* Check input arguments */
551 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification);
555 if (port_id >= p->n_ports_out)
558 if (app_pipeline_fc_key_check(key) != 0)
561 /* Find existing flow or allocate new flow */
562 flow = app_pipeline_fc_flow_find(p, key);
563 new_flow = (flow == NULL);
565 flow = rte_malloc(NULL, sizeof(*flow), RTE_CACHE_LINE_SIZE);
571 /* Allocate and write request */
572 req = app_msg_alloc(app);
576 req->type = PIPELINE_MSG_REQ_CUSTOM;
577 req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD;
578 app_pipeline_fc_key_convert(key, req->key, &signature);
579 req->port_id = port_id;
580 req->flow_id = flow_id;
582 /* Send request and wait for response */
583 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
590 /* Read response and write flow */
592 (rsp->entry_ptr == NULL) ||
593 ((new_flow == 0) && (rsp->key_found == 0)) ||
594 ((new_flow == 1) && (rsp->key_found == 1))) {
595 app_msg_free(app, rsp);
601 memset(&flow->key, 0, sizeof(flow->key));
602 memcpy(&flow->key, key, sizeof(flow->key));
603 flow->port_id = port_id;
604 flow->flow_id = flow_id;
605 flow->signature = signature;
606 flow->entry_ptr = rsp->entry_ptr;
610 uint32_t bucket_id = signature & (N_BUCKETS - 1);
612 TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow, node);
617 app_msg_free(app, rsp);
623 app_pipeline_fc_add_bulk(struct app_params *app,
624 uint32_t pipeline_id,
625 struct pipeline_fc_key *key,
630 struct app_pipeline_fc *p;
631 struct pipeline_fc_add_bulk_msg_req *req;
632 struct pipeline_fc_add_bulk_msg_rsp *rsp;
634 struct app_pipeline_fc_flow **flow;
637 struct pipeline_fc_add_bulk_flow_req *flow_req;
638 struct pipeline_fc_add_bulk_flow_rsp *flow_rsp;
643 /* Check input arguments */
651 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification);
655 for (i = 0; i < n_keys; i++)
656 if (port_id[i] >= p->n_ports_out)
659 for (i = 0; i < n_keys; i++)
660 if (app_pipeline_fc_key_check(&key[i]) != 0)
663 /* Memory allocation */
664 flow = rte_malloc(NULL,
665 n_keys * sizeof(struct app_pipeline_fc_flow *),
666 RTE_CACHE_LINE_SIZE);
670 signature = rte_malloc(NULL,
671 n_keys * sizeof(uint32_t),
672 RTE_CACHE_LINE_SIZE);
673 if (signature == NULL) {
678 new_flow = rte_malloc(
680 n_keys * sizeof(int),
681 RTE_CACHE_LINE_SIZE);
682 if (new_flow == NULL) {
688 flow_req = rte_malloc(NULL,
689 n_keys * sizeof(struct pipeline_fc_add_bulk_flow_req),
690 RTE_CACHE_LINE_SIZE);
691 if (flow_req == NULL) {
698 flow_rsp = rte_malloc(NULL,
699 n_keys * sizeof(struct pipeline_fc_add_bulk_flow_rsp),
700 RTE_CACHE_LINE_SIZE);
701 if (flow_rsp == NULL) {
709 /* Find existing flow or allocate new flow */
710 for (i = 0; i < n_keys; i++) {
711 flow[i] = app_pipeline_fc_flow_find(p, &key[i]);
712 new_flow[i] = (flow[i] == NULL);
713 if (flow[i] == NULL) {
714 flow[i] = rte_zmalloc(NULL,
715 sizeof(struct app_pipeline_fc_flow),
716 RTE_CACHE_LINE_SIZE);
718 if (flow[i] == NULL) {
721 for (j = 0; j < i; j++)
735 /* Allocate and write request */
736 req = app_msg_alloc(app);
738 for (i = 0; i < n_keys; i++)
750 for (i = 0; i < n_keys; i++) {
751 app_pipeline_fc_key_convert(&key[i],
754 flow_req[i].port_id = port_id[i];
755 flow_req[i].flow_id = flow_id[i];
758 req->type = PIPELINE_MSG_REQ_CUSTOM;
759 req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK;
762 req->n_keys = n_keys;
764 /* Send request and wait for response */
765 rsp = app_msg_send_recv(app, pipeline_id, req, 10000);
767 for (i = 0; i < n_keys; i++)
782 for (i = 0; i < rsp->n_keys; i++)
783 if ((flow_rsp[i].entry_ptr == NULL) ||
784 ((new_flow[i] == 0) && (flow_rsp[i].key_found == 0)) ||
785 ((new_flow[i] == 1) && (flow_rsp[i].key_found == 1)))
788 if (rsp->n_keys < n_keys)
792 for (i = 0; i < rsp->n_keys; i++) {
793 memcpy(&flow[i]->key, &key[i], sizeof(flow[i]->key));
794 flow[i]->port_id = port_id[i];
795 flow[i]->flow_id = flow_id[i];
796 flow[i]->signature = signature[i];
797 flow[i]->entry_ptr = flow_rsp[i].entry_ptr;
800 uint32_t bucket_id = signature[i] & (N_BUCKETS - 1);
802 TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow[i], node);
809 for (i = rsp->n_keys; i < n_keys; i++)
813 app_msg_free(app, rsp);
824 app_pipeline_fc_del(struct app_params *app,
825 uint32_t pipeline_id,
826 struct pipeline_fc_key *key)
828 struct app_pipeline_fc *p;
829 struct app_pipeline_fc_flow *flow;
831 struct pipeline_fc_del_msg_req *req;
832 struct pipeline_fc_del_msg_rsp *rsp;
834 uint32_t signature, bucket_id;
836 /* Check input arguments */
841 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification);
845 if (app_pipeline_fc_key_check(key) != 0)
849 flow = app_pipeline_fc_flow_find(p, key);
853 /* Allocate and write request */
854 req = app_msg_alloc(app);
858 req->type = PIPELINE_MSG_REQ_CUSTOM;
859 req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL;
860 app_pipeline_fc_key_convert(key, req->key, &signature);
862 /* Send request and wait for response */
863 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
868 if (rsp->status || !rsp->key_found) {
869 app_msg_free(app, rsp);
874 bucket_id = signature & (N_BUCKETS - 1);
875 TAILQ_REMOVE(&p->flows[bucket_id], flow, node);
880 app_msg_free(app, rsp);
886 app_pipeline_fc_add_default(struct app_params *app,
887 uint32_t pipeline_id,
890 struct app_pipeline_fc *p;
892 struct pipeline_fc_add_default_msg_req *req;
893 struct pipeline_fc_add_default_msg_rsp *rsp;
895 /* Check input arguments */
899 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification);
903 if (port_id >= p->n_ports_out)
906 /* Allocate and write request */
907 req = app_msg_alloc(app);
911 req->type = PIPELINE_MSG_REQ_CUSTOM;
912 req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT;
913 req->port_id = port_id;
915 /* Send request and wait for response */
916 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
920 /* Read response and write flow */
921 if (rsp->status || (rsp->entry_ptr == NULL)) {
922 app_msg_free(app, rsp);
926 p->default_flow_port_id = port_id;
927 p->default_flow_entry_ptr = rsp->entry_ptr;
930 p->default_flow_present = 1;
933 app_msg_free(app, rsp);
939 app_pipeline_fc_del_default(struct app_params *app,
940 uint32_t pipeline_id)
942 struct app_pipeline_fc *p;
944 struct pipeline_fc_del_default_msg_req *req;
945 struct pipeline_fc_del_default_msg_rsp *rsp;
947 /* Check input arguments */
951 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification);
955 /* Allocate and write request */
956 req = app_msg_alloc(app);
960 req->type = PIPELINE_MSG_REQ_CUSTOM;
961 req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT;
963 /* Send request and wait for response */
964 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
970 app_msg_free(app, rsp);
975 p->default_flow_present = 0;
978 app_msg_free(app, rsp);
988 print_fc_qinq_flow(struct app_pipeline_fc_flow *flow)
990 printf("(SVLAN = %" PRIu32 ", "
991 "CVLAN = %" PRIu32 ") => "
992 "Port = %" PRIu32 ", "
993 "Flow ID = %" PRIu32 ", "
994 "(signature = 0x%08" PRIx32 ", "
997 flow->key.key.qinq.svlan,
998 flow->key.key.qinq.cvlan,
1006 print_fc_ipv4_5tuple_flow(struct app_pipeline_fc_flow *flow)
1008 printf("(SA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", "
1009 "DA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", "
1010 "SP = %" PRIu32 ", "
1011 "DP = %" PRIu32 ", "
1012 "Proto = %" PRIu32 ") => "
1013 "Port = %" PRIu32 ", "
1014 "Flow ID = %" PRIu32 " "
1015 "(signature = 0x%08" PRIx32 ", "
1016 "entry_ptr = %p)\n",
1018 (flow->key.key.ipv4_5tuple.ip_src >> 24) & 0xFF,
1019 (flow->key.key.ipv4_5tuple.ip_src >> 16) & 0xFF,
1020 (flow->key.key.ipv4_5tuple.ip_src >> 8) & 0xFF,
1021 flow->key.key.ipv4_5tuple.ip_src & 0xFF,
1023 (flow->key.key.ipv4_5tuple.ip_dst >> 24) & 0xFF,
1024 (flow->key.key.ipv4_5tuple.ip_dst >> 16) & 0xFF,
1025 (flow->key.key.ipv4_5tuple.ip_dst >> 8) & 0xFF,
1026 flow->key.key.ipv4_5tuple.ip_dst & 0xFF,
1028 flow->key.key.ipv4_5tuple.port_src,
1029 flow->key.key.ipv4_5tuple.port_dst,
1031 flow->key.key.ipv4_5tuple.proto,
1040 print_fc_ipv6_5tuple_flow(struct app_pipeline_fc_flow *flow) {
1041 printf("(SA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
1042 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
1043 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
1044 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", "
1045 "DA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
1046 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
1047 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
1048 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", "
1049 "SP = %" PRIu32 ", "
1051 "Proto = %" PRIu32 " "
1052 "=> Port = %" PRIu32 ", "
1053 "Flow ID = %" PRIu32 " "
1054 "(signature = 0x%08" PRIx32 ", "
1055 "entry_ptr = %p)\n",
1057 flow->key.key.ipv6_5tuple.ip_src[0],
1058 flow->key.key.ipv6_5tuple.ip_src[1],
1059 flow->key.key.ipv6_5tuple.ip_src[2],
1060 flow->key.key.ipv6_5tuple.ip_src[3],
1061 flow->key.key.ipv6_5tuple.ip_src[4],
1062 flow->key.key.ipv6_5tuple.ip_src[5],
1063 flow->key.key.ipv6_5tuple.ip_src[6],
1064 flow->key.key.ipv6_5tuple.ip_src[7],
1065 flow->key.key.ipv6_5tuple.ip_src[8],
1066 flow->key.key.ipv6_5tuple.ip_src[9],
1067 flow->key.key.ipv6_5tuple.ip_src[10],
1068 flow->key.key.ipv6_5tuple.ip_src[11],
1069 flow->key.key.ipv6_5tuple.ip_src[12],
1070 flow->key.key.ipv6_5tuple.ip_src[13],
1071 flow->key.key.ipv6_5tuple.ip_src[14],
1072 flow->key.key.ipv6_5tuple.ip_src[15],
1074 flow->key.key.ipv6_5tuple.ip_dst[0],
1075 flow->key.key.ipv6_5tuple.ip_dst[1],
1076 flow->key.key.ipv6_5tuple.ip_dst[2],
1077 flow->key.key.ipv6_5tuple.ip_dst[3],
1078 flow->key.key.ipv6_5tuple.ip_dst[4],
1079 flow->key.key.ipv6_5tuple.ip_dst[5],
1080 flow->key.key.ipv6_5tuple.ip_dst[6],
1081 flow->key.key.ipv6_5tuple.ip_dst[7],
1082 flow->key.key.ipv6_5tuple.ip_dst[8],
1083 flow->key.key.ipv6_5tuple.ip_dst[9],
1084 flow->key.key.ipv6_5tuple.ip_dst[10],
1085 flow->key.key.ipv6_5tuple.ip_dst[11],
1086 flow->key.key.ipv6_5tuple.ip_dst[12],
1087 flow->key.key.ipv6_5tuple.ip_dst[13],
1088 flow->key.key.ipv6_5tuple.ip_dst[14],
1089 flow->key.key.ipv6_5tuple.ip_dst[15],
1091 flow->key.key.ipv6_5tuple.port_src,
1092 flow->key.key.ipv6_5tuple.port_dst,
1094 flow->key.key.ipv6_5tuple.proto,
1103 print_fc_flow(struct app_pipeline_fc_flow *flow)
1105 switch (flow->key.type) {
1107 print_fc_qinq_flow(flow);
1110 case FLOW_KEY_IPV4_5TUPLE:
1111 print_fc_ipv4_5tuple_flow(flow);
1114 case FLOW_KEY_IPV6_5TUPLE:
1115 print_fc_ipv6_5tuple_flow(flow);
1121 app_pipeline_fc_ls(struct app_params *app,
1122 uint32_t pipeline_id)
1124 struct app_pipeline_fc *p;
1125 struct app_pipeline_fc_flow *flow;
1128 /* Check input arguments */
1132 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_classification);
1136 for (i = 0; i < N_BUCKETS; i++)
1137 TAILQ_FOREACH(flow, &p->flows[i], node)
1138 print_fc_flow(flow);
1140 if (p->default_flow_present)
1141 printf("Default flow: port %" PRIu32 " (entry ptr = %p)\n",
1142 p->default_flow_port_id,
1143 p->default_flow_entry_ptr);
1145 printf("Default: DROP\n");
1153 * p <pipelineid> flow add qinq <svlan> <cvlan> port <portid> id <flowid>
1154 * p <pipelineid> flow add qinq bulk <file>
1155 * p <pipelineid> flow add ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid>
1156 * p <pipelineid> flow add ipv4 bulk <file>
1157 * p <pipelineid> flow add ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid>
1158 * p <pipelineid> flow add ipv6 bulk <file>
1161 * p <pipelineid> flow add default <portid>
1164 * p <pipelineid> flow del qinq <svlan> <cvlan>
1165 * p <pipelineid> flow del ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto>
1166 * p <pipelineid> flow del ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto>
1169 * p <pipelineid> flow del default
1172 * p <pipelineid> flow ls
1175 struct cmd_flow_result {
1176 cmdline_fixed_string_t p_string;
1177 uint32_t pipeline_id;
1178 cmdline_fixed_string_t flow_string;
1179 cmdline_multi_string_t multi_string;
1183 cmd_flow_parsed(void *parsed_result,
1184 __attribute__((unused)) struct cmdline *cl,
1187 struct cmd_flow_result *results = parsed_result;
1188 struct app_params *app = data;
1191 uint32_t n_tokens = RTE_DIM(tokens);
1194 status = parse_tokenize_string(results->multi_string, tokens, &n_tokens);
1196 printf(CMD_MSG_TOO_MANY_ARGS, "flow");
1201 if ((n_tokens >= 3) &&
1202 (strcmp(tokens[0], "add") == 0) &&
1203 (strcmp(tokens[1], "qinq") == 0) &&
1204 strcmp(tokens[2], "bulk")) {
1205 struct pipeline_fc_key key;
1211 memset(&key, 0, sizeof(key));
1213 if (n_tokens != 8) {
1214 printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq");
1218 if (parser_read_uint32(&svlan, tokens[2]) != 0) {
1219 printf(CMD_MSG_INVALID_ARG, "svlan");
1223 if (parser_read_uint32(&cvlan, tokens[3]) != 0) {
1224 printf(CMD_MSG_INVALID_ARG, "cvlan");
1228 if (strcmp(tokens[4], "port") != 0) {
1229 printf(CMD_MSG_ARG_NOT_FOUND, "port");
1233 if (parser_read_uint32(&port_id, tokens[5]) != 0) {
1234 printf(CMD_MSG_INVALID_ARG, "portid");
1238 if (strcmp(tokens[6], "id") != 0) {
1239 printf(CMD_MSG_ARG_NOT_FOUND, "id");
1243 if (parser_read_uint32(&flow_id, tokens[7]) != 0) {
1244 printf(CMD_MSG_INVALID_ARG, "flowid");
1248 key.type = FLOW_KEY_QINQ;
1249 key.key.qinq.svlan = svlan;
1250 key.key.qinq.cvlan = cvlan;
1252 status = app_pipeline_fc_add(app,
1253 results->pipeline_id,
1258 printf(CMD_MSG_FAIL, "flow add qinq");
1261 } /* flow add qinq */
1264 if ((n_tokens >= 3) &&
1265 (strcmp(tokens[0], "add") == 0) &&
1266 (strcmp(tokens[1], "ipv4") == 0) &&
1267 strcmp(tokens[2], "bulk")) {
1268 struct pipeline_fc_key key;
1269 struct in_addr sipaddr;
1270 struct in_addr dipaddr;
1277 memset(&key, 0, sizeof(key));
1279 if (n_tokens != 11) {
1280 printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4");
1284 if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) {
1285 printf(CMD_MSG_INVALID_ARG, "sipv4addr");
1288 if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) {
1289 printf(CMD_MSG_INVALID_ARG, "dipv4addr");
1293 if (parser_read_uint32(&sport, tokens[4]) != 0) {
1294 printf(CMD_MSG_INVALID_ARG, "sport");
1298 if (parser_read_uint32(&dport, tokens[5]) != 0) {
1299 printf(CMD_MSG_INVALID_ARG, "dport");
1303 if (parser_read_uint32(&proto, tokens[6]) != 0) {
1304 printf(CMD_MSG_INVALID_ARG, "proto");
1308 if (strcmp(tokens[7], "port") != 0) {
1309 printf(CMD_MSG_ARG_NOT_FOUND, "port");
1313 if (parser_read_uint32(&port_id, tokens[8]) != 0) {
1314 printf(CMD_MSG_INVALID_ARG, "portid");
1318 if (strcmp(tokens[9], "id") != 0) {
1319 printf(CMD_MSG_ARG_NOT_FOUND, "id");
1323 if (parser_read_uint32(&flow_id, tokens[10]) != 0) {
1324 printf(CMD_MSG_INVALID_ARG, "flowid");
1328 key.type = FLOW_KEY_IPV4_5TUPLE;
1329 key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr);
1330 key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr);
1331 key.key.ipv4_5tuple.port_src = sport;
1332 key.key.ipv4_5tuple.port_dst = dport;
1333 key.key.ipv4_5tuple.proto = proto;
1335 status = app_pipeline_fc_add(app,
1336 results->pipeline_id,
1341 printf(CMD_MSG_FAIL, "flow add ipv4");
1344 } /* flow add ipv4 */
1347 if ((n_tokens >= 3) &&
1348 (strcmp(tokens[0], "add") == 0) &&
1349 (strcmp(tokens[1], "ipv6") == 0) &&
1350 strcmp(tokens[2], "bulk")) {
1351 struct pipeline_fc_key key;
1352 struct in6_addr sipaddr;
1353 struct in6_addr dipaddr;
1360 memset(&key, 0, sizeof(key));
1362 if (n_tokens != 11) {
1363 printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6");
1367 if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) {
1368 printf(CMD_MSG_INVALID_ARG, "sipv6addr");
1371 if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) {
1372 printf(CMD_MSG_INVALID_ARG, "dipv6addr");
1376 if (parser_read_uint32(&sport, tokens[4]) != 0) {
1377 printf(CMD_MSG_INVALID_ARG, "sport");
1381 if (parser_read_uint32(&dport, tokens[5]) != 0) {
1382 printf(CMD_MSG_INVALID_ARG, "dport");
1386 if (parser_read_uint32(&proto, tokens[6]) != 0) {
1387 printf(CMD_MSG_INVALID_ARG, "proto");
1391 if (strcmp(tokens[7], "port") != 0) {
1392 printf(CMD_MSG_ARG_NOT_FOUND, "port");
1396 if (parser_read_uint32(&port_id, tokens[8]) != 0) {
1397 printf(CMD_MSG_INVALID_ARG, "portid");
1401 if (strcmp(tokens[9], "id") != 0) {
1402 printf(CMD_MSG_ARG_NOT_FOUND, "id");
1406 if (parser_read_uint32(&flow_id, tokens[10]) != 0) {
1407 printf(CMD_MSG_INVALID_ARG, "flowid");
1411 key.type = FLOW_KEY_IPV6_5TUPLE;
1412 memcpy(key.key.ipv6_5tuple.ip_src, (void *)&sipaddr, 16);
1413 memcpy(key.key.ipv6_5tuple.ip_dst, (void *)&dipaddr, 16);
1414 key.key.ipv6_5tuple.port_src = sport;
1415 key.key.ipv6_5tuple.port_dst = dport;
1416 key.key.ipv6_5tuple.proto = proto;
1418 status = app_pipeline_fc_add(app,
1419 results->pipeline_id,
1424 printf(CMD_MSG_FAIL, "flow add ipv6");
1427 } /* flow add ipv6 */
1429 /* flow add qinq bulk */
1430 if ((n_tokens >= 3) &&
1431 (strcmp(tokens[0], "add") == 0) &&
1432 (strcmp(tokens[1], "qinq") == 0) &&
1433 (strcmp(tokens[2], "bulk") == 0)) {
1434 struct pipeline_fc_key *keys;
1435 uint32_t *port_ids, *flow_ids, n_keys, line;
1438 if (n_tokens != 4) {
1439 printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq bulk");
1443 filename = tokens[3];
1445 n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE;
1446 keys = malloc(n_keys * sizeof(struct pipeline_fc_key));
1449 memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key));
1451 port_ids = malloc(n_keys * sizeof(uint32_t));
1452 if (port_ids == NULL) {
1457 flow_ids = malloc(n_keys * sizeof(uint32_t));
1458 if (flow_ids == NULL) {
1464 status = app_pipeline_fc_load_file_qinq(filename,
1471 printf(CMD_MSG_FILE_ERR, filename, line);
1478 status = app_pipeline_fc_add_bulk(app,
1479 results->pipeline_id,
1485 printf(CMD_MSG_FAIL, "flow add qinq bulk");
1491 } /* flow add qinq bulk */
1493 /* flow add ipv4 bulk */
1494 if ((n_tokens >= 3) &&
1495 (strcmp(tokens[0], "add") == 0) &&
1496 (strcmp(tokens[1], "ipv4") == 0) &&
1497 (strcmp(tokens[2], "bulk") == 0)) {
1498 struct pipeline_fc_key *keys;
1499 uint32_t *port_ids, *flow_ids, n_keys, line;
1502 if (n_tokens != 4) {
1503 printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4 bulk");
1507 filename = tokens[3];
1509 n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE;
1510 keys = malloc(n_keys * sizeof(struct pipeline_fc_key));
1513 memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key));
1515 port_ids = malloc(n_keys * sizeof(uint32_t));
1516 if (port_ids == NULL) {
1521 flow_ids = malloc(n_keys * sizeof(uint32_t));
1522 if (flow_ids == NULL) {
1528 status = app_pipeline_fc_load_file_ipv4(filename,
1535 printf(CMD_MSG_FILE_ERR, filename, line);
1542 status = app_pipeline_fc_add_bulk(app,
1543 results->pipeline_id,
1549 printf(CMD_MSG_FAIL, "flow add ipv4 bulk");
1555 } /* flow add ipv4 bulk */
1557 /* flow add ipv6 bulk */
1558 if ((n_tokens >= 3) &&
1559 (strcmp(tokens[0], "add") == 0) &&
1560 (strcmp(tokens[1], "ipv6") == 0) &&
1561 (strcmp(tokens[2], "bulk") == 0)) {
1562 struct pipeline_fc_key *keys;
1563 uint32_t *port_ids, *flow_ids, n_keys, line;
1566 if (n_tokens != 4) {
1567 printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6 bulk");
1571 filename = tokens[3];
1573 n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE;
1574 keys = malloc(n_keys * sizeof(struct pipeline_fc_key));
1577 memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key));
1579 port_ids = malloc(n_keys * sizeof(uint32_t));
1580 if (port_ids == NULL) {
1585 flow_ids = malloc(n_keys * sizeof(uint32_t));
1586 if (flow_ids == NULL) {
1592 status = app_pipeline_fc_load_file_ipv6(filename,
1599 printf(CMD_MSG_FILE_ERR, filename, line);
1606 status = app_pipeline_fc_add_bulk(app,
1607 results->pipeline_id,
1613 printf(CMD_MSG_FAIL, "flow add ipv6 bulk");
1619 } /* flow add ipv6 bulk */
1621 /* flow add default*/
1622 if ((n_tokens >= 2) &&
1623 (strcmp(tokens[0], "add") == 0) &&
1624 (strcmp(tokens[1], "default") == 0)) {
1627 if (n_tokens != 3) {
1628 printf(CMD_MSG_MISMATCH_ARGS, "flow add default");
1632 if (parser_read_uint32(&port_id, tokens[2]) != 0) {
1633 printf(CMD_MSG_INVALID_ARG, "portid");
1637 status = app_pipeline_fc_add_default(app,
1638 results->pipeline_id,
1641 printf(CMD_MSG_FAIL, "flow add default");
1644 } /* flow add default */
1647 if ((n_tokens >= 2) &&
1648 (strcmp(tokens[0], "del") == 0) &&
1649 (strcmp(tokens[1], "qinq") == 0)) {
1650 struct pipeline_fc_key key;
1654 memset(&key, 0, sizeof(key));
1656 if (n_tokens != 4) {
1657 printf(CMD_MSG_MISMATCH_ARGS, "flow del qinq");
1661 if (parser_read_uint32(&svlan, tokens[2]) != 0) {
1662 printf(CMD_MSG_INVALID_ARG, "svlan");
1666 if (parser_read_uint32(&cvlan, tokens[3]) != 0) {
1667 printf(CMD_MSG_INVALID_ARG, "cvlan");
1671 key.type = FLOW_KEY_QINQ;
1672 key.key.qinq.svlan = svlan;
1673 key.key.qinq.cvlan = cvlan;
1675 status = app_pipeline_fc_del(app,
1676 results->pipeline_id,
1679 printf(CMD_MSG_FAIL, "flow del qinq");
1682 } /* flow del qinq */
1685 if ((n_tokens >= 2) &&
1686 (strcmp(tokens[0], "del") == 0) &&
1687 (strcmp(tokens[1], "ipv4") == 0)) {
1688 struct pipeline_fc_key key;
1689 struct in_addr sipaddr;
1690 struct in_addr dipaddr;
1695 memset(&key, 0, sizeof(key));
1697 if (n_tokens != 7) {
1698 printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv4");
1702 if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) {
1703 printf(CMD_MSG_INVALID_ARG, "sipv4addr");
1706 if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) {
1707 printf(CMD_MSG_INVALID_ARG, "dipv4addr");
1711 if (parser_read_uint32(&sport, tokens[4]) != 0) {
1712 printf(CMD_MSG_INVALID_ARG, "sport");
1716 if (parser_read_uint32(&dport, tokens[5]) != 0) {
1717 printf(CMD_MSG_INVALID_ARG, "dport");
1721 if (parser_read_uint32(&proto, tokens[6]) != 0) {
1722 printf(CMD_MSG_INVALID_ARG, "proto");
1726 key.type = FLOW_KEY_IPV4_5TUPLE;
1727 key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr);
1728 key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr);
1729 key.key.ipv4_5tuple.port_src = sport;
1730 key.key.ipv4_5tuple.port_dst = dport;
1731 key.key.ipv4_5tuple.proto = proto;
1733 status = app_pipeline_fc_del(app,
1734 results->pipeline_id,
1737 printf(CMD_MSG_FAIL, "flow del ipv4");
1740 } /* flow del ipv4 */
1743 if ((n_tokens >= 2) &&
1744 (strcmp(tokens[0], "del") == 0) &&
1745 (strcmp(tokens[1], "ipv6") == 0)) {
1746 struct pipeline_fc_key key;
1747 struct in6_addr sipaddr;
1748 struct in6_addr dipaddr;
1753 memset(&key, 0, sizeof(key));
1755 if (n_tokens != 7) {
1756 printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv6");
1760 if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) {
1761 printf(CMD_MSG_INVALID_ARG, "sipv6addr");
1765 if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) {
1766 printf(CMD_MSG_INVALID_ARG, "dipv6addr");
1770 if (parser_read_uint32(&sport, tokens[4]) != 0) {
1771 printf(CMD_MSG_INVALID_ARG, "sport");
1775 if (parser_read_uint32(&dport, tokens[5]) != 0) {
1776 printf(CMD_MSG_INVALID_ARG, "dport");
1780 if (parser_read_uint32(&proto, tokens[6]) != 0) {
1781 printf(CMD_MSG_INVALID_ARG, "proto");
1785 key.type = FLOW_KEY_IPV6_5TUPLE;
1786 memcpy(key.key.ipv6_5tuple.ip_src, &sipaddr, 16);
1787 memcpy(key.key.ipv6_5tuple.ip_dst, &dipaddr, 16);
1788 key.key.ipv6_5tuple.port_src = sport;
1789 key.key.ipv6_5tuple.port_dst = dport;
1790 key.key.ipv6_5tuple.proto = proto;
1792 status = app_pipeline_fc_del(app,
1793 results->pipeline_id,
1796 printf(CMD_MSG_FAIL, "flow del ipv6");
1799 } /* flow del ipv6 */
1801 /* flow del default*/
1802 if ((n_tokens >= 2) &&
1803 (strcmp(tokens[0], "del") == 0) &&
1804 (strcmp(tokens[1], "default") == 0)) {
1805 if (n_tokens != 2) {
1806 printf(CMD_MSG_MISMATCH_ARGS, "flow del default");
1810 status = app_pipeline_fc_del_default(app,
1811 results->pipeline_id);
1813 printf(CMD_MSG_FAIL, "flow del default");
1816 } /* flow del default */
1819 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1820 if (n_tokens != 1) {
1821 printf(CMD_MSG_MISMATCH_ARGS, "flow ls");
1825 status = app_pipeline_fc_ls(app, results->pipeline_id);
1827 printf(CMD_MSG_FAIL, "flow ls");
1832 printf(CMD_MSG_MISMATCH_ARGS, "flow");
1835 static cmdline_parse_token_string_t cmd_flow_p_string =
1836 TOKEN_STRING_INITIALIZER(struct cmd_flow_result, p_string, "p");
1838 static cmdline_parse_token_num_t cmd_flow_pipeline_id =
1839 TOKEN_NUM_INITIALIZER(struct cmd_flow_result, pipeline_id, UINT32);
1841 static cmdline_parse_token_string_t cmd_flow_flow_string =
1842 TOKEN_STRING_INITIALIZER(struct cmd_flow_result, flow_string, "flow");
1844 static cmdline_parse_token_string_t cmd_flow_multi_string =
1845 TOKEN_STRING_INITIALIZER(struct cmd_flow_result, multi_string,
1846 TOKEN_STRING_MULTI);
1848 static cmdline_parse_inst_t cmd_flow = {
1849 .f = cmd_flow_parsed,
1851 .help_str = "flow add / add bulk / add default / del / del default / ls",
1853 (void *) &cmd_flow_p_string,
1854 (void *) &cmd_flow_pipeline_id,
1855 (void *) &cmd_flow_flow_string,
1856 (void *) &cmd_flow_multi_string,
1861 static cmdline_parse_ctx_t pipeline_cmds[] = {
1862 (cmdline_parse_inst_t *) &cmd_flow,
1866 static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = {
1867 .f_init = app_pipeline_fc_init,
1868 .f_post_init = NULL,
1869 .f_free = app_pipeline_fc_free,
1870 .f_track = app_pipeline_track_default,
1871 .cmds = pipeline_cmds,
1874 struct pipeline_type pipeline_flow_classification = {
1875 .name = "FLOW_CLASSIFICATION",
1876 .be_ops = &pipeline_flow_classification_be_ops,
1877 .fe_ops = &pipeline_flow_classification_fe_ops,