blob: 471be93fd95e41d705878ff48ad972209073aa59 [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
15
Zack Williams045b63d2019-01-22 16:30:57 -070016from __future__ import print_function
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020017import plyxproto.model as m
Sapan Bhatiadb183c22017-06-23 02:47:42 -070018from plyxproto.helpers import Visitor
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070019import argparse
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020020import plyxproto.parser as plyxproto
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070021import traceback
22import sys
23import jinja2
24import os
Sapan Bhatia1e397df2017-05-24 12:17:28 +020025import copy
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040026import pdb
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070027
Zack Williams045b63d2019-01-22 16:30:57 -070028
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040029class MissingPolicyException(Exception):
30 pass
31
Zack Williams045b63d2019-01-22 16:30:57 -070032
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040033def find_missing_policy_calls(name, policies, policy):
34 if isinstance(policy, dict):
35 (k, lst), = policy.items()
Zack Williams045b63d2019-01-22 16:30:57 -070036 if k == "policy":
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040037 policy_name = lst[0]
Zack Williams045b63d2019-01-22 16:30:57 -070038 if policy_name not in policies:
39 raise MissingPolicyException(
40 "Policy %s invoked missing policy %s" % (name, policy_name)
41 )
Sapan Bhatiad3fcb662017-07-25 21:13:48 -040042 else:
43 for p in lst:
44 find_missing_policy_calls(name, policies, p)
45 elif isinstance(policy, list):
46 for p in lst:
47 find_missing_policy_calls(name, policies, p)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070048
Zack Williams045b63d2019-01-22 16:30:57 -070049
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020050def dotname_to_fqn(dotname):
51 b_names = [part.pval for part in dotname]
Zack Williams045b63d2019-01-22 16:30:57 -070052 package = ".".join(b_names[:-1])
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020053 name = b_names[-1]
54 if package:
Zack Williams045b63d2019-01-22 16:30:57 -070055 fqn = package + "." + name
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020056 else:
57 fqn = name
Zack Williams045b63d2019-01-22 16:30:57 -070058 return {"name": name, "fqn": fqn, "package": package}
Matteo Scandolo67654fa2017-06-09 09:33:17 -070059
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020060
61def dotname_to_name(dotname):
62 b_names = [part.pval for part in dotname]
Zack Williams045b63d2019-01-22 16:30:57 -070063 return ".".join(b_names)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020064
65
Sapan Bhatia504cc972017-04-27 01:56:28 +020066def count_messages(body):
67 count = 0
68 for e in body:
Zack Williams045b63d2019-01-22 16:30:57 -070069 if isinstance(e, m.MessageDefinition):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070070 count += 1
Sapan Bhatia504cc972017-04-27 01:56:28 +020071 return count
72
Matteo Scandolo67654fa2017-06-09 09:33:17 -070073
Sapan Bhatia504cc972017-04-27 01:56:28 +020074def count_fields(body):
75 count = 0
76 for e in body:
Zack Williams045b63d2019-01-22 16:30:57 -070077 if type(e) in [m.LinkDefinition, m.FieldDefinition, m.LinkSpec]:
Matteo Scandolo67654fa2017-06-09 09:33:17 -070078 count += 1
Sapan Bhatia504cc972017-04-27 01:56:28 +020079 return count
80
Matteo Scandolo67654fa2017-06-09 09:33:17 -070081
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020082def name_to_value(obj):
83 try:
84 value = obj.value.value.pval
85 except AttributeError:
86 try:
87 value = obj.value.value
88 except AttributeError:
89 value = obj.value.pval
90
91 return value
92
Matteo Scandolo67654fa2017-06-09 09:33:17 -070093
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070094class Stack(list):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070095 def push(self, x):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070096 self.append(x)
97
Matteo Scandolo67654fa2017-06-09 09:33:17 -070098
Zack Williams045b63d2019-01-22 16:30:57 -070099""" XOS2Jinja overrides the underlying visitor pattern to transform the tree
100 in addition to traversing it """
101
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700102
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700103class XOS2Jinja(Visitor):
Scott Bakerc237f882018-09-28 14:12:47 -0700104 def __init__(self, args):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700105 super(XOS2Jinja, self).__init__()
106
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700107 self.stack = Stack()
108 self.models = {}
109 self.options = {}
110 self.package = None
111 self.message_options = {}
112 self.count_stack = Stack()
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700113 self.policies = {}
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700114 self.content = ""
115 self.offset = 0
116 self.current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700117 self.verbose = 0
118 self.first_field = True
119 self.first_method = True
Scott Bakerc237f882018-09-28 14:12:47 -0700120 self.args = args
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700121
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700122 def visit_PolicyDefinition(self, obj):
123 if self.package:
Zack Williams045b63d2019-01-22 16:30:57 -0700124 pname = ".".join([self.package, obj.name.value.pval])
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700125 else:
126 pname = obj.name.value.pval
127
128 self.policies[pname] = obj.body
Sapan Bhatiad3fcb662017-07-25 21:13:48 -0400129 find_missing_policy_calls(pname, self.policies, obj.body)
Sapan Bhatia3e3c1cd2017-07-15 01:35:44 -0400130
131 return True
132
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700133 def visit_PackageStatement(self, obj):
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200134 dotlist = obj.name.value
135 dotlist2 = [f.pval for f in dotlist]
Zack Williams045b63d2019-01-22 16:30:57 -0700136 dotstr = ".".join(dotlist2)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200137 self.package = dotstr
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700138 return True
139
140 def visit_ImportStatement(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700141 """Ignore"""
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700142 return True
143
144 def visit_OptionStatement(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700145 if not hasattr(obj, "mark_for_deletion"):
146 if self.current_message_name:
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200147 self.message_options[obj.name.value.pval] = obj.value.value.pval
148 else:
149 self.options[obj.name.value.pval] = obj.value.value.pval
Sapan Bhatia504cc972017-04-27 01:56:28 +0200150
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700151 return True
152
153 def visit_LU(self, obj):
154 return True
155
156 def visit_default(self, obj):
157 return True
158
159 def visit_FieldDirective(self, obj):
160 return True
161
162 def visit_FieldDirective_post(self, obj):
163
164 try:
165 name = obj.name.value.pval
166 except AttributeError:
167 name = obj.name.value
168
Zack Williams045b63d2019-01-22 16:30:57 -0700169 if isinstance(obj.value, list):
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200170 value = dotname_to_name(obj.value)
171 else:
172 value = name_to_value(obj)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700173
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700174 self.stack.push([name, value])
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700175 return True
176
177 def visit_FieldType(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700178 """Field type, if type is name, then it may need refactoring consistent with refactoring rules according to the table"""
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700179 return True
180
181 def visit_LinkDefinition(self, obj):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700182 s = {}
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700183
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200184 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700185 s["link_type"] = obj.link_type.pval
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200186 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700187 s["link_type"] = obj.link_type
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200188
Zack Williams045b63d2019-01-22 16:30:57 -0700189 s["src_port"] = obj.src_port.value.pval
190 s["name"] = obj.src_port.value.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700191 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700192 s["policy"] = obj.policy.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700193 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700194 s["policy"] = None
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200195
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700196 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700197 s["dst_port"] = obj.dst_port.value.pval
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700198 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700199 s["dst_port"] = obj.dst_port
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200200
Zack Williams045b63d2019-01-22 16:30:57 -0700201 if isinstance(obj.through, list):
202 s["through"] = dotname_to_fqn(obj.through)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200203 else:
204 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700205 s["through"] = obj.through.pval
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200206 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700207 s["through"] = obj.through
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200208
Zack Williams045b63d2019-01-22 16:30:57 -0700209 if isinstance(obj.name, list):
210 s["peer"] = dotname_to_fqn(obj.name)
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200211 else:
212 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700213 s["peer"] = obj.name.pval
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200214 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700215 s["peer"] = obj.name
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200216
Scott Bakerc237f882018-09-28 14:12:47 -0700217 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700218 s["reverse_id"] = obj.reverse_id.pval
Scott Bakerc237f882018-09-28 14:12:47 -0700219 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700220 s["reverse_id"] = obj.reverse_id
Scott Bakerc237f882018-09-28 14:12:47 -0700221
Zack Williams045b63d2019-01-22 16:30:57 -0700222 s["_type"] = "link"
223 s["options"] = {"modifier": "optional"}
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700224
225 self.stack.push(s)
226 return True
227
228 def visit_FieldDefinition(self, obj):
229 self.count_stack.push(len(obj.fieldDirective))
230 return True
231
232 def visit_FieldDefinition_post(self, obj):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700233 s = {}
234
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700235 if isinstance(obj.ftype, m.Name):
Zack Williams045b63d2019-01-22 16:30:57 -0700236 s["type"] = obj.ftype.value
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700237 else:
Zack Williams045b63d2019-01-22 16:30:57 -0700238 s["type"] = obj.ftype.name.pval
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200239
Zack Williams045b63d2019-01-22 16:30:57 -0700240 s["name"] = obj.name.value.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700241
242 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700243 s["policy"] = obj.policy.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700244 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700245 s["policy"] = None
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700246
Zack Williams045b63d2019-01-22 16:30:57 -0700247 s["modifier"] = obj.field_modifier.pval
248 s["id"] = obj.fieldId.pval
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700249
Zack Williams045b63d2019-01-22 16:30:57 -0700250 opts = {"modifier": s["modifier"]}
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700251 n = self.count_stack.pop()
252 for i in range(0, n):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700253 k, v = self.stack.pop()
Sapan Bhatia5769d932017-05-17 11:10:54 +0200254
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700255 # The two lines below may be added to eliminate "" around an option.
Sapan Bhatia5769d932017-05-17 11:10:54 +0200256 # Right now, this is handled in targets. FIXME
257 #
258 # if (v.startswith('"') and v.endswith('"')):
259 # v = v[1:-1]
260
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700261 opts[k] = v
262
Zack Williams045b63d2019-01-22 16:30:57 -0700263 s["options"] = opts
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700264 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700265 last_link = self.stack[-1]["_type"]
266 if last_link == "link":
267 s["link"] = True
268 except BaseException:
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700269 pass
Zack Williams045b63d2019-01-22 16:30:57 -0700270 s["_type"] = "field"
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700271
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700272 self.stack.push(s)
273 return True
274
275 def visit_EnumFieldDefinition(self, obj):
276 if self.verbose > 4:
Zack Williams045b63d2019-01-22 16:30:57 -0700277 print("\tEnumField: name=%s, %s" % (obj.name, obj))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700278
279 return True
280
281 def visit_EnumDefinition(self, obj):
Zack Williams045b63d2019-01-22 16:30:57 -0700282 """New enum definition, refactor name"""
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700283 if self.verbose > 3:
Zack Williams045b63d2019-01-22 16:30:57 -0700284 print("Enum, [%s] body=%s\n\n" % (obj.name, obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700285
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700286 return True
287
288 def visit_MessageDefinition(self, obj):
Sapan Bhatia504cc972017-04-27 01:56:28 +0200289 self.current_message_name = obj.name.value.pval
290 self.message_options = {}
291 self.count_stack.push(count_fields(obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700292 return True
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700293
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700294 def visit_MessageDefinition_post(self, obj):
295 stack_num = self.count_stack.pop()
296 fields = []
297 links = []
298 last_field = None
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200299 try:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200300 obj.bases = map(dotname_to_fqn, obj.bases)
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200301 except AttributeError:
302 pass
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700303
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200304 last_field = {}
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700305 for i in range(0, stack_num):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700306 f = self.stack.pop()
Zack Williams045b63d2019-01-22 16:30:57 -0700307 if f["_type"] == "link":
308 f["options"] = {
309 i: d[i] for d in [f["options"], last_field["options"]] for i in d
310 }
311 assert last_field == fields[0]
312 fields[0].setdefault("options", {})["link_type"] = f["link_type"]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700313 links.insert(0, f)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700314 else:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700315 fields.insert(0, f)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700316 last_field = f
317
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200318 if self.package:
Zack Williams045b63d2019-01-22 16:30:57 -0700319 model_name = ".".join([self.package, obj.name.value.pval])
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200320 else:
321 model_name = obj.name.value.pval
322
Zack Williams045b63d2019-01-22 16:30:57 -0700323 model_def = {
324 "name": obj.name.value.pval,
325 "fields": fields,
326 "links": links,
327 "bases": obj.bases,
328 "options": self.message_options,
329 "package": self.package,
330 "fqn": model_name,
331 "rlinks": [],
332 }
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700333 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700334 model_def["policy"] = obj.policy.pval
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700335 except AttributeError:
Zack Williams045b63d2019-01-22 16:30:57 -0700336 model_def["policy"] = None
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700337
Sapan Bhatia943dad52017-05-19 18:41:01 +0200338 self.stack.push(model_def)
Zack Williams045b63d2019-01-22 16:30:57 -0700339
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200340 self.models[model_name] = model_def
341
342 # Set message options
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700343 for k, v in self.options.iteritems():
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200344 try:
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200345 if k not in self.message_options:
346 self.message_options[k] = v
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200347 except KeyError:
348 pass
349
Sapan Bhatia504cc972017-04-27 01:56:28 +0200350 self.current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700351 return True
352
353 def visit_MessageExtension(self, obj):
354 return True
355
356 def visit_MethodDefinition(self, obj):
357 return True
358
359 def visit_ServiceDefinition(self, obj):
360 return True
361
362 def visit_ExtensionsDirective(self, obj):
363 return True
364
365 def visit_Literal(self, obj):
366 return True
367
368 def visit_Name(self, obj):
369 return True
370
371 def visit_DotName(self, obj):
372 return True
373
374 def visit_Proto(self, obj):
Sapan Bhatia504cc972017-04-27 01:56:28 +0200375 self.count_stack.push(count_messages(obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700376 return True
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700377
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700378 def visit_Proto_post(self, obj):
379 count = self.count_stack.pop()
380 messages = []
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700381 for i in range(0, count):
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200382 try:
383 m = self.stack.pop()
384 except IndexError:
Sapan Bhatia504cc972017-04-27 01:56:28 +0200385 pass
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200386
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700387 messages.insert(0, m)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700388
Scott Bakerc237f882018-09-28 14:12:47 -0700389 self.compute_rlinks(messages, self.models)
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200390
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700391 self.messages = messages
392 return True
393
394 def visit_LinkSpec(self, obj):
395 count = self.count_stack.pop()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700396 self.count_stack.push(count + 1)
Sapan Bhatiadb183c22017-06-23 02:47:42 -0700397 return True
Scott Bakerc237f882018-09-28 14:12:47 -0700398
399 def compute_rlinks(self, messages, message_dict):
400 rev_links = {}
401
402 link_opposite = {
Zack Williams045b63d2019-01-22 16:30:57 -0700403 "manytomany": "manytomany",
404 "manytoone": "onetomany",
405 "onetoone": "onetoone",
406 "onetomany": "manytoone",
Scott Bakerc237f882018-09-28 14:12:47 -0700407 }
408
409 for m in messages:
Zack Williams045b63d2019-01-22 16:30:57 -0700410 for l in m["links"]:
Scott Bakerc237f882018-09-28 14:12:47 -0700411 rlink = copy.deepcopy(l)
412
Zack Williams045b63d2019-01-22 16:30:57 -0700413 rlink["_type"] = "rlink" # An implicit link, not declared in the model
414 rlink["src_port"] = l["dst_port"]
415 rlink["dst_port"] = l["src_port"]
416 rlink["peer"] = {
417 "name": m["name"],
418 "package": m["package"],
419 "fqn": m["fqn"],
420 }
421 rlink["link_type"] = link_opposite[l["link_type"]]
422 rlink["reverse_id"] = l["reverse_id"]
Scott Bakerc237f882018-09-28 14:12:47 -0700423
Zack Williams045b63d2019-01-22 16:30:57 -0700424 if (not l["reverse_id"]) and (self.args.verbosity >= 1):
425 print(
426 "WARNING: Field %s in model %s has no reverse_id"
427 % (l["src_port"], m["name"]),
428 file=sys.stderr,
429 )
Scott Bakerc237f882018-09-28 14:12:47 -0700430
Zack Williams045b63d2019-01-22 16:30:57 -0700431 if l["reverse_id"] and (
432 (int(l["reverse_id"]) < 1000) or (int(l["reverse_id"]) >= 1900)
433 ):
434 raise Exception(
435 "reverse id for field %s in model %s should be between 1000 and 1899"
436 % (l["src_port"], m["name"])
437 )
Scott Bakerc237f882018-09-28 14:12:47 -0700438
439 try:
440 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700441 rev_links[l["peer"]["fqn"]].append(rlink)
Scott Bakerc237f882018-09-28 14:12:47 -0700442 except TypeError:
443 pass
444 except KeyError:
Zack Williams045b63d2019-01-22 16:30:57 -0700445 rev_links[l["peer"]["fqn"]] = [rlink]
Scott Bakerc237f882018-09-28 14:12:47 -0700446
447 for m in messages:
448 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700449 m["rlinks"] = rev_links[m["name"]]
450 message_dict[m["name"]]["rlinks"] = m["rlinks"]
Scott Bakerc237f882018-09-28 14:12:47 -0700451 except KeyError:
452 pass