Ryu Controller
- Ryu는 OpenFlow 기반의 네트워크 제어기 소프트웨어로, OpenFlow 스위치와 통신을 하며 네트워크 트래픽을 제어하는 역할을 합니다.
- OpenFlow 메시지를 수신하면 해당 메시지에 대응하는 이벤트가 생성됨.
- Ryu 응용 프로그램은 수신하고자 하는 메시지에 대응하는 이벤트 처리기를 구현함.
- 이벤트 처리기는 Ryu에서 핸들러로 등록되어야 합니다. 이벤트 처리기는 인수 처리를 위해 이벤트 객체를 갖는 함수를 정의하고 한정(decorate)을 위해 ryu.controller.handler.set_ev_cls 한정자를 사용합니다.
- set_ev_cls는 수신하는 메시지를 지원하는 이벤트 클래스와 인수에 대한 OpenFlow 스위치의 상태를 지정합니다. 즉, 어떤 종류의 OpenFlow 메시지를 처리할지와, 이를 처리할 함수를 연결해 주는 역할을 합니다.
- 이벤트 클래스 이름은 ryu.controller.ofp_event.EventOFP + <OpenFlow 메시지 이름> 입니다. 예를 들어, Packet-In 메시지의 경우 EventOFPPacketIn입니다.
OpenFlow 스위치와 컨트롤러의 역할
Step 1: Ping 요청
- 호스트 h1이 h2와 통신하려고 Ping Request 메시지를 보냅니다.
- 이 메시지는 Open Switch s1의 인터페이스 1로 들어갑니다.
Step 2: OpenSwitch는 무엇을 해야 할지 모름
- Open Switch s1은 h2의 존재를 알지 못하고, Ping Request 메시지를 Open Controller c0에 전달합니다.
- 이때 Packet-in 메시지가 발생합니다. Packet-in은 Open Switch에서 Open Controller로 "이 패킷을 어떻게 처리해야 할지 모르겠다"라고 알려주는 메시지입니다.
Step 3: Controller는 MAC 주소를 찾음
- Open Controller c1은 h2의 IP 주소에 해당하는 MAC 주소를 찾아야 합니다.
- 이를 위해 Packet-out 메시지를 생성하여 Open Switch s1에 보냅니다.
- Packet-out 메시지는 Controller가 Switch에 "이렇게 해야 한다"고 지시하는 메시지입니다.
Step 4: Ping Request를 브로드캐스트
- Open Switch s1은 h2의 MAC 주소를 모르므로, Ping Request 메시지를 모든 포트로 브로드캐스트합니다.
- 이때 ICMP 폭주(Ping Flooding)가 발생할 수 있습니다.
- h1이 연결된 포트는 이미 알고 있으므로, h1을 제외한 다른 포트로만 브로드캐스트합니다.
Step 5: h2가 Ping Reply를 보냄
- h2는 Ping Request 메시지를 수신하고 Ping Reply 메시지를 보냅니다.
- h2는 자신이 존재한다고 응답을 보냅니다.
Step 6: Open Switch는 다시 Controller에 전달
- Open Switch s1은 Ping Reply를 어떻게 처리해야 할지 몰라 다시 Packet-in 메시지를 Open Controller c1에 전달합니다.
- 이때 Controller는 h2의 위치(어떤 포트에 연결되어 있는지)를 확인합니다.
Step 7: Controller는 Flow 설정
- Open Controller c1은 h2의 포트 번호를 파악하고, Flow mod 메시지를 Open Switch s1에 보냅니다.
- Flow mod 메시지는 Switch에 "이 패킷은 이렇게 처리해라"라고 지시하는 메시지입니다.
Step 8: Ping Reply를 h1로 전달
- Ping Reply 메시지는 이제 h1에게 정확히 전달됩니다.
- 이제 Ping Reply는 유니캐스트 방식(1:1 통신으로 브로드캐스트와 반대)으로 전송되므로, ICMP 폭주가 발생하지 않습니다.
-> 처음에는 Switch가 호스트 간의 통신에 대해 알지 못해 많은 메시지 교환이 일어납니다. 그러나 이후에는 Flow Table을 통해 패킷 처리 방식을 지정하고, 다시는 같은 메시지에 대해 반복적인 교환이 발생하지 않게 됩니다.
OpenFlow Controller
- OpenFlow 스위치는 Ryu와 같은 OpenFlow 컨트롤러의 지시를 받고, 다음과 같은 것들을 수행할 수 있음.
- 수신된 패킷의 주소를 재작성(rewrite)하거나 지정된 포트쪽으로 전송
- 받은 패킷을 컨트롤러에 전송 (Packet-In)
- 컨트롤러에 의해 전달된 (forwarded) 패킷을 특정 포트로 전송 (Packet-Out)
- 이러한 기능들을 결합하여 스위칭 허브를 만듦.
- 우선, Packet-In 기능을 이용하여 MAC 주소를 학습함.
- 컨트롤러(Controller) 는 Packet-In 기능을 이용하여 스위치(Switch)로부터 패킷을 받을 수가 있음.
- 스위치는 받은 패킷을 분석하고 연결되어 있는 포트에 대한 호스트의 MAC 주소 및 정보를 학습함.
- 학습 후에는 받은 패킷을 전송함.
- 스위치는 패킷의 목적지 MAC 주소가 학습된 호스트에 속해있는지 아닌지를 찾음.
- 검색 결과 여부에 따라 스위치는 다음과 같은 작업을 수행함.
- 학습된 호스트인 경우 : Packet-Out 기능으로 연결된 포트쪽으로 패킷을 전송
- 알 수 없는 호스트인 경우 : Packet-Out 기능으로 패킷을 플러딩(Flooding: 패킷을 네트워크 상의 모든 연결된 장치로 보내는 방식)
- 이러한 동작을 그림과 함께 단계별로 설명.


