Shad Ansari | 2f7f9be | 2017-06-07 13:34:53 -0700 | [diff] [blame] | 1 | # Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
|
| 2 | #
|
| 3 | # Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 | # you may not use this file except in compliance with the License.
|
| 5 | # You may obtain a copy of the License at
|
| 6 | #
|
| 7 | # http://www.apache.org/licenses/LICENSE-2.0
|
| 8 | #
|
| 9 | # Unless required by applicable law or agreed to in writing, software
|
| 10 | # distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 12 | # implied.
|
| 13 | # See the License for the specific language governing permissions and
|
| 14 | # limitations under the License.
|
| 15 | import logging
|
| 16 |
|
| 17 | from ryu.base import app_manager
|
| 18 | from time import sleep
|
| 19 | from ryu.controller import ofp_event
|
| 20 | from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
|
| 21 | from ryu.controller.handler import set_ev_cls
|
| 22 | from ryu.ofproto import ofproto_v1_3
|
| 23 | from ryu.lib.packet import packet
|
| 24 | from ryu.lib.packet import ethernet
|
| 25 | from ryu.lib import addrconv
|
| 26 |
|
| 27 | LOG = logging.getLogger('ryu.app.pon_topology')
|
| 28 |
|
| 29 | class PonTopology13(app_manager.RyuApp):
|
| 30 | OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
|
| 31 |
|
| 32 | def __init__(self, *args, **kwargs):
|
| 33 | super(PonTopology13, self).__init__(*args, **kwargs)
|
| 34 | self.mac_to_port = {}
|
| 35 |
|
| 36 | @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
|
| 37 | def switch_features_handler(self, ev):
|
| 38 | datapath = ev.msg.datapath
|
| 39 |
|
| 40 | # This does nothing if flows have not been previously configured in the OF agent
|
| 41 | self.del_all_flows(datapath)
|
| 42 |
|
| 43 | # Add a meter (500 Kbps rate limit) with an ID of 11
|
| 44 | self.add_meter(datapath, 11, 500)
|
| 45 |
|
| 46 | # Configure the flows (VID 100)
|
| 47 | # Note: the downstream flow has a meter ID reference
|
| 48 | #
|
| 49 | # Ports 1-128 are implicitly mapped to UNI-0 on ONUs 1->128
|
| 50 | # Ports 129 and above are implicitly mapped to OLT NNI-0 and above
|
| 51 | self.add_vid_flow(datapath,10000, 1, 129, 100, 0)
|
| 52 | self.add_vid_flow(datapath,10001, 129, 1, 100, 11)
|
| 53 |
|
| 54 | sleep(1)
|
| 55 | self.send_barrier(datapath)
|
| 56 |
|
| 57 |
|
| 58 | @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
|
| 59 | def port_status_handler(self, ev):
|
| 60 | LOG.debug('port_status_handler port id: %d', ev.msg.desc.port_no)
|
| 61 |
|
| 62 | def add_meter(self, datapath, meter_id, rate):
|
| 63 | ofproto = datapath.ofproto
|
| 64 | parser = datapath.ofproto_parser
|
| 65 | band = parser.OFPMeterBandDrop(burst_size=0, rate=rate)
|
| 66 | mod = parser.OFPMeterMod(datapath=datapath,command=ofproto.OFPMC_ADD, flags=ofproto.OFPMF_KBPS, meter_id=meter_id, bands=[band])
|
| 67 | LOG.info("add_meter: meter_id=%d, rate=%d KBPS")
|
| 68 | datapath.send_msg(mod)
|
| 69 |
|
| 70 | def add_vid_flow(self, datapath, cookie, src_port, dst_port, vid, meter_id):
|
| 71 | ofproto = datapath.ofproto
|
| 72 | parser = datapath.ofproto_parser
|
| 73 | actions = [parser.OFPActionOutput(dst_port)]
|
| 74 | if meter_id != 0:
|
| 75 | inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions), parser.OFPInstructionMeter(meter_id)]
|
| 76 | else:
|
| 77 | inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)]
|
| 78 |
|
| 79 | # NOTE: 0x1000 is OR'd into the vid to set the OFPVID_PRESENT flag in the OpenFlow FLOW_MOD (OFPFC_ADD)
|
| 80 | # message match field.
|
| 81 | match = parser.OFPMatch(in_port=src_port, vlan_vid=(vid | 0x1000))
|
| 82 | mod = parser.OFPFlowMod(datapath=datapath,
|
| 83 | cookie=cookie,
|
| 84 | cookie_mask=32767,
|
| 85 | priority=0,
|
| 86 | match=match,
|
| 87 | instructions=inst)
|
| 88 | LOG.info("add_vid_flow: src_port=%d dst_port=%d vid=%d meter=%d cookie=%d",
|
| 89 | src_port, dst_port, vid, meter_id, cookie)
|
| 90 | datapath.send_msg(mod)
|
| 91 |
|
| 92 | def del_flow(self, datapath, cookie):
|
| 93 | ofproto = datapath.ofproto
|
| 94 | parser = datapath.ofproto_parser
|
| 95 |
|
| 96 | mod = parser.OFPFlowMod(
|
| 97 | datapath=datapath, match=None, cookie=cookie, cookie_mask=32767,
|
| 98 | command=ofproto.OFPFC_DELETE)
|
| 99 | LOG.info("del_flow: cookie=%d", cookie)
|
| 100 | datapath.send_msg(mod)
|
| 101 |
|
| 102 | def del_all_flows(self, datapath):
|
| 103 | LOG.info("del_all_flows")
|
| 104 | # Cookie 0 (argument 2) tells the OF agent to delete all configured flows
|
| 105 | self._del_flow(datapath, 0, 0)
|
| 106 |
|
| 107 | def _del_flow(self, datapath, cookie, mask):
|
| 108 | ofproto = datapath.ofproto
|
| 109 | parser = datapath.ofproto_parser
|
| 110 |
|
| 111 | mod = parser.OFPFlowMod(datapath=datapath,
|
| 112 | match=None,
|
| 113 | cookie=cookie,
|
| 114 | cookie_mask=mask,
|
| 115 | command=ofproto.OFPFC_DELETE)
|
| 116 | datapath.send_msg(mod)
|
| 117 |
|
| 118 | def send_barrier(self, datapath):
|
| 119 | LOG.info("send_barrier")
|
| 120 | datapath.send_barrier()
|
| 121 |
|
| 122 |
|
| 123 |
|
| 124 |
|
| 125 |
|