kytos-ng / flow_manager

Kytos NApp that manages OpenFlow 1.3 entries

Home Page:https://kytos-ng.github.io/api/flow_manager.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

bug: `log.info` `OSError: [Errno 90] Message too long` if a huge flows payload is sent

viniarck opened this issue · comments

For convenience/debugging/e2e logs historically we decided that log.info including the flows would be helpful, but since currently we don't validate how long the flows list can be, then it can produce a massive log entry which in turn can result in OSError:

https://github.com/kytos-ng/flow_manager/blob/master/main.py#L624-L625
https://github.com/kytos-ng/flow_manager/blob/master/main.py#L563-L564

How can we solve this?

1 - We could start limiting how large the flow list can be, and then return 400 asking for the client to further break it down.
2 - We can introduce a new helper function responsible for reducing flows_dict["flows"] slice up to 200 flows or so at most, which is already plenty.

Option 1 is the one we'll go long term, but that would break the API, so let's only address with option 2 for now, and then in the future we can reassess again the limit we'll put here. In the meantime, this issue can also serve as documentation if anyone hits this, also ideally, as most clients who send a significant number of flows, it's advisable to batch the flows.

@Alopalao can you add this one to your radar and implement option 2?

How to reproduce

  • If you send 5000 flows in the same payload via events for instance:
from kytos.core.events import KytosEvent

dpid = "00:00:00:00:00:00:00:01"


def create_flows(dpid: str, n: int) -> dict[list]:
    """docstring."""
    flows = [
        {
            "priority": i,
            "match": {"in_port": 1, "dl_vlan": i},
            "actions": [{"action_type": "output", "port": 2}],
        }
        for i in range(1, n + 1)
    ]
    return {"flow_dict": {"flows": flows}, "dpid": dpid}


data = create_flows(dpid, 5000)
ev = KytosEvent("kytos.flow_manager.flows.install", content=data)
controller.buffers.app.put(ev)
Traceback (most recent call last):
  File "/usr/lib/python3.9/logging/handlers.py", line 982, in emit
    self.socket.send(msg)
OSError: [Errno 90] Message too long
Call stack:
  File "/usr/lib/python3.9/threading.py", line 937, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib/python3.9/threading.py", line 980, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.9/threading.py", line 917, in run
    self._target(*self._args, **self._kwargs)