blob: 48e2e7e8decf867f01644db8515229b319441837 [file] [log] [blame]
Chip Bolingf5af85d2019-02-12 15:36:17 -06001# Copyright 2017-present Adtran, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
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 implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15from flow_entry import FlowEntry
16from evc import EVC
17
18
19class DeviceFlows(object):
20 """ Tracks existing flows on the device """
21
22 def __init__(self):
23 self._flow_table = dict() # Key = (str)Flow ID, Value = FlowEntry
24
25 def __getitem__(self, item):
26 flow_id = item.flow_id if isinstance(item, FlowEntry) else item
27 return self._flow_table[flow_id]
28
29 def __iter__(self):
30 for _flow_id, _flow in self._flow_table.items():
31 yield _flow_id, _flow
32
33 def itervalues(self):
34 for _flow in self._flow_table.values():
35 yield _flow
36
37 def iterkeys(self):
38 for _id in self._flow_table.keys():
39 yield _id
40
41 def items(self):
42 return self._flow_table.items()
43
44 def values(self):
45 return self._flow_table.values()
46
47 def keys(self):
48 return self._flow_table.keys()
49
50 def __len__(self):
51 return len(self._flow_table)
52
53 def add(self, flow):
54 assert isinstance(flow, FlowEntry)
55 if flow.flow_id not in self._flow_table:
56 self._flow_table[flow.flow_id] = flow
57 return flow
58
59 def get(self, item):
60 flow_id = item.flow_id if isinstance(item, FlowEntry) else item
61 return self._flow_table.get(flow_id)
62
63 def remove(self, item):
64 flow_id = item.flow_id if isinstance(item, FlowEntry) else item
65 return self._flow_table.pop(flow_id, None)
66
67 def clear_all(self):
68 self._flow_table = dict()
69
70
71class DownstreamFlows(object):
72 """
73 Tracks existing flows that are downstream (NNI as source port)
74
75 The downstream table is slightly different than the base DeviceFlows
76 table as it is used to track flows that will become EVCs. The base
77 table tracks flows that will be EVC-maps (or related to them).
78
79 The downstream table is also indexed by a downstream signature that
80 is composed as follows:
81
82 <dev-id>.<ingress-port-number>.<s-tag>.*
83
84 In comparison, the upstream flows is similar, but instead of '*' it has the
85 c-tag (if any).
86
87 TODO: Drop device ID from signatures once flow tables are unique to a device handler
88 """
89 def __init__(self):
90 self._signature_table = dict() # Key = (str)Downstream signature
91 # |
92 # +-> downstream-signature
93 # |
94 # +-> 'evc' -> EVC
95 # |
96 # +-> flow-ids -> flow-entries...
97
98 def __getitem__(self, signature):
99 assert isinstance(signature, str)
100 return self._signature_table[signature]
101
102 def __iter__(self):
103 for _flow_id, _flow in self._signature_table.items():
104 yield _flow_id, _flow
105
106 def itervalues(self):
107 for _flow in self._signature_table.values():
108 yield _flow
109
110 def iterkeys(self):
111 for _id in self._signature_table.keys():
112 yield _id
113
114 def items(self):
115 return self._signature_table.items()
116
117 def values(self):
118 return self._signature_table.values()
119
120 def keys(self):
121 return self._signature_table.keys()
122
123 def __len__(self):
124 return len(self._signature_table)
125
126 def get(self, signature):
127 assert isinstance(signature, str)
128 return self._signature_table.get(signature)
129
130 def add(self, signature):
131 assert isinstance(signature, str)
132 """
133 Can be called by upstream flow to reserve a slot
134 """
135 if signature not in self._signature_table:
136 self._signature_table[signature] = DownstreamFlows.SignatureTableEntry(signature)
137 return self._signature_table[signature]
138
139 def remove(self, signature):
140 assert isinstance(signature, str)
141 return self._signature_table.pop(signature)
142
143 def clear_all(self):
144 self._signature_table = dict()
145
146 class SignatureTableEntry(object):
147 def __init__(self, signature):
148 self._signature = signature
149 self._evc = None
150 self._flow_table = DeviceFlows()
151
152 @property
153 def evc(self):
154 return self._evc
155
156 @evc.setter
157 def evc(self, evc):
158 assert isinstance(evc, (EVC, type(None)))
159 self._evc = evc
160
161 @property
162 def flows(self):
163 return self._flow_table