table: remove deprecated 16-byte key hash tables
[dpdk.git] / examples / ip_pipeline / pipeline / pipeline_routing.c
index c68e470..3deaff9 100644 (file)
@@ -58,8 +58,14 @@ struct app_pipeline_routing_arp_entry {
 
 struct pipeline_routing {
        /* Parameters */
+       struct app_params *app;
+       uint32_t pipeline_id;
        uint32_t n_ports_in;
        uint32_t n_ports_out;
+       struct pipeline_routing_params rp;
+
+       /* Links */
+       uint32_t link_id[PIPELINE_MAX_PORT_OUT];
 
        /* Routes */
        TAILQ_HEAD(, app_pipeline_routing_route) routes;
@@ -78,12 +84,151 @@ struct pipeline_routing {
        void *default_arp_entry_ptr;
 };
 
+static int
+app_pipeline_routing_find_link(struct pipeline_routing *p,
+       uint32_t link_id,
+       uint32_t *port_id)
+{
+       uint32_t i;
+
+       for (i = 0; i < p->n_ports_out; i++)
+               if (p->link_id[i] == link_id) {
+                       *port_id = i;
+                       return 0;
+               }
+
+       return -1;
+}
+
+static void
+app_pipeline_routing_link_op(__rte_unused struct app_params *app,
+       uint32_t link_id,
+       uint32_t up,
+       void *arg)
+{
+       struct pipeline_routing_route_key key0, key1;
+       struct pipeline_routing *p = arg;
+       struct app_link_params *lp;
+       uint32_t port_id, netmask;
+       int status;
+
+       if (app == NULL)
+               return;
+
+       APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp);
+       if (lp == NULL)
+               return;
+
+       status = app_pipeline_routing_find_link(p,
+               link_id,
+               &port_id);
+       if (status)
+               return;
+
+       netmask = (~0U) << (32 - lp->depth);
+
+       /* Local network (directly attached network) */
+       key0.type = PIPELINE_ROUTING_ROUTE_IPV4;
+       key0.key.ipv4.ip = lp->ip & netmask;
+       key0.key.ipv4.depth = lp->depth;
+
+       /* Local termination */
+       key1.type = PIPELINE_ROUTING_ROUTE_IPV4;
+       key1.key.ipv4.ip = lp->ip;
+       key1.key.ipv4.depth = 32;
+
+       if (up) {
+               struct pipeline_routing_route_data data0, data1;
+
+               /* Local network (directly attached network) */
+               memset(&data0, 0, sizeof(data0));
+               data0.flags = PIPELINE_ROUTING_ROUTE_LOCAL |
+                       PIPELINE_ROUTING_ROUTE_ARP;
+               if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ)
+                       data0.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
+               if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) {
+                       data0.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
+                       data0.l2.mpls.n_labels = 1;
+               }
+               data0.port_id = port_id;
+
+               if (p->rp.n_arp_entries)
+                       app_pipeline_routing_add_route(app,
+                               p->pipeline_id,
+                               &key0,
+                               &data0);
+
+               /* Local termination */
+               memset(&data1, 0, sizeof(data1));
+               data1.flags = PIPELINE_ROUTING_ROUTE_LOCAL |
+                       PIPELINE_ROUTING_ROUTE_ARP;
+               if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ)
+                       data1.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
+               if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) {
+                       data1.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
+                       data1.l2.mpls.n_labels = 1;
+               }
+               data1.port_id = p->rp.port_local_dest;
+
+               app_pipeline_routing_add_route(app,
+                       p->pipeline_id,
+                       &key1,
+                       &data1);
+       } else {
+               /* Local network (directly attached network) */
+               if (p->rp.n_arp_entries)
+                       app_pipeline_routing_delete_route(app,
+                               p->pipeline_id,
+                               &key0);
+
+               /* Local termination */
+               app_pipeline_routing_delete_route(app,
+                       p->pipeline_id,
+                       &key1);
+       }
+}
+
+static int
+app_pipeline_routing_set_link_op(
+       struct app_params *app,
+       struct pipeline_routing *p)
+{
+       uint32_t port_id;
+
+       for (port_id = 0; port_id < p->n_ports_out; port_id++) {
+               struct app_link_params *link;
+               uint32_t link_id;
+               int status;
+
+               link = app_pipeline_track_pktq_out_to_link(app,
+                       p->pipeline_id,
+                       port_id);
+               if (link == NULL)
+                       continue;
+
+               link_id = link - app->link_params;
+               p->link_id[port_id] = link_id;
+
+               status = app_link_set_op(app,
+                       link_id,
+                       p->pipeline_id,
+                       app_pipeline_routing_link_op,
+                       (void *) p);
+               if (status)
+                       return status;
+       }
+
+       return 0;
+}
+
 static void *
