(I understand that nox-classic is no longer maintained. However, if pox is using some of the same methodology, maybe this issue still exists.)

I believe install_datapath_flow as implemented in nox has a design flaw...

When a PACKET_IN message occurs from the switch to the controller, it may have a buffer_id and some (or all) of the data of the packet in the buffer. It is my experience that if the full packet is in the buffer, the buffer_id is -1 (in Python, UINT32MAX). The important thing is that sometimes you get a pointer and no full packet; or you get a full packet and no pointer. Install_datapath_flow may behave differently when you pass that information back to the switch.

Suppose you have some action to apply to the packet, more than just outputting it to a port. For the purposes of this discussion, we'll assume the action is to rewrite just the source ethernet address.

There are four ways that install_datapath_flow might be passed buffer information: Buffer is valid, and buffer_id = UINT32MAX (ie, -1) The buffer parameter contains the packet info to be sent out Buffer is None, and buffer_id is a valid buffer_id. The buffer_id parameter is passed back to the switch; the switch uses that information as the packet. Buffer is None and buffer_id = UINT32MAX. No packet is sent when this flow rule is installed Buffer is valid, and buffer_id is valid. I didn't check to see what it does. IMHO, this should be an error.

If there is a valid buffer_id, that id is passed to the switch in the flow mod command. The switch will then apply the actions to the packet stored at that buffer_id, as per the OpenFlow 1.0 spec:
5.3.3 Modify State Messages
struct ofp_flow_mod {
....
uint32_t buffer_id; /* Buffered packet to apply to (or -1).
Likewise, if a buffer_id or a buffer is passed with the to OpenFlow's OFP_Packet_Out message, the actions are applied to the packet.

I would have expected that install_datapath_flow behaved in the same way: it doesn't matter whether you pass the packet as a buffer_id or as a buffer, the actions are applied to the packet.

But that is not so. install_datapath_flow intentionally avoids passing the full set of actions to send_openflow_packet, and raises an error if any actions are not simply an output.
        if buffer_id == UINT32_MAX and packet != None:
            for action in actions:
                if action[0] == openflow.OFPAT_OUTPUT:
                    if type(action[1]) == int or type(action[1]) == long:
self.send_openflow_packet(dp_id, packet, action[1], inport)
                    else:
self.send_openflow_packet(dp_id, packet, action[1][1], inport)
                else:
                    raise NotImplementedError
So, the user of install_datapath_flow that doesn't have a buffer_id has to either apply the actions to the packet himself, or call send_openflow_packet with the full set of actions and call install_datapath_flow with buffer = None.

-----------
A hypothesis I have (but have not confirmed): On the HP ProCurve, for Packet In messages, if you indicate enough bytes are to be sent to the controller so that the entire packet is passed, the switch passes the buffer, and not the buffer-id (ie, it is -1); the buffer on the switch can be flushed. If you have fewer bytes sent than is sufficient to include the whole packet, the packet is buffered and you get the buffer-id.

There is a work-around: If you get a valid buffer_id, use install_datapath_flow. If you get a buffer, use install_datapath_flow with no buffer, and call send_openflow_packet on your own.





Reply via email to