Merge "docs: Update install and release docs for DPDK migration support"
[samplevnf.git] / VNFs / DPPD-PROX / handle_lb_pos.c
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <rte_mbuf.h>
18 #include <rte_ip.h>
19 #include <rte_udp.h>
20 #include <rte_hash_crc.h>
21
22 #include "log.h"
23 #include "task_base.h"
24 #include "defines.h"
25 #include "tx_pkt.h"
26 #include "task_init.h"
27 #include "quit.h"
28 #include "mpls.h"
29 #include "etypes.h"
30 #include "gre.h"
31 #include "prefetch.h"
32
33 struct task_lb_pos {
34         struct task_base base;
35         uint16_t         byte_offset;
36         uint8_t          n_workers;
37 };
38
39 static void init_task_lb_pos(struct task_base *tbase, struct task_args *targ)
40 {
41         struct task_lb_pos *task = (struct task_lb_pos *)tbase;
42
43         task->n_workers = targ->nb_worker_threads;
44         task->byte_offset = targ->byte_offset;
45 }
46
47 static int handle_lb_pos_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
48 {
49         struct task_lb_pos *task = (struct task_lb_pos *)tbase;
50         uint8_t out[MAX_PKT_BURST];
51         uint16_t offset = task->byte_offset;
52         uint16_t j;
53
54         prefetch_first(mbufs, n_pkts);
55
56         for (j = 0; j + PREFETCH_OFFSET < n_pkts; ++j) {
57 #ifdef PROX_PREFETCH_OFFSET
58                 PREFETCH0(mbufs[j + PREFETCH_OFFSET]);
59                 PREFETCH0(rte_pktmbuf_mtod(mbufs[j + PREFETCH_OFFSET - 1], void *));
60 #endif
61                 uint8_t* pkt = rte_pktmbuf_mtod(mbufs[j], uint8_t*);
62                 out[j] = pkt[offset] % task->n_workers;
63         }
64 #ifdef PROX_PREFETCH_OFFSET
65         PREFETCH0(rte_pktmbuf_mtod(mbufs[n_pkts - 1], void *));
66         for (; j < n_pkts; ++j) {
67                 uint8_t* pkt = rte_pktmbuf_mtod(mbufs[j], uint8_t*);
68                 out[j] = pkt[offset] % task->n_workers;
69         }
70 #endif
71
72         return task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
73 }
74
75 union ip_port {
76         struct {
77                 uint32_t ip;
78                 uint32_t port;
79         };
80         uint64_t ip_port;
81 };
82
83 struct pkt_ether_ipv4_udp {
84         struct ether_hdr ether;
85         struct ipv4_hdr  ipv4;
86         struct udp_hdr   udp;
87 } __attribute__((unused));
88
89 static uint8_t handle_lb_ip_port(struct task_lb_pos *task, struct rte_mbuf *mbuf)
90 {
91         union ip_port ip_port;
92         uint8_t ret;
93
94         struct pkt_ether_ipv4_udp *pkt = rte_pktmbuf_mtod(mbuf, void *);
95
96         if (pkt->ether.ether_type != ETYPE_IPv4 ||
97             (pkt->ipv4.next_proto_id != IPPROTO_TCP &&
98              pkt->ipv4.next_proto_id != IPPROTO_UDP))
99                 return OUT_DISCARD;
100
101         if (task->byte_offset == 0) {
102                 ip_port.ip   = pkt->ipv4.src_addr;
103                 ip_port.port = pkt->udp.src_port;
104         }
105         else {
106                 ip_port.ip   = pkt->ipv4.dst_addr;
107                 ip_port.port = pkt->udp.dst_port;
108         }
109
110         return rte_hash_crc(&ip_port.ip_port, sizeof(ip_port.ip_port), 0) % task->n_workers;
111 }
112
113 static int handle_lb_ip_port_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
114 {
115         struct task_lb_pos *task = (struct task_lb_pos *)tbase;
116         uint8_t out[MAX_PKT_BURST];
117         uint16_t j;
118         uint64_t ip_port = 0;
119
120         for (j = 0; j + PREFETCH_OFFSET < n_pkts; ++j) {
121 #ifdef PROX_PREFETCH_OFFSET
122                 PREFETCH0(mbufs[j + PREFETCH_OFFSET]);
123                 PREFETCH0(rte_pktmbuf_mtod(mbufs[j + PREFETCH_OFFSET - 1], void *));
124 #endif
125                 out[j] = handle_lb_ip_port(task, mbufs[j]);
126         }
127 #ifdef PROX_PREFETCH_OFFSET
128         PREFETCH0(rte_pktmbuf_mtod(mbufs[n_pkts - 1], void *));
129         for (; j < n_pkts; ++j) {
130                 out[j] = handle_lb_ip_port(task, mbufs[j]);
131         }
132 #endif
133
134         return task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
135 }
136
137 static struct task_init task_init_lb_pos = {
138         .mode_str = "lbpos",
139         .init = init_task_lb_pos,
140         .handle = handle_lb_pos_bulk,
141         .size = sizeof(struct task_lb_pos)
142 };
143
144 static struct task_init task_init_lb_pos2 = {
145         .mode_str = "lbpos",
146         .sub_mode_str = "ip_port",
147         .init = init_task_lb_pos,
148         .handle = handle_lb_ip_port_bulk,
149         .size = sizeof(struct task_lb_pos)
150 };
151
152 __attribute__((constructor)) static void reg_task_lb_pos(void)
153 {
154         reg_task(&task_init_lb_pos);
155         reg_task(&task_init_lb_pos2);
156 }