Matteo Scandolo | d2044a4 | 2017-08-07 16:08:28 -0700 | [diff] [blame] | 1 | # 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 Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 16 | from __future__ import print_function |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 17 | import plyxproto.model as m |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 18 | from plyxproto.helpers import Visitor |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 19 | import argparse |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 20 | import plyxproto.parser as plyxproto |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 21 | import traceback |
| 22 | import sys |
| 23 | import jinja2 |
| 24 | import os |
Sapan Bhatia | 1e397df | 2017-05-24 12:17:28 +0200 | [diff] [blame] | 25 | import copy |
Sapan Bhatia | d3fcb66 | 2017-07-25 21:13:48 -0400 | [diff] [blame] | 26 | import pdb |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 27 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 28 | |
Sapan Bhatia | d3fcb66 | 2017-07-25 21:13:48 -0400 | [diff] [blame] | 29 | class MissingPolicyException(Exception): |
| 30 | pass |
| 31 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 32 | |
Sapan Bhatia | d3fcb66 | 2017-07-25 21:13:48 -0400 | [diff] [blame] | 33 | def find_missing_policy_calls(name, policies, policy): |
| 34 | if isinstance(policy, dict): |
| 35 | (k, lst), = policy.items() |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 36 | if k == "policy": |
Sapan Bhatia | d3fcb66 | 2017-07-25 21:13:48 -0400 | [diff] [blame] | 37 | policy_name = lst[0] |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 38 | if policy_name not in policies: |
| 39 | raise MissingPolicyException( |
| 40 | "Policy %s invoked missing policy %s" % (name, policy_name) |
| 41 | ) |
Sapan Bhatia | d3fcb66 | 2017-07-25 21:13:48 -0400 | [diff] [blame] | 42 | 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 Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 48 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 49 | |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 50 | def dotname_to_fqn(dotname): |
| 51 | b_names = [part.pval for part in dotname] |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 52 | package = ".".join(b_names[:-1]) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 53 | name = b_names[-1] |
| 54 | if package: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 55 | fqn = package + "." + name |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 56 | else: |
| 57 | fqn = name |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 58 | return {"name": name, "fqn": fqn, "package": package} |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 59 | |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 60 | |
| 61 | def dotname_to_name(dotname): |
| 62 | b_names = [part.pval for part in dotname] |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 63 | return ".".join(b_names) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 64 | |
| 65 | |
Sapan Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 66 | def count_messages(body): |
| 67 | count = 0 |
| 68 | for e in body: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 69 | if isinstance(e, m.MessageDefinition): |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 70 | count += 1 |
Sapan Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 71 | return count |
| 72 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 73 | |
Sapan Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 74 | def count_fields(body): |
| 75 | count = 0 |
| 76 | for e in body: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 77 | if type(e) in [m.LinkDefinition, m.FieldDefinition, m.LinkSpec]: |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 78 | count += 1 |
Sapan Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 79 | return count |
| 80 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 81 | |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 82 | def 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 Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 93 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 94 | class Stack(list): |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 95 | def push(self, x): |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 96 | self.append(x) |
| 97 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 98 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 99 | """ XOS2Jinja overrides the underlying visitor pattern to transform the tree |
| 100 | in addition to traversing it """ |
| 101 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 102 | |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 103 | class XOS2Jinja(Visitor): |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 104 | def __init__(self, args): |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 105 | super(XOS2Jinja, self).__init__() |
| 106 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 107 | self.stack = Stack() |
| 108 | self.models = {} |
| 109 | self.options = {} |
| 110 | self.package = None |
| 111 | self.message_options = {} |
| 112 | self.count_stack = Stack() |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 113 | self.policies = {} |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 114 | self.content = "" |
| 115 | self.offset = 0 |
| 116 | self.current_message_name = None |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 117 | self.verbose = 0 |
| 118 | self.first_field = True |
| 119 | self.first_method = True |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 120 | self.args = args |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 121 | |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 122 | def visit_PolicyDefinition(self, obj): |
| 123 | if self.package: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 124 | pname = ".".join([self.package, obj.name.value.pval]) |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 125 | else: |
| 126 | pname = obj.name.value.pval |
| 127 | |
| 128 | self.policies[pname] = obj.body |
Sapan Bhatia | d3fcb66 | 2017-07-25 21:13:48 -0400 | [diff] [blame] | 129 | find_missing_policy_calls(pname, self.policies, obj.body) |
Sapan Bhatia | 3e3c1cd | 2017-07-15 01:35:44 -0400 | [diff] [blame] | 130 | |
| 131 | return True |
| 132 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 133 | def visit_PackageStatement(self, obj): |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 134 | dotlist = obj.name.value |
| 135 | dotlist2 = [f.pval for f in dotlist] |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 136 | dotstr = ".".join(dotlist2) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 137 | self.package = dotstr |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 138 | return True |
| 139 | |
| 140 | def visit_ImportStatement(self, obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 141 | """Ignore""" |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 142 | return True |
| 143 | |
| 144 | def visit_OptionStatement(self, obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 145 | if not hasattr(obj, "mark_for_deletion"): |
| 146 | if self.current_message_name: |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 147 | 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 Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 150 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 151 | 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 Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 169 | if isinstance(obj.value, list): |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 170 | value = dotname_to_name(obj.value) |
| 171 | else: |
| 172 | value = name_to_value(obj) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 173 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 174 | self.stack.push([name, value]) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 175 | return True |
| 176 | |
| 177 | def visit_FieldType(self, obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 178 | """Field type, if type is name, then it may need refactoring consistent with refactoring rules according to the table""" |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 179 | return True |
| 180 | |
| 181 | def visit_LinkDefinition(self, obj): |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 182 | s = {} |
Sapan Bhatia | 8a57c66 | 2017-04-11 10:39:47 -0700 | [diff] [blame] | 183 | |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 184 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 185 | s["link_type"] = obj.link_type.pval |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 186 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 187 | s["link_type"] = obj.link_type |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 188 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 189 | s["src_port"] = obj.src_port.value.pval |
| 190 | s["name"] = obj.src_port.value.pval |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 191 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 192 | s["policy"] = obj.policy.pval |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 193 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 194 | s["policy"] = None |
Sapan Bhatia | c4f803f | 2017-04-21 11:50:39 +0200 | [diff] [blame] | 195 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 196 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 197 | s["dst_port"] = obj.dst_port.value.pval |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 198 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 199 | s["dst_port"] = obj.dst_port |
Sapan Bhatia | c4f803f | 2017-04-21 11:50:39 +0200 | [diff] [blame] | 200 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 201 | if isinstance(obj.through, list): |
| 202 | s["through"] = dotname_to_fqn(obj.through) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 203 | else: |
| 204 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 205 | s["through"] = obj.through.pval |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 206 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 207 | s["through"] = obj.through |
Sapan Bhatia | c4f803f | 2017-04-21 11:50:39 +0200 | [diff] [blame] | 208 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 209 | if isinstance(obj.name, list): |
| 210 | s["peer"] = dotname_to_fqn(obj.name) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 211 | else: |
| 212 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 213 | s["peer"] = obj.name.pval |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 214 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 215 | s["peer"] = obj.name |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 216 | |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 217 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 218 | s["reverse_id"] = obj.reverse_id.pval |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 219 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 220 | s["reverse_id"] = obj.reverse_id |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 221 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 222 | s["_type"] = "link" |
| 223 | s["options"] = {"modifier": "optional"} |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 224 | |
| 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 Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 233 | s = {} |
| 234 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 235 | if isinstance(obj.ftype, m.Name): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 236 | s["type"] = obj.ftype.value |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 237 | else: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 238 | s["type"] = obj.ftype.name.pval |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 239 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 240 | s["name"] = obj.name.value.pval |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 241 | |
| 242 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 243 | s["policy"] = obj.policy.pval |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 244 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 245 | s["policy"] = None |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 246 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 247 | s["modifier"] = obj.field_modifier.pval |
| 248 | s["id"] = obj.fieldId.pval |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 249 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 250 | opts = {"modifier": s["modifier"]} |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 251 | n = self.count_stack.pop() |
| 252 | for i in range(0, n): |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 253 | k, v = self.stack.pop() |
Sapan Bhatia | 5769d93 | 2017-05-17 11:10:54 +0200 | [diff] [blame] | 254 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 255 | # The two lines below may be added to eliminate "" around an option. |
Sapan Bhatia | 5769d93 | 2017-05-17 11:10:54 +0200 | [diff] [blame] | 256 | # Right now, this is handled in targets. FIXME |
| 257 | # |
| 258 | # if (v.startswith('"') and v.endswith('"')): |
| 259 | # v = v[1:-1] |
| 260 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 261 | opts[k] = v |
| 262 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 263 | s["options"] = opts |
Sapan Bhatia | 8a57c66 | 2017-04-11 10:39:47 -0700 | [diff] [blame] | 264 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 265 | last_link = self.stack[-1]["_type"] |
| 266 | if last_link == "link": |
| 267 | s["link"] = True |
| 268 | except BaseException: |
Sapan Bhatia | 8a57c66 | 2017-04-11 10:39:47 -0700 | [diff] [blame] | 269 | pass |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 270 | s["_type"] = "field" |
Sapan Bhatia | 8a57c66 | 2017-04-11 10:39:47 -0700 | [diff] [blame] | 271 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 272 | self.stack.push(s) |
| 273 | return True |
| 274 | |
| 275 | def visit_EnumFieldDefinition(self, obj): |
| 276 | if self.verbose > 4: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 277 | print("\tEnumField: name=%s, %s" % (obj.name, obj)) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 278 | |
| 279 | return True |
| 280 | |
| 281 | def visit_EnumDefinition(self, obj): |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 282 | """New enum definition, refactor name""" |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 283 | if self.verbose > 3: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 284 | print("Enum, [%s] body=%s\n\n" % (obj.name, obj.body)) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 285 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 286 | return True |
| 287 | |
| 288 | def visit_MessageDefinition(self, obj): |
Sapan Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 289 | self.current_message_name = obj.name.value.pval |
| 290 | self.message_options = {} |
| 291 | self.count_stack.push(count_fields(obj.body)) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 292 | return True |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 293 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 294 | def visit_MessageDefinition_post(self, obj): |
| 295 | stack_num = self.count_stack.pop() |
| 296 | fields = [] |
| 297 | links = [] |
| 298 | last_field = None |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 299 | try: |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 300 | obj.bases = map(dotname_to_fqn, obj.bases) |
Sapan Bhatia | ae9645c | 2017-05-05 15:35:54 +0200 | [diff] [blame] | 301 | except AttributeError: |
| 302 | pass |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 303 | |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 304 | last_field = {} |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 305 | for i in range(0, stack_num): |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 306 | f = self.stack.pop() |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 307 | 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 Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 313 | links.insert(0, f) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 314 | else: |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 315 | fields.insert(0, f) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 316 | last_field = f |
| 317 | |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 318 | if self.package: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 319 | model_name = ".".join([self.package, obj.name.value.pval]) |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 320 | else: |
| 321 | model_name = obj.name.value.pval |
| 322 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 323 | 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 Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 333 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 334 | model_def["policy"] = obj.policy.pval |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 335 | except AttributeError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 336 | model_def["policy"] = None |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 337 | |
Sapan Bhatia | 943dad5 | 2017-05-19 18:41:01 +0200 | [diff] [blame] | 338 | self.stack.push(model_def) |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 339 | |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 340 | self.models[model_name] = model_def |
| 341 | |
| 342 | # Set message options |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 343 | for k, v in self.options.iteritems(): |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 344 | try: |
Sapan Bhatia | cb35e7f | 2017-05-24 12:17:28 +0200 | [diff] [blame] | 345 | if k not in self.message_options: |
| 346 | self.message_options[k] = v |
Sapan Bhatia | 3cfdf63 | 2017-06-08 05:14:03 +0200 | [diff] [blame] | 347 | except KeyError: |
| 348 | pass |
| 349 | |
Sapan Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 350 | self.current_message_name = None |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 351 | 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 Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 375 | self.count_stack.push(count_messages(obj.body)) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 376 | return True |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 377 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 378 | def visit_Proto_post(self, obj): |
| 379 | count = self.count_stack.pop() |
| 380 | messages = [] |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 381 | for i in range(0, count): |
Sapan Bhatia | c4f803f | 2017-04-21 11:50:39 +0200 | [diff] [blame] | 382 | try: |
| 383 | m = self.stack.pop() |
| 384 | except IndexError: |
Sapan Bhatia | 504cc97 | 2017-04-27 01:56:28 +0200 | [diff] [blame] | 385 | pass |
Sapan Bhatia | c4f803f | 2017-04-21 11:50:39 +0200 | [diff] [blame] | 386 | |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 387 | messages.insert(0, m) |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 388 | |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 389 | self.compute_rlinks(messages, self.models) |
Sapan Bhatia | cb35e7f | 2017-05-24 12:17:28 +0200 | [diff] [blame] | 390 | |
Sapan Bhatia | ff1b8fa | 2017-04-10 19:44:38 -0700 | [diff] [blame] | 391 | self.messages = messages |
| 392 | return True |
| 393 | |
| 394 | def visit_LinkSpec(self, obj): |
| 395 | count = self.count_stack.pop() |
Matteo Scandolo | 67654fa | 2017-06-09 09:33:17 -0700 | [diff] [blame] | 396 | self.count_stack.push(count + 1) |
Sapan Bhatia | db183c2 | 2017-06-23 02:47:42 -0700 | [diff] [blame] | 397 | return True |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 398 | |
| 399 | def compute_rlinks(self, messages, message_dict): |
| 400 | rev_links = {} |
| 401 | |
| 402 | link_opposite = { |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 403 | "manytomany": "manytomany", |
| 404 | "manytoone": "onetomany", |
| 405 | "onetoone": "onetoone", |
| 406 | "onetomany": "manytoone", |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 407 | } |
| 408 | |
| 409 | for m in messages: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 410 | for l in m["links"]: |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 411 | rlink = copy.deepcopy(l) |
| 412 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 413 | 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 Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 423 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 424 | 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 Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 430 | |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 431 | 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 Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 438 | |
| 439 | try: |
| 440 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 441 | rev_links[l["peer"]["fqn"]].append(rlink) |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 442 | except TypeError: |
| 443 | pass |
| 444 | except KeyError: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 445 | rev_links[l["peer"]["fqn"]] = [rlink] |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 446 | |
| 447 | for m in messages: |
| 448 | try: |
Zack Williams | 045b63d | 2019-01-22 16:30:57 -0700 | [diff] [blame] | 449 | m["rlinks"] = rev_links[m["name"]] |
| 450 | message_dict[m["name"]]["rlinks"] = m["rlinks"] |
Scott Baker | c237f88 | 2018-09-28 14:12:47 -0700 | [diff] [blame] | 451 | except KeyError: |
| 452 | pass |