Statistics should be captured on the first action in a list
of actions, to do this we need to also capture the last update
time stamp from the first action.

Signed-off-by: Eelco Chaudron <[email protected]>
---
 lib/tc.c |  119 +++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 86 insertions(+), 33 deletions(-)

diff --git a/lib/tc.c b/lib/tc.c
index b37dce22f..b430f1bad 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -994,12 +994,35 @@ nl_parse_flower_flags(struct nlattr **attrs, struct 
tc_flower *flower)
     flower->offloaded_state = nl_get_flower_offloaded_state(attrs);
 }
 
+static int
+get_user_hz(void)
+{
+    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
+    static int user_hz = 100;
+
+    if (ovsthread_once_start(&once)) {
+        user_hz = sysconf(_SC_CLK_TCK);
+        ovsthread_once_done(&once);
+    }
+
+    return user_hz;
+}
+
+static void
+nl_parse_tcf(const struct tcf_t *tm, struct tc_flower *flower)
+{
+    flower->lastused = time_msec() - (tm->lastuse * 1000 / get_user_hz());
+}
+
 static const struct nl_policy pedit_policy[] = {
-            [TCA_PEDIT_PARMS_EX] = { .type = NL_A_UNSPEC,
-                                     .min_len = sizeof(struct tc_pedit),
-                                     .optional = false, },
-            [TCA_PEDIT_KEYS_EX]   = { .type = NL_A_NESTED,
-                                      .optional = false, },
+    [TCA_PEDIT_TM] = { .type = NL_A_UNSPEC,
+                       .min_len = sizeof(struct tcf_t),
+                       .optional = false, },
+    [TCA_PEDIT_PARMS_EX] = { .type = NL_A_UNSPEC,
+                             .min_len = sizeof(struct tc_pedit),
+                             .optional = false, },
+    [TCA_PEDIT_KEYS_EX] = { .type = NL_A_NESTED,
+                            .optional = false, },
 };
 
 static int
@@ -1094,6 +1117,9 @@ nl_parse_act_pedit(struct nlattr *options, struct 
tc_flower *flower)
     action = &flower->actions[flower->action_count++];
     action->type = TC_ACT_PEDIT;
 
+    nl_parse_tcf(nl_attr_get_unspec(pe_attrs[TCA_PEDIT_TM],
+                                    sizeof(struct tcf_t)),
+                 flower);
     return 0;
 }
 
@@ -1101,6 +1127,9 @@ static const struct nl_policy tunnel_key_policy[] = {
     [TCA_TUNNEL_KEY_PARMS] = { .type = NL_A_UNSPEC,
                                .min_len = sizeof(struct tc_tunnel_key),
                                .optional = false, },
+    [TCA_TUNNEL_KEY_TM] = { .type = NL_A_UNSPEC,
+                            .min_len = sizeof(struct tcf_t),
+                            .optional = false, },
     [TCA_TUNNEL_KEY_ENC_IPV4_SRC] = { .type = NL_A_U32, .optional = true, },
     [TCA_TUNNEL_KEY_ENC_IPV4_DST] = { .type = NL_A_U32, .optional = true, },
     [TCA_TUNNEL_KEY_ENC_IPV6_SRC] = { .type = NL_A_UNSPEC,
@@ -1275,6 +1304,10 @@ nl_parse_act_tunnel_key(struct nlattr *options, struct 
tc_flower *flower)
                     tun->action, tun->t_action);
         return EINVAL;
     }
+
+    nl_parse_tcf(nl_attr_get_unspec(tun_attrs[TCA_TUNNEL_KEY_TM],
+                                    sizeof(struct tcf_t)),
+                 flower);
     return 0;
 }
 
@@ -1287,26 +1320,6 @@ static const struct nl_policy gact_policy[] = {
                       .optional = false, },
 };
 
