Hi guys,

I'm having problems receiving ofp_stats_reply messages and similarly other
controller-to-switch reply message such as switch configuration replies.  I
am running a simulated network on mininet and the controller to switch part
of the message works fine as I can modify flows and create a functioning
network.  I can see the ofp_stats_requests and ofp_stats_reply in wireshark
so they are being generated however the switches appear to be sending the
reply to the local connection 127.0.0.1 instead of back out the port
it received the message from hence the POX controller does not receive the
reply.  Is there an initial switch configuration message I'm forgetting to
send or can you guys shed any other light on the problem?



Here is the function that creates the of_stats_request message:

def _handle_ConnectionUp (self, event):
    info_getter(event.connection)
    bd = of.ofp_port_stats_request( port_no = OFPP_NONE )
    pm = of.ofp_stats_request( type=OFPST_PORT, body=bd )
    event.connection.send(pm)


Here is the function that should be receiving replies however it only
ever receives packet.types of LLDP

def _handle_PacketIn (self, event):
    packet = event.parsed
    print event, packet, packet.type







I've included the full code which contains both functions below, it is
modified from spanning_tree.py as found in the Betta build:

# Copyright 2012 James McCauley
#
# This file is part of POX.
#
# POX is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# lub
# POX is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with POX.  If not, see <http://www.gnu.org/licenses/>.

from pox.core import core
import pox                                        ### CHANGED
from pox.lib.packet.ethernet import ethernet
from pox.lib.packet.ipv4 import ipv4
from pox.lib.packet.arp import arp

import pox.openflow.libopenflow_01 as of
from pox.lib.revent import *
from collections import defaultdict
from pox.openflow.discovery import Discovery
from pox.lib.util import dpidToStr
from pox.lib.util import str_to_bool
import time
from pox.lib.recoco               import Timer
from pox.lib.packet.ethernet      import LLDP_MULTICAST, NDP_MULTICAST
from pox.lib.packet.ethernet      import ethernet
from pox.lib.packet.lldp          import lldp, chassis_id, port_id, end_tlv
from pox.lib.packet.lldp          import ttl, system_description
import struct
import array
import socket
import copy
from collections import *

log = core.getLogger()
adj = defaultdict(lambda:defaultdict(lambda:[]))
_flood_delay = 5
TIMEOUT_CHECK_PERIOD = 5.0

def _calc_spanning_tree ():
  def flip (link):
    return Discovery.Link(link[2],link[3], link[0],link[1])

  adj.clear()
  switches = set()
  # Add all links and switches
  for l in core.openflow_discovery.adjacency:
    adj[l.dpid1][l.dpid2].append(l)
    switches.add(l.dpid1)
    switches.add(l.dpid2)

  # Cull links -- we want a single symmetric link connecting nodes
  for s1 in switches:
    for s2 in switches:
      if s2 not in adj[s1]:
        continue
      if not isinstance(adj[s1][s2], list):
        continue
      assert s1 is not s2
      good = False
      for l in adj[s1][s2]:
        if flip(l) in core.openflow_discovery.adjacency:
          # This is a good one
          adj[s1][s2] = l.port1
          adj[s2][s1] = l.port2
          good = True
          break
      if not good:
        del adj[s1][s2]
        if s1 in adj[s2]:
          # Delete the other way too
          del adj[s2][s1]

  q = []
  more = set(switches)

  done = set()

  tree = defaultdict(set)

  while True:
    q = list(reversed(sorted(list(more)))) + q
    more.clear()
    if len(q) == 0: break
    v = q.pop(False)
    if v in done: continue
    done.add(v)
    for w,p in adj[v].iteritems():
      if w in tree: continue
      more.add(w)
      tree[v].add((w,p))
      tree[w].add((v,adj[w][v]))

  if False:
    log.debug("*** SPANNING TREE ***")
    for sw,ports in tree.iteritems():
      log.debug((" %i : " % sw) + " ".join([str(l[0]) for l in
                                           sorted(list(ports))]))
    log.debug("*********************")
  log.debug("Spanning tree updated")
  return tree

_prev = defaultdict(lambda : defaultdict(lambda : None))

def _reset (event):
  _prev[event.dpid].clear()

