Skip to content

Commit 976f4dc

Browse files
authored
Use a repr(C) flow ID to reduce repeated per-packet conversion costs (#475)
This PR replaces `InnerFlowId` with an equivalent C-ABI friendly struct, from which we can directly pass pointers to our dtrace SDTs. This has proven necessary as we are reconstructing this many times per packet in both the UFT slowpath and fastpath. Additionally, this makes partial progress on #460 by using the new `DError` machinery whenever a packet is `Ok(Modified | Hairpin | Bypass)` to elide string formats on layer/port processing. The `Err(_)` and `Ok(Drop{ .. })` cases remain open work, but are less common and in those cases we have at least removed a superfluous realloc + memcpy on the formatted string. From local IGB<->IGB results and comparing 4e2ad7e against master in CI, this seems like O(10%) reduction in packet latency *spent in XDE*, with comparable bandwidth increase. Closes #462.
1 parent 8667a30 commit 976f4dc

File tree

20 files changed

+348
-273
lines changed

20 files changed

+348
-273
lines changed

crates/opte-api/src/ip.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ impl FromStr for IpAddr {
380380
PartialOrd,
381381
Serialize,
382382
)]
383+
#[repr(C)]
383384
pub struct Ipv4Addr {
384385
inner: [u8; 4],
385386
}
@@ -554,6 +555,7 @@ impl Deref for Ipv4Addr {
554555
Serialize,
555556
Deserialize,
556557
)]
558+
#[repr(C)]
557559
pub struct Ipv6Addr {
558560
inner: [u8; 16],
559561
}

crates/opte-api/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub use ulp::*;
4747
///
4848
/// We rely on CI and the check-api-version.sh script to verify that
4949
/// this number is incremented anytime the oxide-api code changes.
50-
pub const API_VERSION: u64 = 29;
50+
pub const API_VERSION: u64 = 30;
5151

5252
/// Major version of the OPTE package.
5353
pub const MAJOR_VERSION: u64 = 0;

dtrace/common.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,32 @@
99
#define FLOW_FMT(svar, fvar) \
1010
this->src_ip = (ipaddr_t *)alloca(4); \
1111
this->dst_ip = (ipaddr_t *)alloca(4); \
12-
*this->src_ip = fvar->src_ip4; \
13-
*this->dst_ip = fvar->dst_ip4; \
12+
*this->src_ip = fvar->addrs.ip4.src; \
13+
*this->dst_ip = fvar->addrs.ip4.dst; \
1414
svar = protos[fvar->proto]; \
1515
svar = strjoin(svar, ","); \
1616
svar = strjoin(svar, inet_ntoa(this->src_ip)); \
1717
svar = strjoin(svar, ":"); \
18-
svar = strjoin(svar, lltostr(ntohs(fvar->src_port))); \
18+
svar = strjoin(svar, lltostr(fvar->src_port)); \
1919
svar = strjoin(svar, ","); \
2020
svar = strjoin(svar, inet_ntoa(this->dst_ip)); \
2121
svar = strjoin(svar, ":"); \
22-
svar = strjoin(svar, lltostr(ntohs(fvar->dst_port)));
22+
svar = strjoin(svar, lltostr(fvar->dst_port));
2323

2424
#define FLOW_FMT6(svar, fvar) \
2525
this->src_ip6 = (in6_addr_t *)alloca(16); \
2626
this->dst_ip6 = (in6_addr_t *)alloca(16); \
27-
*this->src_ip6 = fvar->src_ip6; \
28-
*this->dst_ip6 = fvar->dst_ip6; \
27+
*this->src_ip6 = fvar->addrs.ip6.src; \
28+
*this->dst_ip6 = fvar->addrs.ip6.dst; \
2929
svar = protos[fvar->proto]; \
3030
svar = strjoin(svar, ",["); \
3131
svar = strjoin(svar, inet_ntoa6(this->src_ip6)); \
3232
svar = strjoin(svar, "]:"); \
33-
svar = strjoin(svar, lltostr(ntohs(fvar->src_port))); \
33+
svar = strjoin(svar, lltostr(fvar->src_port)); \
3434
svar = strjoin(svar, ",["); \
3535
svar = strjoin(svar, inet_ntoa6(this->dst_ip6)); \
3636
svar = strjoin(svar, "]:"); \
37-
svar = strjoin(svar, lltostr(ntohs(fvar->dst_port)));
37+
svar = strjoin(svar, lltostr(fvar->dst_port));
3838

