From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id CF851298F for ; Sat, 7 May 2016 01:51:34 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga104.fm.intel.com with ESMTP; 06 May 2016 16:51:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,588,1455004800"; d="scan'208";a="947955399" Received: from sie-lab-212-251.ir.intel.com (HELO silpixa00381635.ir.intel.com) ([10.237.212.251]) by orsmga001.jf.intel.com with ESMTP; 06 May 2016 16:51:32 -0700 From: Jasvinder Singh To: dev@dpdk.org Cc: cristian.dumitrescu@intel.com Date: Sat, 7 May 2016 00:57:51 +0100 Message-Id: <1462579071-82557-1-git-send-email-jasvinder.singh@intel.com> X-Mailer: git-send-email 2.5.5 Subject: [dpdk-dev] [PATCH] ip_pipeline: routing pipeline improvements X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 May 2016 23:51:35 -0000 This patch implements the tracking mechanism for the routing pipeline in order to identify the physical nic port where a specific output port of the rotuing pipeline is eventually connected. Depending upon the application, tracking could involve traversing the other intermediate pipelines. Typically, tracking is successful through those intermediate pipelines where each input port is connected to a single out port for example pass-through (RX, TX and TM), flow-actions etc. In such pipelines, all the packets from the current port can only go out of the idetified output port. In contrast, the pipelines such as flow-classification, firewall don't allow the tracking mechanism due to one to many mapping between input and output ports. As a result of tracking mechainsm, routing pipeline uses the real MAC addresses of the network interfaces instead of hardcoded default value. Furthermore, it allows adding/removing the implicit routes every time when the corresponding physical nic port is brought up/down. Signed-off-by: Jasvinder Singh --- examples/ip_pipeline/app.h | 137 +++++++++++++++++++++ examples/ip_pipeline/pipeline/pipeline_common_fe.c | 88 +++++++++++++ examples/ip_pipeline/pipeline/pipeline_common_fe.h | 5 + examples/ip_pipeline/pipeline/pipeline_routing.c | 62 +++++++++- examples/ip_pipeline/pipeline/pipeline_routing.h | 7 ++ .../ip_pipeline/pipeline/pipeline_routing_be.c | 37 ++++-- .../ip_pipeline/pipeline/pipeline_routing_be.h | 15 +++ 7 files changed, 341 insertions(+), 10 deletions(-) diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h index 55a9841..803e42e 100644 --- a/examples/ip_pipeline/app.h +++ b/examples/ip_pipeline/app.h @@ -665,6 +665,40 @@ app_swq_get_readers(struct app_params *app, struct app_pktq_swq_params *swq) return n_readers; } +static inline struct app_pipeline_params * +app_swq_get_reader(struct app_params *app, struct app_pktq_swq_params *swq, + uint32_t *pktq_in_id) +{ + struct app_pipeline_params *reader; + uint32_t pos = swq - app->swq_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_readers = 0, id, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); + uint32_t j; + + for (j = 0; j < n_pktq_in; j++) { + struct app_pktq_in_params *pktq = &p->pktq_in[j]; + + if ((pktq->type == APP_PKTQ_IN_SWQ) && + (pktq->id == pos)) { + n_readers++; + reader = p; + id = j; + } + } + } + + if (n_readers != 1) + return NULL; + + *pktq_in_id = id; + return reader; +} + static inline uint32_t app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm) { @@ -690,6 +724,40 @@ app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm) return n_readers; } +static inline struct app_pipeline_params * +app_tm_get_reader(struct app_params *app, struct app_pktq_tm_params *tm, + uint32_t *pktq_in_id) +{ + struct app_pipeline_params *reader; + uint32_t pos = tm - app->tm_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_readers = 0, id, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); + uint32_t j; + + for (j = 0; j < n_pktq_in; j++) { + struct app_pktq_in_params *pktq = &p->pktq_in[j]; + + if ((pktq->type == APP_PKTQ_IN_TM) && + (pktq->id == pos)) { + n_readers++; + reader = p; + id = j; + } + } + } + + if (n_readers != 1) + return NULL; + + *pktq_in_id = id; + return reader; +} + static inline uint32_t app_source_get_readers(struct app_params *app, struct app_pktq_source_params *source) @@ -789,6 +857,41 @@ app_swq_get_writers(struct app_params *app, struct app_pktq_swq_params *swq) return n_writers; } +static inline struct app_pipeline_params * +app_swq_get_writer(struct app_params *app, struct app_pktq_swq_params *swq, + uint32_t *pktq_out_id) +{ + struct app_pipeline_params *writer; + uint32_t pos = swq - app->swq_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_writers = 0, id, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, + RTE_DIM(p->pktq_out)); + uint32_t j; + + for (j = 0; j < n_pktq_out; j++) { + struct app_pktq_out_params *pktq = &p->pktq_out[j]; + + if ((pktq->type == APP_PKTQ_OUT_SWQ) && + (pktq->id == pos)) { + n_writers++; + writer = p; + id = j; + } + } + } + + if (n_writers != 1) + return NULL; + + *pktq_out_id = id; + return writer; +} + static inline uint32_t app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm) { @@ -815,6 +918,40 @@ app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm) return n_writers; } +static inline struct app_pipeline_params * +app_tm_get_writer(struct app_params *app, struct app_pktq_tm_params *tm, + uint32_t *pktq_out_id) +{ + struct app_pipeline_params *writer; + uint32_t pos = tm - app->tm_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_writers = 0, id, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, + RTE_DIM(p->pktq_out)); + uint32_t j; + + for (j = 0; j < n_pktq_out; j++) { + struct app_pktq_out_params *pktq = &p->pktq_out[j]; + + if ((pktq->type == APP_PKTQ_OUT_TM) && + (pktq->id == pos)) + n_writers++; + writer = p; + id = j; + } + } + + if (n_writers != 1) + return NULL; + + *pktq_out_id = id; + return writer; +} + static inline uint32_t app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink) { diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c index a691d42..e29d9a1 100644 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c +++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c @@ -49,6 +49,94 @@ #include "pipeline_common_fe.h" +struct app_link_params * +app_pipeline_track_pktq_out_to_link(struct app_params *app, + uint32_t pipeline_id, + uint32_t pktq_out_id) +{ + struct app_pipeline_params *p; + + /* Check input arguments */ + if (app == NULL) + return NULL; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); + if (p == NULL) + return NULL; + + for ( ; ; ) { + struct app_pktq_out_params *pktq_out = + &p->pktq_out[pktq_out_id]; + + switch (pktq_out->type) { + case APP_PKTQ_OUT_HWQ: + { + struct app_pktq_hwq_out_params *hwq_out; + + hwq_out = &app->hwq_out_params[pktq_out->id]; + + return app_get_link_for_txq(app, hwq_out); + } + + case APP_PKTQ_OUT_SWQ: + { + struct app_pipeline_data *pdata; + struct app_pktq_swq_params *swq; + uint32_t pktq_in_id; + int status; + + swq = &app->swq_params[pktq_out->id]; + p = app_swq_get_reader(app, swq, &pktq_in_id); + if (p == NULL) + return NULL; + + pipeline_id = p - app->pipeline_params; + pdata = &app->pipeline_data[pipeline_id]; + if (pdata->ptype->be_ops->f_track == NULL) + return NULL; + + status = pdata->ptype->be_ops->f_track(pdata->be, + pktq_in_id, + &pktq_out_id); + if (status) + return NULL; + + break; + } + + case APP_PKTQ_OUT_TM: + { + struct app_pipeline_data *pdata; + struct app_pktq_tm_params *tm; + uint32_t pktq_in_id; + int status; + + tm = &app->tm_params[pktq_out->id]; + p = app_tm_get_reader(app, tm, &pktq_in_id); + if (p == NULL) + return NULL; + + pipeline_id = p - app->pipeline_params; + pdata = &app->pipeline_data[pipeline_id]; + if (pdata->ptype->be_ops->f_track == NULL) + return NULL; + + status = pdata->ptype->be_ops->f_track(pdata->be, + pktq_in_id, + &pktq_out_id); + if (status) + return NULL; + + break; + } + + case APP_PKTQ_OUT_SINK: + default: + return NULL; + } + } +} + int app_pipeline_ping(struct app_params *app, uint32_t pipeline_id) diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.h b/examples/ip_pipeline/pipeline/pipeline_common_fe.h index cfad963..7fa6ea9 100644 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.h +++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.h @@ -182,6 +182,11 @@ app_msg_send_recv(struct app_params *app, return msg_recv; } +struct app_link_params * +app_pipeline_track_pktq_out_to_link(struct app_params *app, + uint32_t pipeline_id, + uint32_t pktq_out_id); + int app_pipeline_ping(struct app_params *app, uint32_t pipeline_id); diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c index eab89f2..d890cc8 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing.c +++ b/examples/ip_pipeline/pipeline/pipeline_routing.c @@ -81,10 +81,11 @@ struct pipeline_routing { static void * pipeline_routing_init(struct pipeline_params *params, - __rte_unused void *arg) + void *arg) { + struct app_params *app = (struct app_params *) arg; struct pipeline_routing *p; - uint32_t size; + uint32_t pipeline_id, size; /* Check input arguments */ if ((params == NULL) || @@ -108,6 +109,9 @@ pipeline_routing_init(struct pipeline_params *params, TAILQ_INIT(&p->arp_entries); p->n_arp_entries = 0; + APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id); + app_pipeline_routing_set_macaddr(app, pipeline_id); + return p; } @@ -853,6 +857,60 @@ 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 pipeline_routing *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 -1; + + p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing); + 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_ports_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; +} + static int parse_labels(char *string, uint32_t *labels, uint32_t *n_labels) { diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.h b/examples/ip_pipeline/pipeline/pipeline_routing.h index fa41642..0197449 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing.h +++ b/examples/ip_pipeline/pipeline/pipeline_routing.h @@ -86,6 +86,13 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app, uint32_t pipeline_id); /* + * SETTINGS + */ +int +app_pipeline_routing_set_macaddr(struct app_params *app, + uint32_t pipeline_id); + +/* * Pipeline type */ extern struct pipeline_type pipeline_routing; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c index bc5bf7a..d22a465 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c @@ -65,8 +65,6 @@ ((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32)) -#define MAC_SRC_DEFAULT 0x112233445566ULL - #ifndef PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s #define PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s 256 #endif @@ -74,6 +72,7 @@ struct pipeline_routing { struct pipeline p; struct pipeline_routing_params params; + uint64_t macaddr[PIPELINE_MAX_PORT_OUT]; pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS]; } __rte_cache_aligned; @@ -132,6 +131,10 @@ static void * pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg); +static void * +pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, + void *msg); + static pipeline_msg_req_handler custom_handlers[] = { [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] = pipeline_routing_msg_req_route_add_handler, @@ -149,6 +152,8 @@ static pipeline_msg_req_handler custom_handlers[] = { pipeline_routing_msg_req_arp_add_default_handler, [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] = pipeline_routing_msg_req_arp_del_default_handler, + [PIPELINE_ROUTING_MSG_REQ_SET_MACADDR] = + pipeline_routing_msg_req_set_macaddr_handler, }; /* @@ -1534,7 +1539,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether - ARP off */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) && (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t macaddr_dst; uint64_t ethertype = ETHER_TYPE_IPv4; @@ -1556,7 +1561,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether - ARP on */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) && p_rt->params.n_arp_entries) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t ethertype = ETHER_TYPE_IPv4; entry_arp1.slab[0] = rte_bswap64((macaddr_src << 16) | @@ -1571,7 +1576,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether QinQ - ARP off */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t macaddr_dst; uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4; uint64_t ethertype_vlan = 0x8100; @@ -1603,7 +1608,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether QinQ - ARP on */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && p_rt->params.n_arp_entries) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4; uint64_t ethertype_vlan = 0x8100; uint64_t ethertype_qinq = 0x9100; @@ -1628,7 +1633,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether MPLS - ARP off */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t macaddr_dst; uint64_t ethertype_mpls = 0x8847; @@ -1714,7 +1719,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether MPLS - ARP on */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && p_rt->params.n_arp_entries) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t ethertype_mpls = 0x8847; uint64_t label0 = req->data.l2.mpls.labels[0]; @@ -1961,6 +1966,22 @@ pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg) return rsp; } +void * +pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, void *msg) +{ + struct pipeline_routing *p_rt = (struct pipeline_routing *) p; + struct pipeline_routing_set_macaddr_msg_req *req = msg; + struct pipeline_routing_set_macaddr_msg_rsp *rsp = msg; + uint32_t port_id; + + for (port_id = 0; port_id < p->n_ports_out; port_id++) + p_rt->macaddr[port_id] = req->macaddr[port_id]; + + rsp->status = 0; + + return rsp; +} + struct pipeline_be_ops pipeline_routing_be_ops = { .f_init = pipeline_routing_init, .f_free = pipeline_routing_free, diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.h b/examples/ip_pipeline/pipeline/pipeline_routing_be.h index ec767b2..822995b 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.h +++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.h @@ -160,6 +160,7 @@ enum pipeline_routing_msg_req_type { PIPELINE_ROUTING_MSG_REQ_ARP_DEL, PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT, PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT, + PIPELINE_ROUTING_MSG_REQ_SET_MACADDR, PIPELINE_ROUTING_MSG_REQS }; @@ -291,6 +292,20 @@ struct pipeline_routing_arp_delete_default_msg_rsp { int status; }; +/* + * MSG SET MACADDR + */ +struct pipeline_routing_set_macaddr_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_routing_msg_req_type subtype; + + uint64_t macaddr[PIPELINE_MAX_PORT_OUT]; +}; + +struct pipeline_routing_set_macaddr_msg_rsp { + int status; +}; + extern struct pipeline_be_ops pipeline_routing_be_ops; #endif -- 2.5.5