由OpenFlowJ源码学习OpenFlow协议V1.0(队列)

队列

一个OpenFlow交换机可通过简单的队列结构提供有限的QoS(质量服务)支持,从而看出队列在OpenFlow交换机中的重要作用,所以在之前介绍了流表中的三部分内容之外,本节还将以队列角度来看OpenFlow 1.0协议在“四大常见结构”中的最后一个结构:队列结构(其余三个结构即为前三篇文章介绍的头部字段、计数器与动作)。
队列包含四个部分,分别为:

  1. 队列ID(32位)
  2. 长度(16位)
  3. 填充(2*8位,为对齐64位)
  4. 属性列表(列表)

协议中将结构定义如下:

struct ofp_packet_queue {
	uint32_t queue_id; 
	uint16_t len; 
	uint8_t pad[2]; 
	struct ofp_queue_prop_header properties[0]; 
};
OFP_ASSERT(sizeof(struct ofp_packet_queue) == 8);

在OpenFlowJ的OFPacketQueue实现中,和第一节当中的头部字段中介绍的OpenFlow Message基类相类似(见前文:由OpenFlowJ源码学习OpenFlow协议V1.0(流表:头部字段)):

  1. 三个字段的获取&设置函数(queueId、length、properties)
  2. 工具:计算消息长度(computeLength)、转换为字符串(toString)
  3. 重写:重写hashCode函数、重写equals函数、深克隆(动作消息一节中用的浅克隆)
package org.openflow.protocol.queue;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import org.openflow.protocol.factory.OFQueuePropertyFactory;
import org.openflow.protocol.factory.OFQueuePropertyFactoryAware;
import org.openflow.util.U16;

// OFPacketQueue.java
public class OFPacketQueue implements Cloneable, OFQueuePropertyFactoryAware {
    public static int MINIMUM_LENGTH = 8;

    protected OFQueuePropertyFactory queuePropertyFactory;

    protected int queueId;
    protected short length;
    protected List<OFQueueProperty> properties;

    // 获取&设置队列ID
    public int getQueueId() {
        return queueId;
    }
    public OFPacketQueue setQueueId(int queueId) {
        this.queueId = queueId;
        return this;
    }

    // 获取&设置长度值
    public short getLength() {
        return length;
    }
    public int getLengthU() {
        return U16.f(this.length);
    }
    public void setLength(short length) {
        this.length = length;
    }

    // 获取&设置属性值
    public List<OFQueueProperty> getProperties() {
        return properties;
    }
    public OFPacketQueue setProperties(List<OFQueueProperty> properties) {
        this.properties = properties;
        return this;
    }

	// 读取:字节缓冲区(ByteBuffer)-->数据
    // 写入:数据-->字节缓冲区(ByteBuffer)
    public void readFrom(ByteBuffer data) {
        this.queueId = data.getInt();
        this.length = data.getShort();
        data.getShort(); // pad
        if (this.queuePropertyFactory == null)
            throw new RuntimeException("OFQueuePropertyFactory not set");
        this.properties = queuePropertyFactory.parseQueueProperties(data, U16.f(this.length) - MINIMUM_LENGTH);
    }
    public void writeTo(ByteBuffer data) {
        data.putInt(this.queueId);
        data.putShort(this.length);
        data.putShort((short) 0); // pad
        if (this.properties != null) {
            for (OFQueueProperty queueProperty : this.properties) {
                queueProperty.writeTo(data);
            }
        }
    }