def _handle (event):
  tree = _calc_spanning_tree()

  try:
    change_count = 0
    for sw, ports in tree.iteritems():
      con = core.openflow.getConnection(sw)
      print con
      if con is None: continue # Must have disconnected
      tree_ports = [p[1] for p in ports]
      for p in con.features.ports:
        if p.port_no < of.OFPP_MAX:
          flood = p.port_no in tree_ports
          if not flood:
            if not core.openflow_discovery.isSwitchOnlyPort(sw, p.port_no):
              flood = True
          if _prev[sw][p.port_no] is flood:
            continue # Skip
          change_count += 1
          _prev[sw][p.port_no] = flood

          pm = of.ofp_port_mod( port_no=p.port_no,
                               hw_addr=p.hw_addr,
                               config = 0 if flood else of.OFPPC_NO_FLOOD,
                               mask = of.OFPPC_NO_FLOOD )
          con.send(pm)
    if change_count:
      log.info("%i ports changed", change_count)

  except:
    _prev.clear()
    log.exception("Couldn't push spanning tree")

  ttt = False
  for swsw in _prev:
    p_count = 0
    for ppp in _prev[swsw]:
      if _prev[swsw][ppp] == True:
        p_count += 1
        host_or_not = True
        for swswswsw in adj[swsw]:
          if  adj[swsw][swswswsw] == ppp:
            host_or_not = False

    if p_count < 2:
      for pppp in _prev[swsw]:
        _prev[swsw][pppp] = ttt
        for swswsw in adj[swsw]:
          if adj[swsw][swswsw] == pppp:
            ppppp = adj[swswsw][swsw]
            _prev[swswsw][ppppp] = ttt
            con = core.openflow.getConnection(swswsw)
            for q in con.features.ports:
              if q.port_no == ppppp:
                pm = of.ofp_port_mod( port_no=q.port_no,
                               hw_addr=q.hw_addr,
                               config =  of.OFPPC_NO_FLOOD,
                               mask = of.OFPPC_NO_FLOOD )
                con.send(pm)

        con = core.openflow.getConnection(swsw)
        if con is None:
          continue
        for q in con.features.ports:
          if q.port_no == pppp:
            pm = of.ofp_port_mod( port_no=q.port_no,
                               hw_addr=q.hw_addr,
                               config =  of.OFPPC_NO_FLOOD,
                               mask = of.OFPPC_NO_FLOOD )
            con.send(pm)


class info_getter (object):

  def __init__(self, connection):
    self.connection = connection
    connection.addListeners(self)

  def _handle_PacketIn (self, event):
    packet = event.parsed
    print event, packet, packet.type
    if packet.type is not OFPST_PORT: return
    print ' 33 33 33 33 33 '
    if packet.type is not of.ofp_stats_reply: return
    print ' 11 11 11 11 11 '
    if packet.ofp_stats_reply.type is not OFPST_PORT: return
    print ' 22 22 22 22 22 '




class Networker (object):

  def __init__(self):
    core.openflow.addListeners(self)
    self.lemon = 8

  def _handle_ConnectionUp (self, event):
    info_getter(event.connection)
    bd = of.ofp_port_stats_request( port_no = OFPP_NONE )
    pm = of.ofp_stats_request( type=OFPST_PORT, body=bd )
    event.connection.send(pm)
    #pm = of.ofp_stats_request( type=OFPST_DESC )
    #event.connection.send(pm)

  def _handle_PacketIn(self, event):
    print ' Yup Im being called '
    packet = event.parsed
    print packet
    if packet.type is OFPST_DESC:
      print ' OFPST_DESC '
      print packet
    if packet.type is not OFPST_PORT: return
    print ' 33 33 44 33 33 '
    if packet.type is not of.ofp_stats_reply: return
    print ' 11 11 44 11 11 '
    if packet.ofp_stats_reply.type is not OFPST_PORT: return
    print ' 22 22 44 22 22 '

def launch ():
  def start_spanning_tree ():
    core.openflow.addListenerByName("ConnectionUp", _reset)
    core.openflow_discovery.addListenerByName("LinkEvent", _handle)
    core.registerNew(Networker)
    log.debug("Spanning tree component ready")
  core.call_when_ready(start_spanning_tree, "openflow_discovery")


OFPST_DESC = 0
OFPST_FLOW = 1
OFPST_AGGREGATE = 2
OFPST_TABLE = 3
OFPST_PORT = 4
OFPST_QUEUE = 5
OFPST_VENDOR = 0xffff

OFPP_MAX = 0xff00
OFPP_IN_PORT = 0xfff8
OFPP_TABLE = 0xfff9
OFPP_NORMAL = 0xfffa
OFPP_FLOOD = 0xfffb
OFPP_ALL = 0xfffc
OFPP_CONTROLLER = 0xfffd
OFPP_LOCAL = 0xfffe
OFPP_NONE = 0xffff

Reply via email to