OpenVSwitch 1.6 开源版本放出来了,这个版本在进行 OF 流设置的时候,有一个很有趣的功能,就是可以指定端口掩码。
早在 OpenVSwitch 1.4 版本的时候就注意到这个功能,可惜 ovs-ofctl 使用手册中说这个功能只有 1.6 及以上版本才能使用。好不容易 1.6 版本放出来了,但 OpenVSwitch 却没有提供计算端口掩码的工具。没办法,“自己动手,丰衣足食”吧。写了个 Java 的小工具,可以计算端口掩码。
用法很简单,直接调用静态方法 OvsUtil.getPortMask(minPortNum, maxPortNum)
就 OK 了。
import java.util.ArrayList;
import java.util.List;
/**
* OVS工具类
*
* @date 2012-3-24
* @version 0.1
*/
public class OvsUtil {
/**
* 端口位掩码数组
*
* 对于portBitMasks[i],按位与portBitMasks[i][0]可获取低i位的值,<br>
* 按位与portBitMasks[i][1]可获取高(16-i)位的值
*/
private static final int[][] portBitMasks = new int[][] { { 0, 0xffff },
{ 0x1, 0xfffe }, { 0x3, 0xfffc }, { 0x7, 0xfff8 }, { 0xf, 0xfff0 },
{ 0x1f, 0xffe0 }, { 0x3f, 0xffc0 }, { 0x7f, 0xff80 },
{ 0xff, 0xff00 }, { 0x1ff, 0xfe00 }, { 0x3ff, 0xfc00 },
{ 0x7ff, 0xf800 }, { 0xfff, 0xf000 }, { 0x1fff, 0xe000 },
{ 0x3fff, 0xc000 }, { 0x7fff, 0x8000 }, { 0xffff, 0 } };
/**
* 根据端口范围获取端口范围的掩码表示序列
*
* 由于端口号在1-65535之间,所以用int型表示足够了
*
* @param min
* 最小端口号
* @param max
* 最大端口号
*
* @return 表示最小端口号到最大端口号范围的掩码序列
*/
public static String[] getPortMask(int min, int max) {
if (min < 1 || max > 0xffff || min > max) {
System.out.println("错误的端口号或端口号范围!");
return new String[0];
}
List<String> masks = new ArrayList<String>();
for (int n = min; n <= max;) {
int i = 1;
for (; i <= 16; ++i) {
int x = n + portBitMasks[i][0];
if (x > max || (x & portBitMasks[i][1]) != (n & portBitMasks[i][1])) {
break;
}
}
// 因为i已经+1了,所以这里的--i就是掩码的长度
masks.add(toPortMask(n, --i));
// 下一个掩码前缀开始的地方
n += (portBitMasks[i][0] + 1);
}
return masks.toArray(new String[0]);
}
/**
* 根据开始端口号和掩码长度生成端口掩码
*
* @param port
* 端口号
* @param maskLen
* 掩码长度
*
* @return port/mask格式的端口掩码,如果掩码长度为0,则只返回端口号
*/
private static String toPortMask(int port, int maskLen) {
if (0 == maskLen) {
return "0x" + Integer.toHexString(port);
}
return "0x" + Integer.toHexString(port & portBitMasks[maskLen][1]) + "/0x"
+ Integer.toHexString(portBitMasks[maskLen][1]);
}
}