	// 重写hashCode函数与equals函数
    @Override
    public int hashCode() {
        final int prime = 6367;
        int result = 1;
        result = prime * result + length;
        result = prime * result
                + ((properties == null) ? 0 : properties.hashCode());
        result = prime * result + queueId;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof OFPacketQueue))
            return false;
        OFPacketQueue other = (OFPacketQueue) obj;
        if (length != other.length)
            return false;
        if (properties == null) {
            if (other.properties != null)
                return false;
        } else if (!properties.equals(other.properties))
            return false;
        if (queueId != other.queueId)
            return false;
        return true;
    }

	// 深克隆
    @Override
    public OFPacketQueue clone() {
        try {
            OFPacketQueue clone = (OFPacketQueue) super.clone();
            if (this.properties != null) {
                List<OFQueueProperty> queueProps = new ArrayList<OFQueueProperty>();
                for (OFQueueProperty prop : this.properties) {
                    queueProps.add(prop.clone());
                }
                clone.setProperties(queueProps);
            }
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

	// 设置队列属性工厂
    @Override
    public void setQueuePropertyFactory(
            OFQueuePropertyFactory queuePropertyFactory) {
        this.queuePropertyFactory = queuePropertyFactory;
    }

	// 转为字符串,由当前队列属性获取概述
    @Override
    public String toString() {
        return "OFPacketQueue [queueId=" + queueId + ", properties="
                + properties + "]";
    }

    // 计算消息队列消息长度
    public int computeLength() {
        int l = MINIMUM_LENGTH;
        if (this.properties != null) {
            for (OFQueueProperty prop : this.properties) {
                l += prop.getLengthU();
            }
        }
        this.length = U16.t(l);
        return l;
    }
}

目前暂不讲工厂类的细节,等后面会整理各个工厂类的实现关系。

队列属性列表单元结构由三部分组成:

  1. 是否没有被定义的队列属性(默认没有队列属性,即为0)
  2. OpenFlow最低速率
  3. 待添加类型区域

在OpenFlow 1.0协议的结构定义如下:

enum ofp_queue_properties {
	OFPQT_NONE = 0, 
	OFPQT_MIN_RATE, 
	... /* 其他待添加类型 */
};

所以在除了实现前两项的属性之外,还应当动态添加类型映射,在OpenFlowJ中的OFQueuePropertyType.java文件中。关于描述队列属性类型的具体代码实现方式如下:

package org.openflow.protocol.queue;

import java.lang.reflect.Constructor;

import org.openflow.protocol.Instantiable;

// OFQueuePropertyType.java
// 列出OpenFlow队列类型并映射到有线协议值与派生类
public class OFQueuePropertyType {
    public static OFQueuePropertyType NONE = new OFQueuePropertyType(0, "NONE",
            OFQueueProperty.class, new Instantiable<OFQueueProperty>() {
                @Override
                public OFQueueProperty instantiate() {
                    return new OFQueueProperty();
                }
            });

    public static OFQueuePropertyType MIN_RATE = new OFQueuePropertyType(1, "MIN_RATE",
            OFQueuePropertyMinRate.class, new Instantiable<OFQueueProperty>() {
                @Override
                public OFQueueProperty instantiate() {
                    return new OFQueuePropertyMinRate();
                }
            });

    protected static OFQueuePropertyType[] mapping;

    protected Class<? extends OFQueueProperty> clazz;
    protected Constructor<? extends OFQueueProperty> constructor;
    protected Instantiable<OFQueueProperty> instantiable;
    protected int minLen;
    protected String name;
    protected short type;

    // 初始化:类型值、类型名、派生类与可实例化类
    public OFQueuePropertyType(int type, String name, Class<? extends OFQueueProperty> clazz, Instantiable<OFQueueProperty> instantiable) {
        this.type = (short) type;
        this.name = name;
        this.clazz = clazz;
        this.instantiable = instantiable;
        try {
            this.constructor = clazz.getConstructor(new Class[]{});
        } catch (Exception e) {
            throw new RuntimeException(
                    "Failure getting constructor for class: " + clazz, e);
        }
        OFQueuePropertyType.addMapping(this.type, this);
    }

    // 添加一个从类型值到OPType的枚举映射
    static public void addMapping(short i, OFQueuePropertyType t) {
        if (mapping == null)
            mapping = new OFQueuePropertyType[16];
        OFQueuePropertyType.mapping[i] = t;
    }

	// 通过类型值获取相关联的类型
    static public OFQueuePropertyType valueOf(short i) {
        return OFQueuePropertyType.mapping[i];
    }

    // 返回此类型的类型值
    public short getTypeValue() {
        return this.type;
    }
    
    // 获取此类型的子类
    public Class<? extends OFQueueProperty> toClass() {
        return clazz;
    }

    // 获取此类型的无参构造函数
    public Constructor<? extends OFQueueProperty> getConstructor() {
        return constructor;
    }

    // 获取当前类型的一个新建实例
    public OFQueueProperty newInstance() {
        return instantiable.instantiate();
    }

    // 获取&设置:可实例化接口
    public Instantiable<OFQueueProperty> getInstantiable() {
        return instantiable;
    }
    public void setInstantiable(Instantiable<OFQueueProperty> instantiable) {
        this.instantiable = instantiable;
    }

	// 获取类型名
    public String getName() {
        return this.name;
    }
    @Override
    public String toString() {
        return this.name;
    }
}

从上述代码中可看出,与之前三部分的枚举类差异不大,同时在前三节的类型枚举类代码中均涉及添加映射功能。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫零NET

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值