On 27 May 2022, at 11:00, Jianbo Liu wrote:

> As the police actions with indexes of 0x10000000-0x1fffffff are
> reserved for meter offload, to provide a clean environment for OVS,
> these reserved police actions should be deleted on startup. So dump
> all the police actions, delete those actions with indexes in this
> range.
>
> Signed-off-by: Jianbo Liu <[email protected]>
> ---
>  lib/netdev-offload-tc.c | 75 +++++++++++++++++++++++++++++++++++++++++
>  lib/tc.c                | 60 +++++++++++++++++++++++++++++++++
>  lib/tc.h                |  2 ++
>  3 files changed, 137 insertions(+)
>
> diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
> index c88fb6a37..7e5f04bdf 100644
> --- a/lib/netdev-offload-tc.c
> +++ b/lib/netdev-offload-tc.c
> @@ -69,6 +69,11 @@ struct meter_police_mapping_data {
>      uint32_t police_idx;
>  };
>
> +struct policer_node {
> +    struct hmap_node node;
> +    uint32_t police_idx;
> +};
> +
>  #define METER_POLICE_IDS_BASE 0x10000000
>  #define METER_POLICE_IDS_MAX  0x1FFFFFFF
>  /* Protects below meter police ids pool. */
> @@ -2254,6 +2259,74 @@ probe_tc_block_support(int ifindex)
>      }
>  }
>
> +static int
> +tc_get_policer_action_ids(struct hmap *map)
> +{
> +    uint32_t police_idx[TCA_ACT_MAX_PRIO] = {};

Maybe not initialize it here, but to the explicit memset, to avoid the extra 
memset() at the end?

> +    struct policer_node *policer_node;
> +    struct netdev_flow_dump *dump;
> +    struct ofpbuf rbuffer, reply;
> +    size_t hash;
> +    int i, err;
> +
> +    dump = xzalloc(sizeof *dump);
> +    dump->nl_dump = xzalloc(sizeof *dump->nl_dump);
> +
> +    ofpbuf_init(&rbuffer, NL_DUMP_BUFSIZE);
> +    tc_dump_tc_action_start("police", dump->nl_dump);
> +
> +    while (nl_dump_next(dump->nl_dump, &reply, &rbuffer)) {

           memset(police_idx, 0, sizeof police_idx);

In addition use sizeof policy_idx, instead of TCA_ACT_MAX_PRIO * 
sizeof(uint32_t)

> +        if (parse_netlink_to_tc_policer(&reply, police_idx)) {
> +            continue;
> +        }
> +
> +        for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
> +            if (!police_idx[i]) {
> +                break;
> +            }
> +            policer_node = xzalloc(sizeof *policer_node);
> +            policer_node->police_idx = police_idx[i];
> +            hash = hash_int(police_idx[i], 0);
> +            hmap_insert(map, &policer_node->node, hash);
> +        }
> +        memset(police_idx, 0, TCA_ACT_MAX_PRIO * sizeof(uint32_t));

Remove memset above, see an earlier comment.

> +    }
> +
> +    err = nl_dump_done(dump->nl_dump);
> +    ofpbuf_uninit(&rbuffer);
> +    free(dump->nl_dump);
> +    free(dump);
> +
> +    return err;
> +}
> +
> +static void
> +tc_cleanup_policer_actions(struct id_pool *police_ids,
> +                          uint32_t id_min, uint32_t id_max)
> +{
> +    struct policer_node *policer_node;
> +    uint32_t police_idx;
> +    struct hmap map;
> +    int err;
> +
> +    hmap_init(&map);
> +    tc_get_policer_action_ids(&map);
> +
> +    HMAP_FOR_EACH_POP (policer_node, node, &map) {
> +        police_idx = policer_node->police_idx;
> +        if (police_idx >= id_min && police_idx <= id_max) {
> +            err = tc_del_policer_action(police_idx, NULL);
> +            if (err && err != ENOENT) {
> +                /* Don't use this police any more. */
> +                id_pool_add(police_ids, police_idx);
> +            }
> +        }

There is no log message when this happens, and I think this should be logged. 
Maybe a general warning level one with the number of IDs we could not re-user, 
and some debug level messages with the actual ID?

What about the following?

@@ -2326,6 +2327,7 @@ tc_cleanup_policer_actions(struct id_pool *police_ids,
                           uint32_t id_min, uint32_t id_max)
 {
     struct policer_node *policer_node;
+    unsigned int unusable_ids = 0;
     uint32_t police_idx;
     struct hmap map;
     int err;
@@ -2340,11 +2342,19 @@ tc_cleanup_policer_actions(struct id_pool *police_ids,
             if (err && err != ENOENT) {
                 /* Don't use this police any more. */
                 id_pool_add(police_ids, police_idx);
+
+                unusable_ids++;
+                VLOG_DBG("Policer index %u could not be freed for OVS, "
+                         "error %d", police_idx, err);
             }
         }
         free(policer_node);
     }

+    if (unusable_ids) {
+        VLOG_WARN("Full policer index pool allocation failed, "
+                  "%u indexes are unavailable", unusable_ids);
+    }
     hmap_destroy(&map);
 }


> +        free(policer_node);
> +    }
> +
> +    hmap_destroy(&map);
> +}
> +
>  static int
>  netdev_tc_init_flow_api(struct netdev *netdev)
>  {
> @@ -2307,6 +2380,8 @@ netdev_tc_init_flow_api(struct netdev *netdev)
>          ovs_mutex_lock(&meter_police_ids_mutex);
>          meter_police_ids = id_pool_create(METER_POLICE_IDS_BASE,
>                              METER_POLICE_IDS_MAX - METER_POLICE_IDS_BASE + 
> 1);
> +        tc_cleanup_policer_actions(meter_police_ids, METER_POLICE_IDS_BASE,
> +                                   METER_POLICE_IDS_MAX);
>          ovs_mutex_unlock(&meter_police_ids_mutex);
>
>          ovsthread_once_done(&once);
> diff --git a/lib/tc.c b/lib/tc.c
> index 77d0c9de7..ac53c56db 100644
> --- a/lib/tc.c
> +++ b/lib/tc.c
> @@ -2087,6 +2087,66 @@ tc_dump_tc_chain_start(struct tcf_id *id, struct 
> nl_dump *dump)
>      return 0;
>  }
>
> +int
> +tc_dump_tc_action_start(char *name, struct nl_dump *dump)
> +{
> +    size_t offset, root_offset;
> +    struct ofpbuf request;
> +
> +    tc_make_action_request(RTM_GETACTION, NLM_F_DUMP, &request);
> +    root_offset = nl_msg_start_nested(&request, TCA_ACT_TAB);
> +    offset = nl_msg_start_nested(&request, 1);
> +    nl_msg_put_string(&request, TCA_ACT_KIND, name);
> +    nl_msg_end_nested(&request, offset);
> +    nl_msg_end_nested(&request, root_offset);
> +
> +    nl_dump_start(dump, NETLINK_ROUTE, &request);
> +    ofpbuf_uninit(&request);
> +
> +    return 0;
> +}
> +
> +int
> +parse_netlink_to_tc_policer(struct ofpbuf *reply, uint32_t police_idx[])
> +{
> +    static struct nl_policy actions_orders_policy[TCA_ACT_MAX_PRIO] = {};
> +    struct nlattr *actions_orders[ARRAY_SIZE(actions_orders_policy)];
> +    const int max_size = ARRAY_SIZE(actions_orders_policy);
> +    const struct nlattr *actions;
> +    struct tc_flower flower;
> +    struct tcamsg *tca;
> +    int i, cnt = 0;
> +    int err;
> +
> +    for (i = 0; i < max_size; i++) {
> +        actions_orders_policy[i].type = NL_A_NESTED;
> +        actions_orders_policy[i].optional = true;
> +    }
> +
> +    tca = ofpbuf_at_assert(reply, NLMSG_HDRLEN, sizeof *tca);
> +    actions = nl_attr_find(reply, NLMSG_HDRLEN + sizeof *tca, TCA_ACT_TAB);
> +    if (!actions || !nl_parse_nested(actions, actions_orders_policy,
> +                                     actions_orders, max_size)) {
> +        VLOG_ERR_RL(&error_rl, "Failed to parse police actions");

These could be all kinds of actions, not only police ones, i.e. whatever is 
programmed.
Maybe change this to "Failed to parse flower actions".

> +        return EPROTO;
> +    }
> +
> +    for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
> +        if (actions_orders[i]) {
> +            memset(&flower, 0, sizeof(struct tc_flower));
> +            err = nl_parse_single_action(actions_orders[i], &flower, false);
> +            if (err) {
> +                continue;
> +            }
> +            if (flower.actions[0].police.index) {

You need to make sure this is the Police action (see the previous review), i.e.,

  if (flower.action[0].type ==  TC_ACT_POLICE
      && flower.actions[0].police.index) {

> +                police_idx[cnt++] = flower.actions[0].police.index;
> +            }
> +        }
> +    }
> +
> +    return 0;
> +}
> +
>  int
>  tc_del_filter(struct tcf_id *id)
>  {
> diff --git a/lib/tc.h b/lib/tc.h
> index 30cd2f7ff..4690dce4f 100644
> --- a/lib/tc.h
> +++ b/lib/tc.h
> @@ -382,5 +382,7 @@ int tc_parse_action_stats(struct nlattr *action,
>                            struct ovs_flow_stats *stats_sw,
>                            struct ovs_flow_stats *stats_hw,
>                            struct ovs_flow_stats *stats_dropped);
> +int tc_dump_tc_action_start(char *name, struct nl_dump *dump);
> +int parse_netlink_to_tc_policer(struct ofpbuf *reply, uint32_t police_idx[]);
>
>  #endif /* tc.h */
> -- 
> 2.26.2

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

Reply via email to