blob: 14142d9150c191f147bb6dfc82183711d85c9df1 [file] [log] [blame]
Shad Ansari22920932018-05-17 00:33:34 +00001#
2# Copyright 2018 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17from voltha.protos.device_pb2 import Port
mzadige4ad1d22018-07-27 15:27:22 -040018import voltha.protos.device_pb2 as dev_pb2
Shad Ansarie497ad42019-03-11 21:11:38 -070019import voltha.core.flow_decomposer as fd
Shad Ansari22920932018-05-17 00:33:34 +000020
21"""
22Encoding of identifiers
23=======================
24
Shad Ansari22920932018-05-17 00:33:34 +000025Flow id
26
27 Identifies a flow within a single OLT
28 Flow Id is unique per OLT
29 Multiple GEM ports can map to same flow id
30
31 13 11 4 0
32 +--------+--------------+------+
33 | pon id | onu id | Flow |
34 | | | idx |
35 +--------+--------------+------+
36
37 14 bits = 16384 flows (per OLT).
38
39 pon id = 4 bits = 16 PON ports
40 onu id = 7 bits = 128 ONUss per PON port
41 Flow index = 3 bits = 4 bi-directional flows per ONU
42 = 8 uni-directional flows per ONU
43
44
45Logical (OF) UNI port number
46
47 OpenFlow port number corresponding to PON UNI
48
49 15 11 4 0
50 +--+--------+--------------+------+
51 |0 | pon id | onu id | 0 |
52 +--+--------+--------------+------+
53
54 pon id = 4 bits = 16 PON ports
55 onu id = 7 bits = 128 ONUs per PON port
56
Nicolas Palpacuer5780e152018-09-05 17:25:42 -040057Logical (OF) NNI port number
58
59 OpenFlow port number corresponding to PON UNI
60
61 16 0
62 +--+----------------------------+
63 |1 | intf_id |
64 +--+----------------------------+
65
66 No overlap with UNI port number space
67
Shad Ansari22920932018-05-17 00:33:34 +000068
69PON OLT (OF) port number
70
71 OpenFlow port number corresponding to PON OLT ports
72
73 31 28 0
74 +--------+------------------------~~~------+
75 | 0x2 | pon intf id |
76 +--------+------------------------~~~------+
77
78"""
79
Shad Ansarid9642382019-02-19 23:01:28 -080080
Shad Ansaricd20a6d2018-10-02 14:36:33 +000081class OpenOltPlatform(object):
Craig Lutgenabd9c842018-11-15 23:58:27 +000082 MAX_PONS_PER_OLT = 16
Shad Ansarid9642382019-02-19 23:01:28 -080083 MAX_ONUS_PER_PON = 128
Craig Lutgenabd9c842018-11-15 23:58:27 +000084 MAX_UNIS_PER_ONU = 16
Shad Ansaricd20a6d2018-10-02 14:36:33 +000085
Craig Lutgenabd9c842018-11-15 23:58:27 +000086 def mk_uni_port_num(self, intf_id, onu_id, uni_id):
87 assert intf_id < OpenOltPlatform.MAX_PONS_PER_OLT
88 assert onu_id < OpenOltPlatform.MAX_ONUS_PER_PON
89 assert uni_id < OpenOltPlatform.MAX_UNIS_PER_ONU
Shad Ansari9630ee32019-02-21 13:44:16 -080090 # Multiple unis not supported. Physical ONU equates to single UNI.
91 assert uni_id == 0
Craig Lutgenabd9c842018-11-15 23:58:27 +000092 return intf_id << 11 | onu_id << 4 | uni_id
Shad Ansari22920932018-05-17 00:33:34 +000093
Craig Lutgenabd9c842018-11-15 23:58:27 +000094 def uni_id_from_port_num(self, port_num):
95 return port_num & 0xF
Shad Ansari22920932018-05-17 00:33:34 +000096
Shad Ansaricd20a6d2018-10-02 14:36:33 +000097 def onu_id_from_port_num(self, port_num):
98 return (port_num >> 4) & 0x7F
Shad Ansari22920932018-05-17 00:33:34 +000099
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000100 def intf_id_from_uni_port_num(self, port_num):
101 return (port_num >> 11) & 0xF
Shad Ansari22920932018-05-17 00:33:34 +0000102
Shad Ansarie497ad42019-03-11 21:11:38 -0700103 def onu_id_from_uni_port_num(self, port_num):
104 return (port_num >> 4) & 0x7F
105
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000106 def intf_id_from_pon_port_no(self, port_no):
107 return port_no & 0xF
Nicolas Palpacuer36a93442018-05-23 17:38:57 -0400108
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000109 def intf_id_to_port_no(self, intf_id, intf_type):
110 if intf_type is Port.ETHERNET_NNI:
111 return (0x1 << 16) | intf_id
112 elif intf_type is Port.PON_OLT:
113 return 0x2 << 28 | intf_id
114 else:
115 raise Exception('Invalid port type')
Nicolas Palpacuer7d902812018-06-07 16:17:09 -0400116
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000117 def intf_id_from_nni_port_num(self, port_num):
118 return port_num & 0xFFFF
mzadige4ad1d22018-07-27 15:27:22 -0400119
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000120 def intf_id_to_port_type_name(self, intf_id):
121 if (2 << 28 ^ intf_id) < 16:
122 return Port.PON_OLT
123 elif intf_id & (0x1 << 16) == (0x1 << 16):
124 return Port.ETHERNET_NNI
125 else:
Craig Lutgenabd9c842018-11-15 23:58:27 +0000126 return Port.ETHERNET_UNI
mzadige4ad1d22018-07-27 15:27:22 -0400127
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000128 def port_type_name_by_port_index(self, port_index):
129 try:
130 return dev_pb2._PORT_PORTTYPE.values_by_number[port_index].name
131 except Exception as err:
132 raise Exception(err)
mzadige4ad1d22018-07-27 15:27:22 -0400133
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000134 def extract_access_from_flow(self, in_port, out_port):
135 if self.is_upstream(out_port):
Craig Lutgenabd9c842018-11-15 23:58:27 +0000136 return (in_port,
137 self.intf_id_from_uni_port_num(in_port),
138 self.onu_id_from_port_num(in_port),
139 self.uni_id_from_port_num(in_port))
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000140 else:
Craig Lutgenabd9c842018-11-15 23:58:27 +0000141 return (out_port,
142 self.intf_id_from_uni_port_num(out_port),
143 self.onu_id_from_port_num(out_port),
144 self.uni_id_from_port_num(out_port))
Nicolas Palpacuer0c7c3162018-08-08 11:27:57 -0400145
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000146 def is_upstream(self, out_port):
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000147 if out_port in [0xfffd, 0xfffffffd]:
148 # To Controller
149 return True
150 if (out_port & (0x1 << 16)) == (0x1 << 16):
151 # NNI interface
152 return True
Shad Ansaricd20a6d2018-10-02 14:36:33 +0000153 return False
Shad Ansarie497ad42019-03-11 21:11:38 -0700154
155 def flow_extract_info(self, flow, flow_direction):
156 uni_port_no = None
157 if flow_direction == "upstream":
158 for field in fd.get_ofb_fields(flow):
159 if field.type == fd.IN_PORT:
160 uni_port_no = field.port
161 break
162 elif flow_direction == "downstream":
163 for field in fd.get_ofb_fields(flow):
164 if field.type == fd.METADATA:
165 uni_port_no = field.table_metadata & 0xFFFFFFFF
166 break
167
168 if uni_port_no is None:
169 for action in fd.get_actions(flow):
170 if action.type == fd.OUTPUT:
171 uni_port_no = action.output.port
172 break
173
174 if uni_port_no is None:
175 raise ValueError
176
177 pon_intf = self.platform.intf_id_from_uni_port_num(uni_port_no)
178 onu_id = self.platform.onu_id_from_uni_port_num(uni_port_no)
179 uni_id = self.platform.uni_id_from_port_num(uni_port_no)
180
181 return pon_intf, onu_id, uni_id