Skip to content

Commit cb555c1

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 5b16bb6 commit cb555c1

File tree

5 files changed

+73
-24
lines changed

5 files changed

+73
-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, cos_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))
@@ -177,7 +177,7 @@ parse_front_pkt(struct gk_co *this_co,
177177
* IPv6: 14 + 8 + 40 = 62
178178
*/
179179
rte_prefetch0(rte_pktmbuf_mtod_offset(pkt, void *, 0));
180-
yield_next(this_co);
180+
gk_yield_next(this_co);
181181

182182
ret = extract_packet_info(pkt, packet);
183183
if (ret < 0) {
@@ -349,6 +349,10 @@ gk_process_request(struct gk_co *this_co, struct flow_entry *fe,
349349

350350
/* The assigned priority is @priority. */
351351

352+
/* Prepare packet for transmission. */
353+
if (likely(rte_mbuf_prefetch_part2_non_temporal(pkt)))
354+
gk_yield_next(this_co);
355+
352356
/* Encapsulate the packet as a request. */
353357
ret = encapsulate(pkt, priority, back, &fib->u.grantor.gt_addr);
354358
if (ret < 0)
@@ -421,6 +425,10 @@ gk_process_granted(struct gk_co *this_co, struct flow_entry *fe,
421425
priority = PRIORITY_RENEW_CAP;
422426
}
423427

428+
/* Prepare packet for transmission. */
429+
if (likely(rte_mbuf_prefetch_part2_non_temporal(pkt)))
430+
gk_yield_next(this_co);
431+
424432
/*
425433
* Encapsulate packet as a granted packet,
426434
* mark it as a capability renewal request if @renew_cap is true,
@@ -487,7 +495,6 @@ gk_process_bpf(struct gk_co *this_co, struct flow_entry *fe,
487495
{
488496
struct rte_mbuf *pkt = packet->pkt;
489497
struct gk_co_work *work = this_co->work;
490-
struct gk_config *gk_conf = work->gk_conf;
491498
struct gk_measurement_metrics *stats;
492499
uint64_t bpf_ret;
493500
int program_index, rc;
@@ -497,7 +504,7 @@ gk_process_bpf(struct gk_co *this_co, struct flow_entry *fe,
497504
goto expired;
498505

499506
program_index = fe->program_index;
500-
rc = gk_bpf_decide_pkt(gk_conf, program_index, fe, packet, now,
507+
rc = gk_bpf_decide_pkt(this_co, program_index, fe, packet, now,
501508
&bpf_ret);
502509
if (unlikely(rc != 0)) {
503510
GK_LOG(WARNING,
@@ -517,7 +524,7 @@ gk_process_bpf(struct gk_co *this_co, struct flow_entry *fe,
517524
* packet header space.
518525
*/
519526
if (pkt_copy_cached_eth_header(pkt, eth_cache,
520-
gk_conf->net->back.l2_len_out))
527+
work->gk_conf->net->back.l2_len_out))
521528
goto drop_pkt;
522529

523530
stats->pkts_num_granted++;
@@ -996,14 +1003,14 @@ gk_co_process_front_pkt_final(struct gk_co *this_co,
9961003
/* Look up flow entry. */
9971004
rte_hash_prefetch_buckets_non_temporal(
9981005
work->instance->ip_flow_hash_table, ip_flow_hash_val);
999-
yield_next(this_co);
1006+
gk_yield_next(this_co);
10001007
ret = rte_hash_lookup_with_hash(work->instance->ip_flow_hash_table,
10011008
&packet->flow, ip_flow_hash_val);
10021009
if (ret >= 0) {
10031010
fe = &work->instance->ip_flow_entry_table[ret];
10041011
/* TODO Break this prefetch into part1 and part2. */
10051012
prefetch_flow_entry(fe);
1006-
yield_next(this_co);
1013+
gk_yield_next(this_co);
10071014
process_flow_entry(this_co, fe, packet);
10081015
set_leftover_fe(leftover, fe);
10091016
return;
@@ -1079,7 +1086,7 @@ gk_co_scan_flow_table_final(struct gk_co *this_co,
10791086

10801087
rte_hash_prefetch_buckets_non_temporal(instance->ip_flow_hash_table,
10811088
task->task_hash);
1082-
yield_next(this_co);
1089+
gk_yield_next(this_co);
10831090

10841091
gk_del_flow_entry_from_hash(instance->ip_flow_hash_table, fe);
10851092
if (leftover->fe == fe)
@@ -1136,7 +1143,7 @@ gk_co_scan_flow_table(struct gk_co *this_co,
11361143
* check if it's expired.
11371144
*/
11381145
rte_prefetch_non_temporal(fe);
1139-
yield_next(this_co);
1146+
gk_yield_next(this_co);
11401147

11411148
if (!fe->in_use || !is_flow_expired(fe, rte_rdtsc()))
11421149
return;

gk/co.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,7 @@ void
217217
gk_co_process_front_pkt_software_rss(struct gk_co *this_co,
218218
struct gk_co_task *task, struct gk_co_leftover *leftover);
219219

220+
void
221+
gk_yield_next(struct gk_co *this_co);
222+
220223
#endif /* _GATEKEEPER_GK_CO_H_ */

include/gatekeeper_main.h

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

2222
#include <stdint.h>
23+
#include <stdbool.h>
24+
25+
#include <rte_mbuf.h>
26+
#include <rte_prefetch.h>
2327

2428
#ifdef RTE_MACHINE_CPUFLAG_SSE4_2
2529
#include <rte_hash_crc.h>
@@ -52,4 +56,28 @@ extern FILE *log_file;
5256
char *rte_strdup(const char *type, const char *s);
5357
int gatekeeper_log_init(void);
5458

59+
/* XXX #52 This should be part of DPDK. */
60+
/**
61+
* Prefetch the second part of the mbuf
62+
*
63+
* The next 64 bytes of the mbuf corresponds to fields that are used in the
64+
* transmit path. If the cache line of the architecture is higher than 64B,
65+
* this function does nothing as it is expected that the full mbuf is
66+
* already in cache.
67+
*
68+
* @param m
69+
* The pointer to the mbuf.
70+
*/
71+
static inline bool
72+
rte_mbuf_prefetch_part2_non_temporal(struct rte_mbuf *m)
73+
{
74+
#if RTE_CACHE_LINE_SIZE == 64
75+
rte_prefetch_non_temporal(&m->cacheline1);
76+
return true;
77+
#else
78+
RTE_SET_USED(m);
79+
return false;
80+
#endif
81+
}
82+
5583
#endif /* _GATEKEEPER_MAIN_H_ */

0 commit comments

Comments
 (0)