On Mon, 2022-06-20 at 12:16 +0200, Eelco Chaudron wrote:
> 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?
> 

OK, I will change.

> > +    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?

Good idea. Thanks!

> 
> @@ -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".
> 

But this function is intended for police only, and its name is ended
with "_policer". Do you want to make it generel func for all 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.,
> 

I remember your comment in previous version. Sorry I didn't change here
becasue the same reason above.

>   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