Ryu Controller Code를 구성하는 API 함수
- class SimpleSwitch13(app_manager.RyuApp): def __init__(self, *args, **kwargs)
- 컨트롤러에 사용되는 클래스를 정의하고 초기화하며, ofproto_v1_3 OpenFlow 프로토콜을 통해 컨트롤러가 스위치하도록 한다
- 생성자
- @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
- 이벤트 처리기로서의 역할을 하는 컨트롤러는 이벤트를 처리할 수 있는 지능을 가진 소프트웨어이며, 스위치는 패킷 전송 처리를 가진 하드웨어 역할을 한다
- switch_features_handler() 함수는 오류가 없으나, set_ev_cls 한정자의 전처리 함수가 있어야 제대로 동작한다.
- switch_features_handler()
- 컨트롤러가 OpenFlow 스위치와의 핸드 셰이크 완료 후에 수행하는 함수로, 스위치를 제어하는 역할인 Flow Table을 수정하는 add_flow () 함수가 속해 있다
- _packet_in_handler(self, ev)
- 스위치 내부에서 ingress port로 들어오는 packet에 따라 Action 기능을 부여하고 packet이 flow entry 기능에 따라 mac_to_port를 수행하여, 대상 포트로 패킷을 전송한다.





코드 분석
- 클래스 정의 및 초기화
- Ryu 응용 프로그램으로 구현하기 위해 ryu.base.app_manager.RyuApp을 상속함.
- 또한 OpenFlow 1.3을 사용하기 때문에 OFP_VERSIONS에 OpenFlow 1.3 버전을 지정함.
- 또한 MAC 주소 테이블에 해당하는 mac_to_port를 정의함.
- OpenFlow 프로토콜은 OpenFlow 스위치와 컨트롤러가 통신을 위해 필요한 핸드 셰이크 등의 몇 가지 단계가 정의됨.
- 그러나, Ryu 프레임워크가 이러한 단계들을 다루기에, Ryu 응용 프로그램에서는 이러한 것들을 신경쓰지 않아도 됨.

- 이벤트 처리기
- Ryu에서, OpenFlow 메시지를 수신하면 해당 메시지에 대응하는 이벤트가 생성됨.
- Ryu 응용 프로그램은 수신하고자 하는 메시지에 대응하는 이벤트 처리기를 구현함.
- 이벤트 처리기는 인수 처리를 위해 이벤트 객체를 갖는 함수를 정의하고 한정(decorate)을 위해 ryu.controller.handler.set_ev_cls 한정자를 사용함.
- set_ev_cls는 수신하는 메시지를 지원하는 이벤트 클래스와 인수에 대한 OpenFlow 스위치의 상태를 지정함.
- 이벤트 클래스 이름은 ryu.controller.ofp_event.EventOFP + <OpenFlow 메시지 이름>임. 예를 들어, Packet-In 메시지의 경우 EventOFPPacketIn 입니다.
- 이벤트 핸들러는 ryu.controller.handler 다음에 핸들러 상태가 나오고, 이벤트는 ryu.controller.ofp_event 다음에 OpenFlow 메시지가 나옴

