Fix reuseport_kern.c to work under ubuntu 20.04

This commit is contained in:
Tatsuhiro Tsujikawa 2021-08-29 20:56:22 +09:00
parent 7941b559c5
commit e5cb5dca61
1 changed files with 21 additions and 45 deletions

View File

@ -140,7 +140,7 @@ struct bpf_map_def SEC("maps") sk_info = {
}; };
typedef struct quic_hd { typedef struct quic_hd {
__u8 *dcid; const __u8 *dcid;
__u32 dcidlen; __u32 dcidlen;
__u32 dcid_offset; __u32 dcid_offset;
__u8 type; __u8 type;
@ -158,54 +158,33 @@ enum {
NGTCP2_PKT_SHORT = 0x40, NGTCP2_PKT_SHORT = 0x40,
}; };
static inline int parse_quic(quic_hd *qhd, struct sk_reuseport_md *reuse_md) { static inline int parse_quic(quic_hd *qhd, const __u8 *data,
__u64 len = sizeof(struct udphdr) + 1; const __u8 *data_end) {
__u8 *p; const __u8 *p;
__u64 dcidlen; __u64 dcidlen;
if (reuse_md->data + len > reuse_md->data_end) { if (*data & 0x80) {
return -1; p = data + 1 + 4;
}
p = reuse_md->data + sizeof(struct udphdr);
if (*p & 0x80) {
len += 4 + 1;
if (reuse_md->data + len > reuse_md->data_end) {
return -1;
}
p += 1 + 4;
// Do not check the actual DCID length because we might not buffer
// whole DCID here.
dcidlen = *p; dcidlen = *p;
if (dcidlen > MAX_DCIDLEN || dcidlen < MIN_DCIDLEN) { if (dcidlen > MAX_DCIDLEN || dcidlen < MIN_DCIDLEN) {
return -1; return -1;
} }
len += 1 + dcidlen;
if (reuse_md->data + len > reuse_md->data_end) {
return -1;
}
++p; ++p;
qhd->type = qhd->type = (*data & 0x30) >> 4;
(*((__u8 *)(reuse_md->data) + sizeof(struct udphdr)) & 0x30) >> 4;
qhd->dcid = p; qhd->dcid = p;
qhd->dcidlen = dcidlen; qhd->dcidlen = dcidlen;
qhd->dcid_offset = sizeof(struct udphdr) + 6; qhd->dcid_offset = 6;
} else { } else {
len += SV_DCIDLEN;
if (reuse_md->data + len > reuse_md->data_end) {
return -1;
}
qhd->type = NGTCP2_PKT_SHORT; qhd->type = NGTCP2_PKT_SHORT;
qhd->dcid = (__u8 *)reuse_md->data + sizeof(struct udphdr) + 1; qhd->dcid = data + 1;
qhd->dcidlen = SV_DCIDLEN; qhd->dcidlen = SV_DCIDLEN;
qhd->dcid_offset = sizeof(struct udphdr) + 1; qhd->dcid_offset = 1;
} }
return 0; return 0;
@ -220,8 +199,14 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
int rv; int rv;
quic_hd qhd; quic_hd qhd;
__u32 a, b; __u32 a, b;
__u8 pkt_databuf[6 + MAX_DCIDLEN];
rv = parse_quic(&qhd, reuse_md); if (bpf_skb_load_bytes(reuse_md, sizeof(struct udphdr), pkt_databuf,
sizeof(pkt_databuf)) != 0) {
return SK_DROP;
}
rv = parse_quic(&qhd, pkt_databuf, pkt_databuf + sizeof(pkt_databuf));
if (rv != 0) { if (rv != 0) {
return SK_DROP; return SK_DROP;
} }
@ -229,12 +214,7 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
switch (qhd.type) { switch (qhd.type) {
case NGTCP2_PKT_INITIAL: case NGTCP2_PKT_INITIAL:
case NGTCP2_PKT_0RTT: case NGTCP2_PKT_0RTT:
if (reuse_md->data + qhd.dcid_offset + CID_PREFIXLEN > reuse_md->data_end) { memcpy(sk_prefix, pkt_databuf + qhd.dcid_offset, CID_PREFIXLEN);
return SK_DROP;
}
memcpy(sk_prefix, reuse_md->data + sizeof(struct udphdr) + 6,
CID_PREFIXLEN);
if (qhd.dcidlen == SV_DCIDLEN) { if (qhd.dcidlen == SV_DCIDLEN) {
psk_index = bpf_map_lookup_elem(&cid_prefix_map, sk_prefix); psk_index = bpf_map_lookup_elem(&cid_prefix_map, sk_prefix);
@ -263,11 +243,7 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
return SK_DROP; return SK_DROP;
} }
if (reuse_md->data + qhd.dcid_offset + SV_DCIDLEN > reuse_md->data_end) { memcpy(sk_prefix, pkt_databuf + qhd.dcid_offset, CID_PREFIXLEN);
return SK_DROP;
}
memcpy(sk_prefix, reuse_md->data + qhd.dcid_offset, CID_PREFIXLEN);
psk_index = bpf_map_lookup_elem(&cid_prefix_map, sk_prefix); psk_index = bpf_map_lookup_elem(&cid_prefix_map, sk_prefix);
if (psk_index == NULL) { if (psk_index == NULL) {