-static int
-get_user_hz(void)
-{
-    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
-    static int user_hz = 100;
-
-    if (ovsthread_once_start(&once)) {
-        user_hz = sysconf(_SC_CLK_TCK);
-        ovsthread_once_done(&once);
-    }
-
-    return user_hz;
-}
-
-static void
-nl_parse_tcf(const struct tcf_t *tm, struct tc_flower *flower)
-{
-    flower->lastused = time_msec() - (tm->lastuse * 1000 / get_user_hz());
-}
-
 static int
 nl_parse_act_gact(struct nlattr *options, struct tc_flower *flower)
 {
@@ -1394,18 +1407,21 @@ nl_parse_act_mirred(struct nlattr *options, struct 
tc_flower *flower)
 
 static const struct nl_policy ct_policy[] = {
     [TCA_CT_PARMS] = { .type = NL_A_UNSPEC,
-                              .min_len = sizeof(struct tc_ct),
-                              .optional = false, },
+                       .min_len = sizeof(struct tc_ct),
+                       .optional = false, },
+    [TCA_CT_TM] = { .type = NL_A_UNSPEC,
+                    .min_len = sizeof(struct tcf_t),
+                    .optional = false, },
     [TCA_CT_ACTION] = { .type = NL_A_U16,
-                         .optional = true, },
+                        .optional = true, },
     [TCA_CT_ZONE] = { .type = NL_A_U16,
                       .optional = true, },
     [TCA_CT_MARK] = { .type = NL_A_U32,
                        .optional = true, },
     [TCA_CT_MARK_MASK] = { .type = NL_A_U32,
-                            .optional = true, },
+                           .optional = true, },
     [TCA_CT_LABELS] = { .type = NL_A_UNSPEC,
-                         .optional = true, },
+                        .optional = true, },
     [TCA_CT_LABELS_MASK] = { .type = NL_A_UNSPEC,
                               .optional = true, },
     [TCA_CT_NAT_IPV4_MIN] = { .type = NL_A_U32,
@@ -1517,6 +1533,9 @@ nl_parse_act_ct(struct nlattr *options, struct tc_flower 
*flower)
     }
     action->type = TC_ACT_CT;
 
+    nl_parse_tcf(nl_attr_get_unspec(ct_attrs[TCA_CT_TM],
+                                    sizeof(struct tcf_t)),
+                 flower);
     return 0;
 }
 
@@ -1524,6 +1543,9 @@ static const struct nl_policy vlan_policy[] = {
     [TCA_VLAN_PARMS] = { .type = NL_A_UNSPEC,
                          .min_len = sizeof(struct tc_vlan),
                          .optional = false, },
+    [TCA_VLAN_TM] = { .type = NL_A_UNSPEC,
+                      .min_len = sizeof(struct tcf_t),
+                      .optional = false, },
     [TCA_VLAN_PUSH_VLAN_ID] = { .type = NL_A_U16, .optional = true, },
     [TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type = NL_A_U16, .optional = true, },
     [TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type = NL_A_U8, .optional = true, },
@@ -1562,6 +1584,10 @@ nl_parse_act_vlan(struct nlattr *options, struct 
tc_flower *flower)
                     v->action, v->v_action);
         return EINVAL;
     }
+
+    nl_parse_tcf(nl_attr_get_unspec(vlan_attrs[TCA_VLAN_TM],
+                                    sizeof(struct tcf_t)),
+                 flower);
     return 0;
 }
 
@@ -1569,6 +1595,9 @@ static const struct nl_policy mpls_policy[] = {
     [TCA_MPLS_PARMS] = { .type = NL_A_UNSPEC,
                          .min_len = sizeof(struct tc_mpls),
                          .optional = false, },
+    [TCA_MPLS_TM] = { .type = NL_A_UNSPEC,
+                      .min_len = sizeof(struct tcf_t),
+                      .optional = false, },
     [TCA_MPLS_PROTO] = { .type = NL_A_U16, .optional = true, },
     [TCA_MPLS_LABEL] = { .type = NL_A_U32, .optional = true, },
     [TCA_MPLS_TC] = { .type = NL_A_U8, .optional = true, },
@@ -1655,6 +1684,9 @@ nl_parse_act_mpls(struct nlattr *options, struct 
tc_flower *flower)
         return EINVAL;
     }
 
