faucetsdn / ryu

Ryu component-based software defined networking framework
https://ryu-sdn.org
Apache License 2.0
1.52k stars 1.16k forks source link

RYU Controller: How to Force OpenFlow Switch to Send PacketIn Events Even When a Flow Exists in Switch? #202

Closed faniAhmed closed 4 weeks ago

faniAhmed commented 1 month ago

I'm using the RYU controller and OpenFlow switches to secure my network by monitoring traffic. However, I’m facing an issue where I don’t receive PacketIn events from the switch after a flow has been created. My current understanding is:

When a flow exists: The OpenFlow switch forwards packets based on the flow rule, but it does not send a PacketIn event to the controller.
When no flow exists: The switch buffers the packet and waits for a command from the controller to either forward or drop it, generating a PacketIn event.

I want to monitor traffic continuously, even for existing flows, to detect unusual activity. Specifically, I’d like to configure the OpenFlow switch so that:

Packets are not buffered when there is an active flow but are forwarded directly.
A PacketIn event is sent to the controller with each forwarded packet, allowing me to inspect the traffic for security monitoring.

I know I can simply remove flow rules and not add any flow to switch but it is necessary to have both in my case. Is there a way to achieve this behavior in RYU/OpenFlow? I'd appreciate any advice or sample code that could help implement this functionality.

badcodebuilder commented 1 month ago

Before reading my answer, I recommend you to review the concept of SDN, why we separate controller plane and data plane?

Method 1: Add CONTROLLER port to out port list (not recommend)

The CONTROLLER port is defined in OpenFlow specification. According to this specification, any message send to CONTROLLER port will be encapsulated in PacketIn message. So there is a method of adding CONTROLLER port to out port list.

Assuming that you are using simple_switch_13.py as your controller. Out port list is defined here:

https://github.com/faucetsdn/ryu/blob/d6cda4f427ff8de82b94c58aa826824a106014c2/ryu/app/simple_switch_13.py#L101

You can change it to

actions = [
    parser.OFPActionOutput(out_port),
    parser.OFPActionOutput(ofproto.OFPP_CONTROLLER),
]

But there is also a PROBLEM that you have to mark this packet as HAVE_BEEN_READ in original packet, rather than OpenFLow Protocol header. Otherwise, the switch will trap into the infinity loop. If you do not understand, take this scenario into consideration:

One packet come in and no rule matches.

  1. switch encapsulates packet in PacketIn (or use buffer_id) and send to controller
  2. controller adds aforementioned rules to switch
  3. switch execute all actions: send this packet to out_port and CONTROLLER port

If you do not mark this packet as HAVE_BEEN_READ in original packet, the same packet will be send to controller again, step 2 will be executed again, and step 3, and trap into an infinity loop. There must be some methods to deal with is problem, but I do not know how to (and like it, because you modify the original packet).

Method 2: Mirror port data and send to a monitor app (recommend)

To monitor real-time data, I recommend to use dedicated server rather than controller.

For example, if you want to monitor flow of one switch, you can add a host, in which a monitor application like sFlow (not verified, google it yourself) is running, to this switch. Then you can add an extra out port like method 1.

What? You do not know the port_no? You can hard-code port number in Mininet (if you use that when building topology), and you can use LLDP to observer links (maybe a little complex, but you can google that too).

And the remaining works is communication between controller and monitor apps (RPC or RESTful api? if they provide)

One more thing

Controller plane is designed to decide how to forward packet, rather than monitor each packet. Otherwise, why not use traditional switch with port mirror and firewall, or internal monitor in switch?

If you do not need packet content, you can use counters defined in OpenFlow Protocol, they can give you some statistics.

I hope my reply can help you.

faniAhmed commented 4 weeks ago

Thanks for lots of detail, I understand the working of the controller. But needed this functionality for a specific project.