kytos-ng / flow_manager

Kytos NApp that manages OpenFlow 1.3 entries
https://kytos-ng.github.io/api/flow_manager.html
MIT License
0 stars 7 forks source link

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

Closed viniarck closed 1 year ago

viniarck commented 1 year ago

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

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)