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 6 forks source link

Delete flows by cookie and cookie_mask is not working #129

Closed italovalcy closed 1 year ago

italovalcy commented 1 year ago

Hi,

I'm trying to delete all flows matching the cookie id and mask based on: 0xaa00000000000000/0xff00000000000000 (which should delete all flows created by mef_eline), but it does not seem to be working this way.

Steps to reproduce:

  1. Run Kytos (all enabled) and mininet (linear topology with 10 switches)
  2. Create a EVC with dynamic path
    curl -d '{"name": "my evc1", "dynamic_backup_path": true, "enabled": true, "uni_z": {"tag": {"value": 100, "tag_type": 1}, "interface_id": "00:00:00:00:00:00:00:0a:1"}, "uni_a": {"tag": {"value": 100, "tag_type": 1}, "interface_id": "00:00:00:00:00:00:00:01:1"}}' -H 'Content-type: application/json' -X POST http://127.0.0.1:8181/api/kytos/mef_eline/v2/evc
  3. Then remove the flows from switch 05 and list how flow_manager is storing the flows versus the switch 5 OVS OF table:
    
    # curl -X DELETE http://localhost:8181/api/kytos/flow_manager/v2/flows/00:00:00:00:00:00:00:05 -d '{"flows": [{"cookie": 12249790986447749120, "cookie_mask": 18374686479671623680}]}' -H 'Content-type: application/json'
    {"response":"FlowMod Messages Sent"}

sleep 10

curl -s "http://localhost:8181/api/kytos/flow_manager/v2/stored_flows?dpid=00:00:00:00:00:00:00:05&state=installed" | jq -r '.[][]|tostring'

{"flow":{"actions":[{"action_type":"set_vlan","vlan_id":1528},{"action_type":"output","port":3}],"cookie":12308634254196490000,"hard_timeout":0,"idle_timeout":0,"match":{"dl_vlan":3242,"in_port":2},"priority":20000,"table_id":0},"flow_id":"a4b6342a739463a7bca3d86e2efc1988","id":"678666a011a8f396ec479973e669e9c3","inserted_at":"2022-12-22T14:32:31","state":"installed","switch":"00:00:00:00:00:00:00:05","updated_at":"2022-12-22T14:32:32"} {"flow":{"actions":[{"action_type":"set_vlan","vlan_id":3242},{"action_type":"output","port":2}],"cookie":12308634254196490000,"hard_timeout":0,"idle_timeout":0,"match":{"dl_vlan":1528,"in_port":3},"priority":20000,"table_id":0},"flow_id":"e14c479a52f77fbe008e0a95e3c9bec1","id":"1239588f089f5251626600dd7461c948","inserted_at":"2022-12-22T14:32:31","state":"installed","switch":"00:00:00:00:00:00:00:05","updated_at":"2022-12-22T14:32:32"} {"flow":{"actions":[{"action_type":"output","port":4294967293}],"cookie":12321848580485677000,"hard_timeout":0,"idle_timeout":0,"match":{"dl_type":35020,"dl_vlan":3799},"priority":1000,"table_id":0},"flow_id":"3c9a04abef974e9ed67d17fe40cdd8c1","id":"8b1f00ef955221fe5e460064723a606c","inserted_at":"2022-12-22T13:40:38","state":"installed","switch":"00:00:00:00:00:00:00:05","updated_at":"2022-12-22T14:32:30"} {"flow":{"actions":[{"action_type":"output","port":4294967293}],"cookie":12393906174523605000,"hard_timeout":0,"idle_timeout":0,"match":{"dl_src":"ee:ee:ee:ee:ee:04"},"priority":50000,"table_id":0},"flow_id":"bb33916122e5d80bd09c65a0635e1372","id":"161584f4dbe43aeb6063d2360a08a901","inserted_at":"2022-12-22T13:40:40","state":"installed","switch":"00:00:00:00:00:00:00:05","updated_at":"2022-12-22T14:32:30"} {"flow":{"actions":[{"action_type":"output","port":4294967293}],"cookie":12393906174523605000,"hard_timeout":0,"idle_timeout":0,"match":{"dl_src":"ee:ee:ee:ee:ee:06"},"priority":50000,"table_id":0},"flow_id":"cd34704bf69dd8b6e390d3b805ce94a4","id":"fd2f4b2fd3411f9b4338169a4ce65a0f","inserted_at":"2022-12-22T13:40:40","state":"installed","switch":"00:00:00:00:00:00:00:05","updated_at":"2022-12-22T14:32:30"}

ovs-ofctl dump-flows s5

cookie=0xac00000000000005, duration=1050.227s, table=0, n_packets=0, n_bytes=0, priority=50000,dl_src=ee:ee:ee:ee:ee:04 actions=CONTROLLER:65535 cookie=0xac00000000000005, duration=1050.225s, table=0, n_packets=0, n_bytes=0, priority=50000,dl_src=ee:ee:ee:ee:ee:06 actions=CONTROLLER:65535 cookie=0xab00000000000005, duration=1050.280s, table=0, n_packets=682, n_bytes=28644, priority=1000,dl_vlan=3799,dl_type=0x88cc actions=CONTROLLER:65535


It looks like the way we are [getting the flows from DB](https://github.com/kytos-ng/flow_manager/blob/530547390bcc19eb2281f0e4744c8e99726390c5/main.py#L432-L439) does not consider the mask properly:

kytos $> value = {'cookie': 12249790986447749120, 'cookie_mask': 18374686479671623680}

kytos $> cookies = list({int(value.get("cookie", 0)) & int(value.get("cookie_mask", 0))})

kytos $> cookies Out[6]: [12249790986447749120]

kytos $> switches = ['00:00:00:00:00:00:00:05']

kytos $> for dpid, stored_flows in controller.napps[('kytos', 'flow_manager')].flow_controller.get_flows_by_cookies(switches, cookies).items(): ...: print(dpid, stored_flows) ...:

kytos $>

viniarck commented 1 year ago

@italovalcy, thanks for reporting this, good catch.

Yes, looking into the code, the optimization to minimize round trips that I implemented, back fired for deletions with cookie_mask != all 1's. Currently, the get_flows_by_cookies(dpids, cookies) method that i's querying with the $in operator only exact matches in the list will work (so cookie_mask all 1's).

I won't be able to fix it today since I'll be hitting the road shortly, but if anyone wants to take a stab at this issue:

1 - The easiest but not always optimal solution would be to if any of the flows_dict has a cookie_mask diff than all 1's, then only query for the dpids, but don't filter for cookies in the DB, and let the match_flows during the runtime to try to match individually. 2 - The optimal solution would be partition all cookie values that with their range low and high values, and query for the intervals with $gte and $lte with $or operator as well.

The current workaround would to be to send multiple deletion requests with cookie_mask all 1's until this is fixed, and the caller needs to iterate on the stored_flows to know all the cookies that should be removed.