static LIST_HEAD(map_files);
static uint32_t next_timeout;
static uint8_t qosify_dscp_default[2] = { 0xff, 0xff };
-int qosify_map_timeout = 3600;
+int qosify_map_timeout;
+int qosify_active_timeout;
struct qosify_config config;
struct qosify_map_file {
e->data.dscp = e->data.file_dscp;
}
- if (e->data.dscp != prev_dscp && data->id < CL_MAP_DNS)
- bpf_map_update_elem(fd, &data->addr, &e->data.dscp, BPF_ANY);
+ if (e->data.dscp != prev_dscp && data->id < CL_MAP_DNS) {
+ struct qosify_ip_map_val val = {
+ .dscp = e->data.dscp,
+ .seen = 1,
+ };
+
+ bpf_map_update_elem(fd, &data->addr, &val, BPF_ANY);
+ }
if (add) {
if (qosify_map_timeout == ~0 || file) {
qosify_map_set_dscp_default(CL_MAP_TCP_PORTS, 0);
qosify_map_set_dscp_default(CL_MAP_UDP_PORTS, 0);
qosify_map_timeout = 3600;
+ qosify_active_timeout = 60;
memset(&config, 0, sizeof(config));
config.dscp_prio = 0xff;
free(e);
}
+static bool
+qosify_map_entry_refresh_timeout(struct qosify_map_entry *e)
+{
+ struct qosify_ip_map_val val;
+ int fd = qosify_map_fds[e->data.id];
+
+ if (e->data.id != CL_MAP_IPV4_ADDR &&
+ e->data.id != CL_MAP_IPV6_ADDR)
+ return false;
+
+ if (bpf_map_lookup_elem(fd, &e->data.addr, &val))
+ return false;
+
+ if (!val.seen)
+ return false;
+
+ e->timeout = qosify_gettime() + qosify_active_timeout;
+ val.seen = 0;
+ bpf_map_update_elem(fd, &e->data.addr, &val, BPF_ANY);
+
+ return true;
+}
+
void qosify_map_gc(void)
{
struct qosify_map_entry *e, *tmp;
if (e->data.user && e->timeout != ~0) {
cur_timeout = e->timeout - cur_time;
+ if (cur_timeout <= 0 &&
+ qosify_map_entry_refresh_timeout(e))
+ cur_timeout = e->timeout - cur_time;
if (cur_timeout <= 0) {
e->data.user = false;
e->data.dscp = e->data.file_dscp;
__uint(type, BPF_MAP_TYPE_HASH);
__uint(pinning, 1);
__uint(key_size, sizeof(struct in_addr));
- __type(value, __u8);
+ __type(value, struct qosify_ip_map_val);
__uint(max_entries, 100000);
__uint(map_flags, BPF_F_NO_PREALLOC);
} ipv4_map SEC(".maps");
__uint(type, BPF_MAP_TYPE_HASH);
__uint(pinning, 1);
__uint(key_size, sizeof(struct in6_addr));
- __type(value, __u8);
+ __type(value, struct qosify_ip_map_val);
__uint(max_entries, 100000);
__uint(map_flags, BPF_F_NO_PREALLOC);
} ipv6_map SEC(".maps");
parse_ipv4(struct __sk_buff *skb, __u32 *offset)
{
struct qosify_config *config;
+ struct qosify_ip_map_val *ip_val;
const __u32 zero_port = 0;
struct iphdr *iph;
__u8 dscp = 0xff;
else
key = &iph->daddr;
- value = bpf_map_lookup_elem(&ipv4_map, key);
- /* use udp port 0 entry as fallback for non-tcp/udp */
- if (!value && dscp == 0xff)
+ ip_val = bpf_map_lookup_elem(&ipv4_map, key);
+ if (ip_val) {
+ if (!ip_val->seen)
+ ip_val->seen = 1;
+ dscp = ip_val->dscp;
+ } else if (dscp == 0xff) {
+ /* use udp port 0 entry as fallback for non-tcp/udp */
value = bpf_map_lookup_elem(&udp_ports, &zero_port);
- if (value)
- dscp = *value;
+ if (value)
+ dscp = *value;
+ }
check_flow(config, skb, &dscp);
parse_ipv6(struct __sk_buff *skb, __u32 *offset)
{
struct qosify_config *config;
+ struct qosify_ip_map_val *ip_val;
const __u32 zero_port = 0;
struct ipv6hdr *iph;
__u8 dscp = 0;
parse_l4proto(config, skb, *offset, ipproto, &dscp);
- value = bpf_map_lookup_elem(&ipv6_map, key);
-
- /* use udp port 0 entry as fallback for non-tcp/udp */
- if (!value)
+ ip_val = bpf_map_lookup_elem(&ipv6_map, key);
+ if (ip_val) {
+ if (!ip_val->seen)
+ ip_val->seen = 1;
+ dscp = ip_val->dscp;
+ } else if (dscp == 0xff) {
+ /* use udp port 0 entry as fallback for non-tcp/udp */
value = bpf_map_lookup_elem(&udp_ports, &zero_port);
- if (value)
- dscp = *value;
+ if (value)
+ dscp = *value;
+ }
check_flow(config, skb, &dscp);
uint16_t prio_max_avg_pkt_len;
};
+struct qosify_ip_map_val {
+ uint8_t dscp; /* must be first */
+ uint8_t seen;
+};
+
#endif
extern int qosify_map_timeout;
+extern int qosify_active_timeout;
extern struct qosify_config config;
int qosify_loader_init(void);