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 <jian...@nvidia.com> --- lib/netdev-offload-tc.c | 75 +++++++++++++++++++++++++++++++++++++++++ lib/tc.c | 61 +++++++++++++++++++++++++++++++++ lib/tc.h | 2 ++ 3 files changed, 138 insertions(+) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 9364cb530..d6ef5159c 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -2511,12 +2511,87 @@ meter_tc_del_policer(ofproto_meter_id meter_id, return err; } +struct policer_node { + struct hmap_node node; + uint32_t police_idx; +}; + +static int +tc_get_policer_action_ids(struct hmap *map) +{ + uint32_t police_idx[TCA_ACT_MAX_PRIO] = {}; + 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)) { + 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)); + } + + err = nl_dump_done(dump->nl_dump); + ofpbuf_uninit(&rbuffer); + free(dump->nl_dump); + free(dump); + + return err; +} + +static void +tc_cleanup_policer_action(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) { + /* don't use this police any more */ + id_pool_add(police_ids, police_idx); + } + } + free(policer_node); + } + + hmap_destroy(&map); +} + static int meter_tc_init_policer(void) { meter_police_ids = id_pool_create(METER_POLICE_IDS_BASE, METER_POLICE_IDS_MAX - METER_POLICE_IDS_BASE + 1); + tc_cleanup_policer_action(meter_police_ids, METER_POLICE_IDS_BASE, + METER_POLICE_IDS_MAX); return 0; } diff --git a/lib/tc.c b/lib/tc.c index ee16364ea..16d4ae3da 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -2067,6 +2067,67 @@ 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; + uint32_t prio = 0; + + 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, ++prio); + 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"); + return EPROTO; + } + + for (i = 0; i < TCA_ACT_MAX_PRIO; i++) { + if (actions_orders[i]) { + memset(&flower, 0, sizeof(struct tc_flower)); + err = tc_parse_single_action(actions_orders[i], &flower, false); + if (err) { + continue; + } + if (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 96b9e6ccc..f6d1ed91c 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -382,5 +382,7 @@ int parse_netlink_to_tc_chain(struct ofpbuf *reply, uint32_t *chain); void tc_set_policy(const char *policy); int tc_parse_single_action(struct nlattr *action, struct tc_flower *flower, bool terse); +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 d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev