X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fip_pipeline%2Fpipeline%2Fpipeline_routing.c;h=3deaff9c4e8a660712f86604a8da1d9dd30c5c60;hb=ad10c178210e11bfa468f7f5ecca597644d2eb34;hp=4d074c170fe706819e9d9997b625b298dd10c138;hpb=760064838ec06cbdbe96375930237510e260d09e;p=dpdk.git diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c index 4d074c170f..3deaff9c4e 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing.c +++ b/examples/ip_pipeline/pipeline/pipeline_routing.c @@ -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; @@ -848,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 * @@ -1385,8 +1628,8 @@ static cmdline_parse_ctx_t pipeline_cmds[] = { }; static struct pipeline_fe_ops pipeline_routing_fe_ops = { - .f_init = pipeline_routing_init, - .f_post_init = NULL, + .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,