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并不知道那些流是正常哪些是异常的,当前场景是小规模的还是大规模的,特别是在一些突然场景下。所以简单的流量控制在一定程度上是有效的,但专门的安全设备也是必需的。