diff options
-rw-r--r-- | extras/packetforge/README.rst | 11 | ||||
-rw-r--r-- | extras/packetforge/flow_create.py | 92 | ||||
-rw-r--r-- | extras/packetforge/flow_parse.py | 66 | ||||
-rw-r--r-- | extras/packetforge/packetforge.py | 12 |
4 files changed, 141 insertions, 40 deletions
diff --git a/extras/packetforge/README.rst b/extras/packetforge/README.rst index f477c0bab38..6d959967af4 100644 --- a/extras/packetforge/README.rst +++ b/extras/packetforge/README.rst @@ -51,6 +51,17 @@ Users can create their own json files according to examples and Spec. :: + $ python flow_create.py --show -p "mac()/ipv4(src=1.1.1.1,dst=2.2.2.2)/udp()" + + $ python flow_parse.py --show -p "mac()/ipv4(src=1.1.1.1,dst=2.2.2.2)/udp()" + +These commands can show the forging result of spec and mask only, without invoving +VPP. No need to configure actions and interfaces. Users can get the binary string +of spec and mask from a flow pattern if needed. flow_parse.py can be used without +VAPI installed. + +:: + $ show flow entry It is a vnet/flow command, used in VPP CLI. It can show the added flow rules diff --git a/extras/packetforge/flow_create.py b/extras/packetforge/flow_create.py index fbbdec56694..3d4e4b6a702 100644 --- a/extras/packetforge/flow_create.py +++ b/extras/packetforge/flow_create.py @@ -29,17 +29,44 @@ VPP_JSON_DIR_PLUGIN = ( API_FILE_SUFFIX = "*.api.json" +def load_json_api_files(suffix=API_FILE_SUFFIX): + jsonfiles = [] + json_dir = VPP_JSON_DIR + for root, dirnames, filenames in os.walk(json_dir): + for filename in fnmatch.filter(filenames, suffix): + jsonfiles.append(os.path.join(json_dir, filename)) + json_dir = VPP_JSON_DIR_PLUGIN + for root, dirnames, filenames in os.walk(json_dir): + for filename in fnmatch.filter(filenames, suffix): + jsonfiles.append(os.path.join(json_dir, filename)) + if not jsonfiles: + raise RuntimeError("Error: no json api files found") + else: + print("load json api file done") + return jsonfiles + + +def connect_vpp(jsonfiles): + vpp = VPPApiClient(apifiles=jsonfiles) + r = vpp.connect("CLIENT_ID") + print("VPP api opened with code: %s" % r) + return vpp + + def Main(argv): file_flag = False operation = None + actions = "" + iface = "" try: opts, args = getopt.getopt( argv, "hf:p:a:i:I:", [ - "help=", + "help", "add", "del", + "show", "file=", "pattern=", "actions=", @@ -49,21 +76,22 @@ def Main(argv): ) except getopt.GetoptError: print( - "flow_create.py --add|del -f <file> -p <pattern> -a <actions> -i <interface> -I <flow-index>" + "flow_create.py --add|del|show -f <file> -p <pattern> -a <actions> -i <interface> -I <flow-index>" ) sys.exit() for opt, arg in opts: if opt == "-h": print( - "flow_create.py --add|del -f <file> -p <pattern> -a <actions> -i <interface> -I <flow-index>" + "flow_create.py --add|del|show -f <file> -p <pattern> -a <actions> -i <interface> -I <flow-index>" ) sys.exit() elif opt == "--add": operation = "add" elif opt == "--del": operation = "del" + elif opt == "--show": + operation = "show" elif opt in ("-f", "--file"): - actions = "" json_file = arg file_flag = True elif opt in ("-p", "--pattern") and not file_flag: @@ -79,50 +107,37 @@ def Main(argv): print("Error: Please choose the operation: add or del") sys.exit() - if operation == "add": + if operation == "show": if not file_flag: - result = packetforge.Forge(pattern, actions, False) + result = packetforge.Forge(pattern, actions, False, True) else: - result = packetforge.Forge(json_file, actions, True) - return result, int(iface), operation, None - elif operation == "del": - return None, int(iface), operation, int(flow_index) - + result = packetforge.Forge(json_file, actions, True, True) + return result, None, operation, None, None -def load_json_api_files(suffix=API_FILE_SUFFIX): - jsonfiles = [] - json_dir = VPP_JSON_DIR - for root, dirnames, filenames in os.walk(json_dir): - for filename in fnmatch.filter(filenames, suffix): - jsonfiles.append(os.path.join(json_dir, filename)) - json_dir = VPP_JSON_DIR_PLUGIN - for root, dirnames, filenames in os.walk(json_dir): - for filename in fnmatch.filter(filenames, suffix): - jsonfiles.append(os.path.join(json_dir, filename)) - if not jsonfiles: - raise RuntimeError("Error: no json api files found") - else: - print("load json api file done") - return jsonfiles + # Python API need json definitions to interpret messages + vpp = connect_vpp(load_json_api_files()) + # set inteface states + vpp.api.sw_interface_set_flags(sw_if_index=int(iface), flags=1) -def connect_vpp(jsonfiles): - vpp = VPPApiClient(apifiles=jsonfiles) - r = vpp.connect("CLIENT_ID") - print("VPP api opened with code: %s" % r) - return vpp + if operation == "add": + if not file_flag: + result = packetforge.Forge(pattern, actions, False, False) + else: + result = packetforge.Forge(json_file, actions, True, False) + return result, int(iface), operation, None, vpp + elif operation == "del": + return None, int(iface), operation, int(flow_index), vpp if __name__ == "__main__": - # Python API need json definitions to interpret messages - vpp = connect_vpp(load_json_api_files()) - print(vpp.api.show_version()) - # Parse the arguments - my_flow, iface, operation, del_flow_index = Main(sys.argv[1:]) + my_flow, iface, operation, del_flow_index, vpp = Main(sys.argv[1:]) - # set inteface states - vpp.api.sw_interface_set_flags(sw_if_index=iface, flags=1) + # if operation is show, just show spec and mask, then exit + if operation == "show": + print(my_flow) + sys.exit() if operation == "add": # add flow @@ -155,3 +170,4 @@ if __name__ == "__main__": # command example: # python flow_create.py --add -p "mac()/ipv4(src=1.1.1.1,dst=2.2.2.2)/udp()" -a "redirect-to-queue 3" -i 1 # python flow_create.py --del -i 1 -I 0 +# python flow_create.py --show -p "mac()/ipv4(src=1.1.1.1,dst=2.2.2.2)/udp()" diff --git a/extras/packetforge/flow_parse.py b/extras/packetforge/flow_parse.py new file mode 100644 index 00000000000..9b89282e153 --- /dev/null +++ b/extras/packetforge/flow_parse.py @@ -0,0 +1,66 @@ +# Copyright (c) 2022 Intel and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys, getopt +import packetforge + + +def Main(argv): + file_flag = False + operation = None + try: + opts, args = getopt.getopt( + argv, + "hf:p:a:i:I:", + [ + "help", + "show", + "file=", + "pattern=", + ], + ) + except getopt.GetoptError: + print("flow_parse.py --show -f <file> -p <pattern>") + sys.exit() + for opt, arg in opts: + if opt == "-h": + print("flow_parse.py --show -f <file> -p <pattern>") + sys.exit() + elif opt == "--show": + operation = "show" + elif opt in ("-f", "--file"): + json_file = arg + file_flag = True + elif opt in ("-p", "--pattern") and not file_flag: + pattern = arg + + if operation == None: + print("Error: Please choose the operation: show") + sys.exit() + + if not file_flag: + result = packetforge.Forge(pattern, None, False, True) + else: + result = packetforge.Forge(json_file, None, True, True) + + return result + + +if __name__ == "__main__": + # Parse the arguments + my_flow = Main(sys.argv[1:]) + + print(my_flow) + +# command example: +# python flow_parse.py --show -p "mac()/ipv4(src=1.1.1.1,dst=2.2.2.2)/udp()" diff --git a/extras/packetforge/packetforge.py b/extras/packetforge/packetforge.py index 4f149dcd046..42bfeb01e00 100644 --- a/extras/packetforge/packetforge.py +++ b/extras/packetforge/packetforge.py @@ -21,7 +21,7 @@ import os parsegraph_path = os.getcwd() + "/parsegraph" -def Forge(pattern, actions, file_flag): +def Forge(pattern, actions, file_flag, show_result_only): pg = ParseGraph.Create(parsegraph_path) if pg == None: print("error: create parsegraph failed") @@ -54,7 +54,6 @@ def Forge(pattern, actions, file_flag): # create generic flow my_flow = { - "type": VppEnum.vl_api_flow_type_v2_t.FLOW_TYPE_GENERIC_V2, "flow": { "generic": { "pattern": {"spec": bytes(spec.encode()), "mask": bytes(mask.encode())} @@ -62,6 +61,15 @@ def Forge(pattern, actions, file_flag): }, } + if show_result_only: + return my_flow + + my_flow.update( + { + "type": VppEnum.vl_api_flow_type_v2_t.FLOW_TYPE_GENERIC_V2, + } + ) + # update actions entry my_flow = GetAction(actions, my_flow) |