- 패킷 전송
- Packet-In 처리기로 돌아가 마지막 처리 단계를 설명합니다.
- 대상 MAC 주소를 MAC 주소 테이블에서 발견하는 여부와 관계없이 최종적으로 Packet-Out 메시지를 생성하여 수신 패킷을 전송합니다.

스위치 액션 (Action)
- 패킷을 포트로 전달하는 작업
- 패킷을 수정(예: TTL 필드 감소) 하는 작업
- 패킷 우선 상태 변경(예: 큐와 연결) 하는 작업

Flow Table
-
이전에 라우팅 테이블과 라우팅 알고리즘에 대해 알아볼 때는 패킷에 쓰여진 destination IP address만을 보고 forwarding 작업을 수행하였다.
- 이를 destination based forwarding이라고 한다.
-
이것을 확장시킨 개념인 generalized forwarding은 destination IP address 뿐만 아니라 헤더에 있는 다른 다양한 필드들을 가지고 다양한 작업을 수행할 수 있는 메커니즘을 의미한다.
-
Generalized forwarding의 4가지 요소: match, action, priority, counter
-
Match를 위한 Header Fields
-
Header에서 Match된 패킷에 대한 Action
- 패킷을 포트로 전달 또는 Drop
- 패킷을 수정(예: TTL 필드 감소)
- 패킷의 상태를 변경(예: 큐와 연결)하는 작업

-
Match와 Action 예
- 스위치 s3
- h5에서 목적지 IP address가 10.2로 생성된 패킷은 스위치 s3 외부 네트워크로 연결되는 Flow T able에 의해 Match됨에 의해 3번 인터페이스로 Action (forward 3) 지정됨
- 스위치 s3는 3번 인터페이스를 이용하여 패킷을 전송 → s1에 도달함
- 스위치 s1
- 스위치 s1에서는 Flow T able에서 패킷이 Match 되는지 확인함
- 첫 번째로, 스위치 s1 내부 네트워크에 할당된 IP 주소 대역이 10.1임으로, 10.2로 시작되는 패킷의 목적지 주소 IP와는 Match가 되지 않음 확인
- 두 번째로,스위치 s1 외부 네트워크로 연결되는 인터페이스를 가진 Flow Table에 의해 Match됨에 의해 s1의 4번 인터페이스로 Action (forward 4) 지정함
- 스위치 s2
- 스위치 s2에서는 Flow T able에서 패킷이 Match 되는지 확인함
- 첫 번째로, 스위치 s2 내부 네트워크에 할당된 IP 주소 대역이 10.2임으로, 10.2로 시작되는 패킷의 목적지 주소 IP와 Match됨을 확인
- 스위치 s2는 10.2로 시작되는 스위치 s2 내부 네트워크의 모든 호스트 h3, h4에 패킷을 전달함 Action (forward 3, forward 4)

OpenFlow 플로우 테이블 플로우 차트

