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

Murphy McCauley murphy.mccauley at gmail.com
Sun Jun 17 03:27:51 PDT 2018


It sounds like you're on to a solution, but here are some other thoughts...

1) Depending on what kind of switch you're using and exactly how your
controllers are supposed to work... it may be possible to just have the
switch connect to multiple controllers (and have the controllers behave
differently) rather than have one controller connect to another.

2) You're having the first controller send the redirected packet-in to the
second controller's normal OpenFlow-listening-port.  Which, as you found,
is problematic.  Because the second controller is expecting a switch to
connect which does some handshaking which you're not doing.  Why not just
have the second controller like... open a socket and listen on it?  Why
have it go through the normal OpenFlow processing stuff at all?  You could
use POX's messenger component for this (though it's not ideal for this use
case).  Or you should be able to use the ioworker stuff to open a socket
and listen easily.  Or you could just write it by hand.  Or you could just
send the packet-in data between controller using some Python RPC library
(RPyC would probably work).

3) Again, this doesn't seem necessary, but you could have controller 1 act
like a proper OpenFlow switch which just happens to only send packet-in
messages.  The datapaths.switch.SoftwareSwitchBase class will maintain a
connection to a controller.  Create a subclass of it in controller 1 (you
actually may not even need to subclass it!) and have it send the packet-ins
to controller 2 using its .send() method.  This is probably overkill,
even.  You could probably just hardcode enough of the handshake into
controller 1.  (But using SoftwareSwitchBase seems like it'd be really easy
with no particular downside?)

As a sidenote, carp is like 5 years out of date.  eel has updates like six
months ago.  fangtooth (in my fork) has updates last month.

Good luck.

-- Murphy

On Wed, Jun 13, 2018 at 8:22 AM, 夏瑞 <xiarui0428 at 163.com> wrote:

> 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
>
>
>
>
>
>
>
>
>
> 【网易自营|30天无忧退货】爱上书写:施华洛世奇制造商星空原色水晶笔,限时仅29元>>
> <http://you.163.com/item/detail?id=1092001&from=web_gg_mail_jiaobiao_7>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.noxrepo.org/pipermail/pox-dev-noxrepo.org/attachments/20180617/7a93b75b/attachment-0002.html>


More information about the pox-dev mailing list