Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
this application provides the simple example of IGMP snooping. the module "igmplib" mainly offers 2 functions: - listening on in the IGMP conversation between multicast routers and hosts - emulating of the querier function of multicast servers the former operates a switch as a snooping switch and controls transmission of an unnecessary multicasting packet. the latter realizes the IGMP conversation in the environment without multicast routers. the module "simple_switch_igmp" is a variation of "simple_switch". the switch receives the "EventPacketIn" event instead of the "EventOFPPacketIn" event from the module "igmplib" in order to except IGMP. Signed-off-by: Yuichi Ito <ito.yuichi0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
- Loading branch information
Showing
2 changed files
with
914 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
# implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import struct | ||
|
||
from ryu.base import app_manager | ||
from ryu.controller.handler import MAIN_DISPATCHER | ||
from ryu.controller.handler import set_ev_cls | ||
from ryu.ofproto import ofproto_v1_0 | ||
from ryu.lib import addrconv | ||
from ryu.lib import igmplib | ||
from ryu.lib.dpid import str_to_dpid | ||
|
||
|
||
class SimpleSwitchIgmp(app_manager.RyuApp): | ||
OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION] | ||
_CONTEXTS = {'igmplib': igmplib.IgmpLib} | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(SimpleSwitchIgmp, self).__init__(*args, **kwargs) | ||
self.mac_to_port = {} | ||
self._snoop = kwargs['igmplib'] | ||
# if you want a switch to operate as a querier, | ||
# set up as follows: | ||
self._snoop.set_querier_mode( | ||
dpid=str_to_dpid('0000000000000001'), server_port=2) | ||
# dpid the datapath id that will operate as a querier. | ||
# server_port a port number which connect to the multicast | ||
# server. | ||
# | ||
# NOTE: you can set up only the one querier. | ||
# when you called this method several times, | ||
# only the last one becomes effective. | ||
|
||
def add_flow(self, datapath, in_port, dst, actions): | ||
ofproto = datapath.ofproto | ||
parser = datapath.ofproto_parser | ||
|
||
match = parser.OFPMatch(in_port=in_port, | ||
dl_dst=addrconv.mac.text_to_bin(dst)) | ||
mod = parser.OFPFlowMod( | ||
datapath=datapath, match=match, cookie=0, | ||
command=ofproto.OFPFC_ADD, actions=actions) | ||
datapath.send_msg(mod) | ||
|
||
@set_ev_cls(igmplib.EventPacketIn, MAIN_DISPATCHER) | ||
def _packet_in_handler(self, ev): | ||
msg = ev.msg | ||
datapath = msg.datapath | ||
ofproto = datapath.ofproto | ||
|
||
(dst_, src_, _eth_type) = struct.unpack_from( | ||
'!6s6sH', buffer(msg.data), 0) | ||
src = addrconv.mac.bin_to_text(src_) | ||
dst = addrconv.mac.bin_to_text(dst_) | ||
|
||
dpid = datapath.id | ||
self.mac_to_port.setdefault(dpid, {}) | ||
|
||
self.logger.info("packet in %s %s %s %s", | ||
dpid, src, dst, msg.in_port) | ||
|
||
# learn a mac address to avoid FLOOD next time. | ||
self.mac_to_port[dpid][src] = msg.in_port | ||
|
||
if dst in self.mac_to_port[dpid]: | ||
out_port = self.mac_to_port[dpid][dst] | ||
else: | ||
out_port = ofproto.OFPP_FLOOD | ||
|
||
actions = [datapath.ofproto_parser.OFPActionOutput(out_port)] | ||
|
||
# install a flow to avoid packet_in next time | ||
if out_port != ofproto.OFPP_FLOOD: | ||
self.add_flow(datapath, msg.in_port, dst, actions) | ||
|
||
out = datapath.ofproto_parser.OFPPacketOut( | ||
datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port, | ||
actions=actions) | ||
datapath.send_msg(out) | ||
|
||
@set_ev_cls(igmplib.EventMulticastGroupStateChanged, | ||
MAIN_DISPATCHER) | ||
def _status_changed(self, ev): | ||
msg = { | ||
igmplib.MG_GROUP_ADDED: 'Multicast Group Added', | ||
igmplib.MG_MEMBER_CHANGED: 'Multicast Group Member Changed', | ||
igmplib.MG_GROUP_REMOVED: 'Multicast Group Removed', | ||
} | ||
self.logger.info("%s: [%s] querier:[%s] hosts:%s", | ||
msg.get(ev.reason), ev.address, ev.src, | ||
ev.dsts) |
Oops, something went wrong.