플로우 테이블 용어 정리
- 파이프라인: OpenFlow 파이프라인 처리에서는 패킷이 해당 플로우 테이블과 상호 작용하는 방식을 정의합니다
- OpenFlow 스위치에는 최소한 하나의 플로우 테이블이 있어야 하며, 선택적으로 더 많은 플로우 테이블을 가질 수 있습니다.
- 플로우 테이블이 하나뿐인 OpenFlow 스위치도 유효하며, 이 경우 파이프라인 처리가 크게 간소화됩니다.
- OpenFlow 스위치의 플로우 테이블은 0부터 시작하여 순차적으로 번호가 매겨집니다.
- 플로우 항목: 플로우 테이블에 정의된 규칙. 패킷이 여기에 맞으면 명령어가 실행됨.
- 명령어 세트: 플로우 항목에 정의된 작업(ex. 다음 테이블로 패킷 보내기).
- 테이블 미스: 플로우 항목과 패킷이 일치하지 않는 경우. 설정에 따라 다른 처리가 이루어짐.
플로우 테이블 처리 흐름
- 첫 번째 플로우 테이블(0)에서 시작: 패킷이 테이블 0의 플로우 항목과 비교되어 일치 여부를 확인합니다.
- 일치하는 항목이 있다면 플로우 항목을 선택합니다. 플로우 항목이 발견되면 해당 플로우 항목에 포함된 명령어 세트가 실행됩니다.
- 이러한 명령어는 패킷을 다른 플로우 테이블로 명시적으로 지시할 수 있습니다. 여기서 동일한 프로세스가 다시 반복됩니다.
- 플로우 엔트리는 패킷을 자신의 플로우 테이블 번호보다 큰 플로우 테이블 번호로만 보낼 수 있습니다. 즉, 파이프라인 처리가 앞으로만 갈 수 있고 뒤로는 갈 수 없습니다.
- 필요에 따라 다음 플로우 테이블로 패킷을 보내기도 합니다.
- 일치하지 않다면 테이블 미스 처리가 실행되며, 테이블 미스에 대한 동작은 테이블 구성에 따라 달라집니다. 유용한 옵션으로는 다음 방법들이 있습니다.
- 패킷 삭제
- 다른 테이블로 전달
- Contoller 채널을 통해 패킷 수신 메시지를 컨트롤러로 전달
설치 과정 (Ryu Controller)
switch: s1
-
Open vSwitch 상태 확인.
- 윈도우 제목이 「switch : s1 (root)」인 xterm으로 스위치용 xterm.
-
Open vSwitch 실제 화면
ryu controller test
simple test
-
터미널을 열어 ryu controller 실행해서 대기시킴: ryu-manager ryu.app.simple_switch_13
-
다른 터미널을 열어 네트워크를 구성함: sudo mn --wifi --controller remote
-
ryu controller가 packet을 제어한 내용을 보여줌
- 어떤 패킷이 ryu controller 내부로 입력되었으며, 처리한 packet들을 보여줌

-
네트워크에서 ping 구현
-
네트워크에서 발생한 ping을 제어하기 위해 새롭게 ryu controller 내부로 입력된 packet 하나
Second Test
-
터미널을 열어 ryu 컨트롤러 실행해서 대기시킴: ryu-manager ryu.app.simple_switch_13
-
다른 터미널을 열어 ryu controller 동작 확인 위해 간단한 topology 를 가진
네트워크 생성함: sudo mn --topo=single,3 --mac --controller=remote --switch=ovsk
-
다른 터미널에서 실행중인 ryu 컨트롤러가 방금 실행한 single,3 에서 발생한 네트워크를 제어한 내용을 보여줌
-
topo=single,3을 생성시킨 터미널에서 ping 테스트로 패킷을 생성함
-
입력 패킷을 보고 컨트롤러가 결정을 내림
-
h1 ifconfig를 통해 h1의 MAC 주소 확인
-
s1 ifconfig를 통해 s1의 MAC 주소 확인
Ping Test
호스트 1에서 호스트 2로 ping을 실행합니다.
-
ARP request
- 이 시점에서 호스트 1은 호스트 2의 MAC 주소를 모르기 때문에 ICMP echo request 이전에 ARP request를 브로드 캐스팅됩니다.
- 이 브로드 캐스트 패킷은 호스트 2 및 호스트 3에서 수신합니다.
-
ARP reply
- 호스트 2가 ARP에 응답하여 호스트 1에 ARP reply를 반환합니다.
-
ICMP echo request
- 이제 호스트 1 호스트 2의 MAC 주소를 알고 있으므로, echo request를 호스트 2에 보냅니다.
-
ICMP echo reply\
- 호스트 2는 호스트 1의 MAC 주소를 이미 알고 있기 때문에, echo reply를 호스트 1에 반환합니다.
-
h1 ping -c3 h2 테스트시 controller에는 packet in 메시지 발생함
-
첫 번째 Packet-In은 호스트 1이 발행한 ARP request이고, 브로드캐스트이므로 플로우 항목에 등록되지 않고 Packet-Out만 발행됩니다.
-
00:00:00:00:00:01 ff:ff:ff:ff:ff:ff : 스위치 → 컨트롤러: 00:00:00:00:00:01 MAC 주소를 가진 h1이 ARP request를 스위치로 보내면, 스위치에서 packet in 메시지를 통해 컨트롤러로부터 브로드캐스팅하라고 가이드를 받게 됨 (처음 스위치는 자신에게 h2가 연결된 것을 알지 못함)
-
00:00:00:00:00:01 ff:ff:ff:ff:ff:ff : 스위치 → 브로드캐스팅: 00:00:00:00:00:01 MAC 주소를 가진 h1의 ARP request를 ff:ff:ff:ff:ff:ff(브로드캐스팅 mac 주소)로 스위치에 연결된 모든 호스트에게 mac 브로드캐스팅됨
-
두 번째는 호스트 2에서 반환된 ARP reply에서 목적지 MAC 주소가 호스트 1이고 플로우 항목이 등록됩니다.
- 00:00:00:00:00:02 00:00:00:00:00:01 스위치 → 컨트롤러: 00:00:00:00:00:02 MAC 주소를 가진 h2가 ARP reply를 스위치로 보내면, 스위치는 ARP reply 메시지에 대한 Action을 할 수 없으니, packet in 메시지를 만들어서 컨트롤러에게 보냄
- 00:00:00:00:00:02 00:00:00:00:00:01 스위치 → 유니캐스팅: 컨트롤러는 packet out 메시지를 만들어서 ARP reply 메시지를 00:00:00:00:00:01 MAC 주소를 가진 h1에게 유니캐스팅하라고 스위치에 명령함.

