New upstream version 18.02
[deb_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 <pipeline.h>
12
13 #include "pipeline_flow_classification_be.h"
14 #include "pipeline_actions_common.h"
15 #include "parser.h"
16 #include "hash_func.h"
17
18 struct pipeline_flow_classification {
19         struct pipeline p;
20         pipeline_msg_req_handler custom_handlers[PIPELINE_FC_MSG_REQS];
21
22         uint32_t n_flows;
23         uint32_t key_size;
24         uint32_t flow_id;
25
26         uint32_t key_offset;
27         uint32_t hash_offset;
28         uint8_t key_mask[PIPELINE_FC_FLOW_KEY_MAX_SIZE];
29         uint32_t key_mask_present;
30         uint32_t flow_id_offset;
31
32 } __rte_cache_aligned;
33
34 static void *
35 pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg);
36
37 static pipeline_msg_req_handler handlers[] = {
38         [PIPELINE_MSG_REQ_PING] =
39                 pipeline_msg_req_ping_handler,
40         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
41                 pipeline_msg_req_stats_port_in_handler,
42         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
43                 pipeline_msg_req_stats_port_out_handler,
44         [PIPELINE_MSG_REQ_STATS_TABLE] =
45                 pipeline_msg_req_stats_table_handler,
46         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
47                 pipeline_msg_req_port_in_enable_handler,
48         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
49                 pipeline_msg_req_port_in_disable_handler,
50         [PIPELINE_MSG_REQ_CUSTOM] =
51                 pipeline_fc_msg_req_custom_handler,
52 };
53
54 static void *
55 pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg);
56
57 static void *
58 pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg);
59
60 static void *
61 pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg);
62
63 static void *
64 pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg);
65
66 static void *
67 pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg);
68
69 static pipeline_msg_req_handler custom_handlers[] = {
70         [PIPELINE_FC_MSG_REQ_FLOW_ADD] =
71                 pipeline_fc_msg_req_add_handler,
72         [PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK] =
73                 pipeline_fc_msg_req_add_bulk_handler,
74         [PIPELINE_FC_MSG_REQ_FLOW_DEL] =
75                 pipeline_fc_msg_req_del_handler,
76         [PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT] =
77                 pipeline_fc_msg_req_add_default_handler,
78         [PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT] =
79                 pipeline_fc_msg_req_del_default_handler,
80 };
81
82 /*
83  * Flow table
84  */
85 struct flow_table_entry {
86         struct rte_pipeline_table_entry head;
87
88         uint32_t flow_id;
89         uint32_t pad;
90 };
91
92 rte_table_hash_op_hash hash_func[] = {
93         hash_default_key8,
94         hash_default_key16,
95         hash_default_key24,
96         hash_default_key32,
97         hash_default_key40,
98         hash_default_key48,
99         hash_default_key56,
100         hash_default_key64
101 };
102
103 /*
104  * Flow table AH - Write flow_id to packet meta-data
105  */
106 static inline void
107 pkt_work_flow_id(
108         struct rte_mbuf *pkt,
109         struct rte_pipeline_table_entry *table_entry,
110         void *arg)
111 {
112         struct pipeline_flow_classification *p_fc = arg;
113         uint32_t *flow_id_ptr =
114                 RTE_MBUF_METADATA_UINT32_PTR(pkt, p_fc->flow_id_offset);
115         struct flow_table_entry *entry =
116                 (struct flow_table_entry *) table_entry;
117
118         /* Read */
119         uint32_t flow_id = entry->flow_id;
120
121         /* Compute */
122
123         /* Write */
124         *flow_id_ptr = flow_id;
125 }
126
127 static inline void
128 pkt4_work_flow_id(
129         struct rte_mbuf **pkts,
130         struct rte_pipeline_table_entry **table_entries,
131         void *arg)
132 {
133         struct pipeline_flow_classification *p_fc = arg;
134
135         uint32_t *flow_id_ptr0 =
136                 RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p_fc->flow_id_offset);
137         uint32_t *flow_id_ptr1 =
138                 RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p_fc->flow_id_offset);
139         uint32_t *flow_id_ptr2 =
140                 RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p_fc->flow_id_offset);
141         uint32_t *flow_id_ptr3 =
142                 RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p_fc->flow_id_offset);
143
144         struct flow_table_entry *entry0 =
145                 (struct flow_table_entry *) table_entries[0];
146         struct flow_table_entry *entry1 =
147                 (struct flow_table_entry *) table_entries[1];
148         struct flow_table_entry *entry2 =
149                 (struct flow_table_entry *) table_entries[2];
150         struct flow_table_entry *entry3 =
151                 (struct flow_table_entry *) table_entries[3];
152
153         /* Read */
154         uint32_t flow_id0 = entry0->flow_id;
155         uint32_t flow_id1 = entry1->flow_id;
156         uint32_t flow_id2 = entry2->flow_id;
157         uint32_t flow_id3 = entry3->flow_id;
158
159         /* Compute */
160
161         /* Write */
162         *flow_id_ptr0 = flow_id0;
163         *flow_id_ptr1 = flow_id1;
164         *flow_id_ptr2 = flow_id2;
165         *flow_id_ptr3 = flow_id3;
166 }
167
168 PIPELINE_TABLE_AH_HIT(fc_table_ah_hit,
169                 pkt_work_flow_id, pkt4_work_flow_id);
170
171 static rte_pipeline_table_action_handler_hit
172 get_fc_table_ah_hit(struct pipeline_flow_classification *p)
173 {
174         if (p->flow_id)
175                 return fc_table_ah_hit;
176
177         return NULL;
178 }
179
180 /*
181  * Argument parsing
182  */
183 static int
184 pipeline_fc_parse_args(struct pipeline_flow_classification *p,
185         struct pipeline_params *params)
186 {
187         uint32_t n_flows_present = 0;
188         uint32_t key_offset_present = 0;
189         uint32_t key_size_present = 0;
190         uint32_t hash_offset_present = 0;
191         uint32_t key_mask_present = 0;
192         uint32_t flow_id_offset_present = 0;
193
194         uint32_t i;
195         char key_mask_str[PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2 + 1];
196
197         p->hash_offset = 0;
198
199         /* default values */
200         p->flow_id = 0;
201
202         for (i = 0; i < params->n_args; i++) {
203                 char *arg_name = params->args_name[i];
204                 char *arg_value = params->args_value[i];
205
206                 /* n_flows */
207                 if (strcmp(arg_name, "n_flows") == 0) {
208                         int status;
209
210                         PIPELINE_PARSE_ERR_DUPLICATE(
211                                 n_flows_present == 0, params->name,
212                                 arg_name);
213                         n_flows_present = 1;
214
215                         status = parser_read_uint32(&p->n_flows,
216                                 arg_value);
217                         PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&
218                                 (p->n_flows != 0)), params->name,
219                                 arg_name, arg_value);
220                         PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
221                                 params->name, arg_name, arg_value);
222
223                         continue;
224                 }
225
226                 /* key_offset */
227                 if (strcmp(arg_name, "key_offset") == 0) {
228                         int status;
229
230                         PIPELINE_PARSE_ERR_DUPLICATE(
231                                 key_offset_present == 0, params->name,
232                                 arg_name);
233                         key_offset_present = 1;
234
235                         status = parser_read_uint32(&p->key_offset,
236                                 arg_value);
237                         PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
238                                 params->name, arg_name, arg_value);
239                         PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
240                                 params->name, arg_name, arg_value);
241
242                         continue;
243                 }
244
245                 /* key_size */
246                 if (strcmp(arg_name, "key_size") == 0) {
247                         int status;
248
249                         PIPELINE_PARSE_ERR_DUPLICATE(
250                                 key_size_present == 0, params->name,
251                                 arg_name);
252                         key_size_present = 1;
253
254                         status = parser_read_uint32(&p->key_size,
255                                 arg_value);
256                         PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&
257                                 (p->key_size != 0) &&
258                                 (p->key_size % 8 == 0)),
259                                 params->name, arg_name, arg_value);
260                         PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) &&
261                                 (p->key_size <=
262                                 PIPELINE_FC_FLOW_KEY_MAX_SIZE)),
263                                 params->name, arg_name, arg_value);
264
265                         continue;
266                 }
267
268                 /* key_mask */
269                 if (strcmp(arg_name, "key_mask") == 0) {
270                         int mask_str_len = strlen(arg_value);
271
272                         PIPELINE_PARSE_ERR_DUPLICATE(
273                                 key_mask_present == 0,
274                                 params->name, arg_name);
275                         key_mask_present = 1;
276
277                         PIPELINE_ARG_CHECK((mask_str_len <=
278                                 (PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2)),
279                                 "Parse error in section \"%s\": entry "
280                                 "\"%s\" is too long", params->name,
281                                 arg_name);
282
283                         snprintf(key_mask_str, mask_str_len + 1, "%s",
284                                 arg_value);
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 };