[pox-dev] Redirect "ofp_packet_in" packet among multiple controllers in POX?

夏瑞 xiarui0428 at 163.com
Wed Jun 13 08:22:33 PDT 2018


I'm trying to modify the source code of POX to realize my idea.


I find that the "ofnexus" is the key module for processing an event, like "Packet_In". This is the code snippet in "pox/openflow/of_01.py"
###################################################################
def handle_PACKET_IN (con, msg): #A
  e = con.ofnexus.raiseEventNoErrors(PacketIn, con, msg)
  if e is None or e.halt != True:
    con.raiseEventNoErrors(PacketIn, con, msg)
###################################################################


"con.ofnexus" will trigger my customized "_handle_packet_in". However, this value is "_dummyOFNexus" by default, which is set in "__init__()" function of class "Connection".
###################################################################
class DummyOFNexus (object):
  def raiseEventNoErrors (self, event, *args, **kw):
    log.warning("%s raised on dummy OpenFlow nexus" % event)
  def raiseEvent (self, event, *args, **kw):
    log.warning("%s raised on dummy OpenFlow nexus" % event)
  def _disconnect (self, dpid):
    log.warning("%s disconnected on dummy OpenFlow nexus",
                pox.lib.util.dpidToStr(dpid))


_dummyOFNexus = DummyOFNexus()
###################################################################


The value of "con.ofnexus" is formally set in "handle_request_reply" function:
###################################################################
  nexus = core.OpenFlowConnectionArbiter.getNexus(con)
  if nexus is None:
    # Cancel connection
    con.info("No OpenFlow nexus for " +
             pox.lib.util.dpidToStr(msg.datapath_id))
    con.disconnect()
    return
  con.ofnexus = nexus
  con.ofnexus._connect(con)
###################################################################


So I come up with an idea, I manually set the value of "con.ofnexus". In this way, customized "_handle_packet_in" will be triggered:
###################################################################
def handle_PACKET_IN (con, msg): #A
  if con.ofnexus is _dummyOFNexus:
    con.ofnexus = core.OpenFlowConnectionArbiter.getNexus(con)
  e = con.ofnexus.raiseEventNoErrors(PacketIn, con, msg)
  if e is None or e.halt != True:
    con.raiseEventNoErrors(PacketIn, con, msg)
################################################################### 


I was wondering if there are some underlying bugs in my modification.  Any comments or suggestions are welcomed. Thank you for sharing.


Best wishes.
Xia



At 2018-06-13 13:30:35, "夏瑞" <xiarui0428 at 163.com> wrote:

Hello, 
I am trying to redirect `ofp_packet_in` packet among multiple controllers. For example, suppose there are two controllers `c1,c2` and one switch `s1`. `s1` is assigned to `c1`. Now, `c1` receives a `Packet_In` from switch `s1`. Generally, `s1` should dispose of this `Packet_In`. **What I am trying to do is to send this `Packet_In` to `c2` and let `c2` process this `Packet_In`**.


I am trying to implement my idea by POX, but I got some mistakes.


This is the code of `c1`, only `_handle_packet_in` is shown:


##################################################################
    def _handle_PacketIn(self, event):
        log.debug("Switch %s has a PacketIn: [port: %d, ...]", event.dpid, event.port)
        self._redirect_packet(event)


    def _redirect_packet(self, event):
        log.debug("Send packet to 6634!")
        TCP_IP = '10.0.2.15'
        TCP_PORT = 6634
        BUFFER_SIZE = 1024
        packet = event.ofp
        # I attach all the payload of OpenFlow Packet_In to the new packet
        MESSAGE = packet.pack() 
        # MESSAGE = MESSAGE + 'Hello world'


        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((TCP_IP, TCP_PORT))
        s.send(MESSAGE)
        # s.close()
#################################################################
Then I start Mininet and build the topology. (Here the topology has little difference with the formal description, however, it is clear and modified from Mininet example controllers2.py)
#################################################################
    from mininet.net import Mininet
    from mininet.node import Controller, OVSSwitch
    from mininet.cli import CLI
    from mininet.log import setLogLevel
    from mininet.node import RemoteController
    
    def multiControllerNet():
        "Create a network from semi-scratch with multiple controllers."
    
        net = Mininet( controller=Controller, switch=OVSSwitch, autoSetMacs=True )
    
        print "*** Creating (reference) controllers"
        # c1 = net.addController( 'c1', port=6633 )
        # c2 = net.addController( 'c2', port=6634 )
        c1 = net.addController('c1', controller=RemoteController, ip='10.0.2.15', port=6633)
        c2 = net.addController('c2', controller=RemoteController, ip='10.0.2.15', port=6634)
    
        print "*** Creating switches"
        s1 = net.addSwitch( 's1' )
        s2 = net.addSwitch( 's2' )
    
        print "*** Creating hosts"
        hosts1 = [ net.addHost( 'h%d' % n ) for n in 3, 4 ]
        hosts2 = [ net.addHost( 'h%d' % n ) for n in 5, 6 ]
    
        print "*** Creating links"
        for h in hosts1:
            net.addLink( s1, h )
        for h in hosts2:
            net.addLink( s2, h )
        net.addLink( s1, s2 )
    
        print "*** Starting network"
        net.build()
        # c1.start()
        c2.start()
        s1.start( [ c1 ] )
        # s1.start([c2])
        s2.start( [ c2 ] )
        # s2.start([c2])
    
        # print "*** Testing network"
        # net.pingAll()
    
        print "*** Running CLI"
        CLI( net )
    
        print "*** Stopping network"
        net.stop()
    
    if __name__ == '__main__':
        setLogLevel( 'info' )  # for CLI output
        multiControllerNet()
#################################################################
Then, I start two controllers at my host with different ports, `6633, 6634`. Open `c1`:
```
../pox.py openflow.of_01 --port=6633 --address=10.0.2.15 openflow_test log.level --DEBUG
```
and, open `c2`
```
../pox.py openflow.of_01 --port=6634 --address=10.0.2.15 openflow_test_2 log.level --DEBUG
```


`c1` has only the `_handle_packet_in` handler which is shown above. `c2` has no function.


I try to `ping` between `h3` (controlled by `c1`) to `h5` (controller by `c2`), in order to trigger `_handle_packet_in` handler.


I use Wireshark to capture the `of_packet_in` packet, and the new **redirect** packet. It is clear that they have the same payload (OpenFlow packet).


However, `c2` doesn't accept this packet, and warn that this is dummy OpenFlowNexus. This is the error:
###################################################
WARNING:openflow.of_01:<class 'pox.openflow.PacketIn'> raised on dummy OpenFlow nexus
INFO:openflow.of_01:[None 8] closed
###################################################


I guess, even if `c1` sends a **legal** OpenFlow `of_packet_in` to `c2`, `c2` has no idea about **"who is `c1`"**, for `c1` has **not** registered to `c1` using OpenFlow `of_hello`, `of_features_request`,.... Therefore, `c2` discard the OpenFlow `of_packet_in` sent by `c1`, and say **dummy**.


I only want to let `c2` process the `Packet_In` redirected by `c1`. In this way, `c2` can calculate and install table entries for `table-miss` event happened in `s1`.


Maybe I can use other controllers, like floodlight, ONOS..., to solve this problem. Maybe this problem cannot be solved. Thank you for sharing your idea, best wishes.


I am using POX 0.2.0 (carp)


Best wishes,
Xia




 





 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.noxrepo.org/pipermail/pox-dev-noxrepo.org/attachments/20180613/80887330/attachment-0002.html>


More information about the pox-dev mailing list