Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flow_action_t output_intf_del() not deleting interfaces when called #19

Open
edwin-mejia opened this issue Sep 21, 2016 · 2 comments
Open

Comments

@edwin-mejia
Copy link

I've been working on manipulating the group of interfaces attached to a directflow "action" in order to have one matched input send flows to multiple output interfaces. As part of this, I wanted to remove interfaces that exist on other matched inputs so that the output interfaces are only receiving one flow at a time.

Below is the code that I was hoping to use (with some tracer messages for debugging) which uses the output_intf_del() method on a flow_action_t. The flow_action_t is pulled from the action() method on a flow that comes from the flow_entry_iter() within the directflowMgr.

Even after trying to pass output_intf_del() an eossdk.InftId() with the proper name and just a string with the interface's name, it still won't get rid of it in the "action." To solve this, I just created a new action that I passed into flow_entry_set() which updated the existing flow with one less output interface.

If you have any advice for using output_intf_del() it would be greatly appreciated, but if it's just a bug then exposing it for a future fix works too. :)

Thanks a lot for the help and please see below for the code, runtime, and my "fix."

Original code with tracer messages:

When this method is called, we pass it these parameters:

self._removeIdenticalIntf(eossdk.IntfId("Ethernet" + str(destPort)), self.directflowMgr.flow_entry_iter())

def _removeIdenticalIntf(self, intf, flowIter):
      self.tracer.trace7("Called removeIdenticalIntf")
      for flow in flowIter:
         intfs = list(flow.action().output_intfs())
         if intf in intfs:
            self.tracer.trace7("Before: " + repr(flow.action().output_intfs()[0].to_string()))
            self.tracer.trace7("To del: " + repr(intf.to_string()))
            flow.action().output_intf_del(intf)
            self.tracer.trace7("After: " + repr(flow.action().output_intfs()[0].to_string()))
            self.tracer.trace7("Supposedly deleted from intf list")

Runtime:
(Notice the Before:, to del:, & After:)

2016-09-21 21:24:55.644112 2902 AristaRouterAgent 7 on_readable called
2016-09-21 21:24:55.644284 2902 AristaRouterAgent 6 Accepting connection
2016-09-21 21:24:55.644594 2902 AristaRouterAgent 7 on_readable called
2016-09-21 21:24:55.644736 2902 AristaRouterAgent 7 Client said: '\x00\x00\x00\x0c\x00\x00\x00\x01\x00\x00\x00$\x00\x00\x00P\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x04'
2016-09-21 21:24:55.644834 2902 AristaRouterAgent 7 data exists
2016-09-21 21:24:55.644932 2902 AristaRouterAgent 6 command 0x50: 7 to 4
2016-09-21 21:24:55.645131 2902 AristaRouterAgent 7 Called removeIdenticalIntf
2016-09-21 21:24:55.645430 2902 AristaRouterAgent 7 Before: 'Ethernet2'
2016-09-21 21:24:55.645508 2902 AristaRouterAgent 7 To del: 'Ethernet2'
2016-09-21 21:24:55.645613 2902 AristaRouterAgent 7 After: 'Ethernet2'
2016-09-21 21:24:55.645731 2902 AristaRouterAgent 7 Supposedly deleted from intf list

2016-09-21 21:24:55.646588 2902 AristaRouterAgent 5 Routed source 7 to dest 4
2016-09-21 21:24:55.647046 2902 AristaRouterAgent 7 on_readable called
2016-09-21 21:24:55.647153 2902 AristaRouterAgent 7 Client said: ''
2016-09-21 21:24:55.647227 2902 AristaRouterAgent 7 data does not exist
2016-09-21 21:24:55.647308 2902 AristaRouterAgent 7 Ending connection to socket 11

Fix by creating new action to update:

def _removeIdenticalIntf(self, intf, flowIter):   
      for flow in flowIter:
         intfs = list(flow.action().output_intfs())
         if intf in intfs:

            intfs.remove(intf)

            name = flow.name()
            action = createAction(outputIntfs = intfs)
            match = flow.match()
            priority = 100

            entry = eossdk.FlowEntry(name, match, action, priority)
            self.directflowMgr.flow_entry_set(entry)`
@rmadsen
Copy link
Contributor

rmadsen commented Sep 22, 2016

Hi edmejia93,

Thanks for the nice write-up with code examples. There are a couple things going on here. First, the SDK uses value-type semantics for types. That means that changing an attribute on one of these classes doesn't actually change the underlying collection in Sysdb (as your example shows, you have to re-set the flow entry after editing it). We could look into adding a new method on the Directflow Manager to directly edit the action of a flow, but the general rule across the SDK is after editing a value, you need to re-set it.

Another issue is that when you access nested class types, we return const & references. In Python this means that accessing something like flow.action() actually returns a full copy of the action—not a pointer to the action in the flow. Thus,

intf1 = flow.action().output_intfs()[0]
flow.action().output_intf_del(intf) // operating on a copy of action!
intf2 = flow.action().output_intfs()[0]
// so intf1 == intf2!

Now if the SDK exposed setters on the Flow Entry type, we could do the following to have the correct behavior:

      for flow in flowIter:
            action = flow.action()
            action.output_intf_del(intf) # edit the copy of the action
            flow.action_is(action) # update the action attribute of the top level flow
            self.directflowMgr.flow_entry_set(flow) # and set it in Sysdb!

This would save you from having to re-read the name, priority and match when duplicating the flow. We'll look into adding the action_is setter to the Flow Entry type.

@edwin-mejia
Copy link
Author

rmadsen,

Great! Thanks a lot for the info and clarification. The speedy response is also appreciated.

Best,
Edwin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants