1 # Copyright (c) 2022 Intel and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 from vpp_papi.vpp_papi import VppEnum
15 from ParseGraph import *
21 parsegraph_path = os.getcwd() + "/parsegraph"
24 def Forge(pattern, actions, file_flag):
25 pg = ParseGraph.Create(parsegraph_path)
27 print("error: create parsegraph failed")
31 token = ParsePattern(pattern)
35 if not os.path.exists(pattern):
36 print("error: file not exist '%s' " % (pattern))
38 f = open(pattern, "r", encoding="utf-8")
40 if "actions" in token:
41 actions = token["actions"]
43 path = Path.Create(token)
45 print("error: path not exit")
48 result = pg.Forge(path)
50 print("error: result not available")
53 spec, mask = GetBinary(result.ToJSON())
57 "type": VppEnum.vl_api_flow_type_v2_t.FLOW_TYPE_GENERIC_V2,
60 "pattern": {"spec": bytes(spec.encode()), "mask": bytes(mask.encode())}
65 # update actions entry
66 my_flow = GetAction(actions, my_flow)
71 def GetAction(actions, flow):
72 if len(actions.split(" ")) > 1:
73 type = actions.split(" ")[0]
80 "actions": VppEnum.vl_api_flow_action_v2_t.FLOW_ACTION_MARK_V2,
81 "mark_flow_id": int(actions.split(" ")[1]),
84 elif type == "next-node":
87 "actions": VppEnum.vl_api_flow_action_v2_t.FLOW_ACTION_REDIRECT_TO_NODE_V2,
88 "redirect_node_index": int(actions.split(" ")[1]),
91 elif type == "buffer-advance":
94 "actions": VppEnum.vl_api_flow_action_v2_t.FLOW_ACTION_BUFFER_ADVANCE_V2,
95 "buffer_advance": int(actions.split(" ")[1]),
98 elif type == "redirect-to-queue":
101 "actions": VppEnum.vl_api_flow_action_v2_t.FLOW_ACTION_REDIRECT_TO_QUEUE_V2,
102 "redirect_queue": int(actions.split(" ")[1]),
106 flow.update({"actions": VppEnum.vl_api_flow_action_v2_t.FLOW_ACTION_RSS_V2})
107 elif type == "rss-queues":
108 queue_end = int(actions.split(" ")[-1])
109 queue_start = int(actions.split(" ")[-3])
112 "actions": VppEnum.vl_api_flow_action_v2_t.FLOW_ACTION_RSS_V2,
113 "queue_index": queue_start,
114 "queue_num": queue_end - queue_start + 1,
118 flow.update({"actions": VppEnum.vl_api_flow_action_v2_t.FLOW_ACTION_DROP_V2})
123 def GetBinary(flow_info):
124 spec = "".join(flow_info["Packet"])
125 mask = "".join(flow_info["Mask"])
129 def ParseFields(item):
131 prot = item.split("(")[0]
132 stack = {"header": prot}
133 # get fields contents
134 fields = re.findall(r"[(](.*?)[)]", item)
136 print("error: invalid pattern")
140 stack.update({"fields": []})
141 return ParseStack(stack, fields[0].split(","))
146 format = item["format"]
148 mask = "ff:ff:ff:ff:ff:ff"
149 elif format == "ipv4":
150 mask = "255.255.255.255"
151 elif format == "ipv6":
152 mask = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
155 mask = str((1 << int(item["size"])) - 1)
161 # parse protocol headers and its fields. Available fields are defined in corresponding nodes.
162 def ParseStack(stack, fields):
163 prot = stack["header"]
164 node_path = parsegraph_path + "/nodes/" + prot + ".json"
165 if not os.path.exists(node_path):
166 print("error file not exist '%s' " % (node_path))
168 f = open(node_path, "r", encoding="utf-8")
169 nodeinfo = json.load(f)
171 fld_name = field.split("=")[0].strip()
173 field.split("=")[-1].strip() if (len(field.split("=")) >= 2) else None
175 for item in nodeinfo["layout"]:
176 if fld_name == item["name"]:
178 stack["fields"].append(
179 {"name": fld_name, "value": fld_value, "mask": mask}
182 if not stack["fields"]:
183 print("warning: invalid field '%s'" % (fld_name))
189 def ParsePattern(pattern):
190 # create json template
191 json_tmp = {"type": "path", "stack": []}
193 items = pattern.split("/")
195 stack = ParseFields(item)
198 json_tmp["stack"].append(stack)