zoukankan      html  css  js  c++  java
  • 流量管理的实现

    VPP police

    源码:https://docs.fd.io/vpp/20.01/d1/d66/police_8h_source.html

    #ifndef __POLICE_H__

    #define __POLICE_H__

    typedef enum

    {

      POLICE_CONFORM = 0,

      POLICE_EXCEED = 1,

      POLICE_VIOLATE = 2,

    } policer_result_e;

    #define POLICER_TICKS_PER_PERIOD_SHIFT 17

    #define POLICER_TICKS_PER_PERIOD       (1 << POLICER_TICKS_PER_PERIOD_SHIFT)

    typedef struct

    {

      u32 lock;         // for exclusive access to the struct

      u32 single_rate;        // 1 = single rate policer, 0 = two rate policer

      u32 color_aware;        // for hierarchical policing

      u32 scale;            // power-of-2 shift amount for lower rates

      u8 action[3];

      u8 mark_dscp[3];

      u8 pad[2];

      // Fields are marked as 2R if they are only used for a 2-rate policer,

      // and MOD if they are modified as part of the update operation.

      // 1 token = 1 byte.

      u32 cir_tokens_per_period;    // # of tokens for each period

      u32 pir_tokens_per_period;    // 2R

      u32 current_limit;

      u32 current_bucket;        // MOD

      u32 extended_limit;

      u32 extended_bucket;        // MOD

      u64 last_update_time;        // MOD

      u64 pad64;

    } policer_read_response_type_st;

    static inline policer_result_e

    vnet_police_packet (policer_read_response_type_st * policer,

                  u32 packet_length,

                  policer_result_e packet_color, u64 time)

    {

        u64 n_periods;

        u64 current_tokens, extended_tokens;

        policer_result_e result;

        // Scale packet length to support a wide range of speeds

        packet_length = packet_length << policer->scale;

        // Compute the number of policer periods that have passed since the last

        // operation.

        n_periods = time - policer->last_update_time;

        policer->last_update_time = time;

        if (policer->single_rate){

            // Compute number of tokens for this time period

            current_tokens = policer->current_bucket + n_periods * policer->cir_tokens_per_period;

            if (current_tokens > policer->current_limit)

            {

                current_tokens = policer->current_limit;

            }

            extended_tokens = policer->extended_bucket + n_periods * policer->cir_tokens_per_period;

            if (extended_tokens > policer->extended_limit)

            {

                extended_tokens = policer->extended_limit;

            }

            // Determine color

            if ((!policer->color_aware || (packet_color == POLICE_CONFORM))

                  && (current_tokens >= packet_length))

            {

                policer->current_bucket = current_tokens - packet_length;

                policer->extended_bucket = extended_tokens - packet_length;

                result = POLICE_CONFORM;

            }

            else if ((!policer->color_aware || (packet_color != POLICE_VIOLATE))

                  && (extended_tokens >= packet_length))

            {

                policer->current_bucket = current_tokens;

                policer->extended_bucket = extended_tokens - packet_length;

                result = POLICE_EXCEED;

            }

            else

            {

                policer->current_bucket = current_tokens;

                policer->extended_bucket = extended_tokens;

                result = POLICE_VIOLATE;

            }

        }

        else

        {

            // Two-rate policer

            // Compute number of tokens for this time period

            current_tokens = policer->current_bucket + n_periods * policer->cir_tokens_per_period;

            extended_tokens =policer->extended_bucket + n_periods * policer->pir_tokens_per_period;

            if (current_tokens > policer->current_limit)

            {

                current_tokens = policer->current_limit;

            }

            if (extended_tokens > policer->extended_limit)

            {

                extended_tokens = policer->extended_limit;

            }

            // Determine color

            if ((policer->color_aware && (packet_color == POLICE_VIOLATE))

                    || (extended_tokens < packet_length))

            {

                policer->current_bucket = current_tokens;

                policer->extended_bucket = extended_tokens;

                result = POLICE_VIOLATE;

            }

            else if ((policer->color_aware && (packet_color == POLICE_EXCEED))

                   || (current_tokens < packet_length))

            {

                policer->current_bucket = current_tokens;

                policer->extended_bucket = extended_tokens - packet_length;

                result = POLICE_EXCEED;

            }

            else

            {

                policer->current_bucket = current_tokens - packet_length;

                policer->extended_bucket = extended_tokens - packet_length;

                result = POLICE_CONFORM;

            }

        }

        return result;

    }

    #endif // __POLICE_H__

    根据限速规则的设置,主要操作就是计算保证速率和峰值速率当前获得的令牌数,剩下就是根据配置的策略,来判断当前报文的决策。

    // Compute the number of policer periods that have passed since the last operation.

        n_periods = time - policer->last_update_time;

        policer->last_update_time = time;

    // Compute number of tokens for this time period

        current_tokens = policer->current_bucket + n_periods * policer->cir_tokens_per_period;

        if (current_tokens > policer->current_limit){

            current_tokens = policer->current_limit;

        }

        extended_tokens = policer->extended_bucket + n_periods * policer->cir_tokens_per_period;

        if (extended_tokens > policer->extended_limit){

            extended_tokens = policer->extended_limit;

        }

    RateLimiter

    源码:https://github.com/mfycheng/ratelimiter

    std::chrono::microseconds RateLimiter::claim_next(double permits) {

        using namespace std::chrono;

        std::lock_guard<std::mutex> lock(mut_);

    unsigned long long now

    = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();

        // Make sure we're synced

        sync(now);

        // Since we synced before hand, this will always be >= 0.

        unsigned long long wait = next_free_ - now;

        // Determine how many stored and freh permits to consume

        double stored = std::min(permits, stored_permits_);

        double fresh = permits - stored;

        // In the general RateLimiter, stored permits have no wait time,

        // and thus we only have to wait for however many fresh permits we consume

        long next_free = (long)(fresh * interval_);

        next_free_ += next_free;

        stored_permits_ -= stored;

        return microseconds(wait);

    }

    相比上面的代码,核心思想也是利用令牌桶,但使用起来更简单。

  • 相关阅读:
    Sharding-Jdbc 自定义分库分表-复合分片算法自定义实现
    sklearn:Python语言开发的通用机器学习库
    php验证码--图片
    ListView中的Item点击事件和子控件的冲突或者item点击没有反应的解决的方法
    【转载】C# Graphics类具体解释
    Oracle之外键(Foreign Key)使用方法具体解释(二)- 级联删除(DELETE CASCADE)
    职业生涯-小公司和大公司的不同(持续更新)
    视音频数据处理入门:AAC音频码流解析
    让人非常easy误解的TCP拥塞控制算法
    Redis资料整理
  • 原文地址:https://www.cnblogs.com/sunnypoem/p/12491062.html
Copyright © 2011-2022 走看看