diff --git a/ryu/app/ofctl_rest.py b/ryu/app/ofctl_rest.py index b9656b19..8ab53f98 100644 --- a/ryu/app/ofctl_rest.py +++ b/ryu/app/ofctl_rest.py @@ -81,6 +81,10 @@ LOG = logging.getLogger('ryu.app.ofctl_rest') # # delete a meter entry # POST /stats/meterentry/delete +# +# +# send a experimeter message +# POST /stats/experimenter/ class StatsController(ControllerBase): @@ -269,6 +273,27 @@ class StatsController(ControllerBase): return Response(status=200) + def send_experimenter(self, req, dpid, **_kwargs): + dp = self.dpset.get(int(dpid)) + if dp is None: + return Response(status=404) + + try: + exp = eval(req.body) + except SyntaxError: + LOG.debug('invalid syntax %s', req.body) + return Response(status=400) + + if dp.ofproto.OFP_VERSION == ofproto_v1_2.OFP_VERSION: + ofctl_v1_2.send_experimenter(dp, exp) + elif dp.ofproto.OFP_VERSION == ofproto_v1_3.OFP_VERSION: + ofctl_v1_3.send_experimenter(dp, exp) + else: + LOG.debug('Unsupported OF protocol') + return Response(status=501) + + return Response(status=200) + class RestStatsApi(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION, @@ -341,6 +366,11 @@ class RestStatsApi(app_manager.RyuApp): controller=StatsController, action='mod_meter_entry', conditions=dict(method=['POST'])) + uri = path + '/experimenter/{dpid}' + mapper.connect('stats', uri, + controller=StatsController, action='send_experimenter', + conditions=dict(method=['POST'])) + def stats_reply_handler(self, ev): msg = ev.msg dp = msg.datapath diff --git a/ryu/lib/ofctl_v1_2.py b/ryu/lib/ofctl_v1_2.py index 6eb29814..660832ab 100644 --- a/ryu/lib/ofctl_v1_2.py +++ b/ryu/lib/ofctl_v1_2.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 import struct import socket import logging @@ -367,3 +368,19 @@ def mod_flow_entry(dp, flow, cmd): flags, match, inst) dp.send_msg(flow_mod) + + +def send_experimenter(dp, exp): + experimenter = exp.get('experimenter', 0) + exp_type = exp.get('exp_type', 0) + data_type = exp.get('data_type', 'ascii') + if data_type != 'ascii' and data_type != 'base64': + LOG.debug('Unknown data type: %s', data_type) + data = exp.get('data', '') + if data_type == 'base64': + data = base64.b64decode(data) + + expmsg = dp.ofproto_parser.OFPExperimenter( + dp, experimenter, exp_type, data) + + dp.send_msg(expmsg) diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py index 7d2c9fba..f9836246 100644 --- a/ryu/lib/ofctl_v1_3.py +++ b/ryu/lib/ofctl_v1_3.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 import struct import socket import logging @@ -640,3 +641,19 @@ def mod_meter_entry(dp, flow, cmd): dp, cmd, flags, meter_id, bands) dp.send_msg(meter_mod) + + +def send_experimenter(dp, exp): + experimenter = exp.get('experimenter', 0) + exp_type = exp.get('exp_type', 0) + data_type = exp.get('data_type', 'ascii') + if data_type != 'ascii' and data_type != 'base64': + LOG.debug('Unknown data type: %s', data_type) + data = exp.get('data', '') + if data_type == 'base64': + data = base64.b64decode(data) + + expmsg = dp.ofproto_parser.OFPExperimenter( + dp, experimenter, exp_type, data) + + dp.send_msg(expmsg)