-
세 번째는 호스트 1에서 호스트 2로 전송 된 ICMP echo request에서 플로우 항목이 등록됩니다.
-
여기까지가 아래의 ping을 수행함으로 일어나는 스위치와 컨트롤러 사이의 컨트롤 지연시간을 포함한 12.4ms임
- 다음 남은 두 개의 ping request 메시지는 다음과 같이 처리됨
- 세 번째 단계에서 호스트 1에서 호스트 2로 전송된 ICMP echo request가 플로우 항목에 등록됨으로 등록된 규칙대로 두 개의 ping request 메시지를 처리함
- 학습된 경우임으로 이 경우에는 packet in 메시지가 발생하지 않음
- 이것이 아래의 2개 ping 처리시 시간을 절약한 내용임

-
h1에서 h3 로 ping을 하게 되면, 컨트롤러에는 packet in 메시지 발생함
-
첫 번째 Packet-In은 호스트 1이 발행한 ARP request이고, 브로드캐스트이므로 플로우 항목에 등록되지 않고 Packet-Out만 발행됩니다.
- h1에서 ARP request를 스위치에 보내게 되면, 스위치는 packet in 메시지 발생시켜 controller에 보고함
- 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff : 스위치 → 컨트롤러: 즉, 새로운 h3에 대한 mac 주소 정보를 스위치는 알 수 없음으로 packet in 메시지를 발생시켜 controller에 보냄
- 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff : 스위치 → mac 브로드캐스팅 : 컨트롤러는 스위치에게 packet out 메시지를 발생시켜 ARP request mac 브로드캐스팅으로 모든 노드에 보내라고 명령함
-
두 번째는 호스트 3에서 반환된 ARP reply에서 목적지 MAC 주소가 호스트 1이고 플로우 항목이 등록됩니다.
- h3는 mac 브로드캐스팅으로 받은 ARP request에 대응하여 ARP reply를 스위치에 보냄
- 00:00:00:00:00:03 00:00:00:00:00:01 스위치 → 컨트롤러 : h3로부터 ARP reply를 받은 스위치는 ARP reply 메시지에 대한 Action을 할 수 있는 규칙이 없으니, controller에 packet in 메시지 발생시켜 보냄
- 00:00:00:00:00:03 00:00:00:00:00:01 : 스위치 → 유니캐스팅 : controller는 유니캐스팅으로 스위치에게 h1으로 ARP reply를 보내라고 명령함
-
세 번째는 호스트 1에서 호스트 3으로 전송 된 ICMP echo request에서 플로우 항목이 등록됩니다.
- 두 번째 h1 ping h3 메시지에서는 스위치가 컨트롤러로 packe-in 메시지를
보내지 않음
- 세 단계에서 호스트 1에서 호스트 3으로 전송된 ICMP echo request가 플로우 항목에 등록됨으로 등록된 규칙대로 두 개의 남은 ping request와 ping reply 메시지를 처리함
- 학습된 경우임으로 packet in 메시지가 발생하지 않음
- 첫 번째 ping 메시지 교환을 통해 스위치는 h1 에 대한 자신의 스위치 port를 학습했고, h3 에 대한 자신의 스위치 port를 학습했기 때문에, 컨트롤러에게 h3에 대한 포트 정보를 물어볼 필요가 없게 되었다. 즉 이제는 새로운 h3에 대한 정보가 아니라, 학습한 h3에 대한 정보를 통해 h3에 대한 port를 알 수 있게 되었다.