+    nl_parse_tcf(nl_attr_get_unspec(mpls_attrs[TCA_MPLS_TM],
+                                    sizeof(struct tcf_t)),
+                 flower);
     return 0;
 }
 
@@ -1662,6 +1694,9 @@ static const struct nl_policy csum_policy[] = {
     [TCA_CSUM_PARMS] = { .type = NL_A_UNSPEC,
                          .min_len = sizeof(struct tc_csum),
                          .optional = false, },
+    [TCA_CSUM_TM] = { .type = NL_A_UNSPEC,
+                      .min_len = sizeof(struct tcf_t),
+                      .optional = false, },
 };
 
 static int
@@ -1695,6 +1730,9 @@ nl_parse_act_csum(struct nlattr *options, struct 
tc_flower *flower)
         return EINVAL;
     }
 
+    nl_parse_tcf(nl_attr_get_unspec(csum_attrs[TCA_CSUM_TM],
+                                    sizeof(struct tcf_t)),
+                 flower);
     return 0;
 }
 
@@ -1713,7 +1751,7 @@ static const struct nl_policy stats_policy[] = {
 
 static int
 nl_parse_single_action(struct nlattr *action, struct tc_flower *flower,
-                       bool terse)
+                       bool terse, bool update_stats)
 {
     struct nlattr *act_options;
     struct nlattr *act_stats;
@@ -1779,7 +1817,7 @@ nl_parse_single_action(struct nlattr *action, struct 
tc_flower *flower,
     }
 
     bs = nl_attr_get_unspec(stats_attrs[TCA_STATS_BASIC], sizeof *bs);
-    if (bs->packets) {
+    if (bs->packets && update_stats) {
         put_32aligned_u64(&stats->n_packets, bs->packets);
         put_32aligned_u64(&stats->n_bytes, bs->bytes);
     }
@@ -1797,6 +1835,8 @@ nl_parse_flower_actions(struct nlattr **attrs, struct 
tc_flower *flower,
     static struct nl_policy actions_orders_policy[TCA_ACT_MAX_NUM + 1] = {};
     struct nlattr *actions_orders[ARRAY_SIZE(actions_orders_policy)];
     const int max_size = ARRAY_SIZE(actions_orders_policy);
+    bool first_action = true;
+    uint64_t lastused = 0;
 
     for (int i = TCA_ACT_MIN_PRIO; i < max_size; i++) {
         actions_orders_policy[i].type = NL_A_NESTED;
@@ -1817,14 +1857,27 @@ nl_parse_flower_actions(struct nlattr **attrs, struct 
tc_flower *flower,
                 VLOG_DBG_RL(&error_rl, "Can only support %d actions", 
TCA_ACT_MAX_NUM);
                 return EOPNOTSUPP;
             }
-            err = nl_parse_single_action(actions_orders[i], flower, terse);
+            err = nl_parse_single_action(actions_orders[i], flower, terse,
+                                         first_action);
 
             if (err) {
                 return err;
             }
+
+            if (first_action) {
+                /* We need to store the last used timestamp from the first
+                 * action, i.e., the action that was used the track the
+                 * statistics, as all remaining action decoding overwrite
+                 * this value. We also need to use the first actions statistics
+                 * as conditional actions can exist. */
+                lastused = flower->lastused;
+                first_action = false;
+            }
         }
     }
 
+    flower->lastused = lastused;
+
     if (flower->csum_update_flags) {
         VLOG_WARN_RL(&error_rl,
                      "expected act csum with flags: 0x%x",

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to