Floodlight的流量控制

floodlight在bigswitch退出opendaylight后算是活过来了,新的版本在负载均衡中加入了一些机制,可以参见net.floodlight.loadbalancer

不过我关心的是FL对流量的控制,特别是判断packet_in速率的机制,这个在前几个月的Floodlight是没有的。

现在FL的处理机制是在收到packet_in数据包后,首先判断是否超过阈值,在inputThrottled方法中,计算每1000个数据包所花的时间,得出速率。如果速率超过packetInRateThresholdHigh阈值,则进入监控限制流量模式(enablePacketInThrottle)

在该模式下,依次检查packet_in数据包的src mac(频率为每50个packet_in一次)和in port(频率为每100个packet_in一次),如果近期(1s内)有该类数据包则将其禁止。

这种方法的初衷应该是防止controller的负载过高,例如禁止mac是为了防止host发送过多包,禁止in port是为了禁止sw转发过多包。但后者有可能出现在恶意vm发动DDoS攻击(一个in port,但无数src mac),客观上却使控制器免受DDoS攻击,自然也让域内的VM被DDoS。

贴一下主干代码:

 
/**
     * Determine if this message should be dropped.
     *
     * We compute the current rate by taking a timestamp every 100 messages.
     * Could change to a more complex scheme if more accuracy is needed.
     *
     * Enable throttling if the rate goes above packetInRateThresholdHigh
     * Disable throttling when the rate drops below packetInRateThresholdLow
     *
     * While throttling is enabled, we do the following:
     *  - Remove duplicate packetIn's mapped to the same OFMatch
     *  - After filtering, if packetIn rate per host (mac) is above
     *    packetInRatePerMacThreshold, push a flow mod to block mac on port
     *  - After filtering, if packetIn rate per port is above
     *    packetInRatePerPortThreshold, push a flow mod to block port
     *  - Allow blocking flow mods have a hard timeout and expires automatically
     *
     * TODO: keep a history of all events related in input throttling
     *
     * @param ofm
     * @return
     */
    @Override
    public boolean inputThrottled(OFMessage ofm) {
        if (ofm.getType() != OFType.PACKET_IN) {
            return false;
        }
        ctrSwitchPktin.updateCounterNoFlush();
        // Compute current packet in rate
        messageCount++;
        if (messageCount % 1000 == 0) {
            long now = System.currentTimeMillis();
            if (now != lastMessageTime) {
                currentRate = (int) (1000000 / (now - lastMessageTime));
                lastMessageTime = now;
            } else {
                currentRate = Integer.MAX_VALUE;
            }
        }
        if (!packetInThrottleEnabled) {
            if (currentRate <= packetInRateThresholdHigh) {
                return false; // most common case
            }
            enablePacketInThrottle();
        } else if (currentRate < packetInRateThresholdLow) {
            disablePacketInThrottle();
            return false;
        }

        // Now we are in the slow path where we need to do filtering
        // First filter based on OFMatch
        OFPacketIn pin = (OFPacketIn)ofm;
        OFMatch match = new OFMatch();
        match.loadFromPacket(pin.getPacketData(), pin.getInPort());
        if (ofMatchCache.update(match)) {
           ctrSwitchPktinDrops.updateCounterNoFlush();
            return true;
        }

        // We have packet in with a distinct flow, check per mac rate
        messageCountUniqueOFMatch++;
        if ((messageCountUniqueOFMatch % packetInRatePerMacThreshold) == 1) {
            checkPerSourceMacRate(pin);
        }

        // Check per port rate
        if ((messageCountUniqueOFMatch % packetInRatePerPortThreshold) == 1) {
            checkPerPortRate(pin);
        }
        return false;
    }

让我们计算一下这种机制的效率,由于阈值packetInRateThresholdHigh设置的是1000,那么now-lastMessageTime应为1000ms=1s;考虑到controller每1000个packet_in进行判断,也就是说入包的极限是每秒1000个packet_in数据包,即1000条新流。这个在小范围内是没问题的,但Nick McKeown等人在经典文章“OpenFlow: Enabling Innovation in Campus Networks”中提到Preliminary results suggested that an Ethane controller based on a low-cost desktop PC could process over 10,000 new flows per second — enough for a large college campus. 显然每秒1k条流的处理规模还是太小,那么单单增加阈值也不能解决问题:因为controller并不知道那些流是正常哪些是异常的,当前场景是小规模的还是大规模的,特别是在一些突然场景下。所以简单的流量控制在一定程度上是有效的,但专门的安全设备也是必需的。

2 thoughts on “Floodlight的流量控制

  1. Pingback: Floodlight的流量控制(Floodlight教程) | SDNAP原创 | SDNAP

Leave a Comment

Your email address will not be published. Required fields are marked *