1e817dd7ac21a62c7dfe704de7a907f9e311bca4
[dpdk.git] / examples / ip_pipeline / pipeline / pipeline_routing_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 <stdio.h>
35 #include <stdlib.h>
36 #include <stdint.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 #include <rte_common.h>
41 #include <rte_malloc.h>
42 #include <rte_ip.h>
43 #include <rte_byteorder.h>
44 #include <rte_table_lpm.h>
45 #include <rte_table_hash.h>
46 #include <rte_pipeline.h>
47
48 #include "pipeline_routing_be.h"
49 #include "pipeline_actions_common.h"
50 #include "hash_func.h"
51
52 struct pipeline_routing {
53         struct pipeline p;
54         pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS];
55
56         uint32_t n_routes;
57         uint32_t n_arp_entries;
58         uint32_t ip_da_offset;
59         uint32_t arp_key_offset;
60 } __rte_cache_aligned;
61
62 static void *
63 pipeline_routing_msg_req_custom_handler(struct pipeline *p, void *msg);
64
65 static pipeline_msg_req_handler handlers[] = {
66         [PIPELINE_MSG_REQ_PING] =
67                 pipeline_msg_req_ping_handler,
68         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
69                 pipeline_msg_req_stats_port_in_handler,
70         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
71                 pipeline_msg_req_stats_port_out_handler,
72         [PIPELINE_MSG_REQ_STATS_TABLE] =
73                 pipeline_msg_req_stats_table_handler,
74         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
75                 pipeline_msg_req_port_in_enable_handler,
76         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
77                 pipeline_msg_req_port_in_disable_handler,
78         [PIPELINE_MSG_REQ_CUSTOM] =
79                 pipeline_routing_msg_req_custom_handler,
80 };
81
82 static void *
83 pipeline_routing_msg_req_route_add_handler(struct pipeline *p,
84         void *msg);
85
86 static void *
87 pipeline_routing_msg_req_route_del_handler(struct pipeline *p,
88         void *msg);
89
90 static void *
91 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
92         void *msg);
93
94 static void *
95 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
96         void *msg);
97
98 static void *
99 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p,
100         void *msg);
101
102 static void *
103 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p,
104         void *msg);
105
106 static void *
107 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p,
108         void *msg);
109
110 static void *
111 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p,
112         void *msg);
113
114 static pipeline_msg_req_handler custom_handlers[] = {
115         [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] =
116                 pipeline_routing_msg_req_route_add_handler,
117         [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL] =
118                 pipeline_routing_msg_req_route_del_handler,
119         [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT] =
120                 pipeline_routing_msg_req_route_add_default_handler,
121         [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT] =
122                 pipeline_routing_msg_req_route_del_default_handler,
123         [PIPELINE_ROUTING_MSG_REQ_ARP_ADD] =
124                 pipeline_routing_msg_req_arp_add_handler,
125         [PIPELINE_ROUTING_MSG_REQ_ARP_DEL] =
126                 pipeline_routing_msg_req_arp_del_handler,
127         [PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT] =
128                 pipeline_routing_msg_req_arp_add_default_handler,
129         [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] =
130                 pipeline_routing_msg_req_arp_del_default_handler,
131 };
132
133 /*
134  * Routing table
135  */
136 struct routing_table_entry {
137         struct rte_pipeline_table_entry head;
138         uint32_t flags;
139         uint32_t port_id; /* Output port ID */
140         uint32_t ip; /* Next hop IP address (only valid for remote routes) */
141 };
142
143 static inline void
144 pkt_work_routing(
145         struct rte_mbuf *pkt,
146         struct rte_pipeline_table_entry *table_entry,
147         void *arg)
148 {
149         struct routing_table_entry *entry =
150                 (struct routing_table_entry *) table_entry;
151         struct pipeline_routing *p_rt = arg;
152
153         struct pipeline_routing_arp_key_ipv4 *arp_key =
154                 (struct pipeline_routing_arp_key_ipv4 *)
155                 RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->arp_key_offset);
156         uint32_t ip = RTE_MBUF_METADATA_UINT32(pkt, p_rt->ip_da_offset);
157
158         arp_key->port_id = entry->port_id;
159         arp_key->ip = entry->ip;
160         if (entry->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
161                 arp_key->ip = ip;
162 }
163
164 static inline void
165 pkt4_work_routing(
166         struct rte_mbuf **pkts,
167         struct rte_pipeline_table_entry **table_entries,
168         void *arg)
169 {
170         struct routing_table_entry *entry0 =
171                 (struct routing_table_entry *) table_entries[0];
172         struct routing_table_entry *entry1 =
173                 (struct routing_table_entry *) table_entries[1];
174         struct routing_table_entry *entry2 =
175                 (struct routing_table_entry *) table_entries[2];
176         struct routing_table_entry *entry3 =
177                 (struct routing_table_entry *) table_entries[3];
178         struct pipeline_routing *p_rt = arg;
179
180         struct pipeline_routing_arp_key_ipv4 *arp_key0 =
181                 (struct pipeline_routing_arp_key_ipv4 *)
182                 RTE_MBUF_METADATA_UINT8_PTR(pkts[0], p_rt->arp_key_offset);
183         struct pipeline_routing_arp_key_ipv4 *arp_key1 =
184                 (struct pipeline_routing_arp_key_ipv4 *)
185                 RTE_MBUF_METADATA_UINT8_PTR(pkts[1], p_rt->arp_key_offset);
186         struct pipeline_routing_arp_key_ipv4 *arp_key2 =
187                 (struct pipeline_routing_arp_key_ipv4 *)
188                 RTE_MBUF_METADATA_UINT8_PTR(pkts[2], p_rt->arp_key_offset);
189         struct pipeline_routing_arp_key_ipv4 *arp_key3 =
190                 (struct pipeline_routing_arp_key_ipv4 *)
191                 RTE_MBUF_METADATA_UINT8_PTR(pkts[3], p_rt->arp_key_offset);
192
193         uint32_t ip0 = RTE_MBUF_METADATA_UINT32(pkts[0], p_rt->ip_da_offset);
194         uint32_t ip1 = RTE_MBUF_METADATA_UINT32(pkts[1], p_rt->ip_da_offset);
195         uint32_t ip2 = RTE_MBUF_METADATA_UINT32(pkts[2], p_rt->ip_da_offset);
196         uint32_t ip3 = RTE_MBUF_METADATA_UINT32(pkts[3], p_rt->ip_da_offset);
197
198         arp_key0->port_id = entry0->port_id;
199         arp_key1->port_id = entry1->port_id;
200         arp_key2->port_id = entry2->port_id;
201         arp_key3->port_id = entry3->port_id;
202
203         arp_key0->ip = entry0->ip;
204         if (entry0->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
205                 arp_key0->ip = ip0;
206
207         arp_key1->ip = entry1->ip;
208         if (entry1->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
209                 arp_key1->ip = ip1;
210
211         arp_key2->ip = entry2->ip;
212         if (entry2->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
213                 arp_key2->ip = ip2;
214
215         arp_key3->ip = entry3->ip;
216         if (entry3->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
217                 arp_key3->ip = ip3;
218 }
219
220 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit,
221         pkt_work_routing,
222         pkt4_work_routing);
223
224 /*
225  * ARP table
226  */
227 struct arp_table_entry {
228         struct rte_pipeline_table_entry head;
229         uint64_t macaddr;
230 };
231
232 static inline void
233 pkt_work_arp(
234         struct rte_mbuf *pkt,
235         struct rte_pipeline_table_entry *table_entry,
236         __rte_unused void *arg)
237 {
238         struct arp_table_entry *entry = (struct arp_table_entry *) table_entry;
239
240         /* Read: pkt buffer - mbuf */
241         uint8_t *raw = rte_pktmbuf_mtod(pkt, uint8_t *);
242
243         /* Read: table entry */
244         uint64_t mac_addr_dst = entry->macaddr;
245         uint64_t mac_addr_src = 0;
246
247         /* Compute: Ethernet header */
248         uint64_t slab0 = mac_addr_dst | (mac_addr_src << 48);
249         uint32_t slab1 = mac_addr_src >> 16;
250
251         /* Write: pkt buffer - pkt headers */
252         *((uint64_t *) raw) = slab0;
253         *((uint32_t *) (raw + 8)) = slab1;
254 }
255
256 static inline void
257 pkt4_work_arp(
258         struct rte_mbuf **pkts,
259         struct rte_pipeline_table_entry **table_entries,
260         __rte_unused void *arg)
261 {
262         struct arp_table_entry *entry0 =
263                 (struct arp_table_entry *) table_entries[0];
264         struct arp_table_entry *entry1 =
265                 (struct arp_table_entry *) table_entries[1];
266         struct arp_table_entry *entry2 =
267                 (struct arp_table_entry *) table_entries[2];
268         struct arp_table_entry *entry3 =
269                 (struct arp_table_entry *) table_entries[3];
270
271         /* Read: pkt buffer - mbuf */
272         uint8_t *raw0 = rte_pktmbuf_mtod(pkts[0], uint8_t *);
273         uint8_t *raw1 = rte_pktmbuf_mtod(pkts[1], uint8_t *);
274         uint8_t *raw2 = rte_pktmbuf_mtod(pkts[2], uint8_t *);
275         uint8_t *raw3 = rte_pktmbuf_mtod(pkts[3], uint8_t *);
276
277         /* Read: table entry */
278         uint64_t mac_addr_dst0 = entry0->macaddr;
279         uint64_t mac_addr_dst1 = entry1->macaddr;
280         uint64_t mac_addr_dst2 = entry2->macaddr;
281         uint64_t mac_addr_dst3 = entry3->macaddr;
282
283         uint64_t mac_addr_src0 = 0;
284         uint64_t mac_addr_src1 = 0;
285         uint64_t mac_addr_src2 = 0;
286         uint64_t mac_addr_src3 = 0;
287
288         /* Compute: Ethernet header */
289         uint64_t pkt0_slab0 = mac_addr_dst0 | (mac_addr_src0 << 48);
290         uint64_t pkt1_slab0 = mac_addr_dst1 | (mac_addr_src1 << 48);
291         uint64_t pkt2_slab0 = mac_addr_dst2 | (mac_addr_src2 << 48);
292         uint64_t pkt3_slab0 = mac_addr_dst3 | (mac_addr_src3 << 48);
293
294         uint32_t pkt0_slab1 = mac_addr_src0 >> 16;
295         uint32_t pkt1_slab1 = mac_addr_src1 >> 16;
296         uint32_t pkt2_slab1 = mac_addr_src2 >> 16;
297         uint32_t pkt3_slab1 = mac_addr_src3 >> 16;
298
299         /* Write: pkt buffer - pkt headers */
300         *((uint64_t *) raw0) = pkt0_slab0;
301         *((uint32_t *) (raw0 + 8)) = pkt0_slab1;
302         *((uint64_t *) raw1) = pkt1_slab0;
303         *((uint32_t *) (raw1 + 8)) = pkt1_slab1;
304         *((uint64_t *) raw2) = pkt2_slab0;
305         *((uint32_t *) (raw2 + 8)) = pkt2_slab1;
306         *((uint64_t *) raw3) = pkt3_slab0;
307         *((uint32_t *) (raw3 + 8)) = pkt3_slab1;
308 }
309
310 PIPELINE_TABLE_AH_HIT(arp_table_ah_hit,
311         pkt_work_arp,
312         pkt4_work_arp);
313
314 static int
315 pipeline_routing_parse_args(struct pipeline_routing *p,
316         struct pipeline_params *params)
317 {
318         uint32_t n_routes_present = 0;
319         uint32_t n_arp_entries_present = 0;
320         uint32_t ip_da_offset_present = 0;
321         uint32_t arp_key_offset_present = 0;
322         uint32_t i;
323
324         for (i = 0; i < params->n_args; i++) {
325                 char *arg_name = params->args_name[i];
326                 char *arg_value = params->args_value[i];
327
328                 /* n_routes */
329                 if (strcmp(arg_name, "n_routes") == 0) {
330                         if (n_routes_present)
331                                 return -1;
332                         n_routes_present = 1;
333
334                         p->n_routes = atoi(arg_value);
335                         if (p->n_routes == 0)
336                                 return -1;
337
338                         continue;
339                 }
340
341                 /* n_arp_entries */
342                 if (strcmp(arg_name, "n_arp_entries") == 0) {
343                         if (n_arp_entries_present)
344                                 return -1;
345                         n_arp_entries_present = 1;
346
347                         p->n_arp_entries = atoi(arg_value);
348                         if (p->n_arp_entries == 0)
349                                 return -1;
350
351                         continue;
352                 }
353
354                 /* ip_da_offset */
355                 if (strcmp(arg_name, "ip_da_offset") == 0) {
356                         if (ip_da_offset_present)
357                                 return -1;
358                         ip_da_offset_present = 1;
359
360                         p->ip_da_offset = atoi(arg_value);
361
362                         continue;
363                 }
364
365                 /* arp_key_offset */
366                 if (strcmp(arg_name, "arp_key_offset") == 0) {
367                         if (arp_key_offset_present)
368                                 return -1;
369                         arp_key_offset_present = 1;
370
371                         p->arp_key_offset = atoi(arg_value);
372
373                         continue;
374                 }
375
376                 /* any other */
377                 return -1;
378         }
379
380         /* Check that mandatory arguments are present */
381         if ((n_routes_present == 0) ||
382                 (n_arp_entries_present == 0) ||
383                 (ip_da_offset_present == 0) ||
384                 (n_arp_entries_present && (arp_key_offset_present == 0)))
385                 return -1;
386
387         return 0;
388 }
389
390 static void *
391 pipeline_routing_init(struct pipeline_params *params,
392         __rte_unused void *arg)
393 {
394         struct pipeline *p;
395         struct pipeline_routing *p_rt;
396         uint32_t size, i;
397
398         /* Check input arguments */
399         if ((params == NULL) ||
400                 (params->n_ports_in == 0) ||
401                 (params->n_ports_out == 0))
402                 return NULL;
403
404         /* Memory allocation */
405         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
406         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
407         p_rt = (struct pipeline_routing *) p;
408         if (p == NULL)
409                 return NULL;
410
411         strcpy(p->name, params->name);
412         p->log_level = params->log_level;
413
414         PLOG(p, HIGH, "Routing");
415
416         /* Parse arguments */
417         if (pipeline_routing_parse_args(p_rt, params))
418                 return NULL;
419
420         /* Pipeline */
421         {
422                 struct rte_pipeline_params pipeline_params = {
423                         .name = params->name,
424                         .socket_id = params->socket_id,
425                         .offset_port_id = 0,
426                 };
427
428                 p->p = rte_pipeline_create(&pipeline_params);
429                 if (p->p == NULL) {
430                         rte_free(p);
431                         return NULL;
432                 }
433         }
434
435         /* Input ports */
436         p->n_ports_in = params->n_ports_in;
437         for (i = 0; i < p->n_ports_in; i++) {
438                 struct rte_pipeline_port_in_params port_params = {
439                         .ops = pipeline_port_in_params_get_ops(
440                                 &params->port_in[i]),
441                         .arg_create = pipeline_port_in_params_convert(
442                                 &params->port_in[i]),
443                         .f_action = NULL,
444                         .arg_ah = NULL,
445                         .burst_size = params->port_in[i].burst_size,
446                 };
447
448                 int status = rte_pipeline_port_in_create(p->p,
449                         &port_params,
450                         &p->port_in_id[i]);
451
452                 if (status) {
453                         rte_pipeline_free(p->p);
454                         rte_free(p);
455                         return NULL;
456                 }
457         }
458
459         /* Output ports */
460         p->n_ports_out = params->n_ports_out;
461         for (i = 0; i < p->n_ports_out; i++) {
462                 struct rte_pipeline_port_out_params port_params = {
463                         .ops = pipeline_port_out_params_get_ops(
464                                 &params->port_out[i]),
465                         .arg_create = pipeline_port_out_params_convert(
466                                 &params->port_out[i]),
467                         .f_action = NULL,
468                         .f_action_bulk = NULL,
469                         .arg_ah = NULL,
470                 };
471
472                 int status = rte_pipeline_port_out_create(p->p,
473                         &port_params,
474                         &p->port_out_id[i]);
475
476                 if (status) {
477                         rte_pipeline_free(p->p);
478                         rte_free(p);
479                         return NULL;
480                 }
481         }
482
483         /* Routing table */
484         p->n_tables = 1;
485         {
486                 struct rte_table_lpm_params table_lpm_params = {
487                         .n_rules = p_rt->n_routes,
488                         .entry_unique_size = sizeof(struct routing_table_entry),
489                         .offset = p_rt->ip_da_offset,
490                 };
491
492                 struct rte_pipeline_table_params table_params = {
493                                 .ops = &rte_table_lpm_ops,
494                                 .arg_create = &table_lpm_params,
495                                 .f_action_hit = routing_table_ah_hit,
496                                 .f_action_miss = NULL,
497                                 .arg_ah = p_rt,
498                                 .action_data_size =
499                                         sizeof(struct routing_table_entry) -
500                                         sizeof(struct rte_pipeline_table_entry),
501                         };
502
503                 int status;
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         /* ARP table configuration */
517         if (p_rt->n_arp_entries) {
518                 struct rte_table_hash_key8_ext_params table_arp_params = {
519                         .n_entries = p_rt->n_arp_entries,
520                         .n_entries_ext = p_rt->n_arp_entries,
521                         .f_hash = hash_default_key8,
522                         .seed = 0,
523                         .signature_offset = 0, /* Unused */
524                         .key_offset = p_rt->arp_key_offset,
525                 };
526
527                 struct rte_pipeline_table_params table_params = {
528                         .ops = &rte_table_hash_key8_ext_dosig_ops,
529                         .arg_create = &table_arp_params,
530                         .f_action_hit = arp_table_ah_hit,
531                         .f_action_miss = NULL,
532                         .arg_ah = p_rt,
533                         .action_data_size = sizeof(struct arp_table_entry) -
534                                 sizeof(struct rte_pipeline_table_entry),
535                 };
536
537                 int status;
538
539                 status = rte_pipeline_table_create(p->p,
540                         &table_params,
541                         &p->table_id[1]);
542
543                 if (status) {
544                         rte_pipeline_free(p->p);
545                         rte_free(p);
546                         return NULL;
547                 }
548
549                 p->n_tables++;
550         }
551
552         /* Connecting input ports to tables */
553         for (i = 0; i < p->n_ports_in; i++) {
554                 int status = rte_pipeline_port_in_connect_to_table(p->p,
555                         p->port_in_id[i],
556                         p->table_id[0]);
557
558                 if (status) {
559                         rte_pipeline_free(p->p);
560                         rte_free(p);
561                         return NULL;
562                 }
563         }
564
565         /* Enable input ports */
566         for (i = 0; i < p->n_ports_in; i++) {
567                 int status = rte_pipeline_port_in_enable(p->p,
568                         p->port_in_id[i]);
569
570                 if (status) {
571                         rte_pipeline_free(p->p);
572                         rte_free(p);
573                         return NULL;
574                 }
575         }
576
577         /* Check pipeline consistency */
578         if (rte_pipeline_check(p->p) < 0) {
579                 rte_pipeline_free(p->p);
580                 rte_free(p);
581                 return NULL;
582         }
583
584         /* Message queues */
585         p->n_msgq = params->n_msgq;
586         for (i = 0; i < p->n_msgq; i++)
587                 p->msgq_in[i] = params->msgq_in[i];
588         for (i = 0; i < p->n_msgq; i++)
589                 p->msgq_out[i] = params->msgq_out[i];
590
591         /* Message handlers */
592         memcpy(p->handlers, handlers, sizeof(p->handlers));
593         memcpy(p_rt->custom_handlers,
594                 custom_handlers,
595                 sizeof(p_rt->custom_handlers));
596
597         return p;
598 }
599
600 static int
601 pipeline_routing_free(void *pipeline)
602 {
603         struct pipeline *p = (struct pipeline *) pipeline;
604
605         /* Check input arguments */
606         if (p == NULL)
607                 return -1;
608
609         /* Free resources */
610         rte_pipeline_free(p->p);
611         rte_free(p);
612         return 0;
613 }
614
615 static int
616 pipeline_routing_track(void *pipeline,
617         __rte_unused uint32_t port_in,
618         uint32_t *port_out)
619 {
620         struct pipeline *p = (struct pipeline *) pipeline;
621
622         /* Check input arguments */
623         if ((p == NULL) ||
624                 (port_in >= p->n_ports_in) ||
625                 (port_out == NULL))
626                 return -1;
627
628         if (p->n_ports_in == 1) {
629                 *port_out = 0;
630                 return 0;
631         }
632
633         return -1;
634 }
635
636 static int
637 pipeline_routing_timer(void *pipeline)
638 {
639         struct pipeline *p = (struct pipeline *) pipeline;
640
641         pipeline_msg_req_handle(p);
642         rte_pipeline_flush(p->p);
643
644         return 0;
645 }
646
647 void *
648 pipeline_routing_msg_req_custom_handler(struct pipeline *p,
649         void *msg)
650 {
651         struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
652         struct pipeline_custom_msg_req *req = msg;
653         pipeline_msg_req_handler f_handle;
654
655         f_handle = (req->subtype < PIPELINE_ROUTING_MSG_REQS) ?
656                 p_rt->custom_handlers[req->subtype] :
657                 pipeline_msg_req_invalid_handler;
658
659         if (f_handle == NULL)
660                 f_handle = pipeline_msg_req_invalid_handler;
661
662         return f_handle(p, req);
663 }
664
665 void *
666 pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
667 {
668         struct pipeline_routing_route_add_msg_req *req = msg;
669         struct pipeline_routing_route_add_msg_rsp *rsp = msg;
670
671         struct rte_table_lpm_key key = {
672                 .ip = req->key.key.ipv4.ip,
673                 .depth = req->key.key.ipv4.depth,
674         };
675
676         struct routing_table_entry entry = {
677                 .head = {
678                         .action = RTE_PIPELINE_ACTION_TABLE,
679                         {.table_id = p->table_id[1]},
680                 },
681
682                 .flags = req->flags,
683                 .port_id = req->port_id,
684                 .ip = rte_bswap32(req->ip),
685         };
686
687         if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
688                 rsp->status = -1;
689                 return rsp;
690         }
691
692         rsp->status = rte_pipeline_table_entry_add(p->p,
693                 p->table_id[0],
694                 &key,
695                 (struct rte_pipeline_table_entry *) &entry,
696                 &rsp->key_found,
697                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
698
699         return rsp;
700 }
701
702 void *
703 pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg)
704 {
705         struct pipeline_routing_route_delete_msg_req *req = msg;
706         struct pipeline_routing_route_delete_msg_rsp *rsp = msg;
707
708         struct rte_table_lpm_key key = {
709                 .ip = req->key.key.ipv4.ip,
710                 .depth = req->key.key.ipv4.depth,
711         };
712
713         if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
714                 rsp->status = -1;
715                 return rsp;
716         }
717
718         rsp->status = rte_pipeline_table_entry_delete(p->p,
719                 p->table_id[0],
720                 &key,
721                 &rsp->key_found,
722                 NULL);
723
724         return rsp;
725 }
726
727 void *
728 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
729         void *msg)
730 {
731         struct pipeline_routing_route_add_default_msg_req *req = msg;
732         struct pipeline_routing_route_add_default_msg_rsp *rsp = msg;
733
734         struct routing_table_entry default_entry = {
735                 .head = {
736                         .action = RTE_PIPELINE_ACTION_PORT,
737                         {.port_id = p->port_out_id[req->port_id]},
738                 },
739
740                 .flags = 0,
741                 .port_id = 0,
742                 .ip = 0,
743         };
744
745         rsp->status = rte_pipeline_table_default_entry_add(p->p,
746                 p->table_id[0],
747                 (struct rte_pipeline_table_entry *) &default_entry,
748                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
749
750         return rsp;
751 }
752
753 void *
754 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
755         void *msg)
756 {
757         struct pipeline_routing_route_delete_default_msg_rsp *rsp = msg;
758
759         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
760                 p->table_id[0],
761                 NULL);
762
763         return rsp;
764 }
765
766 void *
767 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg)
768 {
769         struct pipeline_routing_arp_add_msg_req *req = msg;
770         struct pipeline_routing_arp_add_msg_rsp *rsp = msg;
771
772         struct pipeline_routing_arp_key_ipv4 key = {
773                 .port_id = req->key.key.ipv4.port_id,
774                 .ip = rte_bswap32(req->key.key.ipv4.ip),
775         };
776
777         struct arp_table_entry entry = {
778                 .head = {
779                         .action = RTE_PIPELINE_ACTION_PORT,
780                         {.port_id = p->port_out_id[req->key.key.ipv4.port_id]},
781                 },
782
783                 .macaddr = 0, /* set below */
784         };
785
786         if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
787                 rsp->status = -1;
788                 return rsp;
789         }
790
791         *((struct ether_addr *) &entry.macaddr) = req->macaddr;
792
793         rsp->status = rte_pipeline_table_entry_add(p->p,
794                 p->table_id[1],
795                 &key,
796                 (struct rte_pipeline_table_entry *) &entry,
797                 &rsp->key_found,
798                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
799
800         return rsp;
801 }
802
803 void *
804 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg)
805 {
806         struct pipeline_routing_arp_delete_msg_req *req = msg;
807         struct pipeline_routing_arp_delete_msg_rsp *rsp = msg;
808
809         struct pipeline_routing_arp_key_ipv4 key = {
810                 .port_id = req->key.key.ipv4.port_id,
811                 .ip = rte_bswap32(req->key.key.ipv4.ip),
812         };
813
814         if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
815                 rsp->status = -1;
816                 return rsp;
817         }
818
819         rsp->status = rte_pipeline_table_entry_delete(p->p,
820                 p->table_id[1],
821                 &key,
822                 &rsp->key_found,
823                 NULL);
824
825         return rsp;
826 }
827
828 void *
829 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg)
830 {
831         struct pipeline_routing_arp_add_default_msg_req *req = msg;
832         struct pipeline_routing_arp_add_default_msg_rsp *rsp = msg;
833
834         struct arp_table_entry default_entry = {
835                 .head = {
836                         .action = RTE_PIPELINE_ACTION_PORT,
837                         {.port_id = p->port_out_id[req->port_id]},
838                 },
839
840                 .macaddr = 0,
841         };
842
843         rsp->status = rte_pipeline_table_default_entry_add(p->p,
844                 p->table_id[1],
845                 (struct rte_pipeline_table_entry *) &default_entry,
846                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
847
848         return rsp;
849 }
850
851 void *
852 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg)
853 {
854         struct pipeline_routing_arp_delete_default_msg_rsp *rsp = msg;
855
856         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
857                 p->table_id[1],
858                 NULL);
859
860         return rsp;
861 }
862
863 struct pipeline_be_ops pipeline_routing_be_ops = {
864         .f_init = pipeline_routing_init,
865         .f_free = pipeline_routing_free,
866         .f_run = NULL,
867         .f_timer = pipeline_routing_timer,
868         .f_track = pipeline_routing_track,
869 };