datapath: Fix flow time used computation.
authorJesse Gross <jesse@nicira.com>
Sat, 29 Jan 2011 22:11:23 +0000 (14:11 -0800)
committerJesse Gross <jesse@nicira.com>
Mon, 31 Jan 2011 22:56:44 +0000 (14:56 -0800)
The current reporting of flow last used time has two issues that
cause it to incorrectly report the system monotonic time when the
flow was last used.

The first is that it simply converts the stored jiffies value to
milliseconds by scaling with a constant.  This does not work because
jiffies is not zero based and can wrap around on 32-bit platforms.

The second is there is no guarantee that jiffies advances at the
same rate as the RTC based monotonic time that userspace uses.
A variety of factors can cause differences, including system suspend
and clock drift.  These are not too important for relatively short
time periods such as the duration of the flow (nor is the flow timing
precision of extreme importance).  However, when the time being
measured is the duration since system boot (assuming that the above
issues had been addressed) the difference can become significant.

This addresses both issues by restoring behavior similar to the
previous method of computing the flow used time, though in a
slightly different form to reflect the needs of the Netlink code.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
datapath/datapath.c
datapath/flow.c
datapath/flow.h

index 89b0d7f0c09f6b6ea06ea71a715344f8246f6d48..babe63c07a93a3e81a80867aec224499773db480 100644 (file)
@@ -855,7 +855,7 @@ static int odp_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
        spin_unlock_bh(&flow->lock);
 
        if (used)
-               NLA_PUT_MSECS(skb, ODP_FLOW_ATTR_USED, used);
+               NLA_PUT_U64(skb, ODP_FLOW_ATTR_USED, flow_used_time(used));
 
        if (stats.n_packets)
                NLA_PUT(skb, ODP_FLOW_ATTR_STATS, sizeof(struct odp_flow_stats), &stats);
index e90b36a93b5a37f2171d540216a1f277b6f7cd52..eb67cf4503ec08f84647792bfb0e8b60f17c5af6 100644 (file)
@@ -82,6 +82,20 @@ static inline bool icmphdr_ok(struct sk_buff *skb)
        return skb->len >= skb_transport_offset(skb) + sizeof(struct icmphdr);
 }
 
+u64 flow_used_time(unsigned long flow_jiffies)
+{
+       struct timespec cur_ts;
+       u64 cur_ms, idle_ms;
+
+       ktime_get_ts(&cur_ts);
+       idle_ms = jiffies_to_msecs(jiffies - flow_jiffies);
+       cur_ms = (u64)cur_ts.tv_sec * MSEC_PER_SEC +
+                cur_ts.tv_nsec / NSEC_PER_MSEC;
+
+       return cur_ms - idle_ms;
+}
+
+
 #define TCP_FLAGS_OFFSET 13
 #define TCP_FLAG_MASK 0x3f
 
index 78d5a7019c00b5d02f33a9aa6f81b63308a5f19b..be734532c2082e0a80db2f22c868d08b43c787c0 100644 (file)
@@ -91,6 +91,7 @@ void flow_put(struct sw_flow *);
 
 int flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *, bool *is_frag);
 void flow_used(struct sw_flow *, struct sk_buff *);
+u64 flow_used_time(unsigned long flow_jiffies);
 
 u32 flow_hash(const struct sw_flow_key *);
 int flow_cmp(const struct tbl_node *, void *target);