struct cname_entry {
struct avl_node node;
+ uint32_t seq;
uint8_t dscp;
uint8_t age;
};
}
static void
-cname_cache_set(const char *name, uint8_t dscp)
+cname_cache_set(const char *name, uint8_t dscp, uint32_t seq)
{
struct cname_entry *e;
e->age = 0;
e->dscp = dscp;
+ e->seq = seq;
}
static int
-cname_cache_get(const char *name, uint8_t *dscp)
+cname_cache_get(const char *name, uint8_t *dscp, uint32_t *seq)
{
struct cname_entry *e;
if (!e)
return -1;
- *dscp = e->dscp;
+ if (*dscp == 0xff || e->seq < *seq) {
+ *dscp = e->dscp;
+ *seq = e->seq;
+ }
+
return 0;
}
static int
-dns_parse_question(struct packet *pkt, const void *hdr, uint8_t *dscp)
+dns_parse_question(struct packet *pkt, const void *hdr, uint8_t *dscp, uint32_t *seq)
{
char qname[MAX_NAME_LEN];
!pkt_pull(pkt, sizeof(struct dns_question)))
return -1;
- cname_cache_get(qname, dscp);
- qosify_map_lookup_dns_entry(qname, dscp);
+ cname_cache_get(qname, dscp, seq);
+ qosify_map_lookup_dns_entry(qname, dscp, seq);
return 0;
}
static int
-dns_parse_answer(struct packet *pkt, void *hdr, uint8_t *dscp)
+dns_parse_answer(struct packet *pkt, void *hdr, uint8_t *dscp, uint32_t *seq)
{
struct qosify_map_data data = {};
char cname[MAX_NAME_LEN];
cname, sizeof(cname)) < 0)
return -1;
- qosify_map_lookup_dns_entry(cname, dscp);
- cname_cache_set(cname, *dscp);
+ qosify_map_lookup_dns_entry(cname, dscp, seq);
+ cname_cache_set(cname, *dscp, *seq);
return 0;
case TYPE_A:
qosify_dns_data_cb(struct packet *pkt)
{
struct dns_header *h;
+ uint32_t lookup_seq = 0;
uint8_t dscp = 0xff;
int i;
if (h->questions != cpu_to_be16(1))
return;
- if (dns_parse_question(pkt, h, &dscp))
+ if (dns_parse_question(pkt, h, &dscp, &lookup_seq))
return;
for (i = 0; i < be16_to_cpu(h->answers); i++)
- if (dns_parse_answer(pkt, h, &dscp))
+ if (dns_parse_answer(pkt, h, &dscp, &lookup_seq))
return;
}
int qosify_active_timeout;
struct qosify_config config;
struct qosify_flow_config flow_config;
+static uint32_t map_dns_seq;
struct qosify_map_file {
struct list_head list;
bpf_map_update_elem(fd, &data->addr, &val, BPF_ANY);
}
+ if (data->id == CL_MAP_DNS)
+ e->data.addr.dns.seq = ++map_dns_seq;
+
if (add) {
if (qosify_map_timeout == ~0 || file) {
e->timeout = ~0;
{
struct qosify_map_entry *e;
+ map_dns_seq = 0;
avl_for_each_element(&map_data, e, avl)
e->data.file = false;
}
uloop_timeout_set(&qosify_map_timer, timeout * 1000);
}
-int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp)
+int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp, uint32_t *seq)
{
struct qosify_map_data data = {
.id = CL_MAP_DNS,
continue;
}
- *dscp = e->data.dscp;
+ if (*dscp == 0xff || e->data.addr.dns.seq < *seq) {
+ *dscp = e->data.dscp;
+ *seq = e->data.addr.dns.seq;
+ }
ret = 0;
}
{
struct qosify_map_data data = {};
int prev_timeout = qosify_map_timeout;
+ uint32_t lookup_seq = 0;
- if (qosify_map_lookup_dns_entry(host, &data.dscp))
+ if (qosify_map_lookup_dns_entry(host, &data.dscp, &lookup_seq))
return 0;
data.user = true;
struct in_addr ip;
struct in6_addr ip6;
struct {
+ uint32_t seq;
const char *pattern;
regex_t regex;
} dns;
void qosify_map_reset_config(void);
void qosify_map_update_config(void);
void qosify_map_set_classes(struct blob_attr *val);
-int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp);
+int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp, uint32_t *seq);
int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int ttl);
int map_parse_flow_config(struct qosify_flow_config *cfg, struct blob_attr *attr,
bool reset);