blob: e4ff7dbff3c15f787c8e6b10e3bc59577042c1e5 [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001# Copyright 2017-present Open Networking Foundation
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
Zack Williams9a42f872019-02-15 17:56:04 -070015from __future__ import absolute_import, print_function
Matteo Scandolod2044a42017-08-07 16:08:28 -070016
Zack Williams9a42f872019-02-15 17:56:04 -070017import copy
18import sys
19
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020020import plyxproto.model as m
Sapan Bhatiadb183c22017-06-23 02:47:42 -070021from plyxproto.helpers import Visitor
Zack Williams9a42f872019-02-15 17:56:04 -070022from six.moves import map, range
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070023
Zack Williams045b63d2019-01-22 16:30:57 -070024
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040025class MissingPolicyException(Exception):
26 pass
27
Zack Williams045b63d2019-01-22 16:30:57 -070028
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040029def find_missing_policy_calls(name, policies, policy):
30 if isinstance(policy, dict):
31 (k, lst), = policy.items()
Zack Williams045b63d2019-01-22 16:30:57 -070032 if k == "policy":
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040033 policy_name = lst[0]
Zack Williams045b63d2019-01-22 16:30:57 -070034 if policy_name not in policies:
35 raise MissingPolicyException(
36 "Policy %s invoked missing policy %s" % (name, policy_name)
37 )
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040038 else:
39 for p in lst:
40 find_missing_policy_calls(name, policies, p)
41 elif isinstance(policy, list):
42 for p in lst:
43 find_missing_policy_calls(name, policies, p)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070044
Zack Williams045b63d2019-01-22 16:30:57 -070045
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020046def dotname_to_fqn(dotname):
47 b_names = [part.pval for part in dotname]
Zack Williams045b63d2019-01-22 16:30:57 -070048 package = ".".join(b_names[:-1])
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020049 name = b_names[-1]
50 if package:
Zack Williams045b63d2019-01-22 16:30:57 -070051 fqn = package + "." + name
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020052 else:
53 fqn = name
Zack Williams045b63d2019-01-22 16:30:57 -070054 return {"name": name, "fqn": fqn, "package": package}
Matteo Scandolo67654fa2017-06-09 09:33:17 -070055
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020056
57def dotname_to_name(dotname):
58 b_names = [part.pval for part in dotname]
Zack Williams045b63d2019-01-22 16:30:57 -070059 return ".".join(b_names)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020060
61
Sapan Bhatia504cc972017-04-27 01:56:28 +020062def count_messages(body):
63 count = 0
64 for e in body:
Zack Williams045b63d2019-01-22 16:30:57 -070065 if isinstance(e, m.MessageDefinition):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070066 count += 1
Sapan Bhatia504cc972017-04-27 01:56:28 +020067 return count
68
Matteo Scandolo67654fa2017-06-09 09:33:17 -070069
Sapan Bhatia504cc972017-04-27 01:56:28 +020070def count_fields(body):
71 count = 0
72 for e in body:
Zack Williams045b63d2019-01-22 16:30:57 -070073 if type(e) in [m.LinkDefinition, m.FieldDefinition, m.LinkSpec]:
Matteo Scandolo67654fa2017-06-09 09:33:17 -070074 count += 1
Sapan Bhatia504cc972017-04-27 01:56:28 +020075 return count
76
Matteo Scandolo67654fa2017-06-09 09:33:17 -070077
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020078def name_to_value(obj):
79 try:
80 value = obj.value.value.pval
81 except AttributeError:
82 try:
83 value = obj.value.value
84 except AttributeError:
85 value = obj.value.pval
86
87 return value
88
Matteo Scandolo67654fa2017-06-09 09:33:17 -070089
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070090class Stack(list):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070091 def push(self, x):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070092 self.append(x)
93
Matteo Scandolo67654fa2017-06-09 09:33:17 -070094
Zack Williams045b63d2019-01-22 16:30:57 -070095""" XOS2Jinja overrides the underlying visitor pattern to transform the tree
96 in addition to traversing it """
97
Matteo Scandolo67654fa2017-06-09 09:33:17 -070098
Sapan Bhatiadb183c22017-06-23 02:47:42 -070099class XOS2Jinja(Visitor):
Scott Bakerc237f882018-09-28 14:12:47 -0700100 def __init__(self, args):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700101 super(XOS2Jinja, self).__init__()
102
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700103 self.stack = Stack()
104 self.models = {}
105 self.options = {}
106 self.package = None
107 self.message_options = {}
108 self.count_stack = Stack()
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700109 self.policies = {}
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700110 self.content = ""
111 self.offset = 0
112 self.current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700113 self.verbose = 0
114 self.first_field = True
115 self.first_method = True
Scott Bakerc237f882018-09-28 14:12:47 -0700116 self.args = args
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700117
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700118 def visit_PolicyDefinition(self, obj):
119 if self.package:
Zack Williams045b63d2019-01-22 16:30:57 -0700120 pname = ".".join([self.package, obj.name.value.pval])
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700121 else:
122 pname = obj.name.value.pval
123
124 self.policies[pname] = obj.body
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400125 find_missing_policy_calls(pname, self.policies, obj.body)
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400126
127 return True
128
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700129 def visit_PackageStatement(self, obj):
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200130 dotlist = obj.name.value
131 dotlist2 = [f.pval for f in dotlist]
Zack Williams045b63d2019-01-22 16:30:57 -0700132 dotstr = ".".join(dotlist2)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200133 self.package = dotstr
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700134 return True
135
136 def visit_ImportStatement(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700137 """Ignore"""
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700138 return True
139
140 def visit_OptionStatement(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700141 if not hasattr(obj, "mark_for_deletion"):
142 if self.current_message_name:
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200143 self.message_options[obj.name.value.pval] = obj.value.value.pval
144 else:
145 self.options[obj.name.value.pval] = obj.value.value.pval
Sapan Bhatia504cc972017-04-27 01:56:28 +0200146
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700147 return True
148
149 def visit_LU(self, obj):
150 return True
151
152 def visit_default(self, obj):
153 return True
154
155 def visit_FieldDirective(self, obj):
156 return True
157
158 def visit_FieldDirective_post(self, obj):
159
160 try:
161 name = obj.name.value.pval
162 except AttributeError:
163 name = obj.name.value
164
Zack Williams045b63d2019-01-22 16:30:57 -0700165 if isinstance(obj.value, list):
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200166 value = dotname_to_name(obj.value)
167 else:
168 value = name_to_value(obj)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700169
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700170 self.stack.push([name, value])
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700171 return True
172
173 def visit_FieldType(self, obj):
Zack Williams9a42f872019-02-15 17:56:04 -0700174 """
175 Field type, if type is name, then it may need refactoring consistent
176 with refactoring rules according to the table
177 """
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700178 return True
179
180 def visit_LinkDefinition(self, obj):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700181 s = {}
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700182
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200183 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700184 s["link_type"] = obj.link_type.pval
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200185 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700186 s["link_type"] = obj.link_type
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200187
Zack Williams045b63d2019-01-22 16:30:57 -0700188 s["src_port"] = obj.src_port.value.pval
189 s["name"] = obj.src_port.value.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700190 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700191 s["policy"] = obj.policy.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700192 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700193 s["policy"] = None
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200194
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700195 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700196 s["dst_port"] = obj.dst_port.value.pval
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700197 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700198 s["dst_port"] = obj.dst_port
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200199
Zack Williams045b63d2019-01-22 16:30:57 -0700200 if isinstance(obj.through, list):
201 s["through"] = dotname_to_fqn(obj.through)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200202 else:
203 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700204 s["through"] = obj.through.pval
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200205 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700206 s["through"] = obj.through
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200207
Zack Williams045b63d2019-01-22 16:30:57 -0700208 if isinstance(obj.name, list):
209 s["peer"] = dotname_to_fqn(obj.name)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200210 else:
211 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700212 s["peer"] = obj.name.pval
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200213 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700214 s["peer"] = obj.name
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200215
Scott Bakerc237f882018-09-28 14:12:47 -0700216 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700217 s["reverse_id"] = obj.reverse_id.pval
Scott Bakerc237f882018-09-28 14:12:47 -0700218 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700219 s["reverse_id"] = obj.reverse_id
Scott Bakerc237f882018-09-28 14:12:47 -0700220
Zack Williams045b63d2019-01-22 16:30:57 -0700221 s["_type"] = "link"
222 s["options"] = {"modifier": "optional"}
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700223
224 self.stack.push(s)
225 return True
226
227 def visit_FieldDefinition(self, obj):
228 self.count_stack.push(len(obj.fieldDirective))
229 return True
230
231 def visit_FieldDefinition_post(self, obj):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700232 s = {}
233
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700234 if isinstance(obj.ftype, m.Name):
Zack Williams045b63d2019-01-22 16:30:57 -0700235 s["type"] = obj.ftype.value
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700236 else:
Zack Williams045b63d2019-01-22 16:30:57 -0700237 s["type"] = obj.ftype.name.pval
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200238
Zack Williams045b63d2019-01-22 16:30:57 -0700239 s["name"] = obj.name.value.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700240
241 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700242 s["policy"] = obj.policy.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700243 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700244 s["policy"] = None
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700245
Zack Williams045b63d2019-01-22 16:30:57 -0700246 s["modifier"] = obj.field_modifier.pval
247 s["id"] = obj.fieldId.pval
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700248
Zack Williams045b63d2019-01-22 16:30:57 -0700249 opts = {"modifier": s["modifier"]}
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700250 n = self.count_stack.pop()
251 for i in range(0, n):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700252 k, v = self.stack.pop()
Sapan Bhatia5769d932017-05-17 11:10:54 +0200253
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700254 # The two lines below may be added to eliminate "" around an option.
Sapan Bhatia5769d932017-05-17 11:10:54 +0200255 # Right now, this is handled in targets. FIXME
256 #
257 # if (v.startswith('"') and v.endswith('"')):
258 # v = v[1:-1]
259
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700260 opts[k] = v
261
Zack Williams045b63d2019-01-22 16:30:57 -0700262 s["options"] = opts
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700263 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700264 last_link = self.stack[-1]["_type"]
265 if last_link == "link":
266 s["link"] = True
267 except BaseException:
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700268 pass
Zack Williams045b63d2019-01-22 16:30:57 -0700269 s["_type"] = "field"
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700270
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700271 self.stack.push(s)
272 return True
273
274 def visit_EnumFieldDefinition(self, obj):
275 if self.verbose > 4:
Zack Williams045b63d2019-01-22 16:30:57 -0700276 print("\tEnumField: name=%s, %s" % (obj.name, obj))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700277
278 return True
279
280 def visit_EnumDefinition(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700281 """New enum definition, refactor name"""
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700282 if self.verbose > 3:
Zack Williams045b63d2019-01-22 16:30:57 -0700283 print("Enum, [%s] body=%s\n\n" % (obj.name, obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700284
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700285 return True
286
287 def visit_MessageDefinition(self, obj):
Sapan Bhatia504cc972017-04-27 01:56:28 +0200288 self.current_message_name = obj.name.value.pval
289 self.message_options = {}
290 self.count_stack.push(count_fields(obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700291 return True
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700292
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700293 def visit_MessageDefinition_post(self, obj):
294 stack_num = self.count_stack.pop()
295 fields = []
296 links = []
Zack Williams9a42f872019-02-15 17:56:04 -0700297 last_field = {}
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200298 try:
Zack Williams9a42f872019-02-15 17:56:04 -0700299 obj.bases = list(map(dotname_to_fqn, obj.bases))
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200300 except AttributeError:
301 pass
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700302
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700303 for i in range(0, stack_num):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700304 f = self.stack.pop()
Zack Williams045b63d2019-01-22 16:30:57 -0700305 if f["_type"] == "link":
306 f["options"] = {
307 i: d[i] for d in [f["options"], last_field["options"]] for i in d
308 }
309 assert last_field == fields[0]
310 fields[0].setdefault("options", {})["link_type"] = f["link_type"]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700311 links.insert(0, f)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700312 else:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700313 fields.insert(0, f)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700314 last_field = f
315
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200316 if self.package:
Zack Williams045b63d2019-01-22 16:30:57 -0700317 model_name = ".".join([self.package, obj.name.value.pval])
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200318 else:
319 model_name = obj.name.value.pval
320
Zack Williams045b63d2019-01-22 16:30:57 -0700321 model_def = {
322 "name": obj.name.value.pval,
323 "fields": fields,
324 "links": links,
325 "bases": obj.bases,
326 "options": self.message_options,
327 "package": self.package,
328 "fqn": model_name,
329 "rlinks": [],
330 }
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700331 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700332 model_def["policy"] = obj.policy.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700333 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700334 model_def["policy"] = None
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700335
Sapan Bhatia943dad52017-05-19 18:41:01 +0200336 self.stack.push(model_def)
Zack Williams045b63d2019-01-22 16:30:57 -0700337
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200338 self.models[model_name] = model_def
339
340 # Set message options
Zack Williams9a42f872019-02-15 17:56:04 -0700341 for k, v in sorted(self.options.items(), key=lambda t: t[0]): # sorted by key
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200342 try:
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200343 if k not in self.message_options:
344 self.message_options[k] = v
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200345 except KeyError:
346 pass
347
Sapan Bhatia504cc972017-04-27 01:56:28 +0200348 self.current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700349 return True
350
351 def visit_MessageExtension(self, obj):
352 return True
353
354 def visit_MethodDefinition(self, obj):
355 return True
356
357 def visit_ServiceDefinition(self, obj):
358 return True
359
360 def visit_ExtensionsDirective(self, obj):
361 return True
362
363 def visit_Literal(self, obj):
364 return True
365
366 def visit_Name(self, obj):
367 return True
368
369 def visit_DotName(self, obj):
370 return True
371
372 def visit_Proto(self, obj):
Sapan Bhatia504cc972017-04-27 01:56:28 +0200373 self.count_stack.push(count_messages(obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700374 return True
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700375
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700376 def visit_Proto_post(self, obj):
377 count = self.count_stack.pop()
378 messages = []
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700379 for i in range(0, count):
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200380 try:
381 m = self.stack.pop()
382 except IndexError:
Sapan Bhatia504cc972017-04-27 01:56:28 +0200383 pass
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200384
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700385 messages.insert(0, m)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700386
Scott Bakerc237f882018-09-28 14:12:47 -0700387 self.compute_rlinks(messages, self.models)
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200388
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700389 self.messages = messages
390 return True
391
392 def visit_LinkSpec(self, obj):
393 count = self.count_stack.pop()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700394 self.count_stack.push(count + 1)
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700395 return True
Scott Bakerc237f882018-09-28 14:12:47 -0700396
397 def compute_rlinks(self, messages, message_dict):
398 rev_links = {}
399
400 link_opposite = {
Zack Williams045b63d2019-01-22 16:30:57 -0700401 "manytomany": "manytomany",
402 "manytoone": "onetomany",
403 "onetoone": "onetoone",
404 "onetomany": "manytoone",
Scott Bakerc237f882018-09-28 14:12:47 -0700405 }
406
Zack Williams9a42f872019-02-15 17:56:04 -0700407 for msg in messages:
408 for lnk in msg["links"]:
409 rlink = copy.deepcopy(lnk)
Scott Bakerc237f882018-09-28 14:12:47 -0700410
Zack Williams045b63d2019-01-22 16:30:57 -0700411 rlink["_type"] = "rlink" # An implicit link, not declared in the model
Zack Williams9a42f872019-02-15 17:56:04 -0700412 rlink["src_port"] = lnk["dst_port"]
413 rlink["dst_port"] = lnk["src_port"]
Zack Williams045b63d2019-01-22 16:30:57 -0700414 rlink["peer"] = {
Zack Williams9a42f872019-02-15 17:56:04 -0700415 "name": msg["name"],
416 "package": msg["package"],
417 "fqn": msg["fqn"],
Zack Williams045b63d2019-01-22 16:30:57 -0700418 }
Zack Williams9a42f872019-02-15 17:56:04 -0700419 rlink["link_type"] = link_opposite[lnk["link_type"]]
420 rlink["reverse_id"] = lnk["reverse_id"]
Scott Bakerc237f882018-09-28 14:12:47 -0700421
Zack Williams9a42f872019-02-15 17:56:04 -0700422 if (not lnk["reverse_id"]) and (self.args.verbosity >= 1):
Zack Williams045b63d2019-01-22 16:30:57 -0700423 print(
424 "WARNING: Field %s in model %s has no reverse_id"
Zack Williams9a42f872019-02-15 17:56:04 -0700425 % (lnk["src_port"], msg["name"]),
Zack Williams045b63d2019-01-22 16:30:57 -0700426 file=sys.stderr,
427 )
Scott Bakerc237f882018-09-28 14:12:47 -0700428
Zack Williams9a42f872019-02-15 17:56:04 -0700429 if lnk["reverse_id"] and (
430 (int(lnk["reverse_id"]) < 1000) or (int(lnk["reverse_id"]) >= 1900)
Zack Williams045b63d2019-01-22 16:30:57 -0700431 ):
432 raise Exception(
433 "reverse id for field %s in model %s should be between 1000 and 1899"
Zack Williams9a42f872019-02-15 17:56:04 -0700434 % (lnk["src_port"], msg["name"])
Zack Williams045b63d2019-01-22 16:30:57 -0700435 )
Scott Bakerc237f882018-09-28 14:12:47 -0700436
437 try:
438 try:
Zack Williams9a42f872019-02-15 17:56:04 -0700439 rev_links[lnk["peer"]["fqn"]].append(rlink)
Scott Bakerc237f882018-09-28 14:12:47 -0700440 except TypeError:
441 pass
442 except KeyError:
Zack Williams9a42f872019-02-15 17:56:04 -0700443 rev_links[lnk["peer"]["fqn"]] = [rlink]
Scott Bakerc237f882018-09-28 14:12:47 -0700444
Zack Williams9a42f872019-02-15 17:56:04 -0700445 for msg in messages:
Scott Bakerc237f882018-09-28 14:12:47 -0700446 try:
Zack Williams9a42f872019-02-15 17:56:04 -0700447 msg["rlinks"] = rev_links[msg["name"]]
448 message_dict[msg["name"]]["rlinks"] = msg["rlinks"]
Scott Bakerc237f882018-09-28 14:12:47 -0700449 except KeyError:
450 pass