- 컨트롤러에서 첫 번째 h1 ping h3 에 대한 메시지 이후로, 두 번째 h1 ping h3 메시지에 대한 packet in 발생이 없음을 확인함

- 컨트롤러는 항상 sudo mn --wifi -c 로 clear를 해야 남아있는 이전 컨트롤러 리소스가 없음

Quiz
1. Ryu 컨트롤러에서 Packet-In 이벤트가 발생하는 이유는 무엇인가요?
스위치가 알 수 없는 목적지에 대한 패킷을 컨트롤러로 전송하기 때문이다.
2. 다음 중 OpenFlow에서 Table-Miss 플로우 항목의 역할은 무엇인가요?
플로우 테이블과 일치하지 않는 패킷을 처리한다.
3. Ryu 컨트롤러의 _packet_in_handler 메소드가 수행하는 주요 작업을 설명하시오.
- MAC 주소 학습: 수신 포트와 원본 MAC 주소를 기반으로 MAC 주소 테이블 업데이트.
- 대상 포트 판정: 목적지 MAC 주소에 해당하는 포트를 찾고, 없으면 플러딩.
- 플로우 테이블 업데이트: 매치 조건과 액션을 플로우 테이블에 추가.
4. Table-Miss 플로우 항목의 우선순위와 기본 액션을 설명하시오.
우선순위: 0 (최저 우선순위).
기본 액션: 패킷을 컨트롤러로 전송 (OFPP_CONTROLLER).
해설: Table-Miss 플로우 항목은 패킷이 플로우 테이블의 다른 항목과 일치하지 않을 때 컨트롤러로 전달합니다.
5. OpenFlow 스위치와 Ryu 컨트롤러 간의 초기 핸드셰이크 과정을 설명하고, 이 과정이 네트워크 작동에 왜 중요한지 논하시오.
핸드셰이크 과정:
HELLO 메시지 교환: 스위치와 컨트롤러 간 OpenFlow 버전 확인.
Features Reply 메시지: 스위치가 컨트롤러에 자신의 포트와 기능을 알림.
Table-Miss 플로우 설정: 플로우 테이블 초기화.
중요성:
스위치와 컨트롤러가 동일한 프로토콜로 통신하도록 보장.
플로우 테이블 초기 설정으로 효율적 데이터 처리를 가능하게 함.
6. 다음 중 Ryu 컨트롤러에서 사용하는 주요 이벤트 클래스는 무엇인가요?
EventOFPPacketIn
7. Ryu 컨트롤러에서 add_flow() 함수의 역할을 설명하고, 플로우 항목 추가가 네트워크 성능에 미치는 영향을 논하시오.
역할:
플로우 테이블에 새로운 플로우 항목 추가.
매치 조건과 액션을 설정하여 패킷 처리를 자동화.
영향:
플로우 항목 추가는 Packet-In 메시지 수를 줄여 네트워크 지연 감소.
대규모 네트워크에서 플로우 테이블의 효율적 관리는 성능 최적화에 필수적.
그러나 플로우 항목이 많아지면 테이블 조회 시간이 증가할 수 있음.
8. Ryu 컨트롤러를 설치하고 ryu-manager 명령어를 사용해 SimpleSwitch13 애플리케이션을 실행하는 방법을 설명하시오.
sudo apt install python3-ryu
ryu-manager ryu.app.simple_switch_13