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