- mac address parser/serializer
- move out WSPathNetwork from rest.py
- introduce wspath.py for URI parser which will be commonly used and
  moved WSPathNetwork into it.

Signed-off-by: Isaku Yamahata <[email protected]>
---
 ryu/app/rest.py |  126 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 101 insertions(+), 25 deletions(-)

diff --git a/ryu/app/rest.py b/ryu/app/rest.py
index 3116424..8993ab2 100644
--- a/ryu/app/rest.py
+++ b/ryu/app/rest.py
@@ -14,12 +14,15 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import json
+from ryu.exception import MacAddressAlreadyExist
 from ryu.exception import NetworkNotFound, NetworkAlreadyExist
 from ryu.exception import PortNotFound, PortAlreadyExist
 from ryu.app.wsapi import WSPathComponent
 from ryu.app.wsapi import WSPathExtractResult
 from ryu.app.wsapi import WSPathStaticString
 from ryu.app.wsapi import wsapi
+from ryu.app.wspath import WSPathNetwork
+from ryu.lib import mac
 
 # REST API
 
@@ -51,45 +54,62 @@ from ryu.app.wsapi import wsapi
 #
 # remove a set of dpid and port
 # DELETE /v1.0/networks/{network-id}/{dpid}_{port-id}
-
-# We store networks and ports like the following:
 #
-# {network_id: [(dpid, port), ...
-# {3: [(3,4), (4,7)], 5: [(3,6)], 1: [(5,6), (4,5), (4, 10)]}
+# get the list of mac addresses of dpid and port
+# GET /v1.0/networks/{network-id}/{dpid}_{port-id}/macs/
+#
+# register a new mac address for dpid and port
+# Fail if mac address is already registered or the mac address is used
+# for other ports of the same network-id
+# POST /v1.0/networks/{network-id}/{dpid}_{port-id}/macs/{mac}
+#
+# update a new mac address for dpid and port
+# Success as nop even if same mac address is already registered.
+# For now, changing mac address is not allows as it fails.
+# PUT /v1.0/networks/{network-id}/{dpid}_{port-id}/macs/{mac}
+#
+# For now DELETE /v1.0/networks/{network-id}/{dpid}_{port-id}/macs/{mac}
+# is not supported. mac address is released when port is deleted.
 #
 
 
-class WSPathNetwork(WSPathComponent):
-    """ Match a network id string """
+class WSPathPort(WSPathComponent):
+    """ Match a {dpid}_{port-id} string """
 
     def __str__(self):
-        return "{network-id}"
+        return "{dpid}_{port-id}"
 
     def extract(self, pc, _data):
         if pc == None:
             return WSPathExtractResult(error="End of requested URI")
 
-        return WSPathExtractResult(value=pc)
+        try:
+            dpid_str, port_str = pc.split('_')
+            dpid = int(dpid_str, 16)
+            port = int(port_str)
+        except ValueError:
+            return WSPathExtractResult(error="Invalid format: %s" % pc)
+
+        return WSPathExtractResult(value={'dpid': dpid, 'port': port})
 
 
-class WSPathPort(WSPathComponent):
-    """ Match a {dpid}_{port-id} string """
+class WSPathMacAddress(WSPathComponent):
+    """ Match a {mac} string: %02x:%02x:%02x:%02x:%02x:%02x
+       Internal representation of mac address is string[6]"""
 
     def __str__(self):
-        return "{dpid}_{port-id}"
+        return "{mac}"
 
-    def extract(self, pc, _data):
+    def extract(self, pc, data):
         if pc == None:
             return WSPathExtractResult(error="End of requested URI")
 
         try:
-            dpid_str, port_str = pc.split('_')
-            dpid = int(dpid_str, 16)
-            port = int(port_str)
+            mac_addr = mac.haddr_to_bin(pc)
         except ValueError:
             return WSPathExtractResult(error="Invalid format: %s" % pc)
 
-        return WSPathExtractResult(value={'dpid': dpid, 'port': port})
+        return WSPathExtractResult(value=mac_addr)
 
 
 class restapi:
@@ -141,10 +161,14 @@ class restapi:
         request.setHeader("Content-Type", 'application/json')
         return body
 
+    @staticmethod
+    def _get_param_port(data):
+        return (data['{network-id}'],
+                data['{dpid}_{port-id}']['dpid'],
+                data['{dpid}_{port-id}']['port'])
+
     def create_port_handler(self, request, data):
-        network_id = data['{network-id}']
-        dpid = data['{dpid}_{port-id}']['dpid']
-        port = data['{dpid}_{port-id}']['port']
+        (network_id, dpid, port) = self._get_param_port(data)
 
         try:
             self.nw.create_port(network_id, dpid, port)
@@ -156,9 +180,7 @@ class restapi:
         return ""
 
     def update_port_handler(self, request, data):
-        network_id = data['{network-id}']
-        dpid = data['{dpid}_{port-id}']['dpid']
-        port = data['{dpid}_{port-id}']['port']
+        (network_id, dpid, port) = self._get_param_port(data)
 
         try:
             self.nw.update_port(network_id, dpid, port)
@@ -168,9 +190,7 @@ class restapi:
         return ""
 
     def remove_port_handler(self, request, data):
-        network_id = data['{network-id}']
-        dpid = data['{dpid}_{port-id}']['dpid']
-        port = data['{dpid}_{port-id}']['port']
+        (network_id, dpid, port) = self._get_param_port(data)
 
         try:
             self.nw.remove_port(network_id, dpid, port)
@@ -179,6 +199,48 @@ class restapi:
 
         return ""
 
+    def list_mac_handler(self, request, data):
+        (_network_id, dpid, port_no) = self._get_param_port(data)
+
+        try:
+            body = json.dumps([mac.haddr_to_str(mac_addr) for mac_addr in
+                               self.nw.list_mac(dpid, port_no)])
+        except PortNotFound:
+            request.setResponseCode(404)
+            return ""
+
+        request.setHeader("Content-Type", 'application/json')
+        return body
+
+    @staticmethod
+    def _get_param_mac(data):
+        return (data['{network-id}'],
+                data['{dpid}_{port-id}']['dpid'],
+                data['{dpid}_{port-id}']['port'],
+                data['{mac}'])
+
+    def create_mac_handler(self, request, data):
+        (network_id, dpid, port_no, mac_addr) = self._get_param_mac(data)
+
+        try:
+            self.nw.create_mac(network_id, dpid, port_no, mac_addr)
+        except MacAddressAlreadyExist:
+            request.setResponseCode(409)
+        except PortNotFound:
+            request.setResponseCode(404)
+
+        return ""
+
+    def update_mac_handler(self, request, data):
+        (network_id, dpid, port_no, mac_addr) = self._get_param_mac(data)
+
+        try:
+            self.nw.update_mac(network_id, dpid, port_no, mac_addr)
+        except PortNotFound:
+            request.setResponseCode(404)
+
+        return ""
+
     def register(self):
         path_networks = (WSPathStaticString('networks'), )
         self.api.register_request(self.list_networks_handler, "GET",
@@ -214,3 +276,17 @@ class restapi:
         self.api.register_request(self.remove_port_handler, "DELETE",
                                   path_port,
                                   "remove a set of dpid and port")
+
+        path_macs = path_port + (WSPathStaticString('macs'), )
+        self.api.register_request(self.list_mac_handler, "GET",
+                                  path_macs,
+                                  "get the list of mac addresses")
+
+        path_mac = path_macs + (WSPathMacAddress(), )
+        self.api.register_request(self.create_mac_handler, "POST",
+                                  path_mac,
+                                  "register a new mac address for a port")
+
+        self.api.register_request(self.update_mac_handler, "PUT",
+                                  path_mac,
+                                  "update a mac address for a port")
-- 
1.7.1.1


------------------------------------------------------------------------------
Better than sec? Nothing is better than sec when it comes to
monitoring Big Data applications. Try Boundary one-second 
resolution app monitoring today. Free.
http://p.sf.net/sfu/Boundary-dev2dev
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to