diff options
Diffstat (limited to 'VNFs/DPPD-PROX/handle_lb_pos.c')
-rw-r--r-- | VNFs/DPPD-PROX/handle_lb_pos.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/handle_lb_pos.c b/VNFs/DPPD-PROX/handle_lb_pos.c new file mode 100644 index 00000000..4324e94d --- /dev/null +++ b/VNFs/DPPD-PROX/handle_lb_pos.c @@ -0,0 +1,156 @@ +/* +// Copyright (c) 2010-2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include <rte_mbuf.h> +#include <rte_ip.h> +#include <rte_udp.h> +#include <rte_hash_crc.h> + +#include "log.h" +#include "task_base.h" +#include "defines.h" +#include "tx_pkt.h" +#include "task_init.h" +#include "quit.h" +#include "mpls.h" +#include "etypes.h" +#include "gre.h" +#include "prefetch.h" + +struct task_lb_pos { + struct task_base base; + uint16_t byte_offset; + uint8_t n_workers; +}; + +static void init_task_lb_pos(struct task_base *tbase, struct task_args *targ) +{ + struct task_lb_pos *task = (struct task_lb_pos *)tbase; + + task->n_workers = targ->nb_worker_threads; + task->byte_offset = targ->byte_offset; +} + +static int handle_lb_pos_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts) +{ + struct task_lb_pos *task = (struct task_lb_pos *)tbase; + uint8_t out[MAX_PKT_BURST]; + uint16_t offset = task->byte_offset; + uint16_t j; + + prefetch_first(mbufs, n_pkts); + + for (j = 0; j + PREFETCH_OFFSET < n_pkts; ++j) { +#ifdef PROX_PREFETCH_OFFSET + PREFETCH0(mbufs[j + PREFETCH_OFFSET]); + PREFETCH0(rte_pktmbuf_mtod(mbufs[j + PREFETCH_OFFSET - 1], void *)); +#endif + uint8_t* pkt = rte_pktmbuf_mtod(mbufs[j], uint8_t*); + out[j] = pkt[offset] % task->n_workers; + } +#ifdef PROX_PREFETCH_OFFSET + PREFETCH0(rte_pktmbuf_mtod(mbufs[n_pkts - 1], void *)); + for (; j < n_pkts; ++j) { + uint8_t* pkt = rte_pktmbuf_mtod(mbufs[j], uint8_t*); + out[j] = pkt[offset] % task->n_workers; + } +#endif + + return task->base.tx_pkt(&task->base, mbufs, n_pkts, out); +} + +union ip_port { + struct { + uint32_t ip; + uint32_t port; + }; + uint64_t ip_port; +}; + +struct pkt_ether_ipv4_udp { + struct ether_hdr ether; + struct ipv4_hdr ipv4; + struct udp_hdr udp; +} __attribute__((unused)); + +static uint8_t handle_lb_ip_port(struct task_lb_pos *task, struct rte_mbuf *mbuf) +{ + union ip_port ip_port; + uint8_t ret; + + struct pkt_ether_ipv4_udp *pkt = rte_pktmbuf_mtod(mbuf, void *); + + if (pkt->ether.ether_type != ETYPE_IPv4 || + (pkt->ipv4.next_proto_id != IPPROTO_TCP && + pkt->ipv4.next_proto_id != IPPROTO_UDP)) + return OUT_DISCARD; + + if (task->byte_offset == 0) { + ip_port.ip = pkt->ipv4.src_addr; + ip_port.port = pkt->udp.src_port; + } + else { + ip_port.ip = pkt->ipv4.dst_addr; + ip_port.port = pkt->udp.dst_port; + } + + return rte_hash_crc(&ip_port.ip_port, sizeof(ip_port.ip_port), 0) % task->n_workers; +} + +static int handle_lb_ip_port_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts) +{ + struct task_lb_pos *task = (struct task_lb_pos *)tbase; + uint8_t out[MAX_PKT_BURST]; + uint16_t j; + uint64_t ip_port = 0; + + for (j = 0; j + PREFETCH_OFFSET < n_pkts; ++j) { +#ifdef PROX_PREFETCH_OFFSET + PREFETCH0(mbufs[j + PREFETCH_OFFSET]); + PREFETCH0(rte_pktmbuf_mtod(mbufs[j + PREFETCH_OFFSET - 1], void *)); +#endif + out[j] = handle_lb_ip_port(task, mbufs[j]); + } +#ifdef PROX_PREFETCH_OFFSET + PREFETCH0(rte_pktmbuf_mtod(mbufs[n_pkts - 1], void *)); + for (; j < n_pkts; ++j) { + out[j] = handle_lb_ip_port(task, mbufs[j]); + } +#endif + + return task->base.tx_pkt(&task->base, mbufs, n_pkts, out); +} + +static struct task_init task_init_lb_pos = { + .mode_str = "lbpos", + .init = init_task_lb_pos, + .handle = handle_lb_pos_bulk, + .size = sizeof(struct task_lb_pos) +}; + +static struct task_init task_init_lb_pos2 = { + .mode_str = "lbpos", + .sub_mode_str = "ip_port", + .init = init_task_lb_pos, + .handle = handle_lb_ip_port_bulk, + .size = sizeof(struct task_lb_pos) +}; + +__attribute__((constructor)) static void reg_task_lb_pos(void) +{ + reg_task(&task_init_lb_pos); + reg_task(&task_init_lb_pos2); +} |