backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / app / sdnhub_apps / tap_rest.py
1 # Copyright (C) 2014 SDN Hub
2 #
3 # Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
4 # You may not use this file except in compliance with this License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.gnu.org/licenses/gpl-3.0.txt
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
14 import logging
15
16 import json
17 from webob import Response
18 import os
19 import mimetypes
20
21 from ryu.base import app_manager
22 from ryu.controller import ofp_event
23 from ryu.controller import dpset
24 from ryu.controller.handler import MAIN_DISPATCHER
25 from ryu.controller.handler import set_ev_cls
26 from ryu.ofproto import ofproto_v1_0
27 from ryu.ofproto import ofproto_v1_3
28 from ryu.lib import ofctl_v1_0
29 from ryu.lib import ofctl_v1_3
30 from ryu.app.wsgi import ControllerBase, WSGIApplication
31 import tap
32 from ryu.ofproto import inet
33
34 LOG = logging.getLogger('ryu.app.sdnhub_apps.tap_rest')
35
36 # REST API
37 #
38 ############# Configure tap
39 #
40 # get all taps
41 # GET /tap
42 #
43 # create tap filter
44 # POST /v1.0/tap/create
45 #
46 # delete tap filter
47 # DELETE /v1.0/tap/delete
48 #
49
50 import re, socket
51 def is_mac_valid(x):
52     if re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", x.lower()):
53         return True
54     else:
55         return False
56
57 def is_ip_valid(x):
58     y = x.split('/')
59     if len(y) > 2:
60         return False
61     try:
62         socket.inet_aton(y[0])
63         return True
64     except socket.error:
65        return False
66
67 class TapController(ControllerBase):
68     def __init__(self, req, link, data, **config):
69         super(TapController, self).__init__(req, link, data, **config)
70         self.tap = data['tap']
71         self.tap.dpset = data['dpset']
72
73     def is_filter_data_valid(self, filter_data):
74         if 'sources' not in filter_data:
75             LOG.error('missing sources %s', filter_data)
76             return False
77         else:
78             for source in filter_data['sources']:
79                 if 'dpid' not in source or 'port_no' not in source:
80                     LOG.error('Invalid source description %s', source)
81                     return False
82
83         if 'sinks' not in filter_data:
84             LOG.error('missing sinks %s', filter_data)
85             return False
86         else:
87             for sink in filter_data['sinks']:
88                 if 'dpid' not in sink or 'port_no' not in sink:
89                     LOG.error('Invalid source description %s', sink)
90                     return False
91
92         if 'fields' in filter_data:
93             for key, val in filter_data['fields'].items():
94                 if key == 'dl_src' or key == 'dl_dst' or key == 'dl_host':
95                     if not is_mac_valid(val):
96                         LOG.error('Invalid MAC address in filter field %s=%s', key, val)
97                         return False
98                 if key == 'nw_src' or key == 'nw_dst' or key == 'nw_host':
99                     if 'dl_type' not in filter_data['fields']:
100                         LOG.error('Ethertype is not set, but IP fields specified')
101                         return False
102                     if not is_ip_valid(val):
103                         LOG.error('Invalid IP address in filter field %s=%s', key, val)
104                         return False
105                 if key == 'tp_src' or key == 'tp_dst' or key == 'tp_port':
106                     nw_proto = filter_data['fields']['nw_proto']
107                     if nw_proto != inet.IPPROTO_TCP and nw_proto != inet.IPPROTO_UDP:
108                         LOG.error('Non TCP/UDP packet specifies TP fields')
109                         return False
110                         
111         return True
112
113     def create_tap(self, req, **_kwargs):
114         try:
115             filter_data = eval(req.body)
116             print filter_data
117             if not self.is_filter_data_valid(filter_data):
118                 return Response(status=400)
119         except SyntaxError:
120             LOG.error('Invalid syntax %s', req.body)
121             return Response(status=400)
122
123         if self.tap.create_tap(filter_data):
124             return Response(status=200,content_type='application/json',
125                     body=json.dumps({'status':'success'}))
126         else:
127             LOG.error('Create tap failed')
128             return Response(status=501)
129
130     def delete_tap(self, req, **_kwargs):
131         try:
132             filter_data = eval(req.body)
133             if not self.is_filter_data_valid(filter_data):
134                 return Response(status=400)
135         except SyntaxError:
136             LOG.error('Invalid syntax %s', req.body)
137
138         self.tap.delete_tap(filter_data)
139         return Response(status=200,content_type='application/json',
140                     body=json.dumps({'status':'success'}))
141
142 class TapRestApi(app_manager.RyuApp):
143     OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION,
144                     ofproto_v1_3.OFP_VERSION]
145     _CONTEXTS = {
146         'dpset': dpset.DPSet,
147         'wsgi': WSGIApplication,
148         'tap': tap.StarterTap
149     }
150
151     def __init__(self, *args, **kwargs):
152         super(TapRestApi, self).__init__(*args, **kwargs)
153         self.dpset = kwargs['dpset']
154         tap = kwargs['tap']
155         wsgi = kwargs['wsgi']
156         self.waiters = {}
157         self.data = {}
158         self.data['dpset'] = self.dpset
159         self.data['waiters'] = self.waiters
160         self.data['tap'] = tap
161
162         wsgi.registory['TapController'] = self.data
163         mapper = wsgi.mapper
164
165         mapper.connect('tap', '/v1.0/tap/create',
166                        controller=TapController, action='create_tap',
167                        conditions=dict(method=['POST']))
168
169         mapper.connect('tap', '/v1.0/tap/delete',
170                        controller=TapController, action='delete_tap',
171                        conditions=dict(method=['POST']))
172
173