-pipeline_routing_init(struct pipeline_params *params,
-       __rte_unused void *arg)
+app_pipeline_routing_init(struct pipeline_params *params,
+       void *arg)
 {
+       struct app_params *app = (struct app_params *) arg;
        struct pipeline_routing *p;
-       uint32_t size;
+       uint32_t pipeline_id, size;
+       int status;
 
        /* Check input arguments */
        if ((params == NULL) ||
@@ -91,6 +236,8 @@ pipeline_routing_init(struct pipeline_params *params,
                (params->n_ports_out == 0))
                return NULL;
 
+       APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id);
+
        /* Memory allocation */
        size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
        p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
@@ -98,18 +245,39 @@ pipeline_routing_init(struct pipeline_params *params,
                return NULL;
 
        /* Initialization */
+       p->app = app;
+       p->pipeline_id = pipeline_id;
        p->n_ports_in = params->n_ports_in;
        p->n_ports_out = params->n_ports_out;
 
+       status = pipeline_routing_parse_args(&p->rp, params);
+       if (status) {
+               rte_free(p);
+               return NULL;
+       }
        TAILQ_INIT(&p->routes);
        p->n_routes = 0;
 
        TAILQ_INIT(&p->arp_entries);
        p->n_arp_entries = 0;
 
+       app_pipeline_routing_set_link_op(app, p);
+
        return p;
 }
 
+static int
+app_pipeline_routing_post_init(void *pipeline)
+{
+       struct pipeline_routing *p = pipeline;
+
+       /* Check input arguments */
+       if (p == NULL)
+               return -1;
+
+       return app_pipeline_routing_set_macaddr(p->app, p->pipeline_id);
+}
+
 static int
 app_pipeline_routing_free(void *pipeline)
 {
@@ -197,7 +365,9 @@ print_route(const struct app_pipeline_routing_route *route)
                        key->depth,
                        route->data.port_id);
 
-               if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
+               if (route->data.flags & PIPELINE_ROUTING_ROUTE_LOCAL)
+                       printf(", Local");
+               else if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
                        printf(
                                ", Next Hop IP = %" PRIu32 ".%" PRIu32
                                ".%" PRIu32 ".%" PRIu32,
@@ -324,6 +494,26 @@ app_pipeline_routing_add_route(struct app_params *app,
                /* data */
                if (data->port_id >= p->n_ports_out)
                        return -1;
+
+               /* Valid range of VLAN tags 12 bits */
+               if (data->flags & PIPELINE_ROUTING_ROUTE_QINQ)
+                       if ((data->l2.qinq.svlan & 0xF000) ||
+                                       (data->l2.qinq.cvlan & 0xF000))
+                               return -1;
+
+               /* Max number of MPLS labels supported */
+               if (data->flags & PIPELINE_ROUTING_ROUTE_MPLS) {
+                       uint32_t i;
+
+                       if (data->l2.mpls.n_labels >
+                                       PIPELINE_ROUTING_MPLS_LABELS_MAX)
+                               return -1;
+
+                       /* Max MPLS label value 20 bits */
+                       for (i = 0; i < data->l2.mpls.n_labels; i++)
+                               if (data->l2.mpls.labels[i] & 0xFFF00000)
+                                       return -1;
+               }
        }
        break;
 
@@ -382,8 +572,6 @@ app_pipeline_routing_add_route(struct app_params *app,
                p->n_routes++;
        }
 
-       print_route(entry);
-
        /* Message buffer free */
        app_msg_free(app, rsp);
        return 0;
@@ -676,8 +864,6 @@ app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
                p->n_arp_entries++;
        }
 
-       print_arp_entry(entry);
-
        /* Message buffer free */
        app_msg_free(app, rsp);
        return 0;
@@ -852,6 +1038,59 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
        return 0;
 }
 
+int
+app_pipeline_routing_set_macaddr(struct app_params *app,
+       uint32_t pipeline_id)
+{
+       struct app_pipeline_params *p;
+       struct pipeline_routing_set_macaddr_msg_req *req;
+       struct pipeline_routing_set_macaddr_msg_rsp *rsp;
+       uint32_t port_id;
+
+       /* Check input arguments */
+       if (app == NULL)
+               return -EINVAL;
+
+       APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
+       if (p == NULL)
+               return -EINVAL;
+
+       /* Allocate and write request */
+       req = app_msg_alloc(app);
+       if (req == NULL)
+               return -ENOMEM;
+
+       req->type = PIPELINE_MSG_REQ_CUSTOM;
+       req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR;
+
+       memset(req->macaddr, 0, sizeof(req->macaddr));
+       for (port_id = 0; port_id < p->n_pktq_out; port_id++) {
+               struct app_link_params *link;
+
+               link = app_pipeline_track_pktq_out_to_link(app,
+                       pipeline_id,
+                       port_id);
+               if (link)
+                       req->macaddr[port_id] = link->mac_addr;
+       }
+
+       /* Send request and wait for response */
+       rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+       if (rsp == NULL)
+               return -ETIMEDOUT;
+
+       /* Read response and write entry */
+       if (rsp->status) {
+               app_msg_free(app, rsp);
+               return rsp->status;
+       }
+
+       /* Free response */
+       app_msg_free(app, rsp);
+
+       return 0;
+}
+
 /*
  * route
  *
@@ -1389,8 +1628,10 @@ static cmdline_parse_ctx_t pipeline_cmds[] = {
 };
 
 static struct pipeline_fe_ops pipeline_routing_fe_ops = {
-       .f_init = pipeline_routing_init,
+       .f_init = app_pipeline_routing_init,
+       .f_post_init = app_pipeline_routing_post_init,
        .f_free = app_pipeline_routing_free,
+       .f_track = app_pipeline_track_default,
        .cmds = pipeline_cmds,
 };