• 流量管理的实现


    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);

    }

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

  • 相关阅读:
    padding magin 盒子模型
    background元素背景--font字体
    border 边框
    浅析mvvm模式和mvc模式的区别和联系
    Win10下小米路由器4A百兆版刷Openwrt固件【图片详细版】
    Vue源码-手写mustache源码
    微信小程序支付实现流程
    Fiddler对安卓模拟器中的app抓包
    Niginx中Vue Router 历史(history)模式的配置
    ES6中Promise方法详解
  • 原文地址:https://www.cnblogs.com/sunnypoem/p/12491062.html
Copyright © 2020-2023  润新知