apps: add name to LPM parameters
[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                         .name = p->name,
488                         .n_rules = p_rt->n_routes,
489                         .entry_unique_size = sizeof(struct routing_table_entry),
490                         .offset = p_rt->ip_da_offset,
491                 };
492
493                 struct rte_pipeline_table_params table_params = {
494                                 .ops = &rte_table_lpm_ops,
495                                 .arg_create = &table_lpm_params,
496                                 .f_action_hit = routing_table_ah_hit,
497                                 .f_action_miss = NULL,
498                                 .arg_ah = p_rt,
499                                 .action_data_size =
500                                         sizeof(struct routing_table_entry) -
501                                         sizeof(struct rte_pipeline_table_entry),
502                         };
503
504                 int status;
505
506                 status = rte_pipeline_table_create(p->p,
507                         &table_params,
508                         &p->table_id[0]);
509
510                 if (status) {
511                         rte_pipeline_free(p->p);
512                         rte_free(p);
513                         return NULL;
514                 }
515         }
516
517         /* ARP table configuration */
518         if (p_rt->n_arp_entries) {
519                 struct rte_table_hash_key8_ext_params table_arp_params = {
520                         .n_entries = p_rt->n_arp_entries,
521                         .n_entries_ext = p_rt->n_arp_entries,
522                         .f_hash = hash_default_key8,
523                         .seed = 0,
524                         .signature_offset = 0, /* Unused */
525                         .key_offset = p_rt->arp_key_offset,
526                 };
527
528                 struct rte_pipeline_table_params table_params = {
529                         .ops = &rte_table_hash_key8_ext_dosig_ops,
530                         .arg_create = &table_arp_params,
531                         .f_action_hit = arp_table_ah_hit,
532                         .f_action_miss = NULL,
533                         .arg_ah = p_rt,
534                         .action_data_size = sizeof(struct arp_table_entry) -
535                                 sizeof(struct rte_pipeline_table_entry),
536                 };
537
538                 int status;
539
540                 status = rte_pipeline_table_create(p->p,
541                         &table_params,
542                         &p->table_id[1]);
543
544                 if (status) {
545                         rte_pipeline_free(p->p);
546                         rte_free(p);
547                         return NULL;
548                 }
549
550                 p->n_tables++;
551         }
552
553         /* Connecting input ports to tables */
554         for (i = 0; i < p->n_ports_in; i++) {
555                 int status = rte_pipeline_port_in_connect_to_table(p->p,
556                         p->port_in_id[i],
557                         p->table_id[0]);
558
559                 if (status) {
560                         rte_pipeline_free(p->p);
561                         rte_free(p);
562                         return NULL;
563                 }
564         }
565
566         /* Enable input ports */
567         for (i = 0; i < p->n_ports_in; i++) {
568                 int status = rte_pipeline_port_in_enable(p->p,
569                         p->port_in_id[i]);
570
571                 if (status) {
572                         rte_pipeline_free(p->p);
573                         rte_free(p);
574                         return NULL;
575                 }
576         }
577
578         /* Check pipeline consistency */
579         if (rte_pipeline_check(p->p) < 0) {
580                 rte_pipeline_free(p->p);
581                 rte_free(p);
582                 return NULL;
583         }
584
585         /* Message queues */
586         p->n_msgq = params->n_msgq;
587         for (i = 0; i < p->n_msgq; i++)
588                 p->msgq_in[i] = params->msgq_in[i];
589         for (i = 0; i < p->n_msgq; i++)
590                 p->msgq_out[i] = params->msgq_out[i];
591
592         /* Message handlers */
593         memcpy(p->handlers, handlers, sizeof(p->handlers));
594         memcpy(p_rt->custom_handlers,
595                 custom_handlers,
596                 sizeof(p_rt->custom_handlers));
597
598         return p;
599 }
600
601 static int
602 pipeline_routing_free(void *pipeline)
603 {
604         struct pipeline *p = (struct pipeline *) pipeline;
605
606         /* Check input arguments */
607         if (p == NULL)
608                 return -1;
609
610         /* Free resources */
611         rte_pipeline_free(p->p);
612         rte_free(p);
613         return 0;
614 }
615
616 static int
617 pipeline_routing_track(void *pipeline,
618         __rte_unused uint32_t port_in,
619         uint32_t *port_out)
620 {
621         struct pipeline *p = (struct pipeline *) pipeline;
622
623         /* Check input arguments */
624         if ((p == NULL) ||
625                 (port_in >= p->n_ports_in) ||
626                 (port_out == NULL))
627                 return -1;
628
629         if (p->n_ports_in == 1) {
630                 *port_out = 0;
631                 return 0;
632         }
633
634         return -1;
635 }
636
637 static int
638 pipeline_routing_timer(void *pipeline)
639 {
640         struct pipeline *p = (struct pipeline *) pipeline;
641
642         pipeline_msg_req_handle(p);
643         rte_pipeline_flush(p->p);
644
645         return 0;
646 }
647
648 void *
649 pipeline_routing_msg_req_custom_handler(struct pipeline *p,
650         void *msg)
651 {
652         struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
653         struct pipeline_custom_msg_req *req = msg;
654         pipeline_msg_req_handler f_handle;
655
656         f_handle = (req->subtype < PIPELINE_ROUTING_MSG_REQS) ?
657                 p_rt->custom_handlers[req->subtype] :
658                 pipeline_msg_req_invalid_handler;
659
660         if (f_handle == NULL)
661                 f_handle = pipeline_msg_req_invalid_handler;
662
663         return f_handle(p, req);
664 }
665
666 void *
667 pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
668 {
669         struct pipeline_routing_route_add_msg_req *req = msg;
670         struct pipeline_routing_route_add_msg_rsp *rsp = msg;
671
672         struct rte_table_lpm_key key = {
673                 .ip = req->key.key.ipv4.ip,
674                 .depth = req->key.key.ipv4.depth,
675         };
676
677         struct routing_table_entry entry = {
678                 .head = {
679                         .action = RTE_PIPELINE_ACTION_TABLE,
680                         {.table_id = p->table_id[1]},
681                 },
682
683                 .flags = req->flags,
684                 .port_id = req->port_id,
685                 .ip = rte_bswap32(req->ip),
686         };
687
688         if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
689                 rsp->status = -1;
690                 return rsp;
691         }
692
693         rsp->status = rte_pipeline_table_entry_add(p->p,
694                 p->table_id[0],
695                 &key,
696                 (struct rte_pipeline_table_entry *) &entry,
697                 &rsp->key_found,
698                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
699
700         return rsp;
701 }
702
703 void *
704 pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg)
705 {
706         struct pipeline_routing_route_delete_msg_req *req = msg;
707         struct pipeline_routing_route_delete_msg_rsp *rsp = msg;
708
709         struct rte_table_lpm_key key = {
710                 .ip = req->key.key.ipv4.ip,
711                 .depth = req->key.key.ipv4.depth,
712         };
713
714         if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
715                 rsp->status = -1;
716                 return rsp;
717         }
718
719         rsp->status = rte_pipeline_table_entry_delete(p->p,
720                 p->table_id[0],
721                 &key,
722                 &rsp->key_found,
723                 NULL);
724
725         return rsp;
726 }
727
728 void *
729 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
730         void *msg)
731 {
732         struct pipeline_routing_route_add_default_msg_req *req = msg;
733         struct pipeline_routing_route_add_default_msg_rsp *rsp = msg;
734
735         struct routing_table_entry default_entry = {
736                 .head = {
737                         .action = RTE_PIPELINE_ACTION_PORT,
738                         {.port_id = p->port_out_id[req->port_id]},
739                 },
740
741                 .flags = 0,
742                 .port_id = 0,
743                 .ip = 0,
744         };
745
746         rsp->status = rte_pipeline_table_default_entry_add(p->p,
747                 p->table_id[0],
748                 (struct rte_pipeline_table_entry *) &default_entry,
749                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
750
751         return rsp;
752 }
753
754 void *
755 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
756         void *msg)
757 {
758         struct pipeline_routing_route_delete_default_msg_rsp *rsp = msg;
759
760         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
761                 p->table_id[0],
762                 NULL);
763
764         return rsp;
765 }
766
767 void *
768 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg)
769 {
770         struct pipeline_routing_arp_add_msg_req *req = msg;
771         struct pipeline_routing_arp_add_msg_rsp *rsp = msg;
772
773         struct pipeline_routing_arp_key_ipv4 key = {
774                 .port_id = req->key.key.ipv4.port_id,
775                 .ip = rte_bswap32(req->key.key.ipv4.ip),
776         };
777
778         struct arp_table_entry entry = {
779                 .head = {
780                         .action = RTE_PIPELINE_ACTION_PORT,
781                         {.port_id = p->port_out_id[req->key.key.ipv4.port_id]},
782                 },
783
784                 .macaddr = 0, /* set below */
785         };
786
787         if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
788                 rsp->status = -1;
789                 return rsp;
790         }
791
792         *((struct ether_addr *) &entry.macaddr) = req->macaddr;
793
794         rsp->status = rte_pipeline_table_entry_add(p->p,
795                 p->table_id[1],
796                 &key,
797                 (struct rte_pipeline_table_entry *) &entry,
798                 &rsp->key_found,
799                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
800
801         return rsp;
802 }
803
804 void *
805 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg)
806 {
807         struct pipeline_routing_arp_delete_msg_req *req = msg;
808         struct pipeline_routing_arp_delete_msg_rsp *rsp = msg;
809
810         struct pipeline_routing_arp_key_ipv4 key = {
811                 .port_id = req->key.key.ipv4.port_id,
812                 .ip = rte_bswap32(req->key.key.ipv4.ip),
813         };
814
815         if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
816                 rsp->status = -1;
817                 return rsp;
818         }
819
820         rsp->status = rte_pipeline_table_entry_delete(p->p,
821                 p->table_id[1],
822                 &key,
823                 &rsp->key_found,
824                 NULL);
825
826         return rsp;
827 }
828
829 void *
830 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg)
831 {
832         struct pipeline_routing_arp_add_default_msg_req *req = msg;
833         struct pipeline_routing_arp_add_default_msg_rsp *rsp = msg;
834
835         struct arp_table_entry default_entry = {
836                 .head = {
837                         .action = RTE_PIPELINE_ACTION_PORT,
838                         {.port_id = p->port_out_id[req->port_id]},
839                 },
840
841                 .macaddr = 0,
842         };
843
844         rsp->status = rte_pipeline_table_default_entry_add(p->p,
845                 p->table_id[1],
846                 (struct rte_pipeline_table_entry *) &default_entry,
847                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
848
849         return rsp;
850 }
851
852 void *
853 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg)
854 {
855         struct pipeline_routing_arp_delete_default_msg_rsp *rsp = msg;
856
857         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
858                 p->table_id[1],
859                 NULL);
860
861         return rsp;
862 }
863
864 struct pipeline_be_ops pipeline_routing_be_ops = {
865         .f_init = pipeline_routing_init,
866         .f_free = pipeline_routing_free,
867         .f_run = NULL,
868         .f_timer = pipeline_routing_timer,
869         .f_track = pipeline_routing_track,
870 };