remove unneeded tests for NULL when freeing
[dpdk.git] / examples / ip_pipeline / pipeline / pipeline_flow_classification_be.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <string.h>
35
36 #include <rte_common.h>
37 #include <rte_malloc.h>
38 #include <rte_table_hash.h>
39 #include <rte_byteorder.h>
40 #include <pipeline.h>
41
42 #include "pipeline_flow_classification_be.h"
43 #include "pipeline_actions_common.h"
44 #include "hash_func.h"
45
46 struct pipeline_flow_classification {
47         struct pipeline p;
48         pipeline_msg_req_handler custom_handlers[PIPELINE_FC_MSG_REQS];
49
50         uint32_t n_flows;
51         uint32_t key_size;
52         uint32_t flow_id;
53
54         uint32_t key_offset;
55         uint32_t hash_offset;
56         uint8_t *key_mask;
57         uint32_t flow_id_offset;
58
59 } __rte_cache_aligned;
60
61 static void *
62 pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg);
63
64 static pipeline_msg_req_handler handlers[] = {
65         [PIPELINE_MSG_REQ_PING] =
66                 pipeline_msg_req_ping_handler,
67         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
68                 pipeline_msg_req_stats_port_in_handler,
69         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
70                 pipeline_msg_req_stats_port_out_handler,
71         [PIPELINE_MSG_REQ_STATS_TABLE] =
72                 pipeline_msg_req_stats_table_handler,
73         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
74                 pipeline_msg_req_port_in_enable_handler,
75         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
76                 pipeline_msg_req_port_in_disable_handler,
77         [PIPELINE_MSG_REQ_CUSTOM] =
78                 pipeline_fc_msg_req_custom_handler,
79 };
80
81 static void *
82 pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg);
83
84 static void *
85 pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg);
86
87 static void *
88 pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg);
89
90 static void *
91 pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg);
92
93 static void *
94 pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg);
95
96 static pipeline_msg_req_handler custom_handlers[] = {
97         [PIPELINE_FC_MSG_REQ_FLOW_ADD] =
98                 pipeline_fc_msg_req_add_handler,
99         [PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK] =
100                 pipeline_fc_msg_req_add_bulk_handler,
101         [PIPELINE_FC_MSG_REQ_FLOW_DEL] =
102                 pipeline_fc_msg_req_del_handler,
103         [PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT] =
104                 pipeline_fc_msg_req_add_default_handler,
105         [PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT] =
106                 pipeline_fc_msg_req_del_default_handler,
107 };
108
109 /*
110  * Flow table
111  */
112 struct flow_table_entry {
113         struct rte_pipeline_table_entry head;
114
115         uint32_t flow_id;
116         uint32_t pad;
117 };
118
119 rte_table_hash_op_hash hash_func[] = {
120         hash_default_key8,
121         hash_default_key16,
122         hash_default_key24,
123         hash_default_key32,
124         hash_default_key40,
125         hash_default_key48,
126         hash_default_key56,
127         hash_default_key64
128 };
129
130 /*
131  * Flow table AH - Write flow_id to packet meta-data
132  */
133 static inline void
134 pkt_work_flow_id(
135         struct rte_mbuf *pkt,
136         struct rte_pipeline_table_entry *table_entry,
137         void *arg)
138 {
139         struct pipeline_flow_classification *p_fc = arg;
140         uint32_t *flow_id_ptr =
141                 RTE_MBUF_METADATA_UINT32_PTR(pkt, p_fc->flow_id_offset);
142         struct flow_table_entry *entry =
143                 (struct flow_table_entry *) table_entry;
144
145         /* Read */
146         uint32_t flow_id = entry->flow_id;
147
148         /* Compute */
149
150         /* Write */
151         *flow_id_ptr = flow_id;
152 }
153
154 static inline void
155 pkt4_work_flow_id(
156         struct rte_mbuf **pkts,
157         struct rte_pipeline_table_entry **table_entries,
158         void *arg)
159 {
160         struct pipeline_flow_classification *p_fc = arg;
161
162         uint32_t *flow_id_ptr0 =
163                 RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p_fc->flow_id_offset);
164         uint32_t *flow_id_ptr1 =
165                 RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p_fc->flow_id_offset);
166         uint32_t *flow_id_ptr2 =
167                 RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p_fc->flow_id_offset);
168         uint32_t *flow_id_ptr3 =
169                 RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p_fc->flow_id_offset);
170
171         struct flow_table_entry *entry0 =
172                 (struct flow_table_entry *) table_entries[0];
173         struct flow_table_entry *entry1 =
174                 (struct flow_table_entry *) table_entries[1];
175         struct flow_table_entry *entry2 =
176                 (struct flow_table_entry *) table_entries[2];
177         struct flow_table_entry *entry3 =
178                 (struct flow_table_entry *) table_entries[3];
179
180         /* Read */
181         uint32_t flow_id0 = entry0->flow_id;
182         uint32_t flow_id1 = entry1->flow_id;
183         uint32_t flow_id2 = entry2->flow_id;
184         uint32_t flow_id3 = entry3->flow_id;
185
186         /* Compute */
187
188         /* Write */
189         *flow_id_ptr0 = flow_id0;
190         *flow_id_ptr1 = flow_id1;
191         *flow_id_ptr2 = flow_id2;
192         *flow_id_ptr3 = flow_id3;
193 }
194
195 PIPELINE_TABLE_AH_HIT(fc_table_ah_hit,
196                 pkt_work_flow_id, pkt4_work_flow_id);
197
198 static rte_pipeline_table_action_handler_hit
199 get_fc_table_ah_hit(struct pipeline_flow_classification *p)
200 {
201         if (p->flow_id)
202                 return fc_table_ah_hit;
203
204         return NULL;
205 }
206
207 /*
208  * Argument parsing
209  */
210 static int
211 pipeline_fc_parse_args(struct pipeline_flow_classification *p,
212         struct pipeline_params *params)
213 {
214         uint32_t n_flows_present = 0;
215         uint32_t key_offset_present = 0;
216         uint32_t key_size_present = 0;
217         uint32_t hash_offset_present = 0;
218         uint32_t key_mask_present = 0;
219         uint32_t flow_id_offset_present = 0;
220
221         uint32_t i;
222         char *key_mask_str = NULL;
223
224         p->hash_offset = 0;
225
226         /* default values */
227         p->flow_id = 0;
228
229         for (i = 0; i < params->n_args; i++) {
230                 char *arg_name = params->args_name[i];
231                 char *arg_value = params->args_value[i];
232
233                 /* n_flows */
234                 if (strcmp(arg_name, "n_flows") == 0) {
235                         if (n_flows_present)
236                                 goto error_parse;
237                         n_flows_present = 1;
238
239                         p->n_flows = atoi(arg_value);
240                         if (p->n_flows == 0)
241                                 goto error_parse;
242
243                         continue;
244                 }
245
246                 /* key_offset */
247                 if (strcmp(arg_name, "key_offset") == 0) {
248                         if (key_offset_present)
249                                 goto error_parse;
250
251                         key_offset_present = 1;
252
253                         p->key_offset = atoi(arg_value);
254
255                         continue;
256                 }
257
258                 /* key_size */
259                 if (strcmp(arg_name, "key_size") == 0) {
260                         if (key_size_present)
261                                 goto error_parse;
262                         key_size_present = 1;
263
264                         p->key_size = atoi(arg_value);
265                         if ((p->key_size == 0) ||
266                                 (p->key_size > PIPELINE_FC_FLOW_KEY_MAX_SIZE) ||
267                                 (p->key_size % 8))
268                                 goto error_parse;
269
270                         continue;
271                 }
272
273                 /* key_mask */
274                 if (strcmp(arg_name, "key_mask") == 0) {
275                         if (key_mask_present)
276                                 goto error_parse;
277
278                         key_mask_str = strdup(arg_value);
279                         if (key_mask_str == NULL)
280                                 goto error_parse;
281
282                         key_mask_present = 1;
283
284                         continue;
285                 }
286
287                 /* hash_offset */
288                 if (strcmp(arg_name, "hash_offset") == 0) {
289                         if (hash_offset_present)
290                                 goto error_parse;
291                         hash_offset_present = 1;
292
293                         p->hash_offset = atoi(arg_value);
294
295                         continue;
296                 }
297
298                 /* flow_id_offset */
299                 if (strcmp(arg_name, "flowid_offset") == 0) {
300                         if (flow_id_offset_present)
301                                 goto error_parse;
302                         flow_id_offset_present = 1;
303
304                         p->flow_id = 1;
305                         p->flow_id_offset = atoi(arg_value);
306
307                         continue;
308                 }
309
310                 /* Unknown argument */
311                 goto error_parse;
312         }
313
314         /* Check that mandatory arguments are present */
315         if ((n_flows_present == 0) ||
316                 (key_offset_present == 0) ||
317                 (key_size_present == 0))
318                 goto error_parse;
319
320         if (key_mask_present) {
321                 p->key_mask = rte_malloc(NULL, p->key_size, 0);
322                 if (p->key_mask == NULL)
323                         goto error_parse;
324
325                 if (parse_hex_string(key_mask_str, p->key_mask, &p->key_size)
326                         != 0) {
327                         goto error_parse;
328                 }
329
330                 free(key_mask_str);
331         }
332
333         return 0;
334
335 error_parse:
336         free(key_mask_str);
337         free(p->key_mask);
338         return -1;
339 }
340
341 static void *pipeline_fc_init(struct pipeline_params *params,
342         __rte_unused void *arg)
343 {
344         struct pipeline *p;
345         struct pipeline_flow_classification *p_fc;
346         uint32_t size, i;
347
348         /* Check input arguments */
349         if (params == NULL)
350                 return NULL;
351
352         /* Memory allocation */
353         size = RTE_CACHE_LINE_ROUNDUP(
354                 sizeof(struct pipeline_flow_classification));
355         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
356         if (p == NULL)
357                 return NULL;
358         p_fc = (struct pipeline_flow_classification *) p;
359
360         strcpy(p->name, params->name);
361         p->log_level = params->log_level;
362
363         PLOG(p, HIGH, "Flow classification");
364
365         /* Parse arguments */
366         if (pipeline_fc_parse_args(p_fc, params))
367                 return NULL;
368
369         /* Pipeline */
370         {
371                 struct rte_pipeline_params pipeline_params = {
372                         .name = params->name,
373                         .socket_id = params->socket_id,
374                         .offset_port_id = 0,
375                 };
376
377                 p->p = rte_pipeline_create(&pipeline_params);
378                 if (p->p == NULL) {
379                         rte_free(p);
380                         return NULL;
381                 }
382         }
383
384         /* Input ports */
385         p->n_ports_in = params->n_ports_in;
386         for (i = 0; i < p->n_ports_in; i++) {
387                 struct rte_pipeline_port_in_params port_params = {
388                         .ops = pipeline_port_in_params_get_ops(
389                                 &params->port_in[i]),
390                         .arg_create = pipeline_port_in_params_convert(
391                                 &params->port_in[i]),
392                         .f_action = NULL,
393                         .arg_ah = NULL,
394                         .burst_size = params->port_in[i].burst_size,
395                 };
396
397                 int status = rte_pipeline_port_in_create(p->p,
398                         &port_params,
399                         &p->port_in_id[i]);
400
401                 if (status) {
402                         rte_pipeline_free(p->p);
403                         rte_free(p);
404                         return NULL;
405                 }
406         }
407
408         /* Output ports */
409         p->n_ports_out = params->n_ports_out;
410         for (i = 0; i < p->n_ports_out; i++) {
411                 struct rte_pipeline_port_out_params port_params = {
412                         .ops = pipeline_port_out_params_get_ops(
413                                 &params->port_out[i]),
414                         .arg_create = pipeline_port_out_params_convert(
415                                 &params->port_out[i]),
416                         .f_action = NULL,
417                         .f_action_bulk = NULL,
418                         .arg_ah = NULL,
419                 };
420
421                 int status = rte_pipeline_port_out_create(p->p,
422                         &port_params,
423                         &p->port_out_id[i]);
424
425                 if (status) {
426                         rte_pipeline_free(p->p);
427                         rte_free(p);
428                         return NULL;
429                 }
430         }
431
432         /* Tables */
433         p->n_tables = 1;
434         {
435                 struct rte_table_hash_key8_ext_params
436                         table_hash_key8_params = {
437                         .n_entries = p_fc->n_flows,
438                         .n_entries_ext = p_fc->n_flows,
439                         .signature_offset = p_fc->hash_offset,
440                         .key_offset = p_fc->key_offset,
441                         .f_hash = hash_func[(p_fc->key_size / 8) - 1],
442                         .key_mask = p_fc->key_mask,
443                         .seed = 0,
444                 };
445
446                 struct rte_table_hash_key16_ext_params
447                         table_hash_key16_params = {
448                         .n_entries = p_fc->n_flows,
449                         .n_entries_ext = p_fc->n_flows,
450                         .signature_offset = p_fc->hash_offset,
451                         .key_offset = p_fc->key_offset,
452                         .f_hash = hash_func[(p_fc->key_size / 8) - 1],
453                         .key_mask = p_fc->key_mask,
454                         .seed = 0,
455                 };
456
457                 struct rte_table_hash_ext_params
458                         table_hash_params = {
459                         .key_size = p_fc->key_size,
460                         .n_keys = p_fc->n_flows,
461                         .n_buckets = p_fc->n_flows / 4,
462                         .n_buckets_ext = p_fc->n_flows / 4,
463                         .f_hash = hash_func[(p_fc->key_size / 8) - 1],
464                         .seed = 0,
465                         .signature_offset = p_fc->hash_offset,
466                         .key_offset = p_fc->key_offset,
467                 };
468
469                 struct rte_pipeline_table_params table_params = {
470                         .ops = NULL, /* set below */
471                         .arg_create = NULL, /* set below */
472                         .f_action_hit = get_fc_table_ah_hit(p_fc),
473                         .f_action_miss = NULL,
474                         .arg_ah = p_fc,
475                         .action_data_size = sizeof(struct flow_table_entry) -
476                                 sizeof(struct rte_pipeline_table_entry),
477                 };
478
479                 int status;
480
481                 switch (p_fc->key_size) {
482                 case 8:
483                         if (p_fc->hash_offset != 0) {
484                                 table_params.ops =
485                                         &rte_table_hash_key8_ext_ops;
486                         } else {
487                                 table_params.ops =
488                                         &rte_table_hash_key8_ext_dosig_ops;
489                         }
490                         table_params.arg_create = &table_hash_key8_params;
491                         break;
492
493                 case 16:
494                         if (p_fc->hash_offset != 0) {
495                                 table_params.ops =
496                                         &rte_table_hash_key16_ext_ops;
497                         } else {
498                                 table_params.ops =
499                                         &rte_table_hash_key16_ext_dosig_ops;
500                         }
501                         table_params.arg_create = &table_hash_key16_params;
502                         break;
503
504                 default:
505                         table_params.ops = &rte_table_hash_ext_ops;
506                         table_params.arg_create = &table_hash_params;
507                 }
508
509                 status = rte_pipeline_table_create(p->p,
510                         &table_params,
511                         &p->table_id[0]);
512
513                 if (status) {
514                         rte_pipeline_free(p->p);
515                         rte_free(p);
516                         return NULL;
517                 }
518         }
519
520         /* Connecting input ports to tables */
521         for (i = 0; i < p->n_ports_in; i++) {
522                 int status = rte_pipeline_port_in_connect_to_table(p->p,
523                         p->port_in_id[i],
524                         p->table_id[0]);
525
526                 if (status) {
527                         rte_pipeline_free(p->p);
528                         rte_free(p);
529                         return NULL;
530                 }
531         }
532
533         /* Enable input ports */
534         for (i = 0; i < p->n_ports_in; i++) {
535                 int status = rte_pipeline_port_in_enable(p->p,
536                         p->port_in_id[i]);
537
538                 if (status) {
539                         rte_pipeline_free(p->p);
540                         rte_free(p);
541                         return NULL;
542                 }
543         }
544
545         /* Check pipeline consistency */
546         if (rte_pipeline_check(p->p) < 0) {
547                 rte_pipeline_free(p->p);
548                 rte_free(p);
549                 return NULL;
550         }
551
552         /* Message queues */
553         p->n_msgq = params->n_msgq;
554         for (i = 0; i < p->n_msgq; i++)
555                 p->msgq_in[i] = params->msgq_in[i];
556         for (i = 0; i < p->n_msgq; i++)
557                 p->msgq_out[i] = params->msgq_out[i];
558
559         /* Message handlers */
560         memcpy(p->handlers, handlers, sizeof(p->handlers));
561         memcpy(p_fc->custom_handlers,
562                 custom_handlers,
563                 sizeof(p_fc->custom_handlers));
564
565         return p;
566 }
567
568 static int
569 pipeline_fc_free(void *pipeline)
570 {
571         struct pipeline *p = (struct pipeline *) pipeline;
572
573         /* Check input arguments */
574         if (p == NULL)
575                 return -1;
576
577         /* Free resources */
578         rte_pipeline_free(p->p);
579         rte_free(p);
580         return 0;
581 }
582
583 static int
584 pipeline_fc_track(void *pipeline,
585         __rte_unused uint32_t port_in,
586         uint32_t *port_out)
587 {
588         struct pipeline *p = (struct pipeline *) pipeline;
589
590         /* Check input arguments */
591         if ((p == NULL) ||
592                 (port_in >= p->n_ports_in) ||
593                 (port_out == NULL))
594                 return -1;
595
596         if (p->n_ports_in == 1) {
597                 *port_out = 0;
598                 return 0;
599         }
600
601         return -1;
602 }
603
604 static int
605 pipeline_fc_timer(void *pipeline)
606 {
607         struct pipeline *p = (struct pipeline *) pipeline;
608
609         pipeline_msg_req_handle(p);
610         rte_pipeline_flush(p->p);
611
612         return 0;
613 }
614
615 static void *
616 pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg)
617 {
618         struct pipeline_flow_classification *p_fc =
619                         (struct pipeline_flow_classification *) p;
620         struct pipeline_custom_msg_req *req = msg;
621         pipeline_msg_req_handler f_handle;
622
623         f_handle = (req->subtype < PIPELINE_FC_MSG_REQS) ?
624                 p_fc->custom_handlers[req->subtype] :
625                 pipeline_msg_req_invalid_handler;
626
627         if (f_handle == NULL)
628                 f_handle = pipeline_msg_req_invalid_handler;
629
630         return f_handle(p, req);
631 }
632
633 static void *
634 pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg)
635 {
636         struct pipeline_fc_add_msg_req *req = msg;
637         struct pipeline_fc_add_msg_rsp *rsp = msg;
638
639         struct flow_table_entry entry = {
640                 .head = {
641                         .action = RTE_PIPELINE_ACTION_PORT,
642                         {.port_id = p->port_out_id[req->port_id]},
643                 },
644                 .flow_id = req->flow_id,
645         };
646
647         rsp->status = rte_pipeline_table_entry_add(p->p,
648                 p->table_id[0],
649                 &req->key,
650                 (struct rte_pipeline_table_entry *) &entry,
651                 &rsp->key_found,
652                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
653
654         return rsp;
655 }
656
657 static void *
658 pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg)
659 {
660         struct pipeline_fc_add_bulk_msg_req *req = msg;
661         struct pipeline_fc_add_bulk_msg_rsp *rsp = msg;
662         uint32_t i;
663
664         for (i = 0; i < req->n_keys; i++) {
665                 struct pipeline_fc_add_bulk_flow_req *flow_req = &req->req[i];
666                 struct pipeline_fc_add_bulk_flow_rsp *flow_rsp = &req->rsp[i];
667
668                 struct flow_table_entry entry = {
669                         .head = {
670                                 .action = RTE_PIPELINE_ACTION_PORT,
671                                 {.port_id = p->port_out_id[flow_req->port_id]},
672                         },
673                         .flow_id = flow_req->flow_id,
674                 };
675
676                 int status = rte_pipeline_table_entry_add(p->p,
677                         p->table_id[0],
678                         &flow_req->key,
679                         (struct rte_pipeline_table_entry *) &entry,
680                         &flow_rsp->key_found,
681                         (struct rte_pipeline_table_entry **)
682                                 &flow_rsp->entry_ptr);
683
684                 if (status)
685                         break;
686         }
687
688         rsp->n_keys = i;
689
690         return rsp;
691 }
692
693 static void *
694 pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg)
695 {
696         struct pipeline_fc_del_msg_req *req = msg;
697         struct pipeline_fc_del_msg_rsp *rsp = msg;
698
699         rsp->status = rte_pipeline_table_entry_delete(p->p,
700                 p->table_id[0],
701                 &req->key,
702                 &rsp->key_found,
703                 NULL);
704
705         return rsp;
706 }
707
708 static void *
709 pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg)
710 {
711         struct pipeline_fc_add_default_msg_req *req = msg;
712         struct pipeline_fc_add_default_msg_rsp *rsp = msg;
713
714         struct flow_table_entry default_entry = {
715                 .head = {
716                         .action = RTE_PIPELINE_ACTION_PORT,
717                         {.port_id = p->port_out_id[req->port_id]},
718                 },
719
720                 .flow_id = 0,
721         };
722
723         rsp->status = rte_pipeline_table_default_entry_add(p->p,
724                 p->table_id[0],
725                 (struct rte_pipeline_table_entry *) &default_entry,
726                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
727
728         return rsp;
729 }
730
731 static void *
732 pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg)
733 {
734         struct pipeline_fc_del_default_msg_rsp *rsp = msg;
735
736         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
737                 p->table_id[0],
738                 NULL);
739
740         return rsp;
741 }
742
743 struct pipeline_be_ops pipeline_flow_classification_be_ops = {
744         .f_init = pipeline_fc_init,
745         .f_free = pipeline_fc_free,
746         .f_run = NULL,
747         .f_timer = pipeline_fc_timer,
748         .f_track = pipeline_fc_track,
749 };