#include "openvswitch/hmap.h"
#include "openvswitch/vlog.h"
#include "timeval.h"
+#include "util.h"
VLOG_DEFINE_THIS_MODULE(dns_resolve);
enum resolve_state {
RESOLVE_INVALID,
RESOLVE_PENDING,
+ RESOLVE_GOOD_UNUSED,
RESOLVE_GOOD,
RESOLVE_ERROR
};
return req;
}
+#define RESOLVE_UNUSED_TIMEOUT 300
+
static bool
resolve_check_expire__(struct resolve_request *req)
OVS_REQUIRES(dns_mutex__)
{
- return time_now() > req->time + req->ub_result->ttl;
+ int ttl = req->ub_result->ttl;
+
+ /* When we just sent a request, but didn't look at the response yet, it's
+ * not caching, but a "transaction in progress" situation, so we can use
+ * the response even with TTL of 0 and more than 1 second passed.
+ * Allow such values to be accessed for at least RESOLVE_UNUSED_TIMEOUT
+ * seconds without considering them stale. This is necessary in case of
+ * large backoff intervals on connections or if the process is doing some
+ * other work not looking at the response for longer than TTL. */
+ if (req->state == RESOLVE_GOOD_UNUSED) {
+ ttl = MAX(ttl, RESOLVE_UNUSED_TIMEOUT);
+ /* Not a "transaction in progress" anymore, normal caching rules should
+ * apply from this point forward. */
+ req->state = RESOLVE_GOOD;
+ }
+
+ return time_now() > req->time + ttl;
}
static bool
OVS_REQUIRES(dns_mutex__)
{
return (req != NULL
- && req->state == RESOLVE_GOOD
+ && (req->state == RESOLVE_GOOD || req->state == RESOLVE_GOOD_UNUSED)
&& !resolve_check_expire__(req));
}
req->ub_result = result;
req->addr = addr;
- req->state = RESOLVE_GOOD;
+ req->state = RESOLVE_GOOD_UNUSED;
req->time = time_now();
}