흐름 표(Flow Table)의 계수기 구조
OpenFlow v1.0에서 흐름 표는 패킷 처리의 핵심 요소로, 각 엔트리에는 세 가지 주요 구성 요소가 포함된다:
- 헤더 필드: 패킷을 매칭하기 위한 조건
- 계수기: 매칭된 패킷의 통계 정보를 수집
- 액션: 매칭된 패킷에 적용할 동작
| 구성 요소 | 기능 |
|---|---|
| 헤더 필드 | 네트워크 패킷의 특정 필드와 비교하여 매칭 여부 판단 |
| 계수기 | 패킷 처리 통계를 실시간으로 기록 및 업데이트 |
| 액션 | 매칭된 패킷에 대해 수행할 제어 명령 실행 |
계수기의 데이터 정의
계수기는 다양한 수준에서 통계 정보를 수집하며, 각 항목은 고정된 비트 크기를 갖는다.
테이블 수준 계수기
| 항목 | 비트 수 |
|---|---|
| 기록 활성화 수 | 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 인터페이스는 모든 통계 메시지의 공통 기반을 제공하며, 다음과 같은 추상 메서드를 포함한다:
getLength(): 메시지 길이 반환 (바이트 단위)readFrom(ByteBuffer): 바이너리 데이터로부터 구조화된 값 읽기writeTo(ByteBuffer): 객체 데이터를 바이너리 버퍼에 쓰기computeLength(): 메시지의 실제 길이 계산
package org.openflow.protocol.statistics;
import java.nio.ByteBuffer;
public interface OFStatistics {
int getLength();
void readFrom(ByteBuffer data);
void writeTo(ByteBuffer data);
int computeLength();
}
통계 유형 분류 및 구현 방식
OpenFlow v1.0은 여러 통계 요청/응답 타입을 정의하며, 각각은 OFStatisticsType 열거형으로 관리된다.
- DESC: 스위치의 하드웨어/소프트웨어 정보를 제공하는 설명 통계
- FLOW: 개별 흐름의 통계 정보 요청 및 응답
- AGGREGATE: 전체 흐름 집계 통계
- TABLE: 테이블 단위의 통계 정보
- PORT: 물리 포트의 트래픽 및 오류 통계
- QUEUE: 포트 내 큐별 전송 및 오류 통계
- VENDOR: 제조사 확장 통계 (고유 식별자 사용)
공식 프로토콜 사양에 따르면 통계 유형은 아래와 같이 정의된다:
enum ofp_stats_types {
OFPST_DESC,
OFPST_FLOW,
OFPST_AGGREGATE,
OFPST_TABLE,
OFPST_PORT,
OFPST_QUEUE,
OFPST_VENDOR = 0xffff
};
통계 타입 관리 클래스 분석
OFStatisticsType.java 파일은 각 통계 유형에 대한 메타정보를 저장하고, 요청/응답 메시지 간의 매핑을 처리한다.
public enum OFStatisticsType {
DESC(0, OFDescriptionStatistics.class, OFDescriptionStatistics.class, ...),
FLOW(1, OFFlowStatisticsRequest.class, OFFlowStatisticsReply.class, ...),
AGGREGATE(2, OFAggregateStatisticsRequest.class, OFAggregateStatisticsReply.class, ...),
TABLE(3, OFTableStatistics.class, OFTableStatistics.class, ...),
PORT(4, OFPortStatisticsRequest.class, OFPortStatisticsReply.class, ...),
QUEUE(5, OFQueueStatisticsRequest.class, OFQueueStatisticsReply.class, ...),
VENDOR(0xffff, OFVendorStatistics.class, OFVendorStatistics.class, ...);
// 매핑 테이블
static OFStatisticsType[] requestMapping;
static OFStatisticsType[] replyMapping;
// 요청/응답 클래스 및 생성자 정보
protected Class<? extends OFStatistics> requestClass;
protected Constructor<? extends OFStatistics> requestConstructor;
protected Class<? extends OFStatistics> replyClass;
protected Constructor<? extends OFStatistics> replyConstructor;
// 생성자: 타입 코드, 클래스 정보, 인스턴스 생성기 등 설정
OFStatisticsType(int type, Class<? extends OFStatistics> reqCls,
Class<? extends OFStatistics> repCls, ...) {
this.type = (short) type;
this.requestClass = reqCls;
this.replyClass = repCls;
try {
this.requestConstructor = reqCls.getConstructor();
this.replyConstructor = repCls.getConstructor();
} catch (Exception e) {
throw new RuntimeException("생성자 접근 실패", e);
}
// 매핑 추가
addMapping((short)type, OFType.STATS_REQUEST, this);
addMapping((short)type, OFType.STATS_REPLY, this);
}
// 타입 값으로 통계 유형 검색
static public OFStatisticsType valueOf(short type, OFType msgType) {
if (msgType == OFType.STATS_REQUEST) return requestMapping[type];
else return replyMapping[type];
}
// 인스턴스 생성
public OFStatistics newInstance(OFType msgType) {
if (msgType == OFType.STATS_REQUEST) return requestInstantiable.instantiate();
else return replyInstantiable.instantiate();
}
// 기타: 매핑 추가/제거, 클래스 가져오기, 생성자 가져오기 등
}
공통 설계 패턴 요약
이러한 통계 시스템 구현은 다음의 반복적 설계 원칙을 따르며, 코드 재사용성과 확장성을 보장한다:
- 모든 타입 이름과 관련 클래스를 열거형으로 정의
- 타입 초기화 시 메타정보(클래스, 생성자, 매핑) 저장
- 요청/응답 메시지에 따른 타입-클래스 매핑 관리
- 타입 기반 조회, 클래스 가져오기, 생성자 접근 등의 쿼리 메서드 제공
- 동적으로 인스턴스 생성 가능하도록 인스턴스화 기능 제공