由OpenFlowJ源码学习OpenFlow协议V1.0(流表:计数器)

本文详细介绍了OpenFlow协议中的流表(FlowTable)结构,特别是其包含的头部字段、计数器和动作,以及OpenFlowJ项目中的OFStatistics接口。文章还讨论了OpenFlowv1.0中的七种统计类型,如描述统计、流统计、表统计等,并展示了如何通过枚举类实现这些统计功能的实例化和映射操作。
摘要由CSDN通过智能技术生成

流表(Flow Table):计数器(Counters)

OpenFlow流表(Flow Table)
流表记录(Flow Table Entry)应当包含三个部分:

  1. 头部字段(header fields);
  2. 计数器(counters);
  3. 动作(actions)。
头部字段计数器动作
用于匹配包通过统计来更新已匹配的包应用已匹配的包

其中,计数器要求统计消息中应当包含如下内容:

每张表的计数器位数
启用记录数32
包查询数64
包匹配数64
每条流的计数器位数
接收包数64
接收字节数64
时长(秒)32
时长(微秒)32
每个端口的计数器位数
接收包数64
已传输包数64
接收字节数64
已传输字节数64
接收丢弃数64
已传输丢弃数64
接收错误数64
已传输错误数64
接收帧队列错误数64
接收溢出错误数64
接收CRC错误数64
冲突数64
每个队列的计数器位数
已传输包数64
已传输字节数64
已传输溢出错误数64

在下方OpenFlowJ项目的OFStatistics.java源文件中,仅定义接口类,包含四个方法声明:

  1. getLength():获取消息长度
  2. readFrom():读取数据,类型为ByteBuffer
  3. writeTo():向ByteBuffer中写入数据
  4. computeLength():计算消息长度
package org.openflow.protocol.statistics;

import java.nio.ByteBuffer;

//OpenFlow统计基类(计数器)
public interface OFStatistics {
    // 获取消息长度(单位:byte)
    public int getLength();

    // 从ByteBuffer中读取数据
    public void readFrom(ByteBuffer data);

    // 将数据写入ByteFuffer
    public void writeTo(ByteBuffer data);

    // 计算消息长度
    public int computeLength();
}

围绕OFStatistics接口实现如下几个分类统计功能,对应协议附件的Read State Messages一节内容:

  1. Description:描述统计,描述OpenFlow交换机信息,请求体为空,回复体参考ofp_desc_stats
  2. Table:表统计,请求体为空,回复体是一组结构体,每个结构体参考ofp_table_stats
  3. Vendor:供应商统计,扩展,请求与回复体都以32位vendor ID开始,与结构体ofp_vendor_header是相同格式
  4. Aggregate(Request&Reply,请求与回复):聚合统计,聚合流统计,请求体参考ofp_aggregate_stats_request,回复体参考ofp_aggregate_stats_reply,请求体和应答体由供应商定义。
  5. Flow(Request&Reply,请求与回复):流统计,独立的流统计,请求体参考ofp_flow_stats_request,回复体是一组结构体,每个结构体参考ofp_flow_stats
  6. Port(Request&Reply,请求与回复):端口统计,物理端口统计,请求体参考ofp_port_stats_request,回复体是一组结构体,每个结构体参考ofp_port_stats
  7. Queue(Request&Reply,请求与回复):队列统计,一个端口的队列统计,请求体参考物理端口请求定义,回复体是一组结构体,每个结构体参考ofp_queue_stats

目前暂不深入解析这7个统计类,先作为简单介绍,后期将展开进行源码解析。在OpenFlow v1.0官方协议中定义了统计类型,具体如下:

enum ofp_stats_types {
	OFPST_DESC,
	OFPST_FLOW,
	OFPST_AGGREGATE,
	OFPST_TABLE,
	OFPST_PORT,
	OFPST_QUEUE,
	OFPST_VENDOR = 0xffff
};

OFStatisticsType.java文件中定义了统计类型的枚举类,即上述7个功能,其源码如下:

package org.openflow.protocol.statistics;

import java.lang.reflect.Constructor;
import org.openflow.protocol.Instantiable;
import org.openflow.protocol.OFType;

// OFStatisticsType.java
// 枚举统计类型,即计数器的内容分类。
public enum OFStatisticsType {
    DESC        (0, OFDescriptionStatistics.class, OFDescriptionStatistics.class,
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFDescriptionStatistics();
                        }
                    },
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFDescriptionStatistics();
                        }
                    }),
    FLOW       (1, OFFlowStatisticsRequest.class, OFFlowStatisticsReply.class,
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFFlowStatisticsRequest();
                        }
                    },
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFFlowStatisticsReply();
                        }
                    }),
    AGGREGATE  (2, OFAggregateStatisticsRequest.class, OFAggregateStatisticsReply.class,
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFAggregateStatisticsRequest();
                        }
                    },
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFAggregateStatisticsReply();
                        }
                    }),
    TABLE      (3, OFTableStatistics.class, OFTableStatistics.class,
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFTableStatistics();
                        }
                    },
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFTableStatistics();
                        }
                    }),
    PORT       (4, OFPortStatisticsRequest.class, OFPortStatisticsReply.class,
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFPortStatisticsRequest();
                        }
                    },
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFPortStatisticsReply();
                        }
                    }),
    QUEUE      (5, OFQueueStatisticsRequest.class, OFQueueStatisticsReply.class,
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFQueueStatisticsRequest();
                        }
                    },
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFQueueStatisticsReply();
                        }
                    }),
    VENDOR     (0xffff, OFVendorStatistics.class, OFVendorStatistics.class,
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFVendorStatistics();
                        }
                    },
                    new Instantiable<OFStatistics>() {
                        @Override
                        public OFStatistics instantiate() {
                            return new OFVendorStatistics();
                        }
                    });

    static OFStatisticsType[] requestMapping;
    static OFStatisticsType[] replyMapping;

    protected Class<? extends OFStatistics> requestClass;
    protected Constructor<? extends OFStatistics> requestConstructor;
    protected Instantiable<OFStatistics> requestInstantiable;
    protected Class<? extends OFStatistics> replyClass;
    protected Constructor<? extends OFStatistics> replyConstructor;
    protected Instantiable<OFStatistics> replyInstantiable;
    protected short type;

    // 初始化OpenFlow统计类型,包含类型值与派生类
    OFStatisticsType(int type, Class<? extends OFStatistics> requestClass,
            Class<? extends OFStatistics> replyClass,
            Instantiable<OFStatistics> requestInstantiable,
            Instantiable<OFStatistics> replyInstantiable) {
        this.type = (short) type;
        this.requestClass = requestClass;
        try {
            this.requestConstructor = requestClass.getConstructor(new Class[]{});
        } catch (Exception e) {
            throw new RuntimeException(
                    "Failure getting constructor for class: " + requestClass, e);
        }
        this.replyClass = replyClass;
        try {
            this.replyConstructor = replyClass.getConstructor(new Class[]{});
        } catch (Exception e) {
            throw new RuntimeException(
                    "Failure getting constructor for class: " + replyClass, e);
        }
        this.requestInstantiable = requestInstantiable;
        this.replyInstantiable = replyInstantiable;
        OFStatisticsType.addMapping(this.type, OFType.STATS_REQUEST, this);
        OFStatisticsType.addMapping(this.type, OFType.STATS_REPLY, this);
    }

    // 添加&移除:从类型值到统计类枚举的映射
    static public void addMapping(short i, OFType t, OFStatisticsType st) {
        if (i < 0)
            i = (short) (16+i);
        if (t == OFType.STATS_REQUEST) {
            if (requestMapping == null)
                requestMapping = new OFStatisticsType[16];
            OFStatisticsType.requestMapping[i] = st;
        } else if (t == OFType.STATS_REPLY){
            if (replyMapping == null)
                replyMapping = new OFStatisticsType[16];
            OFStatisticsType.replyMapping[i] = st;
        } else {
            throw new RuntimeException(t.toString() + " is an invalid OFType");
        }
    }
    static public void removeMapping(short i, OFType t) {
        if (i < 0)
            i = (short) (16+i);
        if (t == OFType.STATS_REQUEST) {
            requestMapping[i] = null;
        } else if (t == OFType.STATS_REPLY){
            replyMapping[i] = null;
        } else {
            throw new RuntimeException(t.toString() + " is an invalid OFType");
        }
    }

    // 通过类型值获取统计类型
    static public OFStatisticsType valueOf(short i, OFType t) {
        if (i < 0)
            i = (short) (16+i);
        if (t == OFType.STATS_REQUEST) {
            return requestMapping[i];
        } else if (t == OFType.STATS_REPLY){
            return replyMapping[i];
        } else {
            throw new RuntimeException(t.toString() + " is an invalid OFType");
        }
    }

    // 获取此统计类型的类型值
    public short getTypeValue() {
        return this.type;
    }

    // 获取此统计类型的子类:(只接受STATS_REQUEST与STATS_REPLY)
    public Class<? extends OFStatistics> toClass(OFType t) {
        if (t == OFType.STATS_REQUEST) {
            return requestClass;
        } else if (t == OFType.STATS_REPLY){
            return replyClass;
        } else {
            throw new RuntimeException(t.toString() + " is an invalid OFType");
        }
    }

    // 根据提供的请求或回复(STATS_REQUEST或STATS_REPLY),获取此OFStatisticsType实现类的无参构造函数
    public Constructor<? extends OFStatistics> getConstructor(OFType t) {
        if (t == OFType.STATS_REQUEST) {
            return requestConstructor;
        } else if (t == OFType.STATS_REPLY) {
            return replyConstructor;
        } else {
            throw new RuntimeException(t.toString() + " is an invalid OFType");
        }
    }

    // 获取&设置:可实例化请求&回复接口
    public Instantiable<OFStatistics> getRequestInstantiable() {
        return requestInstantiable;
    }
    public void setRequestInstantiable(
            Instantiable<OFStatistics> requestInstantiable) {
        this.requestInstantiable = requestInstantiable;
    }
    public Instantiable<OFStatistics> getReplyInstantiable() {
        return replyInstantiable;
    }
    public void setReplyInstantiable(Instantiable<OFStatistics> replyInstantiable) {
        this.replyInstantiable = replyInstantiable;
    }

    // 根据提供的请求或回复(STATS_REQUEST或STATS_REPLY),获取一个此OFStatisticsType实现类的新实例
    public OFStatistics newInstance(OFType t) {
        if (t == OFType.STATS_REQUEST) {
            return requestInstantiable.instantiate();
        } else if (t == OFType.STATS_REPLY) {
            return replyInstantiable.instantiate();
        } else {
            throw new RuntimeException(t.toString() + " is an invalid OFType");
        }
    }
}

结合上一篇关于流表内容的头部字段类型源码分析,可总结源码实现类型代码时的共性:

  1. 枚举所有类型名称,及其对应子类
  2. 初始化(存储基本信息、添加映射操作)
  3. 映射操作(添加&移除映射)
  4. 查询操作(根据类型名查询类型、查询此类型名、查询此类型类、获取此类构造器)
  5. 实例化操作(实例化接口获取&设置、新建此类型实例)
  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

枫零NET

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

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

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

打赏作者

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

抵扣说明:

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

余额充值