qosify: update to latest version

This improves bulk traffic detection.

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2021-11-01 11:32:13 +01:00
parent 11ed0b089c
commit 70c2c36e0f
5 changed files with 112 additions and 61 deletions

View File

@@ -1,10 +1,12 @@
config defaults
list defaults /etc/qosify-defaults.conf
option dscp_prio CS5
option dscp_icmp CS6
option dscp_bulk CS0
option dscp_default_udp CS4
option bulk_trigger_timeout 5
option bulk_trigger_pps 0
option bulk_trigger_pps 100
option prio_max_avg_pkt_len 500
config interface wan
option name wan

View File

@@ -30,10 +30,12 @@ add_defaults() {
add_option int timeout
add_option string dscp_prio
add_option string dscp_bulk
add_option string dscp_icmp
add_option string dscp_default_udp
add_option string dscp_default_tcp
add_option int bulk_trigger_timeout
add_option int bulk_trigger_pps
add_option int prio_max_avg_pkt_len
}
add_interface() {

View File

@@ -36,6 +36,34 @@ static const struct {
[CL_MAP_CONFIG] = { "config", "config" },
};
static const struct {
const char name[5];
uint8_t val;
} codepoints[] = {
{ "CS0", 0 },
{ "CS1", 8 },
{ "CS2", 16 },
{ "CS3", 24 },
{ "CS4", 32 },
{ "CS5", 40 },
{ "CS6", 48 },
{ "CS7", 56 },
{ "AF11", 10 },
{ "AF12", 12 },
{ "AF13", 14 },
{ "AF21", 18 },
{ "AF22", 20 },
{ "AF22", 22 },
{ "AF31", 26 },
{ "AF32", 28 },
{ "AF33", 30 },
{ "AF41", 34 },
{ "AF42", 36 },
{ "AF43", 38 },
{ "EF", 46 },
{ "VA", 44 },
};
static void qosify_map_timer_cb(struct uloop_timeout *t)
{
qosify_map_gc();
@@ -104,6 +132,8 @@ static void __qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val)
int fd = qosify_map_fds[id];
int i;
val |= QOSIFY_DSCP_DEFAULT_FLAG;
for (i = 0; i < (1 << 16); i++) {
data.addr.port = htons(i);
if (avl_find(&map_data, &data))
@@ -159,38 +189,11 @@ static char *str_skip(char *str, bool space)
static int
qosify_map_codepoint(const char *val)
{
static const struct {
const char name[5];
uint8_t val;
} cp[] = {
{ "CS0", 0 },
{ "CS1", 8 },
{ "CS2", 16 },
{ "CS3", 24 },
{ "CS4", 32 },
{ "CS5", 40 },
{ "CS6", 48 },
{ "CS7", 56 },
{ "AF11", 10 },
{ "AF12", 12 },
{ "AF13", 14 },
{ "AF21", 18 },
{ "AF22", 20 },
{ "AF22", 22 },
{ "AF31", 26 },
{ "AF32", 28 },
{ "AF33", 30 },
{ "AF41", 34 },
{ "AF42", 36 },
{ "AF43", 38 },
{ "EF", 46 },
{ "VA", 44 },
};
int i;
for (i = 0; i < ARRAY_SIZE(cp); i++)
if (!strcmp(cp[i].name, val))
return cp[i].val;
for (i = 0; i < ARRAY_SIZE(codepoints); i++)
if (!strcmp(codepoints[i].name, val))
return codepoints[i].val;
return 0xff;
}
@@ -351,6 +354,28 @@ int qosify_map_dscp_value(const char *val)
return dscp + (fallback << 6);
}
static void
qosify_map_dscp_codepoint_str(char *dest, int len, uint8_t dscp)
{
int i;
if (dscp & QOSIFY_DSCP_FALLBACK_FLAG) {
*(dest++) = '+';
len--;
dscp &= ~QOSIFY_DSCP_FALLBACK_FLAG;
}
for (i = 0; i < ARRAY_SIZE(codepoints); i++) {
if (codepoints[i].val != dscp)
continue;
snprintf(dest, len, "%s", codepoints[i].name);
return;
}
snprintf(dest, len, "0x%x", dscp);
}
static void
qosify_map_parse_line(char *str)
{
@@ -543,6 +568,10 @@ void qosify_map_dump(struct blob_buf *b)
blobmsg_add_u8(b, "file", e->data.file);
blobmsg_add_u8(b, "user", e->data.user);
buf = blobmsg_alloc_string_buffer(b, "dscp", buf_len);
qosify_map_dscp_codepoint_str(buf, buf_len, e->data.dscp);
blobmsg_add_string_buffer(b);
blobmsg_add_string(b, "type", qosify_map_info[e->data.id].type_name);
buf = blobmsg_alloc_string_buffer(b, "value", buf_len);

View File

@@ -16,7 +16,6 @@
#include "qosify-bpf.h"
#define INET_ECN_MASK 3
#define DSCP_FALLBACK_FLAG BIT(6)
#define FLOW_CHECK_INTERVAL ((u32)((1000000000ULL) >> 24))
#define FLOW_TIMEOUT ((u32)((30ULL * 1000000000ULL) >> 24))
@@ -211,33 +210,37 @@ static void
parse_l4proto(struct qosify_config *config, struct __sk_buff *skb,
__u32 offset, __u8 proto, __u8 *dscp_out)
{
struct udphdr *udp = skb_ptr(skb, offset);
__u32 key;
struct udphdr *udp;
__u32 src, dest, key;
__u8 *value;
udp = skb_ptr(skb, offset);
if (skb_check(skb, &udp->len))
return;
if (module_flags & QOSIFY_INGRESS)
key = udp->source;
else
key = udp->dest;
if (proto == IPPROTO_TCP)
value = bpf_map_lookup_elem(&tcp_ports, &key);
else if (proto == IPPROTO_UDP)
value = bpf_map_lookup_elem(&udp_ports, &key);
else {
if ((proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) &&
config && config->dscp_icmp != 0xff)
*dscp_out = config->dscp_icmp;
if (config && (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)) {
*dscp_out = config->dscp_icmp;
return;
}
if (!value)
return;
src = udp->source;
dest = udp->dest;
if ((*value & DSCP_FALLBACK_FLAG) && *dscp_out)
if (module_flags & QOSIFY_INGRESS)
key = src;
else
key = dest;
if (proto == IPPROTO_TCP) {
value = bpf_map_lookup_elem(&tcp_ports, &key);
} else {
if (proto != IPPROTO_UDP)
key = 0;
value = bpf_map_lookup_elem(&udp_ports, &key);
}
if (!value)
return;
*dscp_out = *value;
@@ -253,9 +256,16 @@ check_flow(struct qosify_config *config, struct __sk_buff *skb,
__u32 hash;
__u32 time;
if (!(*dscp & QOSIFY_DSCP_DEFAULT_FLAG))
return;
if (!config)
return;
if (!config->bulk_trigger_pps &&
!config->prio_max_avg_pkt_len)
return;
time = cur_time();
hash = bpf_get_hash_recalc(skb);
flow = bpf_map_lookup_elem(&flow_map, &hash);
@@ -287,7 +297,8 @@ check_flow(struct qosify_config *config, struct __sk_buff *skb,
if (flow->pkt_count < 0xffff)
flow->pkt_count++;
if (flow->pkt_count > config->bulk_trigger_pps) {
if (config->bulk_trigger_pps &&
flow->pkt_count > config->bulk_trigger_pps) {
flow->dscp = config->dscp_bulk;
flow->bulk_timeout = config->bulk_trigger_timeout;
}
@@ -302,8 +313,7 @@ out:
flow->dscp = 0xff;
}
if (flow->dscp != 0xff &&
!(*dscp && (flow->dscp & DSCP_FALLBACK_FLAG)))
if (flow->dscp != 0xff)
*dscp = flow->dscp;
return;
@@ -324,8 +334,9 @@ parse_ipv4(struct __sk_buff *skb, __u32 *offset)
struct qosify_config *config;
const __u32 zero_port = 0;
struct iphdr *iph;
__u8 dscp = 0;
__u8 dscp = 0xff;
__u8 *value;
__u8 ipproto;
int hdr_len;
void *key;
bool force;
@@ -337,7 +348,7 @@ parse_ipv4(struct __sk_buff *skb, __u32 *offset)
return;
hdr_len = iph->ihl * 4;
if (bpf_skb_pull_data(skb, *offset + hdr_len))
if (bpf_skb_pull_data(skb, *offset + hdr_len + sizeof(struct udphdr)))
return;
iph = skb_ptr(skb, *offset);
@@ -346,7 +357,8 @@ parse_ipv4(struct __sk_buff *skb, __u32 *offset)
if (skb_check(skb, (void *)(iph + 1)))
return;
parse_l4proto(config, skb, *offset, iph->protocol, &dscp);
ipproto = iph->protocol;
parse_l4proto(config, skb, *offset, ipproto, &dscp);
if (module_flags & QOSIFY_INGRESS)
key = &iph->saddr;
@@ -355,14 +367,14 @@ parse_ipv4(struct __sk_buff *skb, __u32 *offset)
value = bpf_map_lookup_elem(&ipv4_map, key);
/* use udp port 0 entry as fallback for non-tcp/udp */
if (!value)
if (!value && dscp == 0xff)
value = bpf_map_lookup_elem(&udp_ports, &zero_port);
if (value)
dscp = *value;
check_flow(config, skb, &dscp);
force = !(dscp & DSCP_FALLBACK_FLAG);
force = !(dscp & QOSIFY_DSCP_FALLBACK_FLAG);
dscp &= GENMASK(5, 0);
ipv4_change_dsfield(iph, INET_ECN_MASK, dscp << 2, force);
@@ -376,12 +388,13 @@ parse_ipv6(struct __sk_buff *skb, __u32 *offset)
struct ipv6hdr *iph;
__u8 dscp = 0;
__u8 *value;
__u8 ipproto;
void *key;
bool force;
config = get_config();
if (bpf_skb_pull_data(skb, *offset + sizeof(*iph)))
if (bpf_skb_pull_data(skb, *offset + sizeof(*iph) + sizeof(struct udphdr)))
return;
iph = skb_ptr(skb, *offset);
@@ -390,12 +403,13 @@ parse_ipv6(struct __sk_buff *skb, __u32 *offset)
if (skb_check(skb, (void *)(iph + 1)))
return;
ipproto = iph->nexthdr;
if (module_flags & QOSIFY_INGRESS)
key = &iph->saddr;
else
key = &iph->daddr;
parse_l4proto(config, skb, *offset, iph->nexthdr, &dscp);
parse_l4proto(config, skb, *offset, ipproto, &dscp);
value = bpf_map_lookup_elem(&ipv6_map, key);
@@ -407,7 +421,7 @@ parse_ipv6(struct __sk_buff *skb, __u32 *offset)
check_flow(config, skb, &dscp);
force = !(dscp & DSCP_FALLBACK_FLAG);
force = !(dscp & QOSIFY_DSCP_FALLBACK_FLAG);
dscp &= GENMASK(5, 0);
ipv6_change_dsfield(iph, INET_ECN_MASK, dscp << 2, force);

View File

@@ -11,6 +11,10 @@
#define QOSIFY_INGRESS (1 << 0)
#define QOSIFY_IP_ONLY (1 << 1)
#define QOSIFY_DSCP_FALLBACK_FLAG (1 << 6)
#define QOSIFY_DSCP_DEFAULT_FLAG (1 << 7)
/* global config data */
struct qosify_config {
uint8_t dscp_prio;