3939
#define ETH_FMT(svar, evar) \
4040
svar = substr(lltostr(evar[0], 16), 2); \
@@ -55,3 +55,6 @@
5555
* 2 = Outbound
5656
*/
5757
#define DIR_STR(dir) ((dir) == 1 ? "IN" : "OUT")
58+
59+
#define EL_DELIMIT "->"
60+
#define EL_FMT "->%s"

dtrace/lib/common.d

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22
#pragma D depends_on provider ip
33

44
typedef struct flow_id_sdt_arg {
5-
int af;
6-
ipaddr_t src_ip4;
7-
ipaddr_t dst_ip4;
8-
in6_addr_t src_ip6;
9-
in6_addr_t dst_ip6;
5+
uint8_t proto;
6+
uint16_t af;
7+
union addrs {
8+
struct {
9+
ipaddr_t src;
10+
ipaddr_t dst;
11+
} ip4;
12+
struct {
13+
in6_addr_t src;
14+
in6_addr_t dst;
15+
} ip6;
16+
} addrs;
1017
uint16_t src_port;
1118
uint16_t dst_port;
12-
uint8_t proto;
1319
} flow_id_sdt_arg_t;
1420

1521
typedef struct rule_match_sdt_arg {
@@ -48,8 +54,8 @@ typedef struct opte_cmd_ioctl {
4854
} opte_cmd_ioctl_t;
4955

5056
typedef struct derror_sdt_arg {
51-
size_t len;
52-
uint8_t truncated;
53-
uint64_t data[2];
54-
char* entry[8];
57+
size_t len;
58+
uint8_t truncated;
59+
uint64_t data[2];
60+
char* entry[8];
5561
} derror_sdt_arg_t;

dtrace/opte-bad-packet.d

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
#include "common.h"
77

88
#define HDR_FMT "%-12s %-3s %-18s %s\n"
9-
#define LINE_FMT "%-12s %-3s 0x%-16p "
10-
#define EL_FMT "->%s"
9+
#define LINE_FMT "%-12s %-3s 0x%-16p %s[%d, %d]\n"
1110

1211
BEGIN {
1312
printf(HDR_FMT, "PORT", "DIR", "MBLK", "MSG+DATA");
@@ -21,13 +20,13 @@ bad-packet {
2120
this->msgs = (derror_sdt_arg_t*) arg3;
2221
this->msg_len = this->msgs->len;
2322
this->data_len = arg4;
23+
this->res = stringof("");
2424

2525
if (num >= 10) {
2626
printf(HDR_FMT, "PORT", "DIR", "MBLK", "MSG+DATA");
2727
num = 0;
2828
}
2929

30-
printf(LINE_FMT, this->port, this->dir, this->mblk);
3130
num++;
3231
}
3332

@@ -36,51 +35,61 @@ bad-packet {
3635
bad-packet
3736
/this->msg_len > 0/
3837
{
39-
printf("%s", stringof(this->msgs->entry[0]));
38+
this->res = strjoin(this->res, stringof(this->msgs->entry[0]));
4039
}
4140

4241
bad-packet
4342
/this->msg_len > 1/
4443
{
45-
printf(EL_FMT, stringof(this->msgs->entry[1]));
44+
this->res = strjoin(this->res, EL_DELIMIT);
45+
this->res = strjoin(this->res, stringof(this->msgs->entry[1]));
4646
}
4747

4848
bad-packet
4949
/this->msg_len > 2/
5050
{
51-
printf(EL_FMT, stringof(this->msgs->entry[2]));
51+
this->res = strjoin(this->res, EL_DELIMIT);
52+
this->res = strjoin(this->res, stringof(this->msgs->entry[2]));
5253
}
5354

5455
bad-packet
5556
/this->msg_len > 3/
5657
{
57-
printf(EL_FMT, stringof(this->msgs->entry[3]));
58+
this->res = strjoin(this->res, EL_DELIMIT);
59+
this->res = strjoin(this->res, stringof(this->msgs->entry[3]));
5860
}
5961

6062
bad-packet
6163
/this->msg_len > 4/
6264
{
63-
printf(EL_FMT, stringof(this->msgs->entry[4]));
65+
this->res = strjoin(this->res, EL_DELIMIT);
66+
this->res = strjoin(this->res, stringof(this->msgs->entry[4]));
6467
}
6568

6669
bad-packet
6770
/this->msg_len > 5/
6871
{
69-
printf(EL_FMT, stringof(this->msgs->entry[5]));
72+
this->res = strjoin(this->res, EL_DELIMIT);
73+
this->res = strjoin(this->res, stringof(this->msgs->entry[5]));
7074
}
7175

7276
bad-packet
7377
/this->msg_len > 6/
7478
{
75-
printf(EL_FMT, stringof(this->msgs->entry[6]));
79+
this->res = strjoin(this->res, EL_DELIMIT);
80+
this->res = strjoin(this->res, stringof(this->msgs->entry[6]));
7681
}
7782

7883
bad-packet
7984
/this->msg_len > 7/
8085
{
81-
printf(EL_FMT, stringof(this->msgs->entry[7]));
86+
this->res = strjoin(this->res, EL_DELIMIT);
87+
this->res = strjoin(this->res, stringof(this->msgs->entry[7]));
8288
}
8389

8490
bad-packet {
85-
printf(" [%d, %d]\n", this->msgs->data[0], this->msgs->data[1]);
91+
printf(LINE_FMT,
92+
this->port, this->dir, this->mblk,
93+
this->res, this->msgs->data[0], this->msgs->data[1]
94+
);
8695
}

dtrace/opte-layer-process.d

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ layer-process-return {
2323
this->layer = stringof(arg2);
2424
this->flow_before = (flow_id_sdt_arg_t *)arg3;
2525
this->flow_after = (flow_id_sdt_arg_t *)arg4;
26-
this->res = stringof(arg5);
26+
this->msgs = (derror_sdt_arg_t*) arg5;
27+
this->msg_len = this->msgs->len;
28+
this->res = stringof("");
2729

2830
if (num >= 10) {
2931
printf(HDR_FMT, "PORT", "LAYER", "DIR", "FLOW BEFORE",
@@ -38,6 +40,19 @@ layer-process-return {
3840
}
3941
}
4042

43+
layer-process-return
44+
/this->msg_len > 0/
45+
{
46+
this->res = strjoin(this->res, stringof(this->msgs->entry[0]));
47+
}
48+
49+
layer-process-return
50+
/this->msg_len > 1/
51+
{
52+
this->res = strjoin(this->res, EL_DELIMIT);
53+
this->res = strjoin(this->res, stringof(this->msgs->entry[1]));
54+
}
55+
4156
layer-process-return /this->af == AF_INET/ {
4257
FLOW_FMT(this->s_before, this->flow_before);
4358
FLOW_FMT(this->s_after, this->flow_after);

dtrace/opte-port-process.d

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ port-process-return {
2424
this->mp = (mblk_t *)arg5;
2525
/* If the result is a hairpin packet, then hp_mp is non-NULL. */
2626
this->hp_mp = (mblk_t *)arg6;
27-
this->res = stringof(arg7);
27+
this->msgs = (derror_sdt_arg_t*) arg7;
28+
this->msg_len = this->msgs->len;
29+
this->res = stringof("");
2830

2931
if (num >= 10) {
3032
printf(HDR_FMT, "NAME", "DIR", "EPOCH", "FLOW BEFORE",
@@ -39,6 +41,19 @@ port-process-return {
3941
}
4042
}
4143

44+
port-process-return
45+
/this->msg_len > 0/
46+
{
47+
this->res = strjoin(this->res, stringof(this->msgs->entry[0]));
48+
}
49+
50+
port-process-return
51+
/this->msg_len > 1/
52+
{
53+
this->res = strjoin(this->res, EL_DELIMIT);
54+
this->res = strjoin(this->res, stringof(this->msgs->entry[1]));
55+
}
56+
4257
port-process-return /this->af == AF_INET/ {
4358
FLOW_FMT(this->s_before, this->flow_before);
4459
FLOW_FMT(this->s_after, this->flow_after);
@@ -55,4 +70,3 @@ port-process-return /this->af == AF_INET6/ {
5570
num++;
5671
}
5772

58-

0 commit comments

Comments
 (0)