summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/handle_lb_pos.c
blob: 3cf465ce1a5b2c120110aa304b18ae6f43a030da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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 {
	prox_rte_ether_hdr ether;
	prox_rte_ipv4_hdr  ipv4;
	prox_rte_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);
}