Skip to content

Commit 814023b

Browse files
committed
gk: prefetch the transmission fields of packets
This patch prefetches the transmission fields of a packet when it is ready to be prepared for transmission.
1 parent d70bf69 commit 814023b

File tree

5 files changed

+70
-24
lines changed

5 files changed

+70
-24
lines changed

gk/bpf.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,13 @@ static const struct rte_bpf_xsym flow_handler_init_xsym[] = {
106106
};
107107

108108
struct gk_bpf_pkt_frame {
109-
uint64_t password;
110-
struct flow_entry *fe;
111-
struct ipacket *packet;
112-
struct gk_config *gk_conf;
113-
bool ready_to_tx;
114-
struct gk_bpf_pkt_ctx ctx;
109+
uint64_t password;
110+
struct flow_entry *fe;
111+
struct ipacket *packet;
112+
struct gk_co *this_co;
113+
bool pkt_part2_prefetched;
114+
bool ready_to_tx;
115+
struct gk_bpf_pkt_ctx ctx;
115116
};
116117

117118
static const uint64_t pkt_password = 0xa2e329ba8b15af05;
@@ -199,6 +200,7 @@ gk_bpf_prep_for_tx(struct gk_bpf_pkt_ctx *ctx, int priority,
199200
int direct_if_possible)
200201
{
201202
int ret;
203+
struct gatekeeper_if *back;
202204
struct gk_bpf_pkt_frame *frame = pkt_ctx_to_frame(ctx);
203205
if (unlikely(frame == NULL))
204206
return -EINVAL;
@@ -208,11 +210,18 @@ gk_bpf_prep_for_tx(struct gk_bpf_pkt_ctx *ctx, int priority,
208210
if (unlikely(priority < 0 || priority > PRIORITY_MAX))
209211
return -EINVAL;
210212

213+
/* Prepare packet for transmission if needed. */
214+
if (likely(!frame->pkt_part2_prefetched)) {
215+
frame->pkt_part2_prefetched = true;
216+
if (likely(rte_mbuf_prefetch_part2_non_temporal(
217+
frame->packet->pkt)))
218+
gk_yield_next(frame->this_co);
219+
}
220+
221+
back = &frame->this_co->work->gk_conf->net->back;
211222
ret = (direct_if_possible != 0 && priority == PRIORITY_GRANTED)
212-
? update_pkt_priority(frame->packet, priority,
213-
&frame->gk_conf->net->back)
214-
: encapsulate(frame->packet->pkt, priority,
215-
&frame->gk_conf->net->back,
223+
? update_pkt_priority(frame->packet, priority, back)
224+
: encapsulate(frame->packet->pkt, priority, back,
216225
&frame->fe->grantor_fib->u.grantor.gt_addr);
217226

218227
frame->ready_to_tx = ret == 0;
@@ -486,23 +495,24 @@ parse_packet_further(struct ipacket *packet, struct gk_bpf_pkt_ctx *ctx)
486495
}
487496

488497
int
489-
gk_bpf_decide_pkt(struct gk_config *gk_conf, uint8_t program_index,
498+
gk_bpf_decide_pkt(struct gk_co *this_co, uint8_t program_index,
490499
struct flow_entry *fe, struct ipacket *packet, uint64_t now,
491500
uint64_t *p_bpf_ret)
492501
{
493502
struct gk_bpf_pkt_frame frame = {
494503
.password = pkt_password,
495504
.fe = fe,
496505
.packet = packet,
497-
.gk_conf = gk_conf,
506+
.this_co = this_co,
507+
.pkt_part2_prefetched = false,
498508
.ready_to_tx = false,
499509
.ctx = {
500510
.now = now,
501511
.expire_at = fe->u.bpf.expire_at,
502512
},
503513
};
504514
const struct gk_bpf_flow_handler *handler =
505-
&gk_conf->flow_handlers[program_index];
515+
&this_co->work->gk_conf->flow_handlers[program_index];
506516

507517
if (unlikely(handler->f_pkt == NULL)) {
508518
GK_LOG(WARNING,

gk/bpf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define _GATEKEEPER_GK_BPF_H_
2121

2222
#include "gatekeeper_gk.h"
23+
#include "co.h"
2324

2425
/*
2526
* Load the BPF program that handles flows into @gk_conf at
@@ -32,7 +33,7 @@
3233
int gk_load_bpf_flow_handler(struct gk_config *gk_conf, unsigned int index,
3334
const char *filename, int jit);
3435

35-
int gk_bpf_decide_pkt(struct gk_config *gk_conf, uint8_t program_index,
36+
int gk_bpf_decide_pkt(struct gk_co *this_co, uint8_t program_index,
3637
struct flow_entry *fe, struct ipacket *packet, uint64_t now,
3738
uint64_t *p_bpf_ret);
3839

gk/co.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ get_next_co(struct gk_co *this_co)
4040
return list_next_entry(this_co, co_list);
4141
}
4242

43-
static void
44-
yield_next(struct gk_co *this_co)
43+
void
44+
gk_yield_next(struct gk_co *this_co)
4545
{
4646
struct gk_co *next_co = get_next_co(this_co);
4747
if (unlikely(this_co == next_co))
@@ -156,7 +156,7 @@ parse_front_pkt(struct gk_co *this_co,
156156

157157
/* TODO Does this prefetch improve performance?
158158
rte_mbuf_prefetch_part1_non_temporal(pkt);
159-
yield_next(this_co);
159+
gk_yield_next(this_co);
160160
*/
161161
/*
162162
* This prefetch is enough to load Ethernet header (14 bytes),
@@ -167,7 +167,7 @@ parse_front_pkt(struct gk_co *this_co,
167167
* IPv6: 14 + 8 + 40 = 62
168168
*/
169169
rte_prefetch_non_temporal(rte_pktmbuf_mtod_offset(pkt, void *, 0));
170-
yield_next(this_co);
170+
gk_yield_next(this_co);
171171

172172
ret = extract_packet_info(pkt, packet);
173173
if (ret < 0) {
@@ -335,6 +335,10 @@ gk_process_request(struct gk_co *this_co, struct flow_entry *fe,
335335

336336
/* The assigned priority is @priority. */
337337

338+
/* Prepare packet for transmission. */
339+
if (likely(rte_mbuf_prefetch_part2_non_temporal(pkt)))
340+
gk_yield_next(this_co);
341+
338342
/* Encapsulate the packet as a request. */
339343
ret = encapsulate(pkt, priority, back, &fib->u.grantor.gt_addr);
340344
if (ret < 0)
@@ -398,6 +402,10 @@ gk_process_granted(struct gk_co *this_co, struct flow_entry *fe,
398402
priority = PRIORITY_RENEW_CAP;
399403
}
400404

405+
/* Prepare packet for transmission. */
406+
if (likely(rte_mbuf_prefetch_part2_non_temporal(pkt)))
407+
gk_yield_next(this_co);
408+
401409
/*
402410
* Encapsulate packet as a granted packet,
403411
* mark it as a capability renewal request if @renew_cap is true,
@@ -447,7 +455,6 @@ gk_process_bpf(struct gk_co *this_co, struct flow_entry *fe,
447455
{
448456
struct rte_mbuf *pkt = packet->pkt;
449457
struct gk_co_work *work = this_co->work;
450-
struct gk_config *gk_conf = work->gk_conf;
451458
struct gk_measurement_metrics *stats;
452459
uint64_t bpf_ret;
453460
int program_index, rc;
@@ -457,7 +464,7 @@ gk_process_bpf(struct gk_co *this_co, struct flow_entry *fe,
457464
goto expired;
458465

459466
program_index = fe->program_index;
460-
rc = gk_bpf_decide_pkt(gk_conf, program_index, fe, packet, now,
467+
rc = gk_bpf_decide_pkt(this_co, program_index, fe, packet, now,
461468
&bpf_ret);
462469
if (unlikely(rc != 0)) {
463470
GK_LOG(WARNING,
@@ -477,7 +484,7 @@ gk_process_bpf(struct gk_co *this_co, struct flow_entry *fe,
477484
* packet header space.
478485
*/
479486
if (pkt_copy_cached_eth_header(pkt, eth_cache,
480-
gk_conf->net->back.l2_len_out))
487+
work->gk_conf->net->back.l2_len_out))
481488
goto drop_pkt;
482489

483490
stats->pkts_num_granted++;
@@ -890,7 +897,7 @@ static void
890897
prefetch_and_yield(void *addr, void *this_co)
891898
{
892899
rte_prefetch_non_temporal(addr);
893-
yield_next(this_co);
900+
gk_yield_next(this_co);
894901
}
895902

896903
static void
@@ -922,7 +929,7 @@ gk_co_process_front_pkt_final(struct gk_co *this_co, struct gk_co_task *task)
922929
fe = &work->instance->ip_flow_entry_table[ret];
923930
/* TODO Break this prefetch into part1 and part2. */
924931
prefetch_flow_entry(fe);
925-
yield_next(this_co);
932+
gk_yield_next(this_co);
926933
process_flow_entry(this_co, fe, packet);
927934
save_fe_leftover(work, fe);
928935
return;
@@ -1039,7 +1046,7 @@ gk_co_scan_flow_table(struct gk_co *this_co, struct gk_co_task *task)
10391046
* check if it's expired.
10401047
*/
10411048
rte_prefetch_non_temporal(fe);
1042-
yield_next(this_co);
1049+
gk_yield_next(this_co);
10431050

10441051
if (!fe->in_use || !is_flow_expired(fe, rte_rdtsc()))
10451052
return;

gk/co.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,7 @@ void
284284
gk_co_process_front_pkt_software_rss(struct gk_co *this_co,
285285
struct gk_co_task *task);
286286

287+
void
288+
gk_yield_next(struct gk_co *this_co);
289+
287290
#endif /* _GATEKEEPER_GK_CO_H_ */

include/gatekeeper_main.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define _GATEKEEPER_MAIN_H_
2121

2222
#include <stdint.h>
23+
#include <stdbool.h>
2324

2425
#include <rte_mbuf.h>
2526
#include <rte_prefetch.h>
@@ -72,4 +73,28 @@ rte_mbuf_prefetch_part1_non_temporal(struct rte_mbuf *m)
7273
rte_prefetch_non_temporal(&m->cacheline0);
7374
}
7475

76+
/* XXX #52 This should be part of DPDK. */
77+
/**
78+
* Prefetch the second part of the mbuf
79+
*
80+
* The next 64 bytes of the mbuf corresponds to fields that are used in the
81+
* transmit path. If the cache line of the architecture is higher than 64B,
82+
* this function does nothing as it is expected that the full mbuf is
83+
* already in cache.
84+
*
85+
* @param m
86+
* The pointer to the mbuf.
87+
*/
88+
static inline bool
89+
rte_mbuf_prefetch_part2_non_temporal(struct rte_mbuf *m)
90+
{
91+
#if RTE_CACHE_LINE_SIZE == 64
92+
rte_prefetch_non_temporal(&m->cacheline1);
93+
return true;
94+
#else
95+
RTE_SET_USED(m);
96+
return false;
97+
#endif
98+
}
99+
75100
#endif /* _GATEKEEPER_MAIN_H_ */

0 commit comments

Comments
 (0)