From: Jianbo Liu <[email protected]> Add helpers to add, delete and get stats of police action with the specified index.
Signed-off-by: Jianbo Liu <[email protected]> Reviewed-by: Roi Dayan <[email protected]> --- lib/netdev-linux.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/netdev-linux.h | 6 +++ lib/tc.c | 21 +++++++++ lib/tc.h | 6 +++ 4 files changed, 162 insertions(+) diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index ca730a15fede..63bcb8f9b173 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -5654,6 +5654,135 @@ tc_add_policer(struct netdev *netdev, uint32_t kbits_rate, return 0; } +int +tc_add_policer_action(uint32_t index, uint32_t kbits_rate, + uint32_t kbits_burst, uint32_t pkts_rate, + uint32_t pkts_burst, bool update) +{ + struct tc_police tc_police; + struct ofpbuf request; + struct tcamsg *tcamsg; + size_t offset; + int flags; + + tc_policer_init(&tc_police, kbits_rate, kbits_burst); + tc_police.index = index; + + flags = (update ? NLM_F_REPLACE : NLM_F_EXCL) | NLM_F_CREATE; + tcamsg = tc_make_action_request(RTM_NEWACTION, flags, &request); + if (!tcamsg) { + return ENODEV; + } + + offset = nl_msg_start_nested(&request, TCA_ACT_TAB); + nl_msg_put_act_police(&request, &tc_police, pkts_rate, pkts_burst); + nl_msg_end_nested(&request, offset); + + return tc_transact(&request, NULL); +} + +static int +tc_update_policer_action_stats(struct ofpbuf *msg, + struct ofputil_meter_stats *stats) +{ + const struct nlattr *act = NULL; + struct tc_flower flower; + struct nlattr *prio; + struct tcamsg *tca; + int error; + + if (NLMSG_HDRLEN + sizeof *tca > msg->size) { + return EPROTO; + } + + tca = ofpbuf_at_assert(msg, NLMSG_HDRLEN, sizeof *tca); + + act = nl_attr_find(msg, NLMSG_HDRLEN + sizeof *tca, TCA_ACT_TAB); + if (!act) { + return EPROTO; + } + + prio = (struct nlattr *) act + 1; + memset(&flower, 0, sizeof(struct tc_flower)); + error = tc_parse_single_action(prio, &flower, false); + if (!error) { + stats->packet_in_count += get_32aligned_u64(&flower.stats.n_packets); + stats->byte_in_count += get_32aligned_u64(&flower.stats.n_bytes); + } + + return error; +} + +int +tc_get_policer_action(uint32_t index, struct ofputil_meter_stats *stats) +{ + struct ofpbuf *replyp = NULL; + struct ofpbuf request; + struct tcamsg *tcamsg; + size_t root_offset; + size_t prio_offset; + int prio = 0; + int error; + + tcamsg = tc_make_action_request(RTM_GETACTION, 0, &request); + if (!tcamsg) { + return ENODEV; + } + + root_offset = nl_msg_start_nested(&request, TCA_ACT_TAB); + prio_offset = nl_msg_start_nested(&request, ++prio); + nl_msg_put_string(&request, TCA_ACT_KIND, "police"); + nl_msg_put_u32(&request, TCA_ACT_INDEX, index); + nl_msg_end_nested(&request, prio_offset); + nl_msg_end_nested(&request, root_offset); + + error = tc_transact(&request, &replyp); + if (error) { + VLOG_ERR_RL(&rl, "failed to dump police action (index: %u), err=%d", + index, error); + return error; + } + + error = tc_update_policer_action_stats(replyp, stats); + if (error) { + VLOG_ERR_RL(&rl, "failed to update police stats (index: %u), err=%d", + index, error); + } + + return error; +} + +int +tc_del_policer_action(uint32_t index, struct ofputil_meter_stats *stats) +{ + struct ofpbuf *replyp = NULL; + struct ofpbuf request; + struct tcamsg *tcamsg; + size_t root_offset; + size_t prio_offset; + int prio = 0; + int error; + + tcamsg = tc_make_action_request(RTM_DELACTION, NLM_F_ACK, &request); + if (!tcamsg) { + return ENODEV; + } + + root_offset = nl_msg_start_nested(&request, TCA_ACT_TAB); + prio_offset = nl_msg_start_nested(&request, ++prio); + nl_msg_put_string(&request, TCA_ACT_KIND, "police"); + nl_msg_put_u32(&request, TCA_ACT_INDEX, index); + nl_msg_end_nested(&request, prio_offset); + nl_msg_end_nested(&request, root_offset); + + error = tc_transact(&request, &replyp); + if (!error && stats) { + error = tc_update_policer_action_stats(replyp, stats); + } + + return error; +} + static void read_psched(void) { diff --git a/lib/netdev-linux.h b/lib/netdev-linux.h index e1e30f806557..9a416ce505c9 100644 --- a/lib/netdev-linux.h +++ b/lib/netdev-linux.h @@ -19,6 +19,7 @@ #include <stdint.h> #include <stdbool.h> +#include "openvswitch/ofp-meter.h" /* These functions are Linux specific, so they should be used directly only by * Linux-specific code. */ @@ -28,5 +29,10 @@ struct netdev; int netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag, const char *flag_name, bool enable); int linux_get_ifindex(const char *netdev_name); +int tc_add_policer_action(uint32_t index, uint32_t kbits_rate, + uint32_t kbits_burst, uint32_t pkts_rate, + uint32_t pkts_burst, bool update); +int tc_del_policer_action(uint32_t index, struct ofputil_meter_stats *stats); +int tc_get_policer_action(uint32_t index, struct ofputil_meter_stats *stats); #endif /* netdev-linux.h */ diff --git a/lib/tc.c b/lib/tc.c index b351f0e1e65f..75c9e1ad16ea 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -199,6 +199,20 @@ tc_make_request(int ifindex, int type, unsigned int flags, return tcmsg; } +struct tcamsg * +tc_make_action_request(int type, unsigned int flags, + struct ofpbuf *request) +{ + struct tcamsg *tcamsg; + + ofpbuf_init(request, 512); + nl_msg_put_nlmsghdr(request, sizeof *tcamsg, type, NLM_F_REQUEST | flags); + tcamsg = ofpbuf_put_zeros(request, sizeof *tcamsg); + tcamsg->tca_family = AF_UNSPEC; + + return tcamsg; +} + static void request_from_tcf_id(struct tcf_id *id, uint16_t eth_type, int type, unsigned int flags, struct ofpbuf *request) @@ -1828,6 +1842,13 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, return 0; } +int +tc_parse_single_action(struct nlattr *action, struct tc_flower *flower, + bool terse) +{ + return nl_parse_single_action(action, flower, terse); +} + #define TCA_ACT_MIN_PRIO 1 static int diff --git a/lib/tc.h b/lib/tc.h index 85ae5a8908ea..f31bec5d2b4b 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -80,6 +80,8 @@ tc_get_minor(unsigned int handle) struct tcmsg *tc_make_request(int ifindex, int type, unsigned int flags, struct ofpbuf *); +struct tcamsg *tc_make_action_request(int type, unsigned int flags, + struct ofpbuf *request); int tc_transact(struct ofpbuf *request, struct ofpbuf **replyp); int tc_add_del_qdisc(int ifindex, bool add, uint32_t block_id, enum tc_qdisc_hook hook); @@ -356,6 +358,8 @@ struct tc_flower { enum tc_offload_policy tc_policy; }; +struct nlattr; + /* assert that if we overflow with a masked write of uint32_t to the last byte * of flower.rewrite we overflow inside struct flower. * shouldn't happen unless someone moves rewrite to the end of flower */ @@ -374,5 +378,7 @@ int parse_netlink_to_tc_flower(struct ofpbuf *reply, bool terse); 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); #endif /* tc.h */ -- 2.8.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
