Hi I add --observe-hosts option to ryu-manager
Here is new patch Signed-off-by: Takeshi <[email protected]> --- ryu/topology/api.py | 7 +++++ ryu/topology/event.py | 23 ++++++++++++++++ ryu/topology/switches.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/ryu/topology/api.py b/ryu/topology/api.py index 7485a8e..aa8a09f 100644 --- a/ryu/topology/api.py +++ b/ryu/topology/api.py @@ -34,5 +34,12 @@ def get_link(app, dpid=None): def get_all_link(app): return get_link(app) +def get_host(app, dpid=None): + rep = app.send_request(event.EventHostRequest(dpid)) + return rep.hosts + +def get_all_hosts(app): + return get_host(app) + app_manager.require_app('ryu.topology.switches', api_style=True) diff --git a/ryu/topology/event.py b/ryu/topology/event.py index bd87ab0..17fcf94 100644 --- a/ryu/topology/event.py +++ b/ryu/topology/event.py @@ -126,3 +126,26 @@ class EventLinkReply(event.EventReplyBase): def __str__(self): return 'EventLinkReply<dst=%s, dpid=%s, links=%s>' % \ (self.dst, self.dpid, len(self.links)) + + + +class EventHostRequest(event.EventRequestBase): + # If dpid is None, reply all list + def __init__(self, dpid=None): + super(EventHostRequest, self).__init__() + self.dst = 'switches' + self.dpid = dpid + + def __str__(self): + return 'EventHostRequest<dpid=%s>' % \ + (self.dpid) + +class EventHostReply(event.EventReplyBase): + def __init__(self, dst, dpid, hosts): + super(EventHostReply, self).__init__(dst) + self.dpid = dpid + self.hosts = hosts + + def __str__(self): + return 'EventLinkReply<dpid=%s, hosts=%s>' % \ + (self.dpid, self.hosts) diff --git a/ryu/topology/switches.py b/ryu/topology/switches.py index 63335f2..1212c6c 100644 --- a/ryu/topology/switches.py +++ b/ryu/topology/switches.py @@ -46,6 +46,8 @@ CONF = cfg.CONF CONF.register_cli_opts([ cfg.BoolOpt('observe-links', default=False, help='observe link discovery events.'), + cfg.BoolOpt('observe-hosts', default=False, + help='observe host discovery events.'), cfg.BoolOpt('install-lldp-flow', default=True, help='link discovery: explicitly install flow entry ' 'to send lldp packet to controller'), @@ -157,6 +159,34 @@ class Link(object): def __str__(self): return 'Link: %s to %s' % (self.src, self.dst) +class Host(object): + # This is data class passed by EventHostXXXX + def __init__(self, dpid, port, mac): + super(Host, self).__init__() + self.dpid = dpid + self.port = port + self.mac = mac + + def to_dict(self): + d = { + 'dpid': self.dpid, + 'port': self.port, + 'mac': self.mac + } + return d + + def __eq__(self, other): + return self.mac == other.mac + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(self.mac) + + def __str__(self): + return 'Host<Mac address=%s>' % (self.mac, ) + class PortState(dict): # dict: int port_no -> OFPPort port @@ -451,9 +481,12 @@ class Switches(app_manager.RyuApp): self.port_state = {} # datapath_id => ports self.ports = PortDataState() # Port class -> PortData class self.links = LinkState() # Link class -> timestamp + self.hosts = {} self.is_active = True self.link_discovery = self.CONF.observe_links + self.host_discovery = self.CONF.observe_hosts + if self.link_discovery: self.install_flow = self.CONF.install_lldp_flow self.explicit_drop = self.CONF.explicit_drop @@ -681,7 +714,7 @@ class Switches(app_manager.RyuApp): @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def packet_in_handler(self, ev): - if not self.link_discovery: + if not self.link_discovery and not self.host_discovery: return msg = ev.msg @@ -689,7 +722,25 @@ class Switches(app_manager.RyuApp): src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) except LLDPPacket.LLDPUnknownFormat as e: # This handler can receive all the packtes which can be - # not-LLDP packet. Ignore it silently + # not-LLDP packet. + # Check if it's new host + if self.host_discovery: + dpid = msg.datapath.id + port = -1 + + if msg.datapath.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION: + port = msg.in_port + elif msg.datapath.ofproto.OFP_VERSION >= ofproto_v1_2.OFP_VERSION: + port = msg.match['in_port'] + + pkt = packet.Packet(msg.data) + eth = pkt.get_protocols(ethernet.ethernet)[0] + mac = eth.src + + if mac not in self.hosts and port != -1: + LOG.debug('Found host(mac=%s) from dpid=%d, port=%d', mac, dpid, port) + self.hosts[mac] = Host(dpid, port, mac) + return dst_dpid = msg.datapath.id @@ -862,3 +913,19 @@ class Switches(app_manager.RyuApp): links = [link for link in self.links if link.src.dpid == dpid] rep = event.EventLinkReply(req.src, dpid, links) self.reply_to_request(req, rep) + + @set_ev_cls(event.EventHostRequest) + def host_request_handler(self, req): + # LOG.debug(req) + dpid = req.dpid + hosts = [] + + if dpid is None: + hosts = [host for host in self.hosts.itervalues()] + + else: + hosts = [host for host in self.hosts.itervalues() if host.dpid == dpid] + + rep = event.EventHostReply(req.src, dpid, hosts) + self.reply_to_request(req, rep) + -- 2.3.2 (Apple Git-55) 2015-06-11 13:29 GMT+08:00 Yi Tseng <[email protected]>: > Hi > > Sorry that I forgot to remove comment (# this type is used for key value > of LinkState) in class Host (I copied class Link and modify it) > > Should I send a new patch ? > > > > 2015-06-11 13:08 GMT+08:00 Yi Tseng <[email protected]>: > >> Hi >> >> I didn't concern that host can be configured to send lldp packets. >> >> If a host can be configured to send lldp packet, there will be two >> situations: >> >> 1. Host always send lldp packets : ryu can't discover that host. >> >> 2. Host not always send lldp packet, sometimes it send normal packet : >> ryu can discover it. >> >> I think maybe I can add "--observe-hosts" option to ryu manager and send >> a new patch? >> >> >> >> >> 2015-06-11 12:33 GMT+08:00 IWAMOTO Toshihiro <[email protected]>: >> >>> At Thu, 11 Jun 2015 02:30:40 +0800, >>> Yi Tseng wrote: >>> > >>> > Signed-off-by: Takeshi <[email protected]> >>> > --- >>> > ryu/topology/api.py | 7 +++++ >>> > ryu/topology/event.py | 23 +++++++++++++++++ >>> > ryu/topology/switches.py | 66 >>> > +++++++++++++++++++++++++++++++++++++++++++++++- >>> > 3 files changed, 95 insertions(+), 1 deletion(-) >>> >>> > diff --git a/ryu/topology/switches.py b/ryu/topology/switches.py >>> > index 63335f2..ab7f9f6 100644 >>> > --- a/ryu/topology/switches.py >>> > +++ b/ryu/topology/switches.py >>> > @@ -157,6 +157,35 @@ class Link(object): >>> > def __str__(self): >>> > return 'Link: %s to %s' % (self.src, self.dst) >>> > >>> > +class Host(object): >>> > + # This is data class passed by EventHostXXXX >>> > + def __init__(self, dpid, port, mac): >>> > + super(Host, self).__init__() >>> > + self.dpid = dpid >>> > + self.port = port >>> > + self.mac = mac >>> > + >>> > + def to_dict(self): >>> > + d = { >>> > + 'dpid': self.dpid, >>> > + 'port': self.port, >>> > + 'mac': self.mac >>> > + } >>> > + return d >>> > + >>> > + # this type is used for key value of LinkState >>> >>> Really? And why are you ignoring dpid and port in comparison >>> operators? >>> >>> > + def __eq__(self, other): >>> > + return self.mac == other.mac >>> > + >>> > + def __ne__(self, other): >>> > + return not self.__eq__(other) >>> > + >>> > + def __hash__(self): >>> > + return hash(self.mac) >>> > + >>> > + def __str__(self): >>> > + return 'Host<Mac address=%s>' % (self.mac, ) >>> > + >>> > >>> > class PortState(dict): >>> > # dict: int port_no -> OFPPort port >>> > @@ -451,6 +480,7 @@ class Switches(app_manager.RyuApp): >>> > self.port_state = {} # datapath_id => ports >>> > self.ports = PortDataState() # Port class -> PortData class >>> > self.links = LinkState() # Link class -> timestamp >>> > + self.hosts = {} >>> > self.is_active = True >>> > >>> > self.link_discovery = self.CONF.observe_links >>> > @@ -689,7 +719,25 @@ class Switches(app_manager.RyuApp): >>> > src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data) >>> > except LLDPPacket.LLDPUnknownFormat as e: >>> > # This handler can receive all the packtes which can be >>> > - # not-LLDP packet. Ignore it silently >>> > + # not-LLDP packet. >>> > + # Check if it's new host >>> > + >>> > + dpid = msg.datapath.id >>> > + port = -1 >>> > + >>> > + if msg.datapath.ofproto.OFP_VERSION == >>> > ofproto_v1_0.OFP_VERSION: >>> > + port = msg.in_port >>> > + elif msg.datapath.ofproto.OFP_VERSION >= >>> > ofproto_v1_2.OFP_VERSION: >>> > + port = msg.match['in_port'] >>> > + >>> > + pkt = packet.Packet(msg.data) >>> > + eth = pkt.get_protocols(ethernet.ethernet)[0] >>> > + mac = eth.src >>> > + >>> > + if mac not in self.hosts and port != -1: >>> > + LOG.debug('Found host(mac=%s) from dpid=%d, port=%d', >>> mac, >>> > dpid, port) >>> > + self.hosts[mac] = Host(dpid, port, mac) >>> > + >>> > return >>> > >>> > dst_dpid = msg.datapath.id >>> >>> -- >>> IWAMOTO Toshihiro >>> >> >> >> >> -- >> Yi Tseng (a.k.a Takeshi) >> Taiwan National Chiao Tung University >> Department of Computer Science >> W2CNLab >> > > > > -- > Yi Tseng (a.k.a Takeshi) > Taiwan National Chiao Tung University > Department of Computer Science > W2CNLab > -- Yi Tseng (a.k.a Takeshi) Taiwan National Chiao Tung University Department of Computer Science W2CNLab
------------------------------------------------------------------------------
_______________________________________________ Ryu-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ryu-devel
