noxrepo / pox

The POX network software platform
https://noxrepo.github.io/pox-doc/html/
Apache License 2.0
624 stars 471 forks source link

Mirroring ipv4 traffic using l2_multi #196

Open fredericoschardong opened 6 years ago

fredericoschardong commented 6 years ago

Hi,

I have a circular topology which is finely handled by l2_multi. I am trying to update it to mirror all the traffic targeting 10.0.6.2 to 10.0.5.3, which is in a different switch. I created a simple dictionary that maps ipv4 -> ethaddr, then I try to call install_path using the ethaddr and port of 10.0.5.3 with the following code:

if packet.dst.is_multicast:
  log.debug("Flood multicast from %s", packet.src)
  flood()
else:
  if packet.dst not in mac_map:
    log.debug("%s unknown -- flooding" % (packet.dst,))
    flood()
  else:
    dest = mac_map[packet.dst]
    match = of.ofp_match.from_packet(packet)
    self.install_path(dest[0], dest[1], match, event)

    if type(packet.payload) == ipv4 and packet.payload.dstip.toStr() == '10.0.6.2' and '10.0.5.3' in ipv4_map:
      dest = mac_map[ipv4_map['10.0.5.3']]

      from pox.lib.addresses import IPAddr
      match.nw_dst = IPAddr('10.0.5.3')
      match.dl_dst = ipv4_map['10.0.5.3']

      self.install_path(dest[0], dest[1], match, event)

Then I changed the _install method, setting msg.buffer_id = 0xFFFFFFFF to avoid the OFPBRC_BUFFER_EMPTY problem I have introduced, but it didn't work as I still get the same error when my changes are triggered. Can you please point me in the right direction? I am making those changes on top of the eel branch. Thanks!

MurphyMc commented 6 years ago

First off, on a circular topology, l2_multi probably still has problems unless you're also running the spanning tree module to handle the multicast traffic (e.g., ARP). Are you doing that? Without it, I think you'll see multicast traffic getting caught in the loop that is your topology which might cause a bunch of buffer empty errors (I'd have to look at the code to remind myself and at recent changes to OVS to be sure).

As to your mirroring code... this looks wrong to me. You're adjusting the nw_dst and dl_dst, but that's what the switch is trying to match. What you want is to change where it's destined.

The best way to do this probably depends on a number of things.

I think the most generic is that... you want to take the packets to be mirrored and encapsulate them in a packet going to 10.0.5.3. OpenFlow itself (at least up through like 1.3?) doesn't have this sort of capability. But things like Open vSwitch do, by creating virtual ports which do encapsulation. These need to be configured outside of OpenFlow (they're OVS-specific and can be done via OVS commandline tools or ovsdb). You could also do some sort of "hacky encapsulation", where you actually change the destination IP address, but store the original IP address in the src MAC field or something, and have the mirror-receiver specifically look for that. I think you'll probably find that Mininet won't work very well with this type of scenario (if you're using Mininet).

A completely different way would be to just change what's installed when you're installing paths for 10.0.6.2. Instead of installing a single shortest path from wherever to 10.0.6.2, compute a tree which ends up at both 10.0.6.2 and 10.0.5.3, and install that instead. So one of the actual table entries you install should have two output actions.