fixes
This commit is contained in:
1 parent
8e4d62c615
commit
911fcced24
4 files changed
+190
-49
No files matched your search
+73
-17
@@ -43,29 +43,84 @@ struct {
|
||||
__type(value, __u16); // MTU conhecido
|
||||
} path_mtu_map SEC(".maps");
|
||||
|
||||
// Função para ajustar TCP MSS - totalmente reescrita e simplificada para maior compatibilidade
|
||||
static __always_inline int adjust_tcp_mss(struct tcphdr *tcp, void *data_end, __u16 max_mss) {
|
||||
// Verificação básica do cabeçalho TCP
|
||||
// Atualização incremental de checksum de 16 bits (RFC 1071/1624) — a mesma
|
||||
// técnica usada pelo csum_replace2() do kernel. Necessária porque XDP não
|
||||
// tem acesso a helpers de checksum baseados em skb (bpf_l4_csum_replace só
|
||||
// existe para programas TC/socket, não XDP).
|
||||
static __always_inline __u16 csum16_replace(__u16 csum, __u16 old_val, __u16 new_val) {
|
||||
__u32 sum = (__u16)~csum + (__u16)~old_val + new_val;
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
return (__u16)~sum;
|
||||
}
|
||||
|
||||
// Clampa o MSS anunciado em pacotes SYN, reescrevendo o pacote de verdade
|
||||
// (a versão anterior só incrementava uma estatística e admitia no comentário
|
||||
// que não mexia no pacote — ou seja, não fazia nada útil). Como não mudamos
|
||||
// o tamanho do pacote, dá para escrever em cima do buffer existente sem
|
||||
// bpf_xdp_adjust_head, só recalculando o checksum do TCP.
|
||||
static __always_inline int clamp_tcp_mss(struct tcphdr *tcp, void *data_end, __u16 max_mss_host) {
|
||||
if ((void *)(tcp + 1) > data_end)
|
||||
return 0;
|
||||
|
||||
// Ajustamos MSS apenas em pacotes SYN
|
||||
|
||||
// Ajustamos MSS apenas em pacotes SYN puros (não SYN-ACK): este
|
||||
// programa roda no ingress de wg0, ou seja, só vê tráfego entrando
|
||||
// pelo túnel em direção à rede interna. O SYN-ACK de volta sai por
|
||||
// wg0 (egress), fora do alcance do XDP — cobrir essa direção também
|
||||
// exigiria um programa TC de egress, não só XDP.
|
||||
if (!tcp->syn || tcp->ack)
|
||||
return 0;
|
||||
|
||||
// Obter comprimento do cabeçalho e verificar se há opções
|
||||
|
||||
__u8 tcp_hdr_len = tcp->doff * 4;
|
||||
if (tcp_hdr_len <= sizeof(struct tcphdr))
|
||||
return 0; // Sem opções TCP
|
||||
|
||||
// Simplificado: remover a complexidade de analisar as opções
|
||||
// Em vez disso, vamos assumir um MSS conservador para todos os pacotes SYN
|
||||
__u32 key = 0;
|
||||
struct mtu_stats *stats = bpf_map_lookup_elem(&mtu_stats_map, &key);
|
||||
if (stats)
|
||||
stats->mss_adjusted++;
|
||||
|
||||
return 1; // Reportamos ajuste sem tentar modificar o pacote
|
||||
|
||||
__u8 *opt = (__u8 *)(tcp + 1);
|
||||
__u8 *opt_end = (__u8 *)tcp + tcp_hdr_len;
|
||||
if ((void *)opt_end > data_end)
|
||||
return 0;
|
||||
|
||||
// Loop limitado (verificador do BPF exige bound estático): cabeçalho
|
||||
// TCP tem no máximo 40 bytes de opções, então 10 iterações cobrem até
|
||||
// opções de 4 bytes cada — mais que suficiente para chegar no MSS,
|
||||
// que por convenção vem logo no início das opções.
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if ((void *)(opt + 1) > data_end || opt >= opt_end)
|
||||
break;
|
||||
|
||||
__u8 kind = opt[0];
|
||||
if (kind == 0) // End of Option List
|
||||
break;
|
||||
if (kind == 1) { // NOP
|
||||
opt += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((void *)(opt + 2) > data_end || opt + 1 >= opt_end)
|
||||
break;
|
||||
__u8 opt_len = opt[1];
|
||||
if (opt_len < 2 || (void *)(opt + opt_len) > data_end || opt + opt_len > opt_end)
|
||||
break;
|
||||
|
||||
if (kind == 2 && opt_len == 4) { // Maximum Segment Size
|
||||
if ((void *)(opt + 4) > data_end)
|
||||
break;
|
||||
__be16 *mss_ptr = (__be16 *)(opt + 2);
|
||||
__u16 cur_mss = bpf_ntohs(*mss_ptr);
|
||||
if (cur_mss > max_mss_host) {
|
||||
__be16 old_val = *mss_ptr;
|
||||
__be16 new_val = bpf_htons(max_mss_host);
|
||||
*mss_ptr = new_val;
|
||||
tcp->check = csum16_replace(tcp->check, old_val, new_val);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
opt += opt_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Programa XDP principal - simplificado
|
||||
@@ -135,7 +190,8 @@ int xdp_wg_optimizer(struct xdp_md *ctx) {
|
||||
// Verificar se temos espaço para o cabeçalho TCP
|
||||
if (tcp_ptr + sizeof(struct tcphdr) <= data_end) {
|
||||
struct tcphdr *tcp = tcp_ptr;
|
||||
adjust_tcp_mss(tcp, data_end, MSS_CLAMPING_VALUE);
|
||||
if (clamp_tcp_mss(tcp, data_end, MSS_CLAMPING_VALUE) && stats)
|
||||
stats->mss_adjusted++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user