ofproto 라이브러리¶
이 장에서는 Ryu의 ofproto 라이브러리에 대해 소개합니다.
개요¶
ofproto 라이브러리는 OpenFlow 프로토콜 메시지의 작성 · 분석을 하기 위한 라이브러리입니다.
모듈 구성¶
각 OpenFlow 버전 (버전 XY)에 대해 상수 모듈 (ofproto_vX_Y)과 파서 모듈 (ofproto_vX_Y_parser)가 포함되어 있습니다. 각 OpenFlow 버전의 구현은 기본적으로 독립되어 있습니다. 다음은 OpenFlow 1.3 경우에 해당합니다.
OpenFlow버전 | 상수 모듈 | 파서 모듈 |
---|---|---|
1.3.x | ryu.ofproto.ofproto_v1_3 | ryu.ofproto.ofproto_v1_3_parser |
상수 모듈¶
상수 모듈은 프로토콜 상수를 정의합니다. 예를 들면 다음과 같습니다.
상수 | 설명 |
---|---|
OFP_VERSION | 프로토콜 버전 번호 |
OFPP_xxxx | 포트 번호 |
OFPCML_NO_BUFFER | 버퍼없이 전체 패킷을 전송 |
OFP_NO_BUFFER | 잘못된 버퍼 번호 |
파서 모듈¶
파서 모듈은 각 OpenFlow 메시지에 대응 한 클래스가 정의되어 있습니다. 예를 들면 다음과 같습니다. 이 클래스와 그 인스턴스를 앞으로 메시지 클래스, 메시지 개체라고 합니다.
클래스 | 설명 |
---|---|
OFPHello | OFPT_HELLO 메시지 |
OFPPacketOut | OFPT_PACKET_OUT 메시지 |
OFPFlowMod | OFPT_FLOW_MOD 메시지 |
또한 파서 모듈은 OpenFlow 메시지의 페이로드 중에 사용되는 구조에 대응하는 클래스도 정의되어 있습니다. 예를 들면 다음과 같습니다. 이 클래스와 그 인스턴스를 앞으로 구조 클래스, 구조체 개체라고합니다.
클래스 | 구조체 |
---|---|
OFPMatch | ofp_match |
OFPInstructionGotoTable | ofp_instruction_goto_table |
OFPActionOutput | ofp_action_output |
기본적인 사용법¶
ProtocolDesc 클래스¶
사용하는 OpenFlow 프로토콜을 지정하기 위한 클래스입니다. 메시지 클래스의 __init__의 datapath 인수는 이 클래스 (또는 파생 클래스 인 Datapath 클래스)의 객체를 지정합니다.
from ryu.ofproto import ofproto_protocol
from ryu.ofproto import ofproto_v1_3
dp = ofproto_protocol.ProtocolDesc(version=ofproto_v1_3.OFP_VERSION)
네트워크 주소¶
Ryu ofproto 라이브러리의 API는 기본적으로 문자열 표현의 네트워크 주소가 사용됩니다. 예를 들면 다음과 같다.
주석
그러나 OpenFlow 1.0에 관해서는 다른 표현이 사용되고 있습니다. (2014년 2월 현재)
주소 종류 | python 문자열 예제 |
---|---|
MAC 주소 | ‘00:03:47:8c:a1:b3’ |
IPv4 주소 | ‘192.0.2.1’ |
IPv6 주소 | ‘2001:db8::2’ |
메시지 개체의 생성¶
각 메시지 클래스, 구조체 클래스의 인스턴스를 적절한 인수로 생성합니다.
인수의 이름은 기본적으로 OpenFlow 프로토콜에서 정해진 필드 이름은
동일합니다. 그러나 python의 예약어와 충돌하는 경우 마지막에 「_」를 넣습니다.
다음 예제에서는 「type_
」이 이에 해당됩니다.
from ryu.ofproto import ofproto_protocol
from ryu.ofproto import ofproto_v1_3
dp = ofproto_protocol.ProtocolDesc(version=ofproto_v1_3.OFP_VERSION)
ofp = dp.ofproto
ofpp = dp.ofproto_parser
actions = [parser.OFPActionOutput(port=ofp.OFPP_CONTROLLER,
max_len=ofp.OFPCML_NO_BUFFER)]
inst = [parser.OFPInstructionActions(type_=ofp.OFPIT_APPLY_ACTIONS,
actions=actions)]
fm = ofpp.OFPFlowMod(datapath=dp,
priority=0,
match=ofpp.OFPMatch(in_port=1,
eth_src='00:50:56:c0:00:08'),
instructions=inst)
주석
상수 모듈 파서 모듈은 직접 import하여 사용해도 좋지만, 사용하는 OpenFlow 버전을 변경할 때 최소한의 수정으로 끝나도록, 가능한 ProtocolDesc 개체의 ofproto, ofproto_parser 특성을 사용하는 것을 권장합니다.
메시지 개체의 분석¶
메시지 개체의 내용을 확인할 수 있습니다.
예를 들어 OFPPacketIn 개체 pid의 match 필드가 pin.match로 액세스할 수 있습니다.
OFPMatch 개체의 각 TLV 다음과 같이 이름으로 액세스할 수 있습니다.
print pin.match['in_port']
JSON¶
메시지 개체를 json.dumps 호환 dictionary로 변환하는 기능과 json.loads 호환 dictionary에서 메시지 개체를 복원하는 기능이 있습니다.
주석
그러나 OpenFlow 1.0 관해서는 구현이 불완전합니다. (2014년 2월 현재)
import json
print json.dumps(msg.to_jsondict())
메시지의 해석 (Parse)¶
메시지의 바이트 열에서 해당 메시지 객체를 생성합니다. 스위치에서 받은 메시지 내용은 프레임 워크가 자동으로 이 처리를 행하기 위해, Ryu 응용 프로그램에서 인지할 필요는 없습니다.
구체적으로는 다음과 같습니다.
1. ryu.ofproto.ofproto_parser.header 함수를 사용하여 버전 독립적 부분을 분석 2 1. 결과를 ryu.ofproto.ofproto_parser.msg 함수에 전달하여 나머지 부분을 분석
메시지의 생성 (Serialization)¶
메시지 개체에서 해당 메시지의 바이트를 생성합니다. 스위치에 보내는 메시지 내용은 프레임 워크가 자동으로 이 처리를 행하기 위해, Ryu 응용 프로그램이 인지할 필요는 없습니다.
구체적으로는 다음과 같습니다.
- 메시지 개체의 serialize 메서드를 호출
- 메시지 개체의 buf 특성을 읽을
‘len’같은 일부 필드는 명시적으로 값을 지정하지 않아도 serialize시 자동으로 계산됩니다.