VOL-1451 Initial checkin of openonu build
Produced docker container capable of building and running
openonu/brcm_openonci_onu. Copied over current onu code
and resolved all imports by copying into the local source tree.
Change-Id: Ib9785d37afc65b7d32ecf74aee2456352626e2b6
diff --git a/python/core/device_graph.py b/python/core/device_graph.py
new file mode 100644
index 0000000..a4e6d85
--- /dev/null
+++ b/python/core/device_graph.py
@@ -0,0 +1,136 @@
+#
+# Copyright 2017 the original author or authors.
+#
+# 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 networkx as nx
+
+from voltha.core.flow_decomposer import RouteHop
+
+
+class DeviceGraph(object):
+
+ """
+ Mixin class to compute routes in the device graph within
+ a logical device.
+ """
+
+ def compute_routes(self, root_proxy, logical_ports):
+ boundary_ports, graph = self._build_graph(root_proxy, logical_ports)
+ routes = self._build_routes(boundary_ports, graph, logical_ports)
+ return graph, routes
+
+ def _build_graph(self, root_proxy, logical_ports):
+
+ graph = nx.Graph()
+
+ # walk logical device's device and port links to discover full graph
+ devices_added = set() # set of device.id's
+ ports_added = set() # set of (device.id, port_no) tuples
+ peer_links = set()
+
+ boundary_ports = dict(
+ ((lp.device_id, lp.device_port_no), lp.ofp_port.port_no)
+ for lp in logical_ports
+ )
+
+ def add_device(device):
+ if device.id in devices_added:
+ return
+
+ graph.add_node(device.id, device=device)
+ devices_added.add(device.id)
+
+ ports = root_proxy.get('/devices/{}/ports'.format(device.id))
+ for port in ports:
+ port_id = (device.id, port.port_no)
+ if port_id not in ports_added:
+ boundary = port_id in boundary_ports
+ graph.add_node(port_id, port=port, boundary=boundary)
+ graph.add_edge(device.id, port_id)
+ for peer in port.peers:
+ if peer.device_id not in devices_added:
+ peer_device = root_proxy.get(
+ '/devices/{}'.format(peer.device_id))
+ add_device(peer_device)
+ else:
+ peer_port_id = (peer.device_id, peer.port_no)
+ if port_id < peer_port_id:
+ peer_link = (port_id, peer_port_id)
+ else:
+ peer_link = (peer_port_id, port_id)
+ if peer_link not in peer_links:
+ graph.add_edge(*peer_link)
+ peer_links.add(peer_link)
+
+ for logical_port in logical_ports:
+ device_id = logical_port.device_id
+ device = root_proxy.get('/devices/{}'.format(device_id))
+ add_device(device)
+
+ return boundary_ports, graph
+
+ def _build_routes(self, boundary_ports, graph, logical_ports):
+
+ root_ports = dict((lp.ofp_port.port_no, lp.root_port)
+ for lp in logical_ports if lp.root_port == True)
+
+ routes = {}
+
+ for source, source_port_no in boundary_ports.iteritems():
+ for target, target_port_no in boundary_ports.iteritems():
+
+ if source is target:
+ continue
+
+ # Ignore NNI - NNI routes
+ if source_port_no in root_ports \
+ and target_port_no in root_ports:
+ continue
+
+ # Ignore UNI - UNI routes
+ if source_port_no not in root_ports \
+ and target_port_no not in root_ports:
+ continue
+
+ path = nx.shortest_path(graph, source, target)
+
+ # number of nodes in valid paths is always multiple of 3
+ if len(path) % 3:
+ continue
+
+ # in fact, we currently deal with single fan-out networks,
+ # so the number of hops is always 6
+ assert len(path) == 6
+
+ ingress_input_port, ingress_device, ingress_output_port, \
+ egress_input_port, egress_device, egress_output_port = path
+
+ ingress_hop = RouteHop(
+ device=graph.node[ingress_device]['device'],
+ ingress_port=graph.node[ingress_input_port]['port'],
+ egress_port=graph.node[ingress_output_port]['port']
+ )
+ egress_hop = RouteHop(
+ device=graph.node[egress_device]['device'],
+ ingress_port=graph.node[egress_input_port]['port'],
+ egress_port=graph.node[egress_output_port]['port']
+ )
+
+ routes[(source_port_no, target_port_no)] = [
+ ingress_hop, egress_hop
+ ]
+
+ return routes
+